1/* 2 * Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. 4 * Copyright (c) 2024, Altera Corporation. All rights reserved. 5 * 6 * SPDX-License-Identifier: BSD-3-Clause 7 */ 8 9#include <arch.h> 10#include <asm_macros.S> 11#include <cpu_macros.S> 12#include <platform_def.h> 13#include <el3_common_macros.S> 14 15 .globl plat_secondary_cold_boot_setup 16 .globl platform_is_primary_cpu 17 .globl plat_is_my_cpu_primary 18 .globl plat_my_core_pos 19 .globl plat_crash_console_init 20 .globl plat_crash_console_putc 21 .globl plat_crash_console_flush 22 .globl platform_mem_init 23 .globl plat_secondary_cpus_bl31_entry 24 25 .globl plat_get_my_entrypoint 26 27 /* ----------------------------------------------------- 28 * void plat_secondary_cold_boot_setup (void); 29 * 30 * This function performs any platform specific actions 31 * needed for a secondary cpu after a cold reset e.g 32 * mark the cpu's presence, mechanism to place it in a 33 * holding pen etc. 34 * ----------------------------------------------------- 35 */ 36func plat_secondary_cold_boot_setup 37 /* Wait until the it gets reset signal from rstmgr gets populated */ 38poll_mailbox: 39#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 40 mov_imm x0, PLAT_SEC_ENTRY 41 cbz x0, poll_mailbox 42 br x0 43#else 44 wfi 45 mov_imm x0, PLAT_SEC_ENTRY 46 ldr x1, [x0] 47 mov_imm x2, PLAT_CPUID_RELEASE 48 ldr x3, [x2] 49 mrs x4, mpidr_el1 50 and x4, x4, #0xff 51 cmp x3, x4 52 b.ne poll_mailbox 53 br x1 54#endif 55endfunc plat_secondary_cold_boot_setup 56 57#if ((PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10) || \ 58 (PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX) || \ 59 (PLATFORM_MODEL == PLAT_SOCFPGA_N5X)) 60 61func platform_is_primary_cpu 62 and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) 63 cmp x0, #PLAT_PRIMARY_CPU 64 cset x0, eq 65 ret 66endfunc platform_is_primary_cpu 67 68#else 69 70func platform_is_primary_cpu 71 and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) 72 cmp x0, #(PLAT_PRIMARY_CPU_A76) 73 b.eq primary_cpu 74 cmp x0, #(PLAT_PRIMARY_CPU_A55) 75 b.eq primary_cpu 76primary_cpu: 77 cset x0, eq 78 ret 79endfunc platform_is_primary_cpu 80 81#endif 82 83func plat_is_my_cpu_primary 84 mrs x0, mpidr_el1 85 b platform_is_primary_cpu 86endfunc plat_is_my_cpu_primary 87 88func plat_my_core_pos 89 mrs x0, mpidr_el1 90 and x1, x0, #MPIDR_CPU_MASK 91 and x0, x0, #MPIDR_CLUSTER_MASK 92#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 93 add x0, x1, x0, LSR #8 94#else 95 add x0, x1, x0, LSR #6 96#endif 97 ret 98endfunc plat_my_core_pos 99 100func warm_reset_req 101#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 102 /* Clear the markup before going for warm reset */ 103 bic x2, x2, #BS_REG_MAGIC_KEYS_MASK 104 /* Check if the address is 64 bit aligned or not */ 105 ldr x4, =L2_RESET_DONE_REG 106 tst x4, #ALIGN_CHECK_64BIT_MASK 107 b.ne unaligned_store 108 /* Device memory address is aligned, store the value directly */ 109 str x2, [x4] 110 b continue_warm_reset 111 112 /* Unaligned store, use byte by byte method to store */ 113unaligned_store: 114 strb w2, [x4] 115 lsr x2, x2, #8 116 add x4, x4, #1 117 strb w2, [x4] 118 lsr x2, x2, #8 119 add x4, x4, #1 120 strb w2, [x4] 121 lsr x2, x2, #8 122 add x4, x4, #1 123 strb w2, [x4] 124#else 125 /* Clear the markup before going for warm reset */ 126 bic x2, x2, #BS_REG_MAGIC_KEYS_MASK 127 str x2, [x4] 128#endif 129 130continue_warm_reset: 131 bl plat_is_my_cpu_primary 132 cbz x0, cpu_in_wfi 133 mov_imm x1, PLAT_SEC_ENTRY 134 str xzr, [x1] 135 mrs x1, rmr_el3 136 orr x1, x1, #0x02 137 msr rmr_el3, x1 138 isb 139 dsb sy 140cpu_in_wfi: 141 wfi 142 b cpu_in_wfi 143endfunc warm_reset_req 144 145#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 146func plat_get_my_entrypoint 147 ldr x4, =L2_RESET_DONE_REG 148 149 /* Check if the address is 64 bit aligned or not */ 150 tst x4, #ALIGN_CHECK_64BIT_MASK 151 b.ne unaligned_load 152 153 /* Device memory address is aligned, load the value directly */ 154 ldr x1, [x4] 155 b events_check 156 157 /* 158 * It is unaligned device memory access. Read only LSB 32 bits 159 * byte by byte and combine them to get the 32 bit value. 160 */ 161unaligned_load: 162 ldrb w1, [x4] 163 ldrb w2, [x4, #1] 164 ldrb w3, [x4, #2] 165 ldrb w4, [x4, #3] 166 orr x1, x1, x2, lsl #8 167 orr x1, x1, x3, lsl #16 168 orr x1, x1, x4, lsl #24 169 170events_check: 171 /* Keep a backup of the boot scratch register contents */ 172 mov x2, x1 173 174 /* Mask and get the required bits */ 175 and x1, x1, #BS_REG_MAGIC_KEYS_MASK 176 177 /* Check for warm reset request */ 178 ldr x5, =L2_RESET_DONE_STATUS 179 cmp x1, x5 180 b.eq warm_reset_req 181 182 /* Check for SMP secondary cores boot request */ 183 ldr x5, =SMP_SEC_CORE_BOOT_REQ 184 cmp x1, x5 185 b.eq smp_request 186 187 /* Otherwise it is a cold reset request */ 188 mov x0, #0 189 ret 190 191smp_request: 192 /* 193 * On the SMP boot request, return the address 'bl31_warm_entrypoint', 194 * which is passed to 'psci_setup' routine as part of BL31 195 * initialization. 196 */ 197 ldr x1, =PLAT_SEC_ENTRY 198 ldr x0, [x1] 199 ret 200endfunc plat_get_my_entrypoint 201#else 202func plat_get_my_entrypoint 203 ldr x4, =L2_RESET_DONE_REG 204 ldr x5, [x4] 205 206 /* Keep a backup of the boot scratch register contents */ 207 mov x2, x5 208 209 /* Mask and get only the required bits */ 210 and x5, x5, #BS_REG_MAGIC_KEYS_MASK 211 212 /* Check for warm reset request */ 213 ldr x1, =L2_RESET_DONE_STATUS 214 cmp x1, x5 215 b.eq warm_reset_req 216 mov_imm x1, PLAT_SEC_ENTRY 217 ldr x0, [x1] 218 ret 219endfunc plat_get_my_entrypoint 220#endif 221 222 /* --------------------------------------------- 223 * int plat_crash_console_init(void) 224 * Function to initialize the crash console 225 * without a C Runtime to print crash report. 226 * Clobber list : x0, x1, x2 227 * --------------------------------------------- 228 */ 229func plat_crash_console_init 230 mov_imm x0, CRASH_CONSOLE_BASE 231 mov_imm x1, PLAT_UART_CLOCK 232 mov_imm x2, PLAT_BAUDRATE 233 b console_16550_core_init 234endfunc plat_crash_console_init 235 236 /* --------------------------------------------- 237 * int plat_crash_console_putc(void) 238 * Function to print a character on the crash 239 * console without a C Runtime. 240 * Clobber list : x1, x2 241 * --------------------------------------------- 242 */ 243func plat_crash_console_putc 244 mov_imm x1, CRASH_CONSOLE_BASE 245 b console_16550_core_putc 246endfunc plat_crash_console_putc 247 248func plat_crash_console_flush 249 mov_imm x0, CRASH_CONSOLE_BASE 250 b console_16550_core_flush 251endfunc plat_crash_console_flush 252 253 254 /* -------------------------------------------------------- 255 * void platform_mem_init (void); 256 * 257 * Any memory init, relocation to be done before the 258 * platform boots. Called very early in the boot process. 259 * -------------------------------------------------------- 260 */ 261func platform_mem_init 262 mov x0, #0 263 ret 264endfunc platform_mem_init 265 266 /* -------------------------------------------------------- 267 * macro plat_secondary_cpus_bl31_entry; 268 * 269 * el3_entrypoint_common init param configuration. 270 * Called very early in the secondary cores boot process. 271 * -------------------------------------------------------- 272 */ 273func plat_secondary_cpus_bl31_entry 274 el3_entrypoint_common \ 275 _init_sctlr=0 \ 276 _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ 277 _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ 278 _init_memory=1 \ 279 _init_c_runtime=1 \ 280 _exception_vectors=runtime_exceptions \ 281 _pie_fixup_size=BL31_LIMIT - BL31_BASE 282endfunc plat_secondary_cpus_bl31_entry 283