xref: /rk3399_ARM-atf/plat/renesas/common/aarch64/plat_helpers.S (revision 92d0eb0cb4054ec9179e2a45b8a1561ae134c8a8)
1/*
2 * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
3 * Copyright (c) 2015-2026, Renesas Electronics Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include <arch.h>
9#include <asm_macros.S>
10#include <common/bl_common.h>
11#include <common/runtime_svc.h>
12#include <cortex_a57.h>
13#include <platform_def.h>
14
15#include "rcar_def.h"
16
17	.globl	plat_get_my_entrypoint
18	.extern	plat_set_my_stack
19	.globl	platform_mem_init
20
21	.globl	plat_crash_console_init
22	.globl	plat_crash_console_putc
23	.globl	plat_crash_console_flush
24	.globl	plat_invalidate_icache
25	.globl	plat_report_exception
26	.globl	plat_secondary_reset
27	.globl	plat_reset_handler
28	.globl	plat_my_core_pos
29	.extern	rcar_log_init
30
31	.extern console_renesas_init
32	.extern console_renesas_putc
33
34#if IMAGE_BL2
35	#define	INT_ID_MASK	(0x3ff)
36	.extern bl2_interrupt_error_type
37	.extern bl2_interrupt_error_id
38	.globl  bl2_enter_bl31
39	.extern gicv2_acknowledge_interrupt
40	.extern rcar_swdt_exec
41#endif
42
43	/* -----------------------------------------------------
44	 * void platform_get_core_pos (mpidr)
45	 * -----------------------------------------------------
46	 */
47func platform_get_core_pos
48	and     x1, x0, #MPIDR_CPU_MASK
49	and     x0, x0, #MPIDR_CLUSTER_MASK
50	add     x0, x1, x0, LSR #6
51	ret
52endfunc platform_get_core_pos
53
54	/* -----------------------------------------------------
55	 * void platform_my_core_pos
56	 * -----------------------------------------------------
57	 */
58func plat_my_core_pos
59	mrs     x0, mpidr_el1
60	b	platform_get_core_pos
61endfunc plat_my_core_pos
62
63	/* -----------------------------------------------------
64	 * void platform_get_my_entrypoint (unsigned int mpid);
65	 *
66	 * Main job of this routine is to distinguish between
67	 * a cold and warm boot.
68	 * On a cold boot the secondaries first wait for the
69	 * platform to be initialized after which they are
70	 * hotplugged in. The primary proceeds to perform the
71	 * platform initialization.
72	 * On a warm boot, each cpu jumps to the address in its
73	 * mailbox.
74	 *
75	 * TODO: Not a good idea to save lr in a temp reg
76	 * -----------------------------------------------------
77	 */
78func plat_get_my_entrypoint
79	mrs	x0, mpidr_el1
80	mov	x9, x30 /* lr */
81
82#if defined(IMAGE_BL2)
83	/* always cold boot on bl2 */
84	mov	x0, #0
85	ret	x9
86#else
87       ldr 	x1, =BOOT_KIND_BASE
88       ldr	x21, [x1]
89
90	/* Check the reset info */
91	and	x1, x21, #0x000c
92	cmp	x1, #0x0008
93	beq	el3_panic
94	cmp	x1, #0x000c
95	beq	el3_panic
96
97	/* Check the boot kind */
98	and	x1, x21, #0x0003
99	cmp	x1, #0x0002
100	beq	el3_panic
101	cmp	x1, #0x0003
102	beq	el3_panic
103
104	/* warm boot or cold boot */
105	and	x1, x21, #1
106	cmp	x1, #0
107	bne	warm_reset
108
109	/* Cold boot */
110	mov	x0, #0
111	b	exit
112
113warm_reset:
114	/* --------------------------------------------------------------------
115	 * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out
116	 * of the caches after every update using normal memory so its safe to
117	 * read it here with SO attributes
118	 * ---------------------------------------------------------------------
119	 */
120	ldr	x10, =MBOX_BASE
121	bl	platform_get_core_pos
122	lsl	x0, x0, #CACHE_WRITEBACK_SHIFT
123	ldr	x0, [x10, x0]
124	cbz	x0, _panic
125exit:
126	ret	x9
127_panic:
128	b	el3_panic
129#endif
130
131endfunc plat_get_my_entrypoint
132
133	/* ---------------------------------------------
134	 * plat_secondary_reset
135	 *
136	 * ---------------------------------------------
137	 */
138func plat_secondary_reset
139	mrs	x0, sctlr_el3
140	bic	x0, x0, #SCTLR_EE_BIT
141	msr	sctlr_el3, x0
142	isb
143
144	mrs	x0, cptr_el3
145	bic	w0, w0, #TCPAC_BIT
146	bic	w0, w0, #TTA_BIT
147	bic	w0, w0, #TFP_BIT
148	msr	cptr_el3, x0
149
150	/* Clear TCR_EL1 on secondary cores */
151	msr	tcr_el1, xzr
152
153	mov_imm	x0, PARAMS_BASE
154	mov_imm	x2, BL31_BASE
155       ldr x3, =BOOT_KIND_BASE
156	mov x1, #0x1
157	str x1, [x3]
158	br	x2	/* jump to BL31 */
159	nop
160	nop
161	nop
162endfunc plat_secondary_reset
163
164	/* ---------------------------------------------
165	 * plat_enter_bl31
166	 *
167	 * ---------------------------------------------
168	 */
169func bl2_enter_bl31
170	mov	x20, x0
171        /*
172         * MMU needs to be disabled because both BL2 and BL31 execute
173         * in EL3, and therefore share the same address space.
174         * BL31 will initialize the address space according to its
175         * own requirement.
176         */
177	/* Disable mmu and data cache */
178	bl	disable_mmu_el3
179#if RCAR_BL2_DCACHE == 1
180	/* Data cache clean and invalidate */
181	mov	x0, #DCCISW
182	bl	dcsw_op_all
183#endif /* RCAR_BL2_DCACHE == 1 */
184	/* TLB invalidate all, EL3 */
185	tlbi	alle3
186
187	bl	disable_mmu_icache_el3
188	/* Invalidate instruction cache */
189	ic	iallu
190	dsb	sy
191	isb
192
193	/* Clear TCR_EL1 on primary core */
194	msr	tcr_el1, xzr
195
196	ldp	x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
197	msr	elr_el3, x0
198	msr	spsr_el3, x1
199	exception_return
200endfunc bl2_enter_bl31
201
202	/* -----------------------------------------------------
203	 * void platform_mem_init (void);
204	 *
205	 * Zero out the mailbox registers in the shared memory
206	 * and set the rcar_boot_kind_flag.
207	 * The mmu is turned off right now and only the primary can
208	 * ever execute this code. Secondaries will read the
209	 * mailboxes using SO accesses.
210	 * -----------------------------------------------------
211	 */
212func platform_mem_init
213#if !IMAGE_BL2
214	ldr	x0, =MBOX_BASE
215	mov	w1, #PLATFORM_CORE_COUNT
216loop:
217	str	xzr, [x0], #CACHE_WRITEBACK_GRANULE
218	subs	w1, w1, #1
219	b.gt	loop
220#endif
221	ret
222endfunc platform_mem_init
223
224	/* ---------------------------------------------
225	 * void plat_report_exception(unsigned int type)
226	 * Function to report an unhandled exception
227	 * with platform-specific means.
228	 * ---------------------------------------------
229	 */
230func plat_report_exception
231	/* Switch to SP_EL0 */
232	msr	spsel, #0
233#if IMAGE_BL2
234	mov	w1, #FIQ_SP_EL0
235	cmp	w0, w1
236	beq	rep_exec_fiq_elx
237	b	rep_exec_panic_type
238rep_exec_fiq_elx:
239	bl	gicv2_acknowledge_interrupt
240	mov	x2, #INT_ID_MASK
241	and	x0, x0, x2
242	mov	x1, #ARM_IRQ_SEC_WDT
243	cmp	x0, x1
244	bne	rep_exec_panic_id
245	mrs	x0, ELR_EL3
246	b	rcar_swdt_exec
247rep_exec_panic_type:
248	/* x0 is interrupt TYPE */
249	b	bl2_interrupt_error_type
250rep_exec_panic_id:
251	/* x0 is interrupt ID */
252	b	bl2_interrupt_error_id
253rep_exec_end:
254#endif
255	ret
256endfunc plat_report_exception
257
258	/* ---------------------------------------------
259	 * int plat_crash_console_init(void)
260	 * Function to initialize log area
261	 * ---------------------------------------------
262	 */
263func plat_crash_console_init
264#if IMAGE_BL2
265	mov	x0, #0
266#else
267	mov	x1, sp
268	mov_imm	x2, RCAR_CRASH_STACK
269	mov	sp, x2
270	str	x1, [sp, #-16]!
271	str	x30, [sp, #-16]!
272	bl	console_renesas_init
273	ldr	x30, [sp], #16
274	ldr	x1, [sp], #16
275	mov	x0, #1
276	mov	sp, x1
277#endif
278	ret
279endfunc plat_crash_console_init
280
281	/* ---------------------------------------------
282	 * int plat_crash_console_putc(int c)
283	 * Function to store a character to log area
284	 * ---------------------------------------------
285	 */
286func plat_crash_console_putc
287	mov	x1, sp
288	mov_imm	x2, RCAR_CRASH_STACK
289	mov	sp, x2
290	str	x1, [sp, #-16]!
291	str	x30, [sp, #-16]!
292	str	x3, [sp, #-16]!
293	str	x4, [sp, #-16]!
294	str	x5, [sp, #-16]!
295	str	x6, [sp, #-16]!
296	str	x7, [sp, #-16]!
297	bl	console_renesas_putc
298	ldr	x7, [sp], #16
299	ldr	x6, [sp], #16
300	ldr	x5, [sp], #16
301	ldr	x4, [sp], #16
302	ldr	x3, [sp], #16
303	ldr	x30, [sp], #16
304	ldr	x1, [sp], #16
305	mov	sp, x1
306	ret
307endfunc plat_crash_console_putc
308
309	/* ---------------------------------------------
310	 * void plat_crash_console_flush()
311	 * ---------------------------------------------
312	 */
313func plat_crash_console_flush
314	ret
315endfunc plat_crash_console_flush
316
317	/* --------------------------------------------------------------------
318	 * void plat_reset_handler(void);
319	 *
320	 * Before adding code in this function, refer to the guidelines in
321	 * docs/firmware-design.md to determine whether the code should reside
322	 * within the FIRST_RESET_HANDLER_CALL block or not.
323	 *
324	 * For R-Car H3:
325	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
326	 * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57
327	 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
328	 * For R-Car M3/M3N:
329	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
330	 * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57
331	 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
332	 *
333	 * --------------------------------------------------------------------
334	 */
335func plat_reset_handler
336	/*
337	 * On R-Car H3    :  x2 := 0
338	 * On R-Car M3/M3N:  x2 := 1
339	 */
340	/* read PRR */
341	ldr	x0, =0xFFF00044
342	ldr	w0, [x0]
343	ubfx	w0, w0, 8, 8
344	/* H3? */
345	cmp	w0, #0x4F
346	b.eq	RCARH3
347	/* set R-Car M3/M3N */
348	mov	x2, #1
349	b	CHK_A5x
350RCARH3:
351	/* set R-Car H3 */
352	mov	x2, #0
353	/* --------------------------------------------------------------------
354	 * Determine whether this code is executed on a Cortex-A53 or on a
355	 * Cortex-A57 core.
356	 * --------------------------------------------------------------------
357	 */
358CHK_A5x:
359	mrs	x0, midr_el1
360	ubfx	x1, x0, MIDR_PN_SHIFT, #12
361	cmp     w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
362	b.eq	A57
363	ret
364A57:
365	/* Get data from CORTEX_A57_L2CTLR_EL1	*/
366	mrs	x0, CORTEX_A57_L2CTLR_EL1
367	/*
368	 * On R-Car H3/M3/M3N
369	 *
370	 * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1
371	 * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1
372	 * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1
373	 */
374	/* clear bit of L2 RAM	*/
375	/* ~(0x1e7) -> x1	*/
376	mov	x1, #0x1e7
377	neg	x1, x1
378	/* clear bit of L2 RAM -> x0 */
379	and	x0, x0, x1
380	/* L2 Tag RAM latency (3 cycles) */
381	orr	x0, x0, #0x2 << 6
382	/* If M3/M3N then L2 RAM setup is 0 */
383	cbnz	x2, M3_L2
384	/* L2 Data RAM setup (1 cycle) */
385	orr	x0, x0, #0x1 << 5
386M3_L2:
387	/* L2 Data RAM latency (4 cycles) */
388	orr	x0, x0, #0x3
389	/* Store data to L2CTLR_EL1 */
390	msr	CORTEX_A57_L2CTLR_EL1, x0
391apply_l2_ram_latencies:
392	ret
393endfunc plat_reset_handler
394
395	/* ---------------------------------------------
396	 * void plat_invalidate_icache(void)
397	 * Instruction Cache Invalidate All to PoU
398	 * ---------------------------------------------
399	 */
400func plat_invalidate_icache
401	ic	iallu
402
403	ret
404endfunc plat_invalidate_icache
405