aboutsummaryrefslogtreecommitdiff
path: root/plat/renesas/rcar/aarch64/plat_helpers.S
blob: 61dd62287181466984290e135e528a181d27748d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
/*
 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
 * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
#include <common/runtime_svc.h>
#include <cortex_a57.h>
#include <platform_def.h>

#include "rcar_def.h"

	.globl	plat_get_my_entrypoint
	.extern	plat_set_my_stack
	.globl	platform_mem_init

	.globl	plat_crash_console_init
	.globl	plat_crash_console_putc
	.globl	plat_crash_console_flush
	.globl	plat_invalidate_icache
	.globl	plat_report_exception
	.globl	plat_secondary_reset
	.globl	plat_reset_handler
	.globl	plat_my_core_pos
	.extern	rcar_log_init

	.extern console_rcar_init
	.extern console_rcar_putc
	.extern console_rcar_flush

#if IMAGE_BL2
	#define	INT_ID_MASK	(0x3ff)
	.extern bl2_interrupt_error_type
	.extern bl2_interrupt_error_id
	.globl  bl2_enter_bl31
	.extern gicv2_acknowledge_interrupt
	.extern rcar_swdt_exec
#endif

	/* -----------------------------------------------------
	 * void platform_get_core_pos (mpidr)
	 * -----------------------------------------------------
	 */
func platform_get_core_pos
	and     x1, x0, #MPIDR_CPU_MASK
	and     x0, x0, #MPIDR_CLUSTER_MASK
	add     x0, x1, x0, LSR #6
	ret
endfunc platform_get_core_pos

	/* -----------------------------------------------------
	 * void platform_my_core_pos
	 * -----------------------------------------------------
	 */
func plat_my_core_pos
	mrs     x0, mpidr_el1
	b	platform_get_core_pos
endfunc plat_my_core_pos

	/* -----------------------------------------------------
	 * void platform_get_my_entrypoint (unsigned int mpid);
	 *
	 * Main job of this routine is to distinguish between
	 * a cold and warm boot.
	 * On a cold boot the secondaries first wait for the
	 * platform to be initialized after which they are
	 * hotplugged in. The primary proceeds to perform the
	 * platform initialization.
	 * On a warm boot, each cpu jumps to the address in its
	 * mailbox.
	 *
	 * TODO: Not a good idea to save lr in a temp reg
	 * -----------------------------------------------------
	 */
func plat_get_my_entrypoint
	mrs	x0, mpidr_el1
	mov	x9, x30 /* lr */

#if defined(IMAGE_BL2)
	/* always cold boot on bl2 */
	mov	x0, #0
	ret	x9
#else
       ldr 	x1, =BOOT_KIND_BASE
       ldr	x21, [x1]

	/* Check the reset info */
	and	x1, x21, #0x000c
	cmp	x1, #0x0008
	beq	el3_panic
	cmp	x1, #0x000c
	beq	el3_panic

	/* Check the boot kind */
	and	x1, x21, #0x0003
	cmp	x1, #0x0002
	beq	el3_panic
	cmp	x1, #0x0003
	beq	el3_panic

	/* warm boot or cold boot */
	and	x1, x21, #1
	cmp	x1, #0
	bne	warm_reset

	/* Cold boot */
	mov	x0, #0
	b	exit

warm_reset:
	/* --------------------------------------------------------------------
	 * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out
	 * of the caches after every update using normal memory so its safe to
	 * read it here with SO attributes
	 * ---------------------------------------------------------------------
	 */
	ldr	x10, =MBOX_BASE
	bl	platform_get_core_pos
	lsl	x0, x0, #CACHE_WRITEBACK_SHIFT
	ldr	x0, [x10, x0]
	cbz	x0, _panic
exit:
	ret	x9
_panic:
	b	do_panic
#endif

endfunc plat_get_my_entrypoint

	/* ---------------------------------------------
	 * plat_secondary_reset
	 *
	 * ---------------------------------------------
	 */
