b4c5543eb56eb87f469d8d23bd57c8619a124500
[platform/kernel/u-boot.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
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
122 lowboot_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
200 Alignment:
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
211 ProgramCheck:
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          */
254 1:      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
300 transfer_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
322 int_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
360 init_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
450 1:      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
466 icache_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
480 icache_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
493 icache_status:
494         mfspr   r3, HID0
495         rlwinm  r3, r3, HID0_ICE_BITPOS + 1, 31, 31
496         blr
497
498         .globl  dcache_enable
499 dcache_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
513 dcache_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
526 dcache_status:
527         mfspr   r3, HID0
528         rlwinm  r3, r3, HID0_DCE_BITPOS + 1, 31, 31
529         blr
530
531         .globl get_svr
532 get_svr:
533         mfspr   r3, SVR
534         blr
535
536         .globl get_pvr
537 get_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
556 relocate_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)
597 1:      lwzu    r0,4(r8)
598         stwu    r0,4(r7)
599         bdnz    1b
600         b       4f
601
602 2:      slwi    r0,r0,2
603         add     r8,r4,r0
604         add     r7,r3,r0
605 3:      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  */
613 4:      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
623 5:      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 */
628 9:      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
633 6:      icbi    0,r4
634         add     r4,r4,r6
635         cmplw   r4,r5
636         blt     6b
637 7:      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
649 in_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
663 1:      lwzu    r0,4(r3)
664         cmpwi   r0,0
665         beq-    2f
666         add     r0,r0,r11
667         stw     r0,0(r3)
668 2:      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
680 3:      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)
687 5:      bdnz    3b
688 4:
689 clear_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
700 5:
701         stw     r0, 0(r3)
702         addi    r3, r3, 4
703         cmplw   0, r3, r4
704         bne     5b
705 6:
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
718 trap_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 */
728 1:
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
741 2:
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
755 3:
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
763 4:
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 */