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 * See file CREDITS for list of people who contributed to this 10 * project. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; either version 2 of 15 * the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 * MA 02111-1307 USA 26 */ 27 28 29#include <config.h> 30#include <version.h> 31 32 33/* 34 ************************************************************************* 35 * 36 * Jump vector table as in table 3.1 in [1] 37 * 38 ************************************************************************* 39 */ 40 41 42.globl _start 43_start: b reset 44 ldr pc, _undefined_instruction 45 ldr pc, _software_interrupt 46 ldr pc, _prefetch_abort 47 ldr pc, _data_abort 48 ldr pc, _not_used 49 ldr pc, _irq 50 ldr pc, _fiq 51 52_undefined_instruction: .word undefined_instruction 53_software_interrupt: .word software_interrupt 54_prefetch_abort: .word prefetch_abort 55_data_abort: .word data_abort 56_not_used: .word not_used 57_irq: .word irq 58_fiq: .word fiq 59 60 .balignl 16,0xdeadbeef 61 62 63/* 64 ************************************************************************* 65 * 66 * Startup Code (reset vector) 67 * 68 * do important init only if we don't start from memory! 69 * relocate armboot to ram 70 * setup stack 71 * jump to second stage 72 * 73 ************************************************************************* 74 */ 75 76_TEXT_BASE: 77 .word TEXT_BASE 78 79.globl _armboot_start 80_armboot_start: 81 .word _start 82 83/* 84 * These are defined in the board-specific linker script. 85 */ 86.globl _bss_start 87_bss_start: 88 .word __bss_start 89 90.globl _bss_end 91_bss_end: 92 .word _end 93 94#ifdef CONFIG_USE_IRQ 95/* IRQ stack memory (calculated at run-time) */ 96.globl IRQ_STACK_START 97IRQ_STACK_START: 98 .word 0x0badc0de 99 100/* IRQ stack memory (calculated at run-time) */ 101.globl FIQ_STACK_START 102FIQ_STACK_START: 103 .word 0x0badc0de 104#endif 105 106 107/* 108 * the actual reset code 109 */ 110 111reset: 112 /* 113 * set the cpu to SVC32 mode 114 */ 115 mrs r0,cpsr 116 bic r0,r0,#0x1f 117 orr r0,r0,#0x13 118 msr cpsr,r0 119 120 /* 121 * we do sys-critical inits only at reboot, 122 * not when booting from ram! 123 */ 124#ifndef CONFIG_SKIP_LOWLEVEL_INIT 125 bl cpu_init_crit 126#endif 127 128#ifndef CONFIG_SKIP_RELOCATE_UBOOT 129relocate: /* relocate U-Boot to RAM */ 130 adr r0, _start /* r0 <- current position of code */ 131 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 132 cmp r0, r1 /* don't reloc during debug */ 133 beq stack_setup 134 135 ldr r2, _armboot_start 136 ldr r3, _bss_start 137 sub r2, r3, r2 /* r2 <- size of armboot */ 138 add r2, r0, r2 /* r2 <- source end address */ 139 140copy_loop: 141 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 142 stmia r1!, {r3-r10} /* copy to target address [r1] */ 143 cmp r0, r2 /* until source end addreee [r2] */ 144 ble copy_loop 145#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 146 147 /* Set up the stack */ 148stack_setup: 149 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 150 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 151 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 152#ifdef CONFIG_USE_IRQ 153 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 154#endif 155 sub sp, r0, #12 /* leave 3 words for abort-stack */ 156 157clear_bss: 158 ldr r0, _bss_start /* find start of bss segment */ 159 ldr r1, _bss_end /* stop here */ 160 mov r2, #0x00000000 /* clear */ 161 162clbss_l:str r2, [r0] /* clear loop... */ 163 add r0, r0, #4 164 cmp r0, r1 165 ble clbss_l 166 167 ldr pc, _start_armboot 168 169_start_armboot: .word start_armboot 170 171 172/* 173 ************************************************************************* 174 * 175 * CPU_init_critical registers 176 * 177 * setup important registers 178 * setup memory timing 179 * 180 ************************************************************************* 181 */ 182 183 184/* Interupt-Controller base address */ 185IC_BASE: .word 0x90050000 186#define ICMR 0x04 187 188 189/* Reset-Controller */ 190RST_BASE: .word 0x90030000 191#define RSRR 0x00 192#define RCSR 0x04 193 194 195/* PWR */ 196PWR_BASE: .word 0x90020000 197#define PSPR 0x08 198#define PPCR 0x14 199cpuspeed: .word CONFIG_SYS_CPUSPEED 200 201 202cpu_init_crit: 203 /* 204 * mask all IRQs 205 */ 206 ldr r0, IC_BASE 207 mov r1, #0x00 208 str r1, [r0, #ICMR] 209 210 /* set clock speed */ 211 ldr r0, PWR_BASE 212 ldr r1, cpuspeed 213 str r1, [r0, #PPCR] 214 215 /* 216 * before relocating, we have to setup RAM timing 217 * because memory timing is board-dependend, you will 218 * find a lowlevel_init.S in your board directory. 219 */ 220 mov ip, lr 221 bl lowlevel_init 222 mov lr, ip 223 224 /* 225 * disable MMU stuff and enable I-cache 226 */ 227 mrc p15,0,r0,c1,c0 228 bic r0, r0, #0x00002000 @ clear bit 13 (X) 229 bic r0, r0, #0x0000000f @ clear bits 3-0 (WCAM) 230 orr r0, r0, #0x00001000 @ set bit 12 (I) Icache 231 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 232 mcr p15,0,r0,c1,c0 233 234 /* 235 * flush v4 I/D caches 236 */ 237 mov r0, #0 238 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 239 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 240 241 mov pc, lr 242 243 244/* 245 ************************************************************************* 246 * 247 * Interrupt handling 248 * 249 ************************************************************************* 250 */ 251 252@ 253@ IRQ stack frame. 254@ 255#define S_FRAME_SIZE 72 256 257#define S_OLD_R0 68 258#define S_PSR 64 259#define S_PC 60 260#define S_LR 56 261#define S_SP 52 262 263#define S_IP 48 264#define S_FP 44 265#define S_R10 40 266#define S_R9 36 267#define S_R8 32 268#define S_R7 28 269#define S_R6 24 270#define S_R5 20 271#define S_R4 16 272#define S_R3 12 273#define S_R2 8 274#define S_R1 4 275#define S_R0 0 276 277#define MODE_SVC 0x13 278#define I_BIT 0x80 279 280/* 281 * use bad_save_user_regs for abort/prefetch/undef/swi ... 282 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 283 */ 284 285 .macro bad_save_user_regs 286 sub sp, sp, #S_FRAME_SIZE 287 stmia sp, {r0 - r12} @ Calling r0-r12 288 add r8, sp, #S_PC 289 290 ldr r2, _armboot_start 291 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 292 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 293 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 294 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 295 296 add r5, sp, #S_SP 297 mov r1, lr 298 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r 299 mov r0, sp 300 .endm 301 302 .macro irq_save_user_regs 303 sub sp, sp, #S_FRAME_SIZE 304 stmia sp, {r0 - r12} @ Calling r0-r12 305 add r8, sp, #S_PC 306 stmdb r8, {sp, lr}^ @ Calling SP, LR 307 str lr, [r8, #0] @ Save calling PC 308 mrs r6, spsr 309 str r6, [r8, #4] @ Save CPSR 310 str r0, [r8, #8] @ Save OLD_R0 311 mov r0, sp 312 .endm 313 314 .macro irq_restore_user_regs 315 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 316 mov r0, r0 317 ldr lr, [sp, #S_PC] @ Get PC 318 add sp, sp, #S_FRAME_SIZE 319 subs pc, lr, #4 @ return & move spsr_svc into cpsr 320 .endm 321 322 .macro get_bad_stack 323 ldr r13, _armboot_start @ setup our mode stack 324 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 325 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 326 327 str lr, [r13] @ save caller lr / spsr 328 mrs lr, spsr 329 str lr, [r13, #4] 330 331 mov r13, #MODE_SVC @ prepare SVC-Mode 332 msr spsr_c, r13 333 mov lr, pc 334 movs pc, lr 335 .endm 336 337 .macro get_irq_stack @ setup IRQ stack 338 ldr sp, IRQ_STACK_START 339 .endm 340 341 .macro get_fiq_stack @ setup FIQ stack 342 ldr sp, FIQ_STACK_START 343 .endm 344 345/* 346 * exception handlers 347 */ 348 .align 5 349undefined_instruction: 350 get_bad_stack 351 bad_save_user_regs 352 bl do_undefined_instruction 353 354 .align 5 355software_interrupt: 356 get_bad_stack 357 bad_save_user_regs 358 bl do_software_interrupt 359 360 .align 5 361prefetch_abort: 362 get_bad_stack 363 bad_save_user_regs 364 bl do_prefetch_abort 365 366 .align 5 367data_abort: 368 get_bad_stack 369 bad_save_user_regs 370 bl do_data_abort 371 372 .align 5 373not_used: 374 get_bad_stack 375 bad_save_user_regs 376 bl do_not_used 377 378#ifdef CONFIG_USE_IRQ 379 380 .align 5 381irq: 382 get_irq_stack 383 irq_save_user_regs 384 bl do_irq 385 irq_restore_user_regs 386 387 .align 5 388fiq: 389 get_fiq_stack 390 /* someone ought to write a more effiction fiq_save_user_regs */ 391 irq_save_user_regs 392 bl do_fiq 393 irq_restore_user_regs 394 395#else 396 397 .align 5 398irq: 399 get_bad_stack 400 bad_save_user_regs 401 bl do_irq 402 403 .align 5 404fiq: 405 get_bad_stack 406 bad_save_user_regs 407 bl do_fiq 408 409#endif 410 411 .align 5 412.globl reset_cpu 413reset_cpu: 414 ldr r0, RST_BASE 415 mov r1, #0x0 @ set bit 3-0 ... 416 str r1, [r0, #RCSR] @ ... to clear in RCSR 417 mov r1, #0x1 418 str r1, [r0, #RSRR] @ and perform reset 419 b reset_cpu @ silly, but repeat endlessly 420