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 167clear_bss: 168 ldr r0, _bss_start /* find start of bss segment */ 169 ldr r1, _bss_end /* stop here */ 170 mov r2, #0x00000000 /* clear */ 171 172clbss_l:str r2, [r0] /* clear loop... */ 173 add r0, r0, #4 174 cmp r0, r1 175 bne clbss_l 176 177 ldr pc, _start_armboot 178 179_start_armboot: 180 .word start_armboot 181 182 183/* 184 ************************************************************************* 185 * 186 * CPU_init_critical registers 187 * 188 * setup important registers 189 * setup memory timing 190 * 191 ************************************************************************* 192 */ 193 194 195#ifndef CONFIG_SKIP_LOWLEVEL_INIT 196cpu_init_crit: 197 /* 198 * flush v4 I/D caches 199 */ 200 mov r0, #0 201 mcr p15, 0, r0, c7, c5, 0 /* flush v4 I-cache */ 202 mcr p15, 0, r0, c7, c6, 0 /* flush v4 D-cache */ 203 204 /* 205 * disable MMU stuff and caches 206 */ 207 mrc p15, 0, r0, c1, c0, 0 208 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ 209 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ 210 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ 211 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ 212 mcr p15, 0, r0, c1, c0, 0 213 214 /* 215 * Go setup Memory and board specific bits prior to relocation. 216 */ 217 mov ip, lr /* perserve link reg across call */ 218 bl lowlevel_init /* go setup memory */ 219 mov lr, ip /* restore link */ 220 mov pc, lr /* back to my caller */ 221#endif 222/* 223 ************************************************************************* 224 * 225 * Interrupt handling 226 * 227 ************************************************************************* 228 */ 229 230@ 231@ IRQ stack frame. 232@ 233#define S_FRAME_SIZE 72 234 235#define S_OLD_R0 68 236#define S_PSR 64 237#define S_PC 60 238#define S_LR 56 239#define S_SP 52 240 241#define S_IP 48 242#define S_FP 44 243#define S_R10 40 244#define S_R9 36 245#define S_R8 32 246#define S_R7 28 247#define S_R6 24 248#define S_R5 20 249#define S_R4 16 250#define S_R3 12 251#define S_R2 8 252#define S_R1 4 253#define S_R0 0 254 255#define MODE_SVC 0x13 256#define I_BIT 0x80 257 258/* 259 * use bad_save_user_regs for abort/prefetch/undef/swi ... 260 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 261 */ 262 263 .macro bad_save_user_regs 264 @ carve out a frame on current user stack 265 sub sp, sp, #S_FRAME_SIZE 266 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 267 268 ldr r2, _armboot_start 269 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 270 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 271 @ get values for "aborted" pc and cpsr (into parm regs) 272 ldmia r2, {r2 - r3} 273 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 274 add r5, sp, #S_SP 275 mov r1, lr 276 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 277 mov r0, sp @ save current stack into r0 (param register) 278 .endm 279 280 .macro irq_save_user_regs 281 sub sp, sp, #S_FRAME_SIZE 282 stmia sp, {r0 - r12} @ Calling r0-r12 283 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 284 add r8, sp, #S_PC 285 stmdb r8, {sp, lr}^ @ Calling SP, LR 286 str lr, [r8, #0] @ Save calling PC 287 mrs r6, spsr 288 str r6, [r8, #4] @ Save CPSR 289 str r0, [r8, #8] @ Save OLD_R0 290 mov r0, sp 291 .endm 292 293 .macro irq_restore_user_regs 294 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 295 mov r0, r0 296 ldr lr, [sp, #S_PC] @ Get PC 297 add sp, sp, #S_FRAME_SIZE 298 subs pc, lr, #4 @ return & move spsr_svc into cpsr 299 .endm 300 301 .macro get_bad_stack 302 ldr r13, _armboot_start @ setup our mode stack 303 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 304 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 305 306 str lr, [r13] @ save caller lr in position 0 of saved stack 307 mrs lr, spsr @ get the spsr 308 str lr, [r13, #4] @ save spsr in position 1 of saved stack 309 mov r13, #MODE_SVC @ prepare SVC-Mode 310 @ msr spsr_c, r13 311 msr spsr, r13 @ switch modes, make sure moves will execute 312 mov lr, pc @ capture return pc 313 movs pc, lr @ jump to next instruction & switch modes. 314 .endm 315 316 .macro get_irq_stack @ setup IRQ stack 317 ldr sp, IRQ_STACK_START 318 .endm 319 320 .macro get_fiq_stack @ setup FIQ stack 321 ldr sp, FIQ_STACK_START 322 .endm 323 324/* 325 * exception handlers 326 */ 327 .align 5 328undefined_instruction: 329 get_bad_stack 330 bad_save_user_regs 331 bl do_undefined_instruction 332 333 .align 5 334software_interrupt: 335 get_bad_stack 336 bad_save_user_regs 337 bl do_software_interrupt 338 339 .align 5 340prefetch_abort: 341 get_bad_stack 342 bad_save_user_regs 343 bl do_prefetch_abort 344 345 .align 5 346data_abort: 347 get_bad_stack 348 bad_save_user_regs 349 bl do_data_abort 350 351 .align 5 352not_used: 353 get_bad_stack 354 bad_save_user_regs 355 bl do_not_used 356 357#ifdef CONFIG_USE_IRQ 358 359 .align 5 360irq: 361 get_irq_stack 362 irq_save_user_regs 363 bl do_irq 364 irq_restore_user_regs 365 366 .align 5 367fiq: 368 get_fiq_stack 369 /* someone ought to write a more effiction fiq_save_user_regs */ 370 irq_save_user_regs 371 bl do_fiq 372 irq_restore_user_regs 373 374#else 375 376 .align 5 377irq: 378 get_bad_stack 379 bad_save_user_regs 380 bl do_irq 381 382 .align 5 383fiq: 384 get_bad_stack 385 bad_save_user_regs 386 bl do_fiq 387 388#endif 389 390# ifdef CONFIG_INTEGRATOR 391 392 /* Satisfied by general board level routine */ 393 394#else 395 396 .align 5 397.globl reset_cpu 398reset_cpu: 399 400 ldr r1, rstctl1 /* get clkm1 reset ctl */ 401 mov r3, #0x0 402 strh r3, [r1] /* clear it */ 403 mov r3, #0x8 404 strh r3, [r1] /* force dsp+arm reset */ 405_loop_forever: 406 b _loop_forever 407 408rstctl1: 409 .word 0xfffece10 410 411#endif /* #ifdef CONFIG_INTEGRATOR */ 412