1/* 2 * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved. 3 * Copyright (c) 2015-2023, Renesas Electronics Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8#include <arch.h> 9#include <asm_macros.S> 10#include <common/bl_common.h> 11#include <common/runtime_svc.h> 12#include <cortex_a57.h> 13#include <platform_def.h> 14 15#include "rcar_def.h" 16 17 .globl plat_get_my_entrypoint 18 .extern plat_set_my_stack 19 .globl platform_mem_init 20 21 .globl plat_crash_console_init 22 .globl plat_crash_console_putc 23 .globl plat_crash_console_flush 24 .globl plat_invalidate_icache 25 .globl plat_report_exception 26 .globl plat_secondary_reset 27 .globl plat_reset_handler 28 .globl plat_my_core_pos 29 .extern rcar_log_init 30 31 .extern console_rcar_init 32 .extern console_rcar_putc 33 .extern console_rcar_flush 34 35#if IMAGE_BL2 36 #define INT_ID_MASK (0x3ff) 37 .extern bl2_interrupt_error_type 38 .extern bl2_interrupt_error_id 39 .globl bl2_enter_bl31 40 .extern gicv2_acknowledge_interrupt 41 .extern rcar_swdt_exec 42#endif 43 44 /* ----------------------------------------------------- 45 * void platform_get_core_pos (mpidr) 46 * ----------------------------------------------------- 47 */ 48func platform_get_core_pos 49 and x1, x0, #MPIDR_CPU_MASK 50 and x0, x0, #MPIDR_CLUSTER_MASK 51 add x0, x1, x0, LSR #6 52 ret 53endfunc platform_get_core_pos 54 55 /* ----------------------------------------------------- 56 * void platform_my_core_pos 57 * ----------------------------------------------------- 58 */ 59func plat_my_core_pos 60 mrs x0, mpidr_el1 61 b platform_get_core_pos 62endfunc plat_my_core_pos 63 64 /* ----------------------------------------------------- 65 * void platform_get_my_entrypoint (unsigned int mpid); 66 * 67 * Main job of this routine is to distinguish between 68 * a cold and warm boot. 69 * On a cold boot the secondaries first wait for the 70 * platform to be initialized after which they are 71 * hotplugged in. The primary proceeds to perform the 72 * platform initialization. 73 * On a warm boot, each cpu jumps to the address in its 74 * mailbox. 75 * 76 * TODO: Not a good idea to save lr in a temp reg 77 * ----------------------------------------------------- 78 */ 79func plat_get_my_entrypoint 80 mrs x0, mpidr_el1 81 mov x9, x30 /* lr */ 82 83#if defined(IMAGE_BL2) 84 /* always cold boot on bl2 */ 85 mov x0, #0 86 ret x9 87#else 88 ldr x1, =BOOT_KIND_BASE 89 ldr x21, [x1] 90 91 /* Check the reset info */ 92 and x1, x21, #0x000c 93 cmp x1, #0x0008 94 beq el3_panic 95 cmp x1, #0x000c 96 beq el3_panic 97 98 /* Check the boot kind */ 99 and x1, x21, #0x0003 100 cmp x1, #0x0002 101 beq el3_panic 102 cmp x1, #0x0003 103 beq el3_panic 104 105 /* warm boot or cold boot */ 106 and x1, x21, #1 107 cmp x1, #0 108 bne warm_reset 109 110 /* Cold boot */ 111 mov x0, #0 112 b exit 113 114warm_reset: 115 /* -------------------------------------------------------------------- 116 * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out 117 * of the caches after every update using normal memory so its safe to 118 * read it here with SO attributes 119 * --------------------------------------------------------------------- 120 */ 121 ldr x10, =MBOX_BASE 122 bl platform_get_core_pos 123 lsl x0, x0, #CACHE_WRITEBACK_SHIFT 124 ldr x0, [x10, x0] 125 cbz x0, _panic 126exit: 127 ret x9 128_panic: 129 b el3_panic 130#endif 131 132endfunc plat_get_my_entrypoint 133 134 /* --------------------------------------------- 135 * plat_secondary_reset 136 * 137 * --------------------------------------------- 138 */ 139func plat_secondary_reset 140 mrs x0, sctlr_el3 141 bic x0, x0, #SCTLR_EE_BIT 142 msr sctlr_el3, x0 143 isb 144 145 mrs x0, cptr_el3 146 bic w0, w0, #TCPAC_BIT 147 bic w0, w0, #TTA_BIT 148 bic w0, w0, #TFP_BIT 149 msr cptr_el3, x0 150 151 mov_imm x0, PARAMS_BASE 152 mov_imm x2, BL31_BASE 153 ldr x3, =BOOT_KIND_BASE 154 mov x1, #0x1 155 str x1, [x3] 156 br x2 /* jump to BL31 */ 157 nop 158 nop 159 nop 160endfunc plat_secondary_reset 161 162 /* --------------------------------------------- 163 * plat_enter_bl31 164 * 165 * --------------------------------------------- 166 */ 167func bl2_enter_bl31 168 mov x20, x0 169 /* 170 * MMU needs to be disabled because both BL2 and BL31 execute 171 * in EL3, and therefore share the same address space. 172 * BL31 will initialize the address space according to its 173 * own requirement. 174 */ 175 /* Disable mmu and data cache */ 176 bl disable_mmu_el3 177#if RCAR_BL2_DCACHE == 1 178 /* Data cache clean and invalidate */ 179 mov x0, #DCCISW 180 bl dcsw_op_all 181#endif /* RCAR_BL2_DCACHE == 1 */ 182 /* TLB invalidate all, EL3 */ 183 tlbi alle3 184 185 bl disable_mmu_icache_el3 186 /* Invalidate instruction cache */ 187 ic iallu 188 dsb sy 189 isb 190 ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] 191 msr elr_el3, x0 192 msr spsr_el3, x1 193 exception_return 194endfunc bl2_enter_bl31 195 196 /* ----------------------------------------------------- 197 * void platform_mem_init (void); 198 * 199 * Zero out the mailbox registers in the shared memory 200 * and set the rcar_boot_kind_flag. 201 * The mmu is turned off right now and only the primary can 202 * ever execute this code. Secondaries will read the 203 * mailboxes using SO accesses. 204 * ----------------------------------------------------- 205 */ 206func platform_mem_init 207#if !IMAGE_BL2 208 ldr x0, =MBOX_BASE 209 mov w1, #PLATFORM_CORE_COUNT 210loop: 211 str xzr, [x0], #CACHE_WRITEBACK_GRANULE 212 subs w1, w1, #1 213 b.gt loop 214#endif 215 ret 216endfunc platform_mem_init 217 218 /* --------------------------------------------- 219 * void plat_report_exception(unsigned int type) 220 * Function to report an unhandled exception 221 * with platform-specific means. 222 * --------------------------------------------- 223 */ 224func plat_report_exception 225 /* Switch to SP_EL0 */ 226 msr spsel, #0 227#if IMAGE_BL2 228 mov w1, #FIQ_SP_EL0 229 cmp w0, w1 230 beq rep_exec_fiq_elx 231 b rep_exec_panic_type 232rep_exec_fiq_elx: 233 bl gicv2_acknowledge_interrupt 234 mov x2, #INT_ID_MASK 235 and x0, x0, x2 236 mov x1, #ARM_IRQ_SEC_WDT 237 cmp x0, x1 238 bne rep_exec_panic_id 239 mrs x0, ELR_EL3 240 b rcar_swdt_exec 241rep_exec_panic_type: 242 /* x0 is interrupt TYPE */ 243 b bl2_interrupt_error_type 244rep_exec_panic_id: 245 /* x0 is interrupt ID */ 246 b bl2_interrupt_error_id 247rep_exec_end: 248#endif 249 ret 250endfunc plat_report_exception 251 252 /* --------------------------------------------- 253 * int plat_crash_console_init(void) 254 * Function to initialize log area 255 * --------------------------------------------- 256 */ 257func plat_crash_console_init 258#if IMAGE_BL2 259 mov x0, #0 260#else 261 mov x1, sp 262 mov_imm x2, RCAR_CRASH_STACK 263 mov sp, x2 264 str x1, [sp, #-16]! 265 str x30, [sp, #-16]! 266 bl console_rcar_init 267 ldr x30, [sp], #16 268 ldr x1, [sp], #16 269 mov sp, x1 270#endif 271 ret 272endfunc plat_crash_console_init 273 274 /* --------------------------------------------- 275 * int plat_crash_console_putc(int c) 276 * Function to store a character to log area 277 * --------------------------------------------- 278 */ 279func plat_crash_console_putc 280 mov x1, sp 281 mov_imm x2, RCAR_CRASH_STACK 282 mov sp, x2 283 str x1, [sp, #-16]! 284 str x30, [sp, #-16]! 285 str x3, [sp, #-16]! 286 str x4, [sp, #-16]! 287 str x5, [sp, #-16]! 288 str x6, [sp, #-16]! 289 str x7, [sp, #-16]! 290 bl console_rcar_putc 291 ldr x7, [sp], #16 292 ldr x6, [sp], #16 293 ldr x5, [sp], #16 294 ldr x4, [sp], #16 295 ldr x3, [sp], #16 296 ldr x30, [sp], #16 297 ldr x1, [sp], #16 298 mov sp, x1 299 ret 300endfunc plat_crash_console_putc 301 302 /* --------------------------------------------- 303 * void plat_crash_console_flush() 304 * --------------------------------------------- 305 */ 306func plat_crash_console_flush 307 b console_rcar_flush 308endfunc plat_crash_console_flush 309 310 /* -------------------------------------------------------------------- 311 * void plat_reset_handler(void); 312 * 313 * Before adding code in this function, refer to the guidelines in 314 * docs/firmware-design.md to determine whether the code should reside 315 * within the FIRST_RESET_HANDLER_CALL block or not. 316 * 317 * For R-Car H3: 318 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 319 * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57 320 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57 321 * For R-Car M3/M3N: 322 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 323 * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57 324 * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57 325 * 326 * -------------------------------------------------------------------- 327 */ 328func plat_reset_handler 329 /* 330 * On R-Car H3 : x2 := 0 331 * On R-Car M3/M3N: x2 := 1 332 */ 333 /* read PRR */ 334 ldr x0, =0xFFF00044 335 ldr w0, [x0] 336 ubfx w0, w0, 8, 8 337 /* H3? */ 338 cmp w0, #0x4F 339 b.eq RCARH3 340 /* set R-Car M3/M3N */ 341 mov x2, #1 342 b CHK_A5x 343RCARH3: 344 /* set R-Car H3 */ 345 mov x2, #0 346 /* -------------------------------------------------------------------- 347 * Determine whether this code is executed on a Cortex-A53 or on a 348 * Cortex-A57 core. 349 * -------------------------------------------------------------------- 350 */ 351CHK_A5x: 352 mrs x0, midr_el1 353 ubfx x1, x0, MIDR_PN_SHIFT, #12 354 cmp w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK) 355 b.eq A57 356 ret 357A57: 358 /* Get data from CORTEX_A57_L2CTLR_EL1 */ 359 mrs x0, CORTEX_A57_L2CTLR_EL1 360 /* 361 * On R-Car H3/M3/M3N 362 * 363 * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1 364 * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1 365 * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1 366 */ 367 /* clear bit of L2 RAM */ 368 /* ~(0x1e7) -> x1 */ 369 mov x1, #0x1e7 370 neg x1, x1 371 /* clear bit of L2 RAM -> x0 */ 372 and x0, x0, x1 373 /* L2 Tag RAM latency (3 cycles) */ 374 orr x0, x0, #0x2 << 6 375 /* If M3/M3N then L2 RAM setup is 0 */ 376 cbnz x2, M3_L2 377 /* L2 Data RAM setup (1 cycle) */ 378 orr x0, x0, #0x1 << 5 379M3_L2: 380 /* L2 Data RAM latency (4 cycles) */ 381 orr x0, x0, #0x3 382 /* Store data to L2CTLR_EL1 */ 383 msr CORTEX_A57_L2CTLR_EL1, x0 384apply_l2_ram_latencies: 385 ret 386endfunc plat_reset_handler 387 388 /* --------------------------------------------- 389 * void plat_invalidate_icache(void) 390 * Instruction Cache Invalidate All to PoU 391 * --------------------------------------------- 392 */ 393func plat_invalidate_icache 394 ic iallu 395 396 ret 397endfunc plat_invalidate_icache 398