xref: /rk3399_ARM-atf/plat/renesas/common/aarch64/plat_helpers.S (revision c3e5f6b9854ad12e2b6d768f0058c7629f86aceb)
1/*
2 * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
3 * Copyright (c) 2015-2025, 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_rcar_init
32	.extern console_rcar_putc
33	.extern console_rcar_flush
34
35#if IMAGE_BL2
36	#define	INT_ID_MASK	(0x3ff)
37	.extern bl2_interrupt_error_type
38	.extern bl2_interrupt_error_id
39	.globl  bl2_enter_bl31
40	.extern gicv2_acknowledge_interrupt
41	.extern rcar_swdt_exec
42#endif
43
44	/* -----------------------------------------------------
45	 * void platform_get_core_pos (mpidr)
46	 * -----------------------------------------------------
47	 */
48func platform_get_core_pos
49	and     x1, x0, #MPIDR_CPU_MASK
50	and     x0, x0, #MPIDR_CLUSTER_MASK
51	add     x0, x1, x0, LSR #6
52	ret
53endfunc platform_get_core_pos
54
55	/* -----------------------------------------------------
56	 * void platform_my_core_pos
57	 * -----------------------------------------------------
58	 */
59func plat_my_core_pos
60	mrs     x0, mpidr_el1
61	b	platform_get_core_pos
62endfunc plat_my_core_pos
63
64	/* -----------------------------------------------------
65	 * void platform_get_my_entrypoint (unsigned int mpid);
66	 *
67	 * Main job of this routine is to distinguish between
68	 * a cold and warm boot.
69	 * On a cold boot the secondaries first wait for the
70	 * platform to be initialized after which they are
71	 * hotplugged in. The primary proceeds to perform the
72	 * platform initialization.
73	 * On a warm boot, each cpu jumps to the address in its
74	 * mailbox.
75	 *
76	 * TODO: Not a good idea to save lr in a temp reg
77	 * -----------------------------------------------------
78	 */
79func plat_get_my_entrypoint
80	mrs	x0, mpidr_el1
81	mov	x9, x30 /* lr */
82
83#if defined(IMAGE_BL2)
84	/* always cold boot on bl2 */
85	mov	x0, #0
86	ret	x9
87#else
88       ldr 	x1, =BOOT_KIND_BASE
89       ldr	x21, [x1]
90
91	/* Check the reset info */
92	and	x1, x21, #0x000c
93	cmp	x1, #0x0008
94	beq	el3_panic
95	cmp	x1, #0x000c
96	beq	el3_panic
97
98	/* Check the boot kind */
99	and	x1, x21, #0x0003
100	cmp	x1, #0x0002
101	beq	el3_panic
102	cmp	x1, #0x0003
103	beq	el3_panic
104
105	/* warm boot or cold boot */
106	and	x1, x21, #1
107	cmp	x1, #0
108	bne	warm_reset
109
110	/* Cold boot */
111	mov	x0, #0
112	b	exit
113
114warm_reset:
115	/* --------------------------------------------------------------------
116	 * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out
117	 * of the caches after every update using normal memory so its safe to
118	 * read it here with SO attributes
119	 * ---------------------------------------------------------------------
120	 */
121	ldr	x10, =MBOX_BASE
122	bl	platform_get_core_pos
123	lsl	x0, x0, #CACHE_WRITEBACK_SHIFT
124	ldr	x0, [x10, x0]
125	cbz	x0, _panic
126exit:
127	ret	x9
128_panic:
129	b	el3_panic
130#endif
131
132endfunc plat_get_my_entrypoint
133
134	/* ---------------------------------------------
135	 * plat_secondary_reset
136	 *
137	 * ---------------------------------------------
138	 */
139func plat_secondary_reset
140	mrs	x0, sctlr_el3
141	bic	x0, x0, #SCTLR_EE_BIT
142	msr	sctlr_el3, x0
143	isb
144
145	mrs	x0, cptr_el3
146	bic	w0, w0, #TCPAC_BIT
147	bic	w0, w0, #TTA_BIT
148	bic	w0, w0, #TFP_BIT
149	msr	cptr_el3, x0
150
151	/* Clear TCR_EL1 on secondary cores */
152	msr	tcr_el1, xzr
153
154	mov_imm	x0, PARAMS_BASE
155	mov_imm	x2, BL31_BASE
156       ldr x3, =BOOT_KIND_BASE
157	mov x1, #0x1
158	str x1, [x3]
159	br	x2	/* jump to BL31 */
160	nop
161	nop
162	nop
163endfunc plat_secondary_reset
164
165	/* ---------------------------------------------
166	 * plat_enter_bl31
167	 *
168	 * ---------------------------------------------
169	 */
170func bl2_enter_bl31
171	mov	x20, x0
172        /*
173         * MMU needs to be disabled because both BL2 and BL31 execute
174         * in EL3, and therefore share the same address space.
175         * BL31 will initialize the address space according to its
176         * own requirement.
177         */
178	/* Disable mmu and data cache */
179	bl	disable_mmu_el3
180#if RCAR_BL2_DCACHE == 1
181	/* Data cache clean and invalidate */
182	mov	x0, #DCCISW
183	bl	dcsw_op_all
184#endif /* RCAR_BL2_DCACHE == 1 */
185	/* TLB invalidate all, EL3 */
186	tlbi	alle3
187
188	bl	disable_mmu_icache_el3
189	/* Invalidate instruction cache */
190	ic	iallu
191	dsb	sy
192	isb
193
194	/* Clear TCR_EL1 on primary core */
195	msr	tcr_el1, xzr
196
197	ldp	x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
198	msr	elr_el3, x0
199	msr	spsr_el3, x1
200	exception_return
201endfunc bl2_enter_bl31
202
203	/* -----------------------------------------------------
204	 * void platform_mem_init (void);
205	 *
206	 * Zero out the mailbox registers in the shared memory
207	 * and set the rcar_boot_kind_flag.
208	 * The mmu is turned off right now and only the primary can
209	 * ever execute this code. Secondaries will read the
210	 * mailboxes using SO accesses.
211	 * -----------------------------------------------------
212	 */
213func platform_mem_init
214#if !IMAGE_BL2
215	ldr	x0, =MBOX_BASE
216	mov	w1, #PLATFORM_CORE_COUNT
217loop:
218	str	xzr, [x0], #CACHE_WRITEBACK_GRANULE
219	subs	w1, w1, #1
220	b.gt	loop
221#endif
222	ret
223endfunc platform_mem_init
224
225	/* ---------------------------------------------
226	 * void plat_report_exception(unsigned int type)
227	 * Function to report an unhandled exception
228	 * with platform-specific means.
229	 * ---------------------------------------------
230	 */
231func plat_report_exception
232	/* Switch to SP_EL0 */
233	msr	spsel, #0
234#if IMAGE_BL2
235	mov	w1, #FIQ_SP_EL0
236	cmp	w0, w1
237	beq	rep_exec_fiq_elx
238	b	rep_exec_panic_type
239rep_exec_fiq_elx:
240	bl	gicv2_acknowledge_interrupt
241	mov	x2, #INT_ID_MASK
242	and	x0, x0, x2
243	mov	x1, #ARM_IRQ_SEC_WDT
244	cmp	x0, x1
245	bne	rep_exec_panic_id
246	mrs	x0, ELR_EL3
247	b	rcar_swdt_exec
248rep_exec_panic_type:
249	/* x0 is interrupt TYPE */
250	b	bl2_interrupt_error_type
251rep_exec_panic_id:
252	/* x0 is interrupt ID */
253	b	bl2_interrupt_error_id
254rep_exec_end:
255#endif
256	ret
257endfunc plat_report_exception
258
259	/* ---------------------------------------------
260	 * int plat_crash_console_init(void)
261	 * Function to initialize log area
262	 * ---------------------------------------------
263	 */
264func plat_crash_console_init
265#if IMAGE_BL2
266	mov	x0, #0
267#else
268	mov	x1, sp
269	mov_imm	x2, RCAR_CRASH_STACK
270	mov	sp, x2
271	str	x1, [sp, #-16]!
272	str	x30, [sp, #-16]!
273	bl	console_rcar_init
274	ldr	x30, [sp], #16
275	ldr	x1, [sp], #16
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_rcar_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	b	console_rcar_flush
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