diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/cpu/armv8/Kconfig | 18 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fwcall.c | 59 | ||||
-rw-r--r-- | arch/arm/include/asm/system.h | 12 | ||||
-rw-r--r-- | arch/arm/mach-meson/board.c | 2 |
4 files changed, 76 insertions, 15 deletions
diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig index 7e1fc4c..cd2d9bb 100644 --- a/arch/arm/cpu/armv8/Kconfig +++ b/arch/arm/cpu/armv8/Kconfig @@ -21,4 +21,22 @@ config ARMV8_SPIN_TABLE - Reserve the code for the spin-table and the release address via a /memreserve/ region in the Device Tree. +config PSCI_RESET + bool "Use PSCI for reset and shutdown" + default y + depends on !ARCH_EXYNOS7 && !ARCH_BCM283X && !TARGET_LS2080A_EMU && \ + !TARGET_LS2080A_SIMU && !TARGET_LS2080AQDS && \ + !TARGET_LS2080ARDB && !TARGET_LS1012AQDS && \ + !TARGET_LS1012ARDB && !TARGET_LS1012AFRDM && \ + !TARGET_LS1043ARDB && !ARCH_UNIPHIER && !ARCH_SNAPDRAGON && \ + !TARGET_S32V234EVB + help + Most armv8 systems have PSCI support enabled in EL3, either through + ARM Trusted Firmware or other firmware. + + On these systems, we do not need to implement system reset manually, + but can instead rely on higher level firmware to deal with it. + + Select Y here to make use of PSCI calls for system reset + endif diff --git a/arch/arm/cpu/armv8/fwcall.c b/arch/arm/cpu/armv8/fwcall.c index 079e250..7dfd270 100644 --- a/arch/arm/cpu/armv8/fwcall.c +++ b/arch/arm/cpu/armv8/fwcall.c @@ -6,6 +6,7 @@ #include <asm-offsets.h> #include <config.h> +#include <efi_loader.h> #include <version.h> #include <asm/macro.h> #include <asm/psci.h> @@ -17,7 +18,7 @@ * x0~x7: input arguments * x0~x3: output arguments */ -void hvc_call(struct pt_regs *args) +static void __efi_runtime hvc_call(struct pt_regs *args) { asm volatile( "ldr x0, %0\n" @@ -51,7 +52,7 @@ void hvc_call(struct pt_regs *args) * x0~x3: output arguments */ -void smc_call(struct pt_regs *args) +void __efi_runtime smc_call(struct pt_regs *args) { asm volatile( "ldr x0, %0\n" @@ -75,13 +76,36 @@ void smc_call(struct pt_regs *args) "x16", "x17"); } -void __noreturn psci_system_reset(bool conduit_smc) +/* + * For now, all systems we support run at least in EL2 and thus + * trigger PSCI calls to EL3 using SMC. If anyone ever wants to + * use PSCI on U-Boot running below a hypervisor, please detect + * this and set the flag accordingly. + */ +static const __efi_runtime_data bool use_smc_for_psci = true; + +void __noreturn __efi_runtime psci_system_reset(void) { struct pt_regs regs; regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET; - if (conduit_smc) + if (use_smc_for_psci) + smc_call(®s); + else + hvc_call(®s); + + while (1) + ; +} + +void __noreturn __efi_runtime psci_system_off(void) +{ + struct pt_regs regs; + + regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_OFF; + + if (use_smc_for_psci) smc_call(®s); else hvc_call(®s); @@ -89,3 +113,30 @@ void __noreturn psci_system_reset(bool conduit_smc) while (1) ; } + +#ifdef CONFIG_PSCI_RESET +void reset_misc(void) +{ + psci_system_reset(); +} + +#ifdef CONFIG_EFI_LOADER +void __efi_runtime EFIAPI efi_reset_system( + enum efi_reset_type reset_type, + efi_status_t reset_status, + unsigned long data_size, void *reset_data) +{ + switch (reset_type) { + case EFI_RESET_COLD: + case EFI_RESET_WARM: + psci_system_reset(); + break; + case EFI_RESET_SHUTDOWN: + psci_system_off(); + break; + } + + while (1) { } +} +#endif /* CONFIG_EFI_LOADER */ +#endif /* CONFIG_PSCI_RESET */ diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index c18e1e3..b928bd8 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -107,15 +107,6 @@ void smp_kick_all_cpus(void); void flush_l3_cache(void); /* - *Issue a hypervisor call in accordance with ARM "SMC Calling convention", - * DEN0028A - * - * @args: input and output arguments - * - */ -void hvc_call(struct pt_regs *args); - -/* *Issue a secure monitor call in accordance with ARM "SMC Calling convention", * DEN0028A * @@ -124,7 +115,8 @@ void hvc_call(struct pt_regs *args); */ void smc_call(struct pt_regs *args); -void __noreturn psci_system_reset(bool smc); +void __noreturn psci_system_reset(void); +void __noreturn psci_system_off(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/mach-meson/board.c b/arch/arm/mach-meson/board.c index 1dd53e2..f159cbf 100644 --- a/arch/arm/mach-meson/board.c +++ b/arch/arm/mach-meson/board.c @@ -43,7 +43,7 @@ void dram_init_banksize(void) void reset_cpu(ulong addr) { - psci_system_reset(true); + psci_system_reset(); } static struct mm_region gxbb_mem_map[] = { |