aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64
diff options
context:
space:
mode:
authorGraeme Gregory <graeme.gregory@linaro.org>2015-03-24 10:02:43 -0400
committerWill Deacon <will.deacon@arm.com>2015-03-25 07:49:31 -0400
commit7c59a3df15df29c8402a05b92385e83e55355778 (patch)
tree1e41299662d072c04f8d6d45c4d51d5a1f581de5 /arch/arm64
parent3505f30fb6a980283116390e9a962d60cf8e2a57 (diff)
ARM64 / ACPI: Get PSCI flags in FADT for PSCI init
There are two flags: PSCI_COMPLIANT and PSCI_USE_HVC. When set, the former signals to the OS that the firmware is PSCI compliant. The latter selects the appropriate conduit for PSCI calls by toggling between Hypervisor Calls (HVC) and Secure Monitor Calls (SMC). FADT table contains such information in ACPI 5.1, FADT table was parsed in ACPI table init and copy to struct acpi_gbl_FADT, so use the flags in struct acpi_gbl_FADT for PSCI init. Since ACPI 5.1 doesn't support self defined PSCI function IDs, which means that only PSCI 0.2+ is supported in ACPI. CC: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> CC: Catalin Marinas <catalin.marinas@arm.com> CC: Will Deacon <will.deacon@arm.com> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> Tested-by: Yijing Wang <wangyijing@huawei.com> Tested-by: Mark Langsdorf <mlangsdo@redhat.com> Tested-by: Jon Masters <jcm@redhat.com> Tested-by: Timur Tabi <timur@codeaurora.org> Tested-by: Robert Richter <rrichter@cavium.com> Acked-by: Robert Richter <rrichter@cavium.com> Acked-by: Olof Johansson <olof@lixom.net> Acked-by: Grant Likely <grant.likely@linaro.org> Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/include/asm/acpi.h15
-rw-r--r--arch/arm64/include/asm/psci.h3
-rw-r--r--arch/arm64/kernel/psci.c78
-rw-r--r--arch/arm64/kernel/setup.c8
4 files changed, 76 insertions, 28 deletions
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index c5a9b9741635..9ea650c991c9 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -32,6 +32,18 @@ extern int acpi_disabled;
32extern int acpi_noirq; 32extern int acpi_noirq;
33extern int acpi_pci_disabled; 33extern int acpi_pci_disabled;
34 34
35/* 1 to indicate PSCI 0.2+ is implemented */
36static inline bool acpi_psci_present(void)
37{
38 return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT;
39}
40
41/* 1 to indicate HVC must be used instead of SMC as the PSCI conduit */
42static inline bool acpi_psci_use_hvc(void)
43{
44 return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;
45}
46
35static inline void disable_acpi(void) 47static inline void disable_acpi(void)
36{ 48{
37 acpi_disabled = 1; 49 acpi_disabled = 1;
@@ -60,6 +72,9 @@ static inline bool acpi_has_cpu_in_madt(void)
60 72
61static inline void arch_fix_phys_package_id(int num, u32 slot) { } 73static inline void arch_fix_phys_package_id(int num, u32 slot) { }
62 74
75#else
76static inline bool acpi_psci_present(void) { return false; }
77static inline bool acpi_psci_use_hvc(void) { return false; }
63#endif /* CONFIG_ACPI */ 78#endif /* CONFIG_ACPI */
64 79
65#endif /*_ASM_ACPI_H*/ 80#endif /*_ASM_ACPI_H*/
diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
index e5312ea0ec1a..2454bc59c916 100644
--- a/arch/arm64/include/asm/psci.h
+++ b/arch/arm64/include/asm/psci.h
@@ -14,6 +14,7 @@
14#ifndef __ASM_PSCI_H 14#ifndef __ASM_PSCI_H
15#define __ASM_PSCI_H 15#define __ASM_PSCI_H
16 16
17int psci_init(void); 17int psci_dt_init(void);
18int psci_acpi_init(void);
18 19
19#endif /* __ASM_PSCI_H */ 20#endif /* __ASM_PSCI_H */
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 9b8a70ae64a1..d3c52ce5faf3 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -15,6 +15,7 @@
15 15
16#define pr_fmt(fmt) "psci: " fmt 16#define pr_fmt(fmt) "psci: " fmt
17 17
18#include <linux/acpi.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/of.h> 20#include <linux/of.h>
20#include <linux/smp.h> 21#include <linux/smp.h>
@@ -24,6 +25,7 @@
24#include <linux/slab.h> 25#include <linux/slab.h>
25#include <uapi/linux/psci.h> 26#include <uapi/linux/psci.h>
26 27
28#include <asm/acpi.h>
27#include <asm/compiler.h> 29#include <asm/compiler.h>
28#include <asm/cpu_ops.h> 30#include <asm/cpu_ops.h>
29#include <asm/errno.h> 31#include <asm/errno.h>
@@ -273,6 +275,33 @@ static void psci_sys_poweroff(void)
273 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); 275 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
274} 276}
275 277
278static void __init psci_0_2_set_functions(void)
279{
280 pr_info("Using standard PSCI v0.2 function IDs\n");
281 psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
282 psci_ops.cpu_suspend = psci_cpu_suspend;
283
284 psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
285 psci_ops.cpu_off = psci_cpu_off;
286
287 psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON;
288 psci_ops.cpu_on = psci_cpu_on;
289
290 psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE;
291 psci_ops.migrate = psci_migrate;
292
293 psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO;
294 psci_ops.affinity_info = psci_affinity_info;
295
296 psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
297 PSCI_0_2_FN_MIGRATE_INFO_TYPE;
298 psci_ops.migrate_info_type = psci_migrate_info_type;
299
300 arm_pm_restart = psci_sys_reset;
301
302 pm_power_off = psci_sys_poweroff;
303}
304
276/* 305/*
277 * PSCI Function IDs for v0.2+ are well defined so use 306 * PSCI Function IDs for v0.2+ are well defined so use
278 * standard values. 307 * standard values.
@@ -306,29 +335,7 @@ static int __init psci_0_2_init(struct device_node *np)
306 } 335 }
307 } 336 }
308 337
309 pr_info("Using standard PSCI v0.2 function IDs\n"); 338 psci_0_2_set_functions();
310 psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
311 psci_ops.cpu_suspend = psci_cpu_suspend;
312
313 psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
314 psci_ops.cpu_off = psci_cpu_off;
315
316 psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON;
317 psci_ops.cpu_on = psci_cpu_on;
318
319 psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE;
320 psci_ops.migrate = psci_migrate;
321
322 psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO;
323 psci_ops.affinity_info = psci_affinity_info;
324
325 psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
326 PSCI_0_2_FN_MIGRATE_INFO_TYPE;
327 psci_ops.migrate_info_type = psci_migrate_info_type;
328
329 arm_pm_restart = psci_sys_reset;
330
331 pm_power_off = psci_sys_poweroff;
332 339
333out_put_node: 340out_put_node:
334 of_node_put(np); 341 of_node_put(np);
@@ -381,7 +388,7 @@ static const struct of_device_id psci_of_match[] __initconst = {
381 {}, 388 {},
382}; 389};
383 390
384int __init psci_init(void) 391int __init psci_dt_init(void)
385{ 392{
386 struct device_node *np; 393 struct device_node *np;
387 const struct of_device_id *matched_np; 394 const struct of_device_id *matched_np;
@@ -396,6 +403,29 @@ int __init psci_init(void)
396 return init_fn(np); 403 return init_fn(np);
397} 404}
398 405
406/*
407 * We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
408 * explicitly clarified in SBBR
409 */
410int __init psci_acpi_init(void)
411{
412 if (!acpi_psci_present()) {
413 pr_info("is not implemented in ACPI.\n");
414 return -EOPNOTSUPP;
415 }
416
417 pr_info("probing for conduit method from ACPI.\n");
418
419 if (acpi_psci_use_hvc())
420 invoke_psci_fn = __invoke_psci_fn_hvc;
421 else
422 invoke_psci_fn = __invoke_psci_fn_smc;
423
424 psci_0_2_set_functions();
425
426 return 0;
427}
428
399#ifdef CONFIG_SMP 429#ifdef CONFIG_SMP
400 430
401static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu) 431static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index e8c7000af5ba..97fa7f31981d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -390,10 +390,12 @@ void __init setup_arch(char **cmdline_p)
390 390
391 early_ioremap_reset(); 391 early_ioremap_reset();
392 392
393 if (acpi_disabled) 393 if (acpi_disabled) {
394 unflatten_device_tree(); 394 unflatten_device_tree();
395 395 psci_dt_init();
396 psci_init(); 396 } else {
397 psci_acpi_init();
398 }
397 399
398 cpu_read_bootcpu_ops(); 400 cpu_read_bootcpu_ops();
399#ifdef CONFIG_SMP 401#ifdef CONFIG_SMP