xref: /rk3399_ARM-atf/plat/rpi/common/aarch64/plat_helpers.S (revision 07aa0c7e0e13db4b22de135247b4aa3a5b18f15b)
1*07aa0c7eSAndre Przywara/*
2*07aa0c7eSAndre Przywara * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
3*07aa0c7eSAndre Przywara *
4*07aa0c7eSAndre Przywara * SPDX-License-Identifier: BSD-3-Clause
5*07aa0c7eSAndre Przywara */
6*07aa0c7eSAndre Przywara
7*07aa0c7eSAndre Przywara#include <arch.h>
8*07aa0c7eSAndre Przywara#include <asm_macros.S>
9*07aa0c7eSAndre Przywara#include <assert_macros.S>
10*07aa0c7eSAndre Przywara#include <platform_def.h>
11*07aa0c7eSAndre Przywara#include <cortex_a72.h>
12*07aa0c7eSAndre Przywara
13*07aa0c7eSAndre Przywara	.globl	plat_crash_console_flush
14*07aa0c7eSAndre Przywara	.globl	plat_crash_console_init
15*07aa0c7eSAndre Przywara	.globl	plat_crash_console_putc
16*07aa0c7eSAndre Przywara	.globl	platform_mem_init
17*07aa0c7eSAndre Przywara	.globl	plat_get_my_entrypoint
18*07aa0c7eSAndre Przywara	.globl	plat_is_my_cpu_primary
19*07aa0c7eSAndre Przywara	.globl	plat_my_core_pos
20*07aa0c7eSAndre Przywara	.globl	plat_reset_handler
21*07aa0c7eSAndre Przywara	.globl	plat_rpi3_calc_core_pos
22*07aa0c7eSAndre Przywara	.globl	plat_secondary_cold_boot_setup
23*07aa0c7eSAndre Przywara	.globl	plat_rpi_get_model
24*07aa0c7eSAndre Przywara
25*07aa0c7eSAndre Przywara	/* -----------------------------------------------------
26*07aa0c7eSAndre Przywara	 *  unsigned int plat_my_core_pos(void)
27*07aa0c7eSAndre Przywara	 *
28*07aa0c7eSAndre Przywara	 *  This function uses the plat_rpi3_calc_core_pos()
29*07aa0c7eSAndre Przywara	 *  definition to get the index of the calling CPU.
30*07aa0c7eSAndre Przywara	 * -----------------------------------------------------
31*07aa0c7eSAndre Przywara	 */
32*07aa0c7eSAndre Przywarafunc plat_my_core_pos
33*07aa0c7eSAndre Przywara	mrs	x0, mpidr_el1
34*07aa0c7eSAndre Przywara	b	plat_rpi3_calc_core_pos
35*07aa0c7eSAndre Przywaraendfunc plat_my_core_pos
36*07aa0c7eSAndre Przywara
37*07aa0c7eSAndre Przywara	/* -----------------------------------------------------
38*07aa0c7eSAndre Przywara	 *  unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
39*07aa0c7eSAndre Przywara	 *
40*07aa0c7eSAndre Przywara	 *  CorePos = (ClusterId * 4) + CoreId
41*07aa0c7eSAndre Przywara	 * -----------------------------------------------------
42*07aa0c7eSAndre Przywara	 */
43*07aa0c7eSAndre Przywarafunc plat_rpi3_calc_core_pos
44*07aa0c7eSAndre Przywara	and	x1, x0, #MPIDR_CPU_MASK
45*07aa0c7eSAndre Przywara	and	x0, x0, #MPIDR_CLUSTER_MASK
46*07aa0c7eSAndre Przywara	add	x0, x1, x0, LSR #6
47*07aa0c7eSAndre Przywara	ret
48*07aa0c7eSAndre Przywaraendfunc plat_rpi3_calc_core_pos
49*07aa0c7eSAndre Przywara
50*07aa0c7eSAndre Przywara	/* -----------------------------------------------------
51*07aa0c7eSAndre Przywara	 * unsigned int plat_is_my_cpu_primary (void);
52*07aa0c7eSAndre Przywara	 *
53*07aa0c7eSAndre Przywara	 * Find out whether the current cpu is the primary
54*07aa0c7eSAndre Przywara	 * cpu.
55*07aa0c7eSAndre Przywara	 * -----------------------------------------------------
56*07aa0c7eSAndre Przywara	 */
57*07aa0c7eSAndre Przywarafunc plat_is_my_cpu_primary
58*07aa0c7eSAndre Przywara	mrs	x0, mpidr_el1
59*07aa0c7eSAndre Przywara	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
60*07aa0c7eSAndre Przywara	cmp	x0, #RPI_PRIMARY_CPU
61*07aa0c7eSAndre Przywara	cset	w0, eq
62*07aa0c7eSAndre Przywara	ret
63*07aa0c7eSAndre Przywaraendfunc plat_is_my_cpu_primary
64*07aa0c7eSAndre Przywara
65*07aa0c7eSAndre Przywara	/* -----------------------------------------------------
66*07aa0c7eSAndre Przywara	 * void plat_secondary_cold_boot_setup (void);
67*07aa0c7eSAndre Przywara	 *
68*07aa0c7eSAndre Przywara	 * This function performs any platform specific actions
69*07aa0c7eSAndre Przywara	 * needed for a secondary cpu after a cold reset e.g
70*07aa0c7eSAndre Przywara	 * mark the cpu's presence, mechanism to place it in a
71*07aa0c7eSAndre Przywara	 * holding pen etc.
72*07aa0c7eSAndre Przywara	 * -----------------------------------------------------
73*07aa0c7eSAndre Przywara	 */
74*07aa0c7eSAndre Przywarafunc plat_secondary_cold_boot_setup
75*07aa0c7eSAndre Przywara	/* Calculate address of our hold entry */
76*07aa0c7eSAndre Przywara	bl	plat_my_core_pos
77*07aa0c7eSAndre Przywara	lsl	x0, x0, #3
78*07aa0c7eSAndre Przywara	mov_imm	x2, PLAT_RPI3_TM_HOLD_BASE
79*07aa0c7eSAndre Przywara	add	x0, x0, x2
80*07aa0c7eSAndre Przywara
81*07aa0c7eSAndre Przywara	/*
82*07aa0c7eSAndre Przywara	 * This code runs way before requesting the warmboot of this core,
83*07aa0c7eSAndre Przywara	 * so it is possible to clear the mailbox before getting a request
84*07aa0c7eSAndre Przywara	 * to boot.
85*07aa0c7eSAndre Przywara	 */
86*07aa0c7eSAndre Przywara	mov	x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
87*07aa0c7eSAndre Przywara	str	x1,[x0]
88*07aa0c7eSAndre Przywara
89*07aa0c7eSAndre Przywara	/* Wait until we have a go */
90*07aa0c7eSAndre Przywarapoll_mailbox:
91*07aa0c7eSAndre Przywara	wfe
92*07aa0c7eSAndre Przywara	ldr	x1, [x0]
93*07aa0c7eSAndre Przywara	cmp	x1, PLAT_RPI3_TM_HOLD_STATE_GO
94*07aa0c7eSAndre Przywara	bne	poll_mailbox
95*07aa0c7eSAndre Przywara
96*07aa0c7eSAndre Przywara	/* Jump to the provided entrypoint */
97*07aa0c7eSAndre Przywara	mov_imm	x0, PLAT_RPI3_TM_ENTRYPOINT
98*07aa0c7eSAndre Przywara	ldr	x1, [x0]
99*07aa0c7eSAndre Przywara	br	x1
100*07aa0c7eSAndre Przywaraendfunc plat_secondary_cold_boot_setup
101*07aa0c7eSAndre Przywara
102*07aa0c7eSAndre Przywara	/* ---------------------------------------------------------------------
103*07aa0c7eSAndre Przywara	 * uintptr_t plat_get_my_entrypoint (void);
104*07aa0c7eSAndre Przywara	 *
105*07aa0c7eSAndre Przywara	 * Main job of this routine is to distinguish between a cold and a warm
106*07aa0c7eSAndre Przywara	 * boot.
107*07aa0c7eSAndre Przywara	 *
108*07aa0c7eSAndre Przywara	 * This functions returns:
109*07aa0c7eSAndre Przywara	 *  - 0 for a cold boot.
110*07aa0c7eSAndre Przywara	 *  - Any other value for a warm boot.
111*07aa0c7eSAndre Przywara	 * ---------------------------------------------------------------------
112*07aa0c7eSAndre Przywara	 */
113*07aa0c7eSAndre Przywarafunc plat_get_my_entrypoint
114*07aa0c7eSAndre Przywara	/* TODO: support warm boot */
115*07aa0c7eSAndre Przywara	mov	x0, #0
116*07aa0c7eSAndre Przywara	ret
117*07aa0c7eSAndre Przywaraendfunc plat_get_my_entrypoint
118*07aa0c7eSAndre Przywara
119*07aa0c7eSAndre Przywara	/* ---------------------------------------------
120*07aa0c7eSAndre Przywara	 * void platform_mem_init (void);
121*07aa0c7eSAndre Przywara	 *
122*07aa0c7eSAndre Przywara	 * No need to carry out any memory initialization.
123*07aa0c7eSAndre Przywara	 * ---------------------------------------------
124*07aa0c7eSAndre Przywara	 */
125*07aa0c7eSAndre Przywarafunc platform_mem_init
126*07aa0c7eSAndre Przywara	ret
127*07aa0c7eSAndre Przywaraendfunc platform_mem_init
128*07aa0c7eSAndre Przywara
129*07aa0c7eSAndre Przywara	/* ---------------------------------------------
130*07aa0c7eSAndre Przywara	 * int plat_crash_console_init(void)
131*07aa0c7eSAndre Przywara	 * Function to initialize the crash console
132*07aa0c7eSAndre Przywara	 * without a C Runtime to print crash report.
133*07aa0c7eSAndre Przywara	 * Clobber list : x0 - x3
134*07aa0c7eSAndre Przywara	 * ---------------------------------------------
135*07aa0c7eSAndre Przywara	 */
136*07aa0c7eSAndre Przywarafunc plat_crash_console_init
137*07aa0c7eSAndre Przywara	mov_imm	x0, PLAT_RPI_MINI_UART_BASE
138*07aa0c7eSAndre Przywara	mov	x1, xzr
139*07aa0c7eSAndre Przywara	mov	x2, xzr
140*07aa0c7eSAndre Przywara	b	console_16550_core_init
141*07aa0c7eSAndre Przywaraendfunc plat_crash_console_init
142*07aa0c7eSAndre Przywara
143*07aa0c7eSAndre Przywara	/* ---------------------------------------------
144*07aa0c7eSAndre Przywara	 * int plat_crash_console_putc(int c)
145*07aa0c7eSAndre Przywara	 * Function to print a character on the crash
146*07aa0c7eSAndre Przywara	 * console without a C Runtime.
147*07aa0c7eSAndre Przywara	 * Clobber list : x1, x2
148*07aa0c7eSAndre Przywara	 * ---------------------------------------------
149*07aa0c7eSAndre Przywara	 */
150*07aa0c7eSAndre Przywarafunc plat_crash_console_putc
151*07aa0c7eSAndre Przywara	mov_imm	x1, PLAT_RPI_MINI_UART_BASE
152*07aa0c7eSAndre Przywara	b	console_16550_core_putc
153*07aa0c7eSAndre Przywaraendfunc plat_crash_console_putc
154*07aa0c7eSAndre Przywara
155*07aa0c7eSAndre Przywara	/* ---------------------------------------------
156*07aa0c7eSAndre Przywara	 * int plat_crash_console_flush()
157*07aa0c7eSAndre Przywara	 * Function to force a write of all buffered
158*07aa0c7eSAndre Przywara	 * data that hasn't been output.
159*07aa0c7eSAndre Przywara	 * Out : return -1 on error else return 0.
160*07aa0c7eSAndre Przywara	 * Clobber list : x0, x1
161*07aa0c7eSAndre Przywara	 * ---------------------------------------------
162*07aa0c7eSAndre Przywara	 */
163*07aa0c7eSAndre Przywarafunc plat_crash_console_flush
164*07aa0c7eSAndre Przywara	mov_imm	x0, PLAT_RPI_MINI_UART_BASE
165*07aa0c7eSAndre Przywara	b	console_16550_core_flush
166*07aa0c7eSAndre Przywaraendfunc plat_crash_console_flush
167*07aa0c7eSAndre Przywara
168*07aa0c7eSAndre Przywara	/* ---------------------------------------------
169*07aa0c7eSAndre Przywara	 * int plat_rpi_get_model()
170*07aa0c7eSAndre Przywara	 * Macro to determine whether we are running on
171*07aa0c7eSAndre Przywara	 * a Raspberry Pi 3 or 4. Just checks the MIDR for
172*07aa0c7eSAndre Przywara	 * being either a Cortex-A72 or a Cortex-A53.
173*07aa0c7eSAndre Przywara	 * Out : return 4 if RPi4, 3 otherwise.
174*07aa0c7eSAndre Przywara	 * Clobber list : x0
175*07aa0c7eSAndre Przywara	 * ---------------------------------------------
176*07aa0c7eSAndre Przywara	 */
177*07aa0c7eSAndre Przywara	.macro _plat_rpi_get_model
178*07aa0c7eSAndre Przywara	mrs	x0, midr_el1
179*07aa0c7eSAndre Przywara	and	x0, x0, #0xf0	/* Isolate low byte of part number */
180*07aa0c7eSAndre Przywara	cmp	w0, #0x80	/* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */
181*07aa0c7eSAndre Przywara	mov	w0, #3
182*07aa0c7eSAndre Przywara	csinc	w0, w0, w0, ne
183*07aa0c7eSAndre Przywara	.endm
184*07aa0c7eSAndre Przywara
185*07aa0c7eSAndre Przywara	func plat_rpi_get_model
186*07aa0c7eSAndre Przywara	_plat_rpi_get_model
187*07aa0c7eSAndre Przywara	ret
188*07aa0c7eSAndre Przywara	endfunc plat_rpi_get_model
189*07aa0c7eSAndre Przywara
190*07aa0c7eSAndre Przywara	/* ---------------------------------------------
191*07aa0c7eSAndre Przywara	 * void plat_reset_handler(void);
192*07aa0c7eSAndre Przywara	 * ---------------------------------------------
193*07aa0c7eSAndre Przywara	 */
194*07aa0c7eSAndre Przywarafunc plat_reset_handler
195*07aa0c7eSAndre Przywara	/* L2 cache setup only needed on RPi4 */
196*07aa0c7eSAndre Przywara	_plat_rpi_get_model
197*07aa0c7eSAndre Przywara	cmp	w0, #4
198*07aa0c7eSAndre Przywara	b.ne	1f
199*07aa0c7eSAndre Przywara
200*07aa0c7eSAndre Przywara	/* ------------------------------------------------
201*07aa0c7eSAndre Przywara	 * Set L2 read/write cache latency:
202*07aa0c7eSAndre Przywara	 * - L2 Data RAM latency: 3 cycles (0b010)
203*07aa0c7eSAndre Przywara	 * - L2 Data RAM setup: 1 cycle (bit 5)
204*07aa0c7eSAndre Przywara	 * ------------------------------------------------
205*07aa0c7eSAndre Przywara	 */
206*07aa0c7eSAndre Przywara	mrs	x0, CORTEX_A72_L2CTLR_EL1
207*07aa0c7eSAndre Przywara	mov	x1, #0x22
208*07aa0c7eSAndre Przywara	orr	x0, x0, x1
209*07aa0c7eSAndre Przywara	msr	CORTEX_A72_L2CTLR_EL1, x0
210*07aa0c7eSAndre Przywara	isb
211*07aa0c7eSAndre Przywara
212*07aa0c7eSAndre Przywara1:
213*07aa0c7eSAndre Przywara	ret
214*07aa0c7eSAndre Przywaraendfunc plat_reset_handler
215