func plat_secondary_reset
	mrs	x0, sctlr_el3
	bic	x0, x0, #SCTLR_EE_BIT
	msr	sctlr_el3, x0
	isb

	mrs	x0, cptr_el3
	bic	w0, w0, #TCPAC_BIT
	bic	w0, w0, #TTA_BIT
	bic	w0, w0, #TFP_BIT
	msr	cptr_el3, x0

	mov_imm	x0, PARAMS_BASE
	mov_imm	x2, BL31_BASE
       ldr x3, =BOOT_KIND_BASE
	mov x1, #0x1
	str x1, [x3]
	br	x2	/* jump to BL31 */
	nop
	nop
	nop
endfunc plat_secondary_reset

	/* ---------------------------------------------
	 * plat_enter_bl31
	 *
	 * ---------------------------------------------
	 */
func bl2_enter_bl31
	mov	x20, x0
        /*
         * MMU needs to be disabled because both BL2 and BL31 execute
         * in EL3, and therefore share the same address space.
         * BL31 will initialize the address space according to its
         * own requirement.
         */
#if RCAR_BL2_DCACHE == 1
	/* Disable mmu and data cache */
	bl	disable_mmu_el3
	/* Data cache clean and invalidate */
	mov	x0, #DCCISW
	bl	dcsw_op_all
	/* TLB invalidate all, EL3 */
	tlbi	alle3
#endif /* RCAR_BL2_DCACHE == 1 */
	bl	disable_mmu_icache_el3
	/* Invalidate instruction cache */
	ic	iallu
	dsb	sy
	isb
	ldp	x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
	msr	elr_el3, x0
	msr	spsr_el3, x1
	eret
endfunc bl2_enter_bl31

	/* -----------------------------------------------------
	 * void platform_mem_init (void);
	 *
	 * Zero out the mailbox registers in the shared memory
	 * and set the rcar_boot_kind_flag.
	 * The mmu is turned off right now and only the primary can
	 * ever execute this code. Secondaries will read the
	 * mailboxes using SO accesses.
	 * -----------------------------------------------------
	 */
func platform_mem_init
#if !IMAGE_BL2
	ldr	x0, =MBOX_BASE
	mov	w1, #PLATFORM_CORE_COUNT
loop:
	str	xzr, [x0], #CACHE_WRITEBACK_GRANULE
	subs	w1, w1, #1
	b.gt	loop
#endif
	ret
endfunc platform_mem_init

	/* ---------------------------------------------
	 * void plat_report_exception(unsigned int type)
	 * Function to report an unhandled exception
	 * with platform-specific means.
	 * ---------------------------------------------
	 */
func plat_report_exception
	/* Switch to SP_EL0 */
	msr	spsel, #0
#if IMAGE_BL2
	mov	w1, #FIQ_SP_EL0
	cmp	w0, w1
	beq	rep_exec_fiq_elx
	b	rep_exec_panic_type
rep_exec_fiq_elx:
	bl	gicv2_acknowledge_interrupt
	mov	x2, #INT_ID_MASK
	and	x0, x0, x2
	mov	x1, #ARM_IRQ_SEC_WDT
	cmp	x0, x1
	bne	rep_exec_panic_id
	mrs	x0, ELR_EL3
	b	rcar_swdt_exec
rep_exec_panic_type:
	/* x0 is interrupt TYPE */
	b	bl2_interrupt_error_type
rep_exec_panic_id:
	/* x0 is interrupt ID */
	b	bl2_interrupt_error_id
rep_exec_end:
#endif
	ret
endfunc plat_report_exception

	/* ---------------------------------------------
	 * int plat_crash_console_init(void)
	 * Function to initialize log area
	 * ---------------------------------------------
	 */
func plat_crash_console_init
#if IMAGE_BL2
	mov	x0, #0
