]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - cpu/mpc83xx/start.S
Merge branch 'mpc8349ads'
[karo-tx-uboot.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         lwz r4, SWCRR(r3)
430         /* Check to see if its enabled for disabling
431            once disabled by SW you can't re-enable */
432         andi. r4, r4, 0x4
433         beq 1f
434         xor r4, r4, r4
435         stw r4, SWCRR(r3)
436 1:
437 #endif /* CONFIG_WATCHDOG */
438
439         /* Initialize the Hardware Implementation-dependent Registers */
440         /* HID0 also contains cache control                     */
441         /*------------------------------------------------------*/
442
443         lis     r3, CFG_HID0_INIT@h
444         ori     r3, r3, CFG_HID0_INIT@l
445         SYNC
446         mtspr   HID0, r3
447
448         lis     r3, CFG_HID0_FINAL@h
449         ori     r3, r3, CFG_HID0_FINAL@l
450         SYNC
451         mtspr   HID0, r3
452
453         lis     r3, CFG_HID2@h
454         ori     r3, r3, CFG_HID2@l
455         SYNC
456         mtspr   HID2, r3
457
458         /* clear all BAT's                                      */
459         /*----------------------------------*/
460
461         xor     r0, r0, r0
462         mtspr   DBAT0U, r0
463         mtspr   DBAT0L, r0
464         mtspr   DBAT1U, r0
465         mtspr   DBAT1L, r0
466         mtspr   DBAT2U, r0
467         mtspr   DBAT2L, r0
468         mtspr   DBAT3U, r0
469         mtspr   DBAT3L, r0
470         mtspr   IBAT0U, r0
471         mtspr   IBAT0L, r0
472         mtspr   IBAT1U, r0
473         mtspr   IBAT1L, r0
474         mtspr   IBAT2U, r0
475         mtspr   IBAT2L, r0
476         mtspr   IBAT3U, r0
477         mtspr   IBAT3L, r0
478         SYNC
479
480         /* invalidate all tlb's
481          *
482          * From the 603e User Manual: "The 603e provides the ability to
483          * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
484          * instruction invalidates the TLB entry indexed by the EA, and
485          * operates on both the instruction and data TLBs simultaneously
486          * invalidating four TLB entries (both sets in each TLB). The
487          * index corresponds to bits 15-19 of the EA. To invalidate all
488          * entries within both TLBs, 32 tlbie instructions should be
489          * issued, incrementing this field by one each time."
490          *
491          * "Note that the tlbia instruction is not implemented on the
492          * 603e."
493          *
494          * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
495          * incrementing by 0x1000 each time. The code below is sort of
496          * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
497          *
498          */
499
500         li      r3, 32
501         mtctr   r3
502         li      r3, 0
503 1:      tlbie   r3
504         addi    r3, r3, 0x1000
505         bdnz    1b
506         SYNC
507
508         /* Done!                                                */
509         /*------------------------------*/
510         blr
511
512 /* Cache functions.
513  *
514  * Note: requires that all cache bits in
515  * HID0 are in the low half word.
516  */
517         .globl  icache_enable
518 icache_enable:
519         mfspr   r3, HID0
520         ori     r3, r3, HID0_ICE
521         lis     r4, 0
522         ori     r4, r4, HID0_ILOCK
523         andc    r3, r3, r4
524         ori     r4, r3, HID0_ICFI
525         isync
526         mtspr   HID0, r4    /* sets enable and invalidate, clears lock */
527         isync
528         mtspr   HID0, r3        /* clears invalidate */
529         blr
530
531         .globl  icache_disable
532 icache_disable:
533         mfspr   r3, HID0
534         lis     r4, 0
535         ori     r4, r4, HID0_ICE|HID0_ILOCK
536         andc    r3, r3, r4
537         ori     r4, r3, HID0_ICFI
538         isync
539         mtspr   HID0, r4     /* sets invalidate, clears enable and lock*/
540         isync
541         mtspr   HID0, r3        /* clears invalidate */
542         blr
543
544         .globl  icache_status
545 icache_status:
546         mfspr   r3, HID0
547         rlwinm  r3, r3, HID0_ICE_SHIFT, 31, 31
548         blr
549
550         .globl  dcache_enable
551 dcache_enable:
552         mfspr   r3, HID0
553         ori     r3, r3, HID0_ENABLE_DATA_CACHE
554         lis     r4, 0
555         ori     r4, r4, HID0_LOCK_DATA_CACHE
556         andc    r3, r3, r4
557         ori     r4, r3, HID0_LOCK_INSTRUCTION_CACHE
558         sync
559         mtspr   HID0, r4    /* sets enable and invalidate, clears lock */
560         sync
561         mtspr   HID0, r3        /* clears invalidate */
562         blr
563
564         .globl  dcache_disable
565 dcache_disable:
566         mfspr   r3, HID0
567         lis     r4, 0
568         ori     r4, r4, HID0_ENABLE_DATA_CACHE|HID0_LOCK_DATA_CACHE
569         andc    r3, r3, r4
570         ori     r4, r3, HID0_INVALIDATE_DATA_CACHE
571         sync
572         mtspr   HID0, r4    /* sets invalidate, clears enable and lock */
573         sync
574         mtspr   HID0, r3        /* clears invalidate */
575         blr
576
577         .globl  dcache_status
578 dcache_status:
579         mfspr   r3, HID0
580         rlwinm  r3, r3, HID0_DCE_SHIFT, 31, 31
581         blr
582
583         .globl get_pvr
584 get_pvr:
585         mfspr   r3, PVR
586         blr
587
588 /*-------------------------------------------------------------------*/
589
590 /*
591  * void relocate_code (addr_sp, gd, addr_moni)
592  *
593  * This "function" does not return, instead it continues in RAM
594  * after relocating the monitor code.
595  *
596  * r3 = dest
597  * r4 = src
598  * r5 = length in bytes
599  * r6 = cachelinesize
600  */
601         .globl  relocate_code
602 relocate_code:
603         mr      r1,  r3         /* Set new stack pointer        */
604         mr      r9,  r4         /* Save copy of Global Data pointer */
605         mr      r10, r5         /* Save copy of Destination Address */
606
607         mr      r3,  r5                         /* Destination Address */
608         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address */
609         ori     r4, r4, CFG_MONITOR_BASE@l
610         lwz     r5, GOT(__init_end)
611         sub     r5, r5, r4
612         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size */
613
614         /*
615          * Fix GOT pointer:
616          *
617          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
618          *              + Destination Address
619          *
620          * Offset:
621          */
622         sub     r15, r10, r4
623
624         /* First our own GOT */
625         add     r14, r14, r15
626         /* then the one used by the C code */
627         add     r30, r30, r15
628
629         /*
630          * Now relocate code
631          */
632
633         cmplw   cr1,r3,r4
634         addi    r0,r5,3
635         srwi.   r0,r0,2
636         beq     cr1,4f          /* In place copy is not necessary */
637         beq     7f              /* Protect against 0 count        */
638         mtctr   r0
639         bge     cr1,2f
640         la      r8,-4(r4)
641         la      r7,-4(r3)
642
643         /* copy */
644 1:      lwzu    r0,4(r8)
645         stwu    r0,4(r7)
646         bdnz    1b
647
648         addi    r0,r5,3
649         srwi.   r0,r0,2
650         mtctr   r0
651         la      r8,-4(r4)
652         la      r7,-4(r3)
653
654         /* and compare */
655 20:     lwzu    r20,4(r8)
656         lwzu    r21,4(r7)
657         xor. r22, r20, r21
658         bne  30f
659         bdnz    20b
660         b 4f
661
662         /* compare failed */
663 30:     li r3, 0
664         blr
665
666 2:      slwi    r0,r0,2 /* re copy in reverse order ... y do we needed it? */
667         add     r8,r4,r0
668         add     r7,r3,r0
669 3:      lwzu    r0,-4(r8)
670         stwu    r0,-4(r7)
671         bdnz    3b
672
673 /*
674  * Now flush the cache: note that we must start from a cache aligned
675  * address. Otherwise we might miss one cache line.
676  */
677 4:
678         bl un_setup_stack_in_data_cache
679         mr r7, r3
680         mr r8, r4
681         bl dcache_disable
682         mr r3, r7
683         mr r4, r8
684
685         cmpwi   r6,0
686         add     r5,r3,r5
687         beq     7f      /* Always flush prefetch queue in any case */
688         subi    r0,r6,1
689         andc    r3,r3,r0
690         mfspr   r7,HID0         /* don't do dcbst if dcache is disabled*/
691         rlwinm  r7,r7,HID0_DCE_SHIFT,31,31
692         cmpwi   r7,0
693         beq     9f
694         mr      r4,r3
695 5:      dcbst   0,r4
696         add     r4,r4,r6
697         cmplw   r4,r5
698         blt     5b
699         sync            /* Wait for all dcbst to complete on bus */
700 9:      mfspr   r7,HID0         /* don't do icbi if icache is disabled */
701         rlwinm  r7,r7,HID0_DCE_SHIFT,31,31
702         cmpwi   r7,0
703         beq     7f
704         mr      r4,r3
705 6:      icbi    0,r4
706         add     r4,r4,r6
707         cmplw   r4,r5
708         blt     6b
709 7:      sync            /* Wait for all icbi to complete on bus */
710         isync
711
712 /*
713  * We are done. Do not return, instead branch to second part of board
714  * initialization, now running from RAM.
715  */
716
717         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
718         mtlr    r0
719         blr
720
721 in_ram:
722
723         /*
724          * Relocation Function, r14 point to got2+0x8000
725          *
726          * Adjust got2 pointers, no need to check for 0, this code
727          * already puts a few entries in the table.
728          */
729         li      r0,__got2_entries@sectoff@l
730         la      r3,GOT(_GOT2_TABLE_)
731         lwz     r11,GOT(_GOT2_TABLE_)
732         mtctr   r0
733         sub     r11,r3,r11
734         addi    r3,r3,-4
735 1:      lwzu    r0,4(r3)
736         add     r0,r0,r11
737         stw     r0,0(r3)
738         bdnz    1b
739
740         /*
741          * Now adjust the fixups and the pointers to the fixups
742          * in case we need to move ourselves again.
743          */
744 2:      li      r0,__fixup_entries@sectoff@l
745         lwz     r3,GOT(_FIXUP_TABLE_)
746         cmpwi   r0,0
747         mtctr   r0
748         addi    r3,r3,-4
749         beq     4f
750 3:      lwzu    r4,4(r3)
751         lwzux   r0,r4,r11
752         add     r0,r0,r11
753         stw     r10,0(r3)
754         stw     r0,0(r4)
755         bdnz    3b
756 4:
757 clear_bss:
758         /*
759          * Now clear BSS segment
760          */
761         lwz     r3,GOT(__bss_start)
762 #if defined(CONFIG_HYMOD)
763         /*
764          * For HYMOD - the environment is the very last item in flash.
765          * The real .bss stops just before environment starts, so only
766          * clear up to that point.
767          *
768          * taken from mods for FADS board
769          */
770         lwz     r4,GOT(environment)
771 #else
772         lwz     r4,GOT(_end)
773 #endif
774
775         cmplw   0, r3, r4
776         beq     6f
777
778         li      r0, 0
779 5:
780         stw     r0, 0(r3)
781         addi    r3, r3, 4
782         cmplw   0, r3, r4
783         bne     5b
784 6:
785
786         mr      r3, r9          /* Global Data pointer          */
787         mr      r4, r10         /* Destination Address          */
788         bl      board_init_r
789
790         /*
791          * Copy exception vector code to low memory
792          *
793          * r3: dest_addr
794          * r7: source address, r8: end address, r9: target address
795          */
796         .globl  trap_init
797 trap_init:
798         lwz     r7, GOT(_start)
799         lwz     r8, GOT(_end_of_vectors)
800
801         li      r9, 0x100       /* reset vector always at 0x100 */
802
803         cmplw   0, r7, r8
804         bgelr                   /* return if r7>=r8 - just in case */
805
806         mflr    r4              /* save link register */
807 1:
808         lwz     r0, 0(r7)
809         stw     r0, 0(r9)
810         addi    r7, r7, 4
811         addi    r9, r9, 4
812         cmplw   0, r7, r8
813         bne     1b
814
815         /*
816          * relocate `hdlr' and `int_return' entries
817          */
818         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
819         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
820 2:
821         bl      trap_reloc
822         addi    r7, r7, 0x100           /* next exception vector */
823         cmplw   0, r7, r8
824         blt     2b
825
826         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
827         bl      trap_reloc
828
829         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
830         bl      trap_reloc
831
832         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
833         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
834 3:
835         bl      trap_reloc
836         addi    r7, r7, 0x100           /* next exception vector */
837         cmplw   0, r7, r8
838         blt     3b
839
840         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
841         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
842 4:
843         bl      trap_reloc
844         addi    r7, r7, 0x100           /* next exception vector */
845         cmplw   0, r7, r8
846         blt     4b
847
848         mfmsr   r3                      /* now that the vectors have */
849         lis     r7, MSR_IP@h            /* relocated into low memory */
850         ori     r7, r7, MSR_IP@l        /* MSR[IP] can be turned off */
851         andc    r3, r3, r7              /* (if it was on) */
852         SYNC                            /* Some chip revs need this... */
853         mtmsr   r3
854         SYNC
855
856         mtlr    r4                      /* restore link register    */
857         blr
858
859         /*
860          * Function: relocate entries for one exception vector
861          */
862 trap_reloc:
863         lwz     r0, 0(r7)               /* hdlr ...             */
864         add     r0, r0, r3              /*  ... += dest_addr    */
865         stw     r0, 0(r7)
866
867         lwz     r0, 4(r7)               /* int_return ...       */
868         add     r0, r0, r3              /*  ... += dest_addr    */
869         stw     r0, 4(r7)
870
871         blr
872
873 #ifdef CFG_INIT_RAM_LOCK
874 .globl unlock_ram_in_cache
875 unlock_ram_in_cache:
876         /* invalidate the INIT_RAM section */
877         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
878         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
879         li      r2,512
880         mtctr   r2
881 1:      icbi    r0, r3
882         dcbi    r0, r3
883         addi    r3, r3, 32
884         bdnz    1b
885         sync                    /* Wait for all icbi to complete on bus */
886         isync
887         blr
888 #endif
889
890 map_flash_by_law1:
891         /* When booting from ROM (Flash or EPROM), clear the  */
892         /* Address Mask in OR0 so ROM appears everywhere      */
893         /*----------------------------------------------------*/
894         lis     r3, (CFG_IMMRBAR)@h  /* r3 <= CFG_IMMRBAR    */
895         lwz     r4, OR0@l(r3)
896         li      r5, 0x7fff        /* r5 <= 0x00007FFFF */
897         and     r4, r4, r5
898         stw     r4, OR0@l(r3)     /* OR0 <= OR0 & 0x00007FFFF */
899
900         /* As MPC8349E User's Manual presented, when RCW[BMS] is set to 0,
901          * system will boot from 0x0000_0100, and the LBLAWBAR0[BASE_ADDR]
902          * reset value is 0x00000; when RCW[BMS] is set to 1, system will boot
903          * from 0xFFF0_0100, and the LBLAWBAR0[BASE_ADDR] reset value is
904          * 0xFF800.  From the hard resetting to here, the processor fetched and
905          * executed the instructions one by one.  There is not absolutely
906          * jumping happened.  Laterly, the u-boot code has to do an absolutely
907          * jumping to tell the CPU instruction fetching component what the
908          * u-boot TEXT base address is.  Because the TEXT base resides in the
909          * boot ROM memory space, to garantee the code can run smoothly after
910          * that jumping, we must map in the entire boot ROM by Local Access
911          * Window.  Sometimes, we desire an non-0x00000 or non-0xFF800 starting
912          * address for boot ROM, such as 0xFE000000.  In this case, the default
913          * LBIU Local Access Widow 0 will not cover this memory space.  So, we
914          * need another window to map in it.
915          */
916         lis r4, (CFG_FLASH_BASE)@h
917         ori r4, r4, (CFG_FLASH_BASE)@l
918         stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CFG_FLASH_BASE */
919         lis r4, (0x80000016)@h
920         ori r4, r4, (0x80000016)@l
921         stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */
922         blr
923
924         /* Though all the LBIU Local Access Windows and LBC Banks will be
925          * initialized in the C code, we'd better configure boot ROM's
926          * window 0 and bank 0 correctly at here.
927          */
928 remap_flash_by_law0:
929         /* Initialize the BR0 with the boot ROM starting address. */
930         lwz r4, BR0(r3)
931         li  r5, 0x7FFF
932         and r4, r4, r5
933         lis r5, (CFG_FLASH_BASE & 0xFFFF8000)@h
934         ori r5, r5, (CFG_FLASH_BASE & 0xFFFF8000)@l
935         or  r5, r5, r4
936         stw r5, BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
937
938         lwz r4, OR0(r3)
939         lis r5, 0xFF80 /* 8M */
940         or r4, r4, r5
941         stw r4, OR0(r3) /* OR0 <= OR0 | 0xFF800000 */
942
943         lis r4, (CFG_FLASH_BASE)@h
944         ori r4, r4, (CFG_FLASH_BASE)@l
945         stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CFG_FLASH_BASE */
946
947         lis r4, (0x80000016)@h
948         ori r4, r4, (0x80000016)@l
949         stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= 8MB Flash Size */
950
951         xor r4, r4, r4
952         stw r4, LBLAWBAR1(r3)
953         stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
954         blr
955
956 setup_stack_in_data_cache_on_r1:
957         lis r3, (CFG_IMMRBAR)@h
958
959         /* setup D-BAT for the D-Cache (with out real memory backup) */
960
961         lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
962         mtspr   DBAT0U, r4
963         ori r4, r4, 0x0002
964         mtspr   DBAT0L, r4
965         isync
966
967 #if 0
968         /* Enable MMU */
969         mfmsr r4
970         ori r4, r4, (MSR_DR | MSR_IR)@l
971         mtmsr r4
972 #endif
973
974         /* Enable and invalidate data cache. */
975         mfspr   r4, HID0
976         mr      r5, r4
977         ori     r4, r4, HID0_DCE | HID0_DCI
978         ori     r5, r5, HID0_DCE
979         sync
980         mtspr   HID0, r4
981         mtspr   HID0, r5
982         sync
983
984         /* Allocate Initial RAM in data cache.*/
985         li  r0, 0
986         lis     r4, (CFG_INIT_RAM_ADDR)@h
987         ori     r4, r4, (CFG_INIT_RAM_ADDR)@l
988         li      r5, 128*8 /* 128*8*32=32Kb */
989         mtctr   r5
990 1:
991         dcbz    r0, r4
992         addi    r4, r4, 32
993         bdnz    1b
994         isync
995
996         /* Lock all the D-cache, basically leaving the reset of the program without dcache */
997         mfspr   r4, HID0
998         ori     r4, r4, (HID0_DLOCK)@l
999         sync
1000         mtspr   HID0 , r4
1001
1002         /* setup the stack pointer in r1 */
1003         lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
1004         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
1005         li      r0, 0                   /* Make room for stack frame header and */
1006
1007         stwu    r0, -4(r1)              /* clear final stack frame so that      */
1008         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
1009
1010         blr
1011
1012 un_setup_stack_in_data_cache:
1013         blr
1014         mr r14, r4
1015         mr r15, r5
1016
1017
1018         lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
1019         mtspr   DBAT0U, r4
1020         ori r4, r4, 0x0002
1021         mtspr   DBAT0L, r4
1022         isync
1023
1024         /* un lock all the D-cache */
1025         mfspr   r4, HID0
1026         lis r5, (~(HID0_DLOCK))@h
1027         ori     r5, r5, (~(HID0_DLOCK))@l
1028         and r4, r4, r5
1029         sync
1030         mtspr   HID0 , r4
1031
1032         /* Re - Allocate Initial RAM in data cache.*/
1033         li  r0, 0
1034         lis     r4, (CFG_INIT_RAM_ADDR)@h
1035         ori     r4, r4, (CFG_INIT_RAM_ADDR)@l
1036         li      r5, 128*8 /* 128*8*32=32Kb */
1037         mtctr   r5
1038 1:
1039         dcbz    r0, r4
1040         addi    r4, r4, 32
1041         bdnz    1b
1042         isync
1043
1044         mflr r16
1045         bl dcache_disable
1046         mtlr r16
1047
1048         blr
1049
1050 #if 0
1051 #define GREEN_LIGHT 0x2B0D4046
1052 #define RED_LIGHT   0x250D4046
1053 #define LIB_CNT     0x4FFF
1054
1055 /*
1056  * Lib Light
1057  */
1058
1059         .globl liblight
1060 liblight:
1061         lis     r3, CFG_IMMRBAR@h
1062         ori     r3, r3, CFG_IMMRBAR@l
1063         li r4, 0x3002
1064         mtmsr r4
1065         xor r4, r4, r4
1066         mtspr   HID0, r4
1067         mtspr   HID2, r4
1068         lis r4, 0xF8000000@h
1069         ori r4, r4, 0xF8000000@l
1070         stw r4, LBLAWBAR1(r3)
1071         lis r4, 0x8000000E@h
1072         ori r4, r4, 0x8000000E@l
1073         stw r4, LBLAWAR1(r3)
1074         lis r4, 0xF8000801@h
1075         ori r4, r4, 0xF8000801@l
1076         stw r4, BR1(r3)
1077         lis r4, 0xFFFFE8f0@h
1078         ori r4, r4, 0xFFFFE8f0@l
1079         stw r4, OR1(r3)
1080
1081         lis r4, 0xF8000000@h
1082         ori r4, r4, 0xF8000000@l
1083         lis r5, GREEN_LIGHT@h
1084         ori r5, r5, GREEN_LIGHT@l
1085         lis r6, RED_LIGHT@h
1086         ori r6, r6, RED_LIGHT@l
1087         lis r7, LIB_CNT@h
1088         ori r7, r7, LIB_CNT@l
1089
1090 1:
1091         stw r5, 0(r4)
1092         mtctr r7
1093 2:      bdnz 2b
1094         stw r6, 0(r4)
1095         mtctr r7
1096 3:      bdnz 3b
1097         b 1b
1098
1099 #endif