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