1/* 2 * (C) Copyright 2013 3 * David Feng <fenghua@phytium.com.cn> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8#include <asm-offsets.h> 9#include <config.h> 10#include <linux/linkage.h> 11#include <asm/macro.h> 12#include <asm/armv8/mmu.h> 13 14/************************************************************************* 15 * 16 * Startup Code (reset vector) 17 * 18 *************************************************************************/ 19 20.globl _start 21_start: 22#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK 23/* 24 * Various SoCs need something special and SoC-specific up front in 25 * order to boot, allow them to set that in their boot0.h file and then 26 * use it here. 27 */ 28#include <asm/arch/boot0.h> 29#else 30 b reset 31#endif 32 33 .align 3 34 35.globl _TEXT_BASE 36_TEXT_BASE: 37 .quad CONFIG_SYS_TEXT_BASE 38 39/* 40 * These are defined in the linker script. 41 */ 42.globl _end_ofs 43_end_ofs: 44 .quad _end - _start 45 46.globl _bss_start_ofs 47_bss_start_ofs: 48 .quad __bss_start - _start 49 50.globl _bss_end_ofs 51_bss_end_ofs: 52 .quad __bss_end - _start 53 54reset: 55 /* Allow the board to save important registers */ 56 b save_boot_params 57.globl save_boot_params_ret 58save_boot_params_ret: 59 60#ifdef CONFIG_SYS_RESET_SCTRL 61 bl reset_sctrl 62#endif 63 /* 64 * Could be EL3/EL2/EL1, Initial State: 65 * Little Endian, MMU Disabled, i/dCache Disabled 66 */ 67 adr x0, vectors 68 switch_el x1, 3f, 2f, 1f 693: msr vbar_el3, x0 70 mrs x0, scr_el3 71 orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */ 72 msr scr_el3, x0 73 msr cptr_el3, xzr /* Enable FP/SIMD */ 74#ifdef COUNTER_FREQUENCY 75 ldr x0, =COUNTER_FREQUENCY 76 msr cntfrq_el0, x0 /* Initialize CNTFRQ */ 77#endif 78 b 0f 792: msr vbar_el2, x0 80 mov x0, #0x33ff 81 msr cptr_el2, x0 /* Enable FP/SIMD */ 82 b 0f 831: msr vbar_el1, x0 84 mov x0, #3 << 20 85 msr cpacr_el1, x0 /* Enable FP/SIMD */ 860: 87 88 /* 89 * Enable SMPEN bit for coherency. 90 * This register is not architectural but at the moment 91 * this bit should be set for A53/A57/A72. 92 */ 93#ifdef CONFIG_ARMV8_SET_SMPEN 94 switch_el x1, 3f, 1f, 1f 953: 96 mrs x0, S3_1_c15_c2_1 /* cpuectlr_el1 */ 97 orr x0, x0, #0x40 98 msr S3_1_c15_c2_1, x0 991: 100#endif 101 102 /* Apply ARM core specific erratas */ 103 bl apply_core_errata 104 105 /* 106 * Cache/BPB/TLB Invalidate 107 * i-cache is invalidated before enabled in icache_enable() 108 * tlb is invalidated before mmu is enabled in dcache_enable() 109 * d-cache is invalidated before enabled in dcache_enable() 110 */ 111 112 /* Processor specific initialization */ 113 bl lowlevel_init 114 115#if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD) 116 branch_if_master x0, x1, master_cpu 117 b spin_table_secondary_jump 118 /* never return */ 119#elif defined(CONFIG_ARMV8_MULTIENTRY) 120 branch_if_master x0, x1, master_cpu 121 122 /* 123 * Slave CPUs 124 */ 125slave_cpu: 126 wfe 127 ldr x1, =CPU_RELEASE_ADDR 128 ldr x0, [x1] 129 cbz x0, slave_cpu 130 br x0 /* branch to the given address */ 131#endif /* CONFIG_ARMV8_MULTIENTRY */ 132master_cpu: 133 bl _main 134 135#ifdef CONFIG_SYS_RESET_SCTRL 136reset_sctrl: 137 switch_el x1, 3f, 2f, 1f 1383: 139 mrs x0, sctlr_el3 140 b 0f 1412: 142 mrs x0, sctlr_el2 143 b 0f 1441: 145 mrs x0, sctlr_el1 146 1470: 148 ldr x1, =0xfdfffffa 149 and x0, x0, x1 150 151 switch_el x1, 6f, 5f, 4f 1526: 153 msr sctlr_el3, x0 154 b 7f 1555: 156 msr sctlr_el2, x0 157 b 7f 1584: 159 msr sctlr_el1, x0 160 1617: 162 dsb sy 163 isb 164 b __asm_invalidate_tlb_all 165 ret 166#endif 167 168/*-----------------------------------------------------------------------*/ 169 170WEAK(apply_core_errata) 171 172 mov x29, lr /* Save LR */ 173 /* For now, we support Cortex-A57 specific errata only */ 174 175 /* Check if we are running on a Cortex-A57 core */ 176 branch_if_a57_core x0, apply_a57_core_errata 1770: 178 mov lr, x29 /* Restore LR */ 179 ret 180 181apply_a57_core_errata: 182 183#ifdef CONFIG_ARM_ERRATA_828024 184 mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ 185 /* Disable non-allocate hint of w-b-n-a memory type */ 186 orr x0, x0, #1 << 49 187 /* Disable write streaming no L1-allocate threshold */ 188 orr x0, x0, #3 << 25 189 /* Disable write streaming no-allocate threshold */ 190 orr x0, x0, #3 << 27 191 msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ 192#endif 193 194#ifdef CONFIG_ARM_ERRATA_826974 195 mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ 196 /* Disable speculative load execution ahead of a DMB */ 197 orr x0, x0, #1 << 59 198 msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ 199#endif 200 201#ifdef CONFIG_ARM_ERRATA_833471 202 mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ 203 /* FPSCR write flush. 204 * Note that in some cases where a flush is unnecessary this 205 could impact performance. */ 206 orr x0, x0, #1 << 38 207 msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ 208#endif 209 210#ifdef CONFIG_ARM_ERRATA_829520 211 mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ 212 /* Disable Indirect Predictor bit will prevent this erratum 213 from occurring 214 * Note that in some cases where a flush is unnecessary this 215 could impact performance. */ 216 orr x0, x0, #1 << 4 217 msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ 218#endif 219 220#ifdef CONFIG_ARM_ERRATA_833069 221 mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ 222 /* Disable Enable Invalidates of BTB bit */ 223 and x0, x0, #0xE 224 msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ 225#endif 226 b 0b 227ENDPROC(apply_core_errata) 228 229/*-----------------------------------------------------------------------*/ 230 231WEAK(lowlevel_init) 232 mov x29, lr /* Save LR */ 233 234#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) 235 branch_if_slave x0, 1f 236 ldr x0, =GICD_BASE 237 bl gic_init_secure 2381: 239#if defined(CONFIG_GICV3) 240 ldr x0, =GICR_BASE 241 bl gic_init_secure_percpu 242#elif defined(CONFIG_GICV2) 243 ldr x0, =GICD_BASE 244 ldr x1, =GICC_BASE 245 bl gic_init_secure_percpu 246#endif 247#endif 248 249#ifdef CONFIG_ARMV8_MULTIENTRY 250 branch_if_master x0, x1, 2f 251 252 /* 253 * Slave should wait for master clearing spin table. 254 * This sync prevent salves observing incorrect 255 * value of spin table and jumping to wrong place. 256 */ 257#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) 258#ifdef CONFIG_GICV2 259 ldr x0, =GICC_BASE 260#endif 261 bl gic_wait_for_interrupt 262#endif 263 264 /* 265 * All slaves will enter EL2 and optionally EL1. 266 */ 267 adr x4, lowlevel_in_el2 268 ldr x5, =ES_TO_AARCH64 269 bl armv8_switch_to_el2 270 271lowlevel_in_el2: 272#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 273 adr x4, lowlevel_in_el1 274 ldr x5, =ES_TO_AARCH64 275 bl armv8_switch_to_el1 276 277lowlevel_in_el1: 278#endif 279 280#endif /* CONFIG_ARMV8_MULTIENTRY */ 281 2822: 283 mov lr, x29 /* Restore LR */ 284 ret 285ENDPROC(lowlevel_init) 286 287WEAK(smp_kick_all_cpus) 288 /* Kick secondary cpus up by SGI 0 interrupt */ 289#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) 290 ldr x0, =GICD_BASE 291 b gic_kick_secondary_cpus 292#endif 293 ret 294ENDPROC(smp_kick_all_cpus) 295 296/*-----------------------------------------------------------------------*/ 297 298ENTRY(c_runtime_cpu_setup) 299 /* Relocate vBAR */ 300 adr x0, vectors 301 switch_el x1, 3f, 2f, 1f 3023: msr vbar_el3, x0 303 b 0f 3042: msr vbar_el2, x0 305 b 0f 3061: msr vbar_el1, x0 3070: 308 309 ret 310ENDPROC(c_runtime_cpu_setup) 311 312WEAK(save_boot_params) 313 b save_boot_params_ret /* back to my caller */ 314ENDPROC(save_boot_params) 315