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