uboot/arch/powerpc/cpu/74xx_7xx/start.S
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
   3 *  Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
   4 *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
   5 *  Copyright (C) 2001  Josh Huber <huber@mclx.com>
   6 *
   7 * See file CREDITS for list of people who contributed to this
   8 * project.
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation; either version 2 of
  13 * the License, or (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 * MA 02111-1307 USA
  24 */
  25
  26/*  U-Boot - Startup Code for PowerPC based Embedded Boards
  27 *
  28 *
  29 *  The processor starts at 0xfff00100 and the code is executed
  30 *  from flash. The code is organized to be at an other address
  31 *  in memory, but as long we don't jump around before relocating.
  32 *  board_init lies at a quite high address and when the cpu has
  33 *  jumped there, everything is ok.
  34 */
  35#include <asm-offsets.h>
  36#include <config.h>
  37#include <74xx_7xx.h>
  38#include <version.h>
  39
  40#include <ppc_asm.tmpl>
  41#include <ppc_defs.h>
  42
  43#include <asm/cache.h>
  44#include <asm/mmu.h>
  45#include <asm/u-boot.h>
  46
  47#if !defined(CONFIG_DB64360) && \
  48    !defined(CONFIG_DB64460) && \
  49    !defined(CONFIG_CPCI750) && \
  50    !defined(CONFIG_P3Mx)
  51#include <galileo/gt64260R.h>
  52#endif
  53
  54/* We don't want the  MMU yet.
  55*/
  56#undef  MSR_KERNEL
  57/* Machine Check and Recoverable Interr. */
  58#define MSR_KERNEL ( MSR_ME | MSR_RI )
  59
  60/*
  61 * Set up GOT: Global Offset Table
  62 *
  63 * Use r12 to access the GOT
  64 */
  65        START_GOT
  66        GOT_ENTRY(_GOT2_TABLE_)
  67        GOT_ENTRY(_FIXUP_TABLE_)
  68
  69        GOT_ENTRY(_start)
  70        GOT_ENTRY(_start_of_vectors)
  71        GOT_ENTRY(_end_of_vectors)
  72        GOT_ENTRY(transfer_to_handler)
  73
  74        GOT_ENTRY(__init_end)
  75        GOT_ENTRY(__bss_end__)
  76        GOT_ENTRY(__bss_start)
  77        END_GOT
  78
  79/*
  80 * r3 - 1st arg to board_init(): IMMP pointer
  81 * r4 - 2nd arg to board_init(): boot flag
  82 */
  83        .text
  84        .long   0x27051956              /* U-Boot Magic Number          */
  85        .globl  version_string
  86version_string:
  87        .ascii U_BOOT_VERSION_STRING, "\0"
  88
  89        . = EXC_OFF_SYS_RESET
  90        .globl  _start
  91_start:
  92        b       boot_cold
  93
  94        /* the boot code is located below the exception table */
  95
  96        .globl  _start_of_vectors
  97_start_of_vectors:
  98
  99/* Machine check */
 100        STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
 101
 102/* Data Storage exception.  "Never" generated on the 860. */
 103        STD_EXCEPTION(0x300, DataStorage, UnknownException)
 104
 105/* Instruction Storage exception.  "Never" generated on the 860. */
 106        STD_EXCEPTION(0x400, InstStorage, UnknownException)
 107
 108/* External Interrupt exception. */
 109        STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
 110
 111/* Alignment exception. */
 112        . = 0x600
 113Alignment:
 114        EXCEPTION_PROLOG(SRR0, SRR1)
 115        mfspr   r4,DAR
 116        stw     r4,_DAR(r21)
 117        mfspr   r5,DSISR
 118        stw     r5,_DSISR(r21)
 119        addi    r3,r1,STACK_FRAME_OVERHEAD
 120        EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
 121
 122/* Program check exception */
 123        . = 0x700
 124ProgramCheck:
 125        EXCEPTION_PROLOG(SRR0, SRR1)
 126        addi    r3,r1,STACK_FRAME_OVERHEAD
 127        EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
 128                MSR_KERNEL, COPY_EE)
 129
 130        /* No FPU on MPC8xx.  This exception is not supposed to happen.
 131        */
 132        STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
 133
 134        /* I guess we could implement decrementer, and may have
 135         * to someday for timekeeping.
 136         */
 137        STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
 138        STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
 139        STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
 140        STD_EXCEPTION(0xc00, SystemCall, UnknownException)
 141        STD_EXCEPTION(0xd00, SingleStep, UnknownException)
 142
 143        STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
 144        STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
 145
 146        /*
 147         * On the MPC8xx, this is a software emulation interrupt. It
 148         * occurs for all unimplemented and illegal instructions.
 149         */
 150        STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
 151
 152        STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
 153        STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
 154        STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
 155        STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
 156
 157        STD_EXCEPTION(0x1500, Reserved5, UnknownException)
 158        STD_EXCEPTION(0x1600, Reserved6, UnknownException)
 159        STD_EXCEPTION(0x1700, Reserved7, UnknownException)
 160        STD_EXCEPTION(0x1800, Reserved8, UnknownException)
 161        STD_EXCEPTION(0x1900, Reserved9, UnknownException)
 162        STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
 163        STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
 164
 165        STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
 166        STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
 167        STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
 168        STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
 169
 170        .globl  _end_of_vectors
 171_end_of_vectors:
 172
 173        . = 0x2000
 174
 175boot_cold:
 176        /* disable everything */
 177        li      r0, 0
 178        mtspr   HID0, r0
 179        sync
 180        mtmsr   0
 181        bl      invalidate_bats
 182        sync
 183
 184#ifdef CONFIG_SYS_L2
 185        /* init the L2 cache */
 186        addis   r3, r0, L2_INIT@h
 187        ori     r3, r3, L2_INIT@l
 188        sync
 189        mtspr   l2cr, r3
 190#endif
 191#if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
 192        .long   0x7e00066c
 193                /*
 194                 * dssall instruction, gas doesn't have it yet
 195                 * ...for altivec, data stream stop all this probably
 196                 * isn't needed unless we warm (software) reboot U-Boot
 197                 */
 198#endif
 199
 200#ifdef CONFIG_SYS_L2
 201        /* invalidate the L2 cache */
 202        bl      l2cache_invalidate
 203        sync
 204#endif
 205#ifdef CONFIG_SYS_BOARD_ASM_INIT
 206        /* do early init */
 207        bl      board_asm_init
 208#endif
 209
 210        /*
 211         * Calculate absolute address in FLASH and jump there
 212         *------------------------------------------------------*/
 213        lis     r3, CONFIG_SYS_MONITOR_BASE@h
 214        ori     r3, r3, CONFIG_SYS_MONITOR_BASE@l
 215        addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
 216        mtlr    r3
 217        blr
 218
 219in_flash:
 220        /* let the C-code set up the rest                       */
 221        /*                                                      */
 222        /* Be careful to keep code relocatable !                */
 223        /*------------------------------------------------------*/
 224
 225        /* perform low-level init */
 226        /* sdram init, galileo init, etc */
 227        /* r3:  NHR bit from HID0 */
 228
 229        /* setup the bats */
 230        bl      setup_bats
 231        sync
 232
 233        /*
 234         * Cache must be enabled here for stack-in-cache trick.
 235         * This means we need to enable the BATS.
 236         * This means:
 237         *   1) for the EVB, original gt regs need to be mapped
 238         *   2) need to have an IBAT for the 0xf region,
 239         *      we are running there!
 240         * Cache should be turned on after BATs, since by default
 241         * everything is write-through.
 242         * The init-mem BAT can be reused after reloc. The old
 243         * gt-regs BAT can be reused after board_init_f calls
 244         * board_early_init_f (EVB only).
 245         */
 246#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC) && !defined(CONFIG_P3Mx)
 247        /* enable address translation */
 248        bl      enable_addr_trans
 249        sync
 250
 251        /* enable and invalidate the data cache */
 252        bl      l1dcache_enable
 253        sync
 254#endif
 255#ifdef CONFIG_SYS_INIT_RAM_LOCK
 256        bl      lock_ram_in_cache
 257        sync
 258#endif
 259
 260        /* set up the stack pointer in our newly created
 261         * cache-ram (r1) */
 262        lis     r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
 263        ori     r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
 264
 265        li      r0, 0           /* Make room for stack frame header and */
 266        stwu    r0, -4(r1)      /* clear final stack frame so that      */
 267        stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
 268
 269        GET_GOT                 /* initialize GOT access        */
 270
 271        /* run low-level CPU init code     (from Flash) */
 272        bl      cpu_init_f
 273        sync
 274
 275        /* run 1st part of board init code (from Flash)   */
 276        bl      board_init_f
 277        sync
 278
 279        /* NOTREACHED - board_init_f() does not return */
 280
 281        .globl  invalidate_bats
 282invalidate_bats:
 283        /* invalidate BATs */
 284        mtspr   IBAT0U, r0
 285        mtspr   IBAT1U, r0
 286        mtspr   IBAT2U, r0
 287        mtspr   IBAT3U, r0
 288#ifdef CONFIG_HIGH_BATS
 289        mtspr   IBAT4U, r0
 290        mtspr   IBAT5U, r0
 291        mtspr   IBAT6U, r0
 292        mtspr   IBAT7U, r0
 293#endif
 294        isync
 295        mtspr   DBAT0U, r0
 296        mtspr   DBAT1U, r0
 297        mtspr   DBAT2U, r0
 298        mtspr   DBAT3U, r0
 299#ifdef CONFIG_HIGH_BATS
 300        mtspr   DBAT4U, r0
 301        mtspr   DBAT5U, r0
 302        mtspr   DBAT6U, r0
 303        mtspr   DBAT7U, r0
 304#endif
 305        isync
 306        sync
 307        blr
 308
 309        /* setup_bats - set them up to some initial state */
 310        .globl  setup_bats
 311setup_bats:
 312        addis   r0, r0, 0x0000
 313
 314        /* IBAT 0 */
 315        addis   r4, r0, CONFIG_SYS_IBAT0L@h
 316        ori     r4, r4, CONFIG_SYS_IBAT0L@l
 317        addis   r3, r0, CONFIG_SYS_IBAT0U@h
 318        ori     r3, r3, CONFIG_SYS_IBAT0U@l
 319        mtspr   IBAT0L, r4
 320        mtspr   IBAT0U, r3
 321        isync
 322
 323        /* DBAT 0 */
 324        addis   r4, r0, CONFIG_SYS_DBAT0L@h
 325        ori     r4, r4, CONFIG_SYS_DBAT0L@l
 326        addis   r3, r0, CONFIG_SYS_DBAT0U@h
 327        ori     r3, r3, CONFIG_SYS_DBAT0U@l
 328        mtspr   DBAT0L, r4
 329        mtspr   DBAT0U, r3
 330        isync
 331
 332        /* IBAT 1 */
 333        addis   r4, r0, CONFIG_SYS_IBAT1L@h
 334        ori     r4, r4, CONFIG_SYS_IBAT1L@l
 335        addis   r3, r0, CONFIG_SYS_IBAT1U@h
 336        ori     r3, r3, CONFIG_SYS_IBAT1U@l
 337        mtspr   IBAT1L, r4
 338        mtspr   IBAT1U, r3
 339        isync
 340
 341        /* DBAT 1 */
 342        addis   r4, r0, CONFIG_SYS_DBAT1L@h
 343        ori     r4, r4, CONFIG_SYS_DBAT1L@l
 344        addis   r3, r0, CONFIG_SYS_DBAT1U@h
 345        ori     r3, r3, CONFIG_SYS_DBAT1U@l
 346        mtspr   DBAT1L, r4
 347        mtspr   DBAT1U, r3
 348        isync
 349
 350        /* IBAT 2 */
 351        addis   r4, r0, CONFIG_SYS_IBAT2L@h
 352        ori     r4, r4, CONFIG_SYS_IBAT2L@l
 353        addis   r3, r0, CONFIG_SYS_IBAT2U@h
 354        ori     r3, r3, CONFIG_SYS_IBAT2U@l
 355        mtspr   IBAT2L, r4
 356        mtspr   IBAT2U, r3
 357        isync
 358
 359        /* DBAT 2 */
 360        addis   r4, r0, CONFIG_SYS_DBAT2L@h
 361        ori     r4, r4, CONFIG_SYS_DBAT2L@l
 362        addis   r3, r0, CONFIG_SYS_DBAT2U@h
 363        ori     r3, r3, CONFIG_SYS_DBAT2U@l
 364        mtspr   DBAT2L, r4
 365        mtspr   DBAT2U, r3
 366        isync
 367
 368        /* IBAT 3 */
 369        addis   r4, r0, CONFIG_SYS_IBAT3L@h
 370        ori     r4, r4, CONFIG_SYS_IBAT3L@l
 371        addis   r3, r0, CONFIG_SYS_IBAT3U@h
 372        ori     r3, r3, CONFIG_SYS_IBAT3U@l
 373        mtspr   IBAT3L, r4
 374        mtspr   IBAT3U, r3
 375        isync
 376
 377        /* DBAT 3 */
 378        addis   r4, r0, CONFIG_SYS_DBAT3L@h
 379        ori     r4, r4, CONFIG_SYS_DBAT3L@l
 380        addis   r3, r0, CONFIG_SYS_DBAT3U@h
 381        ori     r3, r3, CONFIG_SYS_DBAT3U@l
 382        mtspr   DBAT3L, r4
 383        mtspr   DBAT3U, r3
 384        isync
 385
 386#ifdef CONFIG_HIGH_BATS
 387        /* IBAT 4 */
 388        addis   r4, r0, CONFIG_SYS_IBAT4L@h
 389        ori     r4, r4, CONFIG_SYS_IBAT4L@l
 390        addis   r3, r0, CONFIG_SYS_IBAT4U@h
 391        ori     r3, r3, CONFIG_SYS_IBAT4U@l
 392        mtspr   IBAT4L, r4
 393        mtspr   IBAT4U, r3
 394        isync
 395
 396        /* DBAT 4 */
 397        addis   r4, r0, CONFIG_SYS_DBAT4L@h
 398        ori     r4, r4, CONFIG_SYS_DBAT4L@l
 399        addis   r3, r0, CONFIG_SYS_DBAT4U@h
 400        ori     r3, r3, CONFIG_SYS_DBAT4U@l
 401        mtspr   DBAT4L, r4
 402        mtspr   DBAT4U, r3
 403        isync
 404
 405        /* IBAT 5 */
 406        addis   r4, r0, CONFIG_SYS_IBAT5L@h
 407        ori     r4, r4, CONFIG_SYS_IBAT5L@l
 408        addis   r3, r0, CONFIG_SYS_IBAT5U@h
 409        ori     r3, r3, CONFIG_SYS_IBAT5U@l
 410        mtspr   IBAT5L, r4
 411        mtspr   IBAT5U, r3
 412        isync
 413
 414        /* DBAT 5 */
 415        addis   r4, r0, CONFIG_SYS_DBAT5L@h
 416        ori     r4, r4, CONFIG_SYS_DBAT5L@l
 417        addis   r3, r0, CONFIG_SYS_DBAT5U@h
 418        ori     r3, r3, CONFIG_SYS_DBAT5U@l
 419        mtspr   DBAT5L, r4
 420        mtspr   DBAT5U, r3
 421        isync
 422
 423        /* IBAT 6 */
 424        addis   r4, r0, CONFIG_SYS_IBAT6L@h
 425        ori     r4, r4, CONFIG_SYS_IBAT6L@l
 426        addis   r3, r0, CONFIG_SYS_IBAT6U@h
 427        ori     r3, r3, CONFIG_SYS_IBAT6U@l
 428        mtspr   IBAT6L, r4
 429        mtspr   IBAT6U, r3
 430        isync
 431
 432        /* DBAT 6 */
 433        addis   r4, r0, CONFIG_SYS_DBAT6L@h
 434        ori     r4, r4, CONFIG_SYS_DBAT6L@l
 435        addis   r3, r0, CONFIG_SYS_DBAT6U@h
 436        ori     r3, r3, CONFIG_SYS_DBAT6U@l
 437        mtspr   DBAT6L, r4
 438        mtspr   DBAT6U, r3
 439        isync
 440
 441        /* IBAT 7 */
 442        addis   r4, r0, CONFIG_SYS_IBAT7L@h
 443        ori     r4, r4, CONFIG_SYS_IBAT7L@l
 444        addis   r3, r0, CONFIG_SYS_IBAT7U@h
 445        ori     r3, r3, CONFIG_SYS_IBAT7U@l
 446        mtspr   IBAT7L, r4
 447        mtspr   IBAT7U, r3
 448        isync
 449
 450        /* DBAT 7 */
 451        addis   r4, r0, CONFIG_SYS_DBAT7L@h
 452        ori     r4, r4, CONFIG_SYS_DBAT7L@l
 453        addis   r3, r0, CONFIG_SYS_DBAT7U@h
 454        ori     r3, r3, CONFIG_SYS_DBAT7U@l
 455        mtspr   DBAT7L, r4
 456        mtspr   DBAT7U, r3
 457        isync
 458#endif
 459
 460        /* bats are done, now invalidate the TLBs */
 461
 462        addis   r3, 0, 0x0000
 463        addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
 464
 465        isync
 466
 467tlblp:
 468        tlbie   r3
 469        sync
 470        addi    r3, r3, 0x1000
 471        cmp     0, 0, r3, r5
 472        blt tlblp
 473
 474        blr
 475
 476        .globl enable_addr_trans
 477enable_addr_trans:
 478        /* enable address translation */
 479        mfmsr   r5
 480        ori     r5, r5, (MSR_IR | MSR_DR)
 481        mtmsr   r5
 482        isync
 483        blr
 484
 485        .globl disable_addr_trans
 486disable_addr_trans:
 487        /* disable address translation */
 488        mflr    r4
 489        mfmsr   r3
 490        andi.   r0, r3, (MSR_IR | MSR_DR)
 491        beqlr
 492        andc    r3, r3, r0
 493        mtspr   SRR0, r4
 494        mtspr   SRR1, r3
 495        rfi
 496
 497/*
 498 * This code finishes saving the registers to the exception frame
 499 * and jumps to the appropriate handler for the exception.
 500 * Register r21 is pointer into trap frame, r1 has new stack pointer.
 501 */
 502        .globl  transfer_to_handler
 503transfer_to_handler:
 504        stw     r22,_NIP(r21)
 505        lis     r22,MSR_POW@h
 506        andc    r23,r23,r22
 507        stw     r23,_MSR(r21)
 508        SAVE_GPR(7, r21)
 509        SAVE_4GPRS(8, r21)
 510        SAVE_8GPRS(12, r21)
 511        SAVE_8GPRS(24, r21)
 512        mflr    r23
 513        andi.   r24,r23,0x3f00          /* get vector offset */
 514        stw     r24,TRAP(r21)
 515        li      r22,0
 516        stw     r22,RESULT(r21)
 517        mtspr   SPRG2,r22               /* r1 is now kernel sp */
 518        lwz     r24,0(r23)              /* virtual address of handler */
 519        lwz     r23,4(r23)              /* where to go when done */
 520        mtspr   SRR0,r24
 521        mtspr   SRR1,r20
 522        mtlr    r23
 523        SYNC
 524        rfi                             /* jump to handler, enable MMU */
 525
 526int_return:
 527        mfmsr   r28             /* Disable interrupts */
 528        li      r4,0
 529        ori     r4,r4,MSR_EE
 530        andc    r28,r28,r4
 531        SYNC                    /* Some chip revs need this... */
 532        mtmsr   r28
 533        SYNC
 534        lwz     r2,_CTR(r1)
 535        lwz     r0,_LINK(r1)
 536        mtctr   r2
 537        mtlr    r0
 538        lwz     r2,_XER(r1)
 539        lwz     r0,_CCR(r1)
 540        mtspr   XER,r2
 541        mtcrf   0xFF,r0
 542        REST_10GPRS(3, r1)
 543        REST_10GPRS(13, r1)
 544        REST_8GPRS(23, r1)
 545        REST_GPR(31, r1)
 546        lwz     r2,_NIP(r1)     /* Restore environment */
 547        lwz     r0,_MSR(r1)
 548        mtspr   SRR0,r2
 549        mtspr   SRR1,r0
 550        lwz     r0,GPR0(r1)
 551        lwz     r2,GPR2(r1)
 552        lwz     r1,GPR1(r1)
 553        SYNC
 554        rfi
 555
 556        .globl  dc_read
 557dc_read:
 558        blr
 559
 560        .globl get_pvr
 561get_pvr:
 562        mfspr   r3, PVR
 563        blr
 564
 565/*-----------------------------------------------------------------------*/
 566/*
 567 * void relocate_code (addr_sp, gd, addr_moni)
 568 *
 569 * This "function" does not return, instead it continues in RAM
 570 * after relocating the monitor code.
 571 *
 572 * r3 = dest
 573 * r4 = src
 574 * r5 = length in bytes
 575 * r6 = cachelinesize
 576 */
 577        .globl  relocate_code
 578relocate_code:
 579        mr      r1,  r3         /* Set new stack pointer                */
 580        mr      r9,  r4         /* Save copy of Global Data pointer     */
 581        mr      r10, r5         /* Save copy of Destination Address     */
 582
 583        GET_GOT
 584        mr      r3,  r5                         /* Destination Address  */
 585        lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
 586        ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
 587        lwz     r5, GOT(__init_end)
 588        sub     r5, r5, r4
 589        li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
 590
 591        /*
 592         * Fix GOT pointer:
 593         *
 594         * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
 595         *
 596         * Offset:
 597         */
 598        sub     r15, r10, r4
 599
 600        /* First our own GOT */
 601        add     r12, r12, r15
 602        /* then the one used by the C code */
 603        add     r30, r30, r15
 604
 605        /*
 606         * Now relocate code
 607         */
 608#ifdef CONFIG_ECC
 609        bl      board_relocate_rom
 610        sync
 611        mr      r3, r10                         /* Destination Address  */
 612        lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
 613        ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
 614        lwz     r5, GOT(__init_end)
 615        sub     r5, r5, r4
 616        li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
 617#else
 618        cmplw   cr1,r3,r4
 619        addi    r0,r5,3
 620        srwi.   r0,r0,2
 621        beq     cr1,4f          /* In place copy is not necessary       */
 622        beq     7f              /* Protect against 0 count              */
 623        mtctr   r0
 624        bge     cr1,2f
 625
 626        la      r8,-4(r4)
 627        la      r7,-4(r3)
 6281:      lwzu    r0,4(r8)
 629        stwu    r0,4(r7)
 630        bdnz    1b
 631        b       4f
 632
 6332:      slwi    r0,r0,2
 634        add     r8,r4,r0
 635        add     r7,r3,r0
 6363:      lwzu    r0,-4(r8)
 637        stwu    r0,-4(r7)
 638        bdnz    3b
 639#endif
 640/*
 641 * Now flush the cache: note that we must start from a cache aligned
 642 * address. Otherwise we might miss one cache line.
 643 */
 6444:      cmpwi   r6,0
 645        add     r5,r3,r5
 646        beq     7f              /* Always flush prefetch queue in any case */
 647        subi    r0,r6,1
 648        andc    r3,r3,r0
 649        mr      r4,r3
 6505:      dcbst   0,r4
 651        add     r4,r4,r6
 652        cmplw   r4,r5
 653        blt     5b
 654        sync                    /* Wait for all dcbst to complete on bus */
 655        mr      r4,r3
 6566:      icbi    0,r4
 657        add     r4,r4,r6
 658        cmplw   r4,r5
 659        blt     6b
 6607:      sync                    /* Wait for all icbi to complete on bus */
 661        isync
 662
 663/*
 664 * We are done. Do not return, instead branch to second part of board
 665 * initialization, now running from RAM.
 666 */
 667        addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
 668        mtlr    r0
 669        blr
 670
 671in_ram:
 672#ifdef CONFIG_ECC
 673        bl      board_init_ecc
 674#endif
 675        /*
 676         * Relocation Function, r12 point to got2+0x8000
 677         *
 678         * Adjust got2 pointers, no need to check for 0, this code
 679         * already puts a few entries in the table.
 680         */
 681        li      r0,__got2_entries@sectoff@l
 682        la      r3,GOT(_GOT2_TABLE_)
 683        lwz     r11,GOT(_GOT2_TABLE_)
 684        mtctr   r0
 685        sub     r11,r3,r11
 686        addi    r3,r3,-4
 6871:      lwzu    r0,4(r3)
 688        cmpwi   r0,0
 689        beq-    2f
 690        add     r0,r0,r11
 691        stw     r0,0(r3)
 6922:      bdnz    1b
 693
 694        /*
 695         * Now adjust the fixups and the pointers to the fixups
 696         * in case we need to move ourselves again.
 697         */
 698        li      r0,__fixup_entries@sectoff@l
 699        lwz     r3,GOT(_FIXUP_TABLE_)
 700        cmpwi   r0,0
 701        mtctr   r0
 702        addi    r3,r3,-4
 703        beq     4f
 7043:      lwzu    r4,4(r3)
 705        lwzux   r0,r4,r11
 706        cmpwi   r0,0
 707        add     r0,r0,r11
 708        stw     r4,0(r3)
 709        beq-    5f
 710        stw     r0,0(r4)
 7115:      bdnz    3b
 7124:
 713/* clear_bss: */
 714        /*
 715         * Now clear BSS segment
 716         */
 717        lwz     r3,GOT(__bss_start)
 718        lwz     r4,GOT(__bss_end__)
 719
 720        cmplw   0, r3, r4
 721        beq     6f
 722
 723        li      r0, 0
 7245:
 725        stw     r0, 0(r3)
 726        addi    r3, r3, 4
 727        cmplw   0, r3, r4
 728        bne     5b
 7296:
 730        mr      r3, r10         /* Destination Address          */
 731#if defined(CONFIG_DB64360)     || \
 732    defined(CONFIG_DB64460)     || \
 733    defined(CONFIG_CPCI750)     || \
 734    defined(CONFIG_PPMC7XX)     || \
 735    defined(CONFIG_P3Mx)
 736        mr      r4, r9          /* Use RAM copy of the global data */
 737#endif
 738        bl      after_reloc
 739
 740        /* not reached - end relocate_code */
 741/*-----------------------------------------------------------------------*/
 742
 743        /*
 744         * Copy exception vector code to low memory
 745         *
 746         * r3: dest_addr
 747         * r7: source address, r8: end address, r9: target address
 748         */
 749        .globl  trap_init
 750trap_init:
 751        mflr    r4                      /* save link register           */
 752        GET_GOT
 753        lwz     r7, GOT(_start)
 754        lwz     r8, GOT(_end_of_vectors)
 755
 756        li      r9, 0x100               /* reset vector always at 0x100 */
 757
 758        cmplw   0, r7, r8
 759        bgelr                           /* return if r7>=r8 - just in case */
 7601:
 761        lwz     r0, 0(r7)
 762        stw     r0, 0(r9)
 763        addi    r7, r7, 4
 764        addi    r9, r9, 4
 765        cmplw   0, r7, r8
 766        bne     1b
 767
 768        /*
 769         * relocate `hdlr' and `int_return' entries
 770         */
 771        li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
 772        li      r8, Alignment - _start + EXC_OFF_SYS_RESET
 7732:
 774        bl      trap_reloc
 775        addi    r7, r7, 0x100           /* next exception vector        */
 776        cmplw   0, r7, r8
 777        blt     2b
 778
 779        li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
 780        bl      trap_reloc
 781
 782        li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
 783        bl      trap_reloc
 784
 785        li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
 786        li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
 7873:
 788        bl      trap_reloc
 789        addi    r7, r7, 0x100           /* next exception vector        */
 790        cmplw   0, r7, r8
 791        blt     3b
 792
 793        li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
 794        li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
 7954:
 796        bl      trap_reloc
 797        addi    r7, r7, 0x100           /* next exception vector        */
 798        cmplw   0, r7, r8
 799        blt     4b
 800
 801        /* enable execptions from RAM vectors */
 802        mfmsr   r7
 803        li      r8,MSR_IP
 804        andc    r7,r7,r8
 805        mtmsr   r7
 806
 807        mtlr    r4                      /* restore link register        */
 808        blr
 809
 810#ifdef CONFIG_SYS_INIT_RAM_LOCK
 811lock_ram_in_cache:
 812        /* Allocate Initial RAM in data cache.
 813         */
 814        lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
 815        ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
 816        li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
 817                     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
 818        mtctr   r4
 8191:
 820        dcbz    r0, r3
 821        addi    r3, r3, 32
 822        bdnz    1b
 823
 824        /* Lock the data cache */
 825        mfspr   r0, HID0
 826        ori     r0, r0, 0x1000
 827        sync
 828        mtspr   HID0, r0
 829        sync
 830        blr
 831
 832.globl unlock_ram_in_cache
 833unlock_ram_in_cache:
 834        /* invalidate the INIT_RAM section */
 835        lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
 836        ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
 837        li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
 838                     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
 839        mtctr   r4
 8401:      icbi    r0, r3
 841        addi    r3, r3, 32
 842        bdnz    1b
 843        sync                    /* Wait for all icbi to complete on bus */
 844        isync
 845
 846        /* Unlock the data cache and invalidate it */
 847        mfspr   r0, HID0
 848        li      r3,0x1000
 849        andc    r0,r0,r3
 850        li      r3,0x0400
 851        or      r0,r0,r3
 852        sync
 853        mtspr   HID0, r0
 854        sync
 855        blr
 856#endif
 857