xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/aarch64/tegra_helpers.S (revision aa61368eb554e9910c503f78560153805a2d6859)
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	mov	x0, #0
247	adr	x1, tegra_console_base
248	ldr	x1, [x1]
249	cbz	x1, 1f
250	mov	w0, #1
2511:	ret
252endfunc plat_crash_console_init
253
254	/* ---------------------------------------------
255	 * int plat_crash_console_putc(void)
256	 * Function to print a character on the crash
257	 * console without a C Runtime.
258	 * Clobber list : x1, x2
259	 * ---------------------------------------------
260	 */
261func plat_crash_console_putc
262	adr	x1, tegra_console_base
263	ldr	x1, [x1]
264	b	console_core_putc
265endfunc plat_crash_console_putc
266
267	/* ---------------------------------------------------
268	 * Function to handle a platform reset and store
269	 * input parameters passed by BL2.
270	 * ---------------------------------------------------
271	 */
272func plat_reset_handler
273
274	/* ----------------------------------------------------
275	 * Verify if we are running from BL31_BASE address
276	 * ----------------------------------------------------
277	 */
278	adr	x18, bl31_entrypoint
279	mov	x17, #BL31_BASE
280	cmp	x18, x17
281	b.eq	1f
282
283	/* ----------------------------------------------------
284	 * Copy the entire BL31 code to BL31_BASE if we are not
285	 * running from it already
286	 * ----------------------------------------------------
287	 */
288	mov	x0, x17
289	mov	x1, x18
290	mov	x2, #BL31_SIZE
291_loop16:
292	cmp	x2, #16
293	b.lo	_loop1
294	ldp	x3, x4, [x1], #16
295	stp	x3, x4, [x0], #16
296	sub	x2, x2, #16
297	b	_loop16
298	/* copy byte per byte */
299_loop1:
300	cbz	x2, _end
301	ldrb	w3, [x1], #1
302	strb	w3, [x0], #1
303	subs	x2, x2, #1
304	b.ne	_loop1
305
306	/* ----------------------------------------------------
307	 * Jump to BL31_BASE and start execution again
308	 * ----------------------------------------------------
309	 */
310_end:	mov	x0, x20
311	mov	x1, x21
312	br	x17
3131:
314
315	/* -----------------------------------
316	 * derive and save the phys_base addr
317	 * -----------------------------------
318	 */
319	adr	x17, tegra_bl31_phys_base
320	ldr	x18, [x17]
321	cbnz	x18, 1f
322	adr	x18, bl31_entrypoint
323	str	x18, [x17]
324
3251:	cpu_init_common
326
327	ret
328endfunc plat_reset_handler
329
330	/* ----------------------------------------
331	 * Secure entrypoint function for CPU boot
332	 * ----------------------------------------
333	 */
334	.align 6
335func tegra_secure_entrypoint
336
337#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT
338
339	/* -------------------------------------------------------
340	 * Invalidate BTB along with I$ to remove any stale
341	 * entries from the branch predictor array.
342	 * -------------------------------------------------------
343	 */
344	mrs	x0, CPUACTLR_EL1
345	orr	x0, x0, #1
346	msr	CPUACTLR_EL1, x0	/* invalidate BTB and I$ together */
347	dsb	sy
348	isb
349	ic	iallu			/* actual invalidate */
350	dsb	sy
351	isb
352
353	mrs	x0, CPUACTLR_EL1
354	bic	x0, x0, #1
355	msr	CPUACTLR_EL1, X0	/* restore original CPUACTLR_EL1 */
356	dsb	sy
357	isb
358
359	.rept	7
360	nop				/* wait */
361	.endr
362
363	/* -----------------------------------------------
364	 * Extract OSLK bit and check if it is '1'. This
365	 * bit remains '0' for A53 on warm-resets. If '1',
366	 * turn off regional clock gating and request warm
367	 * reset.
368	 * -----------------------------------------------
369	 */
370	mrs	x0, oslsr_el1
371	and	x0, x0, #2
372	mrs	x1, mpidr_el1
373	bics	xzr, x0, x1, lsr #7	/* 0 = slow cluster or warm reset */
374	b.eq	restore_oslock
375	mov	x0, xzr
376	msr	oslar_el1, x0		/* os lock stays 0 across warm reset */
377	mov	x3, #3
378	movz	x4, #0x8000, lsl #48
379	msr	CPUACTLR_EL1, x4	/* turn off RCG */
380	isb
381	msr	rmr_el3, x3		/* request warm reset */
382	isb
383	dsb	sy
3841:	wfi
385	b	1b
386
387	/* --------------------------------------------------
388	 * These nops are here so that speculative execution
389	 * won't harm us before we are done with warm reset.
390	 * --------------------------------------------------
391	 */
392	.rept	65
393	nop
394	.endr
395
396	/* --------------------------------------------------
397	 * Do not insert instructions here
398	 * --------------------------------------------------
399	 */
400#endif
401
402	/* --------------------------------------------------
403	 * Restore OS Lock bit
404	 * --------------------------------------------------
405	 */
406restore_oslock:
407	mov	x0, #1
408	msr	oslar_el1, x0
409
410	cpu_init_common
411
412	/* ---------------------------------------------------------------------
413	 * The initial state of the Architectural feature trap register
414	 * (CPTR_EL3) is unknown and it must be set to a known state. All
415	 * feature traps are disabled. Some bits in this register are marked as
416	 * Reserved and should not be modified.
417	 *
418	 * CPTR_EL3.TCPAC: This causes a direct access to the CPACR_EL1 from EL1
419	 *  or the CPTR_EL2 from EL2 to trap to EL3 unless it is trapped at EL2.
420	 * CPTR_EL3.TTA: This causes access to the Trace functionality to trap
421	 *  to EL3 when executed from EL0, EL1, EL2, or EL3. If system register
422	 *  access to trace functionality is not supported, this bit is RES0.
423	 * CPTR_EL3.TFP: This causes instructions that access the registers
424	 *  associated with Floating Point and Advanced SIMD execution to trap
425	 *  to EL3 when executed from any exception level, unless trapped to EL1
426	 *  or EL2.
427	 * ---------------------------------------------------------------------
428	 */
429	mrs	x1, cptr_el3
430	bic	w1, w1, #TCPAC_BIT
431	bic	w1, w1, #TTA_BIT
432	bic	w1, w1, #TFP_BIT
433	msr	cptr_el3, x1
434
435	/* --------------------------------------------------
436	 * Get secure world's entry point and jump to it
437	 * --------------------------------------------------
438	 */
439	bl	plat_get_my_entrypoint
440	br	x0
441endfunc tegra_secure_entrypoint
442
443	.data
444	.align 3
445
446	/* --------------------------------------------------
447	 * CPU Secure entry point - resume from suspend
448	 * --------------------------------------------------
449	 */
450tegra_sec_entry_point:
451	.quad	0
452
453	/* --------------------------------------------------
454	 * NS world's cold boot entry point
455	 * --------------------------------------------------
456	 */
457ns_image_entrypoint:
458	.quad	0
459
460	/* --------------------------------------------------
461	 * BL31's physical base address
462	 * --------------------------------------------------
463	 */
464tegra_bl31_phys_base:
465	.quad	0
466
467	/* --------------------------------------------------
468	 * UART controller base for console init
469	 * --------------------------------------------------
470	 */
471tegra_console_base:
472	.quad	0
473
474	/* --------------------------------------------------
475	 * Enable L2 ECC and Parity Protection
476	 * --------------------------------------------------
477	 */
478tegra_enable_l2_ecc_parity_prot:
479	.quad	0
480