1/* 2 * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core 3 * 4 * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com> 5 * 6 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> 7 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> 8 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> 9 * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> 10 * Copyright (c) 2003 Kshitij <kshitij@ti.com> 11 * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com> 12 * 13 * See file CREDITS for list of people who contributed to this 14 * project. 15 * 16 * This program is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU General Public License as 18 * published by the Free Software Foundation; either version 2 of 19 * the License, or (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 29 * MA 02111-1307 USA 30 */ 31 32#include <config.h> 33#include <version.h> 34 35.globl _start 36_start: b reset 37 ldr pc, _undefined_instruction 38 ldr pc, _software_interrupt 39 ldr pc, _prefetch_abort 40 ldr pc, _data_abort 41 ldr pc, _not_used 42 ldr pc, _irq 43 ldr pc, _fiq 44 45_undefined_instruction: .word undefined_instruction 46_software_interrupt: .word software_interrupt 47_prefetch_abort: .word prefetch_abort 48_data_abort: .word data_abort 49_not_used: .word not_used 50_irq: .word irq 51_fiq: .word fiq 52_pad: .word 0x12345678 /* now 16*4=64 */ 53.global _end_vect 54_end_vect: 55 56 .balignl 16,0xdeadbeef 57/************************************************************************* 58 * 59 * Startup Code (reset vector) 60 * 61 * do important init only if we don't start from memory! 62 * setup Memory and board specific bits prior to relocation. 63 * relocate armboot to ram 64 * setup stack 65 * 66 *************************************************************************/ 67 68_TEXT_BASE: 69 .word TEXT_BASE 70 71.globl _armboot_start 72_armboot_start: 73 .word _start 74 75/* 76 * These are defined in the board-specific linker script. 77 */ 78.globl _bss_start 79_bss_start: 80 .word __bss_start 81 82.globl _bss_end 83_bss_end: 84 .word _end 85 86#ifdef CONFIG_USE_IRQ 87/* IRQ stack memory (calculated at run-time) */ 88.globl IRQ_STACK_START 89IRQ_STACK_START: 90 .word 0x0badc0de 91 92/* IRQ stack memory (calculated at run-time) */ 93.globl FIQ_STACK_START 94FIQ_STACK_START: 95 .word 0x0badc0de 96#endif 97 98/* 99 * the actual reset code 100 */ 101 102reset: 103 /* 104 * set the cpu to SVC32 mode 105 */ 106 mrs r0, cpsr 107 bic r0, r0, #0x1f 108 orr r0, r0, #0xd3 109 msr cpsr,r0 110 111#if (CONFIG_OMAP34XX) 112 /* Copy vectors to mask ROM indirect addr */ 113 adr r0, _start @ r0 <- current position of code 114 add r0, r0, #4 @ skip reset vector 115 mov r2, #64 @ r2 <- size to copy 116 add r2, r0, r2 @ r2 <- source end address 117 mov r1, #SRAM_OFFSET0 @ build vect addr 118 mov r3, #SRAM_OFFSET1 119 add r1, r1, r3 120 mov r3, #SRAM_OFFSET2 121 add r1, r1, r3 122next: 123 ldmia r0!, {r3 - r10} @ copy from source address [r0] 124 stmia r1!, {r3 - r10} @ copy to target address [r1] 125 cmp r0, r2 @ until source end address [r2] 126 bne next @ loop until equal */ 127#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT) 128 /* No need to copy/exec the clock code - DPLL adjust already done 129 * in NAND/oneNAND Boot. 130 */ 131 bl cpy_clk_code @ put dpll adjust code behind vectors 132#endif /* NAND Boot */ 133#endif 134 /* the mask ROM code should have PLL and others stable */ 135#ifndef CONFIG_SKIP_LOWLEVEL_INIT 136 bl cpu_init_crit 137#endif 138 139#ifndef CONFIG_SKIP_RELOCATE_UBOOT 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: @ copy 32 bytes at a time 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#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 157 158 /* Set up the stack */ 159stack_setup: 160 ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot 161 sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area 162 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo 163#ifdef CONFIG_USE_IRQ 164 sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ) 165#endif 166 sub sp, r0, #12 @ leave 3 words for abort-stack 167 bic sp, sp, #7 @ 8-byte alignment for ABI compliance 168 169 /* Clear BSS (if any). Is below tx (watch load addr - need space) */ 170clear_bss: 171 ldr r0, _bss_start @ find start of bss segment 172 ldr r1, _bss_end @ stop here 173 mov r2, #0x00000000 @ clear value 174clbss_l: 175 str r2, [r0] @ clear BSS location 176 cmp r0, r1 @ are we at the end yet 177 add r0, r0, #4 @ increment clear index pointer 178 bne clbss_l @ keep clearing till at end 179 180 ldr pc, _start_armboot @ jump to C code 181 182_start_armboot: .word start_armboot 183 184 185/************************************************************************* 186 * 187 * CPU_init_critical registers 188 * 189 * setup important registers 190 * setup memory timing 191 * 192 *************************************************************************/ 193cpu_init_crit: 194 /* 195 * Invalidate L1 I/D 196 */ 197 mov r0, #0 @ set up for MCR 198 mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs 199 mcr p15, 0, r0, c7, c5, 0 @ invalidate icache 200 201 /* 202 * disable MMU stuff and caches 203 */ 204 mrc p15, 0, r0, c1, c0, 0 205 bic r0, r0, #0x00002000 @ clear bits 13 (--V-) 206 bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) 207 orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align 208 orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB 209 mcr p15, 0, r0, c1, c0, 0 210 211 /* 212 * Jump to board specific initialization... 213 * The Mask ROM will have already initialized 214 * basic memory. Go here to bump up clock rate and handle 215 * wake up conditions. 216 */ 217 mov ip, lr @ persevere link reg across call 218 bl lowlevel_init @ go setup pll,mux,memory 219 mov lr, ip @ restore link 220 mov pc, lr @ back to my caller 221/* 222 ************************************************************************* 223 * 224 * Interrupt handling 225 * 226 ************************************************************************* 227 */ 228@ 229@ IRQ stack frame. 230@ 231#define S_FRAME_SIZE 72 232 233#define S_OLD_R0 68 234#define S_PSR 64 235#define S_PC 60 236#define S_LR 56 237#define S_SP 52 238 239#define S_IP 48 240#define S_FP 44 241#define S_R10 40 242#define S_R9 36 243#define S_R8 32 244#define S_R7 28 245#define S_R6 24 246#define S_R5 20 247#define S_R4 16 248#define S_R3 12 249#define S_R2 8 250#define S_R1 4 251#define S_R0 0 252 253#define MODE_SVC 0x13 254#define I_BIT 0x80 255 256/* 257 * use bad_save_user_regs for abort/prefetch/undef/swi ... 258 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 259 */ 260 261 .macro bad_save_user_regs 262 sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current 263 @ user stack 264 stmia sp, {r0 - r12} @ Save user registers (now in 265 @ svc mode) r0-r12 266 267 ldr r2, _armboot_start 268 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) 269 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort 270 @ stack 271 ldmia r2, {r2 - r3} @ get values for "aborted" pc 272 @ and cpsr (into parm regs) 273 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 274 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 279 @ (param register) 280 .endm 281 282 .macro irq_save_user_regs 283 sub sp, sp, #S_FRAME_SIZE 284 stmia sp, {r0 - r12} @ Calling r0-r12 285 add r8, sp, #S_PC @ !! R8 NEEDS to be saved !! 286 @ a reserved stack spot would 287 @ be good. 288 stmdb r8, {sp, lr}^ @ Calling SP, LR 289 str lr, [r8, #0] @ Save calling PC 290 mrs r6, spsr 291 str r6, [r8, #4] @ Save CPSR 292 str r0, [r8, #8] @ Save OLD_R0 293 mov r0, sp 294 .endm 295 296 .macro irq_restore_user_regs 297 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 298 mov r0, r0 299 ldr lr, [sp, #S_PC] @ Get PC 300 add sp, sp, #S_FRAME_SIZE 301 subs pc, lr, #4 @ return & move spsr_svc into 302 @ cpsr 303 .endm 304 305 .macro get_bad_stack 306 ldr r13, _armboot_start @ setup our mode stack (enter 307 @ in banked mode) 308 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool 309 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple 310 @ spots for abort stack 311 312 str lr, [r13] @ save caller lr in position 0 313 @ of saved stack 314 mrs lr, spsr @ get the spsr 315 str lr, [r13, #4] @ save spsr in position 1 of 316 @ saved stack 317 318 mov r13, #MODE_SVC @ prepare SVC-Mode 319 @ msr spsr_c, r13 320 msr spsr, r13 @ switch modes, make sure 321 @ moves will execute 322 mov lr, pc @ capture return pc 323 movs pc, lr @ jump to next instruction & 324 @ switch modes. 325 .endm 326 327 .macro get_bad_stack_swi 328 sub r13, r13, #4 @ space on current stack for 329 @ scratch reg. 330 str r0, [r13] @ save R0's value. 331 ldr r0, _armboot_start @ get data regions start 332 sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool 333 sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple 334 @ spots for abort stack 335 str lr, [r0] @ save caller lr in position 0 336 @ of saved stack 337 mrs r0, spsr @ get the spsr 338 str lr, [r0, #4] @ save spsr in position 1 of 339 @ saved stack 340 ldr r0, [r13] @ restore r0 341 add r13, r13, #4 @ pop stack entry 342 .endm 343 344 .macro get_irq_stack @ setup IRQ stack 345 ldr sp, IRQ_STACK_START 346 .endm 347 348 .macro get_fiq_stack @ setup FIQ stack 349 ldr sp, FIQ_STACK_START 350 .endm 351 352/* 353 * exception handlers 354 */ 355 .align 5 356undefined_instruction: 357 get_bad_stack 358 bad_save_user_regs 359 bl do_undefined_instruction 360 361 .align 5 362software_interrupt: 363 get_bad_stack_swi 364 bad_save_user_regs 365 bl do_software_interrupt 366 367 .align 5 368prefetch_abort: 369 get_bad_stack 370 bad_save_user_regs 371 bl do_prefetch_abort 372 373 .align 5 374data_abort: 375 get_bad_stack 376 bad_save_user_regs 377 bl do_data_abort 378 379 .align 5 380not_used: 381 get_bad_stack 382 bad_save_user_regs 383 bl do_not_used 384 385#ifdef CONFIG_USE_IRQ 386 387 .align 5 388irq: 389 get_irq_stack 390 irq_save_user_regs 391 bl do_irq 392 irq_restore_user_regs 393 394 .align 5 395fiq: 396 get_fiq_stack 397 /* someone ought to write a more effective fiq_save_user_regs */ 398 irq_save_user_regs 399 bl do_fiq 400 irq_restore_user_regs 401 402#else 403 404 .align 5 405irq: 406 get_bad_stack 407 bad_save_user_regs 408 bl do_irq 409 410 .align 5 411fiq: 412 get_bad_stack 413 bad_save_user_regs 414 bl do_fiq 415 416#endif 417