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