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