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