1/* 2 * armboot - Startup Code for ARM720 CPU-core 3 * 4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> 5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10#include <asm-offsets.h> 11#include <config.h> 12#include <version.h> 13#include <asm/hardware.h> 14 15/* 16 ************************************************************************* 17 * 18 * Jump vector table as in table 3.1 in [1] 19 * 20 ************************************************************************* 21 */ 22 23 24.globl _start 25_start: b reset 26 ldr pc, _undefined_instruction 27 ldr pc, _software_interrupt 28 ldr pc, _prefetch_abort 29 ldr pc, _data_abort 30 ldr pc, _not_used 31 ldr pc, _irq 32 ldr pc, _fiq 33 34#ifdef CONFIG_SPL_BUILD 35_undefined_instruction: .word _undefined_instruction 36_software_interrupt: .word _software_interrupt 37_prefetch_abort: .word _prefetch_abort 38_data_abort: .word _data_abort 39_not_used: .word _not_used 40_irq: .word _irq 41_fiq: .word _fiq 42_pad: .word 0x12345678 /* now 16*4=64 */ 43#else 44_undefined_instruction: .word undefined_instruction 45_software_interrupt: .word software_interrupt 46_prefetch_abort: .word prefetch_abort 47_data_abort: .word data_abort 48_not_used: .word not_used 49_irq: .word irq 50_fiq: .word fiq 51_pad: .word 0x12345678 /* now 16*4=64 */ 52#endif /* CONFIG_SPL_BUILD */ 53 54 .balignl 16,0xdeadbeef 55 56 57/* 58 ************************************************************************* 59 * 60 * Startup Code (reset vector) 61 * 62 * do important init only if we don't start from RAM! 63 * relocate armboot to ram 64 * setup stack 65 * jump to second stage 66 * 67 ************************************************************************* 68 */ 69 70.globl _TEXT_BASE 71_TEXT_BASE: 72#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE) 73 .word CONFIG_SPL_TEXT_BASE 74#else 75 .word CONFIG_SYS_TEXT_BASE 76#endif 77 78/* 79 * These are defined in the board-specific linker script. 80 * Subtracting _start from them lets the linker put their 81 * relative position in the executable instead of leaving 82 * them null. 83 */ 84.globl _bss_start_ofs 85_bss_start_ofs: 86 .word __bss_start - _start 87 88.globl _bss_end_ofs 89_bss_end_ofs: 90 .word __bss_end - _start 91 92.globl _end_ofs 93_end_ofs: 94 .word _end - _start 95 96#ifdef CONFIG_USE_IRQ 97/* IRQ stack memory (calculated at run-time) */ 98.globl IRQ_STACK_START 99IRQ_STACK_START: 100 .word 0x0badc0de 101 102/* IRQ stack memory (calculated at run-time) */ 103.globl FIQ_STACK_START 104FIQ_STACK_START: 105 .word 0x0badc0de 106#endif 107 108/* IRQ stack memory (calculated at run-time) + 8 bytes */ 109.globl IRQ_STACK_START_IN 110IRQ_STACK_START_IN: 111 .word 0x0badc0de 112 113/* 114 * the actual reset code 115 */ 116 117reset: 118 /* 119 * set the cpu to SVC32 mode 120 */ 121 mrs r0,cpsr 122 bic r0,r0,#0x1f 123 orr r0,r0,#0xd3 124 msr cpsr,r0 125 126 /* 127 * we do sys-critical inits only at reboot, 128 * not when booting from ram! 129 */ 130#ifndef CONFIG_SKIP_LOWLEVEL_INIT 131 bl cpu_init_crit 132#endif 133 134 bl _main 135 136/*------------------------------------------------------------------------------*/ 137 138 .globl c_runtime_cpu_setup 139c_runtime_cpu_setup: 140 141 mov pc, lr 142 143/* 144 ************************************************************************* 145 * 146 * CPU_init_critical registers 147 * 148 * setup important registers 149 * setup memory timing 150 * 151 ************************************************************************* 152 */ 153 154#ifndef CONFIG_SKIP_LOWLEVEL_INIT 155cpu_init_crit: 156 157 mov ip, lr 158 /* 159 * before relocating, we have to setup RAM timing 160 * because memory timing is board-dependent, you will 161 * find a lowlevel_init.S in your board directory. 162 */ 163 bl lowlevel_init 164 mov lr, ip 165 166 mov pc, lr 167#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 168 169 170#ifndef CONFIG_SPL_BUILD 171/* 172 ************************************************************************* 173 * 174 * Interrupt handling 175 * 176 ************************************************************************* 177 */ 178 179@ 180@ IRQ stack frame. 181@ 182#define S_FRAME_SIZE 72 183 184#define S_OLD_R0 68 185#define S_PSR 64 186#define S_PC 60 187#define S_LR 56 188#define S_SP 52 189 190#define S_IP 48 191#define S_FP 44 192#define S_R10 40 193#define S_R9 36 194#define S_R8 32 195#define S_R7 28 196#define S_R6 24 197#define S_R5 20 198#define S_R4 16 199#define S_R3 12 200#define S_R2 8 201#define S_R1 4 202#define S_R0 0 203 204#define MODE_SVC 0x13 205#define I_BIT 0x80 206 207/* 208 * use bad_save_user_regs for abort/prefetch/undef/swi ... 209 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 210 */ 211 212 .macro bad_save_user_regs 213 sub sp, sp, #S_FRAME_SIZE 214 stmia sp, {r0 - r12} @ Calling r0-r12 215 add r8, sp, #S_PC 216 217 ldr r2, IRQ_STACK_START_IN 218 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 219 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 220 221 add r5, sp, #S_SP 222 mov r1, lr 223 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r 224 mov r0, sp 225 .endm 226 227 .macro irq_save_user_regs 228 sub sp, sp, #S_FRAME_SIZE 229 stmia sp, {r0 - r12} @ Calling r0-r12 230 add r8, sp, #S_PC 231 stmdb r8, {sp, lr}^ @ Calling SP, LR 232 str lr, [r8, #0] @ Save calling PC 233 mrs r6, spsr 234 str r6, [r8, #4] @ Save CPSR 235 str r0, [r8, #8] @ Save OLD_R0 236 mov r0, sp 237 .endm 238 239 .macro irq_restore_user_regs 240 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 241 mov r0, r0 242 ldr lr, [sp, #S_PC] @ Get PC 243 add sp, sp, #S_FRAME_SIZE 244 subs pc, lr, #4 @ return & move spsr_svc into cpsr 245 .endm 246 247 .macro get_bad_stack 248 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 249 250 str lr, [r13] @ save caller lr / spsr 251 mrs lr, spsr 252 str lr, [r13, #4] 253 254 mov r13, #MODE_SVC @ prepare SVC-Mode 255 msr spsr_c, r13 256 mov lr, pc 257 movs pc, lr 258 .endm 259 260 .macro get_irq_stack @ setup IRQ stack 261 ldr sp, IRQ_STACK_START 262 .endm 263 264 .macro get_fiq_stack @ setup FIQ stack 265 ldr sp, FIQ_STACK_START 266 .endm 267 268/* 269 * exception handlers 270 */ 271 .align 5 272undefined_instruction: 273 get_bad_stack 274 bad_save_user_regs 275 bl do_undefined_instruction 276 277 .align 5 278software_interrupt: 279 get_bad_stack 280 bad_save_user_regs 281 bl do_software_interrupt 282 283 .align 5 284prefetch_abort: 285 get_bad_stack 286 bad_save_user_regs 287 bl do_prefetch_abort 288 289 .align 5 290data_abort: 291 get_bad_stack 292 bad_save_user_regs 293 bl do_data_abort 294 295 .align 5 296not_used: 297 get_bad_stack 298 bad_save_user_regs 299 bl do_not_used 300 301#ifdef CONFIG_USE_IRQ 302 303 .align 5 304irq: 305 get_irq_stack 306 irq_save_user_regs 307 bl do_irq 308 irq_restore_user_regs 309 310 .align 5 311fiq: 312 get_fiq_stack 313 /* someone ought to write a more effiction fiq_save_user_regs */ 314 irq_save_user_regs 315 bl do_fiq 316 irq_restore_user_regs 317 318#else 319 320 .align 5 321irq: 322 get_bad_stack 323 bad_save_user_regs 324 bl do_irq 325 326 .align 5 327fiq: 328 get_bad_stack 329 bad_save_user_regs 330 bl do_fiq 331 332#endif 333#endif /* CONFIG_SPL_BUILD */ 334