1a5b9fa30SSergey Temerkhanov /** 2a5b9fa30SSergey Temerkhanov * (C) Copyright 2014, Cavium Inc. 3a5b9fa30SSergey Temerkhanov * 4a5b9fa30SSergey Temerkhanov * SPDX-License-Identifier: GPL-2.0+ 5a5b9fa30SSergey Temerkhanov **/ 6a5b9fa30SSergey Temerkhanov 7a5b9fa30SSergey Temerkhanov #include <asm-offsets.h> 8a5b9fa30SSergey Temerkhanov #include <config.h> 9b6575f34SAlexander Graf #include <efi_loader.h> 10a5b9fa30SSergey Temerkhanov #include <version.h> 11a5b9fa30SSergey Temerkhanov #include <asm/macro.h> 125a07abb3SBeniamino Galvani #include <asm/psci.h> 13a5b9fa30SSergey Temerkhanov #include <asm/system.h> 14a5b9fa30SSergey Temerkhanov 15a5b9fa30SSergey Temerkhanov /* 16a5b9fa30SSergey Temerkhanov * Issue the hypervisor call 17a5b9fa30SSergey Temerkhanov * 18a5b9fa30SSergey Temerkhanov * x0~x7: input arguments 19a5b9fa30SSergey Temerkhanov * x0~x3: output arguments 20a5b9fa30SSergey Temerkhanov */ 21*3c63db9cSAlexander Graf static void __efi_runtime hvc_call(struct pt_regs *args) 22a5b9fa30SSergey Temerkhanov { 23a5b9fa30SSergey Temerkhanov asm volatile( 24a5b9fa30SSergey Temerkhanov "ldr x0, %0\n" 25a5b9fa30SSergey Temerkhanov "ldr x1, %1\n" 26a5b9fa30SSergey Temerkhanov "ldr x2, %2\n" 27a5b9fa30SSergey Temerkhanov "ldr x3, %3\n" 28a5b9fa30SSergey Temerkhanov "ldr x4, %4\n" 29a5b9fa30SSergey Temerkhanov "ldr x5, %5\n" 30a5b9fa30SSergey Temerkhanov "ldr x6, %6\n" 31a5b9fa30SSergey Temerkhanov "ldr x7, %7\n" 32a5b9fa30SSergey Temerkhanov "hvc #0\n" 33a5b9fa30SSergey Temerkhanov "str x0, %0\n" 34a5b9fa30SSergey Temerkhanov "str x1, %1\n" 35a5b9fa30SSergey Temerkhanov "str x2, %2\n" 36a5b9fa30SSergey Temerkhanov "str x3, %3\n" 37a5b9fa30SSergey Temerkhanov : "+m" (args->regs[0]), "+m" (args->regs[1]), 38a5b9fa30SSergey Temerkhanov "+m" (args->regs[2]), "+m" (args->regs[3]) 39a5b9fa30SSergey Temerkhanov : "m" (args->regs[4]), "m" (args->regs[5]), 40a5b9fa30SSergey Temerkhanov "m" (args->regs[6]), "m" (args->regs[7]) 41a5b9fa30SSergey Temerkhanov : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 42a5b9fa30SSergey Temerkhanov "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 43a5b9fa30SSergey Temerkhanov "x16", "x17"); 44a5b9fa30SSergey Temerkhanov } 45a5b9fa30SSergey Temerkhanov 46a5b9fa30SSergey Temerkhanov /* 47a5b9fa30SSergey Temerkhanov * void smc_call(arg0, arg1...arg7) 48a5b9fa30SSergey Temerkhanov * 49a5b9fa30SSergey Temerkhanov * issue the secure monitor call 50a5b9fa30SSergey Temerkhanov * 51a5b9fa30SSergey Temerkhanov * x0~x7: input arguments 52a5b9fa30SSergey Temerkhanov * x0~x3: output arguments 53a5b9fa30SSergey Temerkhanov */ 54a5b9fa30SSergey Temerkhanov 55*3c63db9cSAlexander Graf void __efi_runtime smc_call(struct pt_regs *args) 56a5b9fa30SSergey Temerkhanov { 57a5b9fa30SSergey Temerkhanov asm volatile( 58a5b9fa30SSergey Temerkhanov "ldr x0, %0\n" 59a5b9fa30SSergey Temerkhanov "ldr x1, %1\n" 60a5b9fa30SSergey Temerkhanov "ldr x2, %2\n" 61a5b9fa30SSergey Temerkhanov "ldr x3, %3\n" 62a5b9fa30SSergey Temerkhanov "ldr x4, %4\n" 63a5b9fa30SSergey Temerkhanov "ldr x5, %5\n" 64a5b9fa30SSergey Temerkhanov "ldr x6, %6\n" 65a5b9fa30SSergey Temerkhanov "smc #0\n" 66a5b9fa30SSergey Temerkhanov "str x0, %0\n" 67a5b9fa30SSergey Temerkhanov "str x1, %1\n" 68a5b9fa30SSergey Temerkhanov "str x2, %2\n" 69a5b9fa30SSergey Temerkhanov "str x3, %3\n" 70a5b9fa30SSergey Temerkhanov : "+m" (args->regs[0]), "+m" (args->regs[1]), 71a5b9fa30SSergey Temerkhanov "+m" (args->regs[2]), "+m" (args->regs[3]) 72a5b9fa30SSergey Temerkhanov : "m" (args->regs[4]), "m" (args->regs[5]), 73a5b9fa30SSergey Temerkhanov "m" (args->regs[6]) 74a5b9fa30SSergey Temerkhanov : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 75a5b9fa30SSergey Temerkhanov "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 76a5b9fa30SSergey Temerkhanov "x16", "x17"); 77a5b9fa30SSergey Temerkhanov } 785a07abb3SBeniamino Galvani 7951bfb5b6SAlexander Graf /* 8051bfb5b6SAlexander Graf * For now, all systems we support run at least in EL2 and thus 8151bfb5b6SAlexander Graf * trigger PSCI calls to EL3 using SMC. If anyone ever wants to 8251bfb5b6SAlexander Graf * use PSCI on U-Boot running below a hypervisor, please detect 8351bfb5b6SAlexander Graf * this and set the flag accordingly. 8451bfb5b6SAlexander Graf */ 85*3c63db9cSAlexander Graf static const __efi_runtime_data bool use_smc_for_psci = true; 8651bfb5b6SAlexander Graf 87*3c63db9cSAlexander Graf void __noreturn __efi_runtime psci_system_reset(void) 885a07abb3SBeniamino Galvani { 895a07abb3SBeniamino Galvani struct pt_regs regs; 905a07abb3SBeniamino Galvani 915a07abb3SBeniamino Galvani regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET; 925a07abb3SBeniamino Galvani 9351bfb5b6SAlexander Graf if (use_smc_for_psci) 945a07abb3SBeniamino Galvani smc_call(®s); 955a07abb3SBeniamino Galvani else 965a07abb3SBeniamino Galvani hvc_call(®s); 975a07abb3SBeniamino Galvani 985a07abb3SBeniamino Galvani while (1) 995a07abb3SBeniamino Galvani ; 1005a07abb3SBeniamino Galvani } 1013ee655edSAlexander Graf 102*3c63db9cSAlexander Graf void __noreturn __efi_runtime psci_system_off(void) 1033ee655edSAlexander Graf { 1043ee655edSAlexander Graf struct pt_regs regs; 1053ee655edSAlexander Graf 1063ee655edSAlexander Graf regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_OFF; 1073ee655edSAlexander Graf 1083ee655edSAlexander Graf if (use_smc_for_psci) 1093ee655edSAlexander Graf smc_call(®s); 1103ee655edSAlexander Graf else 1113ee655edSAlexander Graf hvc_call(®s); 1123ee655edSAlexander Graf 1133ee655edSAlexander Graf while (1) 1143ee655edSAlexander Graf ; 1153ee655edSAlexander Graf } 1168069821fSAlexander Graf 1178069821fSAlexander Graf #ifdef CONFIG_PSCI_RESET 1188069821fSAlexander Graf void reset_misc(void) 1198069821fSAlexander Graf { 1208069821fSAlexander Graf psci_system_reset(); 1218069821fSAlexander Graf } 122b6575f34SAlexander Graf 123b6575f34SAlexander Graf #ifdef CONFIG_EFI_LOADER 124*3c63db9cSAlexander Graf void __efi_runtime EFIAPI efi_reset_system( 125b6575f34SAlexander Graf enum efi_reset_type reset_type, 126b6575f34SAlexander Graf efi_status_t reset_status, 127b6575f34SAlexander Graf unsigned long data_size, void *reset_data) 128b6575f34SAlexander Graf { 129b6575f34SAlexander Graf switch (reset_type) { 130b6575f34SAlexander Graf case EFI_RESET_COLD: 131b6575f34SAlexander Graf case EFI_RESET_WARM: 132b6575f34SAlexander Graf psci_system_reset(); 133b6575f34SAlexander Graf break; 134b6575f34SAlexander Graf case EFI_RESET_SHUTDOWN: 135b6575f34SAlexander Graf psci_system_off(); 136b6575f34SAlexander Graf break; 137b6575f34SAlexander Graf } 138b6575f34SAlexander Graf 139b6575f34SAlexander Graf while (1) { } 140b6575f34SAlexander Graf } 141b6575f34SAlexander Graf #endif /* CONFIG_EFI_LOADER */ 1428069821fSAlexander Graf #endif /* CONFIG_PSCI_RESET */ 143