uboot/arch/arm/cpu/pxa/start.S
<<
>>
Prefs
   1/*
   2 *  armboot - Startup Code for XScale CPU-core
   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) 2001  Marius Groger <mag@sysgo.de>
   9 *  Copyright (C) 2002  Alex Zupke <azu@sysgo.de>
  10 *  Copyright (C) 2002  Gary Jennejohn <garyj@denx.de>
  11 *  Copyright (C) 2002  Kyle Harris <kharris@nexus-tech.net>
  12 *  Copyright (C) 2003  Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
  13 *  Copyright (C) 2003  Kshitij <kshitij@ti.com>
  14 *  Copyright (C) 2003  Richard Woodruff <r-woodruff2@ti.com>
  15 *  Copyright (C) 2003  Robert Schwebel <r.schwebel@pengutronix.de>
  16 *  Copyright (C) 2004  Texas Instruments <r-woodruff2@ti.com>
  17 *  Copyright (C) 2010  Marek Vasut <marek.vasut@gmail.com>
  18 *
  19 * See file CREDITS for list of people who contributed to this
  20 * project.
  21 *
  22 * This program is free software; you can redistribute it and/or
  23 * modify it under the terms of the GNU General Public License as
  24 * published by the Free Software Foundation; either version 2 of
  25 * the License, or (at your option) any later version.
  26 *
  27 * This program is distributed in the hope that it will be useful,
  28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30 * GNU General Public License for more details.
  31 *
  32 * You should have received a copy of the GNU General Public License
  33 * along with this program; if not, write to the Free Software
  34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  35 * MA 02111-1307 USA
  36 */
  37
  38#include <asm-offsets.h>
  39#include <config.h>
  40#include <version.h>
  41
  42#ifdef CONFIG_CPU_PXA25X
  43#if ((CONFIG_SYS_INIT_SP_ADDR) != 0xfffff800)
  44#error "Init SP address must be set to 0xfffff800 for PXA250"
  45#endif
  46#endif
  47
  48.globl _start
  49_start: b       reset
  50#ifdef CONFIG_SPL_BUILD
  51        ldr     pc, _hang
  52        ldr     pc, _hang
  53        ldr     pc, _hang
  54        ldr     pc, _hang
  55        ldr     pc, _hang
  56        ldr     pc, _hang
  57        ldr     pc, _hang
  58
  59_hang:
  60        .word   do_hang
  61        .word   0x12345678
  62        .word   0x12345678
  63        .word   0x12345678
  64        .word   0x12345678
  65        .word   0x12345678
  66        .word   0x12345678
  67        .word   0x12345678      /* now 16*4=64 */
  68#else
  69        ldr     pc, _undefined_instruction
  70        ldr     pc, _software_interrupt
  71        ldr     pc, _prefetch_abort
  72        ldr     pc, _data_abort
  73        ldr     pc, _not_used
  74        ldr     pc, _irq
  75        ldr     pc, _fiq
  76
  77_undefined_instruction: .word undefined_instruction
  78_software_interrupt:    .word software_interrupt
  79_prefetch_abort:        .word prefetch_abort
  80_data_abort:            .word data_abort
  81_not_used:              .word not_used
  82_irq:                   .word irq
  83_fiq:                   .word fiq
  84_pad:                   .word 0x12345678 /* now 16*4=64 */
  85#endif  /* CONFIG_SPL_BUILD */
  86.global _end_vect
  87_end_vect:
  88
  89        .balignl 16,0xdeadbeef
  90/*
  91 *************************************************************************
  92 *
  93 * Startup Code (reset vector)
  94 *
  95 * do important init only if we don't start from memory!
  96 * setup Memory and board specific bits prior to relocation.
  97 * relocate armboot to ram
  98 * setup stack
  99 *
 100 *************************************************************************
 101 */
 102
 103.globl _TEXT_BASE
 104_TEXT_BASE:
 105#ifdef  CONFIG_SPL_BUILD
 106        .word   CONFIG_SPL_TEXT_BASE
 107#else
 108        .word   CONFIG_SYS_TEXT_BASE
 109#endif
 110
 111/*
 112 * These are defined in the board-specific linker script.
 113 * Subtracting _start from them lets the linker put their
 114 * relative position in the executable instead of leaving
 115 * them null.
 116 */
 117.globl _bss_start_ofs
 118_bss_start_ofs:
 119        .word __bss_start - _start
 120
 121.globl _bss_end_ofs
 122_bss_end_ofs:
 123        .word __bss_end__ - _start
 124
 125.globl _end_ofs
 126_end_ofs:
 127        .word _end - _start
 128
 129#ifdef CONFIG_USE_IRQ
 130/* IRQ stack memory (calculated at run-time) */
 131.globl IRQ_STACK_START
 132IRQ_STACK_START:
 133        .word   0x0badc0de
 134
 135/* IRQ stack memory (calculated at run-time) */
 136.globl FIQ_STACK_START
 137FIQ_STACK_START:
 138        .word 0x0badc0de
 139#endif
 140
 141/* IRQ stack memory (calculated at run-time) + 8 bytes */
 142.globl IRQ_STACK_START_IN
 143IRQ_STACK_START_IN:
 144        .word   0x0badc0de
 145
 146/*
 147 * the actual reset code
 148 */
 149
 150reset:
 151        /*
 152         * set the cpu to SVC32 mode
 153         */
 154        mrs     r0,cpsr
 155        bic     r0,r0,#0x1f
 156        orr     r0,r0,#0xd3
 157        msr     cpsr,r0
 158
 159#ifndef CONFIG_SKIP_LOWLEVEL_INIT
 160        bl  cpu_init_crit
 161#endif
 162
 163#ifdef  CONFIG_CPU_PXA25X
 164        bl      lock_cache_for_stack
 165#endif
 166
 167/* Set stackpointer in internal RAM to call board_init_f */
 168call_board_init_f:
 169        ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
 170        bic     sp, sp, #7 /* 8-byte alignment for ABI compliance */
 171        ldr     r0, =0x00000000
 172        bl      board_init_f
 173
 174/*------------------------------------------------------------------------------*/
 175#ifndef CONFIG_SPL_BUILD
 176/*
 177 * void relocate_code (addr_sp, gd, addr_moni)
 178 *
 179 * This "function" does not return, instead it continues in RAM
 180 * after relocating the monitor code.
 181 *
 182 */
 183        .globl  relocate_code
 184relocate_code:
 185        mov     r4, r0  /* save addr_sp */
 186        mov     r5, r1  /* save addr of gd */
 187        mov     r6, r2  /* save addr of destination */
 188
 189        /* Set up the stack                                                 */
 190stack_setup:
 191        mov     sp, r4
 192
 193/* Disable the Dcache RAM lock for stack now */
 194#ifdef  CONFIG_CPU_PXA25X
 195        bl      cpu_init_crit
 196#endif
 197
 198        adr     r0, _start
 199        cmp     r0, r6
 200        beq     clear_bss               /* skip relocation */
 201        mov     r1, r6                  /* r1 <- scratch for copy_loop */
 202        ldr     r3, _bss_start_ofs
 203        add     r2, r0, r3              /* r2 <- source end address         */
 204
 205copy_loop:
 206        ldmia   r0!, {r9-r10}           /* copy from source address [r0]    */
 207        stmia   r1!, {r9-r10}           /* copy to   target address [r1]    */
 208        cmp     r0, r2                  /* until source end address [r2]    */
 209        blo     copy_loop
 210
 211#ifndef CONFIG_SPL_BUILD
 212        /*
 213         * fix .rel.dyn relocations
 214         */
 215        ldr     r0, _TEXT_BASE          /* r0 <- Text base */
 216        sub     r9, r6, r0              /* r9 <- relocation offset */
 217        ldr     r10, _dynsym_start_ofs  /* r10 <- sym table ofs */
 218        add     r10, r10, r0            /* r10 <- sym table in FLASH */
 219        ldr     r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */
 220        add     r2, r2, r0              /* r2 <- rel dyn start in FLASH */
 221        ldr     r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */
 222        add     r3, r3, r0              /* r3 <- rel dyn end in FLASH */
 223fixloop:
 224        ldr     r0, [r2]                /* r0 <- location to fix up, IN FLASH! */
 225        add     r0, r0, r9              /* r0 <- location to fix up in RAM */
 226        ldr     r1, [r2, #4]
 227        and     r7, r1, #0xff
 228        cmp     r7, #23                 /* relative fixup? */
 229        beq     fixrel
 230        cmp     r7, #2                  /* absolute fixup? */
 231        beq     fixabs
 232        /* ignore unknown type of fixup */
 233        b       fixnext
 234fixabs:
 235        /* absolute fix: set location to (offset) symbol value */
 236        mov     r1, r1, LSR #4          /* r1 <- symbol index in .dynsym */
 237        add     r1, r10, r1             /* r1 <- address of symbol in table */
 238        ldr     r1, [r1, #4]            /* r1 <- symbol value */
 239        add     r1, r1, r9              /* r1 <- relocated sym addr */
 240        b       fixnext
 241fixrel:
 242        /* relative fix: increase location by offset */
 243        ldr     r1, [r0]
 244        add     r1, r1, r9
 245fixnext:
 246        str     r1, [r0]
 247        add     r2, r2, #8              /* each rel.dyn entry is 8 bytes */
 248        cmp     r2, r3
 249        blo     fixloop
 250#endif
 251
 252clear_bss:
 253#ifndef CONFIG_SPL_BUILD
 254        ldr     r0, _bss_start_ofs
 255        ldr     r1, _bss_end_ofs
 256        mov     r4, r6                  /* reloc addr */
 257        add     r0, r0, r4
 258        add     r1, r1, r4
 259        mov     r2, #0x00000000         /* clear                            */
 260
 261clbss_l:str     r2, [r0]                /* clear loop...                    */
 262        add     r0, r0, #4
 263        cmp     r0, r1
 264        bne     clbss_l
 265#endif  /* #ifndef CONFIG_SPL_BUILD */
 266
 267/*
 268 * We are done. Do not return, instead branch to second part of board
 269 * initialization, now running from RAM.
 270 */
 271#ifdef CONFIG_ONENAND_SPL
 272        ldr     r0, _onenand_boot_ofs
 273        mov     pc, r0
 274
 275_onenand_boot_ofs:
 276        .word onenand_boot
 277#else
 278jump_2_ram:
 279        ldr     r0, _board_init_r_ofs
 280        ldr     r1, _TEXT_BASE
 281        add     lr, r0, r1
 282        add     lr, lr, r9
 283        /* setup parameters for board_init_r */
 284        mov     r0, r5          /* gd_t */
 285        mov     r1, r6          /* dest_addr */
 286        /* jump to it ... */
 287        mov     pc, lr
 288
 289_board_init_r_ofs:
 290        .word board_init_r - _start
 291#endif
 292
 293_rel_dyn_start_ofs:
 294        .word __rel_dyn_start - _start
 295_rel_dyn_end_ofs:
 296        .word __rel_dyn_end - _start
 297_dynsym_start_ofs:
 298        .word __dynsym_start - _start
 299#endif
 300/*
 301 *************************************************************************
 302 *
 303 * CPU_init_critical registers
 304 *
 305 * setup important registers
 306 * setup memory timing
 307 *
 308 *************************************************************************
 309 */
 310#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_CPU_PXA25X)
 311cpu_init_crit:
 312        /*
 313         * flush v4 I/D caches
 314         */
 315        mov     r0, #0
 316        mcr     p15, 0, r0, c7, c7, 0   /* Invalidate I+D+BTB caches */
 317        mcr     p15, 0, r0, c8, c7, 0   /* Invalidate Unified TLB */
 318
 319        /*
 320         * disable MMU stuff and caches
 321         */
 322        mrc     p15, 0, r0, c1, c0, 0
 323        bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
 324        bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
 325        orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
 326        orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
 327        mcr     p15, 0, r0, c1, c0, 0
 328
 329        mov     pc, lr          /* back to my caller */
 330#endif /* !CONFIG_SKIP_LOWLEVEL_INIT || CONFIG_CPU_PXA25X */
 331
 332#ifndef CONFIG_SPL_BUILD
 333/*
 334 *************************************************************************
 335 *
 336 * Interrupt handling
 337 *
 338 *************************************************************************
 339 */
 340@
 341@ IRQ stack frame.
 342@
 343#define S_FRAME_SIZE    72
 344
 345#define S_OLD_R0        68
 346#define S_PSR           64
 347#define S_PC            60
 348#define S_LR            56
 349#define S_SP            52
 350
 351#define S_IP            48
 352#define S_FP            44
 353#define S_R10           40
 354#define S_R9            36
 355#define S_R8            32
 356#define S_R7            28
 357#define S_R6            24
 358#define S_R5            20
 359#define S_R4            16
 360#define S_R3            12
 361#define S_R2            8
 362#define S_R1            4
 363#define S_R0            0
 364
 365#define MODE_SVC 0x13
 366#define I_BIT    0x80
 367
 368/*
 369 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 370 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 371 */
 372
 373        .macro  bad_save_user_regs
 374        sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current user stack
 375        stmia   sp, {r0 - r12}                  @ Save user registers (now in svc mode) r0-r12
 376
 377        ldr     r2, IRQ_STACK_START_IN          @ set base 2 words into abort stack
 378        ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc and cpsr (into parm regs)
 379        add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
 380
 381        add     r5, sp, #S_SP
 382        mov     r1, lr
 383        stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
 384        mov     r0, sp                          @ save current stack into r0 (param register)
 385        .endm
 386
 387        .macro  irq_save_user_regs
 388        sub     sp, sp, #S_FRAME_SIZE
 389        stmia   sp, {r0 - r12}                  @ Calling r0-r12
 390        add     r8, sp, #S_PC                   @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
 391        stmdb   r8, {sp, lr}^                   @ Calling SP, LR
 392        str     lr, [r8, #0]                    @ Save calling PC
 393        mrs     r6, spsr
 394        str     r6, [r8, #4]                    @ Save CPSR
 395        str     r0, [r8, #8]                    @ Save OLD_R0
 396        mov     r0, sp
 397        .endm
 398
 399        .macro  irq_restore_user_regs
 400        ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
 401        mov     r0, r0
 402        ldr     lr, [sp, #S_PC]                 @ Get PC
 403        add     sp, sp, #S_FRAME_SIZE
 404        subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
 405        .endm
 406
 407        .macro get_bad_stack
 408        ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack (enter in banked mode)
 409
 410        str     lr, [r13]                       @ save caller lr in position 0 of saved stack
 411        mrs     lr, spsr                        @ get the spsr
 412        str     lr, [r13, #4]                   @ save spsr in position 1 of saved stack
 413
 414        mov     r13, #MODE_SVC                  @ prepare SVC-Mode
 415        @ msr   spsr_c, r13
 416        msr     spsr, r13                       @ switch modes, make sure moves will execute
 417        mov     lr, pc                          @ capture return pc
 418        movs    pc, lr                          @ jump to next instruction & switch modes.
 419        .endm
 420
 421        .macro get_bad_stack_swi
 422        sub     r13, r13, #4                    @ space on current stack for scratch reg.
 423        str     r0, [r13]                       @ save R0's value.
 424        ldr     r0, IRQ_STACK_START_IN          @ get data regions start
 425        str     lr, [r0]                        @ save caller lr in position 0 of saved stack
 426        mrs     r0, spsr                        @ get the spsr
 427        str     lr, [r0, #4]                    @ save spsr in position 1 of saved stack
 428        ldr     r0, [r13]                       @ restore r0
 429        add     r13, r13, #4                    @ pop stack entry
 430        .endm
 431
 432        .macro get_irq_stack                    @ setup IRQ stack
 433        ldr     sp, IRQ_STACK_START
 434        .endm
 435
 436        .macro get_fiq_stack                    @ setup FIQ stack
 437        ldr     sp, FIQ_STACK_START
 438        .endm
 439#endif  /* CONFIG_SPL_BUILD */
 440
 441/*
 442 * exception handlers
 443 */
 444#ifdef CONFIG_SPL_BUILD
 445        .align  5
 446do_hang:
 447        ldr     sp, _TEXT_BASE                  /* use 32 words about stack */
 448        bl      hang                            /* hang and never return */
 449#else   /* !CONFIG_SPL_BUILD */
 450        .align  5
 451undefined_instruction:
 452        get_bad_stack
 453        bad_save_user_regs
 454        bl      do_undefined_instruction
 455
 456        .align  5
 457software_interrupt:
 458        get_bad_stack_swi
 459        bad_save_user_regs
 460        bl      do_software_interrupt
 461
 462        .align  5
 463prefetch_abort:
 464        get_bad_stack
 465        bad_save_user_regs
 466        bl      do_prefetch_abort
 467
 468        .align  5
 469data_abort:
 470        get_bad_stack
 471        bad_save_user_regs
 472        bl      do_data_abort
 473
 474        .align  5
 475not_used:
 476        get_bad_stack
 477        bad_save_user_regs
 478        bl      do_not_used
 479
 480#ifdef CONFIG_USE_IRQ
 481
 482        .align  5
 483irq:
 484        get_irq_stack
 485        irq_save_user_regs
 486        bl      do_irq
 487        irq_restore_user_regs
 488
 489        .align  5
 490fiq:
 491        get_fiq_stack
 492        /* someone ought to write a more effiction fiq_save_user_regs */
 493        irq_save_user_regs
 494        bl      do_fiq
 495        irq_restore_user_regs
 496
 497#else
 498
 499        .align  5
 500irq:
 501        get_bad_stack
 502        bad_save_user_regs
 503        bl      do_irq
 504
 505        .align  5
 506fiq:
 507        get_bad_stack
 508        bad_save_user_regs
 509        bl      do_fiq
 510
 511#endif
 512        .align 5
 513#endif  /* CONFIG_SPL_BUILD */
 514
 515
 516/*
 517 * Enable MMU to use DCache as DRAM.
 518 *
 519 * This is useful on PXA25x and PXA26x in early bootstages, where there is no
 520 * other possible memory available to hold stack.
 521 */
 522#ifdef CONFIG_CPU_PXA25X
 523.macro CPWAIT reg
 524        mrc     p15, 0, \reg, c2, c0, 0
 525        mov     \reg, \reg
 526        sub     pc, pc, #4
 527.endm
 528lock_cache_for_stack:
 529        /* Domain access -- enable for all CPs */
 530        ldr     r0, =0x0000ffff
 531        mcr     p15, 0, r0, c3, c0, 0
 532
 533        /* Point TTBR to MMU table */
 534        ldr     r0, =mmutable
 535        mcr     p15, 0, r0, c2, c0, 0
 536
 537        /* Kick in MMU, ICache, DCache, BTB */
 538        mrc     p15, 0, r0, c1, c0, 0
 539        bic     r0, #0x1b00
 540        bic     r0, #0x0087
 541        orr     r0, #0x1800
 542        orr     r0, #0x0005
 543        mcr     p15, 0, r0, c1, c0, 0
 544        CPWAIT  r0
 545
 546        /* Unlock Icache, Dcache */
 547        mcr     p15, 0, r0, c9, c1, 1
 548        mcr     p15, 0, r0, c9, c2, 1
 549
 550        /* Flush Icache, Dcache, BTB */
 551        mcr     p15, 0, r0, c7, c7, 0
 552
 553        /* Unlock I-TLB, D-TLB */
 554        mcr     p15, 0, r0, c10, c4, 1
 555        mcr     p15, 0, r0, c10, c8, 1
 556
 557        /* Flush TLB */
 558        mcr     p15, 0, r0, c8, c7, 0
 559
 560        /* Allocate 4096 bytes of Dcache as RAM */
 561
 562        /* Drain pending loads and stores */
 563        mcr     p15, 0, r0, c7, c10, 4
 564
 565        mov     r4, #0x00
 566        mov     r5, #0x00
 567        mov     r2, #0x01
 568        mcr     p15, 0, r0, c9, c2, 0
 569        CPWAIT  r0
 570
 571        /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */
 572        mov     r0, #128
 573        ldr     r1, =0xfffff000
 574
 575alloc:
 576        mcr     p15, 0, r1, c7, c2, 5
 577        /* Drain pending loads and stores */
 578        mcr     p15, 0, r0, c7, c10, 4
 579        strd    r4, [r1], #8
 580        strd    r4, [r1], #8
 581        strd    r4, [r1], #8
 582        strd    r4, [r1], #8
 583        subs    r0, #0x01
 584        bne     alloc
 585        /* Drain pending loads and stores */
 586        mcr     p15, 0, r0, c7, c10, 4
 587        mov     r2, #0x00
 588        mcr     p15, 0, r2, c9, c2, 0
 589        CPWAIT  r0
 590
 591        mov     pc, lr
 592
 593.section .mmutable, "a"
 594mmutable:
 595        .align  14
 596        /* 0x00000000 - 0xffe00000 : 1:1, uncached mapping */
 597        .set    __base, 0
 598        .rept   0xfff
 599        .word   (__base << 20) | 0xc12
 600        .set    __base, __base + 1
 601        .endr
 602
 603        /* 0xfff00000 : 1:1, cached mapping */
 604        .word   (0xfff << 20) | 0x1c1e
 605#endif  /* CONFIG_CPU_PXA25X */
 606