1/* 2 * armboot - Startup Code for SA1100 CPU 3 * 4 * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> 5 * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> 6 * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> 7 * Copyright (c) 2001 Alex Z�pke <azu@sysgo.de> 8 * 9 * See file CREDITS for list of people who contributed to this 10 * project. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; either version 2 of 15 * the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 * MA 02111-1307 USA 26 */ 27 28 29#include <config.h> 30#include <version.h> 31 32 33/* 34 ************************************************************************* 35 * 36 * Jump vector table as in table 3.1 in [1] 37 * 38 ************************************************************************* 39 */ 40 41 42.globl _start 43_start: b reset 44 ldr pc, _undefined_instruction 45 ldr pc, _software_interrupt 46 ldr pc, _prefetch_abort 47 ldr pc, _data_abort 48 ldr pc, _not_used 49 ldr pc, _irq 50 ldr pc, _fiq 51 52_undefined_instruction: .word undefined_instruction 53_software_interrupt: .word software_interrupt 54_prefetch_abort: .word prefetch_abort 55_data_abort: .word data_abort 56_not_used: .word not_used 57_irq: .word irq 58_fiq: .word fiq 59 60 .balignl 16,0xdeadbeef 61 62 63/* 64 ************************************************************************* 65 * 66 * Startup Code (reset vector) 67 * 68 * do important init only if we don't start from memory! 69 * relocate armboot to ram 70 * setup stack 71 * jump to second stage 72 * 73 ************************************************************************* 74 */ 75 76.globl _TEXT_BASE 77_TEXT_BASE: 78 .word TEXT_BASE 79 80#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 81.globl _armboot_start 82_armboot_start: 83 .word _start 84#endif 85 86/* 87 * These are defined in the board-specific linker script. 88 */ 89.globl _bss_start 90_bss_start: 91 .word __bss_start 92 93.globl _bss_end 94_bss_end: 95 .word _end 96 97#ifdef CONFIG_USE_IRQ 98/* IRQ stack memory (calculated at run-time) */ 99.globl IRQ_STACK_START 100IRQ_STACK_START: 101 .word 0x0badc0de 102 103/* IRQ stack memory (calculated at run-time) */ 104.globl FIQ_STACK_START 105FIQ_STACK_START: 106 .word 0x0badc0de 107#endif 108 109#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 110/* IRQ stack memory (calculated at run-time) + 8 bytes */ 111.globl IRQ_STACK_START_IN 112IRQ_STACK_START_IN: 113 .word 0x0badc0de 114 115.globl _datarel_start 116_datarel_start: 117 .word __datarel_start 118 119.globl _datarelrolocal_start 120_datarelrolocal_start: 121 .word __datarelrolocal_start 122 123.globl _datarellocal_start 124_datarellocal_start: 125 .word __datarellocal_start 126 127.globl _datarelro_start 128_datarelro_start: 129 .word __datarelro_start 130 131.globl _got_start 132_got_start: 133 .word __got_start 134 135.globl _got_end 136_got_end: 137 .word __got_end 138 139/* 140 * the actual reset code 141 */ 142 143reset: 144 /* 145 * set the cpu to SVC32 mode 146 */ 147 mrs r0,cpsr 148 bic r0,r0,#0x1f 149 orr r0,r0,#0xd3 150 msr cpsr,r0 151 152 /* 153 * we do sys-critical inits only at reboot, 154 * not when booting from ram! 155 */ 156#ifndef CONFIG_SKIP_LOWLEVEL_INIT 157 bl cpu_init_crit 158#endif 159 160/* Set stackpointer in internal RAM to call board_init_f */ 161call_board_init_f: 162 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 163 ldr r0,=0x00000000 164 bl board_init_f 165 166/*------------------------------------------------------------------------------*/ 167 168/* 169 * void relocate_code (addr_sp, gd, addr_moni) 170 * 171 * This "function" does not return, instead it continues in RAM 172 * after relocating the monitor code. 173 * 174 */ 175 .globl relocate_code 176relocate_code: 177 mov r4, r0 /* save addr_sp */ 178 mov r5, r1 /* save addr of gd */ 179 mov r6, r2 /* save addr of destination */ 180 mov r7, r2 /* save addr of destination */ 181 182 /* Set up the stack */ 183stack_setup: 184 mov sp, r4 185 186 adr r0, _start 187 ldr r2, _TEXT_BASE 188 ldr r3, _bss_start 189 sub r2, r3, r2 /* r2 <- size of armboot */ 190 add r2, r0, r2 /* r2 <- source end address */ 191 cmp r0, r6 192 beq clear_bss 193 194#ifndef CONFIG_SKIP_RELOCATE_UBOOT 195copy_loop: 196 ldmia r0!, {r9-r10} /* copy from source address [r0] */ 197 stmia r6!, {r9-r10} /* copy to target address [r1] */ 198 cmp r0, r2 /* until source end addreee [r2] */ 199 ble copy_loop 200 201#ifndef CONFIG_PRELOADER 202 /* fix got entries */ 203 ldr r1, _TEXT_BASE /* Text base */ 204 mov r0, r7 /* reloc addr */ 205 ldr r2, _got_start /* addr in Flash */ 206 ldr r3, _got_end /* addr in Flash */ 207 sub r3, r3, r1 208 add r3, r3, r0 209 sub r2, r2, r1 210 add r2, r2, r0 211 212fixloop: 213 ldr r4, [r2] 214 sub r4, r4, r1 215 add r4, r4, r0 216 str r4, [r2] 217 add r2, r2, #4 218 cmp r2, r3 219 bne fixloop 220#endif 221#endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */ 222 223clear_bss: 224#ifndef CONFIG_PRELOADER 225 ldr r0, _bss_start 226 ldr r1, _bss_end 227 ldr r3, _TEXT_BASE /* Text base */ 228 mov r4, r7 /* reloc addr */ 229 sub r0, r0, r3 230 add r0, r0, r4 231 sub r1, r1, r3 232 add r1, r1, r4 233 mov r2, #0x00000000 /* clear */ 234 235clbss_l:str r2, [r0] /* clear loop... */ 236 add r0, r0, #4 237 cmp r0, r1 238 bne clbss_l 239#endif 240 241/* 242 * We are done. Do not return, instead branch to second part of board 243 * initialization, now running from RAM. 244 */ 245 ldr r0, _TEXT_BASE 246 ldr r2, _board_init_r 247 sub r2, r2, r0 248 add r2, r2, r7 /* position from board_init_r in RAM */ 249 /* setup parameters for board_init_r */ 250 mov r0, r5 /* gd_t */ 251 mov r1, r7 /* dest_addr */ 252 /* jump to it ... */ 253 mov lr, r2 254 mov pc, lr 255 256_board_init_r: .word board_init_r 257 258#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ 259 260/* 261 * the actual reset code 262 */ 263 264reset: 265 /* 266 * set the cpu to SVC32 mode 267 */ 268 mrs r0,cpsr 269 bic r0,r0,#0x1f 270 orr r0,r0,#0x13 271 msr cpsr,r0 272 273 /* 274 * we do sys-critical inits only at reboot, 275 * not when booting from ram! 276 */ 277#ifndef CONFIG_SKIP_LOWLEVEL_INIT 278 bl cpu_init_crit 279#endif 280 281#ifndef CONFIG_SKIP_RELOCATE_UBOOT 282relocate: /* relocate U-Boot to RAM */ 283 adr r0, _start /* r0 <- current position of code */ 284 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 285 cmp r0, r1 /* don't reloc during debug */ 286 beq stack_setup 287 288 ldr r2, _armboot_start 289 ldr r3, _bss_start 290 sub r2, r3, r2 /* r2 <- size of armboot */ 291 add r2, r0, r2 /* r2 <- source end address */ 292 293copy_loop: 294 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 295 stmia r1!, {r3-r10} /* copy to target address [r1] */ 296 cmp r0, r2 /* until source end addreee [r2] */ 297 ble copy_loop 298#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 299 300 /* Set up the stack */ 301stack_setup: 302 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 303 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 304 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 305#ifdef CONFIG_USE_IRQ 306 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 307#endif 308 sub sp, r0, #12 /* leave 3 words for abort-stack */ 309 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 310 311clear_bss: 312 ldr r0, _bss_start /* find start of bss segment */ 313 ldr r1, _bss_end /* stop here */ 314 mov r2, #0x00000000 /* clear */ 315 316clbss_l:str r2, [r0] /* clear loop... */ 317 add r0, r0, #4 318 cmp r0, r1 319 ble clbss_l 320 321 ldr pc, _start_armboot 322 323_start_armboot: .word start_armboot 324 325#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ 326 327/* 328 ************************************************************************* 329 * 330 * CPU_init_critical registers 331 * 332 * setup important registers 333 * setup memory timing 334 * 335 ************************************************************************* 336 */ 337 338 339/* Interupt-Controller base address */ 340IC_BASE: .word 0x90050000 341#define ICMR 0x04 342 343 344/* Reset-Controller */ 345RST_BASE: .word 0x90030000 346#define RSRR 0x00 347#define RCSR 0x04 348 349 350/* PWR */ 351PWR_BASE: .word 0x90020000 352#define PSPR 0x08 353#define PPCR 0x14 354cpuspeed: .word CONFIG_SYS_CPUSPEED 355 356 357cpu_init_crit: 358 /* 359 * mask all IRQs 360 */ 361 ldr r0, IC_BASE 362 mov r1, #0x00 363 str r1, [r0, #ICMR] 364 365 /* set clock speed */ 366 ldr r0, PWR_BASE 367 ldr r1, cpuspeed 368 str r1, [r0, #PPCR] 369 370 /* 371 * before relocating, we have to setup RAM timing 372 * because memory timing is board-dependend, you will 373 * find a lowlevel_init.S in your board directory. 374 */ 375 mov ip, lr 376 bl lowlevel_init 377 mov lr, ip 378 379 /* 380 * disable MMU stuff and enable I-cache 381 */ 382 mrc p15,0,r0,c1,c0 383 bic r0, r0, #0x00002000 @ clear bit 13 (X) 384 bic r0, r0, #0x0000000f @ clear bits 3-0 (WCAM) 385 orr r0, r0, #0x00001000 @ set bit 12 (I) Icache 386 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 387 mcr p15,0,r0,c1,c0 388 389 /* 390 * flush v4 I/D caches 391 */ 392 mov r0, #0 393 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 394 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 395 396 mov pc, lr 397 398 399/* 400 ************************************************************************* 401 * 402 * Interrupt handling 403 * 404 ************************************************************************* 405 */ 406 407@ 408@ IRQ stack frame. 409@ 410#define S_FRAME_SIZE 72 411 412#define S_OLD_R0 68 413#define S_PSR 64 414#define S_PC 60 415#define S_LR 56 416#define S_SP 52 417 418#define S_IP 48 419#define S_FP 44 420#define S_R10 40 421#define S_R9 36 422#define S_R8 32 423#define S_R7 28 424#define S_R6 24 425#define S_R5 20 426#define S_R4 16 427#define S_R3 12 428#define S_R2 8 429#define S_R1 4 430#define S_R0 0 431 432#define MODE_SVC 0x13 433#define I_BIT 0x80 434 435/* 436 * use bad_save_user_regs for abort/prefetch/undef/swi ... 437 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 438 */ 439 440 .macro bad_save_user_regs 441 sub sp, sp, #S_FRAME_SIZE 442 stmia sp, {r0 - r12} @ Calling r0-r12 443 add r8, sp, #S_PC 444 445#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 446 ldr r2, _armboot_start 447 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 448 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 449#else 450 ldr r2, IRQ_STACK_START_IN 451#endif 452 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 453 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 454 455 add r5, sp, #S_SP 456 mov r1, lr 457 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r 458 mov r0, sp 459 .endm 460 461 .macro irq_save_user_regs 462 sub sp, sp, #S_FRAME_SIZE 463 stmia sp, {r0 - r12} @ Calling r0-r12 464 add r8, sp, #S_PC 465 stmdb r8, {sp, lr}^ @ Calling SP, LR 466 str lr, [r8, #0] @ Save calling PC 467 mrs r6, spsr 468 str r6, [r8, #4] @ Save CPSR 469 str r0, [r8, #8] @ Save OLD_R0 470 mov r0, sp 471 .endm 472 473 .macro irq_restore_user_regs 474 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 475 mov r0, r0 476 ldr lr, [sp, #S_PC] @ Get PC 477 add sp, sp, #S_FRAME_SIZE 478 subs pc, lr, #4 @ return & move spsr_svc into 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 484 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 485 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 486#else 487 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 488#endif 489 490 str lr, [r13] @ save caller lr / spsr 491 mrs lr, spsr 492 str lr, [r13, #4] 493 494 mov r13, #MODE_SVC @ prepare SVC-Mode 495 msr spsr_c, r13 496 mov lr, pc 497 movs pc, lr 498 .endm 499 500 .macro get_irq_stack @ setup IRQ stack 501 ldr sp, IRQ_STACK_START 502 .endm 503 504 .macro get_fiq_stack @ setup FIQ stack 505 ldr sp, FIQ_STACK_START 506 .endm 507 508/* 509 * exception handlers 510 */ 511 .align 5 512undefined_instruction: 513 get_bad_stack 514 bad_save_user_regs 515 bl do_undefined_instruction 516 517 .align 5 518software_interrupt: 519 get_bad_stack 520 bad_save_user_regs 521 bl do_software_interrupt 522 523 .align 5 524prefetch_abort: 525 get_bad_stack 526 bad_save_user_regs 527 bl do_prefetch_abort 528 529 .align 5 530data_abort: 531 get_bad_stack 532 bad_save_user_regs 533 bl do_data_abort 534 535 .align 5 536not_used: 537 get_bad_stack 538 bad_save_user_regs 539 bl do_not_used 540 541#ifdef CONFIG_USE_IRQ 542 543 .align 5 544irq: 545 get_irq_stack 546 irq_save_user_regs 547 bl do_irq 548 irq_restore_user_regs 549 550 .align 5 551fiq: 552 get_fiq_stack 553 /* someone ought to write a more effiction fiq_save_user_regs */ 554 irq_save_user_regs 555 bl do_fiq 556 irq_restore_user_regs 557 558#else 559 560 .align 5 561irq: 562 get_bad_stack 563 bad_save_user_regs 564 bl do_irq 565 566 .align 5 567fiq: 568 get_bad_stack 569 bad_save_user_regs 570 bl do_fiq 571 572#endif 573 574 .align 5 575.globl reset_cpu 576reset_cpu: 577 ldr r0, RST_BASE 578 mov r1, #0x0 @ set bit 3-0 ... 579 str r1, [r0, #RCSR] @ ... to clear in RCSR 580 mov r1, #0x1 581 str r1, [r0, #RSRR] @ and perform reset 582 b reset_cpu @ silly, but repeat endlessly 583