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