e9f07901b8908fb3e35f7daeee7e44d1d497a6c4
[oweals/u-boot.git] / cpu / mpc83xx / 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 2004 Freescale Semiconductor, Inc.
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 /*
27  *  U-Boot - Startup Code for MPC83xx PowerPC based Embedded Boards
28  */
29
30 #include <config.h>
31 #include <mpc83xx.h> 
32 #include <version.h>
33
34 #define CONFIG_83XX     1               /* needed for Linux kernel header files*/
35 #define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file */
36
37 #include <ppc_asm.tmpl>
38 #include <ppc_defs.h>
39
40 #include <asm/cache.h>
41 #include <asm/mmu.h>
42
43 #ifndef  CONFIG_IDENT_STRING
44 #define  CONFIG_IDENT_STRING "MPC83XX"
45 #endif
46
47 /* We don't want the  MMU yet.
48  */
49 #undef  MSR_KERNEL
50
51 /*
52  * Floating Point enable, Machine Check and Recoverable Interr.
53  */
54 #ifdef DEBUG
55 #define MSR_KERNEL (MSR_FP|MSR_RI)
56 #else
57 #define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
58 #endif
59
60 /*
61  * Set up GOT: Global Offset Table
62  *
63  * Use r14 to access the GOT
64  */
65         START_GOT
66         GOT_ENTRY(_GOT2_TABLE_)
67         GOT_ENTRY(_FIXUP_TABLE_)
68
69         GOT_ENTRY(_start)
70         GOT_ENTRY(_start_of_vectors)
71         GOT_ENTRY(_end_of_vectors)
72         GOT_ENTRY(transfer_to_handler)
73
74         GOT_ENTRY(__init_end)
75         GOT_ENTRY(_end)
76         GOT_ENTRY(__bss_start)
77         END_GOT
78
79 /*
80  * Version string - must be in data segment because MPC83xx uses the
81  * first 256 bytes for the Hard Reset Configuration Word table (see
82  * below).  Similarly, can't have the U-Boot Magic Number as the first
83  * thing in the image - don't know how this will affect the image tools,
84  * but I guess I'll find out soon.
85  */
86         .data
87         .globl  version_string
88 version_string:
89         .ascii U_BOOT_VERSION
90         .ascii " (", __DATE__, " - ", __TIME__, ")"
91         .ascii " ", CONFIG_IDENT_STRING, "\0"
92         
93         .text
94 #define _HRCW_TABLE_ENTRY(w)            \
95         .fill   8,1,(((w)>>24)&0xff);   \
96         .fill   8,1,(((w)>>16)&0xff);   \
97         .fill   8,1,(((w)>> 8)&0xff);   \
98         .fill   8,1,(((w)    )&0xff)
99
100         _HRCW_TABLE_ENTRY(CFG_HRCW_LOW)
101         _HRCW_TABLE_ENTRY(CFG_HRCW_HIGH)
102
103
104         
105 #ifndef CONFIG_DEFAULT_IMMR
106 #error CONFIG_DEFAULT_IMMR must be defined
107 #endif /* CFG_DEFAULT_IMMR */
108 #ifndef CFG_IMMRBAR
109 #define CFG_IMMRBAR CONFIG_DEFAULT_IMMR
110 #endif /* CFG_IMMRBAR */
111
112 /*
113  * After configuration, a system reset exception is executed using the
114  * vector at offset 0x100 relative to the base set by MSR[IP]. If
115  * MSR[IP] is 0, the base address is 0x00000000. If MSR[IP] is 1, the
116  * base address is 0xfff00000. In the case of a Power On Reset or Hard
117  * Reset, the value of MSR[IP] is determined by the CIP field in the
118  * HRCW.
119  *
120  * Other bits in the HRCW set up the Base Address and Port Size in BR0.
121  * This determines the location of the boot ROM (flash or EPROM) in the
122  * processor's address space at boot time. As long as the HRCW is set up
123  * so that we eventually end up executing the code below when the
124  * processor executes the reset exception, the actual values used should
125  * not matter.
126  *
127  * Once we have got here, the address mask in OR0 is cleared so that the
128  * bottom 32K of the boot ROM is effectively repeated all throughout the
129  * processor's address space, after which we can jump to the absolute
130  * address at which the boot ROM was linked at compile time, and proceed
131  * to initialise the memory controller without worrying if the rug will
132  * be pulled out from under us, so to speak (it will be fine as long as
133  * we configure BR0 with the same boot ROM link address).
134  */
135         . = EXC_OFF_SYS_RESET
136
137         .globl  _start
138 _start: /* time t 0 */
139         li      r21, BOOTFLAG_COLD  /* Normal Power-On: Boot from FLASH*/
140         nop
141         b       boot_cold
142
143         . = EXC_OFF_SYS_RESET + 0x10
144
145         .globl  _start_warm
146 _start_warm: 
147         li      r21, BOOTFLAG_WARM      /* Software reboot      */
148         b       boot_warm
149
150
151 boot_cold: /* time t 3 */
152         lis     r4, CONFIG_DEFAULT_IMMR@h
153         nop
154 boot_warm: /* time t 5 */
155         mfmsr   r5                      /* save msr contents    */
156         lis     r3, CFG_IMMRBAR@h
157         ori     r3, r3, CFG_IMMRBAR@l
158         stw     r3, IMMRBAR(r4)
159         
160         /* Initialise the E300 processor core           */
161         /*------------------------------------------*/
162         
163         bl      init_e300_core
164         
165 #ifndef CFG_RAMBOOT
166
167         /* Inflate flash location so it appears everywhere, calculate */
168         /* the absolute address in final location of the FLASH, jump  */
169         /* there and deflate the flash size back to minimal size      */
170         /*------------------------------------------------------------*/
171         bl map_flash_by_law1
172         lis r4, (CFG_MONITOR_BASE)@h
173         ori r4, r4, (CFG_MONITOR_BASE)@l
174         addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
175         mtlr r5
176         blr
177 in_flash:
178 #if 1 /* Remapping flash with LAW0. */
179         bl remap_flash_by_law0
180 #endif
181 #endif  /* CFG_RAMBOOT */
182
183         bl setup_stack_in_data_cache_on_r1
184
185         /* let the C-code set up the rest                           */
186         /*                                                                                  */
187         /* Be careful to keep code relocatable & stack humble   */
188         /*------------------------------------------------------*/
189
190         GET_GOT                 /* initialize GOT access        */
191
192         /* r3: IMMR */
193         lis     r3, CFG_IMMRBAR@h
194         /* run low-level CPU init code (in Flash)*/
195         bl      cpu_init_f
196
197         /* r3: BOOTFLAG */
198         mr      r3, r21
199         /* run 1st part of board init code (in Flash)*/
200         bl      board_init_f
201
202 /*
203  * Vector Table
204  */
205
206         .globl  _start_of_vectors
207 _start_of_vectors:
208
209 /* Machine check */
210         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
211
212 /* Data Storage exception. */
213         STD_EXCEPTION(0x300, DataStorage, UnknownException)
214
215 /* Instruction Storage exception. */
216         STD_EXCEPTION(0x400, InstStorage, UnknownException)
217
218 /* External Interrupt exception. */
219 #ifndef FIXME
220         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
221 #endif  
222
223 /* Alignment exception. */
224         . = 0x600
225 Alignment:
226         EXCEPTION_PROLOG
227         mfspr   r4,DAR
228         stw     r4,_DAR(r21)
229         mfspr   r5,DSISR
230         stw     r5,_DSISR(r21)
231         addi    r3,r1,STACK_FRAME_OVERHEAD
232         li      r20,MSR_KERNEL
233         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
234         rlwimi  r20,r23,0,25,25         /* copy IP bit from saved MSR */
235         lwz     r6,GOT(transfer_to_handler)
236         mtlr    r6
237         blrl
238 .L_Alignment:
239         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
240         .long   int_return - _start + EXC_OFF_SYS_RESET
241
242 /* Program check exception */
243         . = 0x700
244 ProgramCheck:
245         EXCEPTION_PROLOG
246         addi    r3,r1,STACK_FRAME_OVERHEAD
247         li      r20,MSR_KERNEL
248         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
249         rlwimi  r20,r23,0,25,25         /* copy IP bit from saved MSR */
250         lwz     r6,GOT(transfer_to_handler)
251         mtlr    r6
252         blrl
253 .L_ProgramCheck:
254         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
255         .long   int_return - _start + EXC_OFF_SYS_RESET
256
257         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
258
259         /* I guess we could implement decrementer, and may have
260          * to someday for timekeeping.
261          */
262         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
263
264         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
265         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
266         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
267         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
268
269         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
270         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
271
272         STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
273         STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
274         STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
275 #ifdef DEBUG
276         . = 0x1300
277         /*
278          * This exception occurs when the program counter matches the
279          * Instruction Address Breakpoint Register (IABR).
280          *
281          * I want the cpu to halt if this occurs so I can hunt around
282          * with the debugger and look at things.
283          *
284          * When DEBUG is defined, both machine check enable (in the MSR)
285          * and checkstop reset enable (in the reset mode register) are
286          * turned off and so a checkstop condition will result in the cpu
287          * halting.
288          *
289          * I force the cpu into a checkstop condition by putting an illegal
290          * instruction here (at least this is the theory).
291          *
292          * well - that didnt work, so just do an infinite loop!
293          */
294 1:      b       1b
295 #else
296         STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
297 #endif
298         STD_EXCEPTION(0x1400, SMI, UnknownException)
299
300         STD_EXCEPTION(0x1500, Trap_15, UnknownException)
301         STD_EXCEPTION(0x1600, Trap_16, UnknownException)
302         STD_EXCEPTION(0x1700, Trap_17, UnknownException)
303         STD_EXCEPTION(0x1800, Trap_18, UnknownException)
304         STD_EXCEPTION(0x1900, Trap_19, UnknownException)
305         STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
306         STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
307         STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
308         STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
309         STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
310         STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
311         STD_EXCEPTION(0x2000, Trap_20, UnknownException)
312         STD_EXCEPTION(0x2100, Trap_21, UnknownException)
313         STD_EXCEPTION(0x2200, Trap_22, UnknownException)
314         STD_EXCEPTION(0x2300, Trap_23, UnknownException)
315         STD_EXCEPTION(0x2400, Trap_24, UnknownException)
316         STD_EXCEPTION(0x2500, Trap_25, UnknownException)
317         STD_EXCEPTION(0x2600, Trap_26, UnknownException)
318         STD_EXCEPTION(0x2700, Trap_27, UnknownException)
319         STD_EXCEPTION(0x2800, Trap_28, UnknownException)
320         STD_EXCEPTION(0x2900, Trap_29, UnknownException)
321         STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
322         STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
323         STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
324         STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
325         STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
326         STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
327
328
329         .globl  _end_of_vectors
330 _end_of_vectors:
331
332         . = 0x3000
333
334 /*
335  * This code finishes saving the registers to the exception frame
336  * and jumps to the appropriate handler for the exception.
337  * Register r21 is pointer into trap frame, r1 has new stack pointer.
338  */
339         .globl  transfer_to_handler
340 transfer_to_handler:
341         stw     r22,_NIP(r21)
342         lis     r22,MSR_POW@h
343         andc    r23,r23,r22
344         stw     r23,_MSR(r21)
345         SAVE_GPR(7, r21)
346         SAVE_4GPRS(8, r21)
347         SAVE_8GPRS(12, r21)
348         SAVE_8GPRS(24, r21)
349         mflr    r23
350         andi.   r24,r23,0x3f00          /* get vector offset */
351         stw     r24,TRAP(r21)
352         li      r22,0
353         stw     r22,RESULT(r21)
354         lwz     r24,0(r23)              /* virtual address of handler */
355         lwz     r23,4(r23)              /* where to go when done */
356         mtspr   SRR0,r24
357         mtspr   SRR1,r20
358         mtlr    r23
359         SYNC
360         rfi                             /* jump to handler, enable MMU */
361
362 int_return:
363         mfmsr   r28             /* Disable interrupts */
364         li      r4,0
365         ori     r4,r4,MSR_EE
366         andc    r28,r28,r4
367         SYNC                    /* Some chip revs need this... */
368         mtmsr   r28
369         SYNC
370         lwz     r2,_CTR(r1)
371         lwz     r0,_LINK(r1)
372         mtctr   r2
373         mtlr    r0
374         lwz     r2,_XER(r1)
375         lwz     r0,_CCR(r1)
376         mtspr   XER,r2
377         mtcrf   0xFF,r0
378         REST_10GPRS(3, r1)
379         REST_10GPRS(13, r1)
380         REST_8GPRS(23, r1)
381         REST_GPR(31, r1)
382         lwz     r2,_NIP(r1)     /* Restore environment */
383         lwz     r0,_MSR(r1)
384         mtspr   SRR0,r2
385         mtspr   SRR1,r0
386         lwz     r0,GPR0(r1)
387         lwz     r2,GPR2(r1)
388         lwz     r1,GPR1(r1)
389         SYNC
390         rfi
391
392 /*
393  * This code initialises the E300 processor core
394  * (conforms to PowerPC 603e spec)
395  * Note: expects original MSR contents to be in r5.
396  */
397         .globl  init_e300_core
398 init_e300_core: /* time t 10 */
399         /* Initialize machine status; enable machine check interrupt */
400         /*-----------------------------------------------------------*/
401
402         li      r3, MSR_KERNEL                  /* Set ME and RI flags */
403         rlwimi  r3, r5, 0, 25, 25       /* preserve IP bit set by HRCW */
404 #ifdef DEBUG
405         rlwimi  r3, r5, 0, 21, 22   /* debugger might set SE & BE bits */
406 #endif
407         SYNC                                            /* Some chip revs need this... */
408         mtmsr   r3
409         SYNC
410         mtspr   SRR1, r3                        /* Make SRR1 match MSR */
411
412
413         lis     r3, CFG_IMMRBAR@h
414 #if defined(CONFIG_WATCHDOG)
415         /* Initialise the Wathcdog values and reset it (if req) */
416         /*------------------------------------------------------*/
417         lis r4, CFG_WATCHDOG_VALUE
418         ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
419         stw r4, SWCRR(r3)
420         
421         /* and reset it */
422         
423         li      r4, 0x556C
424         sth     r4, SWSRR@l(r3)
425         li      r4, 0xAA39
426         sth     r4, SWSRR@l(r3)
427 #else
428         /* Disable Wathcdog  */
429         /*-------------------*/
430         xor r4, r4, r4
431         stw r4, SWCRR(r3)
432 #endif /* CONFIG_WATCHDOG */
433
434         /* Initialize the Hardware Implementation-dependent Registers */
435         /* HID0 also contains cache control                     */
436         /*------------------------------------------------------*/
437
438         lis     r3, CFG_HID0_INIT@h
439         ori     r3, r3, CFG_HID0_INIT@l
440         SYNC
441         mtspr   HID0, r3
442
443         lis     r3, CFG_HID0_FINAL@h
444         ori     r3, r3, CFG_HID0_FINAL@l
445         SYNC
446         mtspr   HID0, r3
447
448         lis     r3, CFG_HID2@h
449         ori     r3, r3, CFG_HID2@l
450         SYNC
451         mtspr   HID2, r3
452
453         /* clear all BAT's                                      */
454         /*----------------------------------*/
455
456         xor     r0, r0, r0
457         mtspr   DBAT0U, r0
458         mtspr   DBAT0L, r0
459         mtspr   DBAT1U, r0
460         mtspr   DBAT1L, r0
461         mtspr   DBAT2U, r0
462         mtspr   DBAT2L, r0
463         mtspr   DBAT3U, r0
464         mtspr   DBAT3L, r0
465         mtspr   IBAT0U, r0
466         mtspr   IBAT0L, r0
467         mtspr   IBAT1U, r0
468         mtspr   IBAT1L, r0
469         mtspr   IBAT2U, r0
470         mtspr   IBAT2L, r0
471         mtspr   IBAT3U, r0
472         mtspr   IBAT3L, r0
473         SYNC
474
475         /* invalidate all tlb's
476          *
477          * From the 603e User Manual: "The 603e provides the ability to
478          * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
479          * instruction invalidates the TLB entry indexed by the EA, and
480          * operates on both the instruction and data TLBs simultaneously
481          * invalidating four TLB entries (both sets in each TLB). The
482          * index corresponds to bits 15-19 of the EA. To invalidate all
483          * entries within both TLBs, 32 tlbie instructions should be
484          * issued, incrementing this field by one each time."
485          *
486          * "Note that the tlbia instruction is not implemented on the
487          * 603e."
488          *
489          * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
490          * incrementing by 0x1000 each time. The code below is sort of
491          * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
492          *
493          */
494
495         li      r3, 32
496         mtctr   r3
497         li      r3, 0
498 1:      tlbie   r3
499         addi    r3, r3, 0x1000
500         bdnz    1b
501         SYNC
502
503         /* Done!                                                */
504         /*------------------------------*/
505         blr 
506
507 /* Cache functions.
508  *
509  * Note: requires that all cache bits in
510  * HID0 are in the low half word.
511  */
512         .globl  icache_enable
513 icache_enable:
514         mfspr   r3, HID0
515         ori     r3, r3, HID0_ICE
516         lis     r4, 0
517         ori     r4, r4, HID0_ILOCK
518         andc    r3, r3, r4
519         ori     r4, r3, HID0_ICFI
520         isync
521         mtspr   HID0, r4    /* sets enable and invalidate, clears lock */
522         isync
523         mtspr   HID0, r3        /* clears invalidate */
524         blr
525
526         .globl  icache_disable
527 icache_disable:
528         mfspr   r3, HID0
529         lis     r4, 0
530         ori     r4, r4, HID0_ICE|HID0_ILOCK
531         andc    r3, r3, r4
532         ori     r4, r3, HID0_ICFI
533         isync
534         mtspr   HID0, r4     /* sets invalidate, clears enable and lock*/
535         isync
536         mtspr   HID0, r3        /* clears invalidate */
537         blr
538
539         .globl  icache_status
540 icache_status:
541         mfspr   r3, HID0
542         rlwinm  r3, r3, HID0_ICE_SHIFT, 31, 31
543         blr
544
545         .globl  dcache_enable
546 dcache_enable:
547         mfspr   r3, HID0
548         ori     r3, r3, HID0_ENABLE_DATA_CACHE
549         lis     r4, 0
550         ori     r4, r4, HID0_LOCK_DATA_CACHE
551         andc    r3, r3, r4
552         ori     r4, r3, HID0_LOCK_INSTRUCTION_CACHE
553         sync
554         mtspr   HID0, r4    /* sets enable and invalidate, clears lock */
555         sync
556         mtspr   HID0, r3        /* clears invalidate */
557         blr
558
559         .globl  dcache_disable
560 dcache_disable:
561         mfspr   r3, HID0
562         lis     r4, 0
563         ori     r4, r4, HID0_ENABLE_DATA_CACHE|HID0_LOCK_DATA_CACHE
564         andc    r3, r3, r4
565         ori     r4, r3, HID0_INVALIDATE_DATA_CACHE
566         sync
567         mtspr   HID0, r4    /* sets invalidate, clears enable and lock */
568         sync
569         mtspr   HID0, r3        /* clears invalidate */
570         blr
571
572         .globl  dcache_status
573 dcache_status:
574         mfspr   r3, HID0
575         rlwinm  r3, r3, HID0_DCE_SHIFT, 31, 31
576         blr
577
578         .globl get_pvr
579 get_pvr:
580         mfspr   r3, PVR
581         blr
582
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         mr      r3,  r5                         /* Destination Address */
603         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address */
604         ori     r4, r4, CFG_MONITOR_BASE@l
605         lwz     r5, GOT(__init_end)
606         sub     r5, r5, r4
607         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size */
608
609         /*
610          * Fix GOT pointer:
611          *
612          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
613          *              + Destination Address
614          *
615          * Offset:
616          */
617         sub     r15, r10, r4
618
619         /* First our own GOT */
620         add     r14, r14, r15
621         /* then the one used by the C code */
622         add     r30, r30, r15
623
624         /*
625          * Now relocate code
626          */
627
628         cmplw   cr1,r3,r4
629         addi    r0,r5,3
630         srwi.   r0,r0,2
631         beq     cr1,4f          /* In place copy is not necessary */
632         beq     7f              /* Protect against 0 count        */
633         mtctr   r0
634         bge     cr1,2f
635         la      r8,-4(r4)
636         la      r7,-4(r3)
637
638         /* copy */
639 1:      lwzu    r0,4(r8)
640         stwu    r0,4(r7)
641         bdnz    1b
642
643         addi    r0,r5,3
644         srwi.   r0,r0,2
645         mtctr   r0
646         la      r8,-4(r4)
647         la      r7,-4(r3)
648         
649         /* and compare */       
650 20:     lwzu    r20,4(r8)
651         lwzu    r21,4(r7)
652         xor. r22, r20, r21
653         bne  30f
654         bdnz    20b
655         b 4f
656
657         /* compare failed */
658 30:     li r3, 0
659         blr
660
661 2:      slwi    r0,r0,2 /* re copy in reverse order ... y do we needed it? */
662         add     r8,r4,r0
663         add     r7,r3,r0
664 3:      lwzu    r0,-4(r8)
665         stwu    r0,-4(r7)
666         bdnz    3b
667         
668         
669
670 /*
671  * Now flush the cache: note that we must start from a cache aligned
672  * address. Otherwise we might miss one cache line.
673  */
674 4:      
675         bl un_setup_stack_in_data_cache
676         mr r7, r3
677         mr r8, r4
678         bl dcache_disable
679         mr r3, r7
680         mr r4, r8
681         
682         cmpwi   r6,0
683         add     r5,r3,r5
684         beq     7f      /* Always flush prefetch queue in any case */
685         subi    r0,r6,1
686         andc    r3,r3,r0
687         mfspr   r7,HID0         /* don't do dcbst if dcache is disabled*/
688         rlwinm  r7,r7,HID0_DCE_SHIFT,31,31
689         cmpwi   r7,0
690         beq     9f
691         mr      r4,r3
692 5:      dcbst   0,r4
693         add     r4,r4,r6
694         cmplw   r4,r5
695         blt     5b
696         sync            /* Wait for all dcbst to complete on bus */
697 9:      mfspr   r7,HID0         /* don't do icbi if icache is disabled */
698         rlwinm  r7,r7,HID0_DCE_SHIFT,31,31
699         cmpwi   r7,0
700         beq     7f
701         mr      r4,r3
702 6:      icbi    0,r4
703         add     r4,r4,r6
704         cmplw   r4,r5
705         blt     6b
706 7:      sync            /* Wait for all icbi to complete on bus */
707         isync
708
709 /*
710  * We are done. Do not return, instead branch to second part of board
711  * initialization, now running from RAM.
712  */
713
714         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
715         mtlr    r0
716         blr
717
718 in_ram:
719
720         /*
721          * Relocation Function, r14 point to got2+0x8000
722          *
723          * Adjust got2 pointers, no need to check for 0, this code
724          * already puts a few entries in the table.
725          */
726         li      r0,__got2_entries@sectoff@l
727         la      r3,GOT(_GOT2_TABLE_)
728         lwz     r11,GOT(_GOT2_TABLE_)
729         mtctr   r0
730         sub     r11,r3,r11
731         addi    r3,r3,-4
732 1:      lwzu    r0,4(r3)
733         add     r0,r0,r11
734         stw     r0,0(r3)
735         bdnz    1b
736
737         /*
738          * Now adjust the fixups and the pointers to the fixups
739          * in case we need to move ourselves again.
740          */
741 2:      li      r0,__fixup_entries@sectoff@l
742         lwz     r3,GOT(_FIXUP_TABLE_)
743         cmpwi   r0,0
744         mtctr   r0
745         addi    r3,r3,-4
746         beq     4f
747 3:      lwzu    r4,4(r3)
748         lwzux   r0,r4,r11
749         add     r0,r0,r11
750         stw     r10,0(r3)
751         stw     r0,0(r4)
752         bdnz    3b
753 4:
754 clear_bss:
755         /*
756          * Now clear BSS segment
757          */
758         lwz     r3,GOT(__bss_start)
759 #if defined(CONFIG_HYMOD)
760         /*
761          * For HYMOD - the environment is the very last item in flash.
762          * The real .bss stops just before environment starts, so only
763          * clear up to that point.
764          *
765          * taken from mods for FADS board
766          */
767         lwz     r4,GOT(environment)
768 #else
769         lwz     r4,GOT(_end)
770 #endif
771
772         cmplw   0, r3, r4
773         beq     6f
774
775         li      r0, 0
776 5:
777         stw     r0, 0(r3)
778         addi    r3, r3, 4
779         cmplw   0, r3, r4
780         bne     5b
781 6:
782
783         mr      r3, r9          /* Global Data pointer          */
784         mr      r4, r10         /* Destination Address          */
785         bl      board_init_r
786
787         /*
788          * Copy exception vector code to low memory
789          *
790          * r3: dest_addr
791          * r7: source address, r8: end address, r9: target address
792          */
793         .globl  trap_init
794 trap_init:
795         lwz     r7, GOT(_start)
796         lwz     r8, GOT(_end_of_vectors)
797
798         li      r9, 0x100       /* reset vector always at 0x100 */
799
800         cmplw   0, r7, r8
801         bgelr                   /* return if r7>=r8 - just in case */
802
803         mflr    r4              /* save link register */
804 1:
805         lwz     r0, 0(r7)
806         stw     r0, 0(r9)
807         addi    r7, r7, 4
808         addi    r9, r9, 4
809         cmplw   0, r7, r8
810         bne     1b
811
812         /*
813          * relocate `hdlr' and `int_return' entries
814          */
815         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
816         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
817 2:
818         bl      trap_reloc
819         addi    r7, r7, 0x100           /* next exception vector */
820         cmplw   0, r7, r8
821         blt     2b
822
823         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
824         bl      trap_reloc
825
826         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
827         bl      trap_reloc
828
829         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
830         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
831 3:
832         bl      trap_reloc
833         addi    r7, r7, 0x100           /* next exception vector */
834         cmplw   0, r7, r8
835         blt     3b
836
837         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
838         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
839 4:
840         bl      trap_reloc
841         addi    r7, r7, 0x100           /* next exception vector */
842         cmplw   0, r7, r8
843         blt     4b
844
845         mfmsr   r3                      /* now that the vectors have */
846         lis     r7, MSR_IP@h            /* relocated into low memory */
847         ori     r7, r7, MSR_IP@l        /* MSR[IP] can be turned off */
848         andc    r3, r3, r7              /* (if it was on) */
849         SYNC                            /* Some chip revs need this... */
850         mtmsr   r3
851         SYNC
852
853         mtlr    r4                      /* restore link register    */
854         blr
855
856         /*
857          * Function: relocate entries for one exception vector
858          */
859 trap_reloc:
860         lwz     r0, 0(r7)               /* hdlr ...             */
861         add     r0, r0, r3              /*  ... += dest_addr    */
862         stw     r0, 0(r7)
863
864         lwz     r0, 4(r7)               /* int_return ...       */
865         add     r0, r0, r3              /*  ... += dest_addr    */
866         stw     r0, 4(r7)
867
868         blr
869
870 #ifdef CFG_INIT_RAM_LOCK
871 .globl unlock_ram_in_cache
872 unlock_ram_in_cache:
873         /* invalidate the INIT_RAM section */
874         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
875         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
876         li      r2,512
877         mtctr   r2
878 1:      icbi    r0, r3
879         dcbi    r0, r3
880         addi    r3, r3, 32
881         bdnz    1b
882         sync                    /* Wait for all icbi to complete on bus */
883         isync
884         blr
885 #endif
886
887 map_flash_by_law1:
888         /* When booting from ROM (Flash or EPROM), clear the  */
889         /* Address Mask in OR0 so ROM appears everywhere      */
890         /*----------------------------------------------------*/
891         lis     r3, (CFG_IMMRBAR)@h  /* r3 <= CFG_IMMRBAR    */
892         lwz     r4, OR0@l(r3)     
893         li      r5, 0x7fff        /* r5 <= 0x00007FFFF */
894         and     r4, r4, r5        
895         stw     r4, OR0@l(r3)     /* OR0 <= OR0 & 0x00007FFFF */
896
897         /* As MPC8349E User's Manual presented, when RCW[BMS] is set to 0,
898          * system will boot from 0x0000_0100, and the LBLAWBAR0[BASE_ADDR]
899          * reset value is 0x00000; when RCW[BMS] is set to 1, system will boot
900          * from 0xFFF0_0100, and the LBLAWBAR0[BASE_ADDR] reset value is
901          * 0xFF800.  From the hard resetting to here, the processor fetched and
902          * executed the instructions one by one.  There is not absolutely
903          * jumping happened.  Laterly, the u-boot code has to do an absolutely
904          * jumping to tell the CPU instruction fetching component what the
905          * u-boot TEXT base address is.  Because the TEXT base resides in the
906          * boot ROM memory space, to garantee the code can run smoothly after
907          * that jumping, we must map in the entire boot ROM by Local Access
908          * Window.  Sometimes, we desire an non-0x00000 or non-0xFF800 starting
909          * address for boot ROM, such as 0xFE000000.  In this case, the default
910          * LBIU Local Access Widow 0 will not cover this memory space.  So, we
911          * need another window to map in it.
912          */
913         lis r4, (CFG_FLASH_BASE)@h
914         ori r4, r4, (CFG_FLASH_BASE)@l
915         stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CFG_FLASH_BASE */
916         lis r4, (0x80000016)@h
917         ori r4, r4, (0x80000016)@l
918         stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */
919         blr
920
921         /* Though all the LBIU Local Access Windows and LBC Banks will be
922          * initialized in the C code, we'd better configure boot ROM's
923          * window 0 and bank 0 correctly at here.
924          */
925 remap_flash_by_law0:
926         /* Initialize the BR0 with the boot ROM starting address. */
927         lwz r4, BR0(r3)
928         li  r5, 0x7FFF
929         and r4, r4, r5             
930         lis r5, (CFG_FLASH_BASE & 0xFFFF8000)@h
931         ori r5, r5, (CFG_FLASH_BASE & 0xFFFF8000)@l 
932         or  r5, r5, r4
933         stw r5, BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
934
935         lwz r4, OR0(r3)
936         lis r5, 0xFF80 /* 8M */
937         or r4, r4, r5
938         stw r4, OR0(r3) /* OR0 <= OR0 | 0xFF800000 */
939
940         lis r4, (CFG_FLASH_BASE)@h
941         ori r4, r4, (CFG_FLASH_BASE)@l
942         stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CFG_FLASH_BASE */
943
944         lis r4, (0x80000016)@h
945         ori r4, r4, (0x80000016)@l
946         stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= 8MB Flash Size */
947
948         xor r4, r4, r4
949         stw r4, LBLAWBAR1(r3)
950         stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
951         blr
952
953 setup_stack_in_data_cache_on_r1: 
954         lis r3, (CFG_IMMRBAR)@h
955         
956         /* setup D-BAT for the D-Cache (with out real memory backup) */
957
958         lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
959         mtspr   DBAT0U, r4
960         ori r4, r4, 0x0002
961         mtspr   DBAT0L, r4
962         isync
963
964 #if 0   
965         /* Enable MMU */
966         mfmsr r4
967         ori r4, r4, (MSR_DR | MSR_IR)@l
968         mtmsr r4
969 #endif  
970         
971         /* Enable and invalidate data cache. */
972         mfspr   r4, HID0
973         mr      r5, r4
974         ori     r4, r4, HID0_DCE | HID0_DCI
975         ori     r5, r5, HID0_DCE
976         sync
977         mtspr   HID0, r4
978         mtspr   HID0, r5
979         sync
980         
981         /* Allocate Initial RAM in data cache.*/
982         li  r0, 0
983         lis     r4, (CFG_INIT_RAM_ADDR)@h
984         ori     r4, r4, (CFG_INIT_RAM_ADDR)@l
985         li      r5, 128*8 /* 128*8*32=32Kb */ 
986         mtctr   r5
987 1:
988         dcbz    r0, r4
989         addi    r4, r4, 32
990         bdnz    1b
991         isync
992                 
993         /* Lock all the D-cache, basically leaving the reset of the program without dcache */
994         mfspr   r4, HID0
995         ori     r4, r4, (HID0_DLOCK)@l
996         sync
997         mtspr   HID0 , r4
998
999         /* setup the stack pointer in r1 */
1000         lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
1001         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
1002         li      r0, 0                   /* Make room for stack frame header and */
1003
1004         stwu    r0, -4(r1)              /* clear final stack frame so that      */
1005         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
1006
1007         blr
1008
1009 un_setup_stack_in_data_cache:
1010         blr
1011         mr r14, r4
1012         mr r15, r5
1013         
1014
1015         lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
1016         mtspr   DBAT0U, r4
1017         ori r4, r4, 0x0002
1018         mtspr   DBAT0L, r4
1019         isync
1020         
1021         /* un lock all the D-cache */
1022         mfspr   r4, HID0
1023         lis r5, (~(HID0_DLOCK))@h
1024         ori     r5, r5, (~(HID0_DLOCK))@l
1025         and r4, r4, r5
1026         sync
1027         mtspr   HID0 , r4
1028
1029         /* Re - Allocate Initial RAM in data cache.*/
1030         li  r0, 0
1031         lis     r4, (CFG_INIT_RAM_ADDR)@h
1032         ori     r4, r4, (CFG_INIT_RAM_ADDR)@l
1033         li      r5, 128*8 /* 128*8*32=32Kb */ 
1034         mtctr   r5
1035 1:
1036         dcbz    r0, r4
1037         addi    r4, r4, 32
1038         bdnz    1b
1039         isync
1040         
1041         mflr r16
1042         bl dcache_disable
1043         mtlr r16
1044         
1045         blr
1046         
1047 #if 0
1048 #define GREEN_LIGHT 0x2B0D4046
1049 #define RED_LIGHT   0x250D4046
1050 #define LIB_CNT     0x4FFF
1051
1052 /*
1053  * Lib Light
1054  */
1055
1056         .globl liblight
1057 liblight:       
1058         lis     r3, CFG_IMMRBAR@h
1059         ori     r3, r3, CFG_IMMRBAR@l
1060         li r4, 0x3002
1061         mtmsr r4
1062         xor r4, r4, r4
1063         mtspr   HID0, r4
1064         mtspr   HID2, r4
1065         lis r4, 0xF8000000@h
1066         ori r4, r4, 0xF8000000@l        
1067         stw r4, LBLAWBAR1(r3)
1068         lis r4, 0x8000000E@h
1069         ori r4, r4, 0x8000000E@l
1070         stw r4, LBLAWAR1(r3)
1071         lis r4, 0xF8000801@h
1072         ori r4, r4, 0xF8000801@l
1073         stw r4, BR1(r3)
1074         lis r4, 0xFFFFE8f0@h
1075         ori r4, r4, 0xFFFFE8f0@l
1076         stw r4, OR1(r3)
1077
1078         lis r4, 0xF8000000@h
1079         ori r4, r4, 0xF8000000@l
1080         lis r5, GREEN_LIGHT@h
1081         ori r5, r5, GREEN_LIGHT@l
1082         lis r6, RED_LIGHT@h
1083         ori r6, r6, RED_LIGHT@l
1084         lis r7, LIB_CNT@h
1085         ori r7, r7, LIB_CNT@l
1086         
1087 1:
1088         stw r5, 0(r4)
1089         mtctr r7        
1090 2:      bdnz 2b
1091         stw r6, 0(r4)
1092         mtctr r7        
1093 3:      bdnz 3b
1094         b 1b
1095         
1096 #endif