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