xref: /OK3568_Linux_fs/kernel/drivers/firmware/rockchip_sip.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or modify
3*4882a593Smuzhiyun  * it under the terms of the GNU General Public License version 2 as
4*4882a593Smuzhiyun  * published by the Free Software Foundation.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This program is distributed in the hope that it will be useful,
7*4882a593Smuzhiyun  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8*4882a593Smuzhiyun  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9*4882a593Smuzhiyun  * GNU General Public License for more details.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Copyright (C) 2016, Fuzhou Rockchip Electronics Co., Ltd
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/arm-smccc.h>
15*4882a593Smuzhiyun #include <linux/io.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/rockchip/rockchip_sip.h>
18*4882a593Smuzhiyun #include <asm/cputype.h>
19*4882a593Smuzhiyun #ifdef CONFIG_ARM
20*4882a593Smuzhiyun #include <asm/psci.h>
21*4882a593Smuzhiyun #endif
22*4882a593Smuzhiyun #include <asm/smp_plat.h>
23*4882a593Smuzhiyun #include <uapi/linux/psci.h>
24*4882a593Smuzhiyun #include <linux/ptrace.h>
25*4882a593Smuzhiyun #include <linux/sched/clock.h>
26*4882a593Smuzhiyun #include <linux/slab.h>
27*4882a593Smuzhiyun #include <soc/rockchip/rockchip_sip.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #ifdef CONFIG_64BIT
30*4882a593Smuzhiyun #define PSCI_FN_NATIVE(version, name)	PSCI_##version##_FN64_##name
31*4882a593Smuzhiyun #else
32*4882a593Smuzhiyun #define PSCI_FN_NATIVE(version, name)	PSCI_##version##_FN_##name
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define SIZE_PAGE(n)	((n) << 12)
36*4882a593Smuzhiyun 
__invoke_sip_fn_smc(unsigned long function_id,unsigned long arg0,unsigned long arg1,unsigned long arg2)37*4882a593Smuzhiyun static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
38*4882a593Smuzhiyun 						unsigned long arg0,
39*4882a593Smuzhiyun 						unsigned long arg1,
40*4882a593Smuzhiyun 						unsigned long arg2)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	struct arm_smccc_res res;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
45*4882a593Smuzhiyun 	return res;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
sip_smc_dram(u32 arg0,u32 arg1,u32 arg2)48*4882a593Smuzhiyun struct arm_smccc_res sip_smc_dram(u32 arg0, u32 arg1, u32 arg2)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	return __invoke_sip_fn_smc(SIP_DRAM_CONFIG, arg0, arg1, arg2);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_dram);
53*4882a593Smuzhiyun 
sip_smc_get_atf_version(void)54*4882a593Smuzhiyun struct arm_smccc_res sip_smc_get_atf_version(void)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	return __invoke_sip_fn_smc(SIP_ATF_VERSION, 0, 0, 0);
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_get_atf_version);
59*4882a593Smuzhiyun 
sip_smc_get_sip_version(void)60*4882a593Smuzhiyun struct arm_smccc_res sip_smc_get_sip_version(void)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0);
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_get_sip_version);
65*4882a593Smuzhiyun 
sip_smc_set_suspend_mode(u32 ctrl,u32 config1,u32 config2)66*4882a593Smuzhiyun int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	struct arm_smccc_res res;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2);
71*4882a593Smuzhiyun 	return res.a0;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_set_suspend_mode);
74*4882a593Smuzhiyun 
sip_smc_get_suspend_info(u32 info)75*4882a593Smuzhiyun struct arm_smccc_res sip_smc_get_suspend_info(u32 info)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	struct arm_smccc_res res;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, info, 0, 0);
80*4882a593Smuzhiyun 	return res;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_get_suspend_info);
83*4882a593Smuzhiyun 
sip_smc_virtual_poweroff(void)84*4882a593Smuzhiyun int sip_smc_virtual_poweroff(void)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	struct arm_smccc_res res;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND), 0, 0, 0);
89*4882a593Smuzhiyun 	return res.a0;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_virtual_poweroff);
92*4882a593Smuzhiyun 
sip_smc_remotectl_config(u32 func,u32 data)93*4882a593Smuzhiyun int sip_smc_remotectl_config(u32 func, u32 data)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	struct arm_smccc_res res;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_REMOTECTL_CFG, func, data, 0);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	return res.a0;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_remotectl_config);
102*4882a593Smuzhiyun 
sip_smc_secure_reg_read(u32 addr_phy)103*4882a593Smuzhiyun u32 sip_smc_secure_reg_read(u32 addr_phy)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	struct arm_smccc_res res;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_ACCESS_REG, 0, addr_phy, SECURE_REG_RD);
108*4882a593Smuzhiyun 	if (res.a0)
109*4882a593Smuzhiyun 		pr_err("%s error: %d, addr phy: 0x%x\n",
110*4882a593Smuzhiyun 		       __func__, (int)res.a0, addr_phy);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	return res.a1;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_secure_reg_read);
115*4882a593Smuzhiyun 
sip_smc_secure_reg_write(u32 addr_phy,u32 val)116*4882a593Smuzhiyun int sip_smc_secure_reg_write(u32 addr_phy, u32 val)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	struct arm_smccc_res res;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_ACCESS_REG, val, addr_phy, SECURE_REG_WR);
121*4882a593Smuzhiyun 	if (res.a0)
122*4882a593Smuzhiyun 		pr_err("%s error: %d, addr phy: 0x%x\n",
123*4882a593Smuzhiyun 		       __func__, (int)res.a0, addr_phy);
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	return res.a0;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_secure_reg_write);
128*4882a593Smuzhiyun 
sip_map(phys_addr_t start,size_t size)129*4882a593Smuzhiyun static void *sip_map(phys_addr_t start, size_t size)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	struct page **pages;
132*4882a593Smuzhiyun 	phys_addr_t page_start;
133*4882a593Smuzhiyun 	unsigned int page_count;
134*4882a593Smuzhiyun 	pgprot_t prot;
135*4882a593Smuzhiyun 	unsigned int i;
136*4882a593Smuzhiyun 	void *vaddr;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	if (!pfn_valid(__phys_to_pfn(start)))
139*4882a593Smuzhiyun 		return ioremap(start, size);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	page_start = start - offset_in_page(start);
142*4882a593Smuzhiyun 	page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	prot = pgprot_noncached(PAGE_KERNEL);
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL);
147*4882a593Smuzhiyun 	if (!pages) {
148*4882a593Smuzhiyun 		pr_err("%s: Failed to allocate array for %u pages\n",
149*4882a593Smuzhiyun 		       __func__, page_count);
150*4882a593Smuzhiyun 		return NULL;
151*4882a593Smuzhiyun 	}
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	for (i = 0; i < page_count; i++)
154*4882a593Smuzhiyun 		pages[i] = phys_to_page(page_start + i * PAGE_SIZE);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	vaddr = vmap(pages, page_count, VM_MAP, prot);
157*4882a593Smuzhiyun 	kfree(pages);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	/*
160*4882a593Smuzhiyun 	 * Since vmap() uses page granularity, we must add the offset
161*4882a593Smuzhiyun 	 * into the page here, to get the byte granularity address
162*4882a593Smuzhiyun 	 * into the mapping to represent the actual "start" location.
163*4882a593Smuzhiyun 	 */
164*4882a593Smuzhiyun 	return vaddr + offset_in_page(start);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
sip_smc_request_share_mem(u32 page_num,share_page_type_t page_type)167*4882a593Smuzhiyun struct arm_smccc_res sip_smc_request_share_mem(u32 page_num,
168*4882a593Smuzhiyun 					       share_page_type_t page_type)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	struct arm_smccc_res res;
171*4882a593Smuzhiyun 	unsigned long share_mem_phy;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0);
174*4882a593Smuzhiyun 	if (IS_SIP_ERROR(res.a0))
175*4882a593Smuzhiyun 		goto error;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	share_mem_phy = res.a1;
178*4882a593Smuzhiyun 	res.a1 = (unsigned long)sip_map(share_mem_phy, SIZE_PAGE(page_num));
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun error:
181*4882a593Smuzhiyun 	return res;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_request_share_mem);
184*4882a593Smuzhiyun 
sip_smc_mcu_el3fiq(u32 arg0,u32 arg1,u32 arg2)185*4882a593Smuzhiyun struct arm_smccc_res sip_smc_mcu_el3fiq(u32 arg0, u32 arg1, u32 arg2)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	return __invoke_sip_fn_smc(SIP_MCU_EL3FIQ_CFG, arg0, arg1, arg2);
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_mcu_el3fiq);
190*4882a593Smuzhiyun 
sip_smc_vpu_reset(u32 arg0,u32 arg1,u32 arg2)191*4882a593Smuzhiyun struct arm_smccc_res sip_smc_vpu_reset(u32 arg0, u32 arg1, u32 arg2)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	struct arm_smccc_res res;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(PSCI_SIP_VPU_RESET, arg0, arg1, arg2);
196*4882a593Smuzhiyun 	return res;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_vpu_reset);
199*4882a593Smuzhiyun 
sip_smc_bus_config(u32 arg0,u32 arg1,u32 arg2)200*4882a593Smuzhiyun struct arm_smccc_res sip_smc_bus_config(u32 arg0, u32 arg1, u32 arg2)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	struct arm_smccc_res res;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_BUS_CFG, arg0, arg1, arg2);
205*4882a593Smuzhiyun 	return res;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_bus_config);
208*4882a593Smuzhiyun 
sip_smc_get_dram_map(void)209*4882a593Smuzhiyun struct dram_addrmap_info *sip_smc_get_dram_map(void)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	struct arm_smccc_res res;
212*4882a593Smuzhiyun 	static struct dram_addrmap_info *map;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	if (map)
215*4882a593Smuzhiyun 		return map;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	/* Request share memory size 4KB */
218*4882a593Smuzhiyun 	res = sip_smc_request_share_mem(1, SHARE_PAGE_TYPE_DDR_ADDRMAP);
219*4882a593Smuzhiyun 	if (res.a0 != 0) {
220*4882a593Smuzhiyun 		pr_err("no ATF memory for init\n");
221*4882a593Smuzhiyun 		return NULL;
222*4882a593Smuzhiyun 	}
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	map = (struct dram_addrmap_info *)res.a1;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	res = sip_smc_dram(SHARE_PAGE_TYPE_DDR_ADDRMAP, 0,
227*4882a593Smuzhiyun 			   ROCKCHIP_SIP_CONFIG_DRAM_ADDRMAP_GET);
228*4882a593Smuzhiyun 	if (res.a0) {
229*4882a593Smuzhiyun 		pr_err("rockchip_sip_config_dram_init error:%lx\n", res.a0);
230*4882a593Smuzhiyun 		map = NULL;
231*4882a593Smuzhiyun 		return NULL;
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	return map;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_get_dram_map);
237*4882a593Smuzhiyun 
sip_smc_lastlog_request(void)238*4882a593Smuzhiyun struct arm_smccc_res sip_smc_lastlog_request(void)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	struct arm_smccc_res res;
241*4882a593Smuzhiyun 	void __iomem *addr1, *addr2;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_LAST_LOG, local_clock(), 0, 0);
244*4882a593Smuzhiyun 	if (IS_SIP_ERROR(res.a0))
245*4882a593Smuzhiyun 		return res;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	addr1 = sip_map(res.a1, res.a3);
248*4882a593Smuzhiyun 	if (!addr1) {
249*4882a593Smuzhiyun 		pr_err("%s: share memory buffer0 ioremap failed\n", __func__);
250*4882a593Smuzhiyun 		res.a0 = SIP_RET_INVALID_ADDRESS;
251*4882a593Smuzhiyun 		return res;
252*4882a593Smuzhiyun 	}
253*4882a593Smuzhiyun 	addr2 = sip_map(res.a2, res.a3);
254*4882a593Smuzhiyun 	if (!addr2) {
255*4882a593Smuzhiyun 		pr_err("%s: share memory buffer1 ioremap failed\n", __func__);
256*4882a593Smuzhiyun 		res.a0 = SIP_RET_INVALID_ADDRESS;
257*4882a593Smuzhiyun 		return res;
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	res.a1 = (unsigned long)addr1;
261*4882a593Smuzhiyun 	res.a2 = (unsigned long)addr2;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	return res;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_lastlog_request);
266*4882a593Smuzhiyun 
sip_smc_amp_config(u32 sub_func_id,u32 arg1,u32 arg2,u32 arg3)267*4882a593Smuzhiyun int sip_smc_amp_config(u32 sub_func_id, u32 arg1, u32 arg2, u32 arg3)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun 	struct arm_smccc_res res;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	arm_smccc_smc(RK_SIP_AMP_CFG, sub_func_id, arg1, arg2, arg3,
272*4882a593Smuzhiyun 		      0, 0, 0, &res);
273*4882a593Smuzhiyun 	return res.a0;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_amp_config);
276*4882a593Smuzhiyun 
sip_smc_get_amp_info(u32 sub_func_id,u32 arg1)277*4882a593Smuzhiyun struct arm_smccc_res sip_smc_get_amp_info(u32 sub_func_id, u32 arg1)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	struct arm_smccc_res res;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	arm_smccc_smc(RK_SIP_AMP_CFG, sub_func_id, arg1, 0, 0, 0, 0, 0, &res);
282*4882a593Smuzhiyun 	return res;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_get_amp_info);
285*4882a593Smuzhiyun 
sip_hdcp_request_share_memory(int id)286*4882a593Smuzhiyun void __iomem *sip_hdcp_request_share_memory(int id)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	static void __iomem *base;
289*4882a593Smuzhiyun 	struct arm_smccc_res res;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	if (id < 0 || id >= MAX_DEVICE) {
292*4882a593Smuzhiyun 		pr_err("%s: invalid device id\n", __func__);
293*4882a593Smuzhiyun 		return NULL;
294*4882a593Smuzhiyun 	}
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	if (!base) {
297*4882a593Smuzhiyun 		/* request page share memory */
298*4882a593Smuzhiyun 		res = sip_smc_request_share_mem(2, SHARE_PAGE_TYPE_HDCP);
299*4882a593Smuzhiyun 		if (IS_SIP_ERROR(res.a0))
300*4882a593Smuzhiyun 			return NULL;
301*4882a593Smuzhiyun 		base = (void __iomem *)res.a1;
302*4882a593Smuzhiyun 	}
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return base + id * 1024;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_hdcp_request_share_memory);
307*4882a593Smuzhiyun 
sip_hdcp_config(u32 arg0,u32 arg1,u32 arg2)308*4882a593Smuzhiyun struct arm_smccc_res sip_hdcp_config(u32 arg0, u32 arg1, u32 arg2)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	struct arm_smccc_res res;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_HDCP_CONFIG, arg0, arg1, arg2);
313*4882a593Smuzhiyun 	return res;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_hdcp_config);
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun /************************** fiq debugger **************************************/
318*4882a593Smuzhiyun /*
319*4882a593Smuzhiyun  * AArch32 is not allowed to call SMC64(ATF framework does not support), so we
320*4882a593Smuzhiyun  * don't change SIP_UARTDBG_FN to SIP_UARTDBG_CFG64 even when cpu is AArch32
321*4882a593Smuzhiyun  * mode. Let ATF support SIP_UARTDBG_CFG, and we just initialize SIP_UARTDBG_FN
322*4882a593Smuzhiyun  * depends on compile option(CONFIG_ARM or CONFIG_ARM64).
323*4882a593Smuzhiyun  */
324*4882a593Smuzhiyun #ifdef CONFIG_ARM64
325*4882a593Smuzhiyun #define SIP_UARTDBG_FN		SIP_UARTDBG_CFG64
326*4882a593Smuzhiyun #else
327*4882a593Smuzhiyun #define SIP_UARTDBG_FN		SIP_UARTDBG_CFG
328*4882a593Smuzhiyun static int firmware_64_32bit;
329*4882a593Smuzhiyun #endif
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun static int fiq_sip_enabled;
332*4882a593Smuzhiyun static int fiq_target_cpu;
333*4882a593Smuzhiyun static phys_addr_t ft_fiq_mem_phy;
334*4882a593Smuzhiyun static void __iomem *ft_fiq_mem_base;
335*4882a593Smuzhiyun static sip_fiq_debugger_uart_irq_tf_cb_t sip_fiq_debugger_uart_irq_tf;
336*4882a593Smuzhiyun static struct pt_regs fiq_pt_regs;
337*4882a593Smuzhiyun 
sip_fiq_debugger_is_enabled(void)338*4882a593Smuzhiyun int sip_fiq_debugger_is_enabled(void)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	return fiq_sip_enabled;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_debugger_is_enabled);
343*4882a593Smuzhiyun 
sip_fiq_debugger_get_pt_regs(void * reg_base,unsigned long sp_el1)344*4882a593Smuzhiyun static void sip_fiq_debugger_get_pt_regs(void *reg_base,
345*4882a593Smuzhiyun 					 unsigned long sp_el1)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun 	__maybe_unused struct sm_nsec_ctx *nsec_ctx = reg_base;
348*4882a593Smuzhiyun 	__maybe_unused struct gp_regs_ctx *gp_regs = reg_base;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun #ifdef CONFIG_ARM64
351*4882a593Smuzhiyun 	/*
352*4882a593Smuzhiyun 	 * 64-bit ATF + 64-bit kernel
353*4882a593Smuzhiyun 	 */
354*4882a593Smuzhiyun 	/* copy cpu context: x0 ~ spsr_el3 */
355*4882a593Smuzhiyun 	memcpy(&fiq_pt_regs, reg_base, 8 * 31);
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	/* copy pstate: spsr_el3 */
358*4882a593Smuzhiyun 	memcpy(&fiq_pt_regs.pstate, reg_base + 0x110, 8);
359*4882a593Smuzhiyun 	fiq_pt_regs.sp = sp_el1;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	/* copy pc: elr_el3 */
362*4882a593Smuzhiyun 	memcpy(&fiq_pt_regs.pc, reg_base + 0x118, 8);
363*4882a593Smuzhiyun #else
364*4882a593Smuzhiyun 	if (firmware_64_32bit == FIRMWARE_ATF_64BIT) {
365*4882a593Smuzhiyun 		/*
366*4882a593Smuzhiyun 		 * 64-bit ATF + 32-bit kernel
367*4882a593Smuzhiyun 		 */
368*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r0 = gp_regs->x0;
369*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r1 = gp_regs->x1;
370*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r2 = gp_regs->x2;
371*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r3 = gp_regs->x3;
372*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r4 = gp_regs->x4;
373*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r5 = gp_regs->x5;
374*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r6 = gp_regs->x6;
375*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r7 = gp_regs->x7;
376*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r8 = gp_regs->x8;
377*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r9 = gp_regs->x9;
378*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r10 = gp_regs->x10;
379*4882a593Smuzhiyun 		fiq_pt_regs.ARM_fp = gp_regs->x11;
380*4882a593Smuzhiyun 		fiq_pt_regs.ARM_ip = gp_regs->x12;
381*4882a593Smuzhiyun 		fiq_pt_regs.ARM_sp = gp_regs->x19;	/* aarch32 svc_r13 */
382*4882a593Smuzhiyun 		fiq_pt_regs.ARM_lr = gp_regs->x18;	/* aarch32 svc_r14 */
383*4882a593Smuzhiyun 		fiq_pt_regs.ARM_cpsr = gp_regs->spsr_el3;
384*4882a593Smuzhiyun 		fiq_pt_regs.ARM_pc = gp_regs->elr_el3;
385*4882a593Smuzhiyun 	} else {
386*4882a593Smuzhiyun 		/*
387*4882a593Smuzhiyun 		 * 32-bit tee firmware + 32-bit kernel
388*4882a593Smuzhiyun 		 */
389*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r0 = nsec_ctx->r0;
390*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r1 = nsec_ctx->r1;
391*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r2 = nsec_ctx->r2;
392*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r3 = nsec_ctx->r3;
393*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r4 = nsec_ctx->r4;
394*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r5 = nsec_ctx->r5;
395*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r6 = nsec_ctx->r6;
396*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r7 = nsec_ctx->r7;
397*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r8 = nsec_ctx->r8;
398*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r9 = nsec_ctx->r9;
399*4882a593Smuzhiyun 		fiq_pt_regs.ARM_r10 = nsec_ctx->r10;
400*4882a593Smuzhiyun 		fiq_pt_regs.ARM_fp = nsec_ctx->r11;
401*4882a593Smuzhiyun 		fiq_pt_regs.ARM_ip = nsec_ctx->r12;
402*4882a593Smuzhiyun 		fiq_pt_regs.ARM_sp = nsec_ctx->svc_sp;
403*4882a593Smuzhiyun 		fiq_pt_regs.ARM_lr = nsec_ctx->svc_lr;
404*4882a593Smuzhiyun 		fiq_pt_regs.ARM_cpsr = nsec_ctx->mon_spsr;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 		/*
407*4882a593Smuzhiyun 		 * 'nsec_ctx->mon_lr' is not the fiq break point's PC, because it will
408*4882a593Smuzhiyun 		 * be override as 'psci_fiq_debugger_uart_irq_tf_cb' for optee-os to
409*4882a593Smuzhiyun 		 * jump to fiq_debugger handler.
410*4882a593Smuzhiyun 		 *
411*4882a593Smuzhiyun 		 * As 'nsec_ctx->und_lr' is not used for kernel, so optee-os uses it to
412*4882a593Smuzhiyun 		 * deliver fiq break point's PC.
413*4882a593Smuzhiyun 		 *
414*4882a593Smuzhiyun 		 */
415*4882a593Smuzhiyun 		fiq_pt_regs.ARM_pc = nsec_ctx->und_lr;
416*4882a593Smuzhiyun 	}
417*4882a593Smuzhiyun #endif
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun 
sip_fiq_debugger_uart_irq_tf_cb(unsigned long sp_el1,unsigned long offset,unsigned long cpu)420*4882a593Smuzhiyun static void sip_fiq_debugger_uart_irq_tf_cb(unsigned long sp_el1,
421*4882a593Smuzhiyun 					    unsigned long offset,
422*4882a593Smuzhiyun 					    unsigned long cpu)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun 	char *cpu_context;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	/* calling fiq handler */
427*4882a593Smuzhiyun 	if (ft_fiq_mem_base) {
428*4882a593Smuzhiyun 		cpu_context = (char *)ft_fiq_mem_base + offset;
429*4882a593Smuzhiyun 		sip_fiq_debugger_get_pt_regs(cpu_context, sp_el1);
430*4882a593Smuzhiyun 		sip_fiq_debugger_uart_irq_tf(&fiq_pt_regs, cpu);
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	/* fiq handler done, return to EL3(then EL3 return to EL1 entry) */
434*4882a593Smuzhiyun 	__invoke_sip_fn_smc(SIP_UARTDBG_FN, 0, 0, UARTDBG_CFG_OSHDL_TO_OS);
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun 
sip_fiq_debugger_uart_irq_tf_init(u32 irq_id,sip_fiq_debugger_uart_irq_tf_cb_t callback_fn)437*4882a593Smuzhiyun int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id, sip_fiq_debugger_uart_irq_tf_cb_t callback_fn)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun 	struct arm_smccc_res res;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	fiq_target_cpu = 0;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	/* init fiq debugger callback */
444*4882a593Smuzhiyun 	sip_fiq_debugger_uart_irq_tf = callback_fn;
445*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, irq_id,
446*4882a593Smuzhiyun 				  (unsigned long)sip_fiq_debugger_uart_irq_tf_cb,
447*4882a593Smuzhiyun 				  UARTDBG_CFG_INIT);
448*4882a593Smuzhiyun 	if (IS_SIP_ERROR(res.a0)) {
449*4882a593Smuzhiyun 		pr_err("%s error: %d\n", __func__, (int)res.a0);
450*4882a593Smuzhiyun 		return res.a0;
451*4882a593Smuzhiyun 	}
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	/* share memory ioremap */
454*4882a593Smuzhiyun 	if (!ft_fiq_mem_base) {
455*4882a593Smuzhiyun 		ft_fiq_mem_phy = res.a1;
456*4882a593Smuzhiyun 		ft_fiq_mem_base = sip_map(ft_fiq_mem_phy,
457*4882a593Smuzhiyun 					  FIQ_UARTDBG_SHARE_MEM_SIZE);
458*4882a593Smuzhiyun 		if (!ft_fiq_mem_base) {
459*4882a593Smuzhiyun 			pr_err("%s: share memory ioremap failed\n", __func__);
460*4882a593Smuzhiyun 			return -ENOMEM;
461*4882a593Smuzhiyun 		}
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	fiq_sip_enabled = 1;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	return SIP_RET_SUCCESS;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_debugger_uart_irq_tf_init);
469*4882a593Smuzhiyun 
cpu_logical_map_mpidr(u32 cpu)470*4882a593Smuzhiyun static ulong cpu_logical_map_mpidr(u32 cpu)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun #ifdef MODULE
473*4882a593Smuzhiyun 	/* Empirically, local "cpu_logical_map()" for rockchip platforms */
474*4882a593Smuzhiyun 	ulong mpidr = read_cpuid_mpidr();
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	if (mpidr & MPIDR_MT_BITMASK) {
477*4882a593Smuzhiyun 		/* 0x100, 0x200, 0x300, 0x400 ... */
478*4882a593Smuzhiyun 		mpidr = (cpu & 0xff) << 8;
479*4882a593Smuzhiyun 	} else {
480*4882a593Smuzhiyun 		if (cpu < 4)
481*4882a593Smuzhiyun 			/* 0x00, 0x01, 0x02, 0x03 */
482*4882a593Smuzhiyun 			mpidr = cpu;
483*4882a593Smuzhiyun 		else if (cpu < 8)
484*4882a593Smuzhiyun 			/* 0x100, 0x101, 0x102, 0x103 */
485*4882a593Smuzhiyun 			mpidr = 0x100 | (cpu - 4);
486*4882a593Smuzhiyun 		else
487*4882a593Smuzhiyun 			pr_err("Unsupported map cpu: %d\n", cpu);
488*4882a593Smuzhiyun 	}
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	return mpidr;
491*4882a593Smuzhiyun #else
492*4882a593Smuzhiyun 	return cpu_logical_map(cpu);
493*4882a593Smuzhiyun #endif
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun 
sip_cpu_logical_map_mpidr(u32 cpu)496*4882a593Smuzhiyun ulong sip_cpu_logical_map_mpidr(u32 cpu)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun 	return cpu_logical_map_mpidr(cpu);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_cpu_logical_map_mpidr);
501*4882a593Smuzhiyun 
sip_fiq_debugger_switch_cpu(u32 cpu)502*4882a593Smuzhiyun int sip_fiq_debugger_switch_cpu(u32 cpu)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	struct arm_smccc_res res;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	fiq_target_cpu = cpu;
507*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, cpu_logical_map_mpidr(cpu),
508*4882a593Smuzhiyun 				  0, UARTDBG_CFG_OSHDL_CPUSW);
509*4882a593Smuzhiyun 	return res.a0;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun 
sip_fiq_debugger_sdei_switch_cpu(u32 cur_cpu,u32 target_cpu,u32 flag)512*4882a593Smuzhiyun int sip_fiq_debugger_sdei_switch_cpu(u32 cur_cpu, u32 target_cpu, u32 flag)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	struct arm_smccc_res res;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SDEI_FIQ_DBG_SWITCH_CPU,
517*4882a593Smuzhiyun 				  cur_cpu, target_cpu, flag);
518*4882a593Smuzhiyun 	return res.a0;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun 
sip_fiq_debugger_sdei_get_event_id(u32 * fiq,u32 * sw_cpu,u32 * flag)521*4882a593Smuzhiyun int sip_fiq_debugger_sdei_get_event_id(u32 *fiq, u32 *sw_cpu, u32 *flag)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun 	struct arm_smccc_res res;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SDEI_FIQ_DBG_GET_EVENT_ID,
526*4882a593Smuzhiyun 				  0, 0, 0);
527*4882a593Smuzhiyun 	*fiq = res.a1;
528*4882a593Smuzhiyun 	*sw_cpu = res.a2;
529*4882a593Smuzhiyun 	if (flag)
530*4882a593Smuzhiyun 		*flag = res.a3;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	return res.a0;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_debugger_switch_cpu);
536*4882a593Smuzhiyun 
sip_fiq_debugger_enable_debug(bool enable)537*4882a593Smuzhiyun void sip_fiq_debugger_enable_debug(bool enable)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	unsigned long val;
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	val = enable ? UARTDBG_CFG_OSHDL_DEBUG_ENABLE :
542*4882a593Smuzhiyun 		       UARTDBG_CFG_OSHDL_DEBUG_DISABLE;
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	__invoke_sip_fn_smc(SIP_UARTDBG_FN, 0, 0, val);
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_debugger_enable_debug);
547*4882a593Smuzhiyun 
sip_fiq_debugger_set_print_port(u32 port_phyaddr,u32 baudrate)548*4882a593Smuzhiyun int sip_fiq_debugger_set_print_port(u32 port_phyaddr, u32 baudrate)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun 	struct arm_smccc_res res;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, port_phyaddr, baudrate,
553*4882a593Smuzhiyun 				  UARTDBG_CFG_PRINT_PORT);
554*4882a593Smuzhiyun 	return res.a0;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_debugger_set_print_port);
557*4882a593Smuzhiyun 
sip_fiq_debugger_request_share_memory(void)558*4882a593Smuzhiyun int sip_fiq_debugger_request_share_memory(void)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	struct arm_smccc_res res;
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	/* request page share memory */
563*4882a593Smuzhiyun 	res = sip_smc_request_share_mem(FIQ_UARTDBG_PAGE_NUMS,
564*4882a593Smuzhiyun 					SHARE_PAGE_TYPE_UARTDBG);
565*4882a593Smuzhiyun 	if (IS_SIP_ERROR(res.a0))
566*4882a593Smuzhiyun 		return res.a0;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	return SIP_RET_SUCCESS;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_debugger_request_share_memory);
571*4882a593Smuzhiyun 
sip_fiq_debugger_get_target_cpu(void)572*4882a593Smuzhiyun int sip_fiq_debugger_get_target_cpu(void)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun 	return fiq_target_cpu;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_debugger_get_target_cpu);
577*4882a593Smuzhiyun 
sip_fiq_debugger_enable_fiq(bool enable,uint32_t tgt_cpu)578*4882a593Smuzhiyun void sip_fiq_debugger_enable_fiq(bool enable, uint32_t tgt_cpu)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun 	u32 en;
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	fiq_target_cpu = tgt_cpu;
583*4882a593Smuzhiyun 	en = enable ? UARTDBG_CFG_FIQ_ENABEL : UARTDBG_CFG_FIQ_DISABEL;
584*4882a593Smuzhiyun 	__invoke_sip_fn_smc(SIP_UARTDBG_FN, tgt_cpu, 0, en);
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_debugger_enable_fiq);
587*4882a593Smuzhiyun 
sip_fiq_control(u32 sub_func,u32 irq,unsigned long data)588*4882a593Smuzhiyun int sip_fiq_control(u32 sub_func, u32 irq, unsigned long data)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun 	struct arm_smccc_res res;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(RK_SIP_FIQ_CTRL,
593*4882a593Smuzhiyun 				  sub_func, irq, data);
594*4882a593Smuzhiyun 	return res.a0;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_fiq_control);
597*4882a593Smuzhiyun 
sip_wdt_config(u32 sub_func,u32 arg1,u32 arg2,u32 arg3)598*4882a593Smuzhiyun int sip_wdt_config(u32 sub_func, u32 arg1, u32 arg2, u32 arg3)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun 	struct arm_smccc_res res;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	arm_smccc_smc(SIP_WDT_CFG, sub_func, arg1, arg2, arg3,
603*4882a593Smuzhiyun 		      0, 0, 0, &res);
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	return res.a0;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_wdt_config);
608*4882a593Smuzhiyun 
sip_hdmirx_config(u32 sub_func,u32 arg1,u32 arg2,u32 arg3)609*4882a593Smuzhiyun int sip_hdmirx_config(u32 sub_func, u32 arg1, u32 arg2, u32 arg3)
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun 	struct arm_smccc_res res;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	arm_smccc_smc(SIP_HDMIRX_CFG, sub_func, arg1, arg2, arg3,
614*4882a593Smuzhiyun 		      0, 0, 0, &res);
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 	return res.a0;
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_hdmirx_config);
619*4882a593Smuzhiyun 
sip_hdcpkey_init(u32 hdcp_id)620*4882a593Smuzhiyun int sip_hdcpkey_init(u32 hdcp_id)
621*4882a593Smuzhiyun {
622*4882a593Smuzhiyun 	struct arm_smccc_res res;
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(TRUSTED_OS_HDCPKEY_INIT, hdcp_id, 0, 0);
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	return res.a0;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_hdcpkey_init);
629*4882a593Smuzhiyun 
sip_smc_mcu_config(unsigned long mcu_id,unsigned long func,unsigned long arg2)630*4882a593Smuzhiyun int sip_smc_mcu_config(unsigned long mcu_id,
631*4882a593Smuzhiyun 		       unsigned long func,
632*4882a593Smuzhiyun 		       unsigned long arg2)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun 	struct arm_smccc_res res;
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_MCU_CFG, mcu_id, func, arg2);
637*4882a593Smuzhiyun 	return res.a0;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sip_smc_mcu_config);
640*4882a593Smuzhiyun /******************************************************************************/
641*4882a593Smuzhiyun #ifdef CONFIG_ARM
sip_firmware_init(void)642*4882a593Smuzhiyun static __init int sip_firmware_init(void)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun 	struct arm_smccc_res res;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	if (!psci_smp_available())
647*4882a593Smuzhiyun 		return 0;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	/*
650*4882a593Smuzhiyun 	 * OP-TEE works on kernel 3.10 and 4.4 and we have different sip
651*4882a593Smuzhiyun 	 * implement. We should tell OP-TEE the current rockchip sip version.
652*4882a593Smuzhiyun 	 */
653*4882a593Smuzhiyun 	res = __invoke_sip_fn_smc(SIP_SIP_VERSION, SIP_IMPLEMENT_V2,
654*4882a593Smuzhiyun 				  SECURE_REG_WR, 0);
655*4882a593Smuzhiyun 	if (IS_SIP_ERROR(res.a0))
656*4882a593Smuzhiyun 		pr_err("%s: set rockchip sip version v2 failed\n", __func__);
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	/*
659*4882a593Smuzhiyun 	 * Currently, we support:
660*4882a593Smuzhiyun 	 *
661*4882a593Smuzhiyun 	 *	1. 64-bit ATF + 64-bit kernel;
662*4882a593Smuzhiyun 	 *	2. 64-bit ATF + 32-bit kernel;
663*4882a593Smuzhiyun 	 *	3. 32-bit TEE + 32-bit kernel;
664*4882a593Smuzhiyun 	 *
665*4882a593Smuzhiyun 	 * We need to detect which case of above and record in firmware_64_32bit
666*4882a593Smuzhiyun 	 * We get info from cpuid and compare with all supported ARMv7 cpu.
667*4882a593Smuzhiyun 	 */
668*4882a593Smuzhiyun 	switch (read_cpuid_part()) {
669*4882a593Smuzhiyun 	case ARM_CPU_PART_CORTEX_A7:
670*4882a593Smuzhiyun 	case ARM_CPU_PART_CORTEX_A8:
671*4882a593Smuzhiyun 	case ARM_CPU_PART_CORTEX_A9:
672*4882a593Smuzhiyun 	case ARM_CPU_PART_CORTEX_A12:
673*4882a593Smuzhiyun 	case ARM_CPU_PART_CORTEX_A15:
674*4882a593Smuzhiyun 	case ARM_CPU_PART_CORTEX_A17:
675*4882a593Smuzhiyun 		firmware_64_32bit = FIRMWARE_TEE_32BIT;
676*4882a593Smuzhiyun 		break;
677*4882a593Smuzhiyun 	default:
678*4882a593Smuzhiyun 		firmware_64_32bit = FIRMWARE_ATF_64BIT;
679*4882a593Smuzhiyun 		break;
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	return 0;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun arch_initcall(sip_firmware_init);
685*4882a593Smuzhiyun #endif
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip SIP Call");
688*4882a593Smuzhiyun MODULE_LICENSE("GPL");
689