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