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