1/* 2 * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. 3 * 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 13 .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 23 .globl plat_rpi_get_model 24 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. 30 * 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. 36 * ----------------------------------------------------- 37 */ 38func plat_my_core_pos 39 mrs x0, mpidr_el1 40 tst x0, #MPIDR_MT_MASK 41 lsr x1, x0, #MPIDR_AFFINITY_BITS 42 csel x0, x1, x0, ne 43 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) 69 cmp x0, #RPI_PRIMARY_CPU 70 cset w0, eq 71 ret 72endfunc plat_is_my_cpu_primary 73 74 /* ----------------------------------------------------- 75 * void plat_wait_for_warm_boot (void); 76 * 77 * This function performs any platform specific actions 78 * needed for a CPU to be put into holding pen to wait 79 * for a warm boot request. 80 * The function will never return. 81 * ----------------------------------------------------- 82 */ 83func 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 */ 88 bl plat_my_core_pos 89 lsl x0, x0, #3 90 mov_imm x2, PLAT_RPI3_TM_HOLD_BASE 91 add x0, x0, x2 92 /* 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 111endfunc 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 124endfunc 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 138 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 156endfunc 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 176 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 182 mov x1, xzr 183 mov x2, xzr 184 b console_16550_core_init 185#endif 186endfunc 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 196 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 200 b console_16550_core_putc 201#endif 202endfunc plat_crash_console_putc 203 204 /* --------------------------------------------- 205 * void plat_crash_console_flush() 206 * Function to force a write of all buffered 207 * data that hasn't been output. 208 * Out : void. 209 * Clobber list : x0, x1 210 * --------------------------------------------- 211 */ 212func plat_crash_console_flush 213 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 217 b console_16550_core_flush 218#endif 219endfunc plat_crash_console_flush 220 221 /* --------------------------------------------- 222 * 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 /* --------------------------------------------- 244 * void plat_reset_handler(void); 245 * --------------------------------------------- 246 */ 247func plat_reset_handler 248 /* L2 cache setup only needed on RPi4 */ 249 _plat_rpi_get_model 250 cmp w0, #4 251 b.ne 1f 252 253 /* ------------------------------------------------ 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 2651: 266 ret 267endfunc plat_reset_handler 268