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