1/*
2 * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
3 * Copyright (c) 2015-2021, 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	do_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	mov_imm	x0, PARAMS_BASE
152	mov_imm	x2, BL31_BASE
153       ldr x3, =BOOT_KIND_BASE
154	mov x1, #0x1
155	str x1, [x3]
156	br	x2	/* jump to BL31 */
157	nop
158	nop
159	nop
160endfunc plat_secondary_reset
161
162	/* ---------------------------------------------
163	 * plat_enter_bl31
164	 *
165	 * ---------------------------------------------
166	 */
167func bl2_enter_bl31
168	mov	x20, x0
169        /*
170         * MMU needs to be disabled because both BL2 and BL31 execute
171         * in EL3, and therefore share the same address space.
172         * BL31 will initialize the address space according to its
173         * own requirement.
174         */
175#if RCAR_BL2_DCACHE == 1
176	/* Disable mmu and data cache */
177	bl	disable_mmu_el3
178	/* Data cache clean and invalidate */
179	mov	x0, #DCCISW
180	bl	dcsw_op_all
181	/* TLB invalidate all, EL3 */
182	tlbi	alle3
183#endif /* RCAR_BL2_DCACHE == 1 */
184	bl	disable_mmu_icache_el3
185	/* Invalidate instruction cache */
186	ic	iallu
187	dsb	sy
188	isb
189	ldp	x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
190	msr	elr_el3, x0
191	msr	spsr_el3, x1
192	exception_return
193endfunc bl2_enter_bl31
194
195	/* -----------------------------------------------------
196	 * void platform_mem_init (void);
197	 *
198	 * Zero out the mailbox registers in the shared memory
199	 * and set the rcar_boot_kind_flag.
200	 * The mmu is turned off right now and only the primary can
201	 * ever execute this code. Secondaries will read the
202	 * mailboxes using SO accesses.
203	 * -----------------------------------------------------
204	 */
205func platform_mem_init
206#if !IMAGE_BL2
207	ldr	x0, =MBOX_BASE
208	mov	w1, #PLATFORM_CORE_COUNT
209loop:
210	str	xzr, [x0], #CACHE_WRITEBACK_GRANULE
211	subs	w1, w1, #1
212	b.gt	loop
213#endif
214	ret
215endfunc platform_mem_init
216
217	/* ---------------------------------------------
218	 * void plat_report_exception(unsigned int type)
219	 * Function to report an unhandled exception
220	 * with platform-specific means.
221	 * ---------------------------------------------
222	 */
223func plat_report_exception
224	/* Switch to SP_EL0 */
225	msr	spsel, #0
226#if IMAGE_BL2
227	mov	w1, #FIQ_SP_EL0
228	cmp	w0, w1
229	beq	rep_exec_fiq_elx
230	b	rep_exec_panic_type
231rep_exec_fiq_elx:
232	bl	gicv2_acknowledge_interrupt
233	mov	x2, #INT_ID_MASK
234	and	x0, x0, x2
235	mov	x1, #ARM_IRQ_SEC_WDT
236	cmp	x0, x1
237	bne	rep_exec_panic_id
238	mrs	x0, ELR_EL3
239	b	rcar_swdt_exec
240rep_exec_panic_type:
241	/* x0 is interrupt TYPE */
242	b	bl2_interrupt_error_type
243rep_exec_panic_id:
244	/* x0 is interrupt ID */
245	b	bl2_interrupt_error_id
246rep_exec_end:
247#endif
248	ret
249endfunc plat_report_exception
250
251	/* ---------------------------------------------
252	 * int plat_crash_console_init(void)
253	 * Function to initialize log area
254	 * ---------------------------------------------
255	 */
256func plat_crash_console_init
257#if IMAGE_BL2
258	mov	x0, #0
259#else
260	mov	x1, sp
261	mov_imm	x2, RCAR_CRASH_STACK
262	mov	sp, x2
263	str	x1, [sp, #-16]!
264	str	x30, [sp, #-16]!
265	bl	console_rcar_init
266	ldr	x30, [sp], #16
267	ldr	x1, [sp], #16
268	mov	sp, x1
269#endif
270	ret
271endfunc plat_crash_console_init
272
273	/* ---------------------------------------------
274	 * int plat_crash_console_putc(int c)
275	 * Function to store a character to log area
276	 * ---------------------------------------------
277	 */
278func plat_crash_console_putc
279	mov	x1, sp
280	mov_imm	x2, RCAR_CRASH_STACK
281	mov	sp, x2
282	str	x1, [sp, #-16]!
283	str	x30, [sp, #-16]!
284	str	x3, [sp, #-16]!
285	str	x4, [sp, #-16]!
286	str	x5, [sp, #-16]!
287	str	x6, [sp, #-16]!
288	str	x7, [sp, #-16]!
289	bl	console_rcar_putc
290	ldr	x7, [sp], #16
291	ldr	x6, [sp], #16
292	ldr	x5, [sp], #16
293	ldr	x4, [sp], #16
294	ldr	x3, [sp], #16
295	ldr	x30, [sp], #16
296	ldr	x1, [sp], #16
297	mov	sp, x1
298	ret
299endfunc plat_crash_console_putc
300
301	/* ---------------------------------------------
302	 * void plat_crash_console_flush()
303	 * ---------------------------------------------
304	 */
305func plat_crash_console_flush
306	b	console_rcar_flush
307endfunc plat_crash_console_flush
308
309	/* --------------------------------------------------------------------
310	 * void plat_reset_handler(void);
311	 *
312	 * Before adding code in this function, refer to the guidelines in
313	 * docs/firmware-design.md to determine whether the code should reside
314	 * within the FIRST_RESET_HANDLER_CALL block or not.
315	 *
316	 * For R-Car H3:
317	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
318	 * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57
319	 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
320	 * For R-Car M3/M3N:
321	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
322	 * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57
323	 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
324	 *
325	 * --------------------------------------------------------------------
326	 */
327func plat_reset_handler
328	/*
329	 * On R-Car H3    :  x2 := 0
330	 * On R-Car M3/M3N:  x2 := 1
331	 */
332	/* read PRR */
333	ldr	x0, =0xFFF00044
334	ldr	w0, [x0]
335	ubfx	w0, w0, 8, 8
336	/* H3? */
337	cmp	w0, #0x4F
338	b.eq	RCARH3
339	/* set R-Car M3/M3N */
340	mov	x2, #1
341	b	CHK_A5x
342RCARH3:
343	/* set R-Car H3 */
344	mov	x2, #0
345	/* --------------------------------------------------------------------
346	 * Determine whether this code is executed on a Cortex-A53 or on a
347	 * Cortex-A57 core.
348	 * --------------------------------------------------------------------
349	 */
350CHK_A5x:
351	mrs	x0, midr_el1
352	ubfx	x1, x0, MIDR_PN_SHIFT, #12
353	cmp     w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
354	b.eq	A57
355	ret
356A57:
357	/* Get data from CORTEX_A57_L2CTLR_EL1	*/
358	mrs	x0, CORTEX_A57_L2CTLR_EL1
359	/*
360	 * On R-Car H3/M3/M3N
361	 *
362	 * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1
363	 * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1
364	 * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1
365	 */
366	/* clear bit of L2 RAM	*/
367	/* ~(0x1e7) -> x1	*/
368	mov	x1, #0x1e7
369	neg	x1, x1
370	/* clear bit of L2 RAM -> x0 */
371	and	x0, x0, x1
372	/* L2 Tag RAM latency (3 cycles) */
373	orr	x0, x0, #0x2 << 6
374	/* If M3/M3N then L2 RAM setup is 0 */
375	cbnz	x2, M3_L2
376	/* L2 Data RAM setup (1 cycle) */
377	orr	x0, x0, #0x1 << 5
378M3_L2:
379	/* L2 Data RAM latency (4 cycles) */
380	orr	x0, x0, #0x3
381	/* Store data to L2CTLR_EL1 */
382	msr	CORTEX_A57_L2CTLR_EL1, x0
383apply_l2_ram_latencies:
384	ret
385endfunc plat_reset_handler
386
387	/* ---------------------------------------------
388	 * void plat_invalidate_icache(void)
389	 * Instruction Cache Invalidate All to PoU
390	 * ---------------------------------------------
391	 */
392func plat_invalidate_icache
393	ic	iallu
394
395	ret
396endfunc plat_invalidate_icache
397