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 208clear_bss: 209 ldr r0, _bss_start /* find start of bss segment */ 210 ldr r1, _bss_end /* stop here */ 211 mov r2, #0x00000000 /* clear */ 212 213clbss_l:str r2, [r0] /* clear loop... */ 214 add r0, r0, #4 215 cmp r0, r1 216 ble clbss_l 217 218 ldr pc, _start_armboot 219 220_start_armboot: .word start_armboot 221 222 223/* 224 ************************************************************************* 225 * 226 * CPU_init_critical registers 227 * 228 * setup important registers 229 * setup memory timing 230 * 231 ************************************************************************* 232 */ 233 234 235#ifndef CONFIG_SKIP_LOWLEVEL_INIT 236cpu_init_crit: 237 /* 238 * flush v4 I/D caches 239 */ 240 mov r0, #0 241 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 242 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 243 244 /* 245 * disable MMU stuff and caches 246 */ 247 mrc p15, 0, r0, c1, c0, 0 248 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 249 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 250 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 251 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 252 mcr p15, 0, r0, c1, c0, 0 253 254 /* 255 * before relocating, we have to setup RAM timing 256 * because memory timing is board-dependend, you will 257 * find a lowlevel_init.S in your board directory. 258 */ 259 mov ip, lr 260 261 bl lowlevel_init 262 263 mov lr, ip 264 mov pc, lr 265#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 266 267/* 268 ************************************************************************* 269 * 270 * Interrupt handling 271 * 272 ************************************************************************* 273 */ 274 275@ 276@ IRQ stack frame. 277@ 278#define S_FRAME_SIZE 72 279 280#define S_OLD_R0 68 281#define S_PSR 64 282#define S_PC 60 283#define S_LR 56 284#define S_SP 52 285 286#define S_IP 48 287#define S_FP 44 288#define S_R10 40 289#define S_R9 36 290#define S_R8 32 291#define S_R7 28 292#define S_R6 24 293#define S_R5 20 294#define S_R4 16 295#define S_R3 12 296#define S_R2 8 297#define S_R1 4 298#define S_R0 0 299 300#define MODE_SVC 0x13 301#define I_BIT 0x80 302 303/* 304 * use bad_save_user_regs for abort/prefetch/undef/swi ... 305 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 306 */ 307 308 .macro bad_save_user_regs 309 sub sp, sp, #S_FRAME_SIZE 310 stmia sp, {r0 - r12} @ Calling r0-r12 311 ldr r2, _armboot_start 312 sub r2, r2, #(CONFIG_STACKSIZE) 313 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) 314 /* set base 2 words into abort stack */ 315 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) 316 ldmia r2, {r2 - r3} @ get pc, cpsr 317 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 318 319 add r5, sp, #S_SP 320 mov r1, lr 321 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 322 mov r0, sp 323 .endm 324 325 .macro irq_save_user_regs 326 sub sp, sp, #S_FRAME_SIZE 327 stmia sp, {r0 - r12} @ Calling r0-r12 328 add r7, sp, #S_PC 329 stmdb r7, {sp, lr}^ @ Calling SP, LR 330 str lr, [r7, #0] @ Save calling PC 331 mrs r6, spsr 332 str r6, [r7, #4] @ Save CPSR 333 str r0, [r7, #8] @ Save OLD_R0 334 mov r0, sp 335 .endm 336 337 .macro irq_restore_user_regs 338 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 339 mov r0, r0 340 ldr lr, [sp, #S_PC] @ Get PC 341 add sp, sp, #S_FRAME_SIZE 342 /* return & move spsr_svc into cpsr */ 343 subs pc, lr, #4 344 .endm 345 346 .macro get_bad_stack 347 ldr r13, _armboot_start @ setup our mode stack 348 sub r13, r13, #(CONFIG_STACKSIZE) 349 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) 350 /* reserve a couple spots in abort stack */ 351 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) 352 353 str lr, [r13] @ save caller lr / spsr 354 mrs lr, spsr 355 str lr, [r13, #4] 356 357 mov r13, #MODE_SVC @ prepare SVC-Mode 358 @ msr spsr_c, r13 359 msr spsr, r13 360 mov lr, pc 361 movs pc, lr 362 .endm 363 364 .macro get_irq_stack @ setup IRQ stack 365 ldr sp, IRQ_STACK_START 366 .endm 367 368 .macro get_fiq_stack @ setup FIQ stack 369 ldr sp, FIQ_STACK_START 370 .endm 371 372/* 373 * exception handlers 374 */ 375 .align 5 376undefined_instruction: 377 get_bad_stack 378 bad_save_user_regs 379 bl do_undefined_instruction 380 381 .align 5 382software_interrupt: 383 get_bad_stack 384 bad_save_user_regs 385 bl do_software_interrupt 386 387 .align 5 388prefetch_abort: 389 get_bad_stack 390 bad_save_user_regs 391 bl do_prefetch_abort 392 393 .align 5 394data_abort: 395 get_bad_stack 396 bad_save_user_regs 397 bl do_data_abort 398 399 .align 5 400not_used: 401 get_bad_stack 402 bad_save_user_regs 403 bl do_not_used 404 405#ifdef CONFIG_USE_IRQ 406 407 .align 5 408irq: 409 get_irq_stack 410 irq_save_user_regs 411 bl do_irq 412 irq_restore_user_regs 413 414 .align 5 415fiq: 416 get_fiq_stack 417 /* someone ought to write a more effiction fiq_save_user_regs */ 418 irq_save_user_regs 419 bl do_fiq 420 irq_restore_user_regs 421 422#else 423 424 .align 5 425irq: 426 get_bad_stack 427 bad_save_user_regs 428 bl do_irq 429 430 .align 5 431fiq: 432 get_bad_stack 433 bad_save_user_regs 434 bl do_fiq 435 436#endif 437