1/* 2 * armboot - Startup Code for OMP2420/ARM1136 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 * 12 * See file CREDITS for list of people who contributed to this 13 * project. 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License as 17 * published by the Free Software Foundation; either version 2 of 18 * the License, or (at your option) any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with this program; if not, write to the Free Software 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 28 * MA 02111-1307 USA 29 */ 30 31#include <config.h> 32#include <version.h> 33.globl _start 34_start: b reset 35#ifdef CONFIG_PRELOADER 36 ldr pc, _hang 37 ldr pc, _hang 38 ldr pc, _hang 39 ldr pc, _hang 40 ldr pc, _hang 41 ldr pc, _hang 42 ldr pc, _hang 43 44_hang: 45 .word do_hang 46 .word 0x12345678 47 .word 0x12345678 48 .word 0x12345678 49 .word 0x12345678 50 .word 0x12345678 51 .word 0x12345678 52 .word 0x12345678 /* now 16*4=64 */ 53#else 54 ldr pc, _undefined_instruction 55 ldr pc, _software_interrupt 56 ldr pc, _prefetch_abort 57 ldr pc, _data_abort 58 ldr pc, _not_used 59 ldr pc, _irq 60 ldr pc, _fiq 61 62_undefined_instruction: .word undefined_instruction 63_software_interrupt: .word software_interrupt 64_prefetch_abort: .word prefetch_abort 65_data_abort: .word data_abort 66_not_used: .word not_used 67_irq: .word irq 68_fiq: .word fiq 69_pad: .word 0x12345678 /* now 16*4=64 */ 70#endif /* CONFIG_PRELOADER */ 71.global _end_vect 72_end_vect: 73 74 .balignl 16,0xdeadbeef 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.globl _TEXT_BASE 89_TEXT_BASE: 90 .word CONFIG_SYS_TEXT_BASE 91 92#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 93.globl _armboot_start 94_armboot_start: 95 .word _start 96#endif 97 98/* 99 * These are defined in the board-specific linker script. 100 */ 101.globl _bss_start 102_bss_start: 103 .word __bss_start 104 105.globl _bss_end 106_bss_end: 107 .word _end 108 109#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 110.globl _datarel_start 111_datarel_start: 112 .word __datarel_start 113 114.globl _datarelrolocal_start 115_datarelrolocal_start: 116 .word __datarelrolocal_start 117 118.globl _datarellocal_start 119_datarellocal_start: 120 .word __datarellocal_start 121 122.globl _datarelro_start 123_datarelro_start: 124 .word __datarelro_start 125 126.globl _got_start 127_got_start: 128 .word __got_start 129 130.globl _got_end 131_got_end: 132 .word __got_end 133#endif 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#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 148/* IRQ stack memory (calculated at run-time) + 8 bytes */ 149.globl IRQ_STACK_START_IN 150IRQ_STACK_START_IN: 151 .word 0x0badc0de 152#endif 153 154#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 155/* 156 * the actual reset code 157 */ 158 159reset: 160 /* 161 * set the cpu to SVC32 mode 162 */ 163 mrs r0,cpsr 164 bic r0,r0,#0x1f 165 orr r0,r0,#0xd3 166 msr cpsr,r0 167 168#ifdef CONFIG_OMAP2420H4 169 /* Copy vectors to mask ROM indirect addr */ 170 adr r0, _start /* r0 <- current position of code */ 171 add r0, r0, #4 /* skip reset vector */ 172 mov r2, #64 /* r2 <- size to copy */ 173 add r2, r0, r2 /* r2 <- source end address */ 174 mov r1, #SRAM_OFFSET0 /* build vect addr */ 175 mov r3, #SRAM_OFFSET1 176 add r1, r1, r3 177 mov r3, #SRAM_OFFSET2 178 add r1, r1, r3 179next: 180 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 181 stmia r1!, {r3-r10} /* copy to target address [r1] */ 182 cmp r0, r2 /* until source end address [r2] */ 183 bne next /* loop until equal */ 184 bl cpy_clk_code /* put dpll adjust code behind vectors */ 185#endif 186 /* the mask ROM code should have PLL and others stable */ 187#ifndef CONFIG_SKIP_LOWLEVEL_INIT 188 bl cpu_init_crit 189#endif 190 191/* Set stackpointer in internal RAM to call board_init_f */ 192call_board_init_f: 193 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 194 ldr r0,=0x00000000 195 196#ifdef CONFIG_NAND_SPL 197 bl nand_boot 198#else 199#ifdef CONFIG_ONENAND_IPL 200 bl start_oneboot 201#else 202 bl board_init_f 203#endif /* CONFIG_ONENAND_IPL */ 204#endif /* CONFIG_NAND_SPL */ 205 206/*------------------------------------------------------------------------------*/ 207 208/* 209 * void relocate_code (addr_sp, gd, addr_moni) 210 * 211 * This "function" does not return, instead it continues in RAM 212 * after relocating the monitor code. 213 * 214 */ 215 .globl relocate_code 216relocate_code: 217 mov r4, r0 /* save addr_sp */ 218 mov r5, r1 /* save addr of gd */ 219 mov r6, r2 /* save addr of destination */ 220 mov r7, r2 /* save addr of destination */ 221 222 /* Set up the stack */ 223stack_setup: 224 mov sp, r4 225 226 adr r0, _start 227 ldr r2, _TEXT_BASE 228 ldr r3, _bss_start 229 sub r2, r3, r2 /* r2 <- size of armboot */ 230 add r2, r0, r2 /* r2 <- source end address */ 231 cmp r0, r6 232 beq clear_bss 233 234#ifndef CONFIG_SKIP_RELOCATE_UBOOT 235copy_loop: 236 ldmia r0!, {r9-r10} /* copy from source address [r0] */ 237 stmia r6!, {r9-r10} /* copy to target address [r1] */ 238 cmp r0, r2 /* until source end address [r2] */ 239 blo copy_loop 240 241#ifndef CONFIG_PRELOADER 242 /* fix got entries */ 243 ldr r1, _TEXT_BASE 244 mov r0, r7 /* reloc addr */ 245 ldr r2, _got_start /* addr in Flash */ 246 ldr r3, _got_end /* addr in Flash */ 247 sub r3, r3, r1 248 add r3, r3, r0 249 sub r2, r2, r1 250 add r2, r2, r0 251 252fixloop: 253 ldr r4, [r2] 254 sub r4, r4, r1 255 add r4, r4, r0 256 str r4, [r2] 257 add r2, r2, #4 258 cmp r2, r3 259 bne fixloop 260#endif 261#endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */ 262 263clear_bss: 264#ifndef CONFIG_PRELOADER 265 ldr r0, _bss_start 266 ldr r1, _bss_end 267 ldr r3, _TEXT_BASE /* Text base */ 268 mov r4, r7 /* reloc addr */ 269 sub r0, r0, r3 270 add r0, r0, r4 271 sub r1, r1, r3 272 add r1, r1, r4 273 mov r2, #0x00000000 /* clear */ 274 275clbss_l:str r2, [r0] /* clear loop... */ 276 add r0, r0, #4 277 cmp r0, r1 278 bne clbss_l 279#endif /* #ifndef CONFIG_PRELOADER */ 280 281/* 282 * We are done. Do not return, instead branch to second part of board 283 * initialization, now running from RAM. 284 */ 285#ifdef CONFIG_NAND_SPL 286 ldr pc, _nand_boot 287 288_nand_boot: .word nand_boot 289#else 290jump_2_ram: 291 ldr r0, _TEXT_BASE 292 ldr r2, _board_init_r 293 sub r2, r2, r0 294 add r2, r2, r7 /* position from board_init_r in RAM */ 295 /* setup parameters for board_init_r */ 296 mov r0, r5 /* gd_t */ 297 mov r1, r7 /* dest_addr */ 298 /* jump to it ... */ 299 mov lr, r2 300 mov pc, lr 301 302_board_init_r: .word board_init_r 303#endif 304#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ 305/* 306 * the actual reset code 307 */ 308 309reset: 310 /* 311 * set the cpu to SVC32 mode 312 */ 313 mrs r0,cpsr 314 bic r0,r0,#0x1f 315 orr r0,r0,#0xd3 316 msr cpsr,r0 317 318#ifdef CONFIG_OMAP2420H4 319 /* Copy vectors to mask ROM indirect addr */ 320 adr r0, _start /* r0 <- current position of code */ 321 add r0, r0, #4 /* skip reset vector */ 322 mov r2, #64 /* r2 <- size to copy */ 323 add r2, r0, r2 /* r2 <- source end address */ 324 mov r1, #SRAM_OFFSET0 /* build vect addr */ 325 mov r3, #SRAM_OFFSET1 326 add r1, r1, r3 327 mov r3, #SRAM_OFFSET2 328 add r1, r1, r3 329next: 330 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 331 stmia r1!, {r3-r10} /* copy to target address [r1] */ 332 cmp r0, r2 /* until source end address [r2] */ 333 bne next /* loop until equal */ 334 bl cpy_clk_code /* put dpll adjust code behind vectors */ 335#endif 336 /* the mask ROM code should have PLL and others stable */ 337#ifndef CONFIG_SKIP_LOWLEVEL_INIT 338 bl cpu_init_crit 339#endif 340 341#ifndef CONFIG_SKIP_RELOCATE_UBOOT 342relocate: /* relocate U-Boot to RAM */ 343 adr r0, _start /* r0 <- current position of code */ 344 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 345 cmp r0, r1 /* don't reloc during debug */ 346#ifndef CONFIG_PRELOADER 347 beq stack_setup 348#endif /* CONFIG_PRELOADER */ 349 350 ldr r2, _armboot_start 351 ldr r3, _bss_start 352 sub r2, r3, r2 /* r2 <- size of armboot */ 353 add r2, r0, r2 /* r2 <- source end address */ 354 355copy_loop: 356 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 357 stmia r1!, {r3-r10} /* copy to target address [r1] */ 358 cmp r0, r2 /* until source end address [r2] */ 359 blo copy_loop 360#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 361 362 /* Set up the stack */ 363stack_setup: 364 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 365#ifdef CONFIG_PRELOADER 366 sub sp, r0, #128 /* leave 32 words for abort-stack */ 367#else 368 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 369 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 370#ifdef CONFIG_USE_IRQ 371 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 372#endif 373 sub sp, r0, #12 /* leave 3 words for abort-stack */ 374#endif /* CONFIG_PRELOADER */ 375 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 376 377clear_bss: 378 ldr r0, _bss_start /* find start of bss segment */ 379 ldr r1, _bss_end /* stop here */ 380 mov r2, #0x00000000 /* clear */ 381 382#ifndef CONFIG_PRELOADER 383clbss_l:str r2, [r0] /* clear loop... */ 384 add r0, r0, #4 385 cmp r0, r1 386 bne clbss_l 387#endif 388 389 ldr pc, _start_armboot 390 391#ifdef CONFIG_NAND_SPL 392_start_armboot: .word nand_boot 393#else 394#ifdef CONFIG_ONENAND_IPL 395_start_armboot: .word start_oneboot 396#else 397_start_armboot: .word start_armboot 398#endif /* CONFIG_ONENAND_IPL */ 399#endif /* CONFIG_NAND_SPL */ 400 401#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ 402 403/* 404 ************************************************************************* 405 * 406 * CPU_init_critical registers 407 * 408 * setup important registers 409 * setup memory timing 410 * 411 ************************************************************************* 412 */ 413#ifndef CONFIG_SKIP_LOWLEVEL_INIT 414cpu_init_crit: 415 /* 416 * flush v4 I/D caches 417 */ 418 mov r0, #0 419 mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */ 420 mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */ 421 422 /* 423 * disable MMU stuff and caches 424 */ 425 mrc p15, 0, r0, c1, c0, 0 426 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 427 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 428 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 429 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 430 mcr p15, 0, r0, c1, c0, 0 431 432 /* 433 * Jump to board specific initialization... The Mask ROM will have already initialized 434 * basic memory. Go here to bump up clock rate and handle wake up conditions. 435 */ 436 mov ip, lr /* persevere link reg across call */ 437 bl lowlevel_init /* go setup pll,mux,memory */ 438 mov lr, ip /* restore link */ 439 mov pc, lr /* back to my caller */ 440#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 441 442#ifndef CONFIG_PRELOADER 443/* 444 ************************************************************************* 445 * 446 * Interrupt handling 447 * 448 ************************************************************************* 449 */ 450@ 451@ IRQ stack frame. 452@ 453#define S_FRAME_SIZE 72 454 455#define S_OLD_R0 68 456#define S_PSR 64 457#define S_PC 60 458#define S_LR 56 459#define S_SP 52 460 461#define S_IP 48 462#define S_FP 44 463#define S_R10 40 464#define S_R9 36 465#define S_R8 32 466#define S_R7 28 467#define S_R6 24 468#define S_R5 20 469#define S_R4 16 470#define S_R3 12 471#define S_R2 8 472#define S_R1 4 473#define S_R0 0 474 475#define MODE_SVC 0x13 476#define I_BIT 0x80 477 478/* 479 * use bad_save_user_regs for abort/prefetch/undef/swi ... 480 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 481 */ 482 483 .macro bad_save_user_regs 484 sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack 485 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 486 487#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 488 ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort stack 489#else 490 ldr r2, _armboot_start 491 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) 492 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 493#endif 494 ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs) 495 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 496 497 add r5, sp, #S_SP 498 mov r1, lr 499 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 500 mov r0, sp @ save current stack into r0 (param register) 501 .endm 502 503 .macro irq_save_user_regs 504 sub sp, sp, #S_FRAME_SIZE 505 stmia sp, {r0 - r12} @ Calling r0-r12 506 add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 507 stmdb r8, {sp, lr}^ @ Calling SP, LR 508 str lr, [r8, #0] @ Save calling PC 509 mrs r6, spsr 510 str r6, [r8, #4] @ Save CPSR 511 str r0, [r8, #8] @ Save OLD_R0 512 mov r0, sp 513 .endm 514 515 .macro irq_restore_user_regs 516 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 517 mov r0, r0 518 ldr lr, [sp, #S_PC] @ Get PC 519 add sp, sp, #S_FRAME_SIZE 520 subs pc, lr, #4 @ return & move spsr_svc into cpsr 521 .endm 522 523 .macro get_bad_stack 524#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 525 ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter in banked mode) 526#else 527 ldr r13, _armboot_start @ setup our mode stack (enter in banked mode) 528 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool 529 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack 530#endif 531 532 str lr, [r13] @ save caller lr in position 0 of saved stack 533 mrs lr, spsr @ get the spsr 534 str lr, [r13, #4] @ save spsr in position 1 of saved stack 535 536 mov r13, #MODE_SVC @ prepare SVC-Mode 537 @ msr spsr_c, r13 538 msr spsr, r13 @ switch modes, make sure moves will execute 539 mov lr, pc @ capture return pc 540 movs pc, lr @ jump to next instruction & switch modes. 541 .endm 542 543 .macro get_bad_stack_swi 544 sub r13, r13, #4 @ space on current stack for scratch reg. 545 str r0, [r13] @ save R0's value. 546#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 547 ldr r0, IRQ_STACK_START_IN @ get data regions start 548#else 549 ldr r0, _armboot_start @ get data regions start 550 sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool 551 sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ move past gbl and a couple spots for abort stack 552#endif 553 str lr, [r0] @ save caller lr in position 0 of saved stack 554 mrs r0, spsr @ get the spsr 555 str lr, [r0, #4] @ save spsr in position 1 of saved stack 556 ldr r0, [r13] @ restore r0 557 add r13, r13, #4 @ pop stack entry 558 .endm 559 560 .macro get_irq_stack @ setup IRQ stack 561 ldr sp, IRQ_STACK_START 562 .endm 563 564 .macro get_fiq_stack @ setup FIQ stack 565 ldr sp, FIQ_STACK_START 566 .endm 567#endif /* CONFIG_PRELOADER */ 568 569/* 570 * exception handlers 571 */ 572#ifdef CONFIG_PRELOADER 573 .align 5 574do_hang: 575 ldr sp, _TEXT_BASE /* use 32 words about stack */ 576 bl hang /* hang and never return */ 577#else /* !CONFIG_PRELOADER */ 578 .align 5 579undefined_instruction: 580 get_bad_stack 581 bad_save_user_regs 582 bl do_undefined_instruction 583 584 .align 5 585software_interrupt: 586 get_bad_stack_swi 587 bad_save_user_regs 588 bl do_software_interrupt 589 590 .align 5 591prefetch_abort: 592 get_bad_stack 593 bad_save_user_regs 594 bl do_prefetch_abort 595 596 .align 5 597data_abort: 598 get_bad_stack 599 bad_save_user_regs 600 bl do_data_abort 601 602 .align 5 603not_used: 604 get_bad_stack 605 bad_save_user_regs 606 bl do_not_used 607 608#ifdef CONFIG_USE_IRQ 609 610 .align 5 611irq: 612 get_irq_stack 613 irq_save_user_regs 614 bl do_irq 615 irq_restore_user_regs 616 617 .align 5 618fiq: 619 get_fiq_stack 620 /* someone ought to write a more effiction fiq_save_user_regs */ 621 irq_save_user_regs 622 bl do_fiq 623 irq_restore_user_regs 624 625#else 626 627 .align 5 628irq: 629 get_bad_stack 630 bad_save_user_regs 631 bl do_irq 632 633 .align 5 634fiq: 635 get_bad_stack 636 bad_save_user_regs 637 bl do_fiq 638 639#endif 640 .align 5 641.global arm1136_cache_flush 642arm1136_cache_flush: 643#if !defined(CONFIG_SYS_NO_ICACHE) 644 mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache 645#endif 646#if !defined(CONFIG_SYS_NO_DCACHE) 647 mcr p15, 0, r1, c7, c14, 0 @ invalidate D cache 648#endif 649 mov pc, lr @ back to caller 650#endif /* CONFIG_PRELOADER */ 651