]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/74xx_7xx/start.S
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / arch / powerpc / cpu / 74xx_7xx / 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,2001,2002 Wolfgang Denk <wd@denx.de>
5  *  Copyright (C) 2001  Josh Huber <huber@mclx.com>
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 /*  U-Boot - Startup Code for PowerPC based Embedded Boards
27  *
28  *
29  *  The processor starts at 0xfff00100 and the code is executed
30  *  from flash. The code is organized to be at an other address
31  *  in memory, but as long we don't jump around before relocating.
32  *  board_init lies at a quite high address and when the cpu has
33  *  jumped there, everything is ok.
34  */
35 #include <asm-offsets.h>
36 #include <config.h>
37 #include <74xx_7xx.h>
38 #include <version.h>
39
40 #include <ppc_asm.tmpl>
41 #include <ppc_defs.h>
42
43 #include <asm/cache.h>
44 #include <asm/mmu.h>
45 #include <asm/u-boot.h>
46
47 #if !defined(CONFIG_DB64360) && \
48     !defined(CONFIG_DB64460) && \
49     !defined(CONFIG_CPCI750) && \
50     !defined(CONFIG_P3Mx)
51 #include <galileo/gt64260R.h>
52 #endif
53
54 /* We don't want the  MMU yet.
55 */
56 #undef  MSR_KERNEL
57 /* Machine Check and Recoverable Interr. */
58 #define MSR_KERNEL ( MSR_ME | MSR_RI )
59
60 /*
61  * Set up GOT: Global Offset Table
62  *
63  * Use r12 to access the GOT
64  */
65         START_GOT
66         GOT_ENTRY(_GOT2_TABLE_)
67         GOT_ENTRY(_FIXUP_TABLE_)
68
69         GOT_ENTRY(_start)
70         GOT_ENTRY(_start_of_vectors)
71         GOT_ENTRY(_end_of_vectors)
72         GOT_ENTRY(transfer_to_handler)
73
74         GOT_ENTRY(__init_end)
75         GOT_ENTRY(__bss_end)
76         GOT_ENTRY(__bss_start)
77         END_GOT
78
79 /*
80  * r3 - 1st arg to board_init(): IMMP pointer
81  * r4 - 2nd arg to board_init(): boot flag
82  */
83         .text
84         .long   0x27051956              /* U-Boot Magic Number          */
85         .globl  version_string
86 version_string:
87         .ascii U_BOOT_VERSION_STRING, "\0"
88
89         . = EXC_OFF_SYS_RESET
90         .globl  _start
91 _start:
92         b       boot_cold
93
94         /* the boot code is located below the exception table */
95
96         .globl  _start_of_vectors
97 _start_of_vectors:
98
99 /* Machine check */
100         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
101
102 /* Data Storage exception.  "Never" generated on the 860. */
103         STD_EXCEPTION(0x300, DataStorage, UnknownException)
104
105 /* Instruction Storage exception.  "Never" generated on the 860. */
106         STD_EXCEPTION(0x400, InstStorage, UnknownException)
107
108 /* External Interrupt exception. */
109         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
110
111 /* Alignment exception. */
112         . = 0x600
113 Alignment:
114         EXCEPTION_PROLOG(SRR0, SRR1)
115         mfspr   r4,DAR
116         stw     r4,_DAR(r21)
117         mfspr   r5,DSISR
118         stw     r5,_DSISR(r21)
119         addi    r3,r1,STACK_FRAME_OVERHEAD
120         EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
121
122 /* Program check exception */
123         . = 0x700
124 ProgramCheck:
125         EXCEPTION_PROLOG(SRR0, SRR1)
126         addi    r3,r1,STACK_FRAME_OVERHEAD
127         EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
128                 MSR_KERNEL, COPY_EE)
129
130         /* No FPU on MPC8xx.  This exception is not supposed to happen.
131         */
132         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
133
134         /* I guess we could implement decrementer, and may have
135          * to someday for timekeeping.
136          */
137         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
138         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
139         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
140         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
141         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
142
143         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
144         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
145
146         /*
147          * On the MPC8xx, this is a software emulation interrupt. It
148          * occurs for all unimplemented and illegal instructions.
149          */
150         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
151
152         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
153         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
154         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
155         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
156
157         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
158         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
159         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
160         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
161         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
162         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
163         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
164
165         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
166         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
167         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
168         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
169
170         .globl  _end_of_vectors
171 _end_of_vectors:
172
173         . = 0x2000
174
175 boot_cold:
176         /* disable everything */
177         li      r0, 0
178         mtspr   HID0, r0
179         sync
180         mtmsr   0
181         bl      invalidate_bats
182         sync
183
184 #ifdef CONFIG_SYS_L2
185         /* init the L2 cache */
186         addis   r3, r0, L2_INIT@h
187         ori     r3, r3, L2_INIT@l
188         sync
189         mtspr   l2cr, r3
190 #endif
191 #if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
192         .long   0x7e00066c
193                 /*
194                  * dssall instruction, gas doesn't have it yet
195                  * ...for altivec, data stream stop all this probably
196                  * isn't needed unless we warm (software) reboot U-Boot
197                  */
198 #endif
199
200 #ifdef CONFIG_SYS_L2
201         /* invalidate the L2 cache */
202         bl      l2cache_invalidate
203         sync
204 #endif
205 #ifdef CONFIG_SYS_BOARD_ASM_INIT
206         /* do early init */
207         bl      board_asm_init
208 #endif
209
210         /*
211          * Calculate absolute address in FLASH and jump there
212          *------------------------------------------------------*/
213         lis     r3, CONFIG_SYS_MONITOR_BASE@h
214         ori     r3, r3, CONFIG_SYS_MONITOR_BASE@l
215         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
216         mtlr    r3
217         blr
218
219 in_flash:
220         /* let the C-code set up the rest                       */
221         /*                                                      */
222         /* Be careful to keep code relocatable !                */
223         /*------------------------------------------------------*/
224
225         /* perform low-level init */
226         /* sdram init, galileo init, etc */
227         /* r3:  NHR bit from HID0 */
228
229         /* setup the bats */
230         bl      setup_bats
231         sync
232
233         /*
234          * Cache must be enabled here for stack-in-cache trick.
235          * This means we need to enable the BATS.
236          * This means:
237          *   1) for the EVB, original gt regs need to be mapped
238          *   2) need to have an IBAT for the 0xf region,
239          *      we are running there!
240          * Cache should be turned on after BATs, since by default
241          * everything is write-through.
242          * The init-mem BAT can be reused after reloc. The old
243          * gt-regs BAT can be reused after board_init_f calls
244          * board_early_init_f (EVB only).
245          */
246 #if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC) && !defined(CONFIG_P3Mx)
247         /* enable address translation */
248         bl      enable_addr_trans
249         sync
250
251         /* enable and invalidate the data cache */
252         bl      l1dcache_enable
253         sync
254 #endif
255 #ifdef CONFIG_SYS_INIT_RAM_LOCK
256         bl      lock_ram_in_cache
257         sync
258 #endif
259
260         /* set up the stack pointer in our newly created
261          * cache-ram (r1) */
262         lis     r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
263         ori     r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
264
265         li      r0, 0           /* Make room for stack frame header and */
266         stwu    r0, -4(r1)      /* clear final stack frame so that      */
267         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
268
269         GET_GOT                 /* initialize GOT access        */
270
271         /* run low-level CPU init code     (from Flash) */
272         bl      cpu_init_f
273         sync
274
275         /* run 1st part of board init code (from Flash)   */
276         bl      board_init_f
277         sync
278
279         /* NOTREACHED - board_init_f() does not return */
280
281         .globl  invalidate_bats
282 invalidate_bats:
283         /* invalidate BATs */
284         mtspr   IBAT0U, r0
285         mtspr   IBAT1U, r0
286         mtspr   IBAT2U, r0
287         mtspr   IBAT3U, r0
288 #ifdef CONFIG_HIGH_BATS
289         mtspr   IBAT4U, r0
290         mtspr   IBAT5U, r0
291         mtspr   IBAT6U, r0
292         mtspr   IBAT7U, r0
293 #endif
294         isync
295         mtspr   DBAT0U, r0
296         mtspr   DBAT1U, r0
297         mtspr   DBAT2U, r0
298         mtspr   DBAT3U, r0
299 #ifdef CONFIG_HIGH_BATS
300         mtspr   DBAT4U, r0
301         mtspr   DBAT5U, r0
302         mtspr   DBAT6U, r0
303         mtspr   DBAT7U, r0
304 #endif
305         isync
306         sync
307         blr
308
309         /* setup_bats - set them up to some initial state */
310         .globl  setup_bats
311 setup_bats:
312         addis   r0, r0, 0x0000
313
314         /* IBAT 0 */
315         addis   r4, r0, CONFIG_SYS_IBAT0L@h
316         ori     r4, r4, CONFIG_SYS_IBAT0L@l
317         addis   r3, r0, CONFIG_SYS_IBAT0U@h
318         ori     r3, r3, CONFIG_SYS_IBAT0U@l
319         mtspr   IBAT0L, r4
320         mtspr   IBAT0U, r3
321         isync
322
323         /* DBAT 0 */
324         addis   r4, r0, CONFIG_SYS_DBAT0L@h
325         ori     r4, r4, CONFIG_SYS_DBAT0L@l
326         addis   r3, r0, CONFIG_SYS_DBAT0U@h
327         ori     r3, r3, CONFIG_SYS_DBAT0U@l
328         mtspr   DBAT0L, r4
329         mtspr   DBAT0U, r3
330         isync
331
332         /* IBAT 1 */
333         addis   r4, r0, CONFIG_SYS_IBAT1L@h
334         ori     r4, r4, CONFIG_SYS_IBAT1L@l
335         addis   r3, r0, CONFIG_SYS_IBAT1U@h
336         ori     r3, r3, CONFIG_SYS_IBAT1U@l
337         mtspr   IBAT1L, r4
338         mtspr   IBAT1U, r3
339         isync
340
341         /* DBAT 1 */
342         addis   r4, r0, CONFIG_SYS_DBAT1L@h
343         ori     r4, r4, CONFIG_SYS_DBAT1L@l
344         addis   r3, r0, CONFIG_SYS_DBAT1U@h
345         ori     r3, r3, CONFIG_SYS_DBAT1U@l
346         mtspr   DBAT1L, r4
347         mtspr   DBAT1U, r3
348         isync
349
350         /* IBAT 2 */
351         addis   r4, r0, CONFIG_SYS_IBAT2L@h
352         ori     r4, r4, CONFIG_SYS_IBAT2L@l
353         addis   r3, r0, CONFIG_SYS_IBAT2U@h
354         ori     r3, r3, CONFIG_SYS_IBAT2U@l
355         mtspr   IBAT2L, r4
356         mtspr   IBAT2U, r3
357         isync
358
359         /* DBAT 2 */
360         addis   r4, r0, CONFIG_SYS_DBAT2L@h
361         ori     r4, r4, CONFIG_SYS_DBAT2L@l
362         addis   r3, r0, CONFIG_SYS_DBAT2U@h
363         ori     r3, r3, CONFIG_SYS_DBAT2U@l
364         mtspr   DBAT2L, r4
365         mtspr   DBAT2U, r3
366         isync
367
368         /* IBAT 3 */
369         addis   r4, r0, CONFIG_SYS_IBAT3L@h
370         ori     r4, r4, CONFIG_SYS_IBAT3L@l
371         addis   r3, r0, CONFIG_SYS_IBAT3U@h
372         ori     r3, r3, CONFIG_SYS_IBAT3U@l
373         mtspr   IBAT3L, r4
374         mtspr   IBAT3U, r3
375         isync
376
377         /* DBAT 3 */
378         addis   r4, r0, CONFIG_SYS_DBAT3L@h
379         ori     r4, r4, CONFIG_SYS_DBAT3L@l
380         addis   r3, r0, CONFIG_SYS_DBAT3U@h
381         ori     r3, r3, CONFIG_SYS_DBAT3U@l
382         mtspr   DBAT3L, r4
383         mtspr   DBAT3U, r3
384         isync
385
386 #ifdef CONFIG_HIGH_BATS
387         /* IBAT 4 */
388         addis   r4, r0, CONFIG_SYS_IBAT4L@h
389         ori     r4, r4, CONFIG_SYS_IBAT4L@l
390         addis   r3, r0, CONFIG_SYS_IBAT4U@h
391         ori     r3, r3, CONFIG_SYS_IBAT4U@l
392         mtspr   IBAT4L, r4
393         mtspr   IBAT4U, r3
394         isync
395
396         /* DBAT 4 */
397         addis   r4, r0, CONFIG_SYS_DBAT4L@h
398         ori     r4, r4, CONFIG_SYS_DBAT4L@l
399         addis   r3, r0, CONFIG_SYS_DBAT4U@h
400         ori     r3, r3, CONFIG_SYS_DBAT4U@l
401         mtspr   DBAT4L, r4
402         mtspr   DBAT4U, r3
403         isync
404
405         /* IBAT 5 */
406         addis   r4, r0, CONFIG_SYS_IBAT5L@h
407         ori     r4, r4, CONFIG_SYS_IBAT5L@l
408         addis   r3, r0, CONFIG_SYS_IBAT5U@h
409         ori     r3, r3, CONFIG_SYS_IBAT5U@l
410         mtspr   IBAT5L, r4
411         mtspr   IBAT5U, r3
412         isync
413
414         /* DBAT 5 */
415         addis   r4, r0, CONFIG_SYS_DBAT5L@h
416         ori     r4, r4, CONFIG_SYS_DBAT5L@l
417         addis   r3, r0, CONFIG_SYS_DBAT5U@h
418         ori     r3, r3, CONFIG_SYS_DBAT5U@l
419         mtspr   DBAT5L, r4
420         mtspr   DBAT5U, r3
421         isync
422
423         /* IBAT 6 */
424         addis   r4, r0, CONFIG_SYS_IBAT6L@h
425         ori     r4, r4, CONFIG_SYS_IBAT6L@l
426         addis   r3, r0, CONFIG_SYS_IBAT6U@h
427         ori     r3, r3, CONFIG_SYS_IBAT6U@l
428         mtspr   IBAT6L, r4
429         mtspr   IBAT6U, r3
430         isync
431
432         /* DBAT 6 */
433         addis   r4, r0, CONFIG_SYS_DBAT6L@h
434         ori     r4, r4, CONFIG_SYS_DBAT6L@l
435         addis   r3, r0, CONFIG_SYS_DBAT6U@h
436         ori     r3, r3, CONFIG_SYS_DBAT6U@l
437         mtspr   DBAT6L, r4
438         mtspr   DBAT6U, r3
439         isync
440
441         /* IBAT 7 */
442         addis   r4, r0, CONFIG_SYS_IBAT7L@h
443         ori     r4, r4, CONFIG_SYS_IBAT7L@l
444         addis   r3, r0, CONFIG_SYS_IBAT7U@h
445         ori     r3, r3, CONFIG_SYS_IBAT7U@l
446         mtspr   IBAT7L, r4
447         mtspr   IBAT7U, r3
448         isync
449
450         /* DBAT 7 */
451         addis   r4, r0, CONFIG_SYS_DBAT7L@h
452         ori     r4, r4, CONFIG_SYS_DBAT7L@l
453         addis   r3, r0, CONFIG_SYS_DBAT7U@h
454         ori     r3, r3, CONFIG_SYS_DBAT7U@l
455         mtspr   DBAT7L, r4
456         mtspr   DBAT7U, r3
457         isync
458 #endif
459
460         /* bats are done, now invalidate the TLBs */
461
462         addis   r3, 0, 0x0000
463         addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
464
465         isync
466
467 tlblp:
468         tlbie   r3
469         sync
470         addi    r3, r3, 0x1000
471         cmp     0, 0, r3, r5
472         blt tlblp
473
474         blr
475
476         .globl enable_addr_trans
477 enable_addr_trans:
478         /* enable address translation */
479         mfmsr   r5
480         ori     r5, r5, (MSR_IR | MSR_DR)
481         mtmsr   r5
482         isync
483         blr
484
485         .globl disable_addr_trans
486 disable_addr_trans:
487         /* disable address translation */
488         mflr    r4
489         mfmsr   r3
490         andi.   r0, r3, (MSR_IR | MSR_DR)
491         beqlr
492         andc    r3, r3, r0
493         mtspr   SRR0, r4
494         mtspr   SRR1, r3
495         rfi
496
497 /*
498  * This code finishes saving the registers to the exception frame
499  * and jumps to the appropriate handler for the exception.
500  * Register r21 is pointer into trap frame, r1 has new stack pointer.
501  */
502         .globl  transfer_to_handler
503 transfer_to_handler:
504         stw     r22,_NIP(r21)
505         lis     r22,MSR_POW@h
506         andc    r23,r23,r22
507         stw     r23,_MSR(r21)
508         SAVE_GPR(7, r21)
509         SAVE_4GPRS(8, r21)
510         SAVE_8GPRS(12, r21)
511         SAVE_8GPRS(24, r21)
512         mflr    r23
513         andi.   r24,r23,0x3f00          /* get vector offset */
514         stw     r24,TRAP(r21)
515         li      r22,0
516         stw     r22,RESULT(r21)
517         mtspr   SPRG2,r22               /* r1 is now kernel sp */
518         lwz     r24,0(r23)              /* virtual address of handler */
519         lwz     r23,4(r23)              /* where to go when done */
520         mtspr   SRR0,r24
521         mtspr   SRR1,r20
522         mtlr    r23
523         SYNC
524         rfi                             /* jump to handler, enable MMU */
525
526 int_return:
527         mfmsr   r28             /* Disable interrupts */
528         li      r4,0
529         ori     r4,r4,MSR_EE
530         andc    r28,r28,r4
531         SYNC                    /* Some chip revs need this... */
532         mtmsr   r28
533         SYNC
534         lwz     r2,_CTR(r1)
535         lwz     r0,_LINK(r1)
536         mtctr   r2
537         mtlr    r0
538         lwz     r2,_XER(r1)
539         lwz     r0,_CCR(r1)
540         mtspr   XER,r2
541         mtcrf   0xFF,r0
542         REST_10GPRS(3, r1)
543         REST_10GPRS(13, r1)
544         REST_8GPRS(23, r1)
545         REST_GPR(31, r1)
546         lwz     r2,_NIP(r1)     /* Restore environment */
547         lwz     r0,_MSR(r1)
548         mtspr   SRR0,r2
549         mtspr   SRR1,r0
550         lwz     r0,GPR0(r1)
551         lwz     r2,GPR2(r1)
552         lwz     r1,GPR1(r1)
553         SYNC
554         rfi
555
556         .globl  dc_read
557 dc_read:
558         blr
559
560         .globl get_pvr
561 get_pvr:
562         mfspr   r3, PVR
563         blr
564
565 /*-----------------------------------------------------------------------*/
566 /*
567  * void relocate_code (addr_sp, gd, addr_moni)
568  *
569  * This "function" does not return, instead it continues in RAM
570  * after relocating the monitor code.
571  *
572  * r3 = dest
573  * r4 = src
574  * r5 = length in bytes
575  * r6 = cachelinesize
576  */
577         .globl  relocate_code
578 relocate_code:
579         mr      r1,  r3         /* Set new stack pointer                */
580         mr      r9,  r4         /* Save copy of Global Data pointer     */
581         mr      r10, r5         /* Save copy of Destination Address     */
582
583         GET_GOT
584         mr      r3,  r5                         /* Destination Address  */
585         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
586         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
587         lwz     r5, GOT(__init_end)
588         sub     r5, r5, r4
589         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
590
591         /*
592          * Fix GOT pointer:
593          *
594          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
595          *
596          * Offset:
597          */
598         sub     r15, r10, r4
599
600         /* First our own GOT */
601         add     r12, r12, r15
602         /* then the one used by the C code */
603         add     r30, r30, r15
604
605         /*
606          * Now relocate code
607          */
608 #ifdef CONFIG_ECC
609         bl      board_relocate_rom
610         sync
611         mr      r3, r10                         /* Destination Address  */
612         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
613         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
614         lwz     r5, GOT(__init_end)
615         sub     r5, r5, r4
616         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
617 #else
618         cmplw   cr1,r3,r4
619         addi    r0,r5,3
620         srwi.   r0,r0,2
621         beq     cr1,4f          /* In place copy is not necessary       */
622         beq     7f              /* Protect against 0 count              */
623         mtctr   r0
624         bge     cr1,2f
625
626         la      r8,-4(r4)
627         la      r7,-4(r3)
628 1:      lwzu    r0,4(r8)
629         stwu    r0,4(r7)
630         bdnz    1b
631         b       4f
632
633 2:      slwi    r0,r0,2
634         add     r8,r4,r0
635         add     r7,r3,r0
636 3:      lwzu    r0,-4(r8)
637         stwu    r0,-4(r7)
638         bdnz    3b
639 #endif
640 /*
641  * Now flush the cache: note that we must start from a cache aligned
642  * address. Otherwise we might miss one cache line.
643  */
644 4:      cmpwi   r6,0
645         add     r5,r3,r5
646         beq     7f              /* Always flush prefetch queue in any case */
647         subi    r0,r6,1
648         andc    r3,r3,r0
649         mr      r4,r3
650 5:      dcbst   0,r4
651         add     r4,r4,r6
652         cmplw   r4,r5
653         blt     5b
654         sync                    /* Wait for all dcbst to complete on bus */
655         mr      r4,r3
656 6:      icbi    0,r4
657         add     r4,r4,r6
658         cmplw   r4,r5
659         blt     6b
660 7:      sync                    /* Wait for all icbi to complete on bus */
661         isync
662
663 /*
664  * We are done. Do not return, instead branch to second part of board
665  * initialization, now running from RAM.
666  */
667         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
668         mtlr    r0
669         blr
670
671 in_ram:
672 #ifdef CONFIG_ECC
673         bl      board_init_ecc
674 #endif
675         /*
676          * Relocation Function, r12 point to got2+0x8000
677          *
678          * Adjust got2 pointers, no need to check for 0, this code
679          * already puts a few entries in the table.
680          */
681         li      r0,__got2_entries@sectoff@l
682         la      r3,GOT(_GOT2_TABLE_)
683         lwz     r11,GOT(_GOT2_TABLE_)
684         mtctr   r0
685         sub     r11,r3,r11
686         addi    r3,r3,-4
687 1:      lwzu    r0,4(r3)
688         cmpwi   r0,0
689         beq-    2f
690         add     r0,r0,r11
691         stw     r0,0(r3)
692 2:      bdnz    1b
693
694         /*
695          * Now adjust the fixups and the pointers to the fixups
696          * in case we need to move ourselves again.
697          */
698         li      r0,__fixup_entries@sectoff@l
699         lwz     r3,GOT(_FIXUP_TABLE_)
700         cmpwi   r0,0
701         mtctr   r0
702         addi    r3,r3,-4
703         beq     4f
704 3:      lwzu    r4,4(r3)
705         lwzux   r0,r4,r11
706         cmpwi   r0,0
707         add     r0,r0,r11
708         stw     r4,0(r3)
709         beq-    5f
710         stw     r0,0(r4)
711 5:      bdnz    3b
712 4:
713 /* clear_bss: */
714         /*
715          * Now clear BSS segment
716          */
717         lwz     r3,GOT(__bss_start)
718         lwz     r4,GOT(__bss_end)
719
720         cmplw   0, r3, r4
721         beq     6f
722
723         li      r0, 0
724 5:
725         stw     r0, 0(r3)
726         addi    r3, r3, 4
727         cmplw   0, r3, r4
728         bne     5b
729 6:
730         mr      r3, r10         /* Destination Address          */
731 #if defined(CONFIG_DB64360)     || \
732     defined(CONFIG_DB64460)     || \
733     defined(CONFIG_CPCI750)     || \
734     defined(CONFIG_PPMC7XX)     || \
735     defined(CONFIG_P3Mx)
736         mr      r4, r9          /* Use RAM copy of the global data */
737 #endif
738         bl      after_reloc
739
740         /* not reached - end relocate_code */
741 /*-----------------------------------------------------------------------*/
742
743         /*
744          * Copy exception vector code to low memory
745          *
746          * r3: dest_addr
747          * r7: source address, r8: end address, r9: target address
748          */
749         .globl  trap_init
750 trap_init:
751         mflr    r4                      /* save link register           */
752         GET_GOT
753         lwz     r7, GOT(_start)
754         lwz     r8, GOT(_end_of_vectors)
755
756         li      r9, 0x100               /* reset vector always at 0x100 */
757
758         cmplw   0, r7, r8
759         bgelr                           /* return if r7>=r8 - just in case */
760 1:
761         lwz     r0, 0(r7)
762         stw     r0, 0(r9)
763         addi    r7, r7, 4
764         addi    r9, r9, 4
765         cmplw   0, r7, r8
766         bne     1b
767
768         /*
769          * relocate `hdlr' and `int_return' entries
770          */
771         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
772         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
773 2:
774         bl      trap_reloc
775         addi    r7, r7, 0x100           /* next exception vector        */
776         cmplw   0, r7, r8
777         blt     2b
778
779         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
780         bl      trap_reloc
781
782         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
783         bl      trap_reloc
784
785         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
786         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
787 3:
788         bl      trap_reloc
789         addi    r7, r7, 0x100           /* next exception vector        */
790         cmplw   0, r7, r8
791         blt     3b
792
793         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
794         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
795 4:
796         bl      trap_reloc
797         addi    r7, r7, 0x100           /* next exception vector        */
798         cmplw   0, r7, r8
799         blt     4b
800
801         /* enable execptions from RAM vectors */
802         mfmsr   r7
803         li      r8,MSR_IP
804         andc    r7,r7,r8
805         mtmsr   r7
806
807         mtlr    r4                      /* restore link register        */
808         blr
809
810 #ifdef CONFIG_SYS_INIT_RAM_LOCK
811 lock_ram_in_cache:
812         /* Allocate Initial RAM in data cache.
813          */
814         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
815         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
816         li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
817                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
818         mtctr   r4
819 1:
820         dcbz    r0, r3
821         addi    r3, r3, 32
822         bdnz    1b
823
824         /* Lock the data cache */
825         mfspr   r0, HID0
826         ori     r0, r0, 0x1000
827         sync
828         mtspr   HID0, r0
829         sync
830         blr
831
832 .globl unlock_ram_in_cache
833 unlock_ram_in_cache:
834         /* invalidate the INIT_RAM section */
835         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
836         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
837         li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
838                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
839         mtctr   r4
840 1:      icbi    r0, r3
841         addi    r3, r3, 32
842         bdnz    1b
843         sync                    /* Wait for all icbi to complete on bus */
844         isync
845
846         /* Unlock the data cache and invalidate it */
847         mfspr   r0, HID0
848         li      r3,0x1000
849         andc    r0,r0,r3
850         li      r3,0x0400
851         or      r0,r0,r3
852         sync
853         mtspr   HID0, r0
854         sync
855         blr
856 #endif