tegra_helpers.S 12.3 KB
Newer Older
1
/*
2
 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3
 *
dp-arm's avatar
dp-arm committed
4
 * SPDX-License-Identifier: BSD-3-Clause
5
6
7
8
9
10
 */
#include <arch.h>
#include <asm_macros.S>
#include <assert_macros.S>
#include <cpu_macros.S>
#include <cortex_a53.h>
11
#include <cortex_a57.h>
12
#include <platform_def.h>
13
#include <tegra_def.h>
14
#include <tegra_platform.h>
15

16
17
18
19
20
#define MIDR_PN_CORTEX_A57		0xD07

/*******************************************************************************
 * Implementation defined ACTLR_EL3 bit definitions
 ******************************************************************************/
21
22
23
24
25
26
27
28
29
30
#define ACTLR_EL3_L2ACTLR_BIT		(U(1) << 6)
#define ACTLR_EL3_L2ECTLR_BIT		(U(1) << 5)
#define ACTLR_EL3_L2CTLR_BIT		(U(1) << 4)
#define ACTLR_EL3_CPUECTLR_BIT		(U(1) << 1)
#define ACTLR_EL3_CPUACTLR_BIT		(U(1) << 0)
#define ACTLR_EL3_ENABLE_ALL_MASK	(ACTLR_EL3_L2ACTLR_BIT | \
								ACTLR_EL3_L2ECTLR_BIT | \
					 			ACTLR_EL3_L2CTLR_BIT | \
					 			ACTLR_EL3_CPUECTLR_BIT | \
					 			ACTLR_EL3_CPUACTLR_BIT)
31
#define ACTLR_EL3_ENABLE_ALL_ACCESS	(ACTLR_EL3_L2ACTLR_BIT | \
32
33
34
35
					 			ACTLR_EL3_L2ECTLR_BIT | \
					 			ACTLR_EL3_L2CTLR_BIT | \
					 			ACTLR_EL3_CPUECTLR_BIT | \
					 			ACTLR_EL3_CPUACTLR_BIT)
36

37
	/* Global functions */
38
39
40
	.globl	plat_is_my_cpu_primary
	.globl	plat_my_core_pos
	.globl	plat_get_my_entrypoint
41
42
43
44
	.globl	plat_secondary_cold_boot_setup
	.globl	platform_mem_init
	.globl	plat_crash_console_init
	.globl	plat_crash_console_putc
45
	.globl	plat_crash_console_flush
46
47
48
49
	.globl	tegra_secure_entrypoint
	.globl	plat_reset_handler

	/* Global variables */
50
	.globl	tegra_sec_entry_point
51
52
	.globl	ns_image_entrypoint
	.globl	tegra_bl31_phys_base
53
	.globl	tegra_console_base
54
55
56
57
58
59
60

	/* ---------------------
	 * Common CPU init code
	 * ---------------------
	 */
.macro	cpu_init_common

61
	/* ------------------------------------------------
62
63
	 * We enable procesor retention, L2/CPUECTLR NS
	 * access and ECC/Parity protection for A57 CPUs
64
65
66
67
68
69
70
71
72
	 * ------------------------------------------------
	 */
	mrs	x0, midr_el1
	mov	x1, #(MIDR_PN_MASK << MIDR_PN_SHIFT)
	and	x0, x0, x1
	lsr	x0, x0, #MIDR_PN_SHIFT
	cmp	x0, #MIDR_PN_CORTEX_A57
	b.ne	1f

73
74
75
	/* ---------------------------
	 * Enable processor retention
	 * ---------------------------
76
	 */
77
78
79
	mrs	x0, CORTEX_A57_L2ECTLR_EL1
	mov	x1, #RETENTION_ENTRY_TICKS_512
	bic	x0, x0, #CORTEX_A57_L2ECTLR_RET_CTRL_MASK
80
	orr	x0, x0, x1
81
	msr	CORTEX_A57_L2ECTLR_EL1, x0
82
83
	isb

84
85
86
	mrs	x0, CORTEX_A57_ECTLR_EL1
	mov	x1, #RETENTION_ENTRY_TICKS_512
	bic	x0, x0, #CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK
87
	orr	x0, x0, x1
