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#ifdef CONFIG_USE_IRQ 60/* IRQ stack memory (calculated at run-time) */ 61.globl IRQ_STACK_START 62IRQ_STACK_START: 63 .word 0x0badc0de 64 65/* IRQ stack memory (calculated at run-time) */ 66.globl FIQ_STACK_START 67FIQ_STACK_START: 68 .word 0x0badc0de 69#endif 70 71/* IRQ stack memory (calculated at run-time) + 8 bytes */ 72.globl IRQ_STACK_START_IN 73IRQ_STACK_START_IN: 74 .word 0x0badc0de 75 76/* 77 * the actual reset code 78 */ 79 80reset: 81 /* 82 * set the cpu to SVC32 mode 83 */ 84 mrs r0,cpsr 85 bic r0,r0,#0x1f 86 orr r0,r0,#0xd3 87 msr cpsr,r0 88 89 /* 90 * we do sys-critical inits only at reboot, 91 * not when booting from ram! 92 */ 93#ifndef CONFIG_SKIP_LOWLEVEL_INIT 94 bl cpu_init_crit 95#endif 96 97 bl _main 98 99/*------------------------------------------------------------------------------*/ 100 101 .globl c_runtime_cpu_setup 102c_runtime_cpu_setup: 103 104 mov pc, lr 105 106/* 107 ************************************************************************* 108 * 109 * CPU_init_critical registers 110 * 111 * setup important registers 112 * setup memory timing 113 * 114 ************************************************************************* 115 */ 116 117 118/* Interrupt-Controller base address */ 119IC_BASE: .word 0x90050000 120#define ICMR 0x04 121 122 123/* Reset-Controller */ 124RST_BASE: .word 0x90030000 125#define RSRR 0x00 126#define RCSR 0x04 127 128 129/* PWR */ 130PWR_BASE: .word 0x90020000 131#define PSPR 0x08 132#define PPCR 0x14 133cpuspeed: .word CONFIG_SYS_CPUSPEED 134 135 136cpu_init_crit: 137 /* 138 * mask all IRQs 139 */ 140 ldr r0, IC_BASE 141 mov r1, #0x00 142 str r1, [r0, #ICMR] 143 144 /* set clock speed */ 145 ldr r0, PWR_BASE 146 ldr r1, cpuspeed 147 str r1, [r0, #PPCR] 148 149 /* 150 * before relocating, we have to setup RAM timing 151 * because memory timing is board-dependend, you will 152 * find a lowlevel_init.S in your board directory. 153 */ 154 mov ip, lr 155 bl lowlevel_init 156 mov lr, ip 157 158 /* 159 * disable MMU stuff and enable I-cache 160 */ 161 mrc p15,0,r0,c1,c0 162 bic r0, r0, #0x00002000 @ clear bit 13 (X) 163 bic r0, r0, #0x0000000f @ clear bits 3-0 (WCAM) 164 orr r0, r0, #0x00001000 @ set bit 12 (I) Icache 165 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 166 mcr p15,0,r0,c1,c0 167 168 /* 169 * flush v4 I/D caches 170 */ 171 mov r0, #0 172 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 173 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 174 175 mov pc, lr 176 177 178/* 179 ************************************************************************* 180 * 181 * Interrupt handling 182 * 183 ************************************************************************* 184 */ 185 186@ 187@ IRQ stack frame. 188@ 189#define S_FRAME_SIZE 72 190 191#define S_OLD_R0 68 192#define S_PSR 64 193#define S_PC 60 194#define S_LR 56 195#define S_SP 52 196 197#define S_IP 48 198#define S_FP 44 199#define S_R10 40 200#define S_R9 36 201#define S_R8 32 202#define S_R7 28 203#define S_R6 24 204#define S_R5 20 205#define S_R4 16 206#define S_R3 12 207#define S_R2 8 208#define S_R1 4 209#define S_R0 0 210 211#define MODE_SVC 0x13 212#define I_BIT 0x80 213 214/* 215 * use bad_save_user_regs for abort/prefetch/undef/swi ... 216 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 217 */ 218 219 .macro bad_save_user_regs 220 sub sp, sp, #S_FRAME_SIZE 221 stmia sp, {r0 - r12} @ Calling r0-r12 222 add r8, sp, #S_PC 223 224 ldr r2, IRQ_STACK_START_IN 225 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 226 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 227 228 add r5, sp, #S_SP 229 mov r1, lr 230 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r 231 mov r0, sp 232 .endm 233 234 .macro irq_save_user_regs 235 sub sp, sp, #S_FRAME_SIZE 236 stmia sp, {r0 - r12} @ Calling r0-r12 237 add r8, sp, #S_PC 238 stmdb r8, {sp, lr}^ @ Calling SP, LR 239 str lr, [r8, #0] @ Save calling PC 240 mrs r6, spsr 241 str r6, [r8, #4] @ Save CPSR 242 str r0, [r8, #8] @ Save OLD_R0 243 mov r0, sp 244 .endm 245 246 .macro irq_restore_user_regs 247 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 248 mov r0, r0 249 ldr lr, [sp, #S_PC] @ Get PC 250 add sp, sp, #S_FRAME_SIZE 251 subs pc, lr, #4 @ return & move spsr_svc into cpsr 252 .endm 253 254 .macro get_bad_stack 255 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 256 257 str lr, [r13] @ save caller lr / spsr 258 mrs lr, spsr 259 str lr, [r13, #4] 260 261 mov r13, #MODE_SVC @ prepare SVC-Mode 262 msr spsr_c, r13 263 mov lr, pc 264 movs pc, lr 265 .endm 266 267 .macro get_irq_stack @ setup IRQ stack 268 ldr sp, IRQ_STACK_START 269 .endm 270 271 .macro get_fiq_stack @ setup FIQ stack 272 ldr sp, FIQ_STACK_START 273 .endm 274 275/* 276 * exception handlers 277 */ 278 .align 5 279undefined_instruction: 280 get_bad_stack 281 bad_save_user_regs 282 bl do_undefined_instruction 283 284 .align 5 285software_interrupt: 286 get_bad_stack 287 bad_save_user_regs 288 bl do_software_interrupt 289 290 .align 5 291prefetch_abort: 292 get_bad_stack 293 bad_save_user_regs 294 bl do_prefetch_abort 295 296 .align 5 297data_abort: 298 get_bad_stack 299 bad_save_user_regs 300 bl do_data_abort 301 302 .align 5 303not_used: 304 get_bad_stack 305 bad_save_user_regs 306 bl do_not_used 307 308#ifdef CONFIG_USE_IRQ 309 310 .align 5 311irq: 312 get_irq_stack 313 irq_save_user_regs 314 bl do_irq 315 irq_restore_user_regs 316 317 .align 5 318fiq: 319 get_fiq_stack 320 /* someone ought to write a more effiction fiq_save_user_regs */ 321 irq_save_user_regs 322 bl do_fiq 323 irq_restore_user_regs 324 325#else 326 327 .align 5 328irq: 329 get_bad_stack 330 bad_save_user_regs 331 bl do_irq 332 333 .align 5 334fiq: 335 get_bad_stack 336 bad_save_user_regs 337 bl do_fiq 338 339#endif 340 341 .align 5 342.globl reset_cpu 343reset_cpu: 344 ldr r0, RST_BASE 345 mov r1, #0x0 @ set bit 3-0 ... 346 str r1, [r0, #RCSR] @ ... to clear in RCSR 347 mov r1, #0x1 348 str r1, [r0, #RSRR] @ and perform reset 349 b reset_cpu @ silly, but repeat endlessly 350