1/*
2 * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
3 * Copyright (c) 2015-2019, 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	bl	console_rcar_putc
288	ldr	x5, [sp], #16
289	ldr	x4, [sp], #16
290	ldr	x3, [sp], #16
291	ldr	x30, [sp], #16
292	ldr	x1, [sp], #16
293	mov	sp, x1
294	ret
295endfunc plat_crash_console_putc
296
297	/* ---------------------------------------------
298	 * void plat_crash_console_flush()
299	 * ---------------------------------------------
300	 */
301func plat_crash_console_flush
302	b	console_rcar_flush
303endfunc plat_crash_console_flush
304
305	/* --------------------------------------------------------------------
306	 * void plat_reset_handler(void);
307	 *
308	 * Before adding code in this function, refer to the guidelines in
309	 * docs/firmware-design.md to determine whether the code should reside
310	 * within the FIRST_RESET_HANDLER_CALL block or not.
311	 *
312	 * For R-Car H3:
313	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
314	 * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57
315	 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
316	 * For R-Car M3/M3N:
317	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
318	 * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57
319	 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
320	 *
321	 * --------------------------------------------------------------------
322	 */
323func plat_reset_handler
324	/*
325	 * On R-Car H3    :  x2 := 0
326	 * On R-Car M3/M3N:  x2 := 1
327	 */
328	/* read PRR */
329	ldr	x0, =0xFFF00044
330	ldr	w0, [x0]
331	ubfx	w0, w0, 8, 8
332	/* H3? */
333	cmp	w0, #0x4F
334	b.eq	RCARH3
335	/* set R-Car M3/M3N */
336	mov	x2, #1
337	b	CHK_A5x
338RCARH3:
339	/* set R-Car H3 */
340	mov	x2, #0
341	/* --------------------------------------------------------------------
342	 * Determine whether this code is executed on a Cortex-A53 or on a
343	 * Cortex-A57 core.
344	 * --------------------------------------------------------------------
345	 */
346CHK_A5x:
347	mrs	x0, midr_el1
348	ubfx	x1, x0, MIDR_PN_SHIFT, #12
349	cmp     w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
350	b.eq	A57
351	ret
352A57:
353	/* Get data from CORTEX_A57_L2CTLR_EL1	*/
354	mrs	x0, CORTEX_A57_L2CTLR_EL1
355	/*
356	 * On R-Car H3/M3/M3N
357	 *
358	 * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1
359	 * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1
360	 * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1
361	 */
362	/* clear bit of L2 RAM	*/
363	/* ~(0x1e7) -> x1	*/
364	mov	x1, #0x1e7
365	neg	x1, x1
366	/* clear bit of L2 RAM -> x0 */
367	and	x0, x0, x1
368	/* L2 Tag RAM latency (3 cycles) */
369	orr	x0, x0, #0x2 << 6
370	/* If M3/M3N then L2 RAM setup is 0 */
371	cbnz	x2, M3_L2
372	/* L2 Data RAM setup (1 cycle) */
373	orr	x0, x0, #0x1 << 5
374M3_L2:
375	/* L2 Data RAM latency (4 cycles) */
376	orr	x0, x0, #0x3
377	/* Store data to L2CTLR_EL1 */
378	msr	CORTEX_A57_L2CTLR_EL1, x0
379apply_l2_ram_latencies:
380	ret
381endfunc plat_reset_handler
382
383	/* ---------------------------------------------
384	 * void plat_invalidate_icache(void)
385	 * Instruction Cache Invalidate All to PoU
386	 * ---------------------------------------------
387	 */
388func plat_invalidate_icache
389	ic	iallu
390
391	ret
392endfunc plat_invalidate_icache
393