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