uboot/arch/mips/cpu/start.S
<<
>>
Prefs
   1/*
   2 *  Startup Code for MIPS32 CPU-core
   3 *
   4 *  Copyright (c) 2003  Wolfgang Denk <wd@denx.de>
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24
  25#include <config.h>
  26#include <asm/regdef.h>
  27#include <asm/mipsregs.h>
  28
  29        /*
  30         * For the moment disable interrupts, mark the kernel mode and
  31         * set ST0_KX so that the CPU does not spit fire when using
  32         * 64-bit addresses.
  33         */
  34        .macro  setup_c0_status set clr
  35        .set    push
  36        mfc0    t0, CP0_STATUS
  37        or      t0, ST0_CU0 | \set | 0x1f | \clr
  38        xor     t0, 0x1f | \clr
  39        mtc0    t0, CP0_STATUS
  40        .set    noreorder
  41        sll     zero, 3                         # ehb
  42        .set    pop
  43        .endm
  44
  45        .macro  setup_c0_status_reset
  46#ifdef CONFIG_64BIT
  47        setup_c0_status ST0_KX 0
  48#else
  49        setup_c0_status 0 0
  50#endif
  51        .endm
  52
  53#define RVECENT(f,n) \
  54   b f; nop
  55#define XVECENT(f,bev) \
  56   b f     ;           \
  57   li k0,bev
  58
  59        .set noreorder
  60
  61        .globl _start
  62        .text
  63_start:
  64        RVECENT(reset,0)        /* U-boot entry point */
  65        RVECENT(reset,1)        /* software reboot */
  66#if defined(CONFIG_INCA_IP)
  67        .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
  68        .word 0x00000000           /* phase of the flash                    */
  69#elif defined(CONFIG_PURPLE)
  70        .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
  71        .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
  72#else
  73        RVECENT(romReserved,2)
  74#endif
  75        RVECENT(romReserved,3)
  76        RVECENT(romReserved,4)
  77        RVECENT(romReserved,5)
  78        RVECENT(romReserved,6)
  79        RVECENT(romReserved,7)
  80        RVECENT(romReserved,8)
  81        RVECENT(romReserved,9)
  82        RVECENT(romReserved,10)
  83        RVECENT(romReserved,11)
  84        RVECENT(romReserved,12)
  85        RVECENT(romReserved,13)
  86        RVECENT(romReserved,14)
  87        RVECENT(romReserved,15)
  88        RVECENT(romReserved,16)
  89        RVECENT(romReserved,17)
  90        RVECENT(romReserved,18)
  91        RVECENT(romReserved,19)
  92        RVECENT(romReserved,20)
  93        RVECENT(romReserved,21)
  94        RVECENT(romReserved,22)
  95        RVECENT(romReserved,23)
  96        RVECENT(romReserved,24)
  97        RVECENT(romReserved,25)
  98        RVECENT(romReserved,26)
  99        RVECENT(romReserved,27)
 100        RVECENT(romReserved,28)
 101        RVECENT(romReserved,29)
 102        RVECENT(romReserved,30)
 103        RVECENT(romReserved,31)
 104        RVECENT(romReserved,32)
 105        RVECENT(romReserved,33)
 106        RVECENT(romReserved,34)
 107        RVECENT(romReserved,35)
 108        RVECENT(romReserved,36)
 109        RVECENT(romReserved,37)
 110        RVECENT(romReserved,38)
 111        RVECENT(romReserved,39)
 112        RVECENT(romReserved,40)
 113        RVECENT(romReserved,41)
 114        RVECENT(romReserved,42)
 115        RVECENT(romReserved,43)
 116        RVECENT(romReserved,44)
 117        RVECENT(romReserved,45)
 118        RVECENT(romReserved,46)
 119        RVECENT(romReserved,47)
 120        RVECENT(romReserved,48)
 121        RVECENT(romReserved,49)
 122        RVECENT(romReserved,50)
 123        RVECENT(romReserved,51)
 124        RVECENT(romReserved,52)
 125        RVECENT(romReserved,53)
 126        RVECENT(romReserved,54)
 127        RVECENT(romReserved,55)
 128        RVECENT(romReserved,56)
 129        RVECENT(romReserved,57)
 130        RVECENT(romReserved,58)
 131        RVECENT(romReserved,59)
 132        RVECENT(romReserved,60)
 133        RVECENT(romReserved,61)
 134        RVECENT(romReserved,62)
 135        RVECENT(romReserved,63)
 136        XVECENT(romExcHandle,0x200)     /* bfc00200: R4000 tlbmiss vector */
 137        RVECENT(romReserved,65)
 138        RVECENT(romReserved,66)
 139        RVECENT(romReserved,67)
 140        RVECENT(romReserved,68)
 141        RVECENT(romReserved,69)
 142        RVECENT(romReserved,70)
 143        RVECENT(romReserved,71)
 144        RVECENT(romReserved,72)
 145        RVECENT(romReserved,73)
 146        RVECENT(romReserved,74)
 147        RVECENT(romReserved,75)
 148        RVECENT(romReserved,76)
 149        RVECENT(romReserved,77)
 150        RVECENT(romReserved,78)
 151        RVECENT(romReserved,79)
 152        XVECENT(romExcHandle,0x280)     /* bfc00280: R4000 xtlbmiss vector */
 153        RVECENT(romReserved,81)
 154        RVECENT(romReserved,82)
 155        RVECENT(romReserved,83)
 156        RVECENT(romReserved,84)
 157        RVECENT(romReserved,85)
 158        RVECENT(romReserved,86)
 159        RVECENT(romReserved,87)
 160        RVECENT(romReserved,88)
 161        RVECENT(romReserved,89)
 162        RVECENT(romReserved,90)
 163        RVECENT(romReserved,91)
 164        RVECENT(romReserved,92)
 165        RVECENT(romReserved,93)
 166        RVECENT(romReserved,94)
 167        RVECENT(romReserved,95)
 168        XVECENT(romExcHandle,0x300)     /* bfc00300: R4000 cache vector */
 169        RVECENT(romReserved,97)
 170        RVECENT(romReserved,98)
 171        RVECENT(romReserved,99)
 172        RVECENT(romReserved,100)
 173        RVECENT(romReserved,101)
 174        RVECENT(romReserved,102)
 175        RVECENT(romReserved,103)
 176        RVECENT(romReserved,104)
 177        RVECENT(romReserved,105)
 178        RVECENT(romReserved,106)
 179        RVECENT(romReserved,107)
 180        RVECENT(romReserved,108)
 181        RVECENT(romReserved,109)
 182        RVECENT(romReserved,110)
 183        RVECENT(romReserved,111)
 184        XVECENT(romExcHandle,0x380)     /* bfc00380: R4000 general vector */
 185        RVECENT(romReserved,113)
 186        RVECENT(romReserved,114)
 187        RVECENT(romReserved,115)
 188        RVECENT(romReserved,116)
 189        RVECENT(romReserved,116)
 190        RVECENT(romReserved,118)
 191        RVECENT(romReserved,119)
 192        RVECENT(romReserved,120)
 193        RVECENT(romReserved,121)
 194        RVECENT(romReserved,122)
 195        RVECENT(romReserved,123)
 196        RVECENT(romReserved,124)
 197        RVECENT(romReserved,125)
 198        RVECENT(romReserved,126)
 199        RVECENT(romReserved,127)
 200
 201        /* We hope there are no more reserved vectors!
 202         * 128 * 8 == 1024 == 0x400
 203         * so this is address R_VEC+0x400 == 0xbfc00400
 204         */
 205#ifdef CONFIG_PURPLE
 206/* 0xbfc00400 */
 207        .word   0xdc870000
 208        .word   0xfca70000
 209        .word   0x20840008
 210        .word   0x20a50008
 211        .word   0x20c6ffff
 212        .word   0x14c0fffa
 213        .word   0x00000000
 214        .word   0x03e00008
 215        .word   0x00000000
 216        .word   0x00000000
 217/* 0xbfc00428 */
 218        .word   0xdc870000
 219        .word   0xfca70000
 220        .word   0x20840008
 221        .word   0x20a50008
 222        .word   0x20c6ffff
 223        .word   0x14c0fffa
 224        .word   0x00000000
 225        .word   0x03e00008
 226        .word   0x00000000
 227        .word   0x00000000
 228#endif /* CONFIG_PURPLE */
 229        .align 4
 230reset:
 231
 232        /* Clear watch registers.
 233         */
 234        mtc0    zero, CP0_WATCHLO
 235        mtc0    zero, CP0_WATCHHI
 236
 237        /* WP(Watch Pending), SW0/1 should be cleared. */
 238        mtc0    zero, CP0_CAUSE
 239
 240        setup_c0_status_reset
 241
 242        /* Init Timer */
 243        mtc0    zero, CP0_COUNT
 244        mtc0    zero, CP0_COMPARE
 245
 246#if !defined(CONFIG_SKIP_LOWLEVEL_INIT)
 247        /* CONFIG0 register */
 248        li      t0, CONF_CM_UNCACHED
 249        mtc0    t0, CP0_CONFIG
 250#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
 251
 252        /* Initialize $gp.
 253         */
 254        bal     1f
 255        nop
 256        .word   _gp
 2571:
 258        lw      gp, 0(ra)
 259
 260#if !defined(CONFIG_SKIP_LOWLEVEL_INIT)
 261        /* Initialize any external memory.
 262         */
 263        la      t9, lowlevel_init
 264        jalr    t9
 265        nop
 266
 267        /* Initialize caches...
 268         */
 269        la      t9, mips_cache_reset
 270        jalr    t9
 271        nop
 272
 273        /* ... and enable them.
 274         */
 275        li      t0, CONF_CM_CACHABLE_NONCOHERENT
 276        mtc0    t0, CP0_CONFIG
 277#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
 278
 279        /* Set up temporary stack.
 280         */
 281#ifdef CONFIG_SYS_INIT_RAM_LOCK_MIPS
 282        li      a0, CONFIG_SYS_INIT_SP_OFFSET
 283        la      t9, mips_cache_lock
 284        jalr    t9
 285        nop
 286#endif
 287
 288        li      t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
 289        la      sp, 0(t0)
 290
 291        la      t9, board_init_f
 292        jr      t9
 293        nop
 294
 295/*
 296 * void relocate_code (addr_sp, gd, addr_moni)
 297 *
 298 * This "function" does not return, instead it continues in RAM
 299 * after relocating the monitor code.
 300 *
 301 * a0 = addr_sp
 302 * a1 = gd
 303 * a2 = destination address
 304 */
 305        .globl  relocate_code
 306        .ent    relocate_code
 307relocate_code:
 308        move    sp, a0          /* Set new stack pointer        */
 309
 310        li      t0, CONFIG_SYS_MONITOR_BASE
 311        la      t3, in_ram
 312        lw      t2, -12(t3)     /* t2 <-- uboot_end_data        */
 313        move    t1, a2
 314        move    s2, a2          /* s2 <-- destination address   */
 315
 316        /*
 317         * Fix $gp:
 318         *
 319         * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address
 320         */
 321        move    t6, gp
 322        sub     gp, CONFIG_SYS_MONITOR_BASE
 323        add     gp, a2          /* gp now adjusted              */
 324        sub     s1, gp, t6      /* s1 <-- relocation offset     */
 325
 326        /*
 327         * t0 = source address
 328         * t1 = target address
 329         * t2 = source end address
 330         */
 331
 332        /*
 333         * Save destination address and size for later usage in flush_cache()
 334         */
 335        move    s0, a1          /* save gd in s0                */
 336        move    a0, t1          /* a0 <-- destination addr      */
 337        sub     a1, t2, t0      /* a1 <-- size                  */
 338
 339        /* On the purple board we copy the code earlier in a special way
 340         * in order to solve flash problems
 341         */
 342#ifndef CONFIG_PURPLE
 3431:
 344        lw      t3, 0(t0)
 345        sw      t3, 0(t1)
 346        addu    t0, 4
 347        ble     t0, t2, 1b
 348        addu    t1, 4           /* delay slot                   */
 349#endif
 350
 351        /* If caches were enabled, we would have to flush them here.
 352         */
 353
 354        /* a0 & a1 are already set up for flush_cache(start, size) */
 355        la      t9, flush_cache
 356        jalr    t9
 357        nop
 358
 359        /* Jump to where we've relocated ourselves.
 360         */
 361        addi    t0, s2, in_ram - _start
 362        jr      t0
 363        nop
 364
 365        .word   _gp
 366        .word   _GLOBAL_OFFSET_TABLE_
 367        .word   uboot_end_data
 368        .word   uboot_end
 369        .word   num_got_entries
 370
 371in_ram:
 372        /*
 373         * Now we want to update GOT.
 374         *
 375         * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
 376         * generated by GNU ld. Skip these reserved entries from relocation.
 377         */
 378        lw      t3, -4(t0)      /* t3 <-- num_got_entries       */
 379        lw      t4, -16(t0)     /* t4 <-- _GLOBAL_OFFSET_TABLE_ */
 380        lw      t5, -20(t0)     /* t5 <-- _gp   */
 381        sub     t4, t5          /* compute offset*/
 382        add     t4, t4, gp      /* t4 now holds relocated _GLOBAL_OFFSET_TABLE_ */
 383        addi    t4, t4, 8       /* Skipping first two entries.  */
 384        li      t2, 2
 3851:
 386        lw      t1, 0(t4)
 387        beqz    t1, 2f
 388        add     t1, s1
 389        sw      t1, 0(t4)
 3902:
 391        addi    t2, 1
 392        blt     t2, t3, 1b
 393        addi    t4, 4           /* delay slot                   */
 394
 395        /* Clear BSS.
 396         */
 397        lw      t1, -12(t0)     /* t1 <-- uboot_end_data        */
 398        lw      t2, -8(t0)      /* t2 <-- uboot_end             */
 399        add     t1, s1          /* adjust pointers              */
 400        add     t2, s1
 401
 402        sub     t1, 4
 4031:
 404        addi    t1, 4
 405        bltl    t1, t2, 1b
 406        sw      zero, 0(t1)     /* delay slot                   */
 407
 408        move    a0, s0          /* a0 <-- gd                    */
 409        la      t9, board_init_r
 410        jr      t9
 411        move    a1, s2          /* delay slot                   */
 412
 413        .end    relocate_code
 414
 415        /* Exception handlers.
 416         */
 417romReserved:
 418        b       romReserved
 419
 420romExcHandle:
 421        b       romExcHandle
 422