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