88
	msr	CORTEX_A57_ECTLR_EL1, x0
89
90
	isb

91
92
93
	/* -------------------------------------------------------
	 * Enable L2 and CPU ECTLR RW access from non-secure world
	 * -------------------------------------------------------
94
	 */
95
96
97
98
99
	mrs	x0, actlr_el3
	mov	x1, #ACTLR_EL3_ENABLE_ALL_MASK
	bic	x0, x0, x1
	mov	x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
	orr	x0, x0, x1
100
	msr	actlr_el3, x0
101
102
103
104
105
	mrs	x0, actlr_el2
	mov	x1, #ACTLR_EL3_ENABLE_ALL_MASK
	bic	x0, x0, x1
	mov	x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
	orr	x0, x0, x1
106
107
108
109
110
111
112
	msr	actlr_el2, x0
	isb

	/* --------------------------------
	 * Enable the cycle count register
	 * --------------------------------
	 */
113
1:	mrs	x0, pmcr_el0
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
	ubfx	x0, x0, #11, #5		// read PMCR.N field
	mov	x1, #1
	lsl	x0, x1, x0
	sub	x0, x0, #1		// mask of event counters
	orr	x0, x0, #0x80000000	// disable overflow intrs
	msr	pmintenclr_el1, x0
	msr	pmuserenr_el0, x1	// enable user mode access

	/* ----------------------------------------------------------------
	 * Allow non-privileged access to CNTVCT: Set CNTKCTL (Kernel Count
	 * register), bit 1 (EL0VCTEN) to enable access to CNTVCT/CNTFRQ
	 * registers from EL0.
	 * ----------------------------------------------------------------
	 */
	mrs	x0, cntkctl_el1
	orr	x0, x0, #EL0VCTEN_BIT
	msr	cntkctl_el1, x0
.endm

	/* -----------------------------------------------------
134
	 * unsigned int plat_is_my_cpu_primary(void);
135
136
137
138
	 *
	 * This function checks if this is the Primary CPU
	 * -----------------------------------------------------
	 */
139
140
func plat_is_my_cpu_primary
	mrs	x0, mpidr_el1
141
142
143
144
	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
	cmp	x0, #TEGRA_PRIMARY_CPU
	cset	x0, eq
	ret
145
endfunc plat_is_my_cpu_primary
146

147
	/* ----------------------------------------------------------
148
149
	 * unsigned int plat_my_core_pos(void);
	 *
150
151
	 * result: CorePos = CoreId + (ClusterId * cpus per cluster)
	 * ----------------------------------------------------------
152
153
154
155
156
	 */
func plat_my_core_pos
	mrs	x0, mpidr_el1
	and	x1, x0, #MPIDR_CPU_MASK
	and	x0, x0, #MPIDR_CLUSTER_MASK
157
158
159
160
	lsr	x0, x0, #MPIDR_AFFINITY_BITS
	mov	x2, #PLATFORM_MAX_CPUS_PER_CLUSTER
	mul	x0, x0, x2
	add	x0, x1, x0
161
162
163
164
165
166
167
168
169
	ret
endfunc plat_my_core_pos

	/* -----------------------------------------------------
	 * unsigned long plat_get_my_entrypoint (void);
	 *
	 * Main job of this routine is to distinguish between
	 * a cold and warm boot. If the tegra_sec_entry_point for
	 * this CPU is present, then it's a warm boot.
170
171
172
	 *
	 * -----------------------------------------------------
	 */
173
174
175
func plat_get_my_entrypoint
	adr	x1, tegra_sec_entry_point
	ldr	x0, [x1]
176
	ret
177
endfunc plat_get_my_entrypoint
178

179
180
181
	/* -----------------------------------------------------
	 * int platform_get_core_pos(int mpidr);
	 *
182
183
	 * result: CorePos = (ClusterId * cpus per cluster) +
	 *                   CoreId
184
185
186
187
188
	 * -----------------------------------------------------
	 */
func platform_get_core_pos
	and	x1, x0, #MPIDR_CPU_MASK
	and	x0, x0, #MPIDR_CLUSTER_MASK
189
190
191
192
	lsr	x0, x0, #MPIDR_AFFINITY_BITS
	mov	x2, #PLATFORM_MAX_CPUS_PER_CLUSTER
	mul	x0, x0, x2
	add	x0, x1, x0
