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