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