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