uboot/arch/arm/cpu/lh7a40x/start.S
<<
>>
Prefs
   1/*
   2 *  armboot - Startup Code for ARM920 CPU-core
   3 *
   4 *  Copyright (c) 2001  Marius Gröger <mag@sysgo.de>
   5 *  Copyright (c) 2002  Alex Züpke <azu@sysgo.de>
   6 *  Copyright (c) 2002  Gary Jennejohn <garyj@denx.de>
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27
  28#include <config.h>
  29#include <version.h>
  30
  31
  32/*
  33 *************************************************************************
  34 *
  35 * Jump vector table as in table 3.1 in [1]
  36 *
  37 *************************************************************************
  38 */
  39
  40
  41.globl _start
  42_start: b       reset
  43        ldr     pc, _undefined_instruction
  44        ldr     pc, _software_interrupt
  45        ldr     pc, _prefetch_abort
  46        ldr     pc, _data_abort
  47        ldr     pc, _not_used
  48        ldr     pc, _irq
  49        ldr     pc, _fiq
  50
  51_undefined_instruction: .word undefined_instruction
  52_software_interrupt:    .word software_interrupt
  53_prefetch_abort:        .word prefetch_abort
  54_data_abort:            .word data_abort
  55_not_used:              .word not_used
  56_irq:                   .word irq
  57_fiq:                   .word fiq
  58
  59        .balignl 16,0xdeadbeef
  60
  61
  62/*
  63 *************************************************************************
  64 *
  65 * Startup Code (reset vector)
  66 *
  67 * do important init only if we don't start from memory!
  68 * relocate armboot to ram
  69 * setup stack
  70 * jump to second stage
  71 *
  72 *************************************************************************
  73 */
  74
  75_TEXT_BASE:
  76        .word   TEXT_BASE
  77
  78.globl _armboot_start
  79_armboot_start:
  80        .word _start
  81
  82/*
  83 * These are defined in the board-specific linker script.
  84 */
  85.globl _bss_start
  86_bss_start:
  87        .word __bss_start
  88
  89.globl _bss_end
  90_bss_end:
  91        .word _end
  92
  93#ifdef CONFIG_USE_IRQ
  94/* IRQ stack memory (calculated at run-time) */
  95.globl IRQ_STACK_START
  96IRQ_STACK_START:
  97        .word   0x0badc0de
  98
  99/* IRQ stack memory (calculated at run-time) */
 100.globl FIQ_STACK_START
 101FIQ_STACK_START:
 102        .word 0x0badc0de
 103#endif
 104
 105
 106/*
 107 * the actual reset code
 108 */
 109
 110reset:
 111        /*
 112         * set the cpu to SVC32 mode
 113         */
 114        mrs     r0,cpsr
 115        bic     r0,r0,#0x1f
 116        orr     r0,r0,#0xd3
 117        msr     cpsr,r0
 118
 119#define pWDTCTL         0x80001400  /* Watchdog Timer control register */
 120#define pINTENC         0x8000050C  /* Interupt-Controller enable clear register */
 121#define pCLKSET         0x80000420  /* clock divisor register */
 122
 123        /* disable watchdog, set watchdog control register to
 124         * all zeros (default reset)
 125         */
 126        ldr     r0, =pWDTCTL
 127        mov     r1, #0x0
 128        str     r1, [r0]
 129
 130        /*
 131         * mask all IRQs by setting all bits in the INTENC register (default)
 132         */
 133        mov     r1, #0xffffffff
 134        ldr     r0, =pINTENC
 135        str     r1, [r0]
 136
 137        /* FCLK:HCLK:PCLK = 1:2:2 */
 138        /* default FCLK is 200 MHz, using 14.7456 MHz fin */
 139        ldr     r0, =pCLKSET
 140        ldr r1, =0x0004ee39
 141@       ldr r1, =0x0005ee39     @ 1: 2: 4
 142        str     r1, [r0]
 143
 144        /*
 145         * we do sys-critical inits only at reboot,
 146         * not when booting from ram!
 147         */
 148#ifndef CONFIG_SKIP_LOWLEVEL_INIT
 149        bl      cpu_init_crit
 150#endif
 151
 152#ifndef CONFIG_SKIP_RELOCATE_UBOOT
 153relocate:                               /* relocate U-Boot to RAM           */
 154        adr     r0, _start              /* r0 <- current position of code   */
 155        ldr     r1, _TEXT_BASE          /* test if we run from flash or RAM */
 156        cmp     r0, r1                  /* don't reloc during debug         */
 157        beq     stack_setup
 158
 159        ldr     r2, _armboot_start
 160        ldr     r3, _bss_start
 161        sub     r2, r3, r2              /* r2 <- size of armboot            */
 162        add     r2, r0, r2              /* r2 <- source end address         */
 163
 164copy_loop:
 165        ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
 166        stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
 167        cmp     r0, r2                  /* until source end addreee [r2]    */
 168        blt     copy_loop               /* a 'ble' here actually copies     */
 169                                        /*   four bytes of bss              */
 170#endif  /* CONFIG_SKIP_RELOCATE_UBOOT */
 171
 172        /* Set up the stack                                                 */
 173stack_setup:
 174        ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
 175        sub     r0, r0, #CONFIG_SYS_MALLOC_LEN  /* malloc area                      */
 176        sub     r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                        */
 177#ifdef CONFIG_USE_IRQ
 178        sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
 179#endif
 180        sub     sp, r0, #12             /* leave 3 words for abort-stack    */
 181        bic     sp, sp, #7              /* 8-byte alignment for ABI compliance */
 182
 183clear_bss:
 184        ldr     r0, _bss_start          /* find start of bss segment        */
 185        @add    r0, r0, #4              /* start at first byte of bss       */
 186                                        /*   why inc. 4 bytes past then?    */
 187        ldr     r1, _bss_end            /* stop here                        */
 188        mov     r2, #0x00000000         /* clear                            */
 189
 190clbss_l:str     r2, [r0]                /* clear loop...                    */
 191        add     r0, r0, #4
 192        cmp     r0, r1
 193        ble     clbss_l
 194
 195        ldr     pc, _start_armboot
 196
 197_start_armboot: .word start_armboot
 198
 199
 200/*
 201 *************************************************************************
 202 *
 203 * CPU_init_critical registers
 204 *
 205 * setup important registers
 206 * setup memory timing
 207 *
 208 *************************************************************************
 209 */
 210
 211
 212cpu_init_crit:
 213        /*
 214         * flush v4 I/D caches
 215         */
 216        mov     r0, #0
 217        mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
 218        mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
 219
 220        /*
 221         * disable MMU stuff and caches
 222         */
 223        mrc     p15, 0, r0, c1, c0, 0
 224        bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
 225        bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
 226        orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
 227        orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
 228        orr     r0, r0, #0x40000000     @ set bit 30 (nF) notFastBus
 229        mcr     p15, 0, r0, c1, c0, 0
 230
 231
 232        /*
 233         * before relocating, we have to setup RAM timing
 234         * because memory timing is board-dependend, you will
 235         * find a lowlevel_init.S in your board directory.
 236         */
 237        mov     ip, lr
 238        bl      lowlevel_init
 239        mov     lr, ip
 240
 241        mov     pc, lr
 242
 243
 244/*
 245 *************************************************************************
 246 *
 247 * Interrupt handling
 248 *
 249 *************************************************************************
 250 */
 251
 252@
 253@ IRQ stack frame.
 254@
 255#define S_FRAME_SIZE    72
 256
 257#define S_OLD_R0        68
 258#define S_PSR           64
 259#define S_PC            60
 260#define S_LR            56
 261#define S_SP            52
 262
 263#define S_IP            48
 264#define S_FP            44
 265#define S_R10           40
 266#define S_R9            36
 267#define S_R8            32
 268#define S_R7            28
 269#define S_R6            24
 270#define S_R5            20
 271#define S_R4            16
 272#define S_R3            12
 273#define S_R2            8
 274#define S_R1            4
 275#define S_R0            0
 276
 277#define MODE_SVC 0x13
 278#define I_BIT    0x80
 279
 280/*
 281 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 282 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 283 */
 284
 285        .macro  bad_save_user_regs
 286        sub     sp, sp, #S_FRAME_SIZE
 287        stmia   sp, {r0 - r12}                  @ Calling r0-r12
 288        ldr     r2, _armboot_start
 289        sub     r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
 290        sub     r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
 291        ldmia   r2, {r2 - r3}                   @ get pc, cpsr
 292        add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
 293
 294        add     r5, sp, #S_SP
 295        mov     r1, lr
 296        stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
 297        mov     r0, sp
 298        .endm
 299
 300        .macro  irq_save_user_regs
 301        sub     sp, sp, #S_FRAME_SIZE
 302        stmia   sp, {r0 - r12}                  @ Calling r0-r12
 303        add     r8, sp, #S_PC
 304        stmdb   r8, {sp, lr}^                   @ Calling SP, LR
 305        str     lr, [r8, #0]                    @ Save calling PC
 306        mrs     r6, spsr
 307        str     r6, [r8, #4]                    @ Save CPSR
 308        str     r0, [r8, #8]                    @ Save OLD_R0
 309        mov     r0, sp
 310        .endm
 311
 312        .macro  irq_restore_user_regs
 313        ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
 314        mov     r0, r0
 315        ldr     lr, [sp, #S_PC]                 @ Get PC
 316        add     sp, sp, #S_FRAME_SIZE
 317        subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
 318        .endm
 319
 320        .macro get_bad_stack
 321        ldr     r13, _armboot_start             @ setup our mode stack
 322        sub     r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
 323        sub     r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
 324
 325        str     lr, [r13]                       @ save caller lr / spsr
 326        mrs     lr, spsr
 327        str     lr, [r13, #4]
 328
 329        mov     r13, #MODE_SVC                  @ prepare SVC-Mode
 330        @ msr   spsr_c, r13
 331        msr     spsr, r13
 332        mov     lr, pc
 333        movs    pc, lr
 334        .endm
 335
 336        .macro get_irq_stack                    @ setup IRQ stack
 337        ldr     sp, IRQ_STACK_START
 338        .endm
 339
 340        .macro get_fiq_stack                    @ setup FIQ stack
 341        ldr     sp, FIQ_STACK_START
 342        .endm
 343
 344/*
 345 * exception handlers
 346 */
 347        .align  5
 348undefined_instruction:
 349        get_bad_stack
 350        bad_save_user_regs
 351        bl      do_undefined_instruction
 352
 353        .align  5
 354software_interrupt:
 355        get_bad_stack
 356        bad_save_user_regs
 357        bl      do_software_interrupt
 358
 359        .align  5
 360prefetch_abort:
 361        get_bad_stack
 362        bad_save_user_regs
 363        bl      do_prefetch_abort
 364
 365        .align  5
 366data_abort:
 367        get_bad_stack
 368        bad_save_user_regs
 369        bl      do_data_abort
 370
 371        .align  5
 372not_used:
 373        get_bad_stack
 374        bad_save_user_regs
 375        bl      do_not_used
 376
 377#ifdef CONFIG_USE_IRQ
 378
 379        .align  5
 380irq:
 381        get_irq_stack
 382        irq_save_user_regs
 383        bl      do_irq
 384        irq_restore_user_regs
 385
 386        .align  5
 387fiq:
 388        get_fiq_stack
 389        /* someone ought to write a more effiction fiq_save_user_regs */
 390        irq_save_user_regs
 391        bl      do_fiq
 392        irq_restore_user_regs
 393
 394#else
 395
 396        .align  5
 397irq:
 398        get_bad_stack
 399        bad_save_user_regs
 400        bl      do_irq
 401
 402        .align  5
 403fiq:
 404        get_bad_stack
 405        bad_save_user_regs
 406        bl      do_fiq
 407
 408#endif
 409
 410        .align  5
 411.globl reset_cpu
 412reset_cpu:
 413        bl      disable_interrupts
 414
 415        /* Disable watchdog */
 416        ldr     r1, =pWDTCTL
 417        mov     r3, #0
 418        str     r3, [r1]
 419
 420        /* reset counter */
 421        ldr     r3, =0x00001984
 422        str     r3, [r1, #4]
 423
 424        /* Enable the watchdog */
 425        mov     r3, #1
 426        str     r3, [r1]
 427
 428_loop_forever:
 429        b       _loop_forever
 430