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