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