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 as in table 3.1 in [1] 41 * 42 ************************************************************************* 43 */ 44 45 46.globl _start 47_start: 48 b reset 49 ldr pc, _undefined_instruction 50 ldr pc, _software_interrupt 51 ldr pc, _prefetch_abort 52 ldr pc, _data_abort 53 ldr pc, _not_used 54 ldr pc, _irq 55 ldr pc, _fiq 56 57_undefined_instruction: 58 .word undefined_instruction 59_software_interrupt: 60 .word software_interrupt 61_prefetch_abort: 62 .word prefetch_abort 63_data_abort: 64 .word data_abort 65_not_used: 66 .word not_used 67_irq: 68 .word irq 69_fiq: 70 .word fiq 71 72 .balignl 16,0xdeadbeef 73 74 75/* 76 ************************************************************************* 77 * 78 * Startup Code (reset vector) 79 * 80 * do important init only if we don't start from memory! 81 * setup Memory and board specific bits prior to relocation. 82 * relocate armboot to ram 83 * setup stack 84 * 85 ************************************************************************* 86 */ 87 88_TEXT_BASE: 89 .word TEXT_BASE 90 91.globl _armboot_start 92_armboot_start: 93 .word _start 94 95/* 96 * These are defined in the board-specific linker script. 97 */ 98.globl _bss_start 99_bss_start: 100 .word __bss_start 101 102.globl _bss_end 103_bss_end: 104 .word _end 105 106#ifdef CONFIG_USE_IRQ 107/* IRQ stack memory (calculated at run-time) */ 108.globl IRQ_STACK_START 109IRQ_STACK_START: 110 .word 0x0badc0de 111 112/* IRQ stack memory (calculated at run-time) */ 113.globl FIQ_STACK_START 114FIQ_STACK_START: 115 .word 0x0badc0de 116#endif 117 118 119/* 120 * the actual reset code 121 */ 122 123reset: 124 /* 125 * set the cpu to SVC32 mode 126 */ 127 mrs r0,cpsr 128 bic r0,r0,#0x1f 129 orr r0,r0,#0xd3 130 msr cpsr,r0 131 132 /* 133 * we do sys-critical inits only at reboot, 134 * not when booting from ram! 135 */ 136#ifndef CONFIG_SKIP_LOWLEVEL_INIT 137 bl cpu_init_crit 138#endif 139 140relocate: /* relocate U-Boot to RAM */ 141 adr r0, _start /* r0 <- current position of code */ 142 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 143 cmp r0, r1 /* don't reloc during debug */ 144 beq stack_setup 145 146 ldr r2, _armboot_start 147 ldr r3, _bss_start 148 sub r2, r3, r2 /* r2 <- size of armboot */ 149 add r2, r0, r2 /* r2 <- source end address */ 150 151copy_loop: 152 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 153 stmia r1!, {r3-r10} /* copy to target address [r1] */ 154 cmp r0, r2 /* until source end addreee [r2] */ 155 ble copy_loop 156 157 /* Set up the stack */ 158stack_setup: 159 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 160 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 161 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 162#ifdef CONFIG_USE_IRQ 163 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 164#endif 165 sub sp, r0, #12 /* leave 3 words for abort-stack */ 166 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 167 168clear_bss: 169 ldr r0, _bss_start /* find start of bss segment */ 170 ldr r1, _bss_end /* stop here */ 171 mov r2, #0x00000000 /* clear */ 172 173clbss_l:str r2, [r0] /* clear loop... */ 174 add r0, r0, #4 175 cmp r0, r1 176 bne clbss_l 177 178 ldr pc, _start_armboot 179 180_start_armboot: 181 .word start_armboot 182 183 184/* 185 ************************************************************************* 186 * 187 * CPU_init_critical registers 188 * 189 * setup important registers 190 * setup memory timing 191 * 192 ************************************************************************* 193 */ 194 195 196#ifndef CONFIG_SKIP_LOWLEVEL_INIT 197cpu_init_crit: 198 /* 199 * flush v4 I/D caches 200 */ 201 mov r0, #0 202 mcr p15, 0, r0, c7, c5, 0 /* flush v4 I-cache */ 203 mcr p15, 0, r0, c7, c6, 0 /* flush v4 D-cache */ 204 205 /* 206 * disable MMU stuff and caches 207 */ 208 mrc p15, 0, r0, c1, c0, 0 209 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ 210 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ 211 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ 212 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ 213 mcr p15, 0, r0, c1, c0, 0 214 215 /* 216 * Go setup Memory and board specific bits prior to relocation. 217 */ 218 mov ip, lr /* perserve link reg across call */ 219 bl lowlevel_init /* go setup memory */ 220 mov lr, ip /* restore link */ 221 mov pc, lr /* back to my caller */ 222#endif 223/* 224 ************************************************************************* 225 * 226 * Interrupt handling 227 * 228 ************************************************************************* 229 */ 230 231@ 232@ IRQ stack frame. 233@ 234#define S_FRAME_SIZE 72 235 236#define S_OLD_R0 68 237#define S_PSR 64 238#define S_PC 60 239#define S_LR 56 240#define S_SP 52 241 242#define S_IP 48 243#define S_FP 44 244#define S_R10 40 245#define S_R9 36 246#define S_R8 32 247#define S_R7 28 248#define S_R6 24 249#define S_R5 20 250#define S_R4 16 251#define S_R3 12 252#define S_R2 8 253#define S_R1 4 254#define S_R0 0 255 256#define MODE_SVC 0x13 257#define I_BIT 0x80 258 259/* 260 * use bad_save_user_regs for abort/prefetch/undef/swi ... 261 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 262 */ 263 264 .macro bad_save_user_regs 265 @ carve out a frame on current user stack 266 sub sp, sp, #S_FRAME_SIZE 267 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 268 269 ldr r2, _armboot_start 270 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 271 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 272 @ get values for "aborted" pc and cpsr (into parm regs) 273 ldmia r2, {r2 - r3} 274 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 275 add r5, sp, #S_SP 276 mov r1, lr 277 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 278 mov r0, sp @ save current stack into r0 (param register) 279 .endm 280 281 .macro irq_save_user_regs 282 sub sp, sp, #S_FRAME_SIZE 283 stmia sp, {r0 - r12} @ Calling r0-r12 284 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 285 add r8, sp, #S_PC 286 stmdb r8, {sp, lr}^ @ Calling SP, LR 287 str lr, [r8, #0] @ Save calling PC 288 mrs r6, spsr 289 str r6, [r8, #4] @ Save CPSR 290 str r0, [r8, #8] @ Save OLD_R0 291 mov r0, sp 292 .endm 293 294 .macro irq_restore_user_regs 295 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 296 mov r0, r0 297 ldr lr, [sp, #S_PC] @ Get PC 298 add sp, sp, #S_FRAME_SIZE 299 subs pc, lr, #4 @ return & move spsr_svc into cpsr 300 .endm 301 302 .macro get_bad_stack 303 ldr r13, _armboot_start @ setup our mode stack 304 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 305 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 306 307 str lr, [r13] @ save caller lr in position 0 of saved stack 308 mrs lr, spsr @ get the spsr 309 str lr, [r13, #4] @ save spsr in position 1 of saved stack 310 mov r13, #MODE_SVC @ prepare SVC-Mode 311 @ msr spsr_c, r13 312 msr spsr, r13 @ switch modes, make sure moves will execute 313 mov lr, pc @ capture return pc 314 movs pc, lr @ jump to next instruction & switch modes. 315 .endm 316 317 .macro get_irq_stack @ setup IRQ stack 318 ldr sp, IRQ_STACK_START 319 .endm 320 321 .macro get_fiq_stack @ setup FIQ stack 322 ldr sp, FIQ_STACK_START 323 .endm 324 325/* 326 * exception handlers 327 */ 328 .align 5 329undefined_instruction: 330 get_bad_stack 331 bad_save_user_regs 332 bl do_undefined_instruction 333 334 .align 5 335software_interrupt: 336 get_bad_stack 337 bad_save_user_regs 338 bl do_software_interrupt 339 340 .align 5 341prefetch_abort: 342 get_bad_stack 343 bad_save_user_regs 344 bl do_prefetch_abort 345 346 .align 5 347data_abort: 348 get_bad_stack 349 bad_save_user_regs 350 bl do_data_abort 351 352 .align 5 353not_used: 354 get_bad_stack 355 bad_save_user_regs 356 bl do_not_used 357 358#ifdef CONFIG_USE_IRQ 359 360 .align 5 361irq: 362 get_irq_stack 363 irq_save_user_regs 364 bl do_irq 365 irq_restore_user_regs 366 367 .align 5 368fiq: 369 get_fiq_stack 370 /* someone ought to write a more effiction fiq_save_user_regs */ 371 irq_save_user_regs 372 bl do_fiq 373 irq_restore_user_regs 374 375#else 376 377 .align 5 378irq: 379 get_bad_stack 380 bad_save_user_regs 381 bl do_irq 382 383 .align 5 384fiq: 385 get_bad_stack 386 bad_save_user_regs 387 bl do_fiq 388 389#endif 390 391# ifdef CONFIG_INTEGRATOR 392 393 /* Satisfied by general board level routine */ 394 395#else 396 397 .align 5 398.globl reset_cpu 399reset_cpu: 400 401 ldr r1, rstctl1 /* get clkm1 reset ctl */ 402 mov r3, #0x0 403 strh r3, [r1] /* clear it */ 404 mov r3, #0x8 405 strh r3, [r1] /* force dsp+arm reset */ 406_loop_forever: 407 b _loop_forever 408 409rstctl1: 410 .word 0xfffece10 411 412#endif /* #ifdef CONFIG_INTEGRATOR */ 413