1*907208c4SChristophe Leroy/* 2*907208c4SChristophe Leroy * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> 3*907208c4SChristophe Leroy * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> 4*907208c4SChristophe Leroy * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de> 5*907208c4SChristophe Leroy * 6*907208c4SChristophe Leroy * SPDX-License-Identifier: GPL-2.0+ 7*907208c4SChristophe Leroy */ 8*907208c4SChristophe Leroy 9*907208c4SChristophe Leroy/* U-Boot - Startup Code for PowerPC based Embedded Boards 10*907208c4SChristophe Leroy * 11*907208c4SChristophe Leroy * 12*907208c4SChristophe Leroy * The processor starts at 0x00000100 and the code is executed 13*907208c4SChristophe Leroy * from flash. The code is organized to be at an other address 14*907208c4SChristophe Leroy * in memory, but as long we don't jump around before relocating, 15*907208c4SChristophe Leroy * board_init lies at a quite high address and when the cpu has 16*907208c4SChristophe Leroy * jumped there, everything is ok. 17*907208c4SChristophe Leroy * This works because the cpu gives the FLASH (CS0) the whole 18*907208c4SChristophe Leroy * address space at startup, and board_init lies as a echo of 19*907208c4SChristophe Leroy * the flash somewhere up there in the memory map. 20*907208c4SChristophe Leroy * 21*907208c4SChristophe Leroy * board_init will change CS0 to be positioned at the correct 22*907208c4SChristophe Leroy * address and (s)dram will be positioned at address 0 23*907208c4SChristophe Leroy */ 24*907208c4SChristophe Leroy#include <asm-offsets.h> 25*907208c4SChristophe Leroy#include <config.h> 26*907208c4SChristophe Leroy#include <mpc8xx.h> 27*907208c4SChristophe Leroy#include <version.h> 28*907208c4SChristophe Leroy 29*907208c4SChristophe Leroy#include <ppc_asm.tmpl> 30*907208c4SChristophe Leroy#include <ppc_defs.h> 31*907208c4SChristophe Leroy 32*907208c4SChristophe Leroy#include <asm/cache.h> 33*907208c4SChristophe Leroy#include <asm/mmu.h> 34*907208c4SChristophe Leroy#include <asm/u-boot.h> 35*907208c4SChristophe Leroy 36*907208c4SChristophe Leroy/* We don't want the MMU yet. 37*907208c4SChristophe Leroy*/ 38*907208c4SChristophe Leroy#undef MSR_KERNEL 39*907208c4SChristophe Leroy#define MSR_KERNEL ( MSR_ME | MSR_RI ) /* Machine Check and Recoverable Interr. */ 40*907208c4SChristophe Leroy 41*907208c4SChristophe Leroy/* 42*907208c4SChristophe Leroy * Set up GOT: Global Offset Table 43*907208c4SChristophe Leroy * 44*907208c4SChristophe Leroy * Use r12 to access the GOT 45*907208c4SChristophe Leroy */ 46*907208c4SChristophe Leroy START_GOT 47*907208c4SChristophe Leroy GOT_ENTRY(_GOT2_TABLE_) 48*907208c4SChristophe Leroy GOT_ENTRY(_FIXUP_TABLE_) 49*907208c4SChristophe Leroy 50*907208c4SChristophe Leroy GOT_ENTRY(_start) 51*907208c4SChristophe Leroy GOT_ENTRY(_start_of_vectors) 52*907208c4SChristophe Leroy GOT_ENTRY(_end_of_vectors) 53*907208c4SChristophe Leroy GOT_ENTRY(transfer_to_handler) 54*907208c4SChristophe Leroy 55*907208c4SChristophe Leroy GOT_ENTRY(__init_end) 56*907208c4SChristophe Leroy GOT_ENTRY(__bss_end) 57*907208c4SChristophe Leroy GOT_ENTRY(__bss_start) 58*907208c4SChristophe Leroy END_GOT 59*907208c4SChristophe Leroy 60*907208c4SChristophe Leroy/* 61*907208c4SChristophe Leroy * r3 - 1st arg to board_init(): IMMP pointer 62*907208c4SChristophe Leroy * r4 - 2nd arg to board_init(): boot flag 63*907208c4SChristophe Leroy */ 64*907208c4SChristophe Leroy .text 65*907208c4SChristophe Leroy .long 0x27051956 /* U-Boot Magic Number */ 66*907208c4SChristophe Leroy .globl version_string 67*907208c4SChristophe Leroyversion_string: 68*907208c4SChristophe Leroy .ascii U_BOOT_VERSION_STRING, "\0" 69*907208c4SChristophe Leroy 70*907208c4SChristophe Leroy . = EXC_OFF_SYS_RESET 71*907208c4SChristophe Leroy .globl _start 72*907208c4SChristophe Leroy_start: 73*907208c4SChristophe Leroy lis r3, CONFIG_SYS_IMMR@h /* position IMMR */ 74*907208c4SChristophe Leroy mtspr 638, r3 75*907208c4SChristophe Leroy 76*907208c4SChristophe Leroy /* Initialize machine status; enable machine check interrupt */ 77*907208c4SChristophe Leroy /*----------------------------------------------------------------------*/ 78*907208c4SChristophe Leroy li r3, MSR_KERNEL /* Set ME, RI flags */ 79*907208c4SChristophe Leroy mtmsr r3 80*907208c4SChristophe Leroy mtspr SRR1, r3 /* Make SRR1 match MSR */ 81*907208c4SChristophe Leroy 82*907208c4SChristophe Leroy mfspr r3, ICR /* clear Interrupt Cause Register */ 83*907208c4SChristophe Leroy 84*907208c4SChristophe Leroy /* Initialize debug port registers */ 85*907208c4SChristophe Leroy /*----------------------------------------------------------------------*/ 86*907208c4SChristophe Leroy xor r0, r0, r0 /* Clear R0 */ 87*907208c4SChristophe Leroy mtspr LCTRL1, r0 /* Initialize debug port regs */ 88*907208c4SChristophe Leroy mtspr LCTRL2, r0 89*907208c4SChristophe Leroy mtspr COUNTA, r0 90*907208c4SChristophe Leroy mtspr COUNTB, r0 91*907208c4SChristophe Leroy 92*907208c4SChristophe Leroy /* Reset the caches */ 93*907208c4SChristophe Leroy /*----------------------------------------------------------------------*/ 94*907208c4SChristophe Leroy 95*907208c4SChristophe Leroy mfspr r3, IC_CST /* Clear error bits */ 96*907208c4SChristophe Leroy mfspr r3, DC_CST 97*907208c4SChristophe Leroy 98*907208c4SChristophe Leroy lis r3, IDC_UNALL@h /* Unlock all */ 99*907208c4SChristophe Leroy mtspr IC_CST, r3 100*907208c4SChristophe Leroy mtspr DC_CST, r3 101*907208c4SChristophe Leroy 102*907208c4SChristophe Leroy lis r3, IDC_INVALL@h /* Invalidate all */ 103*907208c4SChristophe Leroy mtspr IC_CST, r3 104*907208c4SChristophe Leroy mtspr DC_CST, r3 105*907208c4SChristophe Leroy 106*907208c4SChristophe Leroy lis r3, IDC_DISABLE@h /* Disable data cache */ 107*907208c4SChristophe Leroy mtspr DC_CST, r3 108*907208c4SChristophe Leroy 109*907208c4SChristophe Leroy lis r3, IDC_ENABLE@h /* Enable instruction cache */ 110*907208c4SChristophe Leroy mtspr IC_CST, r3 111*907208c4SChristophe Leroy 112*907208c4SChristophe Leroy /* invalidate all tlb's */ 113*907208c4SChristophe Leroy /*----------------------------------------------------------------------*/ 114*907208c4SChristophe Leroy 115*907208c4SChristophe Leroy tlbia 116*907208c4SChristophe Leroy isync 117*907208c4SChristophe Leroy 118*907208c4SChristophe Leroy /* 119*907208c4SChristophe Leroy * Calculate absolute address in FLASH and jump there 120*907208c4SChristophe Leroy *----------------------------------------------------------------------*/ 121*907208c4SChristophe Leroy 122*907208c4SChristophe Leroy lis r3, CONFIG_SYS_MONITOR_BASE@h 123*907208c4SChristophe Leroy ori r3, r3, CONFIG_SYS_MONITOR_BASE@l 124*907208c4SChristophe Leroy addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET 125*907208c4SChristophe Leroy mtlr r3 126*907208c4SChristophe Leroy blr 127*907208c4SChristophe Leroy 128*907208c4SChristophe Leroyin_flash: 129*907208c4SChristophe Leroy 130*907208c4SChristophe Leroy /* initialize some SPRs that are hard to access from C */ 131*907208c4SChristophe Leroy /*----------------------------------------------------------------------*/ 132*907208c4SChristophe Leroy 133*907208c4SChristophe Leroy lis r3, CONFIG_SYS_IMMR@h /* pass IMMR as arg1 to C routine */ 134*907208c4SChristophe Leroy ori r1, r3, CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in internal DPRAM */ 135*907208c4SChristophe Leroy /* Note: R0 is still 0 here */ 136*907208c4SChristophe Leroy stwu r0, -4(r1) /* clear final stack frame so that */ 137*907208c4SChristophe Leroy stwu r0, -4(r1) /* stack backtraces terminate cleanly */ 138*907208c4SChristophe Leroy 139*907208c4SChristophe Leroy /* 140*907208c4SChristophe Leroy * Disable serialized ifetch and show cycles 141*907208c4SChristophe Leroy * (i.e. set processor to normal mode). 142*907208c4SChristophe Leroy * This is also a silicon bug workaround, see errata 143*907208c4SChristophe Leroy */ 144*907208c4SChristophe Leroy 145*907208c4SChristophe Leroy li r2, 0x0007 146*907208c4SChristophe Leroy mtspr ICTRL, r2 147*907208c4SChristophe Leroy 148*907208c4SChristophe Leroy /* Set up debug mode entry */ 149*907208c4SChristophe Leroy 150*907208c4SChristophe Leroy lis r2, CONFIG_SYS_DER@h 151*907208c4SChristophe Leroy ori r2, r2, CONFIG_SYS_DER@l 152*907208c4SChristophe Leroy mtspr DER, r2 153*907208c4SChristophe Leroy 154*907208c4SChristophe Leroy /* let the C-code set up the rest */ 155*907208c4SChristophe Leroy /* */ 156*907208c4SChristophe Leroy /* Be careful to keep code relocatable ! */ 157*907208c4SChristophe Leroy /*----------------------------------------------------------------------*/ 158*907208c4SChristophe Leroy 159*907208c4SChristophe Leroy GET_GOT /* initialize GOT access */ 160*907208c4SChristophe Leroy 161*907208c4SChristophe Leroy /* r3: IMMR */ 162*907208c4SChristophe Leroy bl cpu_init_f /* run low-level CPU init code (from Flash) */ 163*907208c4SChristophe Leroy 164*907208c4SChristophe Leroy bl board_init_f /* run 1st part of board init code (from Flash) */ 165*907208c4SChristophe Leroy 166*907208c4SChristophe Leroy /* NOTREACHED - board_init_f() does not return */ 167*907208c4SChristophe Leroy 168*907208c4SChristophe Leroy 169*907208c4SChristophe Leroy .globl _start_of_vectors 170*907208c4SChristophe Leroy_start_of_vectors: 171*907208c4SChristophe Leroy 172*907208c4SChristophe Leroy/* Machine check */ 173*907208c4SChristophe Leroy STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) 174*907208c4SChristophe Leroy 175*907208c4SChristophe Leroy/* Data Storage exception. "Never" generated on the 860. */ 176*907208c4SChristophe Leroy STD_EXCEPTION(0x300, DataStorage, UnknownException) 177*907208c4SChristophe Leroy 178*907208c4SChristophe Leroy/* Instruction Storage exception. "Never" generated on the 860. */ 179*907208c4SChristophe Leroy STD_EXCEPTION(0x400, InstStorage, UnknownException) 180*907208c4SChristophe Leroy 181*907208c4SChristophe Leroy/* External Interrupt exception. */ 182*907208c4SChristophe Leroy STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) 183*907208c4SChristophe Leroy 184*907208c4SChristophe Leroy/* Alignment exception. */ 185*907208c4SChristophe Leroy . = 0x600 186*907208c4SChristophe LeroyAlignment: 187*907208c4SChristophe Leroy EXCEPTION_PROLOG(SRR0, SRR1) 188*907208c4SChristophe Leroy mfspr r4,DAR 189*907208c4SChristophe Leroy stw r4,_DAR(r21) 190*907208c4SChristophe Leroy mfspr r5,DSISR 191*907208c4SChristophe Leroy stw r5,_DSISR(r21) 192*907208c4SChristophe Leroy addi r3,r1,STACK_FRAME_OVERHEAD 193*907208c4SChristophe Leroy EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE) 194*907208c4SChristophe Leroy 195*907208c4SChristophe Leroy/* Program check exception */ 196*907208c4SChristophe Leroy . = 0x700 197*907208c4SChristophe LeroyProgramCheck: 198*907208c4SChristophe Leroy EXCEPTION_PROLOG(SRR0, SRR1) 199*907208c4SChristophe Leroy addi r3,r1,STACK_FRAME_OVERHEAD 200*907208c4SChristophe Leroy EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException, 201*907208c4SChristophe Leroy MSR_KERNEL, COPY_EE) 202*907208c4SChristophe Leroy 203*907208c4SChristophe Leroy /* No FPU on MPC8xx. This exception is not supposed to happen. 204*907208c4SChristophe Leroy */ 205*907208c4SChristophe Leroy STD_EXCEPTION(0x800, FPUnavailable, UnknownException) 206*907208c4SChristophe Leroy 207*907208c4SChristophe Leroy /* I guess we could implement decrementer, and may have 208*907208c4SChristophe Leroy * to someday for timekeeping. 209*907208c4SChristophe Leroy */ 210*907208c4SChristophe Leroy STD_EXCEPTION(0x900, Decrementer, timer_interrupt) 211*907208c4SChristophe Leroy STD_EXCEPTION(0xa00, Trap_0a, UnknownException) 212*907208c4SChristophe Leroy STD_EXCEPTION(0xb00, Trap_0b, UnknownException) 213*907208c4SChristophe Leroy STD_EXCEPTION(0xc00, SystemCall, UnknownException) 214*907208c4SChristophe Leroy STD_EXCEPTION(0xd00, SingleStep, UnknownException) 215*907208c4SChristophe Leroy 216*907208c4SChristophe Leroy STD_EXCEPTION(0xe00, Trap_0e, UnknownException) 217*907208c4SChristophe Leroy STD_EXCEPTION(0xf00, Trap_0f, UnknownException) 218*907208c4SChristophe Leroy 219*907208c4SChristophe Leroy /* On the MPC8xx, this is a software emulation interrupt. It occurs 220*907208c4SChristophe Leroy * for all unimplemented and illegal instructions. 221*907208c4SChristophe Leroy */ 222*907208c4SChristophe Leroy STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException) 223*907208c4SChristophe Leroy 224*907208c4SChristophe Leroy STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) 225*907208c4SChristophe Leroy STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) 226*907208c4SChristophe Leroy STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException) 227*907208c4SChristophe Leroy STD_EXCEPTION(0x1400, DataTLBError, UnknownException) 228*907208c4SChristophe Leroy 229*907208c4SChristophe Leroy STD_EXCEPTION(0x1500, Reserved5, UnknownException) 230*907208c4SChristophe Leroy STD_EXCEPTION(0x1600, Reserved6, UnknownException) 231*907208c4SChristophe Leroy STD_EXCEPTION(0x1700, Reserved7, UnknownException) 232*907208c4SChristophe Leroy STD_EXCEPTION(0x1800, Reserved8, UnknownException) 233*907208c4SChristophe Leroy STD_EXCEPTION(0x1900, Reserved9, UnknownException) 234*907208c4SChristophe Leroy STD_EXCEPTION(0x1a00, ReservedA, UnknownException) 235*907208c4SChristophe Leroy STD_EXCEPTION(0x1b00, ReservedB, UnknownException) 236*907208c4SChristophe Leroy 237*907208c4SChristophe Leroy STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException) 238*907208c4SChristophe Leroy STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException) 239*907208c4SChristophe Leroy STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException) 240*907208c4SChristophe Leroy STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException) 241*907208c4SChristophe Leroy 242*907208c4SChristophe Leroy 243*907208c4SChristophe Leroy .globl _end_of_vectors 244*907208c4SChristophe Leroy_end_of_vectors: 245*907208c4SChristophe Leroy 246*907208c4SChristophe Leroy 247*907208c4SChristophe Leroy . = 0x2000 248*907208c4SChristophe Leroy 249*907208c4SChristophe Leroy/* 250*907208c4SChristophe Leroy * This code finishes saving the registers to the exception frame 251*907208c4SChristophe Leroy * and jumps to the appropriate handler for the exception. 252*907208c4SChristophe Leroy * Register r21 is pointer into trap frame, r1 has new stack pointer. 253*907208c4SChristophe Leroy */ 254*907208c4SChristophe Leroy .globl transfer_to_handler 255*907208c4SChristophe Leroytransfer_to_handler: 256*907208c4SChristophe Leroy stw r22,_NIP(r21) 257*907208c4SChristophe Leroy lis r22,MSR_POW@h 258*907208c4SChristophe Leroy andc r23,r23,r22 259*907208c4SChristophe Leroy stw r23,_MSR(r21) 260*907208c4SChristophe Leroy SAVE_GPR(7, r21) 261*907208c4SChristophe Leroy SAVE_4GPRS(8, r21) 262*907208c4SChristophe Leroy SAVE_8GPRS(12, r21) 263*907208c4SChristophe Leroy SAVE_8GPRS(24, r21) 264*907208c4SChristophe Leroy mflr r23 265*907208c4SChristophe Leroy andi. r24,r23,0x3f00 /* get vector offset */ 266*907208c4SChristophe Leroy stw r24,TRAP(r21) 267*907208c4SChristophe Leroy li r22,0 268*907208c4SChristophe Leroy stw r22,RESULT(r21) 269*907208c4SChristophe Leroy mtspr SPRG2,r22 /* r1 is now kernel sp */ 270*907208c4SChristophe Leroy lwz r24,0(r23) /* virtual address of handler */ 271*907208c4SChristophe Leroy lwz r23,4(r23) /* where to go when done */ 272*907208c4SChristophe Leroy mtspr SRR0,r24 273*907208c4SChristophe Leroy mtspr SRR1,r20 274*907208c4SChristophe Leroy mtlr r23 275*907208c4SChristophe Leroy SYNC 276*907208c4SChristophe Leroy rfi /* jump to handler, enable MMU */ 277*907208c4SChristophe Leroy 278*907208c4SChristophe Leroyint_return: 279*907208c4SChristophe Leroy mfmsr r28 /* Disable interrupts */ 280*907208c4SChristophe Leroy li r4,0 281*907208c4SChristophe Leroy ori r4,r4,MSR_EE 282*907208c4SChristophe Leroy andc r28,r28,r4 283*907208c4SChristophe Leroy SYNC /* Some chip revs need this... */ 284*907208c4SChristophe Leroy mtmsr r28 285*907208c4SChristophe Leroy SYNC 286*907208c4SChristophe Leroy lwz r2,_CTR(r1) 287*907208c4SChristophe Leroy lwz r0,_LINK(r1) 288*907208c4SChristophe Leroy mtctr r2 289*907208c4SChristophe Leroy mtlr r0 290*907208c4SChristophe Leroy lwz r2,_XER(r1) 291*907208c4SChristophe Leroy lwz r0,_CCR(r1) 292*907208c4SChristophe Leroy mtspr XER,r2 293*907208c4SChristophe Leroy mtcrf 0xFF,r0 294*907208c4SChristophe Leroy REST_10GPRS(3, r1) 295*907208c4SChristophe Leroy REST_10GPRS(13, r1) 296*907208c4SChristophe Leroy REST_8GPRS(23, r1) 297*907208c4SChristophe Leroy REST_GPR(31, r1) 298*907208c4SChristophe Leroy lwz r2,_NIP(r1) /* Restore environment */ 299*907208c4SChristophe Leroy lwz r0,_MSR(r1) 300*907208c4SChristophe Leroy mtspr SRR0,r2 301*907208c4SChristophe Leroy mtspr SRR1,r0 302*907208c4SChristophe Leroy lwz r0,GPR0(r1) 303*907208c4SChristophe Leroy lwz r2,GPR2(r1) 304*907208c4SChristophe Leroy lwz r1,GPR1(r1) 305*907208c4SChristophe Leroy SYNC 306*907208c4SChristophe Leroy rfi 307*907208c4SChristophe Leroy 308*907208c4SChristophe Leroy/*------------------------------------------------------------------------------*/ 309*907208c4SChristophe Leroy 310*907208c4SChristophe Leroy/* 311*907208c4SChristophe Leroy * void relocate_code (addr_sp, gd, addr_moni) 312*907208c4SChristophe Leroy * 313*907208c4SChristophe Leroy * This "function" does not return, instead it continues in RAM 314*907208c4SChristophe Leroy * after relocating the monitor code. 315*907208c4SChristophe Leroy * 316*907208c4SChristophe Leroy * r3 = dest 317*907208c4SChristophe Leroy * r4 = src 318*907208c4SChristophe Leroy * r5 = length in bytes 319*907208c4SChristophe Leroy * r6 = cachelinesize 320*907208c4SChristophe Leroy */ 321*907208c4SChristophe Leroy .globl relocate_code 322*907208c4SChristophe Leroyrelocate_code: 323*907208c4SChristophe Leroy mr r1, r3 /* Set new stack pointer */ 324*907208c4SChristophe Leroy mr r9, r4 /* Save copy of Global Data pointer */ 325*907208c4SChristophe Leroy mr r10, r5 /* Save copy of Destination Address */ 326*907208c4SChristophe Leroy 327*907208c4SChristophe Leroy GET_GOT 328*907208c4SChristophe Leroy mr r3, r5 /* Destination Address */ 329*907208c4SChristophe Leroy lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */ 330*907208c4SChristophe Leroy ori r4, r4, CONFIG_SYS_MONITOR_BASE@l 331*907208c4SChristophe Leroy lwz r5, GOT(__init_end) 332*907208c4SChristophe Leroy sub r5, r5, r4 333*907208c4SChristophe Leroy li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */ 334*907208c4SChristophe Leroy 335*907208c4SChristophe Leroy /* 336*907208c4SChristophe Leroy * Fix GOT pointer: 337*907208c4SChristophe Leroy * 338*907208c4SChristophe Leroy * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address 339*907208c4SChristophe Leroy * 340*907208c4SChristophe Leroy * Offset: 341*907208c4SChristophe Leroy */ 342*907208c4SChristophe Leroy sub r15, r10, r4 343*907208c4SChristophe Leroy 344*907208c4SChristophe Leroy /* First our own GOT */ 345*907208c4SChristophe Leroy add r12, r12, r15 346*907208c4SChristophe Leroy /* then the one used by the C code */ 347*907208c4SChristophe Leroy add r30, r30, r15 348*907208c4SChristophe Leroy 349*907208c4SChristophe Leroy /* 350*907208c4SChristophe Leroy * Now relocate code 351*907208c4SChristophe Leroy */ 352*907208c4SChristophe Leroy 353*907208c4SChristophe Leroy cmplw cr1,r3,r4 354*907208c4SChristophe Leroy addi r0,r5,3 355*907208c4SChristophe Leroy srwi. r0,r0,2 356*907208c4SChristophe Leroy beq cr1,4f /* In place copy is not necessary */ 357*907208c4SChristophe Leroy beq 7f /* Protect against 0 count */ 358*907208c4SChristophe Leroy mtctr r0 359*907208c4SChristophe Leroy bge cr1,2f 360*907208c4SChristophe Leroy 361*907208c4SChristophe Leroy la r8,-4(r4) 362*907208c4SChristophe Leroy la r7,-4(r3) 363*907208c4SChristophe Leroy1: lwzu r0,4(r8) 364*907208c4SChristophe Leroy stwu r0,4(r7) 365*907208c4SChristophe Leroy bdnz 1b 366*907208c4SChristophe Leroy b 4f 367*907208c4SChristophe Leroy 368*907208c4SChristophe Leroy2: slwi r0,r0,2 369*907208c4SChristophe Leroy add r8,r4,r0 370*907208c4SChristophe Leroy add r7,r3,r0 371*907208c4SChristophe Leroy3: lwzu r0,-4(r8) 372*907208c4SChristophe Leroy stwu r0,-4(r7) 373*907208c4SChristophe Leroy bdnz 3b 374*907208c4SChristophe Leroy 375*907208c4SChristophe Leroy/* 376*907208c4SChristophe Leroy * Now flush the cache: note that we must start from a cache aligned 377*907208c4SChristophe Leroy * address. Otherwise we might miss one cache line. 378*907208c4SChristophe Leroy */ 379*907208c4SChristophe Leroy4: cmpwi r6,0 380*907208c4SChristophe Leroy add r5,r3,r5 381*907208c4SChristophe Leroy beq 7f /* Always flush prefetch queue in any case */ 382*907208c4SChristophe Leroy subi r0,r6,1 383*907208c4SChristophe Leroy andc r3,r3,r0 384*907208c4SChristophe Leroy mr r4,r3 385*907208c4SChristophe Leroy5: dcbst 0,r4 386*907208c4SChristophe Leroy add r4,r4,r6 387*907208c4SChristophe Leroy cmplw r4,r5 388*907208c4SChristophe Leroy blt 5b 389*907208c4SChristophe Leroy sync /* Wait for all dcbst to complete on bus */ 390*907208c4SChristophe Leroy mr r4,r3 391*907208c4SChristophe Leroy6: icbi 0,r4 392*907208c4SChristophe Leroy add r4,r4,r6 393*907208c4SChristophe Leroy cmplw r4,r5 394*907208c4SChristophe Leroy blt 6b 395*907208c4SChristophe Leroy7: sync /* Wait for all icbi to complete on bus */ 396*907208c4SChristophe Leroy isync 397*907208c4SChristophe Leroy 398*907208c4SChristophe Leroy/* 399*907208c4SChristophe Leroy * We are done. Do not return, instead branch to second part of board 400*907208c4SChristophe Leroy * initialization, now running from RAM. 401*907208c4SChristophe Leroy */ 402*907208c4SChristophe Leroy 403*907208c4SChristophe Leroy addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET 404*907208c4SChristophe Leroy mtlr r0 405*907208c4SChristophe Leroy blr 406*907208c4SChristophe Leroy 407*907208c4SChristophe Leroyin_ram: 408*907208c4SChristophe Leroy 409*907208c4SChristophe Leroy /* 410*907208c4SChristophe Leroy * Relocation Function, r12 point to got2+0x8000 411*907208c4SChristophe Leroy * 412*907208c4SChristophe Leroy * Adjust got2 pointers, no need to check for 0, this code 413*907208c4SChristophe Leroy * already puts a few entries in the table. 414*907208c4SChristophe Leroy */ 415*907208c4SChristophe Leroy li r0,__got2_entries@sectoff@l 416*907208c4SChristophe Leroy la r3,GOT(_GOT2_TABLE_) 417*907208c4SChristophe Leroy lwz r11,GOT(_GOT2_TABLE_) 418*907208c4SChristophe Leroy mtctr r0 419*907208c4SChristophe Leroy sub r11,r3,r11 420*907208c4SChristophe Leroy addi r3,r3,-4 421*907208c4SChristophe Leroy1: lwzu r0,4(r3) 422*907208c4SChristophe Leroy cmpwi r0,0 423*907208c4SChristophe Leroy beq- 2f 424*907208c4SChristophe Leroy add r0,r0,r11 425*907208c4SChristophe Leroy stw r0,0(r3) 426*907208c4SChristophe Leroy2: bdnz 1b 427*907208c4SChristophe Leroy 428*907208c4SChristophe Leroy /* 429*907208c4SChristophe Leroy * Now adjust the fixups and the pointers to the fixups 430*907208c4SChristophe Leroy * in case we need to move ourselves again. 431*907208c4SChristophe Leroy */ 432*907208c4SChristophe Leroy li r0,__fixup_entries@sectoff@l 433*907208c4SChristophe Leroy lwz r3,GOT(_FIXUP_TABLE_) 434*907208c4SChristophe Leroy cmpwi r0,0 435*907208c4SChristophe Leroy mtctr r0 436*907208c4SChristophe Leroy addi r3,r3,-4 437*907208c4SChristophe Leroy beq 4f 438*907208c4SChristophe Leroy3: lwzu r4,4(r3) 439*907208c4SChristophe Leroy lwzux r0,r4,r11 440*907208c4SChristophe Leroy cmpwi r0,0 441*907208c4SChristophe Leroy add r0,r0,r11 442*907208c4SChristophe Leroy stw r4,0(r3) 443*907208c4SChristophe Leroy beq- 5f 444*907208c4SChristophe Leroy stw r0,0(r4) 445*907208c4SChristophe Leroy5: bdnz 3b 446*907208c4SChristophe Leroy4: 447*907208c4SChristophe Leroyclear_bss: 448*907208c4SChristophe Leroy /* 449*907208c4SChristophe Leroy * Now clear BSS segment 450*907208c4SChristophe Leroy */ 451*907208c4SChristophe Leroy lwz r3,GOT(__bss_start) 452*907208c4SChristophe Leroy lwz r4,GOT(__bss_end) 453*907208c4SChristophe Leroy 454*907208c4SChristophe Leroy cmplw 0, r3, r4 455*907208c4SChristophe Leroy beq 6f 456*907208c4SChristophe Leroy 457*907208c4SChristophe Leroy li r0, 0 458*907208c4SChristophe Leroy5: 459*907208c4SChristophe Leroy stw r0, 0(r3) 460*907208c4SChristophe Leroy addi r3, r3, 4 461*907208c4SChristophe Leroy cmplw 0, r3, r4 462*907208c4SChristophe Leroy bne 5b 463*907208c4SChristophe Leroy6: 464*907208c4SChristophe Leroy 465*907208c4SChristophe Leroy mr r3, r9 /* Global Data pointer */ 466*907208c4SChristophe Leroy mr r4, r10 /* Destination Address */ 467*907208c4SChristophe Leroy bl board_init_r 468*907208c4SChristophe Leroy 469*907208c4SChristophe Leroy /* 470*907208c4SChristophe Leroy * Copy exception vector code to low memory 471*907208c4SChristophe Leroy * 472*907208c4SChristophe Leroy * r3: dest_addr 473*907208c4SChristophe Leroy * r7: source address, r8: end address, r9: target address 474*907208c4SChristophe Leroy */ 475*907208c4SChristophe Leroy .globl trap_init 476*907208c4SChristophe Leroytrap_init: 477*907208c4SChristophe Leroy mflr r4 /* save link register */ 478*907208c4SChristophe Leroy GET_GOT 479*907208c4SChristophe Leroy lwz r7, GOT(_start) 480*907208c4SChristophe Leroy lwz r8, GOT(_end_of_vectors) 481*907208c4SChristophe Leroy 482*907208c4SChristophe Leroy li r9, 0x100 /* reset vector always at 0x100 */ 483*907208c4SChristophe Leroy 484*907208c4SChristophe Leroy cmplw 0, r7, r8 485*907208c4SChristophe Leroy bgelr /* return if r7>=r8 - just in case */ 486*907208c4SChristophe Leroy1: 487*907208c4SChristophe Leroy lwz r0, 0(r7) 488*907208c4SChristophe Leroy stw r0, 0(r9) 489*907208c4SChristophe Leroy addi r7, r7, 4 490*907208c4SChristophe Leroy addi r9, r9, 4 491*907208c4SChristophe Leroy cmplw 0, r7, r8 492*907208c4SChristophe Leroy bne 1b 493*907208c4SChristophe Leroy 494*907208c4SChristophe Leroy /* 495*907208c4SChristophe Leroy * relocate `hdlr' and `int_return' entries 496*907208c4SChristophe Leroy */ 497*907208c4SChristophe Leroy li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET 498*907208c4SChristophe Leroy li r8, Alignment - _start + EXC_OFF_SYS_RESET 499*907208c4SChristophe Leroy2: 500*907208c4SChristophe Leroy bl trap_reloc 501*907208c4SChristophe Leroy addi r7, r7, 0x100 /* next exception vector */ 502*907208c4SChristophe Leroy cmplw 0, r7, r8 503*907208c4SChristophe Leroy blt 2b 504*907208c4SChristophe Leroy 505*907208c4SChristophe Leroy li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET 506*907208c4SChristophe Leroy bl trap_reloc 507*907208c4SChristophe Leroy 508*907208c4SChristophe Leroy li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET 509*907208c4SChristophe Leroy bl trap_reloc 510*907208c4SChristophe Leroy 511*907208c4SChristophe Leroy li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET 512*907208c4SChristophe Leroy li r8, SystemCall - _start + EXC_OFF_SYS_RESET 513*907208c4SChristophe Leroy3: 514*907208c4SChristophe Leroy bl trap_reloc 515*907208c4SChristophe Leroy addi r7, r7, 0x100 /* next exception vector */ 516*907208c4SChristophe Leroy cmplw 0, r7, r8 517*907208c4SChristophe Leroy blt 3b 518*907208c4SChristophe Leroy 519*907208c4SChristophe Leroy li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET 520*907208c4SChristophe Leroy li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET 521*907208c4SChristophe Leroy4: 522*907208c4SChristophe Leroy bl trap_reloc 523*907208c4SChristophe Leroy addi r7, r7, 0x100 /* next exception vector */ 524*907208c4SChristophe Leroy cmplw 0, r7, r8 525*907208c4SChristophe Leroy blt 4b 526*907208c4SChristophe Leroy 527*907208c4SChristophe Leroy mtlr r4 /* restore link register */ 528*907208c4SChristophe Leroy blr 529