X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Farm%2Fcpu%2Farmv8%2Ffwcall.c;h=c2202675366f37d3853f1ef3e5d4d11d2b4a3e08;hb=90351547ceeb76c1337757c51af0fb5a2c30bd02;hp=079e250cbe995d4f09de60f394e3a3d73e7492bf;hpb=3fc304b8d77ce6646d38ae506e9fae74b9975631;p=oweals%2Fu-boot.git diff --git a/arch/arm/cpu/armv8/fwcall.c b/arch/arm/cpu/armv8/fwcall.c index 079e250cbe..c220267536 100644 --- a/arch/arm/cpu/armv8/fwcall.c +++ b/arch/arm/cpu/armv8/fwcall.c @@ -1,11 +1,13 @@ /** * (C) Copyright 2014, Cavium Inc. + * (C) Copyright 2017, Xilinx Inc. * * SPDX-License-Identifier: GPL-2.0+ **/ #include #include +#include #include #include #include @@ -17,7 +19,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 +53,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 +77,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 +114,46 @@ void __noreturn psci_system_reset(bool conduit_smc) while (1) ; } + +#ifdef CONFIG_CMD_POWEROFF +int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + puts("poweroff ...\n"); + + udelay(50000); /* wait 50 ms */ + + disable_interrupts(); + + psci_system_off(); + + /*NOTREACHED*/ + return 0; +} +#endif + +#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 */