Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Graeme Gregory and committed by
Will Deacon
7c59a3df 3505f30f

+76 -28
+15
arch/arm64/include/asm/acpi.h
··· 32 32 extern int acpi_noirq; 33 33 extern int acpi_pci_disabled; 34 34 35 + /* 1 to indicate PSCI 0.2+ is implemented */ 36 + static 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 */ 42 + static inline bool acpi_psci_use_hvc(void) 43 + { 44 + return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC; 45 + } 46 + 35 47 static inline void disable_acpi(void) 36 48 { 37 49 acpi_disabled = 1; ··· 72 60 73 61 static inline void arch_fix_phys_package_id(int num, u32 slot) { } 74 62 63 + #else 64 + static inline bool acpi_psci_present(void) { return false; } 65 + static inline bool acpi_psci_use_hvc(void) { return false; } 75 66 #endif /* CONFIG_ACPI */ 76 67 77 68 #endif /*_ASM_ACPI_H*/
+2 -1
arch/arm64/include/asm/psci.h
··· 14 14 #ifndef __ASM_PSCI_H 15 15 #define __ASM_PSCI_H 16 16 17 - int psci_init(void); 17 + int psci_dt_init(void); 18 + int psci_acpi_init(void); 18 19 19 20 #endif /* __ASM_PSCI_H */
+54 -24
arch/arm64/kernel/psci.c
··· 15 15 16 16 #define pr_fmt(fmt) "psci: " fmt 17 17 18 + #include <linux/acpi.h> 18 19 #include <linux/init.h> 19 20 #include <linux/of.h> 20 21 #include <linux/smp.h> ··· 25 24 #include <linux/slab.h> 26 25 #include <uapi/linux/psci.h> 27 26 27 + #include <asm/acpi.h> 28 28 #include <asm/compiler.h> 29 29 #include <asm/cpu_ops.h> 30 30 #include <asm/errno.h> ··· 275 273 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); 276 274 } 277 275 276 + static void __init psci_0_2_set_functions(void) 277 + { 278 + pr_info("Using standard PSCI v0.2 function IDs\n"); 279 + psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND; 280 + psci_ops.cpu_suspend = psci_cpu_suspend; 281 + 282 + psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF; 283 + psci_ops.cpu_off = psci_cpu_off; 284 + 285 + psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON; 286 + psci_ops.cpu_on = psci_cpu_on; 287 + 288 + psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE; 289 + psci_ops.migrate = psci_migrate; 290 + 291 + psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO; 292 + psci_ops.affinity_info = psci_affinity_info; 293 + 294 + psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] = 295 + PSCI_0_2_FN_MIGRATE_INFO_TYPE; 296 + psci_ops.migrate_info_type = psci_migrate_info_type; 297 + 298 + arm_pm_restart = psci_sys_reset; 299 + 300 + pm_power_off = psci_sys_poweroff; 301 + } 302 + 278 303 /* 279 304 * PSCI Function IDs for v0.2+ are well defined so use 280 305 * standard values. ··· 335 306 } 336 307 } 337 308 338 - pr_info("Using standard PSCI v0.2 function IDs\n"); 339 - psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND; 340 - psci_ops.cpu_suspend = psci_cpu_suspend; 341 - 342 - psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF; 343 - psci_ops.cpu_off = psci_cpu_off; 344 - 345 - psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON; 346 - psci_ops.cpu_on = psci_cpu_on; 347 - 348 - psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE; 349 - psci_ops.migrate = psci_migrate; 350 - 351 - psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO; 352 - psci_ops.affinity_info = psci_affinity_info; 353 - 354 - psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] = 355 - PSCI_0_2_FN_MIGRATE_INFO_TYPE; 356 - psci_ops.migrate_info_type = psci_migrate_info_type; 357 - 358 - arm_pm_restart = psci_sys_reset; 359 - 360 - pm_power_off = psci_sys_poweroff; 309 + psci_0_2_set_functions(); 361 310 362 311 out_put_node: 363 312 of_node_put(np); ··· 388 381 {}, 389 382 }; 390 383 391 - int __init psci_init(void) 384 + int __init psci_dt_init(void) 392 385 { 393 386 struct device_node *np; 394 387 const struct of_device_id *matched_np; ··· 401 394 402 395 init_fn = (psci_initcall_t)matched_np->data; 403 396 return init_fn(np); 397 + } 398 + 399 + /* 400 + * We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's 401 + * explicitly clarified in SBBR 402 + */ 403 + int __init psci_acpi_init(void) 404 + { 405 + if (!acpi_psci_present()) { 406 + pr_info("is not implemented in ACPI.\n"); 407 + return -EOPNOTSUPP; 408 + } 409 + 410 + pr_info("probing for conduit method from ACPI.\n"); 411 + 412 + if (acpi_psci_use_hvc()) 413 + invoke_psci_fn = __invoke_psci_fn_hvc; 414 + else 415 + invoke_psci_fn = __invoke_psci_fn_smc; 416 + 417 + psci_0_2_set_functions(); 418 + 419 + return 0; 404 420 } 405 421 406 422 #ifdef CONFIG_SMP
+5 -3
arch/arm64/kernel/setup.c
··· 390 390 391 391 early_ioremap_reset(); 392 392 393 - if (acpi_disabled) 393 + if (acpi_disabled) { 394 394 unflatten_device_tree(); 395 - 396 - psci_init(); 395 + psci_dt_init(); 396 + } else { 397 + psci_acpi_init(); 398 + } 397 399 398 400 cpu_read_bootcpu_ops(); 399 401 #ifdef CONFIG_SMP