Merge branch 'master' of git://git.denx.de/u-boot-x86
[oweals/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 <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(__bss_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 #if defined(__pic__) && __pic__ == 1
278         /* Needed for upcoming -msingle-pic-base */
279         bl      _GLOBAL_OFFSET_TABLE_@local-4
280         mflr    r30
281 #endif
282         /* run low-level CPU init code     (from Flash) */
283         bl      cpu_init_f
284         sync
285
286         /* run 1st part of board init code (from Flash)   */
287         bl      board_init_f
288         sync
289
290         /* NOTREACHED - board_init_f() does not return */
291
292         .globl  invalidate_bats
293 invalidate_bats:
294         /* invalidate BATs */
295         mtspr   IBAT0U, r0
296         mtspr   IBAT1U, r0
297         mtspr   IBAT2U, r0
298         mtspr   IBAT3U, r0
299 #ifdef CONFIG_HIGH_BATS
300         mtspr   IBAT4U, r0
301         mtspr   IBAT5U, r0
302         mtspr   IBAT6U, r0
303         mtspr   IBAT7U, r0
304 #endif
305         isync
306         mtspr   DBAT0U, r0
307         mtspr   DBAT1U, r0
308         mtspr   DBAT2U, r0
309         mtspr   DBAT3U, r0
310 #ifdef CONFIG_HIGH_BATS
311         mtspr   DBAT4U, r0
312         mtspr   DBAT5U, r0
313         mtspr   DBAT6U, r0
314         mtspr   DBAT7U, r0
315 #endif
316         isync
317         sync
318         blr
319
320         /* setup_bats - set them up to some initial state */
321         .globl  setup_bats
322 setup_bats:
323         addis   r0, r0, 0x0000
324
325         /* IBAT 0 */
326         addis   r4, r0, CONFIG_SYS_IBAT0L@h
327         ori     r4, r4, CONFIG_SYS_IBAT0L@l
328         addis   r3, r0, CONFIG_SYS_IBAT0U@h
329         ori     r3, r3, CONFIG_SYS_IBAT0U@l
330         mtspr   IBAT0L, r4
331         mtspr   IBAT0U, r3
332         isync
333
334         /* DBAT 0 */
335         addis   r4, r0, CONFIG_SYS_DBAT0L@h
336         ori     r4, r4, CONFIG_SYS_DBAT0L@l
337         addis   r3, r0, CONFIG_SYS_DBAT0U@h
338         ori     r3, r3, CONFIG_SYS_DBAT0U@l
339         mtspr   DBAT0L, r4
340         mtspr   DBAT0U, r3
341         isync
342
343         /* IBAT 1 */
344         addis   r4, r0, CONFIG_SYS_IBAT1L@h
345         ori     r4, r4, CONFIG_SYS_IBAT1L@l
346         addis   r3, r0, CONFIG_SYS_IBAT1U@h
347         ori     r3, r3, CONFIG_SYS_IBAT1U@l
348         mtspr   IBAT1L, r4
349         mtspr   IBAT1U, r3
350         isync
351
352         /* DBAT 1 */
353         addis   r4, r0, CONFIG_SYS_DBAT1L@h
354         ori     r4, r4, CONFIG_SYS_DBAT1L@l
355         addis   r3, r0, CONFIG_SYS_DBAT1U@h
356         ori     r3, r3, CONFIG_SYS_DBAT1U@l
357         mtspr   DBAT1L, r4
358         mtspr   DBAT1U, r3
359         isync
360
361         /* IBAT 2 */
362         addis   r4, r0, CONFIG_SYS_IBAT2L@h
363         ori     r4, r4, CONFIG_SYS_IBAT2L@l
364         addis   r3, r0, CONFIG_SYS_IBAT2U@h
365         ori     r3, r3, CONFIG_SYS_IBAT2U@l
366         mtspr   IBAT2L, r4
367         mtspr   IBAT2U, r3
368         isync
369
370         /* DBAT 2 */
371         addis   r4, r0, CONFIG_SYS_DBAT2L@h
372         ori     r4, r4, CONFIG_SYS_DBAT2L@l
373         addis   r3, r0, CONFIG_SYS_DBAT2U@h
374         ori     r3, r3, CONFIG_SYS_DBAT2U@l
375         mtspr   DBAT2L, r4
376         mtspr   DBAT2U, r3
377         isync
378
379         /* IBAT 3 */
380         addis   r4, r0, CONFIG_SYS_IBAT3L@h
381         ori     r4, r4, CONFIG_SYS_IBAT3L@l
382         addis   r3, r0, CONFIG_SYS_IBAT3U@h
383         ori     r3, r3, CONFIG_SYS_IBAT3U@l
384         mtspr   IBAT3L, r4
385         mtspr   IBAT3U, r3
386         isync
387
388         /* DBAT 3 */
389         addis   r4, r0, CONFIG_SYS_DBAT3L@h
390         ori     r4, r4, CONFIG_SYS_DBAT3L@l
391         addis   r3, r0, CONFIG_SYS_DBAT3U@h
392         ori     r3, r3, CONFIG_SYS_DBAT3U@l
393         mtspr   DBAT3L, r4
394         mtspr   DBAT3U, r3
395         isync
396
397 #ifdef CONFIG_HIGH_BATS
398         /* IBAT 4 */
399         addis   r4, r0, CONFIG_SYS_IBAT4L@h
400         ori     r4, r4, CONFIG_SYS_IBAT4L@l
401         addis   r3, r0, CONFIG_SYS_IBAT4U@h
402         ori     r3, r3, CONFIG_SYS_IBAT4U@l
403         mtspr   IBAT4L, r4
404         mtspr   IBAT4U, r3
405         isync
406
407         /* DBAT 4 */
408         addis   r4, r0, CONFIG_SYS_DBAT4L@h
409         ori     r4, r4, CONFIG_SYS_DBAT4L@l
410         addis   r3, r0, CONFIG_SYS_DBAT4U@h
411         ori     r3, r3, CONFIG_SYS_DBAT4U@l
412         mtspr   DBAT4L, r4
413         mtspr   DBAT4U, r3
414         isync
415
416         /* IBAT 5 */
417         addis   r4, r0, CONFIG_SYS_IBAT5L@h
418         ori     r4, r4, CONFIG_SYS_IBAT5L@l
419         addis   r3, r0, CONFIG_SYS_IBAT5U@h
420         ori     r3, r3, CONFIG_SYS_IBAT5U@l
421         mtspr   IBAT5L, r4
422         mtspr   IBAT5U, r3
423         isync
424
425         /* DBAT 5 */
426         addis   r4, r0, CONFIG_SYS_DBAT5L@h
427         ori     r4, r4, CONFIG_SYS_DBAT5L@l
428         addis   r3, r0, CONFIG_SYS_DBAT5U@h
429         ori     r3, r3, CONFIG_SYS_DBAT5U@l
430         mtspr   DBAT5L, r4
431         mtspr   DBAT5U, r3
432         isync
433
434         /* IBAT 6 */
435         addis   r4, r0, CONFIG_SYS_IBAT6L@h
436         ori     r4, r4, CONFIG_SYS_IBAT6L@l
437         addis   r3, r0, CONFIG_SYS_IBAT6U@h
438         ori     r3, r3, CONFIG_SYS_IBAT6U@l
439         mtspr   IBAT6L, r4
440         mtspr   IBAT6U, r3
441         isync
442
443         /* DBAT 6 */
444         addis   r4, r0, CONFIG_SYS_DBAT6L@h
445         ori     r4, r4, CONFIG_SYS_DBAT6L@l
446         addis   r3, r0, CONFIG_SYS_DBAT6U@h
447         ori     r3, r3, CONFIG_SYS_DBAT6U@l
448         mtspr   DBAT6L, r4
449         mtspr   DBAT6U, r3
450         isync
451
452         /* IBAT 7 */
453         addis   r4, r0, CONFIG_SYS_IBAT7L@h
454         ori     r4, r4, CONFIG_SYS_IBAT7L@l
455         addis   r3, r0, CONFIG_SYS_IBAT7U@h
456         ori     r3, r3, CONFIG_SYS_IBAT7U@l
457         mtspr   IBAT7L, r4
458         mtspr   IBAT7U, r3
459         isync
460
461         /* DBAT 7 */
462         addis   r4, r0, CONFIG_SYS_DBAT7L@h
463         ori     r4, r4, CONFIG_SYS_DBAT7L@l
464         addis   r3, r0, CONFIG_SYS_DBAT7U@h
465         ori     r3, r3, CONFIG_SYS_DBAT7U@l
466         mtspr   DBAT7L, r4
467         mtspr   DBAT7U, r3
468         isync
469 #endif
470
471         /* bats are done, now invalidate the TLBs */
472
473         addis   r3, 0, 0x0000
474         addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
475
476         isync
477
478 tlblp:
479         tlbie   r3
480         sync
481         addi    r3, r3, 0x1000
482         cmp     0, 0, r3, r5
483         blt tlblp
484
485         blr
486
487         .globl enable_addr_trans
488 enable_addr_trans:
489         /* enable address translation */
490         mfmsr   r5
491         ori     r5, r5, (MSR_IR | MSR_DR)
492         mtmsr   r5
493         isync
494         blr
495
496         .globl disable_addr_trans
497 disable_addr_trans:
498         /* disable address translation */
499         mflr    r4
500         mfmsr   r3
501         andi.   r0, r3, (MSR_IR | MSR_DR)
502         beqlr
503         andc    r3, r3, r0
504         mtspr   SRR0, r4
505         mtspr   SRR1, r3
506         rfi
507
508 /*
509  * This code finishes saving the registers to the exception frame
510  * and jumps to the appropriate handler for the exception.
511  * Register r21 is pointer into trap frame, r1 has new stack pointer.
512  */
513         .globl  transfer_to_handler
514 transfer_to_handler:
515         stw     r22,_NIP(r21)
516         lis     r22,MSR_POW@h
517         andc    r23,r23,r22
518         stw     r23,_MSR(r21)
519         SAVE_GPR(7, r21)
520         SAVE_4GPRS(8, r21)
521         SAVE_8GPRS(12, r21)
522         SAVE_8GPRS(24, r21)
523         mflr    r23
524         andi.   r24,r23,0x3f00          /* get vector offset */
525         stw     r24,TRAP(r21)
526         li      r22,0
527         stw     r22,RESULT(r21)
528         mtspr   SPRG2,r22               /* r1 is now kernel sp */
529         lwz     r24,0(r23)              /* virtual address of handler */
530         lwz     r23,4(r23)              /* where to go when done */
531         mtspr   SRR0,r24
532         mtspr   SRR1,r20
533         mtlr    r23
534         SYNC
535         rfi                             /* jump to handler, enable MMU */
536
537 int_return:
538         mfmsr   r28             /* Disable interrupts */
539         li      r4,0
540         ori     r4,r4,MSR_EE
541         andc    r28,r28,r4
542         SYNC                    /* Some chip revs need this... */
543         mtmsr   r28
544         SYNC
545         lwz     r2,_CTR(r1)
546         lwz     r0,_LINK(r1)
547         mtctr   r2
548         mtlr    r0
549         lwz     r2,_XER(r1)
550         lwz     r0,_CCR(r1)
551         mtspr   XER,r2
552         mtcrf   0xFF,r0
553         REST_10GPRS(3, r1)
554         REST_10GPRS(13, r1)
555         REST_8GPRS(23, r1)
556         REST_GPR(31, r1)
557         lwz     r2,_NIP(r1)     /* Restore environment */
558         lwz     r0,_MSR(r1)
559         mtspr   SRR0,r2
560         mtspr   SRR1,r0
561         lwz     r0,GPR0(r1)
562         lwz     r2,GPR2(r1)
563         lwz     r1,GPR1(r1)
564         SYNC
565         rfi
566
567         .globl  dc_read
568 dc_read:
569         blr
570
571         .globl get_pvr
572 get_pvr:
573         mfspr   r3, PVR
574         blr
575
576 /*-----------------------------------------------------------------------*/
577 /*
578  * void relocate_code (addr_sp, gd, addr_moni)
579  *
580  * This "function" does not return, instead it continues in RAM
581  * after relocating the monitor code.
582  *
583  * r3 = dest
584  * r4 = src
585  * r5 = length in bytes
586  * r6 = cachelinesize
587  */
588         .globl  relocate_code
589 relocate_code:
590         mr      r1,  r3         /* Set new stack pointer                */
591         mr      r9,  r4         /* Save copy of Global Data pointer     */
592         mr      r10, r5         /* Save copy of Destination Address     */
593
594         GET_GOT
595 #if defined(__pic__) && __pic__ == 1
596         /* Needed for upcoming -msingle-pic-base */
597         bl      _GLOBAL_OFFSET_TABLE_@local-4
598         mflr    r30
599 #endif
600         mr      r3,  r5                         /* Destination Address  */
601         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
602         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
603         lwz     r5, GOT(__init_end)
604         sub     r5, r5, r4
605         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
606
607         /*
608          * Fix GOT pointer:
609          *
610          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
611          *
612          * Offset:
613          */
614         sub     r15, r10, r4
615
616         /* First our own GOT */
617         add     r12, r12, r15
618         /* then the one used by the C code */
619         add     r30, r30, r15
620
621         /*
622          * Now relocate code
623          */
624 #ifdef CONFIG_ECC
625         bl      board_relocate_rom
626         sync
627         mr      r3, r10                         /* Destination Address  */
628         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
629         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
630         lwz     r5, GOT(__init_end)
631         sub     r5, r5, r4
632         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
633 #else
634         cmplw   cr1,r3,r4
635         addi    r0,r5,3
636         srwi.   r0,r0,2
637         beq     cr1,4f          /* In place copy is not necessary       */
638         beq     7f              /* Protect against 0 count              */
639         mtctr   r0
640         bge     cr1,2f
641
642         la      r8,-4(r4)
643         la      r7,-4(r3)
644 1:      lwzu    r0,4(r8)
645         stwu    r0,4(r7)
646         bdnz    1b
647         b       4f
648
649 2:      slwi    r0,r0,2
650         add     r8,r4,r0
651         add     r7,r3,r0
652 3:      lwzu    r0,-4(r8)
653         stwu    r0,-4(r7)
654         bdnz    3b
655 #endif
656 /*
657  * Now flush the cache: note that we must start from a cache aligned
658  * address. Otherwise we might miss one cache line.
659  */
660 4:      cmpwi   r6,0
661         add     r5,r3,r5
662         beq     7f              /* Always flush prefetch queue in any case */
663         subi    r0,r6,1
664         andc    r3,r3,r0
665         mr      r4,r3
666 5:      dcbst   0,r4
667         add     r4,r4,r6
668         cmplw   r4,r5
669         blt     5b
670         sync                    /* Wait for all dcbst to complete on bus */
671         mr      r4,r3
672 6:      icbi    0,r4
673         add     r4,r4,r6
674         cmplw   r4,r5
675         blt     6b
676 7:      sync                    /* Wait for all icbi to complete on bus */
677         isync
678
679 /*
680  * We are done. Do not return, instead branch to second part of board
681  * initialization, now running from RAM.
682  */
683         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
684         mtlr    r0
685         blr
686
687 in_ram:
688 #ifdef CONFIG_ECC
689         bl      board_init_ecc
690 #endif
691         /*
692          * Relocation Function, r12 point to got2+0x8000
693          *
694          * Adjust got2 pointers, no need to check for 0, this code
695          * already puts a few entries in the table.
696          */
697         li      r0,__got2_entries@sectoff@l
698         la      r3,GOT(_GOT2_TABLE_)
699         lwz     r11,GOT(_GOT2_TABLE_)
700         mtctr   r0
701         sub     r11,r3,r11
702         addi    r3,r3,-4
703 1:      lwzu    r0,4(r3)
704         cmpwi   r0,0
705         beq-    2f
706         add     r0,r0,r11
707         stw     r0,0(r3)
708 2:      bdnz    1b
709
710         /*
711          * Now adjust the fixups and the pointers to the fixups
712          * in case we need to move ourselves again.
713          */
714         li      r0,__fixup_entries@sectoff@l
715         lwz     r3,GOT(_FIXUP_TABLE_)
716         cmpwi   r0,0
717         mtctr   r0
718         addi    r3,r3,-4
719         beq     4f
720 3:      lwzu    r4,4(r3)
721         lwzux   r0,r4,r11
722         cmpwi   r0,0
723         add     r0,r0,r11
724         stw     r4,0(r3)
725         beq-    5f
726         stw     r0,0(r4)
727 5:      bdnz    3b
728 4:
729 /* clear_bss: */
730         /*
731          * Now clear BSS segment
732          */
733         lwz     r3,GOT(__bss_start)
734         lwz     r4,GOT(__bss_end__)
735
736         cmplw   0, r3, r4
737         beq     6f
738
739         li      r0, 0
740 5:
741         stw     r0, 0(r3)
742         addi    r3, r3, 4
743         cmplw   0, r3, r4
744         bne     5b
745 6:
746         mr      r3, r10         /* Destination Address          */
747 #if defined(CONFIG_DB64360)     || \
748     defined(CONFIG_DB64460)     || \
749     defined(CONFIG_CPCI750)     || \
750     defined(CONFIG_PPMC7XX)     || \
751     defined(CONFIG_P3Mx)
752         mr      r4, r9          /* Use RAM copy of the global data */
753 #endif
754         bl      after_reloc
755
756         /* not reached - end relocate_code */
757 /*-----------------------------------------------------------------------*/
758
759         /*
760          * Copy exception vector code to low memory
761          *
762          * r3: dest_addr
763          * r7: source address, r8: end address, r9: target address
764          */
765         .globl  trap_init
766 trap_init:
767         mflr    r4                      /* save link register           */
768         GET_GOT
769         lwz     r7, GOT(_start)
770         lwz     r8, GOT(_end_of_vectors)
771
772         li      r9, 0x100               /* reset vector always at 0x100 */
773
774         cmplw   0, r7, r8
775         bgelr                           /* return if r7>=r8 - just in case */
776 1:
777         lwz     r0, 0(r7)
778         stw     r0, 0(r9)
779         addi    r7, r7, 4
780         addi    r9, r9, 4
781         cmplw   0, r7, r8
782         bne     1b
783
784         /*
785          * relocate `hdlr' and `int_return' entries
786          */
787         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
788         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
789 2:
790         bl      trap_reloc
791         addi    r7, r7, 0x100           /* next exception vector        */
792         cmplw   0, r7, r8
793         blt     2b
794
795         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
796         bl      trap_reloc
797
798         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
799         bl      trap_reloc
800
801         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
802         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
803 3:
804         bl      trap_reloc
805         addi    r7, r7, 0x100           /* next exception vector        */
806         cmplw   0, r7, r8
807         blt     3b
808
809         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
810         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
811 4:
812         bl      trap_reloc
813         addi    r7, r7, 0x100           /* next exception vector        */
814         cmplw   0, r7, r8
815         blt     4b
816
817         /* enable execptions from RAM vectors */
818         mfmsr   r7
819         li      r8,MSR_IP
820         andc    r7,r7,r8
821         mtmsr   r7
822
823         mtlr    r4                      /* restore link register        */
824         blr
825
826 #ifdef CONFIG_SYS_INIT_RAM_LOCK
827 lock_ram_in_cache:
828         /* Allocate Initial RAM in data cache.
829          */
830         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
831         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
832         li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
833                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
834         mtctr   r4
835 1:
836         dcbz    r0, r3
837         addi    r3, r3, 32
838         bdnz    1b
839
840         /* Lock the data cache */
841         mfspr   r0, HID0
842         ori     r0, r0, 0x1000
843         sync
844         mtspr   HID0, r0
845         sync
846         blr
847
848 .globl unlock_ram_in_cache
849 unlock_ram_in_cache:
850         /* invalidate the INIT_RAM section */
851         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
852         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
853         li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
854                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
855         mtctr   r4
856 1:      icbi    r0, r3
857         addi    r3, r3, 32
858         bdnz    1b
859         sync                    /* Wait for all icbi to complete on bus */
860         isync
861
862         /* Unlock the data cache and invalidate it */
863         mfspr   r0, HID0
864         li      r3,0x1000
865         andc    r0,r0,r3
866         li      r3,0x0400
867         or      r0,r0,r3
868         sync
869         mtspr   HID0, r0
870         sync
871         blr
872 #endif