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