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