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