xref: /openbmc/u-boot/arch/arm/cpu/armv8/fwcall.c (revision f388e3bed7318efe97058b673801dda6f563d319)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2a5b9fa30SSergey Temerkhanov /**
3a5b9fa30SSergey Temerkhanov  * (C) Copyright 2014, Cavium Inc.
43c85417fSMichal Simek  * (C) Copyright 2017, Xilinx Inc.
5a5b9fa30SSergey Temerkhanov  *
6a5b9fa30SSergey Temerkhanov **/
7a5b9fa30SSergey Temerkhanov 
8a5b9fa30SSergey Temerkhanov #include <asm-offsets.h>
9a5b9fa30SSergey Temerkhanov #include <config.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  */
hvc_call(struct pt_regs * args)21*81ea0083SHeinrich Schuchardt static void 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 
smc_call(struct pt_regs * args)55*81ea0083SHeinrich Schuchardt void 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*81ea0083SHeinrich Schuchardt static const bool use_smc_for_psci = true;
8651bfb5b6SAlexander Graf 
psci_system_reset(void)87*81ea0083SHeinrich Schuchardt void __noreturn 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(&regs);
955a07abb3SBeniamino Galvani 	else
965a07abb3SBeniamino Galvani 		hvc_call(&regs);
975a07abb3SBeniamino Galvani 
985a07abb3SBeniamino Galvani 	while (1)
995a07abb3SBeniamino Galvani 		;
1005a07abb3SBeniamino Galvani }
1013ee655edSAlexander Graf 
psci_system_off(void)102*81ea0083SHeinrich Schuchardt void __noreturn 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(&regs);
1103ee655edSAlexander Graf 	else
1113ee655edSAlexander Graf 		hvc_call(&regs);
1123ee655edSAlexander Graf 
1133ee655edSAlexander Graf 	while (1)
1143ee655edSAlexander Graf 		;
1153ee655edSAlexander Graf }
116