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.globl _TEXT_BASE 69_TEXT_BASE: 70 .word CONFIG_SYS_TEXT_BASE 71 72#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 73.globl _armboot_start 74_armboot_start: 75 .word _start 76#endif 77 78/* 79 * These are defined in the board-specific linker script. 80 */ 81.globl _bss_start 82_bss_start: 83 .word __bss_start 84 85.globl _bss_end 86_bss_end: 87 .word _end 88 89#ifdef CONFIG_USE_IRQ 90/* IRQ stack memory (calculated at run-time) */ 91.globl IRQ_STACK_START 92IRQ_STACK_START: 93 .word 0x0badc0de 94 95/* IRQ stack memory (calculated at run-time) */ 96.globl FIQ_STACK_START 97FIQ_STACK_START: 98 .word 0x0badc0de 99#endif 100 101#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 102/* IRQ stack memory (calculated at run-time) + 8 bytes */ 103.globl IRQ_STACK_START_IN 104IRQ_STACK_START_IN: 105 .word 0x0badc0de 106 107.globl _datarel_start 108_datarel_start: 109 .word __datarel_start 110 111.globl _datarelrolocal_start 112_datarelrolocal_start: 113 .word __datarelrolocal_start 114 115.globl _datarellocal_start 116_datarellocal_start: 117 .word __datarellocal_start 118 119.globl _datarelro_start 120_datarelro_start: 121 .word __datarelro_start 122 123.globl _got_start 124_got_start: 125 .word __got_start 126 127.globl _got_end 128_got_end: 129 .word __got_end 130 131/* 132 * the actual reset code 133 */ 134 135reset: 136 /* 137 * set the cpu to SVC32 mode 138 */ 139 mrs r0, cpsr 140 bic r0, r0, #0x1f 141 orr r0, r0, #0xd3 142 msr cpsr,r0 143 144#if (CONFIG_OMAP34XX) 145 /* Copy vectors to mask ROM indirect addr */ 146 adr r0, _start @ r0 <- current position of code 147 add r0, r0, #4 @ skip reset vector 148 mov r2, #64 @ r2 <- size to copy 149 add r2, r0, r2 @ r2 <- source end address 150 mov r1, #SRAM_OFFSET0 @ build vect addr 151 mov r3, #SRAM_OFFSET1 152 add r1, r1, r3 153 mov r3, #SRAM_OFFSET2 154 add r1, r1, r3 155next: 156 ldmia r0!, {r3 - r10} @ copy from source address [r0] 157 stmia r1!, {r3 - r10} @ copy to target address [r1] 158 cmp r0, r2 @ until source end address [r2] 159 bne next @ loop until equal */ 160#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT) 161 /* No need to copy/exec the clock code - DPLL adjust already done 162 * in NAND/oneNAND Boot. 163 */ 164 bl cpy_clk_code @ put dpll adjust code behind vectors 165#endif /* NAND Boot */ 166#endif 167 /* the mask ROM code should have PLL and others stable */ 168#ifndef CONFIG_SKIP_LOWLEVEL_INIT 169 bl cpu_init_crit 170#endif 171 172/* Set stackpointer in internal RAM to call board_init_f */ 173call_board_init_f: 174 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 175 ldr r0,=0x00000000 176 bl board_init_f 177 178/*------------------------------------------------------------------------------*/ 179 180/* 181 * void relocate_code (addr_sp, gd, addr_moni) 182 * 183 * This "function" does not return, instead it continues in RAM 184 * after relocating the monitor code. 185 * 186 */ 187 .globl relocate_code 188relocate_code: 189 mov r4, r0 /* save addr_sp */ 190 mov r5, r1 /* save addr of gd */ 191 mov r6, r2 /* save addr of destination */ 192 mov r7, r2 /* save addr of destination */ 193 194 /* Set up the stack */ 195stack_setup: 196 mov sp, r4 197 198#ifndef CONFIG_SKIP_RELOCATE_UBOOT 199 adr r0, _start 200 ldr r2, _TEXT_BASE 201 ldr r3, _bss_start 202 sub r2, r3, r2 /* r2 <- size of armboot */ 203 add r2, r0, r2 /* r2 <- source end address */ 204 cmp r0, r6 205#ifndef CONFIG_PRELOADER 206 beq jump_2_ram 207#endif 208 209copy_loop: 210 ldmia r0!, {r9-r10} /* copy from source address [r0] */ 211 stmia r6!, {r9-r10} /* copy to target address [r1] */ 212 cmp r0, r2 /* until source end address [r2] */ 213 blo copy_loop 214 215#ifndef CONFIG_PRELOADER 216 /* fix got entries */ 217 ldr r1, _TEXT_BASE 218 mov r0, r7 /* reloc addr */ 219 ldr r2, _got_start /* addr in Flash */ 220 ldr r3, _got_end /* addr in Flash */ 221 sub r3, r3, r1 222 add r3, r3, r0 223 sub r2, r2, r1 224 add r2, r2, r0 225 226fixloop: 227 ldr r4, [r2] 228 sub r4, r4, r1 229 add r4, r4, r0 230 str r4, [r2] 231 add r2, r2, #4 232 cmp r2, r3 233 bne fixloop 234 235clear_bss: 236 ldr r0, _bss_start 237 ldr r1, _bss_end 238 ldr r3, _TEXT_BASE /* Text base */ 239 mov r4, r7 /* reloc addr */ 240 sub r0, r0, r3 241 add r0, r0, r4 242 sub r1, r1, r3 243 add r1, r1, r4 244 mov r2, #0x00000000 /* clear */ 245 246clbss_l:str r2, [r0] /* clear loop... */ 247 add r0, r0, #4 248 cmp r0, r1 249 bne clbss_l 250#endif /* #ifndef CONFIG_PRELOADER */ 251#endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */ 252 253/* 254 * We are done. Do not return, instead branch to second part of board 255 * initialization, now running from RAM. 256 */ 257jump_2_ram: 258 ldr r0, _TEXT_BASE 259 ldr r2, _board_init_r 260 sub r2, r2, r0 261 add r2, r2, r7 /* position from board_init_r in RAM */ 262 /* setup parameters for board_init_r */ 263 mov r0, r5 /* gd_t */ 264 mov r1, r7 /* dest_addr */ 265 /* jump to it ... */ 266 mov lr, r2 267 mov pc, lr 268 269_board_init_r: .word board_init_r 270#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ 271/* 272 * the actual reset code 273 */ 274 275reset: 276 /* 277 * set the cpu to SVC32 mode 278 */ 279 mrs r0, cpsr 280 bic r0, r0, #0x1f 281 orr r0, r0, #0xd3 282 msr cpsr,r0 283 284#if (CONFIG_OMAP34XX) 285 /* Copy vectors to mask ROM indirect addr */ 286 adr r0, _start @ r0 <- current position of code 287 add r0, r0, #4 @ skip reset vector 288 mov r2, #64 @ r2 <- size to copy 289 add r2, r0, r2 @ r2 <- source end address 290 mov r1, #SRAM_OFFSET0 @ build vect addr 291 mov r3, #SRAM_OFFSET1 292 add r1, r1, r3 293 mov r3, #SRAM_OFFSET2 294 add r1, r1, r3 295next: 296 ldmia r0!, {r3 - r10} @ copy from source address [r0] 297 stmia r1!, {r3 - r10} @ copy to target address [r1] 298 cmp r0, r2 @ until source end address [r2] 299 bne next @ loop until equal */ 300#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT) 301 /* No need to copy/exec the clock code - DPLL adjust already done 302 * in NAND/oneNAND Boot. 303 */ 304 bl cpy_clk_code @ put dpll adjust code behind vectors 305#endif /* NAND Boot */ 306#endif 307 /* the mask ROM code should have PLL and others stable */ 308#ifndef CONFIG_SKIP_LOWLEVEL_INIT 309 bl cpu_init_crit 310#endif 311 312#ifndef CONFIG_SKIP_RELOCATE_UBOOT 313relocate: @ relocate U-Boot to RAM 314 adr r0, _start @ r0 <- current position of code 315 ldr r1, _TEXT_BASE @ test if we run from flash or RAM 316 cmp r0, r1 @ don't reloc during debug 317 beq stack_setup 318 319 ldr r2, _armboot_start 320 ldr r3, _bss_start 321 sub r2, r3, r2 @ r2 <- size of armboot 322 add r2, r0, r2 @ r2 <- source end address 323 324copy_loop: @ copy 32 bytes at a time 325 ldmia r0!, {r3 - r10} @ copy from source address [r0] 326 stmia r1!, {r3 - r10} @ copy to target address [r1] 327 cmp r0, r2 @ until source end address [r2] 328 blo copy_loop 329#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 330 331 /* Set up the stack */ 332stack_setup: 333 ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot 334 sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area 335 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo 336#ifdef CONFIG_USE_IRQ 337 sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ) 338#endif 339 sub sp, r0, #12 @ leave 3 words for abort-stack 340 bic sp, sp, #7 @ 8-byte alignment for ABI compliance 341 342 /* Clear BSS (if any). Is below tx (watch load addr - need space) */ 343clear_bss: 344 ldr r0, _bss_start @ find start of bss segment 345 ldr r1, _bss_end @ stop here 346 mov r2, #0x00000000 @ clear value 347clbss_l: 348 str r2, [r0] @ clear BSS location 349 cmp r0, r1 @ are we at the end yet 350 add r0, r0, #4 @ increment clear index pointer 351 bne clbss_l @ keep clearing till at end 352 353 ldr pc, _start_armboot @ jump to C code 354 355_start_armboot: .word start_armboot 356#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ 357 358/************************************************************************* 359 * 360 * CPU_init_critical registers 361 * 362 * setup important registers 363 * setup memory timing 364 * 365 *************************************************************************/ 366cpu_init_crit: 367 /* 368 * Invalidate L1 I/D 369 */ 370 mov r0, #0 @ set up for MCR 371 mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs 372 mcr p15, 0, r0, c7, c5, 0 @ invalidate icache 373 374 /* 375 * disable MMU stuff and caches 376 */ 377 mrc p15, 0, r0, c1, c0, 0 378 bic r0, r0, #0x00002000 @ clear bits 13 (--V-) 379 bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) 380 orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align 381 orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB 382 mcr p15, 0, r0, c1, c0, 0 383 384 /* 385 * Jump to board specific initialization... 386 * The Mask ROM will have already initialized 387 * basic memory. Go here to bump up clock rate and handle 388 * wake up conditions. 389 */ 390 mov ip, lr @ persevere link reg across call 391 bl lowlevel_init @ go setup pll,mux,memory 392 mov lr, ip @ restore link 393 mov pc, lr @ back to my caller 394/* 395 ************************************************************************* 396 * 397 * Interrupt handling 398 * 399 ************************************************************************* 400 */ 401@ 402@ IRQ stack frame. 403@ 404#define S_FRAME_SIZE 72 405 406#define S_OLD_R0 68 407#define S_PSR 64 408#define S_PC 60 409#define S_LR 56 410#define S_SP 52 411 412#define S_IP 48 413#define S_FP 44 414#define S_R10 40 415#define S_R9 36 416#define S_R8 32 417#define S_R7 28 418#define S_R6 24 419#define S_R5 20 420#define S_R4 16 421#define S_R3 12 422#define S_R2 8 423#define S_R1 4 424#define S_R0 0 425 426#define MODE_SVC 0x13 427#define I_BIT 0x80 428 429/* 430 * use bad_save_user_regs for abort/prefetch/undef/swi ... 431 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 432 */ 433 434 .macro bad_save_user_regs 435 sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current 436 @ user stack 437 stmia sp, {r0 - r12} @ Save user registers (now in 438 @ svc mode) r0-r12 439#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 440 ldr r2, _armboot_start 441 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) 442 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort 443#else 444 ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort 445 @ stack 446#endif 447 ldmia r2, {r2 - r3} @ get values for "aborted" pc 448 @ and cpsr (into parm regs) 449 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 450 451 add r5, sp, #S_SP 452 mov r1, lr 453 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 454 mov r0, sp @ save current stack into r0 455 @ (param register) 456 .endm 457 458 .macro irq_save_user_regs 459 sub sp, sp, #S_FRAME_SIZE 460 stmia sp, {r0 - r12} @ Calling r0-r12 461 add r8, sp, #S_PC @ !! R8 NEEDS to be saved !! 462 @ a reserved stack spot would 463 @ be good. 464 stmdb r8, {sp, lr}^ @ Calling SP, LR 465 str lr, [r8, #0] @ Save calling PC 466 mrs r6, spsr 467 str r6, [r8, #4] @ Save CPSR 468 str r0, [r8, #8] @ Save OLD_R0 469 mov r0, sp 470 .endm 471 472 .macro irq_restore_user_regs 473 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 474 mov r0, r0 475 ldr lr, [sp, #S_PC] @ Get PC 476 add sp, sp, #S_FRAME_SIZE 477 subs pc, lr, #4 @ return & move spsr_svc into 478 @ cpsr 479 .endm 480 481 .macro get_bad_stack 482#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 483 ldr r13, _armboot_start @ setup our mode stack (enter 484 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool 485 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple 486#else 487 ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter 488 @ in banked mode) 489#endif 490 491 str lr, [r13] @ save caller lr in position 0 492 @ of saved stack 493 mrs lr, spsr @ get the spsr 494 str lr, [r13, #4] @ save spsr in position 1 of 495 @ saved stack 496 497 mov r13, #MODE_SVC @ prepare SVC-Mode 498 @ msr spsr_c, r13 499 msr spsr, r13 @ switch modes, make sure 500 @ moves will execute 501 mov lr, pc @ capture return pc 502 movs pc, lr @ jump to next instruction & 503 @ switch modes. 504 .endm 505 506 .macro get_bad_stack_swi 507 sub r13, r13, #4 @ space on current stack for 508 @ scratch reg. 509 str r0, [r13] @ save R0's value. 510#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 511 ldr r0, _armboot_start @ get data regions start 512 sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool 513 sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple 514#else 515 ldr r0, IRQ_STACK_START_IN @ get data regions start 516 @ spots for abort stack 517#endif 518 str lr, [r0] @ save caller lr in position 0 519 @ of saved stack 520 mrs r0, spsr @ get the spsr 521 str lr, [r0, #4] @ save spsr in position 1 of 522 @ saved stack 523 ldr r0, [r13] @ restore r0 524 add r13, r13, #4 @ pop stack entry 525 .endm 526 527 .macro get_irq_stack @ setup IRQ stack 528 ldr sp, IRQ_STACK_START 529 .endm 530 531 .macro get_fiq_stack @ setup FIQ stack 532 ldr sp, FIQ_STACK_START 533 .endm 534 535/* 536 * exception handlers 537 */ 538 .align 5 539undefined_instruction: 540 get_bad_stack 541 bad_save_user_regs 542 bl do_undefined_instruction 543 544 .align 5 545software_interrupt: 546 get_bad_stack_swi 547 bad_save_user_regs 548 bl do_software_interrupt 549 550 .align 5 551prefetch_abort: 552 get_bad_stack 553 bad_save_user_regs 554 bl do_prefetch_abort 555 556 .align 5 557data_abort: 558 get_bad_stack 559 bad_save_user_regs 560 bl do_data_abort 561 562 .align 5 563not_used: 564 get_bad_stack 565 bad_save_user_regs 566 bl do_not_used 567 568#ifdef CONFIG_USE_IRQ 569 570 .align 5 571irq: 572 get_irq_stack 573 irq_save_user_regs 574 bl do_irq 575 irq_restore_user_regs 576 577 .align 5 578fiq: 579 get_fiq_stack 580 /* someone ought to write a more effective fiq_save_user_regs */ 581 irq_save_user_regs 582 bl do_fiq 583 irq_restore_user_regs 584 585#else 586 587 .align 5 588irq: 589 get_bad_stack 590 bad_save_user_regs 591 bl do_irq 592 593 .align 5 594fiq: 595 get_bad_stack 596 bad_save_user_regs 597 bl do_fiq 598 599#endif 600