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 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 157 158clear_bss: 159 ldr r0, _bss_start /* find start of bss segment */ 160 ldr r1, _bss_end /* stop here */ 161 mov r2, #0x00000000 /* clear */ 162 163clbss_l:str r2, [r0] /* clear loop... */ 164 add r0, r0, #4 165 cmp r0, r1 166 ble clbss_l 167 168 ldr pc, _start_armboot 169 170_start_armboot: .word start_armboot 171 172 173/* 174 ************************************************************************* 175 * 176 * CPU_init_critical registers 177 * 178 * setup important registers 179 * setup memory timing 180 * 181 ************************************************************************* 182 */ 183 184 185/* Interupt-Controller base address */ 186IC_BASE: .word 0x90050000 187#define ICMR 0x04 188 189 190/* Reset-Controller */ 191RST_BASE: .word 0x90030000 192#define RSRR 0x00 193#define RCSR 0x04 194 195 196/* PWR */ 197PWR_BASE: .word 0x90020000 198#define PSPR 0x08 199#define PPCR 0x14 200cpuspeed: .word CONFIG_SYS_CPUSPEED 201 202 203cpu_init_crit: 204 /* 205 * mask all IRQs 206 */ 207 ldr r0, IC_BASE 208 mov r1, #0x00 209 str r1, [r0, #ICMR] 210 211 /* set clock speed */ 212 ldr r0, PWR_BASE 213 ldr r1, cpuspeed 214 str r1, [r0, #PPCR] 215 216 /* 217 * before relocating, we have to setup RAM timing 218 * because memory timing is board-dependend, you will 219 * find a lowlevel_init.S in your board directory. 220 */ 221 mov ip, lr 222 bl lowlevel_init 223 mov lr, ip 224 225 /* 226 * disable MMU stuff and enable I-cache 227 */ 228 mrc p15,0,r0,c1,c0 229 bic r0, r0, #0x00002000 @ clear bit 13 (X) 230 bic r0, r0, #0x0000000f @ clear bits 3-0 (WCAM) 231 orr r0, r0, #0x00001000 @ set bit 12 (I) Icache 232 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 233 mcr p15,0,r0,c1,c0 234 235 /* 236 * flush v4 I/D caches 237 */ 238 mov r0, #0 239 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 240 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 241 242 mov pc, lr 243 244 245/* 246 ************************************************************************* 247 * 248 * Interrupt handling 249 * 250 ************************************************************************* 251 */ 252 253@ 254@ IRQ stack frame. 255@ 256#define S_FRAME_SIZE 72 257 258#define S_OLD_R0 68 259#define S_PSR 64 260#define S_PC 60 261#define S_LR 56 262#define S_SP 52 263 264#define S_IP 48 265#define S_FP 44 266#define S_R10 40 267#define S_R9 36 268#define S_R8 32 269#define S_R7 28 270#define S_R6 24 271#define S_R5 20 272#define S_R4 16 273#define S_R3 12 274#define S_R2 8 275#define S_R1 4 276#define S_R0 0 277 278#define MODE_SVC 0x13 279#define I_BIT 0x80 280 281/* 282 * use bad_save_user_regs for abort/prefetch/undef/swi ... 283 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 284 */ 285 286 .macro bad_save_user_regs 287 sub sp, sp, #S_FRAME_SIZE 288 stmia sp, {r0 - r12} @ Calling r0-r12 289 add r8, sp, #S_PC 290 291 ldr r2, _armboot_start 292 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 293 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 294 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 295 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 296 297 add r5, sp, #S_SP 298 mov r1, lr 299 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r 300 mov r0, sp 301 .endm 302 303 .macro irq_save_user_regs 304 sub sp, sp, #S_FRAME_SIZE 305 stmia sp, {r0 - r12} @ Calling r0-r12 306 add r8, sp, #S_PC 307 stmdb r8, {sp, lr}^ @ Calling SP, LR 308 str lr, [r8, #0] @ Save calling PC 309 mrs r6, spsr 310 str r6, [r8, #4] @ Save CPSR 311 str r0, [r8, #8] @ Save OLD_R0 312 mov r0, sp 313 .endm 314 315 .macro irq_restore_user_regs 316 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 317 mov r0, r0 318 ldr lr, [sp, #S_PC] @ Get PC 319 add sp, sp, #S_FRAME_SIZE 320 subs pc, lr, #4 @ return & move spsr_svc into cpsr 321 .endm 322 323 .macro get_bad_stack 324 ldr r13, _armboot_start @ setup our mode stack 325 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 326 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 327 328 str lr, [r13] @ save caller lr / spsr 329 mrs lr, spsr 330 str lr, [r13, #4] 331 332 mov r13, #MODE_SVC @ prepare SVC-Mode 333 msr spsr_c, r13 334 mov lr, pc 335 movs pc, lr 336 .endm 337 338 .macro get_irq_stack @ setup IRQ stack 339 ldr sp, IRQ_STACK_START 340 .endm 341 342 .macro get_fiq_stack @ setup FIQ stack 343 ldr sp, FIQ_STACK_START 344 .endm 345 346/* 347 * exception handlers 348 */ 349 .align 5 350undefined_instruction: 351 get_bad_stack 352 bad_save_user_regs 353 bl do_undefined_instruction 354 355 .align 5 356software_interrupt: 357 get_bad_stack 358 bad_save_user_regs 359 bl do_software_interrupt 360 361 .align 5 362prefetch_abort: 363 get_bad_stack 364 bad_save_user_regs 365 bl do_prefetch_abort 366 367 .align 5 368data_abort: 369 get_bad_stack 370 bad_save_user_regs 371 bl do_data_abort 372 373 .align 5 374not_used: 375 get_bad_stack 376 bad_save_user_regs 377 bl do_not_used 378 379#ifdef CONFIG_USE_IRQ 380 381 .align 5 382irq: 383 get_irq_stack 384 irq_save_user_regs 385 bl do_irq 386 irq_restore_user_regs 387 388 .align 5 389fiq: 390 get_fiq_stack 391 /* someone ought to write a more effiction fiq_save_user_regs */ 392 irq_save_user_regs 393 bl do_fiq 394 irq_restore_user_regs 395 396#else 397 398 .align 5 399irq: 400 get_bad_stack 401 bad_save_user_regs 402 bl do_irq 403 404 .align 5 405fiq: 406 get_bad_stack 407 bad_save_user_regs 408 bl do_fiq 409 410#endif 411 412 .align 5 413.globl reset_cpu 414reset_cpu: 415 ldr r0, RST_BASE 416 mov r1, #0x0 @ set bit 3-0 ... 417 str r1, [r0, #RCSR] @ ... to clear in RCSR 418 mov r1, #0x1 419 str r1, [r0, #RSRR] @ and perform reset 420 b reset_cpu @ silly, but repeat endlessly 421