1/* 2 * armboot - Startup Code for SA1100 CPU 3 * 4 * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> 5 * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> 6 * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> 7 * Copyright (c) 2001 Alex Züpke <azu@sysgo.de> 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12#include <asm-offsets.h> 13#include <config.h> 14#include <version.h> 15 16/* 17 ************************************************************************* 18 * 19 * Jump vector table as in table 3.1 in [1] 20 * 21 ************************************************************************* 22 */ 23 24 25.globl _start 26_start: b reset 27 ldr pc, _undefined_instruction 28 ldr pc, _software_interrupt 29 ldr pc, _prefetch_abort 30 ldr pc, _data_abort 31 ldr pc, _not_used 32 ldr pc, _irq 33 ldr pc, _fiq 34 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 43 .balignl 16,0xdeadbeef 44 45 46/* 47 ************************************************************************* 48 * 49 * Startup Code (reset vector) 50 * 51 * do important init only if we don't start from memory! 52 * relocate armboot to ram 53 * setup stack 54 * jump to second stage 55 * 56 ************************************************************************* 57 */ 58 59.globl _TEXT_BASE 60_TEXT_BASE: 61#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE) 62 .word CONFIG_SPL_TEXT_BASE 63#else 64 .word CONFIG_SYS_TEXT_BASE 65#endif 66 67/* 68 * These are defined in the board-specific linker script. 69 * Subtracting _start from them lets the linker put their 70 * relative position in the executable instead of leaving 71 * them null. 72 */ 73.globl _bss_start_ofs 74_bss_start_ofs: 75 .word __bss_start - _start 76 77.globl _bss_end_ofs 78_bss_end_ofs: 79 .word __bss_end - _start 80 81.globl _end_ofs 82_end_ofs: 83 .word _end - _start 84 85#ifdef CONFIG_USE_IRQ 86/* IRQ stack memory (calculated at run-time) */ 87.globl IRQ_STACK_START 88IRQ_STACK_START: 89 .word 0x0badc0de 90 91/* IRQ stack memory (calculated at run-time) */ 92.globl FIQ_STACK_START 93FIQ_STACK_START: 94 .word 0x0badc0de 95#endif 96 97/* IRQ stack memory (calculated at run-time) + 8 bytes */ 98.globl IRQ_STACK_START_IN 99IRQ_STACK_START_IN: 100 .word 0x0badc0de 101 102/* 103 * the actual reset code 104 */ 105 106reset: 107 /* 108 * set the cpu to SVC32 mode 109 */ 110 mrs r0,cpsr 111 bic r0,r0,#0x1f 112 orr r0,r0,#0xd3 113 msr cpsr,r0 114 115 /* 116 * we do sys-critical inits only at reboot, 117 * not when booting from ram! 118 */ 119#ifndef CONFIG_SKIP_LOWLEVEL_INIT 120 bl cpu_init_crit 121#endif 122 123 bl _main 124 125/*------------------------------------------------------------------------------*/ 126 127 .globl c_runtime_cpu_setup 128c_runtime_cpu_setup: 129 130 mov pc, lr 131 132/* 133 ************************************************************************* 134 * 135 * CPU_init_critical registers 136 * 137 * setup important registers 138 * setup memory timing 139 * 140 ************************************************************************* 141 */ 142 143 144/* Interrupt-Controller base address */ 145IC_BASE: .word 0x90050000 146#define ICMR 0x04 147 148 149/* Reset-Controller */ 150RST_BASE: .word 0x90030000 151#define RSRR 0x00 152#define RCSR 0x04 153 154 155/* PWR */ 156PWR_BASE: .word 0x90020000 157#define PSPR 0x08 158#define PPCR 0x14 159cpuspeed: .word CONFIG_SYS_CPUSPEED 160 161 162cpu_init_crit: 163 /* 164 * mask all IRQs 165 */ 166 ldr r0, IC_BASE 167 mov r1, #0x00 168 str r1, [r0, #ICMR] 169 170 /* set clock speed */ 171 ldr r0, PWR_BASE 172 ldr r1, cpuspeed 173 str r1, [r0, #PPCR] 174 175 /* 176 * before relocating, we have to setup RAM timing 177 * because memory timing is board-dependend, you will 178 * find a lowlevel_init.S in your board directory. 179 */ 180 mov ip, lr 181 bl lowlevel_init 182 mov lr, ip 183 184 /* 185 * disable MMU stuff and enable I-cache 186 */ 187 mrc p15,0,r0,c1,c0 188 bic r0, r0, #0x00002000 @ clear bit 13 (X) 189 bic r0, r0, #0x0000000f @ clear bits 3-0 (WCAM) 190 orr r0, r0, #0x00001000 @ set bit 12 (I) Icache 191 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 192 mcr p15,0,r0,c1,c0 193 194 /* 195 * flush v4 I/D caches 196 */ 197 mov r0, #0 198 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 199 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 200 201 mov pc, lr 202 203 204/* 205 ************************************************************************* 206 * 207 * Interrupt handling 208 * 209 ************************************************************************* 210 */ 211 212@ 213@ IRQ stack frame. 214@ 215#define S_FRAME_SIZE 72 216 217#define S_OLD_R0 68 218#define S_PSR 64 219#define S_PC 60 220#define S_LR 56 221#define S_SP 52 222 223#define S_IP 48 224#define S_FP 44 225#define S_R10 40 226#define S_R9 36 227#define S_R8 32 228#define S_R7 28 229#define S_R6 24 230#define S_R5 20 231#define S_R4 16 232#define S_R3 12 233#define S_R2 8 234#define S_R1 4 235#define S_R0 0 236 237#define MODE_SVC 0x13 238#define I_BIT 0x80 239 240/* 241 * use bad_save_user_regs for abort/prefetch/undef/swi ... 242 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 243 */ 244 245 .macro bad_save_user_regs 246 sub sp, sp, #S_FRAME_SIZE 247 stmia sp, {r0 - r12} @ Calling r0-r12 248 add r8, sp, #S_PC 249 250 ldr r2, IRQ_STACK_START_IN 251 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 252 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 253 254 add r5, sp, #S_SP 255 mov r1, lr 256 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r 257 mov r0, sp 258 .endm 259 260 .macro irq_save_user_regs 261 sub sp, sp, #S_FRAME_SIZE 262 stmia sp, {r0 - r12} @ Calling r0-r12 263 add r8, sp, #S_PC 264 stmdb r8, {sp, lr}^ @ Calling SP, LR 265 str lr, [r8, #0] @ Save calling PC 266 mrs r6, spsr 267 str r6, [r8, #4] @ Save CPSR 268 str r0, [r8, #8] @ Save OLD_R0 269 mov r0, sp 270 .endm 271 272 .macro irq_restore_user_regs 273 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 274 mov r0, r0 275 ldr lr, [sp, #S_PC] @ Get PC 276 add sp, sp, #S_FRAME_SIZE 277 subs pc, lr, #4 @ return & move spsr_svc into cpsr 278 .endm 279 280 .macro get_bad_stack 281 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 282 283 str lr, [r13] @ save caller lr / spsr 284 mrs lr, spsr 285 str lr, [r13, #4] 286 287 mov r13, #MODE_SVC @ prepare SVC-Mode 288 msr spsr_c, r13 289 mov lr, pc 290 movs pc, lr 291 .endm 292 293 .macro get_irq_stack @ setup IRQ stack 294 ldr sp, IRQ_STACK_START 295 .endm 296 297 .macro get_fiq_stack @ setup FIQ stack 298 ldr sp, FIQ_STACK_START 299 .endm 300 301/* 302 * exception handlers 303 */ 304 .align 5 305undefined_instruction: 306 get_bad_stack 307 bad_save_user_regs 308 bl do_undefined_instruction 309 310 .align 5 311software_interrupt: 312 get_bad_stack 313 bad_save_user_regs 314 bl do_software_interrupt 315 316 .align 5 317prefetch_abort: 318 get_bad_stack 319 bad_save_user_regs 320 bl do_prefetch_abort 321 322 .align 5 323data_abort: 324 get_bad_stack 325 bad_save_user_regs 326 bl do_data_abort 327 328 .align 5 329not_used: 330 get_bad_stack 331 bad_save_user_regs 332 bl do_not_used 333 334#ifdef CONFIG_USE_IRQ 335 336 .align 5 337irq: 338 get_irq_stack 339 irq_save_user_regs 340 bl do_irq 341 irq_restore_user_regs 342 343 .align 5 344fiq: 345 get_fiq_stack 346 /* someone ought to write a more effiction fiq_save_user_regs */ 347 irq_save_user_regs 348 bl do_fiq 349 irq_restore_user_regs 350 351#else 352 353 .align 5 354irq: 355 get_bad_stack 356 bad_save_user_regs 357 bl do_irq 358 359 .align 5 360fiq: 361 get_bad_stack 362 bad_save_user_regs 363 bl do_fiq 364 365#endif 366 367 .align 5 368.globl reset_cpu 369reset_cpu: 370 ldr r0, RST_BASE 371 mov r1, #0x0 @ set bit 3-0 ... 372 str r1, [r0, #RCSR] @ ... to clear in RCSR 373 mov r1, #0x1 374 str r1, [r0, #RSRR] @ and perform reset 375 b reset_cpu @ silly, but repeat endlessly 376