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