xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-rockchip/rockchip_smccc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:     GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <asm/arch/rockchip_smccc.h>
8*4882a593Smuzhiyun #include <asm/io.h>
9*4882a593Smuzhiyun #include <asm/psci.h>
10*4882a593Smuzhiyun #include <asm/suspend.h>
11*4882a593Smuzhiyun #include <linux/io.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #ifdef CONFIG_ARM64
14*4882a593Smuzhiyun #define ARM_PSCI_1_0_SYSTEM_SUSPEND	ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND
15*4882a593Smuzhiyun #define ARM_PSCI_0_2_CPU_ON		ARM_PSCI_0_2_FN64_CPU_ON
16*4882a593Smuzhiyun #else
17*4882a593Smuzhiyun #define ARM_PSCI_1_0_SYSTEM_SUSPEND	ARM_PSCI_1_0_FN_SYSTEM_SUSPEND
18*4882a593Smuzhiyun #define ARM_PSCI_0_2_CPU_ON		ARM_PSCI_0_2_FN_CPU_ON
19*4882a593Smuzhiyun #endif
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define SIZE_PAGE(n)	((n) << 12)
22*4882a593Smuzhiyun 
__invoke_sip_fn_smc(unsigned long function_id,unsigned long arg0,unsigned long arg1,unsigned long arg2)23*4882a593Smuzhiyun static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
24*4882a593Smuzhiyun 						unsigned long arg0,
25*4882a593Smuzhiyun 						unsigned long arg1,
26*4882a593Smuzhiyun 						unsigned long arg2)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	struct arm_smccc_res res;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
31*4882a593Smuzhiyun 	return res;
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun 
psci_cpu_on(unsigned long cpuid,unsigned long entry_point)34*4882a593Smuzhiyun int psci_cpu_on(unsigned long cpuid, unsigned long entry_point)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	struct arm_smccc_res res;
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(ARM_PSCI_0_2_CPU_ON, cpuid, entry_point, 0);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	return res.a0;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #ifdef CONFIG_ARM_CPU_SUSPEND
psci_system_suspend(unsigned long unused)44*4882a593Smuzhiyun int psci_system_suspend(unsigned long unused)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	struct arm_smccc_res res;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(ARM_PSCI_1_0_SYSTEM_SUSPEND,
49*4882a593Smuzhiyun 				  virt_to_phys(cpu_resume), 0, 0);
50*4882a593Smuzhiyun 	return res.a0;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun #endif
53*4882a593Smuzhiyun 
sip_smc_set_suspend_mode(unsigned long ctrl,unsigned long config1,unsigned long config2)54*4882a593Smuzhiyun int sip_smc_set_suspend_mode(unsigned long ctrl,
55*4882a593Smuzhiyun 			     unsigned long config1,
56*4882a593Smuzhiyun 			     unsigned long config2)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	struct arm_smccc_res res;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2);
61*4882a593Smuzhiyun 	return res.a0;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
sip_smc_remotectl_config(unsigned long func,unsigned long data)64*4882a593Smuzhiyun int sip_smc_remotectl_config(unsigned long func, unsigned long data)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	struct arm_smccc_res res;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_REMOTECTL_CFG, func, data, 0);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return res.a0;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
sip_smc_amp_cfg(unsigned long func,unsigned long arg0,unsigned long arg1,unsigned long arg2)73*4882a593Smuzhiyun int sip_smc_amp_cfg(unsigned long func, unsigned long arg0, unsigned long arg1,
74*4882a593Smuzhiyun 		    unsigned long arg2)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	struct arm_smccc_res res;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	arm_smccc_smc(SIP_AMP_CFG, func, arg0, arg1, arg2, 0, 0, 0, &res);
79*4882a593Smuzhiyun 	return res.a0;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
sip_smc_dram(unsigned long arg0,unsigned long arg1,unsigned long arg2)82*4882a593Smuzhiyun struct arm_smccc_res sip_smc_dram(unsigned long arg0,
83*4882a593Smuzhiyun 				  unsigned long arg1,
84*4882a593Smuzhiyun 				  unsigned long arg2)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	return __invoke_sip_fn_smc(SIP_DRAM_CONFIG, arg0, arg1, arg2);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
sip_smc_request_share_mem(unsigned long page_num,share_page_type_t page_type)89*4882a593Smuzhiyun struct arm_smccc_res sip_smc_request_share_mem(unsigned long page_num,
90*4882a593Smuzhiyun 					       share_page_type_t page_type)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	struct arm_smccc_res res;
93*4882a593Smuzhiyun 	unsigned long share_mem_phy;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0);
96*4882a593Smuzhiyun 	if (IS_SIP_ERROR(res.a0))
97*4882a593Smuzhiyun 		goto error;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	share_mem_phy = res.a1;
100*4882a593Smuzhiyun 	res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun error:
103*4882a593Smuzhiyun 	return res;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
sip_smc_secure_reg_read(unsigned long addr_phy)106*4882a593Smuzhiyun struct arm_smccc_res sip_smc_secure_reg_read(unsigned long addr_phy)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	struct arm_smccc_res res;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_ACCESS_REG, 0, addr_phy, SECURE_REG_RD);
111*4882a593Smuzhiyun 	return res;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
sip_smc_secure_reg_write(unsigned long addr_phy,unsigned long val)114*4882a593Smuzhiyun int sip_smc_secure_reg_write(unsigned long addr_phy, unsigned long val)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	struct arm_smccc_res res;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_ACCESS_REG, val, addr_phy, SECURE_REG_WR);
119*4882a593Smuzhiyun 	return res.a0;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
sip_smc_hdcp_config(unsigned long func,unsigned long arg1,unsigned long arg2)122*4882a593Smuzhiyun int sip_smc_hdcp_config(unsigned long func, unsigned long arg1, unsigned long arg2)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	struct arm_smccc_res res;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_HDCP_CONFIG, func, arg1, arg2);
127*4882a593Smuzhiyun 	return res.a0;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
sip_smc_get_sip_version(void)130*4882a593Smuzhiyun struct arm_smccc_res sip_smc_get_sip_version(void)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun /*
136*4882a593Smuzhiyun  * OP-TEE works both for kernel 3.10 and 4.4, and these two kernels have
137*4882a593Smuzhiyun  * different sip implement that 3.10 uses SIP_IMPLEMENT_V1 and 4.4 uses
138*4882a593Smuzhiyun  * SIP_IMPLEMENT_V2. So we should tell OP-TEE the current rockchip sip
139*4882a593Smuzhiyun  * version(default SIP_IMPLEMENT_V1) before use.
140*4882a593Smuzhiyun  */
sip_smc_set_sip_version(unsigned long version)141*4882a593Smuzhiyun int sip_smc_set_sip_version(unsigned long version)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	struct arm_smccc_res res;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SIP_VERSION, version, SECURE_REG_WR, 0);
146*4882a593Smuzhiyun 	if (IS_SIP_ERROR(res.a0)) {
147*4882a593Smuzhiyun 		printf("%s: set rockchip sip version v%ld failed\n",
148*4882a593Smuzhiyun 		       __func__, version);
149*4882a593Smuzhiyun 		return res.a0;
150*4882a593Smuzhiyun 	}
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	return 0;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
sip_smc_mcu_config(unsigned long mcu_id,unsigned long func,unsigned long arg2)155*4882a593Smuzhiyun int sip_smc_mcu_config(unsigned long mcu_id, unsigned long func, unsigned long arg2)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	struct arm_smccc_res res;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_MCU_CFG, mcu_id, func, arg2);
160*4882a593Smuzhiyun 	return res.a0;
161*4882a593Smuzhiyun }
162