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