uboot/arch/powerpc/cpu/mpc5xxx/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 - 2003 Wolfgang Denk <wd@denx.de>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9/*
  10 *  U-Boot - Startup Code for MPC5xxx CPUs
  11 */
  12#include <asm-offsets.h>
  13#include <config.h>
  14#include <mpc5xxx.h>
  15#include <version.h>
  16
  17#include <ppc_asm.tmpl>
  18#include <ppc_defs.h>
  19
  20#include <asm/cache.h>
  21#include <asm/mmu.h>
  22#include <asm/u-boot.h>
  23
  24/* We don't want the  MMU yet.
  25*/
  26#undef  MSR_KERNEL
  27/* Floating Point enable, Machine Check and Recoverable Interr. */
  28#ifdef DEBUG
  29#define MSR_KERNEL (MSR_FP|MSR_RI)
  30#else
  31#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
  32#endif
  33
  34#ifndef CONFIG_SPL_BUILD
  35/*
  36 * Set up GOT: Global Offset Table
  37 *
  38 * Use r12 to access the GOT
  39 */
  40        START_GOT
  41        GOT_ENTRY(_GOT2_TABLE_)
  42        GOT_ENTRY(_FIXUP_TABLE_)
  43
  44        GOT_ENTRY(_start)
  45        GOT_ENTRY(_start_of_vectors)
  46        GOT_ENTRY(_end_of_vectors)
  47        GOT_ENTRY(transfer_to_handler)
  48
  49        GOT_ENTRY(__init_end)
  50        GOT_ENTRY(__bss_end)
  51        GOT_ENTRY(__bss_start)
  52        END_GOT
  53#endif
  54
  55/*
  56 * Version string
  57 */
  58        .data
  59        .globl  version_string
  60version_string:
  61        .ascii U_BOOT_VERSION_STRING, "\0"
  62
  63/*
  64 * Exception vectors
  65 */
  66        .text
  67        . = EXC_OFF_SYS_RESET
  68        .globl  _start
  69_start:
  70
  71#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
  72        /*
  73         * This is the entry of the real U-Boot from a board port
  74         * that supports SPL booting on the MPC5200. We only need
  75         * to call board_init_f() here. Everything else has already
  76         * been done in the SPL u-boot version.
  77         */
  78        GET_GOT                 /* initialize GOT access                */
  79
  80        /*
  81         * The GD (global data) struct needs to get cleared. Lets do
  82         * this by calling memset().
  83         * This function is called when the platform is build with SPL
  84         * support from the main (full-blown) U-Boot. And the GD needs
  85         * to get cleared (again) so that the following generic
  86         * board support code initializes all variables correctly.
  87         */
  88        mr      r3, r2          /* parameter 1:  GD pointer             */
  89        li      r4,0            /* parameter 2:  value to fill          */
  90        li      r5,GD_SIZE      /* parameter 3:  count                  */
  91        bl      memset
  92
  93        li      r3, 0           /* parameter 1:  bootflag               */
  94        bl      board_init_f    /* run 1st part of board init code (in Flash)*/
  95        /* NOTREACHED - board_init_f() does not return */
  96#else
  97        mfmsr   r5                      /* save msr contents            */
  98
  99        /* Move CSBoot and adjust instruction pointer                   */
 100        /*--------------------------------------------------------------*/
 101
 102#if defined(CONFIG_SYS_LOWBOOT)
 103# if defined(CONFIG_SYS_RAMBOOT)
 104#  error CONFIG_SYS_LOWBOOT is incompatible with CONFIG_SYS_RAMBOOT
 105# endif /* CONFIG_SYS_RAMBOOT */
 106        lis     r4, CONFIG_SYS_DEFAULT_MBAR@h
 107        lis     r3,     START_REG(CONFIG_SYS_BOOTCS_START)@h
 108        ori     r3, r3, START_REG(CONFIG_SYS_BOOTCS_START)@l
 109        stw     r3, 0x4(r4)             /* CS0 start */
 110        lis     r3,     STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@h
 111        ori     r3, r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@l
 112        stw     r3, 0x8(r4)             /* CS0 stop */
 113        lis     r3,     0x02010000@h
 114        ori     r3, r3, 0x02010000@l
 115        stw     r3, 0x54(r4)            /* CS0 and Boot enable */
 116
 117        lis     r3,     lowboot_reentry@h       /* jump from bootlow address space (0x0000xxxx) */
 118        ori     r3, r3, lowboot_reentry@l       /* to the address space the linker used */
 119        mtlr    r3
 120        blr
 121
 122lowboot_reentry:
 123        lis     r3,     START_REG(CONFIG_SYS_BOOTCS_START)@h
 124        ori     r3, r3, START_REG(CONFIG_SYS_BOOTCS_START)@l
 125        stw     r3, 0x4c(r4)            /* Boot start */
 126        lis     r3,     STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@h
 127        ori     r3, r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@l
 128        stw     r3, 0x50(r4)            /* Boot stop */
 129        lis     r3,     0x02000001@h
 130        ori     r3, r3, 0x02000001@l
 131        stw     r3, 0x54(r4)            /* Boot enable, CS0 disable */
 132#endif  /* CONFIG_SYS_LOWBOOT */
 133
 134#if defined(CONFIG_SYS_DEFAULT_MBAR) && !defined(CONFIG_SYS_RAMBOOT)
 135        lis     r3, CONFIG_SYS_MBAR@h
 136        ori     r3, r3, CONFIG_SYS_MBAR@l
 137        /* MBAR is mirrored into the MBAR SPR */
 138        mtspr   MBAR,r3
 139        rlwinm  r3, r3, 16, 16, 31
 140        lis     r4, CONFIG_SYS_DEFAULT_MBAR@h
 141        stw     r3, 0(r4)
 142#endif /* CONFIG_SYS_DEFAULT_MBAR */
 143
 144        /* Initialise the MPC5xxx processor core                        */
 145        /*--------------------------------------------------------------*/
 146
 147        bl      init_5xxx_core
 148
 149        /* initialize some things that are hard to access from C        */
 150        /*--------------------------------------------------------------*/
 151
 152        /* set up stack in on-chip SRAM */
 153        lis     r3, CONFIG_SYS_INIT_RAM_ADDR@h
 154        ori     r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
 155        ori     r1, r3, CONFIG_SYS_INIT_SP_OFFSET
 156        li      r0, 0                   /* Make room for stack frame header and */
 157        stwu    r0, -4(r1)              /* clear final stack frame so that      */
 158        stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
 159
 160        /* let the C-code set up the rest                               */
 161        /*                                                              */
 162        /* Be careful to keep code relocatable !                        */
 163        /*--------------------------------------------------------------*/
 164
 165#ifndef CONFIG_SPL_BUILD
 166        GET_GOT                 /* initialize GOT access                */
 167#endif
 168
 169        /* r3: IMMR */
 170        bl      cpu_init_f      /* run low-level CPU init code (in Flash)*/
 171
 172        li      r3, 0           /* parameter 1:  bootflag               */
 173        bl      board_init_f    /* run 1st part of board init code (in Flash)*/
 174
 175        /* NOTREACHED - board_init_f() does not return */
 176#endif
 177
 178#ifndef CONFIG_SPL_BUILD
 179/*
 180 * Vector Table
 181 */
 182
 183        .globl  _start_of_vectors
 184_start_of_vectors:
 185
 186/* Machine check */
 187        STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
 188
 189/* Data Storage exception. */
 190        STD_EXCEPTION(0x300, DataStorage, UnknownException)
 191
 192/* Instruction Storage exception. */
 193        STD_EXCEPTION(0x400, InstStorage, UnknownException)
 194
 195/* External Interrupt exception. */
 196        STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
 197
 198/* Alignment exception. */
 199        . = 0x600
 200Alignment:
 201        EXCEPTION_PROLOG(SRR0, SRR1)
 202        mfspr   r4,DAR
 203        stw     r4,_DAR(r21)
 204        mfspr   r5,DSISR
 205        stw     r5,_DSISR(r21)
 206        addi    r3,r1,STACK_FRAME_OVERHEAD
 207        EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
 208
 209/* Program check exception */
 210        . = 0x700
 211ProgramCheck:
 212        EXCEPTION_PROLOG(SRR0, SRR1)
 213        addi    r3,r1,STACK_FRAME_OVERHEAD
 214        EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
 215                MSR_KERNEL, COPY_EE)
 216
 217        STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
 218
 219        /* I guess we could implement decrementer, and may have
 220         * to someday for timekeeping.
 221         */
 222        STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
 223
 224        STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
 225        STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
 226        STD_EXCEPTION(0xc00, SystemCall, UnknownException)
 227        STD_EXCEPTION(0xd00, SingleStep, UnknownException)
 228
 229        STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
 230        STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
 231
 232        STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
 233        STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
 234        STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
 235#ifdef DEBUG
 236        . = 0x1300
 237        /*
 238         * This exception occurs when the program counter matches the
 239         * Instruction Address Breakpoint Register (IABR).
 240         *
 241         * I want the cpu to halt if this occurs so I can hunt around
 242         * with the debugger and look at things.
 243         *
 244         * When DEBUG is defined, both machine check enable (in the MSR)
 245         * and checkstop reset enable (in the reset mode register) are
 246         * turned off and so a checkstop condition will result in the cpu
 247         * halting.
 248         *
 249         * I force the cpu into a checkstop condition by putting an illegal
 250         * instruction here (at least this is the theory).
 251         *
 252         * well - that didnt work, so just do an infinite loop!
 253         */
 2541:      b       1b
 255#else
 256        STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
 257#endif
 258        STD_EXCEPTION(0x1400, SMI, UnknownException)
 259
 260        STD_EXCEPTION(0x1500, Trap_15, UnknownException)
 261        STD_EXCEPTION(0x1600, Trap_16, UnknownException)
 262        STD_EXCEPTION(0x1700, Trap_17, UnknownException)
 263        STD_EXCEPTION(0x1800, Trap_18, UnknownException)
 264        STD_EXCEPTION(0x1900, Trap_19, UnknownException)
 265        STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
 266        STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
 267        STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
 268        STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
 269        STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
 270        STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
 271        STD_EXCEPTION(0x2000, Trap_20, UnknownException)
 272        STD_EXCEPTION(0x2100, Trap_21, UnknownException)
 273        STD_EXCEPTION(0x2200, Trap_22, UnknownException)
 274        STD_EXCEPTION(0x2300, Trap_23, UnknownException)
 275        STD_EXCEPTION(0x2400, Trap_24, UnknownException)
 276        STD_EXCEPTION(0x2500, Trap_25, UnknownException)
 277        STD_EXCEPTION(0x2600, Trap_26, UnknownException)
 278        STD_EXCEPTION(0x2700, Trap_27, UnknownException)
 279        STD_EXCEPTION(0x2800, Trap_28, UnknownException)
 280        STD_EXCEPTION(0x2900, Trap_29, UnknownException)
 281        STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
 282        STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
 283        STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
 284        STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
 285        STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
 286        STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
 287
 288
 289        .globl  _end_of_vectors
 290_end_of_vectors:
 291
 292        . = 0x3000
 293
 294/*
 295 * This code finishes saving the registers to the exception frame
 296 * and jumps to the appropriate handler for the exception.
 297 * Register r21 is pointer into trap frame, r1 has new stack pointer.
 298 */
 299        .globl  transfer_to_handler
 300transfer_to_handler:
 301        stw     r22,_NIP(r21)
 302        lis     r22,MSR_POW@h
 303        andc    r23,r23,r22
 304        stw     r23,_MSR(r21)
 305        SAVE_GPR(7, r21)
 306        SAVE_4GPRS(8, r21)
 307        SAVE_8GPRS(12, r21)
 308        SAVE_8GPRS(24, r21)
 309        mflr    r23
 310        andi.   r24,r23,0x3f00          /* get vector offset */
 311        stw     r24,TRAP(r21)
 312        li      r22,0
 313        stw     r22,RESULT(r21)
 314        lwz     r24,0(r23)              /* virtual address of handler */
 315        lwz     r23,4(r23)              /* where to go when done */
 316        mtspr   SRR0,r24
 317        mtspr   SRR1,r20
 318        mtlr    r23
 319        SYNC
 320        rfi                             /* jump to handler, enable MMU */
 321
 322int_return:
 323        mfmsr   r28             /* Disable interrupts */
 324        li      r4,0
 325        ori     r4,r4,MSR_EE
 326        andc    r28,r28,r4
 327        SYNC                    /* Some chip revs need this... */
 328        mtmsr   r28
 329        SYNC
 330        lwz     r2,_CTR(r1)
 331        lwz     r0,_LINK(r1)
 332        mtctr   r2
 333        mtlr    r0
 334        lwz     r2,_XER(r1)
 335        lwz     r0,_CCR(r1)
 336        mtspr   XER,r2
 337        mtcrf   0xFF,r0
 338        REST_10GPRS(3, r1)
 339        REST_10GPRS(13, r1)
 340        REST_8GPRS(23, r1)
 341        REST_GPR(31, r1)
 342        lwz     r2,_NIP(r1)     /* Restore environment */
 343        lwz     r0,_MSR(r1)
 344        mtspr   SRR0,r2
 345        mtspr   SRR1,r0
 346        lwz     r0,GPR0(r1)
 347        lwz     r2,GPR2(r1)
 348        lwz     r1,GPR1(r1)
 349        SYNC
 350        rfi
 351#endif /* CONFIG_SPL_BUILD */
 352
 353/*
 354 * This code initialises the MPC5xxx processor core
 355 * (conforms to PowerPC 603e spec)
 356 * Note: expects original MSR contents to be in r5.
 357 */
 358
 359        .globl  init_5xx_core
 360init_5xxx_core:
 361
 362        /* Initialize machine status; enable machine check interrupt    */
 363        /*--------------------------------------------------------------*/
 364
 365        li      r3, MSR_KERNEL          /* Set ME and RI flags */
 366        rlwimi  r3, r5, 0, 25, 25       /* preserve IP bit set by HRCW */
 367#ifdef DEBUG
 368        rlwimi  r3, r5, 0, 21, 22       /* debugger might set SE & BE bits */
 369#endif
 370        SYNC                            /* Some chip revs need this... */
 371        mtmsr   r3
 372        SYNC
 373        mtspr   SRR1, r3                /* Make SRR1 match MSR */
 374
 375        /* Initialize the Hardware Implementation-dependent Registers   */
 376        /* HID0 also contains cache control                             */
 377        /*--------------------------------------------------------------*/
 378
 379        lis     r3, CONFIG_SYS_HID0_INIT@h
 380        ori     r3, r3, CONFIG_SYS_HID0_INIT@l
 381        SYNC
 382        mtspr   HID0, r3
 383
 384        lis     r3, CONFIG_SYS_HID0_FINAL@h
 385        ori     r3, r3, CONFIG_SYS_HID0_FINAL@l
 386        SYNC
 387        mtspr   HID0, r3
 388
 389        /* clear all BAT's                                              */
 390        /*--------------------------------------------------------------*/
 391
 392        li      r0, 0
 393        mtspr   DBAT0U, r0
 394        mtspr   DBAT0L, r0
 395        mtspr   DBAT1U, r0
 396        mtspr   DBAT1L, r0
 397        mtspr   DBAT2U, r0
 398        mtspr   DBAT2L, r0
 399        mtspr   DBAT3U, r0
 400        mtspr   DBAT3L, r0
 401        mtspr   DBAT4U, r0
 402        mtspr   DBAT4L, r0
 403        mtspr   DBAT5U, r0
 404        mtspr   DBAT5L, r0
 405        mtspr   DBAT6U, r0
 406        mtspr   DBAT6L, r0
 407        mtspr   DBAT7U, r0
 408        mtspr   DBAT7L, r0
 409        mtspr   IBAT0U, r0
 410        mtspr   IBAT0L, r0
 411        mtspr   IBAT1U, r0
 412        mtspr   IBAT1L, r0
 413        mtspr   IBAT2U, r0
 414        mtspr   IBAT2L, r0
 415        mtspr   IBAT3U, r0
 416        mtspr   IBAT3L, r0
 417        mtspr   IBAT4U, r0
 418        mtspr   IBAT4L, r0
 419        mtspr   IBAT5U, r0
 420        mtspr   IBAT5L, r0
 421        mtspr   IBAT6U, r0
 422        mtspr   IBAT6L, r0
 423        mtspr   IBAT7U, r0
 424        mtspr   IBAT7L, r0
 425        SYNC
 426
 427        /* invalidate all tlb's                                         */
 428        /*                                                              */
 429        /* From the 603e User Manual: "The 603e provides the ability to */
 430        /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)     */
 431        /* instruction invalidates the TLB entry indexed by the EA, and */
 432        /* operates on both the instruction and data TLBs simultaneously*/
 433        /* invalidating four TLB entries (both sets in each TLB). The   */
 434        /* index corresponds to bits 15-19 of the EA. To invalidate all */
 435        /* entries within both TLBs, 32 tlbie instructions should be    */
 436        /* issued, incrementing this field by one each time."           */
 437        /*                                                              */
 438        /* "Note that the tlbia instruction is not implemented on the   */
 439        /* 603e."                                                       */
 440        /*                                                              */
 441        /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000  */
 442        /* incrementing by 0x1000 each time. The code below is sort of  */
 443        /* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S        */
 444        /*                                                              */
 445        /*--------------------------------------------------------------*/
 446
 447        li      r3, 32
 448        mtctr   r3
 449        li      r3, 0
 4501:      tlbie   r3
 451        addi    r3, r3, 0x1000
 452        bdnz    1b
 453        SYNC
 454
 455        /* Done!                                                        */
 456        /*--------------------------------------------------------------*/
 457
 458        blr
 459
 460/* Cache functions.
 461 *
 462 * Note: requires that all cache bits in
 463 * HID0 are in the low half word.
 464 */
 465        .globl  icache_enable
 466icache_enable:
 467        mfspr   r3, HID0
 468        ori     r3, r3, HID0_ICE
 469        lis     r4, 0
 470        ori     r4, r4, HID0_ILOCK
 471        andc    r3, r3, r4
 472        ori     r4, r3, HID0_ICFI
 473        isync
 474        mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
 475        isync
 476        mtspr   HID0, r3        /* clears invalidate */
 477        blr
 478
 479        .globl  icache_disable
 480icache_disable:
 481        mfspr   r3, HID0
 482        lis     r4, 0
 483        ori     r4, r4, HID0_ICE|HID0_ILOCK
 484        andc    r3, r3, r4
 485        ori     r4, r3, HID0_ICFI
 486        isync
 487        mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
 488        isync
 489        mtspr   HID0, r3        /* clears invalidate */
 490        blr
 491
 492        .globl  icache_status
 493icache_status:
 494        mfspr   r3, HID0
 495        rlwinm  r3, r3, HID0_ICE_BITPOS + 1, 31, 31
 496        blr
 497
 498        .globl  dcache_enable
 499dcache_enable:
 500        mfspr   r3, HID0
 501        ori     r3, r3, HID0_DCE
 502        lis     r4, 0
 503        ori     r4, r4, HID0_DLOCK
 504        andc    r3, r3, r4
 505        ori     r4, r3, HID0_DCI
 506        sync
 507        mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
 508        sync
 509        mtspr   HID0, r3        /* clears invalidate */
 510        blr
 511
 512        .globl  dcache_disable
 513dcache_disable:
 514        mfspr   r3, HID0
 515        lis     r4, 0
 516        ori     r4, r4, HID0_DCE|HID0_DLOCK
 517        andc    r3, r3, r4
 518        ori     r4, r3, HID0_DCI
 519        sync
 520        mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
 521        sync
 522        mtspr   HID0, r3        /* clears invalidate */
 523        blr
 524
 525        .globl  dcache_status
 526dcache_status:
 527        mfspr   r3, HID0
 528        rlwinm  r3, r3, HID0_DCE_BITPOS + 1, 31, 31
 529        blr
 530
 531        .globl get_svr
 532get_svr:
 533        mfspr   r3, SVR
 534        blr
 535
 536        .globl get_pvr
 537get_pvr:
 538        mfspr   r3, PVR
 539        blr
 540
 541#ifndef CONFIG_SPL_BUILD
 542/*------------------------------------------------------------------------------*/
 543
 544/*
 545 * void relocate_code (addr_sp, gd, addr_moni)
 546 *
 547 * This "function" does not return, instead it continues in RAM
 548 * after relocating the monitor code.
 549 *
 550 * r3 = dest
 551 * r4 = src
 552 * r5 = length in bytes
 553 * r6 = cachelinesize
 554 */
 555        .globl  relocate_code
 556relocate_code:
 557        mr      r1,  r3         /* Set new stack pointer                */
 558        mr      r9,  r4         /* Save copy of Global Data pointer     */
 559        mr      r10, r5         /* Save copy of Destination Address     */
 560
 561        GET_GOT
 562        mr      r3,  r5                         /* Destination Address  */
 563        lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
 564        ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
 565        lwz     r5, GOT(__init_end)
 566        sub     r5, r5, r4
 567        li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
 568
 569        /*
 570         * Fix GOT pointer:
 571         *
 572         * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
 573         *
 574         * Offset:
 575         */
 576        sub     r15, r10, r4
 577
 578        /* First our own GOT */
 579        add     r12, r12, r15
 580        /* then the one used by the C code */
 581        add     r30, r30, r15
 582
 583        /*
 584         * Now relocate code
 585         */
 586
 587        cmplw   cr1,r3,r4
 588        addi    r0,r5,3
 589        srwi.   r0,r0,2
 590        beq     cr1,4f          /* In place copy is not necessary       */
 591        beq     7f              /* Protect against 0 count              */
 592        mtctr   r0
 593        bge     cr1,2f
 594
 595        la      r8,-4(r4)
 596        la      r7,-4(r3)
 5971:      lwzu    r0,4(r8)
 598        stwu    r0,4(r7)
 599        bdnz    1b
 600        b       4f
 601
 6022:      slwi    r0,r0,2
 603        add     r8,r4,r0
 604        add     r7,r3,r0
 6053:      lwzu    r0,-4(r8)
 606        stwu    r0,-4(r7)
 607        bdnz    3b
 608
 609/*
 610 * Now flush the cache: note that we must start from a cache aligned
 611 * address. Otherwise we might miss one cache line.
 612 */
 6134:      cmpwi   r6,0
 614        add     r5,r3,r5
 615        beq     7f              /* Always flush prefetch queue in any case */
 616        subi    r0,r6,1
 617        andc    r3,r3,r0
 618        mfspr   r7,HID0         /* don't do dcbst if dcache is disabled */
 619        rlwinm  r7,r7,HID0_DCE_BITPOS+1,31,31
 620        cmpwi   r7,0
 621        beq     9f
 622        mr      r4,r3
 6235:      dcbst   0,r4
 624        add     r4,r4,r6
 625        cmplw   r4,r5
 626        blt     5b
 627        sync                    /* Wait for all dcbst to complete on bus */
 6289:      mfspr   r7,HID0         /* don't do icbi if icache is disabled */
 629        rlwinm  r7,r7,HID0_ICE_BITPOS+1,31,31
 630        cmpwi   r7,0
 631        beq     7f
 632        mr      r4,r3
 6336:      icbi    0,r4
 634        add     r4,r4,r6
 635        cmplw   r4,r5
 636        blt     6b
 6377:      sync                    /* Wait for all icbi to complete on bus */
 638        isync
 639
 640/*
 641 * We are done. Do not return, instead branch to second part of board
 642 * initialization, now running from RAM.
 643 */
 644
 645        addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
 646        mtlr    r0
 647        blr
 648
 649in_ram:
 650
 651        /*
 652         * Relocation Function, r12 point to got2+0x8000
 653         *
 654         * Adjust got2 pointers, no need to check for 0, this code
 655         * already puts a few entries in the table.
 656         */
 657        li      r0,__got2_entries@sectoff@l
 658        la      r3,GOT(_GOT2_TABLE_)
 659        lwz     r11,GOT(_GOT2_TABLE_)
 660        mtctr   r0
 661        sub     r11,r3,r11
 662        addi    r3,r3,-4
 6631:      lwzu    r0,4(r3)
 664        cmpwi   r0,0
 665        beq-    2f
 666        add     r0,r0,r11
 667        stw     r0,0(r3)
 6682:      bdnz    1b
 669
 670        /*
 671         * Now adjust the fixups and the pointers to the fixups
 672         * in case we need to move ourselves again.
 673         */
 674        li      r0,__fixup_entries@sectoff@l
 675        lwz     r3,GOT(_FIXUP_TABLE_)
 676        cmpwi   r0,0
 677        mtctr   r0
 678        addi    r3,r3,-4
 679        beq     4f
 6803:      lwzu    r4,4(r3)
 681        lwzux   r0,r4,r11
 682        cmpwi   r0,0
 683        add     r0,r0,r11
 684        stw     r4,0(r3)
 685        beq-    5f
 686        stw     r0,0(r4)
 6875:      bdnz    3b
 6884:
 689clear_bss:
 690        /*
 691         * Now clear BSS segment
 692         */
 693        lwz     r3,GOT(__bss_start)
 694        lwz     r4,GOT(__bss_end)
 695
 696        cmplw   0, r3, r4
 697        beq     6f
 698
 699        li      r0, 0
 7005:
 701        stw     r0, 0(r3)
 702        addi    r3, r3, 4
 703        cmplw   0, r3, r4
 704        bne     5b
 7056:
 706
 707        mr      r3, r9          /* Global Data pointer          */
 708        mr      r4, r10         /* Destination Address          */
 709        bl      board_init_r
 710
 711        /*
 712         * Copy exception vector code to low memory
 713         *
 714         * r3: dest_addr
 715         * r7: source address, r8: end address, r9: target address
 716         */
 717        .globl  trap_init
 718trap_init:
 719        mflr    r4                      /* save link register           */
 720        GET_GOT
 721        lwz     r7, GOT(_start)
 722        lwz     r8, GOT(_end_of_vectors)
 723
 724        li      r9, 0x100               /* reset vector always at 0x100 */
 725
 726        cmplw   0, r7, r8
 727        bgelr                           /* return if r7>=r8 - just in case */
 7281:
 729        lwz     r0, 0(r7)
 730        stw     r0, 0(r9)
 731        addi    r7, r7, 4
 732        addi    r9, r9, 4
 733        cmplw   0, r7, r8
 734        bne     1b
 735
 736        /*
 737         * relocate `hdlr' and `int_return' entries
 738         */
 739        li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
 740        li      r8, Alignment - _start + EXC_OFF_SYS_RESET
 7412:
 742        bl      trap_reloc
 743        addi    r7, r7, 0x100           /* next exception vector        */
 744        cmplw   0, r7, r8
 745        blt     2b
 746
 747        li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
 748        bl      trap_reloc
 749
 750        li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
 751        bl      trap_reloc
 752
 753        li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
 754        li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
 7553:
 756        bl      trap_reloc
 757        addi    r7, r7, 0x100           /* next exception vector        */
 758        cmplw   0, r7, r8
 759        blt     3b
 760
 761        li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
 762        li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
 7634:
 764        bl      trap_reloc
 765        addi    r7, r7, 0x100           /* next exception vector        */
 766        cmplw   0, r7, r8
 767        blt     4b
 768
 769        mfmsr   r3                      /* now that the vectors have    */
 770        lis     r7, MSR_IP@h            /* relocated into low memory    */
 771        ori     r7, r7, MSR_IP@l        /* MSR[IP] can be turned off    */
 772        andc    r3, r3, r7              /* (if it was on)               */
 773        SYNC                            /* Some chip revs need this... */
 774        mtmsr   r3
 775        SYNC
 776
 777        mtlr    r4                      /* restore link register    */
 778        blr
 779
 780#endif /* CONFIG_SPL_BUILD */
 781