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