xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/aarch64/tegra_helpers.S (revision a10d3632acbd1135648f07c2a998cba8c5c77cfd)
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	 * derive and save the phys_base addr
259	 * -----------------------------------
260	 */
261	adr	x17, tegra_bl31_phys_base
262	ldr	x18, [x17]
263	cbnz	x18, 1f
264	adr	x18, bl31_entrypoint
265	str	x18, [x17]
266
2671:	cpu_init_common
268
269	ret
270endfunc plat_reset_handler
271
272	/* ----------------------------------------
273	 * Secure entrypoint function for CPU boot
274	 * ----------------------------------------
275	 */
276	.align 6
277func tegra_secure_entrypoint
278
279#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT
280
281	/* -------------------------------------------------------
282	 * Invalidate BTB along with I$ to remove any stale
283	 * entries from the branch predictor array.
284	 * -------------------------------------------------------
285	 */
286	mrs	x0, CPUACTLR_EL1
287	orr	x0, x0, #1
288	msr	CPUACTLR_EL1, x0	/* invalidate BTB and I$ together */
289	dsb	sy
290	isb
291	ic	iallu			/* actual invalidate */
292	dsb	sy
293	isb
294
295	mrs	x0, CPUACTLR_EL1
296	bic	x0, x0, #1
297	msr	CPUACTLR_EL1, X0	/* restore original CPUACTLR_EL1 */
298	dsb	sy
299	isb
300
301	.rept	7
302	nop				/* wait */
303	.endr
304
305	/* -----------------------------------------------
306	 * Extract OSLK bit and check if it is '1'. This
307	 * bit remains '0' for A53 on warm-resets. If '1',
308	 * turn off regional clock gating and request warm
309	 * reset.
310	 * -----------------------------------------------
311	 */
312	mrs	x0, oslsr_el1
313	and	x0, x0, #2
314	mrs	x1, mpidr_el1
315	bics	xzr, x0, x1, lsr #7	/* 0 = slow cluster or warm reset */
316	b.eq	restore_oslock
317	mov	x0, xzr
318	msr	oslar_el1, x0		/* os lock stays 0 across warm reset */
319	mov	x3, #3
320	movz	x4, #0x8000, lsl #48
321	msr	CPUACTLR_EL1, x4	/* turn off RCG */
322	isb
323	msr	rmr_el3, x3		/* request warm reset */
324	isb
325	dsb	sy
3261:	wfi
327	b	1b
328
329	/* --------------------------------------------------
330	 * These nops are here so that speculative execution
331	 * won't harm us before we are done with warm reset.
332	 * --------------------------------------------------
333	 */
334	.rept	65
335	nop
336	.endr
337
338	/* --------------------------------------------------
339	 * Do not insert instructions here
340	 * --------------------------------------------------
341	 */
342#endif
343
344	/* --------------------------------------------------
345	 * Restore OS Lock bit
346	 * --------------------------------------------------
347	 */
348restore_oslock:
349	mov	x0, #1
350	msr	oslar_el1, x0
351
352	cpu_init_common
353
354	/* ---------------------------------------------------------------------
355	 * The initial state of the Architectural feature trap register
356	 * (CPTR_EL3) is unknown and it must be set to a known state. All
357	 * feature traps are disabled. Some bits in this register are marked as
358	 * Reserved and should not be modified.
359	 *
360	 * CPTR_EL3.TCPAC: This causes a direct access to the CPACR_EL1 from EL1
361	 *  or the CPTR_EL2 from EL2 to trap to EL3 unless it is trapped at EL2.
362	 * CPTR_EL3.TTA: This causes access to the Trace functionality to trap
363	 *  to EL3 when executed from EL0, EL1, EL2, or EL3. If system register
364	 *  access to trace functionality is not supported, this bit is RES0.
365	 * CPTR_EL3.TFP: This causes instructions that access the registers
366	 *  associated with Floating Point and Advanced SIMD execution to trap
367	 *  to EL3 when executed from any exception level, unless trapped to EL1
368	 *  or EL2.
369	 * ---------------------------------------------------------------------
370	 */
371	mrs	x1, cptr_el3
372	bic	w1, w1, #TCPAC_BIT
373	bic	w1, w1, #TTA_BIT
374	bic	w1, w1, #TFP_BIT
375	msr	cptr_el3, x1
376
377	/* --------------------------------------------------
378	 * Get secure world's entry point and jump to it
379	 * --------------------------------------------------
380	 */
381	bl	plat_get_my_entrypoint
382	br	x0
383endfunc tegra_secure_entrypoint
384
385	.data
386	.align 3
387
388	/* --------------------------------------------------
389	 * CPU Secure entry point - resume from suspend
390	 * --------------------------------------------------
391	 */
392tegra_sec_entry_point:
393	.quad	0
394
395	/* --------------------------------------------------
396	 * NS world's cold boot entry point
397	 * --------------------------------------------------
398	 */
399ns_image_entrypoint:
400	.quad	0
401
402	/* --------------------------------------------------
403	 * BL31's physical base address
404	 * --------------------------------------------------
405	 */
406tegra_bl31_phys_base:
407	.quad	0
408
409	/* --------------------------------------------------
410	 * UART controller base for console init
411	 * --------------------------------------------------
412	 */
413tegra_console_base:
414	.quad	0
415