blob: 18873af7f479254265f835818a205d6161ce86bc [file] [log] [blame]
Andre Przywara6d471e12019-07-09 11:25:57 +01001/*
Mario Bălănică3bb68ae2023-12-01 05:12:58 +02002 * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
Andre Przywara6d471e12019-07-09 11:25:57 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <asm_macros.S>
9#include <assert_macros.S>
10#include <platform_def.h>
11#include <cortex_a72.h>
12
Andre Przywara6d471e12019-07-09 11:25:57 +010013 .globl plat_crash_console_flush
14 .globl plat_crash_console_init
15 .globl plat_crash_console_putc
16 .globl platform_mem_init
17 .globl plat_get_my_entrypoint
18 .globl plat_is_my_cpu_primary
19 .globl plat_my_core_pos
20 .globl plat_reset_handler
21 .globl plat_rpi3_calc_core_pos
22 .globl plat_secondary_cold_boot_setup
Andre Przywara98e48562020-03-12 14:20:04 +000023 .globl plat_rpi_get_model
Andre Przywara6d471e12019-07-09 11:25:57 +010024
25 /* -----------------------------------------------------
26 * unsigned int plat_my_core_pos(void)
27 *
28 * This function uses the plat_rpi3_calc_core_pos()
29 * definition to get the index of the calling CPU.
Mario Bălănică40656462023-12-01 05:43:53 +020030 *
31 * When MT is set, lowest affinity represents the thread ID.
32 * Since we only support one thread per core, discard this field
33 * so cluster and core IDs go back into Aff1 and Aff0 respectively.
34 * The upper bits are also affected, but plat_rpi3_calc_core_pos()
35 * does not use them.
Andre Przywara6d471e12019-07-09 11:25:57 +010036 * -----------------------------------------------------
37 */
38func plat_my_core_pos
39 mrs x0, mpidr_el1
Mario Bălănică40656462023-12-01 05:43:53 +020040 tst x0, #MPIDR_MT_MASK
41 lsr x1, x0, #MPIDR_AFFINITY_BITS
42 csel x0, x1, x0, ne
Andre Przywara6d471e12019-07-09 11:25:57 +010043 b plat_rpi3_calc_core_pos
44endfunc plat_my_core_pos
45
46 /* -----------------------------------------------------
47 * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
48 *
49 * CorePos = (ClusterId * 4) + CoreId
50 * -----------------------------------------------------
51 */
52func plat_rpi3_calc_core_pos
53 and x1, x0, #MPIDR_CPU_MASK
54 and x0, x0, #MPIDR_CLUSTER_MASK
55 add x0, x1, x0, LSR #6
56 ret
57endfunc plat_rpi3_calc_core_pos
58
59 /* -----------------------------------------------------
60 * unsigned int plat_is_my_cpu_primary (void);
61 *
62 * Find out whether the current cpu is the primary
63 * cpu.
64 * -----------------------------------------------------
65 */
66func plat_is_my_cpu_primary
67 mrs x0, mpidr_el1
68 and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
Andre Przywara98e48562020-03-12 14:20:04 +000069 cmp x0, #RPI_PRIMARY_CPU
Andre Przywara6d471e12019-07-09 11:25:57 +010070 cset w0, eq
71 ret
72endfunc plat_is_my_cpu_primary
73
74 /* -----------------------------------------------------
Andrei Warkentinc96d4302020-03-11 22:11:06 -070075 * void plat_wait_for_warm_boot (void);
Andre Przywara6d471e12019-07-09 11:25:57 +010076 *
77 * This function performs any platform specific actions
Andrei Warkentinc96d4302020-03-11 22:11:06 -070078 * needed for a CPU to be put into holding pen to wait
79 * for a warm boot request.
80 * The function will never return.
Andre Przywara6d471e12019-07-09 11:25:57 +010081 * -----------------------------------------------------
82 */
Andrei Warkentinc96d4302020-03-11 22:11:06 -070083func plat_wait_for_warm_boot
84 /*
85 * Calculate address of our hold entry.
86 * As the function will never return, there is no need to save LR.
87 */
Andre Przywara6d471e12019-07-09 11:25:57 +010088 bl plat_my_core_pos
89 lsl x0, x0, #3
90 mov_imm x2, PLAT_RPI3_TM_HOLD_BASE
91 add x0, x0, x2
Andre Przywara6d471e12019-07-09 11:25:57 +010092 /*
93 * This code runs way before requesting the warmboot of this core,
94 * so it is possible to clear the mailbox before getting a request
95 * to boot.
96 */
97 mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
98 str x1,[x0]
99
100 /* Wait until we have a go */
101poll_mailbox:
102 wfe
103 ldr x1, [x0]
104 cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO
105 bne poll_mailbox
106
107 /* Jump to the provided entrypoint */
108 mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT
109 ldr x1, [x0]
110 br x1
Andrei Warkentinc96d4302020-03-11 22:11:06 -0700111endfunc plat_wait_for_warm_boot
112
113 /* -----------------------------------------------------
114 * void plat_secondary_cold_boot_setup (void);
115 *
116 * This function performs any platform specific actions
117 * needed for a secondary cpu after a cold reset e.g
118 * mark the cpu's presence, mechanism to place it in a
119 * holding pen etc.
120 * -----------------------------------------------------
121 */
122func plat_secondary_cold_boot_setup
123 b plat_wait_for_warm_boot
Andre Przywara6d471e12019-07-09 11:25:57 +0100124endfunc plat_secondary_cold_boot_setup
125
126 /* ---------------------------------------------------------------------
127 * uintptr_t plat_get_my_entrypoint (void);
128 *
129 * Main job of this routine is to distinguish between a cold and a warm
130 * boot.
131 *
132 * This functions returns:
133 * - 0 for a cold boot.
134 * - Any other value for a warm boot.
135 * ---------------------------------------------------------------------
136 */
137func plat_get_my_entrypoint
Andrei Warkentinc96d4302020-03-11 22:11:06 -0700138 mov x1, x30
139 bl plat_is_my_cpu_primary
140 /*
141 * Secondaries always cold boot.
142 */
143 cbz w0, 1f
144 /*
145 * Primaries warm boot if they are requested
146 * to power off.
147 */
148 mov_imm x0, PLAT_RPI3_TM_HOLD_BASE
149 ldr x0, [x0]
150 cmp x0, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF
151 adr x0, plat_wait_for_warm_boot
152 csel x0, x0, xzr, eq
153 ret x1
1541: mov x0, #0
155 ret x1
Andre Przywara6d471e12019-07-09 11:25:57 +0100156endfunc plat_get_my_entrypoint
157
158 /* ---------------------------------------------
159 * void platform_mem_init (void);
160 *
161 * No need to carry out any memory initialization.
162 * ---------------------------------------------
163 */
164func platform_mem_init
165 ret
166endfunc platform_mem_init
167
168 /* ---------------------------------------------
169 * int plat_crash_console_init(void)
170 * Function to initialize the crash console
171 * without a C Runtime to print crash report.
172 * Clobber list : x0 - x3
173 * ---------------------------------------------
174 */
175func plat_crash_console_init
Mario Bălănică3bb68ae2023-12-01 05:12:58 +0200176 mov_imm x0, PLAT_RPI_CRASH_UART_BASE
177#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
178 mov_imm x1, RPI4_PL011_UART_CLOCK
179 mov_imm x2, PLAT_RPI_UART_BAUDRATE
180 b console_pl011_core_init
181#else
Andre Przywaraeb10a862019-12-12 16:31:11 +0000182 mov x1, xzr
183 mov x2, xzr
Andre Przywara6d471e12019-07-09 11:25:57 +0100184 b console_16550_core_init
Mario Bălănică3bb68ae2023-12-01 05:12:58 +0200185#endif
Andre Przywara6d471e12019-07-09 11:25:57 +0100186endfunc plat_crash_console_init
187
188 /* ---------------------------------------------
189 * int plat_crash_console_putc(int c)
190 * Function to print a character on the crash
191 * console without a C Runtime.
192 * Clobber list : x1, x2
193 * ---------------------------------------------
194 */
195func plat_crash_console_putc
Mario Bălănică3bb68ae2023-12-01 05:12:58 +0200196 mov_imm x1, PLAT_RPI_CRASH_UART_BASE
197#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
198 b console_pl011_core_putc
199#else
Andre Przywara6d471e12019-07-09 11:25:57 +0100200 b console_16550_core_putc
Mario Bălănică3bb68ae2023-12-01 05:12:58 +0200201#endif
Andre Przywara6d471e12019-07-09 11:25:57 +0100202endfunc plat_crash_console_putc
203
204 /* ---------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500205 * void plat_crash_console_flush()
Andre Przywara6d471e12019-07-09 11:25:57 +0100206 * Function to force a write of all buffered
207 * data that hasn't been output.
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500208 * Out : void.
Andre Przywara6d471e12019-07-09 11:25:57 +0100209 * Clobber list : x0, x1
210 * ---------------------------------------------
211 */
212func plat_crash_console_flush
Mario Bălănică3bb68ae2023-12-01 05:12:58 +0200213 mov_imm x0, PLAT_RPI_CRASH_UART_BASE
214#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
215 b console_pl011_core_flush
216#else
Andre Przywara6d471e12019-07-09 11:25:57 +0100217 b console_16550_core_flush
Mario Bălănică3bb68ae2023-12-01 05:12:58 +0200218#endif
Andre Przywara6d471e12019-07-09 11:25:57 +0100219endfunc plat_crash_console_flush
220
221 /* ---------------------------------------------
Andre Przywara98e48562020-03-12 14:20:04 +0000222 * int plat_rpi_get_model()
223 * Macro to determine whether we are running on
224 * a Raspberry Pi 3 or 4. Just checks the MIDR for
225 * being either a Cortex-A72 or a Cortex-A53.
226 * Out : return 4 if RPi4, 3 otherwise.
227 * Clobber list : x0
228 * ---------------------------------------------
229 */
230 .macro _plat_rpi_get_model
231 mrs x0, midr_el1
232 and x0, x0, #0xf0 /* Isolate low byte of part number */
233 cmp w0, #0x80 /* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */
234 mov w0, #3
235 csinc w0, w0, w0, ne
236 .endm
237
238 func plat_rpi_get_model
239 _plat_rpi_get_model
240 ret
241 endfunc plat_rpi_get_model
242
243 /* ---------------------------------------------
Andre Przywara6d471e12019-07-09 11:25:57 +0100244 * void plat_reset_handler(void);
245 * ---------------------------------------------
246 */
247func plat_reset_handler
Andre Przywara98e48562020-03-12 14:20:04 +0000248 /* L2 cache setup only needed on RPi4 */
249 _plat_rpi_get_model
250 cmp w0, #4
251 b.ne 1f
252
Andre Przywara6d471e12019-07-09 11:25:57 +0100253 /* ------------------------------------------------
254 * Set L2 read/write cache latency:
255 * - L2 Data RAM latency: 3 cycles (0b010)
256 * - L2 Data RAM setup: 1 cycle (bit 5)
257 * ------------------------------------------------
258 */
259 mrs x0, CORTEX_A72_L2CTLR_EL1
260 mov x1, #0x22
261 orr x0, x0, x1
262 msr CORTEX_A72_L2CTLR_EL1, x0
263 isb
264
Andre Przywara98e48562020-03-12 14:20:04 +00002651:
Andre Przywara6d471e12019-07-09 11:25:57 +0100266 ret
267endfunc plat_reset_handler