xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/rockchip_smccc.c (revision 3c3675ddd7dfb95c8dc592003d9f5feb2e081ff9)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 
7 #include <asm/arch/rockchip_smccc.h>
8 #include <asm/io.h>
9 #include <asm/psci.h>
10 #include <asm/suspend.h>
11 #include <linux/arm-smccc.h>
12 #include <linux/io.h>
13 
14 #ifdef CONFIG_ARM64
15 #define ARM_PSCI_1_0_SYSTEM_SUSPEND	ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND
16 #else
17 #define ARM_PSCI_1_0_SYSTEM_SUSPEND	ARM_PSCI_1_0_FN_SYSTEM_SUSPEND
18 #endif
19 
20 #define SIZE_PAGE(n)	((n) << 12)
21 
22 static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
23 						unsigned long arg0,
24 						unsigned long arg1,
25 						unsigned long arg2)
26 {
27 	struct arm_smccc_res res;
28 
29 	arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
30 	return res;
31 }
32 
33 int psci_system_suspend(unsigned long unused)
34 {
35 	struct arm_smccc_res res;
36 
37 	res = __invoke_sip_fn_smc(ARM_PSCI_1_0_SYSTEM_SUSPEND,
38 				  virt_to_phys(cpu_resume), 0, 0);
39 	return res.a0;
40 }
41 
42 int sip_smc_set_suspend_mode(unsigned long ctrl,
43 			     unsigned long config1,
44 			     unsigned long config2)
45 {
46 	struct arm_smccc_res res;
47 
48 	res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2);
49 	return res.a0;
50 }
51 
52 struct arm_smccc_res sip_smc_dram(unsigned long arg0,
53 				  unsigned long arg1,
54 				  unsigned long arg2)
55 {
56 	return __invoke_sip_fn_smc(SIP_DRAM_CONFIG, arg0, arg1, arg2);
57 }
58 
59 struct arm_smccc_res sip_smc_request_share_mem(unsigned long page_num,
60 					       share_page_type_t page_type)
61 {
62 	struct arm_smccc_res res;
63 	unsigned long share_mem_phy;
64 
65 	res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0);
66 	if (IS_SIP_ERROR(res.a0))
67 		goto error;
68 
69 	share_mem_phy = res.a1;
70 	res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
71 
72 error:
73 	return res;
74 }
75 
76 struct arm_smccc_res sip_smc_get_sip_version(void)
77 {
78 	return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0);
79 }
80 
81 /*
82  * OP-TEE works both for kernel 3.10 and 4.4, and these two kernels have
83  * different sip implement that 3.10 uses SIP_IMPLEMENT_V1 and 4.4 uses
84  * SIP_IMPLEMENT_V2. So we should tell OP-TEE the current rockchip sip
85  * version(default SIP_IMPLEMENT_V1) before use.
86  */
87 int sip_smc_set_sip_version(unsigned long version)
88 {
89 	struct arm_smccc_res res;
90 
91 	res = __invoke_sip_fn_smc(SIP_SIP_VERSION, version, SECURE_REG_WR, 0);
92 	if (IS_SIP_ERROR(res.a0)) {
93 		printf("%s: set rockchip sip version v%ld failed\n",
94 		       __func__, version);
95 		return res.a0;
96 	}
97 
98 	return 0;
99 }
100