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 * 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#include <asm/arch/pxa-regs.h> 34 35.globl _start 36_start: b reset 37#ifdef CONFIG_PRELOADER 38 ldr pc, _hang 39 ldr pc, _hang 40 ldr pc, _hang 41 ldr pc, _hang 42 ldr pc, _hang 43 ldr pc, _hang 44 ldr pc, _hang 45 46_hang: 47 .word do_hang 48 .word 0x12345678 49 .word 0x12345678 50 .word 0x12345678 51 .word 0x12345678 52 .word 0x12345678 53 .word 0x12345678 54 .word 0x12345678 /* now 16*4=64 */ 55#else 56 ldr pc, _undefined_instruction 57 ldr pc, _software_interrupt 58 ldr pc, _prefetch_abort 59 ldr pc, _data_abort 60 ldr pc, _not_used 61 ldr pc, _irq 62 ldr pc, _fiq 63 64_undefined_instruction: .word undefined_instruction 65_software_interrupt: .word software_interrupt 66_prefetch_abort: .word prefetch_abort 67_data_abort: .word data_abort 68_not_used: .word not_used 69_irq: .word irq 70_fiq: .word fiq 71#endif /* CONFIG_PRELOADER */ 72 73 .balignl 16,0xdeadbeef 74 75 76/* 77 * Startup Code (reset vector) 78 * 79 * do important init only if we don't start from RAM! 80 * - relocate armboot to RAM 81 * - setup stack 82 * - jump to second stage 83 */ 84 85.globl _TEXT_BASE 86_TEXT_BASE: 87 .word TEXT_BASE 88 89#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 90.globl _armboot_start 91_armboot_start: 92 .word _start 93#endif 94 95/* 96 * These are defined in the board-specific linker script. 97 */ 98.globl _bss_start 99_bss_start: 100 .word __bss_start 101 102.globl _bss_end 103_bss_end: 104 .word _end 105 106#ifdef CONFIG_USE_IRQ 107/* IRQ stack memory (calculated at run-time) */ 108.globl IRQ_STACK_START 109IRQ_STACK_START: 110 .word 0x0badc0de 111 112/* IRQ stack memory (calculated at run-time) */ 113.globl FIQ_STACK_START 114FIQ_STACK_START: 115 .word 0x0badc0de 116#endif /* CONFIG_USE_IRQ */ 117 118#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 119/* IRQ stack memory (calculated at run-time) + 8 bytes */ 120.globl IRQ_STACK_START_IN 121IRQ_STACK_START_IN: 122 .word 0x0badc0de 123 124.globl _datarel_start 125_datarel_start: 126 .word __datarel_start 127 128.globl _datarelrolocal_start 129_datarelrolocal_start: 130 .word __datarelrolocal_start 131 132.globl _datarellocal_start 133_datarellocal_start: 134 .word __datarellocal_start 135 136.globl _datarelro_start 137_datarelro_start: 138 .word __datarelro_start 139 140.globl _got_start 141_got_start: 142 .word __got_start 143 144.globl _got_end 145_got_end: 146 .word __got_end 147 148/* 149 * the actual reset code 150 */ 151 152reset: 153 /* 154 * set the cpu to SVC32 mode 155 */ 156 mrs r0,cpsr 157 bic r0,r0,#0x1f 158 orr r0,r0,#0xd3 159 msr cpsr,r0 160 161 /* 162 * we do sys-critical inits only at reboot, 163 * not when booting from ram! 164 */ 165#ifndef CONFIG_SKIP_LOWLEVEL_INIT 166 bl cpu_init_crit 167#endif 168 169/* Set stackpointer in internal RAM to call board_init_f */ 170call_board_init_f: 171 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 172 ldr r0,=0x00000000 173 bl board_init_f 174 175/*------------------------------------------------------------------------------*/ 176 177/* 178 * void relocate_code (addr_sp, gd, addr_moni) 179 * 180 * This "function" does not return, instead it continues in RAM 181 * after relocating the monitor code. 182 * 183 */ 184 .globl relocate_code 185relocate_code: 186 mov r4, r0 /* save addr_sp */ 187 mov r5, r1 /* save addr of gd */ 188 mov r6, r2 /* save addr of destination */ 189 mov r7, r2 /* save addr of destination */ 190 191 /* Set up the stack */ 192stack_setup: 193 mov sp, r4 194 195 adr r0, _start 196 ldr r2, _TEXT_BASE 197 ldr r3, _bss_start 198 sub r2, r3, r2 /* r2 <- size of armboot */ 199 add r2, r0, r2 /* r2 <- source end address */ 200 cmp r0, r6 201 beq clear_bss 202 203#ifndef CONFIG_SKIP_RELOCATE_UBOOT 204copy_loop: 205 ldmia r0!, {r9-r10} /* copy from source address [r0] */ 206 stmia r6!, {r9-r10} /* copy to target address [r1] */ 207 cmp r0, r2 /* until source end addreee [r2] */ 208 ble copy_loop 209 210#ifndef CONFIG_PRELOADER 211 /* fix got entries */ 212 ldr r1, _TEXT_BASE /* Text base */ 213 mov r0, r7 /* reloc addr */ 214 ldr r2, _got_start /* addr in Flash */ 215 ldr r3, _got_end /* addr in Flash */ 216 sub r3, r3, r1 217 add r3, r3, r0 218 sub r2, r2, r1 219 add r2, r2, r0 220 221fixloop: 222 ldr r4, [r2] 223 sub r4, r4, r1 224 add r4, r4, r0 225 str r4, [r2] 226 add r2, r2, #4 227 cmp r2, r3 228 bne fixloop 229#endif 230#endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */ 231 232clear_bss: 233#ifndef CONFIG_PRELOADER 234 ldr r0, _bss_start 235 ldr r1, _bss_end 236 ldr r3, _TEXT_BASE /* Text base */ 237 mov r4, r7 /* reloc addr */ 238 sub r0, r0, r3 239 add r0, r0, r4 240 sub r1, r1, r3 241 add r1, r1, r4 242 mov r2, #0x00000000 /* clear */ 243 244clbss_l:str r2, [r0] /* clear loop... */ 245 add r0, r0, #4 246 cmp r0, r1 247 bne clbss_l 248#endif 249 250/* 251 * We are done. Do not return, instead branch to second part of board 252 * initialization, now running from RAM. 253 */ 254#ifdef CONFIG_ONENAND_IPL 255 ldr pc, _start_oneboot 256 257_start_oneboot: .word start_oneboot 258#else 259 ldr r0, _TEXT_BASE 260 ldr r2, _board_init_r 261 sub r2, r2, r0 262 add r2, r2, r7 /* position from board_init_r in RAM */ 263 /* setup parameters for board_init_r */ 264 mov r0, r5 /* gd_t */ 265 mov r1, r7 /* dest_addr */ 266 /* jump to it ... */ 267 mov lr, r2 268 mov pc, lr 269 270_board_init_r: .word board_init_r 271#endif 272 273#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ 274 275/****************************************************************************/ 276/* */ 277/* the actual reset code */ 278/* */ 279/****************************************************************************/ 280 281reset: 282 mrs r0,cpsr /* set the CPU to SVC32 mode */ 283 bic r0,r0,#0x1f /* (superviser mode, M=10011) */ 284 orr r0,r0,#0x13 285 msr cpsr,r0 286 287 /* 288 * we do sys-critical inits only at reboot, 289 * not when booting from RAM! 290 */ 291#ifndef CONFIG_SKIP_LOWLEVEL_INIT 292 bl cpu_init_crit /* we do sys-critical inits */ 293#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ 294 295#ifndef CONFIG_SKIP_RELOCATE_UBOOT 296relocate: /* relocate U-Boot to RAM */ 297 adr r0, _start /* r0 <- current position of code */ 298 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 299#ifndef CONFIG_PRELOADER 300 cmp r0, r1 /* don't reloc during debug */ 301 beq stack_setup 302#endif 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 ble copy_loop 314#endif /* !CONFIG_SKIP_RELOCATE_UBOOT */ 315 316 /* Set up the stack */ 317stack_setup: 318 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 319#ifdef CONFIG_PRELOADER 320 sub sp, r0, #128 /* leave 32 words for abort-stack */ 321#else 322 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 323 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 324#ifdef CONFIG_USE_IRQ 325 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 326#endif /* CONFIG_USE_IRQ */ 327 sub sp, r0, #12 /* leave 3 words for abort-stack */ 328 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 329#endif 330 331clear_bss: 332 ldr r0, _bss_start /* find start of bss segment */ 333 ldr r1, _bss_end /* stop here */ 334 mov r2, #0x00000000 /* clear */ 335 336#ifndef CONFIG_PRELOADER 337clbss_l:str r2, [r0] /* clear loop... */ 338 add r0, r0, #4 339 cmp r0, r1 340 ble clbss_l 341#endif 342 343 ldr pc, _start_armboot 344 345#ifdef CONFIG_ONENAND_IPL 346_start_armboot: .word start_oneboot 347#else 348_start_armboot: .word start_armboot 349#endif 350#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ 351 352/****************************************************************************/ 353/* */ 354/* CPU_init_critical registers */ 355/* */ 356/* - setup important registers */ 357/* - setup memory timing */ 358/* */ 359/****************************************************************************/ 360/* mk@tbd: Fix this! */ 361#undef RCSR 362#undef ICMR 363#undef OSMR3 364#undef OSCR 365#undef OWER 366#undef OIER 367#undef CCCR 368 369/* Interrupt-Controller base address */ 370IC_BASE: .word 0x40d00000 371#define ICMR 0x04 372 373/* Reset-Controller */ 374RST_BASE: .word 0x40f00030 375#define RCSR 0x00 376 377/* Operating System Timer */ 378OSTIMER_BASE: .word 0x40a00000 379#define OSMR3 0x0C 380#define OSCR 0x10 381#define OWER 0x18 382#define OIER 0x1C 383 384/* Clock Manager Registers */ 385#ifdef CONFIG_CPU_MONAHANS 386# ifndef CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO 387# error "You have to define CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO!!" 388# endif /* !CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO */ 389# ifndef CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 390# define CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 0x1 391# endif /* !CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO */ 392#else /* !CONFIG_CPU_MONAHANS */ 393#ifdef CONFIG_SYS_CPUSPEED 394CC_BASE: .word 0x41300000 395#define CCCR 0x00 396cpuspeed: .word CONFIG_SYS_CPUSPEED 397#else /* !CONFIG_SYS_CPUSPEED */ 398#error "You have to define CONFIG_SYS_CPUSPEED!!" 399#endif /* CONFIG_SYS_CPUSPEED */ 400#endif /* CONFIG_CPU_MONAHANS */ 401 402 /* takes care the CP15 update has taken place */ 403 .macro CPWAIT reg 404 mrc p15,0,\reg,c2,c0,0 405 mov \reg,\reg 406 sub pc,pc,#4 407 .endm 408 409cpu_init_crit: 410 411 /* mask all IRQs */ 412#ifndef CONFIG_CPU_MONAHANS 413 ldr r0, IC_BASE 414 mov r1, #0x00 415 str r1, [r0, #ICMR] 416#else /* CONFIG_CPU_MONAHANS */ 417 /* Step 1 - Enable CP6 permission */ 418 mrc p15, 0, r1, c15, c1, 0 @ read CPAR 419 orr r1, r1, #0x40 420 mcr p15, 0, r1, c15, c1, 0 421 CPWAIT r1 422 423 /* Step 2 - Mask ICMR & ICMR2 */ 424 mov r1, #0 425 mcr p6, 0, r1, c1, c0, 0 @ ICMR 426 mcr p6, 0, r1, c7, c0, 0 @ ICMR2 427 428 /* turn off all clocks but the ones we will definitly require */ 429 ldr r1, =CKENA 430 ldr r2, =(CKENA_22_FFUART | CKENA_10_SRAM | CKENA_9_SMC | CKENA_8_DMC) 431 str r2, [r1] 432 ldr r1, =CKENB 433 ldr r2, =(CKENB_6_IRQ) 434 str r2, [r1] 435#endif /* !CONFIG_CPU_MONAHANS */ 436 437 /* set clock speed */ 438#ifdef CONFIG_CPU_MONAHANS 439 ldr r0, =ACCR 440 ldr r1, =(((CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO<<8) & ACCR_XN_MASK) | (CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO & ACCR_XL_MASK)) 441 str r1, [r0] 442#else /* !CONFIG_CPU_MONAHANS */ 443#ifdef CONFIG_SYS_CPUSPEED 444 ldr r0, CC_BASE 445 ldr r1, cpuspeed 446 str r1, [r0, #CCCR] 447 mov r0, #2 448 mcr p14, 0, r0, c6, c0, 0 449 450setspeed_done: 451 452#endif /* CONFIG_SYS_CPUSPEED */ 453#endif /* CONFIG_CPU_MONAHANS */ 454 455 /* 456 * before relocating, we have to setup RAM timing 457 * because memory timing is board-dependend, you will 458 * find a lowlevel_init.S in your board directory. 459 */ 460 mov ip, lr 461 bl lowlevel_init 462 mov lr, ip 463 464 /* Memory interfaces are working. Disable MMU and enable I-cache. */ 465 /* mk: hmm, this is not in the monahans docs, leave it now but 466 * check here if it doesn't work :-) */ 467 468 ldr r0, =0x2001 /* enable access to all coproc. */ 469 mcr p15, 0, r0, c15, c1, 0 470 CPWAIT r0 471 472 mcr p15, 0, r0, c7, c10, 4 /* drain the write & fill buffers */ 473 CPWAIT r0 474 475 mcr p15, 0, r0, c7, c7, 0 /* flush Icache, Dcache and BTB */ 476 CPWAIT r0 477 478 mcr p15, 0, r0, c8, c7, 0 /* flush instuction and data TLBs */ 479 CPWAIT r0 480 481 /* Enable the Icache */ 482/* 483 mrc p15, 0, r0, c1, c0, 0 484 orr r0, r0, #0x1800 485 mcr p15, 0, r0, c1, c0, 0 486 CPWAIT 487*/ 488 mov pc, lr 489 490#ifndef CONFIG_PRELOADER 491/****************************************************************************/ 492/* */ 493/* Interrupt handling */ 494/* */ 495/****************************************************************************/ 496 497/* IRQ stack frame */ 498 499#define S_FRAME_SIZE 72 500 501#define S_OLD_R0 68 502#define S_PSR 64 503#define S_PC 60 504#define S_LR 56 505#define S_SP 52 506 507#define S_IP 48 508#define S_FP 44 509#define S_R10 40 510#define S_R9 36 511#define S_R8 32 512#define S_R7 28 513#define S_R6 24 514#define S_R5 20 515#define S_R4 16 516#define S_R3 12 517#define S_R2 8 518#define S_R1 4 519#define S_R0 0 520 521#define MODE_SVC 0x13 522 523 /* use bad_save_user_regs for abort/prefetch/undef/swi ... */ 524 525 .macro bad_save_user_regs 526 sub sp, sp, #S_FRAME_SIZE 527 stmia sp, {r0 - r12} /* Calling r0-r12 */ 528 add r8, sp, #S_PC 529 530#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 531 ldr r2, _armboot_start 532 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 533 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 534#else 535 ldr r2, IRQ_STACK_START_IN 536#endif 537 ldmia r2, {r2 - r4} /* get pc, cpsr, old_r0 */ 538 add r0, sp, #S_FRAME_SIZE /* restore sp_SVC */ 539 540 add r5, sp, #S_SP 541 mov r1, lr 542 stmia r5, {r0 - r4} /* save sp_SVC, lr_SVC, pc, cpsr, old_r */ 543 mov r0, sp 544 .endm 545 546 547 /* use irq_save_user_regs / irq_restore_user_regs for */ 548 /* IRQ/FIQ handling */ 549 550 .macro irq_save_user_regs 551 sub sp, sp, #S_FRAME_SIZE 552 stmia sp, {r0 - r12} /* Calling r0-r12 */ 553 add r8, sp, #S_PC 554 stmdb r8, {sp, lr}^ /* Calling SP, LR */ 555 str lr, [r8, #0] /* Save calling PC */ 556 mrs r6, spsr 557 str r6, [r8, #4] /* Save CPSR */ 558 str r0, [r8, #8] /* Save OLD_R0 */ 559 mov r0, sp 560 .endm 561 562 .macro irq_restore_user_regs 563 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 564 mov r0, r0 565 ldr lr, [sp, #S_PC] @ Get PC 566 add sp, sp, #S_FRAME_SIZE 567 subs pc, lr, #4 @ return & move spsr_svc into cpsr 568 .endm 569 570 .macro get_bad_stack 571#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) 572 ldr r13, _armboot_start @ setup our mode stack 573 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 574 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 575#else 576 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 577#endif 578 579 str lr, [r13] @ save caller lr / spsr 580 mrs lr, spsr 581 str lr, [r13, #4] 582 583 mov r13, #MODE_SVC @ prepare SVC-Mode 584 msr spsr_c, r13 585 mov lr, pc 586 movs pc, lr 587 .endm 588 589 .macro get_irq_stack @ setup IRQ stack 590 ldr sp, IRQ_STACK_START 591 .endm 592 593 .macro get_fiq_stack @ setup FIQ stack 594 ldr sp, FIQ_STACK_START 595 .endm 596#endif /* CONFIG_PRELOADER */ 597 598 599/****************************************************************************/ 600/* */ 601/* exception handlers */ 602/* */ 603/****************************************************************************/ 604 605#ifdef CONFIG_PRELOADER 606 .align 5 607do_hang: 608 ldr sp, _TEXT_BASE /* use 32 words abort stack */ 609 bl hang /* hang and never return */ 610#else /* !CONFIG_PRELOADER */ 611 .align 5 612undefined_instruction: 613 get_bad_stack 614 bad_save_user_regs 615 bl do_undefined_instruction 616 617 .align 5 618software_interrupt: 619 get_bad_stack 620 bad_save_user_regs 621 bl do_software_interrupt 622 623 .align 5 624prefetch_abort: 625 get_bad_stack 626 bad_save_user_regs 627 bl do_prefetch_abort 628 629 .align 5 630data_abort: 631 get_bad_stack 632 bad_save_user_regs 633 bl do_data_abort 634 635 .align 5 636not_used: 637 get_bad_stack 638 bad_save_user_regs 639 bl do_not_used 640 641#ifdef CONFIG_USE_IRQ 642 643 .align 5 644irq: 645 get_irq_stack 646 irq_save_user_regs 647 bl do_irq 648 irq_restore_user_regs 649 650 .align 5 651fiq: 652 get_fiq_stack 653 irq_save_user_regs /* someone ought to write a more */ 654 bl do_fiq /* effiction fiq_save_user_regs */ 655 irq_restore_user_regs 656 657#else /* !CONFIG_USE_IRQ */ 658 659 .align 5 660irq: 661 get_bad_stack 662 bad_save_user_regs 663 bl do_irq 664 665 .align 5 666fiq: 667 get_bad_stack 668 bad_save_user_regs 669 bl do_fiq 670#endif /* CONFIG_PRELOADER */ 671#endif /* CONFIG_USE_IRQ */ 672 673/****************************************************************************/ 674/* */ 675/* Reset function: the PXA250 doesn't have a reset function, so we have to */ 676/* perform a watchdog timeout for a soft reset. */ 677/* */ 678/****************************************************************************/ 679 680 .align 5 681.globl reset_cpu 682 683 /* FIXME: this code is PXA250 specific. How is this handled on */ 684 /* other XScale processors? */ 685 686reset_cpu: 687 688 /* We set OWE:WME (watchdog enable) and wait until timeout happens */ 689 690 ldr r0, OSTIMER_BASE 691 ldr r1, [r0, #OWER] 692 orr r1, r1, #0x0001 /* bit0: WME */ 693 str r1, [r0, #OWER] 694 695 /* OS timer does only wrap every 1165 seconds, so we have to set */ 696 /* the match register as well. */ 697 698 ldr r1, [r0, #OSCR] /* read OS timer */ 699 add r1, r1, #0x800 /* let OSMR3 match after */ 700 add r1, r1, #0x800 /* 4096*(1/3.6864MHz)=1ms */ 701 str r1, [r0, #OSMR3] 702 703reset_endless: 704 705 b reset_endless 706