1/* 2 * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7#include <arch.h> 8#include <asm_macros.S> 9#include <assert_macros.S> 10#include <cpu_macros.S> 11#include <cortex_a53.h> 12#include <cortex_a57.h> 13#include <platform_def.h> 14#include <tegra_def.h> 15#include <tegra_platform.h> 16 17#define MIDR_PN_CORTEX_A57 0xD07 18 19/******************************************************************************* 20 * Implementation defined ACTLR_EL3 bit definitions 21 ******************************************************************************/ 22#define ACTLR_ELx_L2ACTLR_BIT (U(1) << 6) 23#define ACTLR_ELx_L2ECTLR_BIT (U(1) << 5) 24#define ACTLR_ELx_L2CTLR_BIT (U(1) << 4) 25#define ACTLR_ELx_CPUECTLR_BIT (U(1) << 1) 26#define ACTLR_ELx_CPUACTLR_BIT (U(1) << 0) 27#define ACTLR_ELx_ENABLE_ALL_ACCESS (ACTLR_ELx_L2ACTLR_BIT | \ 28 ACTLR_ELx_L2ECTLR_BIT | \ 29 ACTLR_ELx_L2CTLR_BIT | \ 30 ACTLR_ELx_CPUECTLR_BIT | \ 31 ACTLR_ELx_CPUACTLR_BIT) 32 33 /* Global functions */ 34 .globl plat_is_my_cpu_primary 35 .globl plat_my_core_pos 36 .globl plat_get_my_entrypoint 37 .globl plat_secondary_cold_boot_setup 38 .globl platform_mem_init 39 .globl plat_crash_console_init 40 .globl plat_crash_console_putc 41 .globl plat_crash_console_flush 42 .weak plat_core_pos_by_mpidr 43 .globl tegra_secure_entrypoint 44 .globl plat_reset_handler 45 46 /* Global variables */ 47 .globl tegra_sec_entry_point 48 .globl ns_image_entrypoint 49 .globl tegra_bl31_phys_base 50 .globl tegra_console_base 51 52 /* --------------------- 53 * Common CPU init code 54 * --------------------- 55 */ 56.macro cpu_init_common 57 58 /* ------------------------------------------------ 59 * We enable procesor retention, L2/CPUECTLR NS 60 * access and ECC/Parity protection for A57 CPUs 61 * ------------------------------------------------ 62 */ 63 mrs x0, midr_el1 64 mov x1, #(MIDR_PN_MASK << MIDR_PN_SHIFT) 65 and x0, x0, x1 66 lsr x0, x0, #MIDR_PN_SHIFT 67 cmp x0, #MIDR_PN_CORTEX_A57 68 b.ne 1f 69 70 /* --------------------------- 71 * Enable processor retention 72 * --------------------------- 73 */ 74 mrs x0, CORTEX_A57_L2ECTLR_EL1 75 mov x1, #RETENTION_ENTRY_TICKS_512 76 bic x0, x0, #CORTEX_A57_L2ECTLR_RET_CTRL_MASK 77 orr x0, x0, x1 78 msr CORTEX_A57_L2ECTLR_EL1, x0 79 isb 80 81 mrs x0, CORTEX_A57_ECTLR_EL1 82 mov x1, #RETENTION_ENTRY_TICKS_512 83 bic x0, x0, #CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK 84 orr x0, x0, x1 85 msr CORTEX_A57_ECTLR_EL1, x0 86 isb 87 88 /* ------------------------------------------------------- 89 * Enable L2 and CPU ECTLR RW access from non-secure world 90 * ------------------------------------------------------- 91 */ 92 mrs x0, actlr_el3 93 mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS 94 orr x0, x0, x1 95 msr actlr_el3, x0 96 mrs x0, actlr_el2 97 mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS 98 orr x0, x0, x1 99 msr actlr_el2, x0 100 isb 101 102 /* -------------------------------- 103 * Enable the cycle count register 104 * -------------------------------- 105 */ 1061: mrs x0, pmcr_el0 107 ubfx x0, x0, #11, #5 // read PMCR.N field 108 mov x1, #1 109 lsl x0, x1, x0 110 sub x0, x0, #1 // mask of event counters 111 orr x0, x0, #0x80000000 // disable overflow intrs 112 msr pmintenclr_el1, x0 113 msr pmuserenr_el0, x1 // enable user mode access 114 115 /* ---------------------------------------------------------------- 116 * Allow non-privileged access to CNTVCT: Set CNTKCTL (Kernel Count 117 * register), bit 1 (EL0VCTEN) to enable access to CNTVCT/CNTFRQ 118 * registers from EL0. 119 * ---------------------------------------------------------------- 120 */ 121 mrs x0, cntkctl_el1 122 orr x0, x0, #EL0VCTEN_BIT 123 msr cntkctl_el1, x0 124.endm 125 126 /* ----------------------------------------------------- 127 * unsigned int plat_is_my_cpu_primary(void); 128 * 129 * This function checks if this is the Primary CPU 130 * ----------------------------------------------------- 131 */ 132func plat_is_my_cpu_primary 133 mrs x0, mpidr_el1 134 and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) 135 cmp x0, #TEGRA_PRIMARY_CPU 136 cset x0, eq 137 ret 138endfunc plat_is_my_cpu_primary 139 140 /* ---------------------------------------------------------- 141 * unsigned int plat_my_core_pos(void); 142 * 143 * result: CorePos = CoreId + (ClusterId * cpus per cluster) 144 * Registers clobbered: x0, x8 145 * ---------------------------------------------------------- 146 */ 147func plat_my_core_pos 148 mov x8, x30 149 mrs x0, mpidr_el1 150 bl plat_core_pos_by_mpidr 151 ret x8 152endfunc plat_my_core_pos 153 154 /* ----------------------------------------------------- 155 * unsigned long plat_get_my_entrypoint (void); 156 * 157 * Main job of this routine is to distinguish between 158 * a cold and warm boot. If the tegra_sec_entry_point for 159 * this CPU is present, then it's a warm boot. 160 * 161 * ----------------------------------------------------- 162 */ 163func plat_get_my_entrypoint 164 adr x1, tegra_sec_entry_point 165 ldr x0, [x1] 166 ret 167endfunc plat_get_my_entrypoint 168 169 /* ----------------------------------------------------- 170 * void plat_secondary_cold_boot_setup (void); 171 * 172 * This function performs any platform specific actions 173 * needed for a secondary cpu after a cold reset. Right 174 * now this is a stub function. 175 * ----------------------------------------------------- 176 */ 177func plat_secondary_cold_boot_setup 178 mov x0, #0 179 ret 180endfunc plat_secondary_cold_boot_setup 181 182 /* -------------------------------------------------------- 183 * void platform_mem_init (void); 184 * 185 * Any memory init, relocation to be done before the 186 * platform boots. Called very early in the boot process. 187 * -------------------------------------------------------- 188 */ 189func platform_mem_init 190 mov x0, #0 191 ret 192endfunc platform_mem_init 193 194 /* --------------------------------------------------- 195 * Function to handle a platform reset and store 196 * input parameters passed by BL2. 197 * --------------------------------------------------- 198 */ 199func plat_reset_handler 200 201 /* ---------------------------------------------------- 202 * Verify if we are running from BL31_BASE address 203 * ---------------------------------------------------- 204 */ 205 adr x18, bl31_entrypoint 206 mov x17, #BL31_BASE 207 cmp x18, x17 208 b.eq 1f 209 210 /* ---------------------------------------------------- 211 * Copy the entire BL31 code to BL31_BASE if we are not 212 * running from it already 213 * ---------------------------------------------------- 214 */ 215 mov x0, x17 216 mov x1, x18 217 mov x2, #BL31_SIZE 218_loop16: 219 cmp x2, #16 220 b.lo _loop1 221 ldp x3, x4, [x1], #16 222 stp x3, x4, [x0], #16 223 sub x2, x2, #16 224 b _loop16 225 /* copy byte per byte */ 226_loop1: 227 cbz x2, _end 228 ldrb w3, [x1], #1 229 strb w3, [x0], #1 230 subs x2, x2, #1 231 b.ne _loop1 232 233 /* ---------------------------------------------------- 234 * Jump to BL31_BASE and start execution again 235 * ---------------------------------------------------- 236 */ 237_end: mov x0, x20 238 mov x1, x21 239 br x17 2401: 241 242 /* ----------------------------------- 243 * derive and save the phys_base addr 244 * ----------------------------------- 245 */ 246 adr x17, tegra_bl31_phys_base 247 ldr x18, [x17] 248 cbnz x18, 1f 249 adr x18, bl31_entrypoint 250 str x18, [x17] 251 2521: cpu_init_common 253 254 ret 255endfunc plat_reset_handler 256 257 /* ------------------------------------------------------ 258 * int32_t plat_core_pos_by_mpidr(u_register_t mpidr) 259 * 260 * This function implements a part of the critical 261 * interface between the psci generic layer and the 262 * platform that allows the former to query the platform 263 * to convert an MPIDR to a unique linear index. An error 264 * code (-1) is returned in case the MPIDR is invalid. 265 * 266 * Clobbers: x0-x3 267 * ------------------------------------------------------ 268 */ 269func plat_core_pos_by_mpidr 270 lsr x1, x0, #MPIDR_AFF0_SHIFT 271 and x1, x1, #MPIDR_AFFLVL_MASK /* core id */ 272 lsr x2, x0, #MPIDR_AFF1_SHIFT 273 and x2, x2, #MPIDR_AFFLVL_MASK /* cluster id */ 274 275 /* core_id >= PLATFORM_MAX_CPUS_PER_CLUSTER */ 276 mov x0, #-1 277 cmp x1, #(PLATFORM_MAX_CPUS_PER_CLUSTER - 1) 278 b.gt 1f 279 280 /* cluster_id >= PLATFORM_CLUSTER_COUNT */ 281 cmp x2, #(PLATFORM_CLUSTER_COUNT - 1) 282 b.gt 1f 283 284 /* CorePos = CoreId + (ClusterId * cpus per cluster) */ 285 mov x3, #PLATFORM_MAX_CPUS_PER_CLUSTER 286 mul x3, x3, x2 287 add x0, x1, x3 288 2891: 290 ret 291endfunc plat_core_pos_by_mpidr 292 293 /* ---------------------------------------- 294 * Secure entrypoint function for CPU boot 295 * ---------------------------------------- 296 */ 297func tegra_secure_entrypoint _align=6 298 299#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT 300 301 /* -------------------------------------------------------- 302 * Skip the invalidate BTB workaround for Tegra210B01 SKUs. 303 * -------------------------------------------------------- 304 */ 305 mov x0, #TEGRA_MISC_BASE 306 add x0, x0, #HARDWARE_REVISION_OFFSET 307 ldr w1, [x0] 308 lsr w1, w1, #CHIP_ID_SHIFT 309 and w1, w1, #CHIP_ID_MASK 310 cmp w1, #TEGRA_CHIPID_TEGRA21 /* T210? */ 311 b.ne 2f 312 ldr w1, [x0] 313 lsr w1, w1, #MAJOR_VERSION_SHIFT 314 and w1, w1, #MAJOR_VERSION_MASK 315 cmp w1, #0x02 /* T210 B01? */ 316 b.eq 2f 317 318 /* ------------------------------------------------------- 319 * Invalidate BTB along with I$ to remove any stale 320 * entries from the branch predictor array. 321 * ------------------------------------------------------- 322 */ 323 mrs x0, CORTEX_A57_CPUACTLR_EL1 324 orr x0, x0, #1 325 msr CORTEX_A57_CPUACTLR_EL1, x0 /* invalidate BTB and I$ together */ 326 dsb sy 327 isb 328 ic iallu /* actual invalidate */ 329 dsb sy 330 isb 331 332 mrs x0, CORTEX_A57_CPUACTLR_EL1 333 bic x0, x0, #1 334 msr CORTEX_A57_CPUACTLR_EL1, X0 /* restore original CPUACTLR_EL1 */ 335 dsb sy 336 isb 337 338 .rept 7 339 nop /* wait */ 340 .endr 341 342 /* ----------------------------------------------- 343 * Extract OSLK bit and check if it is '1'. This 344 * bit remains '0' for A53 on warm-resets. If '1', 345 * turn off regional clock gating and request warm 346 * reset. 347 * ----------------------------------------------- 348 */ 349 mrs x0, oslsr_el1 350 and x0, x0, #2 351 mrs x1, mpidr_el1 352 bics xzr, x0, x1, lsr #7 /* 0 = slow cluster or warm reset */ 353 b.eq restore_oslock 354 mov x0, xzr 355 msr oslar_el1, x0 /* os lock stays 0 across warm reset */ 356 mov x3, #3 357 movz x4, #0x8000, lsl #48 358 msr CORTEX_A57_CPUACTLR_EL1, x4 /* turn off RCG */ 359 isb 360 msr rmr_el3, x3 /* request warm reset */ 361 isb 362 dsb sy 3631: wfi 364 b 1b 365 366 /* -------------------------------------------------- 367 * These nops are here so that speculative execution 368 * won't harm us before we are done with warm reset. 369 * -------------------------------------------------- 370 */ 371 .rept 65 372 nop 373 .endr 3742: 375 /* -------------------------------------------------- 376 * Do not insert instructions here 377 * -------------------------------------------------- 378 */ 379#endif 380 381 /* -------------------------------------------------- 382 * Restore OS Lock bit 383 * -------------------------------------------------- 384 */ 385restore_oslock: 386 mov x0, #1 387 msr oslar_el1, x0 388 389 /* -------------------------------------------------- 390 * Get secure world's entry point and jump to it 391 * -------------------------------------------------- 392 */ 393 bl plat_get_my_entrypoint 394 br x0 395endfunc tegra_secure_entrypoint 396 397 .data 398 .align 3 399 400 /* -------------------------------------------------- 401 * CPU Secure entry point - resume from suspend 402 * -------------------------------------------------- 403 */ 404tegra_sec_entry_point: 405 .quad 0 406 407 /* -------------------------------------------------- 408 * NS world's cold boot entry point 409 * -------------------------------------------------- 410 */ 411ns_image_entrypoint: 412 .quad 0 413 414 /* -------------------------------------------------- 415 * BL31's physical base address 416 * -------------------------------------------------- 417 */ 418tegra_bl31_phys_base: 419 .quad 0 420 421 /* -------------------------------------------------- 422 * UART controller base for console init 423 * -------------------------------------------------- 424 */ 425tegra_console_base: 426 .quad 0 427