|
@@ -15,6 +15,7 @@
|
|
|
|
|
|
#define pr_fmt(fmt) "psci: " fmt
|
|
|
|
|
|
+#include <linux/acpi.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/of.h>
|
|
|
#include <linux/smp.h>
|
|
@@ -24,6 +25,7 @@
|
|
|
#include <linux/slab.h>
|
|
|
#include <uapi/linux/psci.h>
|
|
|
|
|
|
+#include <asm/acpi.h>
|
|
|
#include <asm/compiler.h>
|
|
|
#include <asm/cpu_ops.h>
|
|
|
#include <asm/errno.h>
|
|
@@ -273,6 +275,33 @@ static void psci_sys_poweroff(void)
|
|
|
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
|
|
|
}
|
|
|
|
|
|
+static void __init psci_0_2_set_functions(void)
|
|
|
+{
|
|
|
+ pr_info("Using standard PSCI v0.2 function IDs\n");
|
|
|
+ psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
|
|
|
+ psci_ops.cpu_suspend = psci_cpu_suspend;
|
|
|
+
|
|
|
+ psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
|
|
|
+ psci_ops.cpu_off = psci_cpu_off;
|
|
|
+
|
|
|
+ psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON;
|
|
|
+ psci_ops.cpu_on = psci_cpu_on;
|
|
|
+
|
|
|
+ psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE;
|
|
|
+ psci_ops.migrate = psci_migrate;
|
|
|
+
|
|
|
+ psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO;
|
|
|
+ psci_ops.affinity_info = psci_affinity_info;
|
|
|
+
|
|
|
+ psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
|
|
|
+ PSCI_0_2_FN_MIGRATE_INFO_TYPE;
|
|
|
+ psci_ops.migrate_info_type = psci_migrate_info_type;
|
|
|
+
|
|
|
+ arm_pm_restart = psci_sys_reset;
|
|
|
+
|
|
|
+ pm_power_off = psci_sys_poweroff;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* PSCI Function IDs for v0.2+ are well defined so use
|
|
|
* standard values.
|
|
@@ -306,29 +335,7 @@ static int __init psci_0_2_init(struct device_node *np)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- pr_info("Using standard PSCI v0.2 function IDs\n");
|
|
|
- psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
|
|
|
- psci_ops.cpu_suspend = psci_cpu_suspend;
|
|
|
-
|
|
|
- psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
|
|
|
- psci_ops.cpu_off = psci_cpu_off;
|
|
|
-
|
|
|
- psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON;
|
|
|
- psci_ops.cpu_on = psci_cpu_on;
|
|
|
-
|
|
|
- psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE;
|
|
|
- psci_ops.migrate = psci_migrate;
|
|
|
-
|
|
|
- psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO;
|
|
|
- psci_ops.affinity_info = psci_affinity_info;
|
|
|
-
|
|
|
- psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
|
|
|
- PSCI_0_2_FN_MIGRATE_INFO_TYPE;
|
|
|
- psci_ops.migrate_info_type = psci_migrate_info_type;
|
|
|
-
|
|
|
- arm_pm_restart = psci_sys_reset;
|
|
|
-
|
|
|
- pm_power_off = psci_sys_poweroff;
|
|
|
+ psci_0_2_set_functions();
|
|
|
|
|
|
out_put_node:
|
|
|
of_node_put(np);
|
|
@@ -381,7 +388,7 @@ static const struct of_device_id psci_of_match[] __initconst = {
|
|
|
{},
|
|
|
};
|
|
|
|
|
|
-int __init psci_init(void)
|
|
|
+int __init psci_dt_init(void)
|
|
|
{
|
|
|
struct device_node *np;
|
|
|
const struct of_device_id *matched_np;
|
|
@@ -396,6 +403,29 @@ int __init psci_init(void)
|
|
|
return init_fn(np);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
|
|
|
+ * explicitly clarified in SBBR
|
|
|
+ */
|
|
|
+int __init psci_acpi_init(void)
|
|
|
+{
|
|
|
+ if (!acpi_psci_present()) {
|
|
|
+ pr_info("is not implemented in ACPI.\n");
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_info("probing for conduit method from ACPI.\n");
|
|
|
+
|
|
|
+ if (acpi_psci_use_hvc())
|
|
|
+ invoke_psci_fn = __invoke_psci_fn_hvc;
|
|
|
+ else
|
|
|
+ invoke_psci_fn = __invoke_psci_fn_smc;
|
|
|
+
|
|
|
+ psci_0_2_set_functions();
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
|
|
static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)
|