mpc83xx: Add support for variable flash memory sizes on 83xx systems
[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 Freescale Semiconductor, Inc. 2004, 2006. All rights reserved.
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         /* setup the bats */
183         bl      setup_bats
184         sync
185
186         /*
187          * Cache must be enabled here for stack-in-cache trick.
188          * This means we need to enable the BATS.
189          * This means:
190          *   1) for the EVB, original gt regs need to be mapped
191          *   2) need to have an IBAT for the 0xf region,
192          *      we are running there!
193          * Cache should be turned on after BATs, since by default
194          * everything is write-through.
195          * The init-mem BAT can be reused after reloc. The old
196          * gt-regs BAT can be reused after board_init_f calls
197          * board_early_init_f (EVB only).
198          */
199         /* enable address translation */
200         bl      enable_addr_trans
201         sync
202
203         /* enable and invalidate the data cache */
204         bl      dcache_enable
205         sync
206 #ifdef CFG_INIT_RAM_LOCK
207         bl      lock_ram_in_cache
208         sync
209 #endif
210
211         /* set up the stack pointer in our newly created
212          * cache-ram (r1) */
213         lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
214         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
215
216         li      r0, 0           /* Make room for stack frame header and */
217         stwu    r0, -4(r1)      /* clear final stack frame so that      */
218         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
219
220
221         /* let the C-code set up the rest                           */
222         /*                                                          */
223         /* Be careful to keep code relocatable & stack humble   */
224         /*------------------------------------------------------*/
225
226         GET_GOT                 /* initialize GOT access        */
227
228         /* r3: IMMR */
229         lis     r3, CFG_IMMRBAR@h
230         /* run low-level CPU init code (in Flash)*/
231         bl      cpu_init_f
232
233         /* r3: BOOTFLAG */
234         mr      r3, r21
235         /* run 1st part of board init code (in Flash)*/
236         bl      board_init_f
237
238 /*
239  * Vector Table
240  */
241
242         .globl  _start_of_vectors
243 _start_of_vectors:
244
245 /* Machine check */
246         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
247
248 /* Data Storage exception. */
249         STD_EXCEPTION(0x300, DataStorage, UnknownException)
250
251 /* Instruction Storage exception. */
252         STD_EXCEPTION(0x400, InstStorage, UnknownException)
253
254 /* External Interrupt exception. */
255 #ifndef FIXME
256         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
257 #endif
258
259 /* Alignment exception. */
260         . = 0x600
261 Alignment:
262         EXCEPTION_PROLOG
263         mfspr   r4,DAR
264         stw     r4,_DAR(r21)
265         mfspr   r5,DSISR
266         stw     r5,_DSISR(r21)
267         addi    r3,r1,STACK_FRAME_OVERHEAD
268         li      r20,MSR_KERNEL
269         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
270         rlwimi  r20,r23,0,25,25         /* copy IP bit from saved MSR */
271         lwz     r6,GOT(transfer_to_handler)
272         mtlr    r6
273         blrl
274 .L_Alignment:
275         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
276         .long   int_return - _start + EXC_OFF_SYS_RESET
277
278 /* Program check exception */
279         . = 0x700
280 ProgramCheck:
281         EXCEPTION_PROLOG
282         addi    r3,r1,STACK_FRAME_OVERHEAD
283         li      r20,MSR_KERNEL
284         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
285         rlwimi  r20,r23,0,25,25         /* copy IP bit from saved MSR */
286         lwz     r6,GOT(transfer_to_handler)
287         mtlr    r6
288         blrl
289 .L_ProgramCheck:
290         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
291         .long   int_return - _start + EXC_OFF_SYS_RESET
292
293         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
294
295         /* I guess we could implement decrementer, and may have
296          * to someday for timekeeping.
297          */
298         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
299
300         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
301         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
302         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
303         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
304
305         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
306         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
307
308         STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
309         STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
310         STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
311 #ifdef DEBUG
312         . = 0x1300
313         /*
314          * This exception occurs when the program counter matches the
315          * Instruction Address Breakpoint Register (IABR).
316          *
317          * I want the cpu to halt if this occurs so I can hunt around
318          * with the debugger and look at things.
319          *
320          * When DEBUG is defined, both machine check enable (in the MSR)
321          * and checkstop reset enable (in the reset mode register) are
322          * turned off and so a checkstop condition will result in the cpu
323          * halting.
324          *
325          * I force the cpu into a checkstop condition by putting an illegal
326          * instruction here (at least this is the theory).
327          *
328          * well - that didnt work, so just do an infinite loop!
329          */
330 1:      b       1b
331 #else
332         STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
333 #endif
334         STD_EXCEPTION(0x1400, SMI, UnknownException)
335
336         STD_EXCEPTION(0x1500, Trap_15, UnknownException)
337         STD_EXCEPTION(0x1600, Trap_16, UnknownException)
338         STD_EXCEPTION(0x1700, Trap_17, UnknownException)
339         STD_EXCEPTION(0x1800, Trap_18, UnknownException)
340         STD_EXCEPTION(0x1900, Trap_19, UnknownException)
341         STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
342         STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
343         STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
344         STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
345         STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
346         STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
347         STD_EXCEPTION(0x2000, Trap_20, UnknownException)
348         STD_EXCEPTION(0x2100, Trap_21, UnknownException)
349         STD_EXCEPTION(0x2200, Trap_22, UnknownException)
350         STD_EXCEPTION(0x2300, Trap_23, UnknownException)
351         STD_EXCEPTION(0x2400, Trap_24, UnknownException)
352         STD_EXCEPTION(0x2500, Trap_25, UnknownException)
353         STD_EXCEPTION(0x2600, Trap_26, UnknownException)
354         STD_EXCEPTION(0x2700, Trap_27, UnknownException)
355         STD_EXCEPTION(0x2800, Trap_28, UnknownException)
356         STD_EXCEPTION(0x2900, Trap_29, UnknownException)
357         STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
358         STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
359         STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
360         STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
361         STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
362         STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
363
364
365         .globl  _end_of_vectors
366 _end_of_vectors:
367
368         . = 0x3000
369
370 /*
371  * This code finishes saving the registers to the exception frame
372  * and jumps to the appropriate handler for the exception.
373  * Register r21 is pointer into trap frame, r1 has new stack pointer.
374  */
375         .globl  transfer_to_handler
376 transfer_to_handler:
377         stw     r22,_NIP(r21)
378         lis     r22,MSR_POW@h
379         andc    r23,r23,r22
380         stw     r23,_MSR(r21)
381         SAVE_GPR(7, r21)
382         SAVE_4GPRS(8, r21)
383         SAVE_8GPRS(12, r21)
384         SAVE_8GPRS(24, r21)
385         mflr    r23
386         andi.   r24,r23,0x3f00          /* get vector offset */
387         stw     r24,TRAP(r21)
388         li      r22,0
389         stw     r22,RESULT(r21)
390         lwz     r24,0(r23)              /* virtual address of handler */
391         lwz     r23,4(r23)              /* where to go when done */
392         mtspr   SRR0,r24
393         mtspr   SRR1,r20
394         mtlr    r23
395         SYNC
396         rfi                             /* jump to handler, enable MMU */
397
398 int_return:
399         mfmsr   r28             /* Disable interrupts */
400         li      r4,0
401         ori     r4,r4,MSR_EE
402         andc    r28,r28,r4
403         SYNC                    /* Some chip revs need this... */
404         mtmsr   r28
405         SYNC
406         lwz     r2,_CTR(r1)
407         lwz     r0,_LINK(r1)
408         mtctr   r2
409         mtlr    r0
410         lwz     r2,_XER(r1)
411         lwz     r0,_CCR(r1)
412         mtspr   XER,r2
413         mtcrf   0xFF,r0
414         REST_10GPRS(3, r1)
415         REST_10GPRS(13, r1)
416         REST_8GPRS(23, r1)
417         REST_GPR(31, r1)
418         lwz     r2,_NIP(r1)     /* Restore environment */
419         lwz     r0,_MSR(r1)
420         mtspr   SRR0,r2
421         mtspr   SRR1,r0
422         lwz     r0,GPR0(r1)
423         lwz     r2,GPR2(r1)
424         lwz     r1,GPR1(r1)
425         SYNC
426         rfi
427
428 /*
429  * This code initialises the E300 processor core
430  * (conforms to PowerPC 603e spec)
431  * Note: expects original MSR contents to be in r5.
432  */
433         .globl  init_e300_core
434 init_e300_core: /* time t 10 */
435         /* Initialize machine status; enable machine check interrupt */
436         /*-----------------------------------------------------------*/
437
438         li      r3, MSR_KERNEL                  /* Set ME and RI flags */
439         rlwimi  r3, r5, 0, 25, 25       /* preserve IP bit set by HRCW */
440 #ifdef DEBUG
441         rlwimi  r3, r5, 0, 21, 22   /* debugger might set SE & BE bits */
442 #endif
443         SYNC                                            /* Some chip revs need this... */
444         mtmsr   r3
445         SYNC
446         mtspr   SRR1, r3                        /* Make SRR1 match MSR */
447
448
449         lis     r3, CFG_IMMRBAR@h
450 #if defined(CONFIG_WATCHDOG)
451         /* Initialise the Wathcdog values and reset it (if req) */
452         /*------------------------------------------------------*/
453         lis r4, CFG_WATCHDOG_VALUE
454         ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
455         stw r4, SWCRR(r3)
456
457         /* and reset it */
458
459         li      r4, 0x556C
460         sth     r4, SWSRR@l(r3)
461         li      r4, 0xAA39
462         sth     r4, SWSRR@l(r3)
463 #else
464         /* Disable Wathcdog  */
465         /*-------------------*/
466         lwz r4, SWCRR(r3)
467         /* Check to see if its enabled for disabling
468            once disabled by SW you can't re-enable */
469         andi. r4, r4, 0x4
470         beq 1f
471         xor r4, r4, r4
472         stw r4, SWCRR(r3)
473 1:
474 #endif /* CONFIG_WATCHDOG */
475
476         /* Initialize the Hardware Implementation-dependent Registers */
477         /* HID0 also contains cache control                     */
478         /*------------------------------------------------------*/
479
480         lis     r3, CFG_HID0_INIT@h
481         ori     r3, r3, CFG_HID0_INIT@l
482         SYNC
483         mtspr   HID0, r3
484
485         lis     r3, CFG_HID0_FINAL@h
486         ori     r3, r3, CFG_HID0_FINAL@l
487         SYNC
488         mtspr   HID0, r3
489
490         lis     r3, CFG_HID2@h
491         ori     r3, r3, CFG_HID2@l
492         SYNC
493         mtspr   HID2, r3
494
495         /* clear all BAT's                                      */
496         /*----------------------------------*/
497
498         xor     r0, r0, r0
499         mtspr   DBAT0U, r0
500         mtspr   DBAT0L, r0
501         mtspr   DBAT1U, r0
502         mtspr   DBAT1L, r0
503         mtspr   DBAT2U, r0
504         mtspr   DBAT2L, r0
505         mtspr   DBAT3U, r0
506         mtspr   DBAT3L, r0
507         mtspr   IBAT0U, r0
508         mtspr   IBAT0L, r0
509         mtspr   IBAT1U, r0
510         mtspr   IBAT1L, r0
511         mtspr   IBAT2U, r0
512         mtspr   IBAT2L, r0
513         mtspr   IBAT3U, r0
514         mtspr   IBAT3L, r0
515         SYNC
516
517         /* invalidate all tlb's
518          *
519          * From the 603e User Manual: "The 603e provides the ability to
520          * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
521          * instruction invalidates the TLB entry indexed by the EA, and
522          * operates on both the instruction and data TLBs simultaneously
523          * invalidating four TLB entries (both sets in each TLB). The
524          * index corresponds to bits 15-19 of the EA. To invalidate all
525          * entries within both TLBs, 32 tlbie instructions should be
526          * issued, incrementing this field by one each time."
527          *
528          * "Note that the tlbia instruction is not implemented on the
529          * 603e."
530          *
531          * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
532          * incrementing by 0x1000 each time. The code below is sort of
533          * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
534          *
535          */
536
537         li      r3, 32
538         mtctr   r3
539         li      r3, 0
540 1:      tlbie   r3
541         addi    r3, r3, 0x1000
542         bdnz    1b
543         SYNC
544
545         /* Done!                                                */
546         /*------------------------------*/
547         blr
548
549         .globl  invalidate_bats
550 invalidate_bats:
551         /* invalidate BATs */
552         mtspr   IBAT0U, r0
553         mtspr   IBAT1U, r0
554         mtspr   IBAT2U, r0
555         mtspr   IBAT3U, r0
556 #if (CFG_HID2 & HID2_HBE)
557         mtspr   IBAT4U, r0
558         mtspr   IBAT5U, r0
559         mtspr   IBAT6U, r0
560         mtspr   IBAT7U, r0
561 #endif
562         isync
563         mtspr   DBAT0U, r0
564         mtspr   DBAT1U, r0
565         mtspr   DBAT2U, r0
566         mtspr   DBAT3U, r0
567 #if (CFG_HID2 & HID2_HBE)
568         mtspr   DBAT4U, r0
569         mtspr   DBAT5U, r0
570         mtspr   DBAT6U, r0
571         mtspr   DBAT7U, r0
572 #endif
573         isync
574         sync
575         blr
576
577         /* setup_bats - set them up to some initial state */
578         .globl  setup_bats
579 setup_bats:
580         addis   r0, r0, 0x0000
581
582         /* IBAT 0 */
583         addis   r4, r0, CFG_IBAT0L@h
584         ori     r4, r4, CFG_IBAT0L@l
585         addis   r3, r0, CFG_IBAT0U@h
586         ori     r3, r3, CFG_IBAT0U@l
587         mtspr   IBAT0L, r4
588         mtspr   IBAT0U, r3
589         isync
590
591         /* DBAT 0 */
592         addis   r4, r0, CFG_DBAT0L@h
593         ori     r4, r4, CFG_DBAT0L@l
594         addis   r3, r0, CFG_DBAT0U@h
595         ori     r3, r3, CFG_DBAT0U@l
596         mtspr   DBAT0L, r4
597         mtspr   DBAT0U, r3
598         isync
599
600         /* IBAT 1 */
601         addis   r4, r0, CFG_IBAT1L@h
602         ori     r4, r4, CFG_IBAT1L@l
603         addis   r3, r0, CFG_IBAT1U@h
604         ori     r3, r3, CFG_IBAT1U@l
605         mtspr   IBAT1L, r4
606         mtspr   IBAT1U, r3
607         isync
608
609         /* DBAT 1 */
610         addis   r4, r0, CFG_DBAT1L@h
611         ori     r4, r4, CFG_DBAT1L@l
612         addis   r3, r0, CFG_DBAT1U@h
613         ori     r3, r3, CFG_DBAT1U@l
614         mtspr   DBAT1L, r4
615         mtspr   DBAT1U, r3
616         isync
617
618         /* IBAT 2 */
619         addis   r4, r0, CFG_IBAT2L@h
620         ori     r4, r4, CFG_IBAT2L@l
621         addis   r3, r0, CFG_IBAT2U@h
622         ori     r3, r3, CFG_IBAT2U@l
623         mtspr   IBAT2L, r4
624         mtspr   IBAT2U, r3
625         isync
626
627         /* DBAT 2 */
628         addis   r4, r0, CFG_DBAT2L@h
629         ori     r4, r4, CFG_DBAT2L@l
630         addis   r3, r0, CFG_DBAT2U@h
631         ori     r3, r3, CFG_DBAT2U@l
632         mtspr   DBAT2L, r4
633         mtspr   DBAT2U, r3
634         isync
635
636         /* IBAT 3 */
637         addis   r4, r0, CFG_IBAT3L@h
638         ori     r4, r4, CFG_IBAT3L@l
639         addis   r3, r0, CFG_IBAT3U@h
640         ori     r3, r3, CFG_IBAT3U@l
641         mtspr   IBAT3L, r4
642         mtspr   IBAT3U, r3
643         isync
644
645         /* DBAT 3 */
646         addis   r4, r0, CFG_DBAT3L@h
647         ori     r4, r4, CFG_DBAT3L@l
648         addis   r3, r0, CFG_DBAT3U@h
649         ori     r3, r3, CFG_DBAT3U@l
650         mtspr   DBAT3L, r4
651         mtspr   DBAT3U, r3
652         isync
653
654 #if (CFG_HID2 & HID2_HBE)
655         /* IBAT 4 */
656         addis   r4, r0, CFG_IBAT4L@h
657         ori     r4, r4, CFG_IBAT4L@l
658         addis   r3, r0, CFG_IBAT4U@h
659         ori     r3, r3, CFG_IBAT4U@l
660         mtspr   IBAT4L, r4
661         mtspr   IBAT4U, r3
662         isync
663
664         /* DBAT 4 */
665         addis   r4, r0, CFG_DBAT4L@h
666         ori     r4, r4, CFG_DBAT4L@l
667         addis   r3, r0, CFG_DBAT4U@h
668         ori     r3, r3, CFG_DBAT4U@l
669         mtspr   DBAT4L, r4
670         mtspr   DBAT4U, r3
671         isync
672
673         /* IBAT 5 */
674         addis   r4, r0, CFG_IBAT5L@h
675         ori     r4, r4, CFG_IBAT5L@l
676         addis   r3, r0, CFG_IBAT5U@h
677         ori     r3, r3, CFG_IBAT5U@l
678         mtspr   IBAT5L, r4
679         mtspr   IBAT5U, r3
680         isync
681
682         /* DBAT 5 */
683         addis   r4, r0, CFG_DBAT5L@h
684         ori     r4, r4, CFG_DBAT5L@l
685         addis   r3, r0, CFG_DBAT5U@h
686         ori     r3, r3, CFG_DBAT5U@l
687         mtspr   DBAT5L, r4
688         mtspr   DBAT5U, r3
689         isync
690
691         /* IBAT 6 */
692         addis   r4, r0, CFG_IBAT6L@h
693         ori     r4, r4, CFG_IBAT6L@l
694         addis   r3, r0, CFG_IBAT6U@h
695         ori     r3, r3, CFG_IBAT6U@l
696         mtspr   IBAT6L, r4
697         mtspr   IBAT6U, r3
698         isync
699
700         /* DBAT 6 */
701         addis   r4, r0, CFG_DBAT6L@h
702         ori     r4, r4, CFG_DBAT6L@l
703         addis   r3, r0, CFG_DBAT6U@h
704         ori     r3, r3, CFG_DBAT6U@l
705         mtspr   DBAT6L, r4
706         mtspr   DBAT6U, r3
707         isync
708
709         /* IBAT 7 */
710         addis   r4, r0, CFG_IBAT7L@h
711         ori     r4, r4, CFG_IBAT7L@l
712         addis   r3, r0, CFG_IBAT7U@h
713         ori     r3, r3, CFG_IBAT7U@l
714         mtspr   IBAT7L, r4
715         mtspr   IBAT7U, r3
716         isync
717
718         /* DBAT 7 */
719         addis   r4, r0, CFG_DBAT7L@h
720         ori     r4, r4, CFG_DBAT7L@l
721         addis   r3, r0, CFG_DBAT7U@h
722         ori     r3, r3, CFG_DBAT7U@l
723         mtspr   DBAT7L, r4
724         mtspr   DBAT7U, r3
725         isync
726 #endif
727
728         /* Invalidate TLBs.
729          * -> for (val = 0; val < 0x20000; val+=0x1000)
730          * ->   tlbie(val);
731          */
732         lis     r3, 0
733         lis     r5, 2
734
735 1:
736         tlbie   r3
737         addi    r3, r3, 0x1000
738         cmp     0, 0, r3, r5
739         blt     1b
740
741         blr
742
743         .globl enable_addr_trans
744 enable_addr_trans:
745         /* enable address translation */
746         mfmsr   r5
747         ori     r5, r5, (MSR_IR | MSR_DR)
748         mtmsr   r5
749         isync
750         blr
751
752         .globl disable_addr_trans
753 disable_addr_trans:
754         /* disable address translation */
755         mflr    r4
756         mfmsr   r3
757         andi.   r0, r3, (MSR_IR | MSR_DR)
758         beqlr
759         andc    r3, r3, r0
760         mtspr   SRR0, r4
761         mtspr   SRR1, r3
762         rfi
763
764 /* Cache functions.
765  *
766  * Note: requires that all cache bits in
767  * HID0 are in the low half word.
768  */
769         .globl  icache_enable
770 icache_enable:
771         mfspr   r3, HID0
772         ori     r3, r3, HID0_ICE
773         lis     r4, 0
774         ori     r4, r4, HID0_ILOCK
775         andc    r3, r3, r4
776         ori     r4, r3, HID0_ICFI
777         isync
778         mtspr   HID0, r4    /* sets enable and invalidate, clears lock */
779         isync
780         mtspr   HID0, r3        /* clears invalidate */
781         blr
782
783         .globl  icache_disable
784 icache_disable:
785         mfspr   r3, HID0
786         lis     r4, 0
787         ori     r4, r4, HID0_ICE|HID0_ILOCK
788         andc    r3, r3, r4
789         ori     r4, r3, HID0_ICFI
790         isync
791         mtspr   HID0, r4     /* sets invalidate, clears enable and lock*/
792         isync
793         mtspr   HID0, r3        /* clears invalidate */
794         blr
795
796         .globl  icache_status
797 icache_status:
798         mfspr   r3, HID0
799         rlwinm  r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31
800         blr
801
802         .globl  dcache_enable
803 dcache_enable:
804         mfspr   r3, HID0
805         li      r5, HID0_DCFI|HID0_DLOCK
806         andc    r3, r3, r5
807         mtspr   HID0, r3                /* no invalidate, unlock */
808         ori     r3, r3, HID0_DCE
809         ori     r5, r3, HID0_DCFI
810         mtspr   HID0, r5                /* enable + invalidate */
811         mtspr   HID0, r3                /* enable */
812         sync
813         blr
814
815         .globl  dcache_disable
816 dcache_disable:
817         mfspr   r3, HID0
818         lis     r4, 0
819         ori     r4, r4, HID0_DCE|HID0_DLOCK
820         andc    r3, r3, r4
821         ori     r4, r3, HID0_DCI
822         sync
823         mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
824         sync
825         mtspr   HID0, r3        /* clears invalidate */
826         blr
827
828         .globl  dcache_status
829 dcache_status:
830         mfspr   r3, HID0
831         rlwinm  r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31
832         blr
833
834         .globl get_pvr
835 get_pvr:
836         mfspr   r3, PVR
837         blr
838
839 /*------------------------------------------------------------------------------- */
840 /* Function:     ppcDcbf */
841 /* Description:  Data Cache block flush */
842 /* Input:        r3 = effective address */
843 /* Output:       none. */
844 /*------------------------------------------------------------------------------- */
845         .globl  ppcDcbf
846 ppcDcbf:
847         dcbf    r0,r3
848         blr
849
850 /*------------------------------------------------------------------------------- */
851 /* Function:     ppcDcbi */
852 /* Description:  Data Cache block Invalidate */
853 /* Input:        r3 = effective address */
854 /* Output:       none. */
855 /*------------------------------------------------------------------------------- */
856         .globl  ppcDcbi
857 ppcDcbi:
858         dcbi    r0,r3
859         blr
860
861 /*--------------------------------------------------------------------------
862  * Function:     ppcDcbz
863  * Description:  Data Cache block zero.
864  * Input:        r3 = effective address
865  * Output:       none.
866  *-------------------------------------------------------------------------- */
867
868         .globl  ppcDcbz
869 ppcDcbz:
870         dcbz    r0,r3
871         blr
872
873 /*-------------------------------------------------------------------*/
874
875 /*
876  * void relocate_code (addr_sp, gd, addr_moni)
877  *
878  * This "function" does not return, instead it continues in RAM
879  * after relocating the monitor code.
880  *
881  * r3 = dest
882  * r4 = src
883  * r5 = length in bytes
884  * r6 = cachelinesize
885  */
886         .globl  relocate_code
887 relocate_code:
888         mr      r1,  r3         /* Set new stack pointer        */
889         mr      r9,  r4         /* Save copy of Global Data pointer */
890         mr      r10, r5         /* Save copy of Destination Address */
891
892         mr      r3,  r5                         /* Destination Address */
893         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address */
894         ori     r4, r4, CFG_MONITOR_BASE@l
895         lwz     r5, GOT(__init_end)
896         sub     r5, r5, r4
897         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size */
898
899         /*
900          * Fix GOT pointer:
901          *
902          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
903          *              + Destination Address
904          *
905          * Offset:
906          */
907         sub     r15, r10, r4
908
909         /* First our own GOT */
910         add     r14, r14, r15
911         /* then the one used by the C code */
912         add     r30, r30, r15
913
914         /*
915          * Now relocate code
916          */
917
918         cmplw   cr1,r3,r4
919         addi    r0,r5,3
920         srwi.   r0,r0,2
921         beq     cr1,4f          /* In place copy is not necessary */
922         beq     7f              /* Protect against 0 count        */
923         mtctr   r0
924         bge     cr1,2f
925         la      r8,-4(r4)
926         la      r7,-4(r3)
927
928         /* copy */
929 1:      lwzu    r0,4(r8)
930         stwu    r0,4(r7)
931         bdnz    1b
932
933         addi    r0,r5,3
934         srwi.   r0,r0,2
935         mtctr   r0
936         la      r8,-4(r4)
937         la      r7,-4(r3)
938
939         /* and compare */
940 20:     lwzu    r20,4(r8)
941         lwzu    r21,4(r7)
942         xor. r22, r20, r21
943         bne  30f
944         bdnz    20b
945         b 4f
946
947         /* compare failed */
948 30:     li r3, 0
949         blr
950
951 2:      slwi    r0,r0,2 /* re copy in reverse order ... y do we needed it? */
952         add     r8,r4,r0
953         add     r7,r3,r0
954 3:      lwzu    r0,-4(r8)
955         stwu    r0,-4(r7)
956         bdnz    3b
957
958 /*
959  * Now flush the cache: note that we must start from a cache aligned
960  * address. Otherwise we might miss one cache line.
961  */
962 4:      cmpwi   r6,0
963         add     r5,r3,r5
964         beq     7f              /* Always flush prefetch queue in any case */
965         subi    r0,r6,1
966         andc    r3,r3,r0
967         mr      r4,r3
968 5:      dcbst   0,r4
969         add     r4,r4,r6
970         cmplw   r4,r5
971         blt     5b
972         sync                    /* Wait for all dcbst to complete on bus */
973         mr      r4,r3
974 6:      icbi    0,r4
975         add     r4,r4,r6
976         cmplw   r4,r5
977         blt     6b
978 7:      sync                    /* Wait for all icbi to complete on bus */
979         isync
980
981 /*
982  * We are done. Do not return, instead branch to second part of board
983  * initialization, now running from RAM.
984  */
985         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
986         mtlr    r0
987         blr
988
989 in_ram:
990
991         /*
992          * Relocation Function, r14 point to got2+0x8000
993          *
994          * Adjust got2 pointers, no need to check for 0, this code
995          * already puts a few entries in the table.
996          */
997         li      r0,__got2_entries@sectoff@l
998         la      r3,GOT(_GOT2_TABLE_)
999         lwz     r11,GOT(_GOT2_TABLE_)
1000         mtctr   r0
1001         sub     r11,r3,r11
1002         addi    r3,r3,-4
1003 1:      lwzu    r0,4(r3)
1004         add     r0,r0,r11
1005         stw     r0,0(r3)
1006         bdnz    1b
1007
1008         /*
1009          * Now adjust the fixups and the pointers to the fixups
1010          * in case we need to move ourselves again.
1011          */
1012 2:      li      r0,__fixup_entries@sectoff@l
1013         lwz     r3,GOT(_FIXUP_TABLE_)
1014         cmpwi   r0,0
1015         mtctr   r0
1016         addi    r3,r3,-4
1017         beq     4f
1018 3:      lwzu    r4,4(r3)
1019         lwzux   r0,r4,r11
1020         add     r0,r0,r11
1021         stw     r10,0(r3)
1022         stw     r0,0(r4)
1023         bdnz    3b
1024 4:
1025 clear_bss:
1026         /*
1027          * Now clear BSS segment
1028          */
1029         lwz     r3,GOT(__bss_start)
1030 #if defined(CONFIG_HYMOD)
1031         /*
1032          * For HYMOD - the environment is the very last item in flash.
1033          * The real .bss stops just before environment starts, so only
1034          * clear up to that point.
1035          *
1036          * taken from mods for FADS board
1037          */
1038         lwz     r4,GOT(environment)
1039 #else
1040         lwz     r4,GOT(_end)
1041 #endif
1042
1043         cmplw   0, r3, r4
1044         beq     6f
1045
1046         li      r0, 0
1047 5:
1048         stw     r0, 0(r3)
1049         addi    r3, r3, 4
1050         cmplw   0, r3, r4
1051         bne     5b
1052 6:
1053
1054         mr      r3, r9          /* Global Data pointer          */
1055         mr      r4, r10         /* Destination Address          */
1056         bl      board_init_r
1057
1058         /*
1059          * Copy exception vector code to low memory
1060          *
1061          * r3: dest_addr
1062          * r7: source address, r8: end address, r9: target address
1063          */
1064         .globl  trap_init
1065 trap_init:
1066         lwz     r7, GOT(_start)
1067         lwz     r8, GOT(_end_of_vectors)
1068
1069         li      r9, 0x100       /* reset vector always at 0x100 */
1070
1071         cmplw   0, r7, r8
1072         bgelr                   /* return if r7>=r8 - just in case */
1073
1074         mflr    r4              /* save link register */
1075 1:
1076         lwz     r0, 0(r7)
1077         stw     r0, 0(r9)
1078         addi    r7, r7, 4
1079         addi    r9, r9, 4
1080         cmplw   0, r7, r8
1081         bne     1b
1082
1083         /*
1084          * relocate `hdlr' and `int_return' entries
1085          */
1086         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1087         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
1088 2:
1089         bl      trap_reloc
1090         addi    r7, r7, 0x100           /* next exception vector */
1091         cmplw   0, r7, r8
1092         blt     2b
1093
1094         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1095         bl      trap_reloc
1096
1097         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1098         bl      trap_reloc
1099
1100         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1101         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1102 3:
1103         bl      trap_reloc
1104         addi    r7, r7, 0x100           /* next exception vector */
1105         cmplw   0, r7, r8
1106         blt     3b
1107
1108         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1109         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1110 4:
1111         bl      trap_reloc
1112         addi    r7, r7, 0x100           /* next exception vector */
1113         cmplw   0, r7, r8
1114         blt     4b
1115
1116         mfmsr   r3                      /* now that the vectors have */
1117         lis     r7, MSR_IP@h            /* relocated into low memory */
1118         ori     r7, r7, MSR_IP@l        /* MSR[IP] can be turned off */
1119         andc    r3, r3, r7              /* (if it was on) */
1120         SYNC                            /* Some chip revs need this... */
1121         mtmsr   r3
1122         SYNC
1123
1124         mtlr    r4                      /* restore link register    */
1125         blr
1126
1127         /*
1128          * Function: relocate entries for one exception vector
1129          */
1130 trap_reloc:
1131         lwz     r0, 0(r7)               /* hdlr ...             */
1132         add     r0, r0, r3              /*  ... += dest_addr    */
1133         stw     r0, 0(r7)
1134
1135         lwz     r0, 4(r7)               /* int_return ...       */
1136         add     r0, r0, r3              /*  ... += dest_addr    */
1137         stw     r0, 4(r7)
1138
1139         blr
1140
1141 #ifdef CFG_INIT_RAM_LOCK
1142 lock_ram_in_cache:
1143         /* Allocate Initial RAM in data cache.
1144          */
1145         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1146         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1147         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1148                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1149         mtctr   r2
1150 1:
1151         dcbz    r0, r3
1152         addi    r3, r3, 32
1153         bdnz    1b
1154
1155         /* Lock the data cache */
1156         mfspr   r0, HID0
1157         ori     r0, r0, 0x1000
1158         sync
1159         mtspr   HID0, r0
1160         sync
1161         blr
1162
1163 .globl unlock_ram_in_cache
1164 unlock_ram_in_cache:
1165         /* invalidate the INIT_RAM section */
1166         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1167         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1168         li      r2,512
1169         mtctr   r2
1170 1:      icbi    r0, r3
1171         dcbi    r0, r3
1172         addi    r3, r3, 32
1173         bdnz    1b
1174         sync                    /* Wait for all icbi to complete on bus */
1175         isync
1176
1177         /* Unlock the data cache and invalidate it */
1178         mfspr   r3, HID0
1179         li      r5, HID0_DLOCK|HID0_DCFI
1180         andc    r3, r3, r5              /* no invalidate, unlock */
1181         ori     r5, r3, HID0_DCFI       /* invalidate, unlock */
1182         mtspr   HID0, r5                /* invalidate, unlock */
1183         mtspr   HID0, r3                /* no invalidate, unlock */
1184         sync
1185         blr
1186 #endif
1187
1188 map_flash_by_law1:
1189         /* When booting from ROM (Flash or EPROM), clear the  */
1190         /* Address Mask in OR0 so ROM appears everywhere      */
1191         /*----------------------------------------------------*/
1192         lis     r3, (CFG_IMMRBAR)@h  /* r3 <= CFG_IMMRBAR    */
1193         lwz     r4, OR0@l(r3)
1194         li      r5, 0x7fff        /* r5 <= 0x00007FFFF */
1195         and     r4, r4, r5
1196         stw     r4, OR0@l(r3)     /* OR0 <= OR0 & 0x00007FFFF */
1197
1198         /* As MPC8349E User's Manual presented, when RCW[BMS] is set to 0,
1199          * system will boot from 0x0000_0100, and the LBLAWBAR0[BASE_ADDR]
1200          * reset value is 0x00000; when RCW[BMS] is set to 1, system will boot
1201          * from 0xFFF0_0100, and the LBLAWBAR0[BASE_ADDR] reset value is
1202          * 0xFF800.  From the hard resetting to here, the processor fetched and
1203          * executed the instructions one by one.  There is not absolutely
1204          * jumping happened.  Laterly, the u-boot code has to do an absolutely
1205          * jumping to tell the CPU instruction fetching component what the
1206          * u-boot TEXT base address is.  Because the TEXT base resides in the
1207          * boot ROM memory space, to garantee the code can run smoothly after
1208          * that jumping, we must map in the entire boot ROM by Local Access
1209          * Window.  Sometimes, we desire an non-0x00000 or non-0xFF800 starting
1210          * address for boot ROM, such as 0xFE000000.  In this case, the default
1211          * LBIU Local Access Widow 0 will not cover this memory space.  So, we
1212          * need another window to map in it.
1213          */
1214         lis r4, (CFG_FLASH_BASE)@h
1215         ori r4, r4, (CFG_FLASH_BASE)@l
1216         stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CFG_FLASH_BASE */
1217
1218         /* Store 0x80000012 + log2(CFG_FLASH_SIZE) into LBLAWAR1 */
1219         lis r4, (0x80000012)@h
1220         ori r4, r4, (0x80000012)@l
1221         li r5, CFG_FLASH_SIZE
1222 1:      srawi. r5, r5, 1        /* r5 = r5 >> 1 */
1223         addi r4, r4, 1
1224         bne 1b
1225
1226         stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */
1227         blr
1228
1229         /* Though all the LBIU Local Access Windows and LBC Banks will be
1230          * initialized in the C code, we'd better configure boot ROM's
1231          * window 0 and bank 0 correctly at here.
1232          */
1233 remap_flash_by_law0:
1234         /* Initialize the BR0 with the boot ROM starting address. */
1235         lwz r4, BR0(r3)
1236         li  r5, 0x7FFF
1237         and r4, r4, r5
1238         lis r5, (CFG_FLASH_BASE & 0xFFFF8000)@h
1239         ori r5, r5, (CFG_FLASH_BASE & 0xFFFF8000)@l
1240         or  r5, r5, r4
1241         stw r5, BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
1242
1243         lwz r4, OR0(r3)
1244         lis r5, ~((CFG_FLASH_SIZE << 4) - 1)
1245         or r4, r4, r5
1246         stw r4, OR0(r3)
1247
1248         lis r4, (CFG_FLASH_BASE)@h
1249         ori r4, r4, (CFG_FLASH_BASE)@l
1250         stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CFG_FLASH_BASE */
1251
1252         /* Store 0x80000012 + log2(CFG_FLASH_SIZE) into LBLAWAR0 */
1253         lis r4, (0x80000012)@h
1254         ori r4, r4, (0x80000012)@l
1255         li r5, CFG_FLASH_SIZE
1256 1:      srawi. r5, r5, 1 /* r5 = r5 >> 1 */
1257         addi r4, r4, 1
1258         bne 1b
1259         stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= Flash Size */
1260
1261
1262         xor r4, r4, r4
1263         stw r4, LBLAWBAR1(r3)
1264         stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
1265         blr