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