xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/aarch64/tegra_helpers.S (revision d55b8f6a89591b8784026b5c818e3cacd8a01f90)
1/*
2 * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
3 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7#include <arch.h>
8#include <asm_macros.S>
9#include <assert_macros.S>
10#include <cpu_macros.S>
11#include <cortex_a53.h>
12#include <cortex_a57.h>
13#include <platform_def.h>
14#include <tegra_def.h>
15#include <tegra_platform.h>
16
17#define MIDR_PN_CORTEX_A57		0xD07
18
19/*******************************************************************************
20 * Implementation defined ACTLR_EL3 bit definitions
21 ******************************************************************************/
22#define ACTLR_ELx_L2ACTLR_BIT		(U(1) << 6)
23#define ACTLR_ELx_L2ECTLR_BIT		(U(1) << 5)
24#define ACTLR_ELx_L2CTLR_BIT		(U(1) << 4)
25#define ACTLR_ELx_CPUECTLR_BIT		(U(1) << 1)
26#define ACTLR_ELx_CPUACTLR_BIT		(U(1) << 0)
27#define ACTLR_ELx_ENABLE_ALL_ACCESS	(ACTLR_ELx_L2ACTLR_BIT | \
28					 ACTLR_ELx_L2ECTLR_BIT | \
29					 ACTLR_ELx_L2CTLR_BIT | \
30					 ACTLR_ELx_CPUECTLR_BIT | \
31					 ACTLR_ELx_CPUACTLR_BIT)
32
33	/* Global functions */
34	.globl	plat_is_my_cpu_primary
35	.globl	plat_my_core_pos
36	.globl	plat_get_my_entrypoint
37	.globl	plat_secondary_cold_boot_setup
38	.globl	platform_mem_init
39	.globl	plat_crash_console_init
40	.globl	plat_crash_console_putc
41	.globl	plat_crash_console_flush
42	.globl	tegra_secure_entrypoint
43	.globl	plat_reset_handler
44
45	/* Global variables */
46	.globl	tegra_sec_entry_point
47	.globl	ns_image_entrypoint
48	.globl	tegra_bl31_phys_base
49	.globl	tegra_console_base
50
51	/* ---------------------
52	 * Common CPU init code
53	 * ---------------------
54	 */
55.macro	cpu_init_common
56
57	/* ------------------------------------------------
58	 * We enable procesor retention, L2/CPUECTLR NS
59	 * access and ECC/Parity protection for A57 CPUs
60	 * ------------------------------------------------
61	 */
62	mrs	x0, midr_el1
63	mov	x1, #(MIDR_PN_MASK << MIDR_PN_SHIFT)
64	and	x0, x0, x1
65	lsr	x0, x0, #MIDR_PN_SHIFT
66	cmp	x0, #MIDR_PN_CORTEX_A57
67	b.ne	1f
68
69	/* ---------------------------
70	 * Enable processor retention
71	 * ---------------------------
72	 */
73	mrs	x0, CORTEX_A57_L2ECTLR_EL1
74	mov	x1, #RETENTION_ENTRY_TICKS_512
75	bic	x0, x0, #CORTEX_A57_L2ECTLR_RET_CTRL_MASK
76	orr	x0, x0, x1
77	msr	CORTEX_A57_L2ECTLR_EL1, x0
78	isb
79
80	mrs	x0, CORTEX_A57_ECTLR_EL1
81	mov	x1, #RETENTION_ENTRY_TICKS_512
82	bic	x0, x0, #CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK
83	orr	x0, x0, x1
84	msr	CORTEX_A57_ECTLR_EL1, x0
85	isb
86
87	/* -------------------------------------------------------
88	 * Enable L2 and CPU ECTLR RW access from non-secure world
89	 * -------------------------------------------------------
90	 */
91	mrs	x0, actlr_el3
92	mov	x1, #ACTLR_ELx_ENABLE_ALL_ACCESS
93	orr	x0, x0, x1
94	msr	actlr_el3, x0
95	mrs	x0, actlr_el2
96	mov	x1, #ACTLR_ELx_ENABLE_ALL_ACCESS
97	orr	x0, x0, x1
98	msr	actlr_el2, x0
99	isb
100
101	/* --------------------------------
102	 * Enable the cycle count register
103	 * --------------------------------
104	 */
1051:	mrs	x0, pmcr_el0
106	ubfx	x0, x0, #11, #5		// read PMCR.N field
107	mov	x1, #1
108	lsl	x0, x1, x0
109	sub	x0, x0, #1		// mask of event counters
110	orr	x0, x0, #0x80000000	// disable overflow intrs
111	msr	pmintenclr_el1, x0
112	msr	pmuserenr_el0, x1	// enable user mode access
113
114	/* ----------------------------------------------------------------
115	 * Allow non-privileged access to CNTVCT: Set CNTKCTL (Kernel Count
116	 * register), bit 1 (EL0VCTEN) to enable access to CNTVCT/CNTFRQ
117	 * registers from EL0.
118	 * ----------------------------------------------------------------
119	 */
120	mrs	x0, cntkctl_el1
121	orr	x0, x0, #EL0VCTEN_BIT
122	msr	cntkctl_el1, x0
123.endm
124
125	/* -----------------------------------------------------
126	 * unsigned int plat_is_my_cpu_primary(void);
127	 *
128	 * This function checks if this is the Primary CPU
129	 * -----------------------------------------------------
130	 */
131func plat_is_my_cpu_primary
132	mrs	x0, mpidr_el1
133	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
134	cmp	x0, #TEGRA_PRIMARY_CPU
135	cset	x0, eq
136	ret
137endfunc plat_is_my_cpu_primary
138
139	/* ----------------------------------------------------------
140	 * unsigned int plat_my_core_pos(void);
141	 *
142	 * result: CorePos = CoreId + (ClusterId * cpus per cluster)
143	 * Registers clobbered: x0, x8
144	 * ----------------------------------------------------------
145	 */
146func plat_my_core_pos
147	mov	x8, x30
148	mrs	x0, mpidr_el1
149	bl	plat_core_pos_by_mpidr
150	ret	x8
151endfunc plat_my_core_pos
152
153	/* -----------------------------------------------------
154	 * unsigned long plat_get_my_entrypoint (void);
155	 *
156	 * Main job of this routine is to distinguish between
157	 * a cold and warm boot. If the tegra_sec_entry_point for
158	 * this CPU is present, then it's a warm boot.
159	 *
160	 * -----------------------------------------------------
161	 */
162func plat_get_my_entrypoint
163	adr	x1, tegra_sec_entry_point
164	ldr	x0, [x1]
165	ret
166endfunc plat_get_my_entrypoint
167
168	/* -----------------------------------------------------
169	 * int platform_get_core_pos(int mpidr);
170	 *
171	 * result: CorePos = (ClusterId * cpus per cluster) +
172	 *                   CoreId
173	 * -----------------------------------------------------
174	 */
175func platform_get_core_pos
176	and	x1, x0, #MPIDR_CPU_MASK
177	and	x0, x0, #MPIDR_CLUSTER_MASK
178	lsr	x0, x0, #MPIDR_AFFINITY_BITS
179	mov	x2, #PLATFORM_MAX_CPUS_PER_CLUSTER
180	mul	x0, x0, x2
181	add	x0, x1, x0
182	ret
183endfunc platform_get_core_pos
184
185	/* -----------------------------------------------------
186	 * void plat_secondary_cold_boot_setup (void);
187	 *
188	 * This function performs any platform specific actions
189	 * needed for a secondary cpu after a cold reset. Right
190	 * now this is a stub function.
191	 * -----------------------------------------------------
192	 */
193func plat_secondary_cold_boot_setup
194	mov	x0, #0
195	ret
196endfunc plat_secondary_cold_boot_setup
197
198	/* --------------------------------------------------------
199	 * void platform_mem_init (void);
200	 *
201	 * Any memory init, relocation to be done before the
202	 * platform boots. Called very early in the boot process.
203	 * --------------------------------------------------------
204	 */
205func platform_mem_init
206	mov	x0, #0
207	ret
208endfunc platform_mem_init
209
210	/* ---------------------------------------------------
211	 * Function to handle a platform reset and store
212	 * input parameters passed by BL2.
213	 * ---------------------------------------------------
214	 */
215func plat_reset_handler
216
217	/* ----------------------------------------------------
218	 * Verify if we are running from BL31_BASE address
219	 * ----------------------------------------------------
220	 */
221	adr	x18, bl31_entrypoint
222	mov	x17, #BL31_BASE
223	cmp	x18, x17
224	b.eq	1f
225
226	/* ----------------------------------------------------
227	 * Copy the entire BL31 code to BL31_BASE if we are not
228	 * running from it already
229	 * ----------------------------------------------------
230	 */
231	mov	x0, x17
232	mov	x1, x18
233	mov	x2, #BL31_SIZE
234_loop16:
235	cmp	x2, #16
236	b.lo	_loop1
237	ldp	x3, x4, [x1], #16
238	stp	x3, x4, [x0], #16
239	sub	x2, x2, #16
240	b	_loop16
241	/* copy byte per byte */
242_loop1:
243	cbz	x2, _end
244	ldrb	w3, [x1], #1
245	strb	w3, [x0], #1
246	subs	x2, x2, #1
247	b.ne	_loop1
248
249	/* ----------------------------------------------------
250	 * Jump to BL31_BASE and start execution again
251	 * ----------------------------------------------------
252	 */
253_end:	mov	x0, x20
254	mov	x1, x21
255	br	x17
2561:
257
258	/* -----------------------------------
259	 * derive and save the phys_base addr
260	 * -----------------------------------
261	 */
262	adr	x17, tegra_bl31_phys_base
263	ldr	x18, [x17]
264	cbnz	x18, 1f
265	adr	x18, bl31_entrypoint
266	str	x18, [x17]
267
2681:	cpu_init_common
269
270	ret
271endfunc plat_reset_handler
272
273	/* ----------------------------------------
274	 * Secure entrypoint function for CPU boot
275	 * ----------------------------------------
276	 */
277func tegra_secure_entrypoint _align=6
278
279#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT
280
281	/* --------------------------------------------------------
282	 * Skip the invalidate BTB workaround for Tegra210B01 SKUs.
283	 * --------------------------------------------------------
284	 */
285	mov	x0, #TEGRA_MISC_BASE
286	add	x0, x0, #HARDWARE_REVISION_OFFSET
287	ldr	w1, [x0]
288	lsr	w1, w1, #CHIP_ID_SHIFT
289	and	w1, w1, #CHIP_ID_MASK
290	cmp	w1, #TEGRA_CHIPID_TEGRA21	/* T210? */
291	b.ne	2f
292	ldr	w1, [x0]
293	lsr	w1, w1, #MAJOR_VERSION_SHIFT
294	and	w1, w1, #MAJOR_VERSION_MASK
295	cmp	w1, #0x02			/* T210 B01? */
296	b.eq	2f
297
298	/* -------------------------------------------------------
299	 * Invalidate BTB along with I$ to remove any stale
300	 * entries from the branch predictor array.
301	 * -------------------------------------------------------
302	 */
303	mrs	x0, CORTEX_A57_CPUACTLR_EL1
304	orr	x0, x0, #1
305	msr	CORTEX_A57_CPUACTLR_EL1, x0	/* invalidate BTB and I$ together */
306	dsb	sy
307	isb
308	ic	iallu			/* actual invalidate */
309	dsb	sy
310	isb
311
312	mrs	x0, CORTEX_A57_CPUACTLR_EL1
313	bic	x0, x0, #1
314	msr	CORTEX_A57_CPUACTLR_EL1, X0	/* restore original CPUACTLR_EL1 */
315	dsb	sy
316	isb
317
318	.rept	7
319	nop				/* wait */
320	.endr
321
322	/* -----------------------------------------------
323	 * Extract OSLK bit and check if it is '1'. This
324	 * bit remains '0' for A53 on warm-resets. If '1',
325	 * turn off regional clock gating and request warm
326	 * reset.
327	 * -----------------------------------------------
328	 */
329	mrs	x0, oslsr_el1
330	and	x0, x0, #2
331	mrs	x1, mpidr_el1
332	bics	xzr, x0, x1, lsr #7	/* 0 = slow cluster or warm reset */
333	b.eq	restore_oslock
334	mov	x0, xzr
335	msr	oslar_el1, x0		/* os lock stays 0 across warm reset */
336	mov	x3, #3
337	movz	x4, #0x8000, lsl #48
338	msr	CORTEX_A57_CPUACTLR_EL1, x4	/* turn off RCG */
339	isb
340	msr	rmr_el3, x3		/* request warm reset */
341	isb
342	dsb	sy
3431:	wfi
344	b	1b
345
346	/* --------------------------------------------------
347	 * These nops are here so that speculative execution
348	 * won't harm us before we are done with warm reset.
349	 * --------------------------------------------------
350	 */
351	.rept	65
352	nop
353	.endr
3542:
355	/* --------------------------------------------------
356	 * Do not insert instructions here
357	 * --------------------------------------------------
358	 */
359#endif
360
361	/* --------------------------------------------------
362	 * Restore OS Lock bit
363	 * --------------------------------------------------
364	 */
365restore_oslock:
366	mov	x0, #1
367	msr	oslar_el1, x0
368
369	/* --------------------------------------------------
370	 * Get secure world's entry point and jump to it
371	 * --------------------------------------------------
372	 */
373	bl	plat_get_my_entrypoint
374	br	x0
375endfunc tegra_secure_entrypoint
376
377	.data
378	.align 3
379
380	/* --------------------------------------------------
381	 * CPU Secure entry point - resume from suspend
382	 * --------------------------------------------------
383	 */
384tegra_sec_entry_point:
385	.quad	0
386
387	/* --------------------------------------------------
388	 * NS world's cold boot entry point
389	 * --------------------------------------------------
390	 */
391ns_image_entrypoint:
392	.quad	0
393
394	/* --------------------------------------------------
395	 * BL31's physical base address
396	 * --------------------------------------------------
397	 */
398tegra_bl31_phys_base:
399	.quad	0
400
401	/* --------------------------------------------------
402	 * UART controller base for console init
403	 * --------------------------------------------------
404	 */
405tegra_console_base:
406	.quad	0
407