#else
	mov	x1, sp
	mov_imm	x2, RCAR_CRASH_STACK
	mov	sp, x2
	str	x1, [sp, #-16]!
	str	x30, [sp, #-16]!
	bl	console_rcar_init
	ldr	x30, [sp], #16
	ldr	x1, [sp], #16
	mov	sp, x1
#endif
	ret
endfunc plat_crash_console_init

	/* ---------------------------------------------
	 * int plat_crash_console_putc(int c)
	 * Function to store a character to log area
	 * ---------------------------------------------
	 */
func plat_crash_console_putc
	mov	x1, sp
	mov_imm	x2, RCAR_CRASH_STACK
	mov	sp, x2
	str	x1, [sp, #-16]!
	str	x30, [sp, #-16]!
	str	x3, [sp, #-16]!
	str	x4, [sp, #-16]!
	str	x5, [sp, #-16]!
	bl	console_rcar_putc
	ldr	x5, [sp], #16
	ldr	x4, [sp], #16
	ldr	x3, [sp], #16
	ldr	x30, [sp], #16
	ldr	x1, [sp], #16
	mov	sp, x1
	ret
endfunc plat_crash_console_putc

	/* ---------------------------------------------
	 * int plat_crash_console_flush()
	 * ---------------------------------------------
	 */
func plat_crash_console_flush
	b	console_rcar_flush
endfunc plat_crash_console_flush

	/* --------------------------------------------------------------------
	 * void plat_reset_handler(void);
	 *
	 * Before adding code in this function, refer to the guidelines in
	 * docs/firmware-design.md to determine whether the code should reside
	 * within the FIRST_RESET_HANDLER_CALL block or not.
	 *
	 * For R-Car H3:
	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
	 * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57
	 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
	 * For R-Car M3/M3N:
	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
	 * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57
	 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
	 *
	 * --------------------------------------------------------------------
	 */
func plat_reset_handler
	/*
	 * On R-Car H3    :  x2 := 0
	 * On R-Car M3/M3N:  x2 := 1
	 */
	/* read PRR */
	ldr	x0, =0xFFF00044
	ldr	w0, [x0]
	ubfx	w0, w0, 8, 8
	/* H3? */
	cmp	w0, #0x4F
	b.eq	RCARH3
	/* set R-Car M3/M3N */
	mov	x2, #1
	b	CHK_A5x
RCARH3:
	/* set R-Car H3 */
	mov	x2, #0
	/* --------------------------------------------------------------------
	 * Determine whether this code is executed on a Cortex-A53 or on a
	 * Cortex-A57 core.
	 * --------------------------------------------------------------------
	 */
CHK_A5x:
	mrs	x0, midr_el1
	ubfx	x1, x0, MIDR_PN_SHIFT, #12
	cmp     w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
	b.eq	A57
	ret
A57:
	/* Get data from CORTEX_A57_L2CTLR_EL1	*/
	mrs	x0, CORTEX_A57_L2CTLR_EL1
	/*
	 * On R-Car H3/M3/M3N
	 *
	 * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1
	 * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1
	 * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1
	 */
	/* clear bit of L2 RAM	*/
	/* ~(0x1e7) -> x1	*/
	mov	x1, #0x1e7
	neg	x1, x1
	/* clear bit of L2 RAM -> x0 */
	and	x0, x0, x1
	/* L2 Tag RAM latency (3 cycles) */
	orr	x0, x0, #0x2 << 6
	/* If M3/M3N then L2 RAM setup is 0 */
	cbnz	x2, M3_L2
	/* L2 Data RAM setup (1 cycle) */
	orr	x0, x0, #0x1 << 5
M3_L2:
	/* L2 Data RAM latency (4 cycles) */
	orr	x0, x0, #0x3
	/* Store data to L2CTLR_EL1 */
	msr	CORTEX_A57_L2CTLR_EL1, x0
apply_l2_ram_latencies:
	ret
endfunc plat_reset_handler

	/* ---------------------------------------------
	 * void plat_invalidate_icache(void)
	 * Instruction Cache Invalidate All to PoU
	 * ---------------------------------------------
	 */
func plat_invalidate_icache
	ic	iallu

	ret
endfunc plat_invalidate_icache