xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/aarch64/tegra_helpers.S (revision c3cf06f1a3a9b9ee8ac7a0ae505f95c45f7dca84)
1/*
2 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <arch.h>
7#include <asm_macros.S>
8#include <assert_macros.S>
9#include <cpu_macros.S>
10#include <cortex_a53.h>
11#include <cortex_a57.h>
12#include <platform_def.h>
13#include <tegra_def.h>
14
15#define MIDR_PN_CORTEX_A57		0xD07
16
17/*******************************************************************************
18 * Implementation defined ACTLR_EL3 bit definitions
19 ******************************************************************************/
20#define ACTLR_EL3_L2ACTLR_BIT		(1 << 6)
21#define ACTLR_EL3_L2ECTLR_BIT		(1 << 5)
22#define ACTLR_EL3_L2CTLR_BIT		(1 << 4)
23#define ACTLR_EL3_CPUECTLR_BIT		(1 << 1)
24#define ACTLR_EL3_CPUACTLR_BIT		(1 << 0)
25#define ACTLR_EL3_ENABLE_ALL_ACCESS	(ACTLR_EL3_L2ACTLR_BIT | \
26					 ACTLR_EL3_L2ECTLR_BIT | \
27					 ACTLR_EL3_L2CTLR_BIT | \
28					 ACTLR_EL3_CPUECTLR_BIT | \
29					 ACTLR_EL3_CPUACTLR_BIT)
30
31	/* Global functions */
32	.globl	plat_is_my_cpu_primary
33	.globl	plat_my_core_pos
34	.globl	plat_get_my_entrypoint
35	.globl	plat_secondary_cold_boot_setup
36	.globl	platform_mem_init
37	.globl	plat_crash_console_init
38	.globl	plat_crash_console_putc
39	.globl	plat_crash_console_flush
40	.globl	tegra_secure_entrypoint
41	.globl	plat_reset_handler
42
43	/* Global variables */
44	.globl	tegra_sec_entry_point
45	.globl	ns_image_entrypoint
46	.globl	tegra_bl31_phys_base
47	.globl	tegra_console_base
48	.globl	tegra_enable_l2_ecc_parity_prot
49
50	/* ---------------------
51	 * Common CPU init code
52	 * ---------------------
53	 */
54.macro	cpu_init_common
55
56	/* ------------------------------------------------
57	 * We enable procesor retention, L2/CPUECTLR NS
58	 * access and ECC/Parity protection for A57 CPUs
59	 * ------------------------------------------------
60	 */
61	mrs	x0, midr_el1
62	mov	x1, #(MIDR_PN_MASK << MIDR_PN_SHIFT)
63	and	x0, x0, x1
64	lsr	x0, x0, #MIDR_PN_SHIFT
65	cmp	x0, #MIDR_PN_CORTEX_A57
66	b.ne	1f
67
68	/* ---------------------------
69	 * Enable processor retention
70	 * ---------------------------
71	 */
72	mrs	x0, CORTEX_A57_L2ECTLR_EL1
73	mov	x1, #RETENTION_ENTRY_TICKS_512
74	bic	x0, x0, #CORTEX_A57_L2ECTLR_RET_CTRL_MASK
75	orr	x0, x0, x1
76	msr	CORTEX_A57_L2ECTLR_EL1, x0
77	isb
78
79	mrs	x0, CORTEX_A57_ECTLR_EL1
80	mov	x1, #RETENTION_ENTRY_TICKS_512
81	bic	x0, x0, #CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK
82	orr	x0, x0, x1
83	msr	CORTEX_A57_ECTLR_EL1, x0
84	isb
85
86	/* -------------------------------------------------------
87	 * Enable L2 and CPU ECTLR RW access from non-secure world
88	 * -------------------------------------------------------
89	 */
90	mov	x0, #ACTLR_EL3_ENABLE_ALL_ACCESS
91	msr	actlr_el3, x0
92	msr	actlr_el2, x0
93	isb
94
95	/* -------------------------------------------------------
96	 * Enable L2 ECC and Parity Protection
97	 * -------------------------------------------------------
98	 */
99	adr	x0, tegra_enable_l2_ecc_parity_prot
100	ldr	x0, [x0]
101	cbz	x0, 1f
102	mrs	x0, CORTEX_A57_L2CTLR_EL1
103	and	x1, x0, #CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT
104	cbnz	x1, 1f
105	orr	x0, x0, #CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT
106	msr	CORTEX_A57_L2CTLR_EL1, x0
107	isb
108
109	/* --------------------------------
110	 * Enable the cycle count register
111	 * --------------------------------
112	 */
1131:	mrs	x0, pmcr_el0
114	ubfx	x0, x0, #11, #5		// read PMCR.N field
115	mov	x1, #1
116	lsl	x0, x1, x0
117	sub	x0, x0, #1		// mask of event counters
118	orr	x0, x0, #0x80000000	// disable overflow intrs
119	msr	pmintenclr_el1, x0
120	msr	pmuserenr_el0, x1	// enable user mode access
121
122	/* ----------------------------------------------------------------
123	 * Allow non-privileged access to CNTVCT: Set CNTKCTL (Kernel Count
124	 * register), bit 1 (EL0VCTEN) to enable access to CNTVCT/CNTFRQ
125	 * registers from EL0.
126	 * ----------------------------------------------------------------
127	 */
128	mrs	x0, cntkctl_el1
129	orr	x0, x0, #EL0VCTEN_BIT
130	msr	cntkctl_el1, x0
131.endm
132
133	/* -----------------------------------------------------
134	 * unsigned int plat_is_my_cpu_primary(void);
135	 *
136	 * This function checks if this is the Primary CPU
137	 * -----------------------------------------------------
138	 */
139func plat_is_my_cpu_primary
140	mrs	x0, mpidr_el1
141	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
142	cmp	x0, #TEGRA_PRIMARY_CPU
143	cset	x0, eq
144	ret
145endfunc plat_is_my_cpu_primary
146
147	/* -----------------------------------------------------
148	 * unsigned int plat_my_core_pos(void);
149	 *
150	 * result: CorePos = CoreId + (ClusterId << 2)
151	 * -----------------------------------------------------
152	 */
153func plat_my_core_pos
154	mrs	x0, mpidr_el1
155	and	x1, x0, #MPIDR_CPU_MASK
156	and	x0, x0, #MPIDR_CLUSTER_MASK
157	add	x0, x1, x0, LSR #6
158	ret
159endfunc plat_my_core_pos
160
161	/* -----------------------------------------------------
162	 * unsigned long plat_get_my_entrypoint (void);
163	 *
164	 * Main job of this routine is to distinguish between
165	 * a cold and warm boot. If the tegra_sec_entry_point for
166	 * this CPU is present, then it's a warm boot.
167	 *
168	 * -----------------------------------------------------
169	 */
170func plat_get_my_entrypoint
171	adr	x1, tegra_sec_entry_point
172	ldr	x0, [x1]
173	ret
174endfunc plat_get_my_entrypoint
175
176	/* -----------------------------------------------------
177	 * int platform_get_core_pos(int mpidr);
178	 *
179	 * With this function: CorePos = (ClusterId * 4) +
180	 *                                CoreId
181	 * -----------------------------------------------------
182	 */
183func platform_get_core_pos
184	and	x1, x0, #MPIDR_CPU_MASK
185	and	x0, x0, #MPIDR_CLUSTER_MASK
186	add	x0, x1, x0, LSR #6
187	ret
188endfunc platform_get_core_pos
189
190	/* -----------------------------------------------------
191	 * void plat_secondary_cold_boot_setup (void);
192	 *
193	 * This function performs any platform specific actions
194	 * needed for a secondary cpu after a cold reset. Right
195	 * now this is a stub function.
196	 * -----------------------------------------------------
197	 */
198func plat_secondary_cold_boot_setup
199	mov	x0, #0
200	ret
201endfunc plat_secondary_cold_boot_setup
202
203	/* --------------------------------------------------------
204	 * void platform_mem_init (void);
205	 *
206	 * Any memory init, relocation to be done before the
207	 * platform boots. Called very early in the boot process.
208	 * --------------------------------------------------------
209	 */
210func platform_mem_init
211	mov	x0, #0
212	ret
213endfunc platform_mem_init
214
215	/* ---------------------------------------------
216	 * int plat_crash_console_init(void)
217	 * Function to initialize the crash console
218	 * without a C Runtime to print crash report.
219	 * Clobber list : x0 - x4
220	 * ---------------------------------------------
221	 */
222func plat_crash_console_init
223	mov	x0, #0
224	adr	x1, tegra_console_base
225	ldr	x1, [x1]
226	cbz	x1, 1f
227	mov	w0, #1
2281:	ret
229endfunc plat_crash_console_init
230
231	/* ---------------------------------------------
232	 * int plat_crash_console_putc(void)
233	 * Function to print a character on the crash
234	 * console without a C Runtime.
235	 * Clobber list : x1, x2
236	 * ---------------------------------------------
237	 */
238func plat_crash_console_putc
239	adr	x1, tegra_console_base
240	ldr	x1, [x1]
241	b	console_core_putc
242endfunc plat_crash_console_putc
243
244	/* ---------------------------------------------
245	 * int plat_crash_console_flush()
246	 * Function to force a write of all buffered
247	 * data that hasn't been output.
248	 * Out : return -1 on error else return 0.
249	 * Clobber list : x0, x1
250	 * ---------------------------------------------
251	 */
252func plat_crash_console_flush
253	adr	x0, tegra_console_base
254	ldr	x0, [x0]
255	b	console_core_flush
256endfunc plat_crash_console_flush
257
258	/* ---------------------------------------------------
259	 * Function to handle a platform reset and store
260	 * input parameters passed by BL2.
261	 * ---------------------------------------------------
262	 */
263func plat_reset_handler
264
265	/* ----------------------------------------------------
266	 * Verify if we are running from BL31_BASE address
267	 * ----------------------------------------------------
268	 */
269	adr	x18, bl31_entrypoint
270	mov	x17, #BL31_BASE
271	cmp	x18, x17
272	b.eq	1f
273
274	/* ----------------------------------------------------
275	 * Copy the entire BL31 code to BL31_BASE if we are not
276	 * running from it already
277	 * ----------------------------------------------------
278	 */
279	mov	x0, x17
280	mov	x1, x18
281	mov	x2, #BL31_SIZE
282_loop16:
283	cmp	x2, #16
284	b.lo	_loop1
285	ldp	x3, x4, [x1], #16
286	stp	x3, x4, [x0], #16
287	sub	x2, x2, #16
288	b	_loop16
289	/* copy byte per byte */
290_loop1:
291	cbz	x2, _end
292	ldrb	w3, [x1], #1
293	strb	w3, [x0], #1
294	subs	x2, x2, #1
295	b.ne	_loop1
296
297	/* ----------------------------------------------------
298	 * Jump to BL31_BASE and start execution again
299	 * ----------------------------------------------------
300	 */
301_end:	mov	x0, x20
302	mov	x1, x21
303	br	x17
3041:
305
306	/* -----------------------------------
307	 * derive and save the phys_base addr
308	 * -----------------------------------
309	 */
310	adr	x17, tegra_bl31_phys_base
311	ldr	x18, [x17]
312	cbnz	x18, 1f
313	adr	x18, bl31_entrypoint
314	str	x18, [x17]
315
3161:	cpu_init_common
317
318	ret
319endfunc plat_reset_handler
320
321	/* ----------------------------------------
322	 * Secure entrypoint function for CPU boot
323	 * ----------------------------------------
324	 */
325func tegra_secure_entrypoint _align=6
326
327#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT
328
329	/* -------------------------------------------------------
330	 * Invalidate BTB along with I$ to remove any stale
331	 * entries from the branch predictor array.
332	 * -------------------------------------------------------
333	 */
334	mrs	x0, CORTEX_A57_CPUACTLR_EL1
335	orr	x0, x0, #1
336	msr	CORTEX_A57_CPUACTLR_EL1, x0	/* invalidate BTB and I$ together */
337	dsb	sy
338	isb
339	ic	iallu			/* actual invalidate */
340	dsb	sy
341	isb
342
343	mrs	x0, CORTEX_A57_CPUACTLR_EL1
344	bic	x0, x0, #1
345	msr	CORTEX_A57_CPUACTLR_EL1, X0	/* restore original CPUACTLR_EL1 */
346	dsb	sy
347	isb
348
349	.rept	7
350	nop				/* wait */
351	.endr
352
353	/* -----------------------------------------------
354	 * Extract OSLK bit and check if it is '1'. This
355	 * bit remains '0' for A53 on warm-resets. If '1',
356	 * turn off regional clock gating and request warm
357	 * reset.
358	 * -----------------------------------------------
359	 */
360	mrs	x0, oslsr_el1
361	and	x0, x0, #2
362	mrs	x1, mpidr_el1
363	bics	xzr, x0, x1, lsr #7	/* 0 = slow cluster or warm reset */
364	b.eq	restore_oslock
365	mov	x0, xzr
366	msr	oslar_el1, x0		/* os lock stays 0 across warm reset */
367	mov	x3, #3
368	movz	x4, #0x8000, lsl #48
369	msr	CORTEX_A57_CPUACTLR_EL1, x4	/* turn off RCG */
370	isb
371	msr	rmr_el3, x3		/* request warm reset */
372	isb
373	dsb	sy
3741:	wfi
375	b	1b
376
377	/* --------------------------------------------------
378	 * These nops are here so that speculative execution
379	 * won't harm us before we are done with warm reset.
380	 * --------------------------------------------------
381	 */
382	.rept	65
383	nop
384	.endr
385
386	/* --------------------------------------------------
387	 * Do not insert instructions here
388	 * --------------------------------------------------
389	 */
390#endif
391
392	/* --------------------------------------------------
393	 * Restore OS Lock bit
394	 * --------------------------------------------------
395	 */
396restore_oslock:
397	mov	x0, #1
398	msr	oslar_el1, x0
399
400	cpu_init_common
401
402	/* ---------------------------------------------------------------------
403	 * The initial state of the Architectural feature trap register
404	 * (CPTR_EL3) is unknown and it must be set to a known state. All
405	 * feature traps are disabled. Some bits in this register are marked as
406	 * Reserved and should not be modified.
407	 *
408	 * CPTR_EL3.TCPAC: This causes a direct access to the CPACR_EL1 from EL1
409	 *  or the CPTR_EL2 from EL2 to trap to EL3 unless it is trapped at EL2.
410	 * CPTR_EL3.TTA: This causes access to the Trace functionality to trap
411	 *  to EL3 when executed from EL0, EL1, EL2, or EL3. If system register
412	 *  access to trace functionality is not supported, this bit is RES0.
413	 * CPTR_EL3.TFP: This causes instructions that access the registers
414	 *  associated with Floating Point and Advanced SIMD execution to trap
415	 *  to EL3 when executed from any exception level, unless trapped to EL1
416	 *  or EL2.
417	 * ---------------------------------------------------------------------
418	 */
419	mrs	x1, cptr_el3
420	bic	w1, w1, #TCPAC_BIT
421	bic	w1, w1, #TTA_BIT
422	bic	w1, w1, #TFP_BIT
423	msr	cptr_el3, x1
424
425	/* --------------------------------------------------
426	 * Get secure world's entry point and jump to it
427	 * --------------------------------------------------
428	 */
429	bl	plat_get_my_entrypoint
430	br	x0
431endfunc tegra_secure_entrypoint
432
433	.data
434	.align 3
435
436	/* --------------------------------------------------
437	 * CPU Secure entry point - resume from suspend
438	 * --------------------------------------------------
439	 */
440tegra_sec_entry_point:
441	.quad	0
442
443	/* --------------------------------------------------
444	 * NS world's cold boot entry point
445	 * --------------------------------------------------
446	 */
447ns_image_entrypoint:
448	.quad	0
449
450	/* --------------------------------------------------
451	 * BL31's physical base address
452	 * --------------------------------------------------
453	 */
454tegra_bl31_phys_base:
455	.quad	0
456
457	/* --------------------------------------------------
458	 * UART controller base for console init
459	 * --------------------------------------------------
460	 */
461tegra_console_base:
462	.quad	0
463
464	/* --------------------------------------------------
465	 * Enable L2 ECC and Parity Protection
466	 * --------------------------------------------------
467	 */
468tegra_enable_l2_ecc_parity_prot:
469	.quad	0
470