1/* 2 * armboot - Startup Code for XScale 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 Zuepke <azu@sysgo.de> 8 * Copyright (C) 2002 Kyle Harris <kharris@nexus-tech.net> 9 * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de> 10 * Copyright (C) 2003 Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de> 11 * Copyright (c) 2010 Marek Vasut <marek.vasut@gmail.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 <asm-offsets.h> 33#include <config.h> 34#include <version.h> 35#include <asm/arch/pxa-regs.h> 36 37/* takes care the CP15 update has taken place */ 38.macro CPWAIT reg 39mrc p15,0,\reg,c2,c0,0 40mov \reg,\reg 41sub pc,pc,#4 42.endm 43 44.globl _start 45_start: b reset 46#ifdef CONFIG_SPL_BUILD 47 ldr pc, _hang 48 ldr pc, _hang 49 ldr pc, _hang 50 ldr pc, _hang 51 ldr pc, _hang 52 ldr pc, _hang 53 ldr pc, _hang 54 55_hang: 56 .word do_hang 57 .word 0x12345678 58 .word 0x12345678 59 .word 0x12345678 60 .word 0x12345678 61 .word 0x12345678 62 .word 0x12345678 63 .word 0x12345678 /* now 16*4=64 */ 64#else 65 ldr pc, _undefined_instruction 66 ldr pc, _software_interrupt 67 ldr pc, _prefetch_abort 68 ldr pc, _data_abort 69 ldr pc, _not_used 70 ldr pc, _irq 71 ldr pc, _fiq 72 73_undefined_instruction: .word undefined_instruction 74_software_interrupt: .word software_interrupt 75_prefetch_abort: .word prefetch_abort 76_data_abort: .word data_abort 77_not_used: .word not_used 78_irq: .word irq 79_fiq: .word fiq 80#endif /* CONFIG_SPL_BUILD */ 81 82 .balignl 16,0xdeadbeef 83 84 85/* 86 * Startup Code (reset vector) 87 * 88 * do important init only if we don't start from RAM! 89 * - relocate armboot to RAM 90 * - setup stack 91 * - jump to second stage 92 */ 93 94.globl _TEXT_BASE 95_TEXT_BASE: 96 .word CONFIG_SYS_TEXT_BASE 97 98/* 99 * These are defined in the board-specific linker script. 100 */ 101.globl _bss_start_ofs 102_bss_start_ofs: 103 .word __bss_start - _start 104 105.globl _bss_end_ofs 106_bss_end_ofs: 107 .word __bss_end__ - _start 108 109.globl _end_ofs 110_end_ofs: 111 .word _end - _start 112 113#ifdef CONFIG_USE_IRQ 114/* IRQ stack memory (calculated at run-time) */ 115.globl IRQ_STACK_START 116IRQ_STACK_START: 117 .word 0x0badc0de 118 119/* IRQ stack memory (calculated at run-time) */ 120.globl FIQ_STACK_START 121FIQ_STACK_START: 122 .word 0x0badc0de 123#endif /* CONFIG_USE_IRQ */ 124 125#ifndef CONFIG_SPL_BUILD 126/* IRQ stack memory (calculated at run-time) + 8 bytes */ 127.globl IRQ_STACK_START_IN 128IRQ_STACK_START_IN: 129 .word 0x0badc0de 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 /* 145 * Enable MMU to use DCache as DRAM 146 */ 147 /* Domain access -- enable for all CPs */ 148 ldr r0, =0x0000ffff 149 mcr p15, 0, r0, c3, c0, 0 150 151 /* Point TTBR to MMU table */ 152 ldr r0, =mmu_table 153 adr r2, _start 154 orr r0, r2 155 mcr p15, 0, r0, c2, c0, 0 156 157/* !!! Hereby, check if the code is running from SRAM !!! */ 158/* If the code is running from SRAM, alias SRAM to 0x0 to simulate NOR. The code 159 * is linked to 0x0 too, so this makes things easier. */ 160 cmp r2, #0x5c000000 161 162 ldreq r1, [r0] 163 orreq r1, r2 164 streq r1, [r0] 165 166 /* Kick in MMU, ICache, DCache, BTB */ 167 mrc p15, 0, r0, c1, c0, 0 168 bic r0, #0x1b00 169 bic r0, #0x0087 170 orr r0, #0x1800 171 orr r0, #0x0005 172 mcr p15, 0, r0, c1, c0, 0 173 CPWAIT r0 174 175 /* Unlock Icache, Dcache */ 176 mcr p15, 0, r0, c9, c1, 1 177 mcr p15, 0, r0, c9, c2, 1 178 179 /* Flush Icache, Dcache, BTB */ 180 mcr p15, 0, r0, c7, c7, 0 181 182 /* Unlock I-TLB, D-TLB */ 183 mcr p15, 0, r0, c10, c4, 1 184 mcr p15, 0, r0, c10, c8, 1 185 186 /* Flush TLB */ 187 mcr p15, 0, r0, c8, c7, 0 188 /* Allocate 4096 bytes of Dcache as RAM */ 189 190 /* Drain pending loads and stores */ 191 mcr p15, 0, r0, c7, c10, 4 192 193 mov r4, #0x00 194 mov r5, #0x00 195 mov r2, #0x01 196 mcr p15, 0, r0, c9, c2, 0 197 CPWAIT r0 198 199 /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */ 200 mov r0, #128 201 mov r1, #0xa0000000 202alloc: 203 mcr p15, 0, r1, c7, c2, 5 204 /* Drain pending loads and stores */ 205 mcr p15, 0, r0, c7, c10, 4 206 strd r4, [r1], #8 207 strd r4, [r1], #8 208 strd r4, [r1], #8 209 strd r4, [r1], #8 210 subs r0, #0x01 211 bne alloc 212 /* Drain pending loads and stores */ 213 mcr p15, 0, r0, c7, c10, 4 214 mov r2, #0x00 215 mcr p15, 0, r2, c9, c2, 0 216 CPWAIT r0 217 218 /* Jump to 0x0 ( + offset) if running from SRAM */ 219 adr r0, zerojmp 220 bic r0, #0x5c000000 221 mov pc, r0 222zerojmp: 223 224/* Set stackpointer in internal RAM to call board_init_f */ 225call_board_init_f: 226 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 227 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 228 ldr r0,=0x00000000 229 bl board_init_f 230 231/*------------------------------------------------------------------------------*/ 232 233/* 234 * void relocate_code (addr_sp, gd, addr_moni) 235 * 236 * This "function" does not return, instead it continues in RAM 237 * after relocating the monitor code. 238 * 239 */ 240 .globl relocate_code 241relocate_code: 242 mov r4, r0 /* save addr_sp */ 243 mov r5, r1 /* save addr of gd */ 244 mov r6, r2 /* save addr of destination */ 245 246 /* Set up the stack */ 247stack_setup: 248 mov sp, r4 249 250 adr r0, _start 251 cmp r0, r6 252 beq clear_bss /* skip relocation */ 253 mov r1, r6 /* r1 <- scratch for copy_loop */ 254 ldr r3, _bss_start_ofs 255 add r2, r0, r3 /* r2 <- source end address */ 256 257 stmfd sp!, {r0-r12} 258copy_loop: 259 ldmia r0!, {r3-r5, r7-r11} /* copy from source address [r0] */ 260 stmia r1!, {r3-r5, r7-r11} /* copy to target address [r1] */ 261 cmp r0, r2 /* until source end address [r2] */ 262 blo copy_loop 263 ldmfd sp!, {r0-r12} 264 265#ifndef CONFIG_SPL_BUILD 266 /* 267 * fix .rel.dyn relocations 268 */ 269 ldr r0, _TEXT_BASE /* r0 <- Text base */ 270 sub r9, r6, r0 /* r9 <- relocation offset */ 271 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ 272 add r10, r10, r0 /* r10 <- sym table in FLASH */ 273 ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ 274 add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ 275 ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ 276 add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ 277fixloop: 278 ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ 279 add r0, r9 /* r0 <- location to fix up in RAM */ 280 ldr r1, [r2, #4] 281 and r7, r1, #0xff 282 cmp r7, #23 /* relative fixup? */ 283 beq fixrel 284 cmp r7, #2 /* absolute fixup? */ 285 beq fixabs 286 /* ignore unknown type of fixup */ 287 b fixnext 288fixabs: 289 /* absolute fix: set location to (offset) symbol value */ 290 mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ 291 add r1, r10, r1 /* r1 <- address of symbol in table */ 292 ldr r1, [r1, #4] /* r1 <- symbol value */ 293 add r1, r1, r9 /* r1 <- relocated sym addr */ 294 b fixnext 295fixrel: 296 /* relative fix: increase location by offset */ 297 ldr r1, [r0] 298 add r1, r1, r9 299fixnext: 300 str r1, [r0] 301 add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ 302 cmp r2, r3 303 blo fixloop 304#endif /* #ifndef CONFIG_SPL_BUILD */ 305 306clear_bss: 307#ifndef CONFIG_SPL_BUILD 308 ldr r0, _bss_start_ofs 309 ldr r1, _bss_end_ofs 310 mov r4, r6 /* reloc addr */ 311 add r0, r0, r4 312 add r1, r1, r4 313 mov r2, #0x00000000 /* clear */ 314 315clbss_l:str r2, [r0] /* clear loop... */ 316 add r0, r0, #4 317 cmp r0, r1 318 bne clbss_l 319#endif /* #ifndef CONFIG_SPL_BUILD */ 320 321/* 322 * We are done. Do not return, instead branch to second part of board 323 * initialization, now running from RAM. 324 */ 325#ifdef CONFIG_ONENAND_IPL 326 ldr r0, _start_oneboot_ofs 327 mov pc, r0 328 329_start_oneboot_ofs 330 : .word start_oneboot 331#else 332 ldr r0, _board_init_r_ofs 333 adr r1, _start 334 add lr, r0, r1 335 add lr, lr, r9 336 /* setup parameters for board_init_r */ 337 mov r0, r5 /* gd_t */ 338 mov r1, r6 /* dest_addr */ 339 /* jump to it ... */ 340 mov pc, lr 341 342_board_init_r_ofs: 343 .word board_init_r - _start 344#endif /* CONFIG_ONENAND_IPL */ 345 346_rel_dyn_start_ofs: 347 .word __rel_dyn_start - _start 348_rel_dyn_end_ofs: 349 .word __rel_dyn_end - _start 350_dynsym_start_ofs: 351 .word __dynsym_start - _start 352 353#else /* CONFIG_SPL_BUILD */ 354 355/****************************************************************************/ 356/* */ 357/* the actual reset code for OneNAND IPL */ 358/* */ 359/****************************************************************************/ 360 361#ifndef CONFIG_PXA27X 362#error OneNAND IPL is not supported on PXA25x and 26x due to lack of SRAM 363#endif 364 365reset: 366 /* Set CPU to SVC32 mode */ 367 mrs r0,cpsr 368 bic r0,r0,#0x1f 369 orr r0,r0,#0x13 370 msr cpsr,r0 371 372 /* Point stack at the end of SRAM and leave 32 words for abort-stack */ 373 ldr sp, =0x5c03ff80 374 375 /* Start OneNAND IPL */ 376 ldr pc, =start_oneboot 377 378#endif /* CONFIG_SPL_BUILD */ 379 380#ifndef CONFIG_SPL_BUILD 381/****************************************************************************/ 382/* */ 383/* Interrupt handling */ 384/* */ 385/****************************************************************************/ 386 387/* IRQ stack frame */ 388 389#define S_FRAME_SIZE 72 390 391#define S_OLD_R0 68 392#define S_PSR 64 393#define S_PC 60 394#define S_LR 56 395#define S_SP 52 396 397#define S_IP 48 398#define S_FP 44 399#define S_R10 40 400#define S_R9 36 401#define S_R8 32 402#define S_R7 28 403#define S_R6 24 404#define S_R5 20 405#define S_R4 16 406#define S_R3 12 407#define S_R2 8 408#define S_R1 4 409#define S_R0 0 410 411#define MODE_SVC 0x13 412 413 /* use bad_save_user_regs for abort/prefetch/undef/swi ... */ 414 415 .macro bad_save_user_regs 416 sub sp, sp, #S_FRAME_SIZE 417 stmia sp, {r0 - r12} /* Calling r0-r12 */ 418 add r8, sp, #S_PC 419 420 ldr r2, IRQ_STACK_START_IN 421 ldmia r2, {r2 - r4} /* get pc, cpsr, old_r0 */ 422 add r0, sp, #S_FRAME_SIZE /* restore sp_SVC */ 423 424 add r5, sp, #S_SP 425 mov r1, lr 426 stmia r5, {r0 - r4} /* save sp_SVC, lr_SVC, pc, cpsr, old_r */ 427 mov r0, sp 428 .endm 429 430 431 /* use irq_save_user_regs / irq_restore_user_regs for */ 432 /* IRQ/FIQ handling */ 433 434 .macro irq_save_user_regs 435 sub sp, sp, #S_FRAME_SIZE 436 stmia sp, {r0 - r12} /* Calling r0-r12 */ 437 add r8, sp, #S_PC 438 stmdb r8, {sp, lr}^ /* Calling SP, LR */ 439 str lr, [r8, #0] /* Save calling PC */ 440 mrs r6, spsr 441 str r6, [r8, #4] /* Save CPSR */ 442 str r0, [r8, #8] /* Save OLD_R0 */ 443 mov r0, sp 444 .endm 445 446 .macro irq_restore_user_regs 447 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 448 mov r0, r0 449 ldr lr, [sp, #S_PC] @ Get PC 450 add sp, sp, #S_FRAME_SIZE 451 subs pc, lr, #4 @ return & move spsr_svc into cpsr 452 .endm 453 454 .macro get_bad_stack 455 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 456 457 str lr, [r13] @ save caller lr / spsr 458 mrs lr, spsr 459 str lr, [r13, #4] 460 461 mov r13, #MODE_SVC @ prepare SVC-Mode 462 msr spsr_c, r13 463 mov lr, pc 464 movs pc, lr 465 .endm 466 467 .macro get_irq_stack @ setup IRQ stack 468 ldr sp, IRQ_STACK_START 469 .endm 470 471 .macro get_fiq_stack @ setup FIQ stack 472 ldr sp, FIQ_STACK_START 473 .endm 474#endif /* CONFIG_SPL_BUILD 475 476 477/****************************************************************************/ 478/* */ 479/* exception handlers */ 480/* */ 481/****************************************************************************/ 482 483#ifdef CONFIG_SPL_BUILD 484 .align 5 485do_hang: 486 ldr sp, _TEXT_BASE /* use 32 words abort stack */ 487 bl hang /* hang and never return */ 488#else 489 .align 5 490undefined_instruction: 491 get_bad_stack 492 bad_save_user_regs 493 bl do_undefined_instruction 494 495 .align 5 496software_interrupt: 497 get_bad_stack 498 bad_save_user_regs 499 bl do_software_interrupt 500 501 .align 5 502prefetch_abort: 503 get_bad_stack 504 bad_save_user_regs 505 bl do_prefetch_abort 506 507 .align 5 508data_abort: 509 get_bad_stack 510 bad_save_user_regs 511 bl do_data_abort 512 513 .align 5 514not_used: 515 get_bad_stack 516 bad_save_user_regs 517 bl do_not_used 518 519#ifdef CONFIG_USE_IRQ 520 521 .align 5 522irq: 523 get_irq_stack 524 irq_save_user_regs 525 bl do_irq 526 irq_restore_user_regs 527 528 .align 5 529fiq: 530 get_fiq_stack 531 irq_save_user_regs /* someone ought to write a more */ 532 bl do_fiq /* effiction fiq_save_user_regs */ 533 irq_restore_user_regs 534 535#else /* !CONFIG_USE_IRQ */ 536 537 .align 5 538irq: 539 get_bad_stack 540 bad_save_user_regs 541 bl do_irq 542 543 .align 5 544fiq: 545 get_bad_stack 546 bad_save_user_regs 547 bl do_fiq 548#endif /* CONFIG_SPL_BUILD */ 549#endif /* CONFIG_USE_IRQ */ 550 551/****************************************************************************/ 552/* */ 553/* Reset function: the PXA250 doesn't have a reset function, so we have to */ 554/* perform a watchdog timeout for a soft reset. */ 555/* */ 556/****************************************************************************/ 557/* Operating System Timer */ 558.align 5 559.globl reset_cpu 560 561 /* FIXME: this code is PXA250 specific. How is this handled on */ 562 /* other XScale processors? */ 563 564reset_cpu: 565 566 /* We set OWE:WME (watchdog enable) and wait until timeout happens */ 567 568 ldr r0, =OWER 569 ldr r1, [r0] 570 orr r1, r1, #0x0001 /* bit0: WME */ 571 str r1, [r0] 572 573 /* OS timer does only wrap every 1165 seconds, so we have to set */ 574 /* the match register as well. */ 575 576 ldr r0, =OSCR 577 ldr r1, [r0] /* read OS timer */ 578 add r1, r1, #0x800 /* let OSMR3 match after */ 579 add r1, r1, #0x800 /* 4096*(1/3.6864MHz)=1ms */ 580 ldr r0, =OSMR3 581 str r1, [r0] 582 583reset_endless: 584 585 b reset_endless 586 587#ifndef CONFIG_SPL_BUILD 588.section .mmudata, "a" 589 .align 14 590 .globl mmu_table 591mmu_table: 592 /* 0x00000000 - 0xa0000000 : 1:1, uncached mapping */ 593 .set __base, 0 594 .rept 0xa00 595 .word (__base << 20) | 0xc12 596 .set __base, __base + 1 597 .endr 598 599 /* 0xa0000000 - 0xa0100000 : 1:1, cached mapping */ 600 .word (0xa00 << 20) | 0x1c1e 601 602 .set __base, 0xa01 603 .rept 0x1000 - 0xa01 604 .word (__base << 20) | 0xc12 605 .set __base, __base + 1 606 .endr 607#endif /* CONFIG_SPL_BUILD */ 608