1/* 2 * armboot - Startup Code for ARM926EJS CPU-core 3 * 4 * Copyright (c) 2003 Texas Instruments 5 * 6 * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ 7 * 8 * Copyright (c) 2001 Marius Gr�ger <mag@sysgo.de> 9 * Copyright (c) 2002 Alex Z�pke <azu@sysgo.de> 10 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> 11 * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> 12 * Copyright (c) 2003 Kshitij <kshitij@ti.com> 13 * 14 * See file CREDITS for list of people who contributed to this 15 * project. 16 * 17 * This program is free software; you can redistribute it and/or 18 * modify it under the terms of the GNU General Public License as 19 * published by the Free Software Foundation; either version 2 of 20 * the License, or (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 30 * MA 02111-1307 USA 31 */ 32 33 34#include <config.h> 35#include <version.h> 36 37/* 38 ************************************************************************* 39 * 40 * Jump vector table 41 * 42 ************************************************************************* 43 */ 44 45.globl _start 46_start: 47 b reset 48 ldr pc, _undefined_instruction 49 ldr pc, _software_interrupt 50 ldr pc, _prefetch_abort 51 ldr pc, _data_abort 52 ldr pc, _not_used 53 ldr pc, _irq 54 ldr pc, _fiq 55 56_undefined_instruction: 57 .word undefined_instruction 58_software_interrupt: 59 .word software_interrupt 60_prefetch_abort: 61 .word prefetch_abort 62_data_abort: 63 .word data_abort 64_not_used: 65 .word not_used 66_irq: 67 .word irq 68_fiq: 69 .word fiq 70 71 .balignl 16,0xdeadbeef 72 73/* 74 ************************************************************************* 75 * 76 * Startup Code (reset vector) 77 * 78 * do important init only if we don't start from memory! 79 * setup memory and board specific bits prior to relocation. 80 * relocate armboot to ram 81 * setup stack 82 * 83 ************************************************************************* 84 */ 85 86_TEXT_BASE: 87 .word TEXT_BASE /* address of _start in the linked image */ 88 89.globl _armboot_start 90_armboot_start: 91 .word _start 92 93/* 94 * These are defined in the board-specific linker script. 95 */ 96.globl _bss_start 97_bss_start: 98 .word __bss_start 99 100.globl _bss_end 101_bss_end: 102 .word _end 103 104#ifdef CONFIG_USE_IRQ 105/* IRQ stack memory (calculated at run-time) */ 106.globl IRQ_STACK_START 107IRQ_STACK_START: 108 .word 0x0badc0de 109 110/* IRQ stack memory (calculated at run-time) */ 111.globl FIQ_STACK_START 112FIQ_STACK_START: 113 .word 0x0badc0de 114#endif 115 116 117/* 118 * the actual reset code 119 */ 120.globl reset 121reset: 122 /* 123 * set the cpu to SVC32 mode 124 */ 125 mrs r0,cpsr 126 bic r0,r0,#0x1f 127 orr r0,r0,#0xd3 128 msr cpsr,r0 129 130 /* 131 * we do sys-critical inits only at reboot, 132 * not when booting from ram! 133 */ 134#ifndef CONFIG_SKIP_LOWLEVEL_INIT 135 bl cpu_init_crit 136#endif 137 138relocate: /* relocate U-Boot to RAM */ 139 adr r0, _start /* pc relative address of label */ 140 ldr r1, _TEXT_BASE /* linked image address of label */ 141 cmp r0, r1 /* test if we run from flash or RAM */ 142 beq stack_setup /* ifeq we are in the RAM copy */ 143 144 ldr r2, _armboot_start 145 ldr r3, _bss_start 146 sub r2, r3, r2 /* r2 <- size of armboot */ 147 add r2, r0, r2 /* r2 <- source end address */ 148 149copy_loop: 150 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 151 stmia r1!, {r3-r10} /* copy to target address [r1] */ 152 cmp r0, r2 /* until source end addreee [r2] */ 153 ble copy_loop 154 155 /* Set up the stack */ 156stack_setup: 157 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 158 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 159 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 160#ifdef CONFIG_USE_IRQ 161 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 162#endif 163 sub sp, r0, #12 /* leave 3 words for abort-stack */ 164 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 165 166clear_bss: 167 ldr r0, _bss_start /* find start of bss segment */ 168 ldr r1, _bss_end /* stop here */ 169 mov r2, #0x00000000 /* clear */ 170 171clbss_l:str r2, [r0] /* clear loop... */ 172 add r0, r0, #4 173 cmp r0, r1 174 ble clbss_l 175 176 ldr pc, _start_armboot 177 178_start_armboot: 179 .word start_armboot 180 181/* 182 ************************************************************************* 183 * 184 * CPU_init_critical registers 185 * 186 * setup important registers 187 * setup memory timing 188 * 189 ************************************************************************* 190 */ 191 192#ifndef CONFIG_SKIP_LOWLEVEL_INIT 193cpu_init_crit: 194 /* arm_int_generic assumes the ARM boot monitor, or user software, 195 * has initialized the platform 196 */ 197 mov pc, lr /* back to my caller */ 198#endif 199/* 200 ************************************************************************* 201 * 202 * Interrupt handling 203 * 204 ************************************************************************* 205 */ 206 207@ 208@ IRQ stack frame. 209@ 210#define S_FRAME_SIZE 72 211 212#define S_OLD_R0 68 213#define S_PSR 64 214#define S_PC 60 215#define S_LR 56 216#define S_SP 52 217 218#define S_IP 48 219#define S_FP 44 220#define S_R10 40 221#define S_R9 36 222#define S_R8 32 223#define S_R7 28 224#define S_R6 24 225#define S_R5 20 226#define S_R4 16 227#define S_R3 12 228#define S_R2 8 229#define S_R1 4 230#define S_R0 0 231 232#define MODE_SVC 0x13 233#define I_BIT 0x80 234 235/* 236 * use bad_save_user_regs for abort/prefetch/undef/swi ... 237 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 238 */ 239 240 .macro bad_save_user_regs 241 @ carve out a frame on current user stack 242 sub sp, sp, #S_FRAME_SIZE 243 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 244 245 ldr r2, _armboot_start 246 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 247 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 248 @ get values for "aborted" pc and cpsr (into parm regs) 249 ldmia r2, {r2 - r3} 250 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 251 add r5, sp, #S_SP 252 mov r1, lr 253 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 254 mov r0, sp @ save current stack into r0 (param register) 255 .endm 256 257 .macro irq_save_user_regs 258 sub sp, sp, #S_FRAME_SIZE 259 stmia sp, {r0 - r12} @ Calling r0-r12 260 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 261 add r8, sp, #S_PC 262 stmdb r8, {sp, lr}^ @ Calling SP, LR 263 str lr, [r8, #0] @ Save calling PC 264 mrs r6, spsr 265 str r6, [r8, #4] @ Save CPSR 266 str r0, [r8, #8] @ Save OLD_R0 267 mov r0, sp 268 .endm 269 270 .macro irq_restore_user_regs 271 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 272 mov r0, r0 273 ldr lr, [sp, #S_PC] @ Get PC 274 add sp, sp, #S_FRAME_SIZE 275 subs pc, lr, #4 @ return & move spsr_svc into cpsr 276 .endm 277 278 .macro get_bad_stack 279 ldr r13, _armboot_start @ setup our mode stack 280 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 281 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 282 283 str lr, [r13] @ save caller lr in position 0 of saved stack 284 mrs lr, spsr @ get the spsr 285 str lr, [r13, #4] @ save spsr in position 1 of saved stack 286 mov r13, #MODE_SVC @ prepare SVC-Mode 287 @ msr spsr_c, r13 288 msr spsr, r13 @ switch modes, make sure moves will execute 289 mov lr, pc @ capture return pc 290 movs pc, lr @ jump to next instruction & switch modes. 291 .endm 292 293 .macro get_irq_stack @ setup IRQ stack 294 ldr sp, IRQ_STACK_START 295 .endm 296 297 .macro get_fiq_stack @ setup FIQ stack 298 ldr sp, FIQ_STACK_START 299 .endm 300 301/* 302 * exception handlers 303 */ 304 .align 5 305.globl undefined_instruction 306undefined_instruction: 307 get_bad_stack 308 bad_save_user_regs 309 bl do_undefined_instruction 310 311 .align 5 312.globl software_interrupt 313software_interrupt: 314 get_bad_stack 315 bad_save_user_regs 316 bl do_software_interrupt 317 318 .align 5 319.globl prefetch_abort 320prefetch_abort: 321 get_bad_stack 322 bad_save_user_regs 323 bl do_prefetch_abort 324 325 .align 5 326.globl data_abort 327data_abort: 328 get_bad_stack 329 bad_save_user_regs 330 bl do_data_abort 331 332 .align 5 333.globl not_used 334not_used: 335 get_bad_stack 336 bad_save_user_regs 337 bl do_not_used 338 339#ifdef CONFIG_USE_IRQ 340 .align 5 341.globl irq 342irq: 343 get_irq_stack 344 irq_save_user_regs 345 bl do_irq 346 irq_restore_user_regs 347 348 .align 5 349.globl fiq 350fiq: 351 get_fiq_stack 352 /* someone ought to write a more effiction fiq_save_user_regs */ 353 irq_save_user_regs 354 bl do_fiq 355 irq_restore_user_regs 356 357#else 358 359 .align 5 360.globl irq 361irq: 362 get_bad_stack 363 bad_save_user_regs 364 bl do_irq 365 366 .align 5 367.globl fiq 368fiq: 369 get_bad_stack 370 bad_save_user_regs 371 bl do_fiq 372 373#endif 374