193
194
195
	ret
endfunc platform_get_core_pos

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
	/* -----------------------------------------------------
	 * void plat_secondary_cold_boot_setup (void);
	 *
	 * This function performs any platform specific actions
	 * needed for a secondary cpu after a cold reset. Right
	 * now this is a stub function.
	 * -----------------------------------------------------
	 */
func plat_secondary_cold_boot_setup
	mov	x0, #0
	ret
endfunc plat_secondary_cold_boot_setup

	/* --------------------------------------------------------
	 * void platform_mem_init (void);
	 *
	 * Any memory init, relocation to be done before the
	 * platform boots. Called very early in the boot process.
	 * --------------------------------------------------------
	 */
func platform_mem_init
	mov	x0, #0
	ret
endfunc platform_mem_init

	/* ---------------------------------------------
	 * int plat_crash_console_init(void)
	 * Function to initialize the crash console
	 * without a C Runtime to print crash report.
225
	 * Clobber list : x0 - x4
226
227
228
	 * ---------------------------------------------
	 */
func plat_crash_console_init
229
230
231
232
233
234
	mov	x0, #0
	adr	x1, tegra_console_base
	ldr	x1, [x1]
	cbz	x1, 1f
	mov	w0, #1
1:	ret
235
236
237
238
239
240
241
242
243
244
endfunc plat_crash_console_init

	/* ---------------------------------------------
	 * int plat_crash_console_putc(void)
	 * Function to print a character on the crash
	 * console without a C Runtime.
	 * Clobber list : x1, x2
	 * ---------------------------------------------
	 */
func plat_crash_console_putc
245
246
	adr	x1, tegra_console_base
	ldr	x1, [x1]
247
248
249
	b	console_core_putc
endfunc plat_crash_console_putc

250
251
252
253
254
255
256
257
258
259
260
261
262
263
	/* ---------------------------------------------
	 * int plat_crash_console_flush()
	 * Function to force a write of all buffered
	 * data that hasn't been output.
	 * Out : return -1 on error else return 0.
	 * Clobber list : x0, x1
	 * ---------------------------------------------
	 */
func plat_crash_console_flush
	adr	x0, tegra_console_base
	ldr	x0, [x0]
	b	console_core_flush
endfunc plat_crash_console_flush

264
265
266
267
268
269
270
	/* ---------------------------------------------------
	 * Function to handle a platform reset and store
	 * input parameters passed by BL2.
	 * ---------------------------------------------------
	 */
func plat_reset_handler

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
	/* ----------------------------------------------------
	 * Verify if we are running from BL31_BASE address
	 * ----------------------------------------------------
	 */
	adr	x18, bl31_entrypoint
	mov	x17, #BL31_BASE
	cmp	x18, x17
	b.eq	1f

	/* ----------------------------------------------------
	 * Copy the entire BL31 code to BL31_BASE if we are not
	 * running from it already
	 * ----------------------------------------------------
	 */
	mov	x0, x17
	mov	x1, x18
	mov	x2, #BL31_SIZE
_loop16:
	cmp	x2, #16
290
	b.lo	_loop1
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
	ldp	x3, x4, [x1], #16
	stp	x3, x4, [x0], #16
	sub	x2, x2, #16
	b	_loop16
	/* copy byte per byte */
_loop1:
	cbz	x2, _end
	ldrb	w3, [x1], #1
	strb	w3, [x0], #1
	subs	x2, x2, #1
	b.ne	_loop1

	/* ----------------------------------------------------
	 * Jump to BL31_BASE and start execution again
	 * ----------------------------------------------------
	 */
_end:	mov	x0, x20
	mov	x1, x21
	br	x17
1:

312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
	/* -----------------------------------
	 * derive and save the phys_base addr
	 * -----------------------------------
	 */
	adr	x17, tegra_bl31_phys_base
	ldr	x18, [x17]
	cbnz	x18, 1f
	adr	x18, bl31_entrypoint
	str	x18, [x17]

1:	cpu_init_common

	ret
endfunc plat_reset_handler

	/* ----------------------------------------
	 * Secure entrypoint function for CPU boot
	 * ----------------------------------------
	 */
