1/*
2 * Secure entry function for CPU Core #1
3 *
4 * (C) Copyright 2016
5 * Texas Instruments, <www.ti.com>
6 *
7 * Author :
8 *	Harinarayan Bhatta <harinarayan@ti.com>
9 *
10 * SPDX-License-Identifier:	GPL-2.0+
11 */
12
13#include <config.h>
14#include <asm/arch/omap.h>
15#include <asm/omap_common.h>
16#include <linux/linkage.h>
17
18.arch_extension sec
19
20#if !defined(CONFIG_SYS_DCACHE_OFF)
21.global flush_dcache_range
22#endif
23
24#define AUX_CORE_BOOT_0		0x48281800
25#define AUX_CORE_BOOT_1		0x48281804
26
27#ifdef CONFIG_DRA7XX
28/* DRA7xx ROM code function "startup_BootSlave". This function is where CPU1
29 * waits on WFE, polling on AUX_CORE_BOOT_x registers.
30 * This address is same for J6 and J6 Eco.
31 */
32#define ROM_FXN_STARTUP_BOOTSLAVE     0x00038a64
33#endif
34
35/* Assembly core where CPU1 is woken up into
36 * No need to save-restore registers, does not use stack.
37 */
38LENTRY(cpu1_entry)
39	ldr	r4, =omap_smc_sec_cpu1_args
40	ldm	r4, {r0,r1,r2,r3}	@ Retrieve args
41
42	mov	r6, #0xFF	@ Indicate new Task call
43	mov	r12, #0x00	@ Secure Service ID in R12
44
45	dsb
46	dmb
47	smc	0		@ SMC #0 to enter monitor mode
48
49	b	.Lend		@ exit at end of the service execution
50	nop
51
52	@ In case of IRQ happening in Secure, then ARM will branch here.
53	@ At that moment, IRQ will be pending and ARM will jump to Non Secure
54	@ IRQ handler
55	mov	r12, #0xFE
56
57	dsb
58	dmb
59	smc	0		@ SMC #0 to enter monitor mode
60
61.Lend:
62	ldr	r4, =omap_smc_sec_cpu1_args
63	str	r0, [r4, #0x10]		@ save return value
64	ldr	r4, =AUX_CORE_BOOT_0
65	mov	r5, #0x0
66	str	r5, [r4]
67	ldr	r4, =ROM_FXN_STARTUP_BOOTSLAVE
68	sev				@ Tell CPU0 we are done
69	bx	r4			@ Jump back to ROM
70END(cpu1_entry)
71
72/*
73 * u32 omap_smc_sec_cpu1(u32 service, u32 proc_id, u32 flag, u32 *params);
74 *
75 * Makes a secure ROM/PPA call on CPU Core #1 on supported platforms.
76 * Assumes that CPU #1 is waiting in ROM code and not yet woken up or used by
77 * u-boot.
78 */
79ENTRY(omap_smc_sec_cpu1)
80	push	{r4, r5, lr}
81	ldr	r4, =omap_smc_sec_cpu1_args
82	stm	r4, {r0,r1,r2,r3}	@ Save args to memory
83#if !defined(CONFIG_SYS_DCACHE_OFF)
84	mov	r0, r4
85	mov	r1, #CONFIG_SYS_CACHELINE_SIZE
86	add	r1, r0, r1		@ dcache is not enabled on CPU1, so
87	blx	flush_dcache_range	@ flush the cache on args buffer
88#endif
89	ldr	r4, =AUX_CORE_BOOT_1
90	ldr	r5, =cpu1_entry
91	str	r5, [r4]		@ Setup CPU1 entry function
92	ldr	r4, =AUX_CORE_BOOT_0
93	mov	r5, #0x10
94	str	r5, [r4]		@ Tell ROM to exit while loop
95	sev				@ Wake up CPU1
96.Lwait:
97	wfe				@ Wait for CPU1 to finish
98	nop
99	ldr	r5, [r4]		@ Check if CPU1 is done
100	cmp	r5, #0
101	bne	.Lwait
102
103	ldr	r4, =omap_smc_sec_cpu1_args
104	ldr	r0, [r4, #0x10]         @ Retrieve return value
105	pop	{r4, r5, pc}
106ENDPROC(omap_smc_sec_cpu1)
107
108/*
109 * Buffer to save function arguments and return value for omap_smc_sec_cpu1
110 */
111.section .data
112omap_smc_sec_cpu1_args:
113#if !defined(CONFIG_SYS_DCACHE_OFF)
114	.balign CONFIG_SYS_CACHELINE_SIZE
115	.rept  CONFIG_SYS_CACHELINE_SIZE/4
116	.word 0
117	.endr
118#else
119	.rept 5
120	.word 0
121	.endr
122#endif
123END(omap_smc_sec_cpu1_args)
124