331
func tegra_secure_entrypoint _align=6
332
333
334

#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
	/* --------------------------------------------------------
	 * Skip the invalidate BTB workaround for Tegra210B01 SKUs.
	 * --------------------------------------------------------
	 */
	mov	x0, #TEGRA_MISC_BASE
	add	x0, x0, #HARDWARE_REVISION_OFFSET
	ldr	w1, [x0]
	lsr	w1, w1, #CHIP_ID_SHIFT
	and	w1, w1, #CHIP_ID_MASK
	cmp	w1, #TEGRA_CHIPID_TEGRA21	/* T210? */
	b.ne	2f
	ldr	w1, [x0]
	lsr	w1, w1, #MAJOR_VERSION_SHIFT
	and	w1, w1, #MAJOR_VERSION_MASK
	cmp	w1, #0x02			/* T210 B01? */
	b.eq	2f

352
353
354
355
356
	/* -------------------------------------------------------
	 * Invalidate BTB along with I$ to remove any stale
	 * entries from the branch predictor array.
	 * -------------------------------------------------------
	 */
357
	mrs	x0, CORTEX_A57_CPUACTLR_EL1
358
	orr	x0, x0, #1
359
	msr	CORTEX_A57_CPUACTLR_EL1, x0	/* invalidate BTB and I$ together */
360
361
362
363
364
365
	dsb	sy
	isb
	ic	iallu			/* actual invalidate */
	dsb	sy
	isb

366
	mrs	x0, CORTEX_A57_CPUACTLR_EL1
367
	bic	x0, x0, #1
368
	msr	CORTEX_A57_CPUACTLR_EL1, X0	/* restore original CPUACTLR_EL1 */
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
	dsb	sy
	isb

	.rept	7
	nop				/* wait */
	.endr

	/* -----------------------------------------------
	 * Extract OSLK bit and check if it is '1'. This
	 * bit remains '0' for A53 on warm-resets. If '1',
	 * turn off regional clock gating and request warm
	 * reset.
	 * -----------------------------------------------
	 */
	mrs	x0, oslsr_el1
	and	x0, x0, #2
	mrs	x1, mpidr_el1
	bics	xzr, x0, x1, lsr #7	/* 0 = slow cluster or warm reset */
	b.eq	restore_oslock
	mov	x0, xzr
	msr	oslar_el1, x0		/* os lock stays 0 across warm reset */
	mov	x3, #3
	movz	x4, #0x8000, lsl #48
392
	msr	CORTEX_A57_CPUACTLR_EL1, x4	/* turn off RCG */
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
	isb
	msr	rmr_el3, x3		/* request warm reset */
	isb
	dsb	sy
1:	wfi
	b	1b

	/* --------------------------------------------------
	 * These nops are here so that speculative execution
	 * won't harm us before we are done with warm reset.
	 * --------------------------------------------------
	 */
	.rept	65
	nop
	.endr
408
2:
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
	/* --------------------------------------------------
	 * Do not insert instructions here
	 * --------------------------------------------------
	 */
#endif

	/* --------------------------------------------------
	 * Restore OS Lock bit
	 * --------------------------------------------------
	 */
restore_oslock:
	mov	x0, #1
	msr	oslar_el1, x0

	/* --------------------------------------------------
	 * Get secure world's entry point and jump to it
	 * --------------------------------------------------
	 */
427
	bl	plat_get_my_entrypoint
428
429
430
431
432
433
434
	br	x0
endfunc tegra_secure_entrypoint

	.data
	.align 3

	/* --------------------------------------------------
435
	 * CPU Secure entry point - resume from suspend
436
437
	 * --------------------------------------------------
	 */
438
tegra_sec_entry_point:
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
	.quad	0

	/* --------------------------------------------------
	 * NS world's cold boot entry point
	 * --------------------------------------------------
	 */
ns_image_entrypoint:
	.quad	0

	/* --------------------------------------------------
	 * BL31's physical base address
	 * --------------------------------------------------
	 */
tegra_bl31_phys_base:
	.quad	0
454
455
456
457
458
459
460

	/* --------------------------------------------------
	 * UART controller base for console init
	 * --------------------------------------------------
	 */
tegra_console_base:
	.quad	0