]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc86xx/start.S
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / cpu / mpc86xx / start.S
1 /*
2  * Copyright 2004, 2007 Freescale Semiconductor.
3  * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*  U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
25  *
26  *
27  *  The processor starts at 0xfff00100 and the code is executed
28  *  from flash. The code is organized to be at an other address
29  *  in memory, but as long we don't jump around before relocating.
30  *  board_init lies at a quite high address and when the cpu has
31  *  jumped there, everything is ok.
32  */
33 #include <config.h>
34 #include <mpc86xx.h>
35 #include <timestamp.h>
36 #include <version.h>
37
38 #include <ppc_asm.tmpl>
39 #include <ppc_defs.h>
40
41 #include <asm/cache.h>
42 #include <asm/mmu.h>
43
44 #ifndef CONFIG_IDENT_STRING
45 #define CONFIG_IDENT_STRING ""
46 #endif
47
48 /*
49  * Need MSR_DR | MSR_IR enabled to access I/O (printf) in exceptions
50  */
51
52 /*
53  * Set up GOT: Global Offset Table
54  *
55  * Use r14 to access the GOT
56  */
57         START_GOT
58         GOT_ENTRY(_GOT2_TABLE_)
59         GOT_ENTRY(_FIXUP_TABLE_)
60
61         GOT_ENTRY(_start)
62         GOT_ENTRY(_start_of_vectors)
63         GOT_ENTRY(_end_of_vectors)
64         GOT_ENTRY(transfer_to_handler)
65
66         GOT_ENTRY(__init_end)
67         GOT_ENTRY(_end)
68         GOT_ENTRY(__bss_start)
69         END_GOT
70
71 /*
72  * r3 - 1st arg to board_init(): IMMP pointer
73  * r4 - 2nd arg to board_init(): boot flag
74  */
75         .text
76         .long   0x27051956              /* U-Boot Magic Number */
77         .globl  version_string
78 version_string:
79         .ascii  U_BOOT_VERSION
80         .ascii  " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
81         .ascii  CONFIG_IDENT_STRING, "\0"
82
83         . = EXC_OFF_SYS_RESET
84         .globl  _start
85 _start:
86         li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH */
87         b       boot_cold
88         sync
89
90         . = EXC_OFF_SYS_RESET + 0x10
91
92         .globl  _start_warm
93 _start_warm:
94         li      r21, BOOTFLAG_WARM      /* Software reboot */
95         b       boot_warm
96         sync
97
98         /* the boot code is located below the exception table */
99
100         .globl  _start_of_vectors
101 _start_of_vectors:
102
103 /* Machine check */
104         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
105
106 /* Data Storage exception. */
107         STD_EXCEPTION(0x300, DataStorage, UnknownException)
108
109 /* Instruction Storage exception. */
110         STD_EXCEPTION(0x400, InstStorage, UnknownException)
111
112 /* External Interrupt exception. */
113         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
114
115 /* Alignment exception. */
116         . = 0x600
117 Alignment:
118         EXCEPTION_PROLOG(SRR0, SRR1)
119         mfspr   r4,DAR
120         stw     r4,_DAR(r21)
121         mfspr   r5,DSISR
122         stw     r5,_DSISR(r21)
123         addi    r3,r1,STACK_FRAME_OVERHEAD
124         li      r20,MSR_KERNEL
125         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
126         lwz     r6,GOT(transfer_to_handler)
127         mtlr    r6
128         blrl
129 .L_Alignment:
130         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
131         .long   int_return - _start + EXC_OFF_SYS_RESET
132
133 /* Program check exception */
134         . = 0x700
135 ProgramCheck:
136         EXCEPTION_PROLOG(SRR0, SRR1)
137         addi    r3,r1,STACK_FRAME_OVERHEAD
138         li      r20,MSR_KERNEL
139         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
140         lwz     r6,GOT(transfer_to_handler)
141         mtlr    r6
142         blrl
143 .L_ProgramCheck:
144         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
145         .long   int_return - _start + EXC_OFF_SYS_RESET
146
147         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
148
149         /* I guess we could implement decrementer, and may have
150          * to someday for timekeeping.
151          */
152         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
153         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
154         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
155         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
156         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
157         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
158         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
159         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
160         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
161         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
162         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
163         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
164         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
165         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
166         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
167         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
168         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
169         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
170         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
171         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
172         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
173         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
174         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
175
176         .globl  _end_of_vectors
177 _end_of_vectors:
178
179         . = 0x2000
180
181 boot_cold:
182 boot_warm:
183         /*
184          * NOTE: Only Cpu 0 will ever come here.  Other cores go to an
185          * address specified by the BPTR
186          */
187 1:
188 #ifdef CONFIG_SYS_RAMBOOT
189         /* disable everything */
190         li      r0, 0
191         mtspr   HID0, r0
192         sync
193         mtmsr   0
194 #endif
195
196         /* Invalidate BATs */
197         bl      invalidate_bats
198         sync
199         /* Invalidate all of TLB before MMU turn on */
200         bl      clear_tlbs
201         sync
202
203 #ifdef CONFIG_SYS_L2
204         /* init the L2 cache */
205         lis     r3, L2_INIT@h
206         ori     r3, r3, L2_INIT@l
207         mtspr   l2cr, r3
208         /* invalidate the L2 cache */
209         bl      l2cache_invalidate
210         sync
211 #endif
212
213         /*
214          * Calculate absolute address in FLASH and jump there
215          *------------------------------------------------------*/
216         lis     r3, CONFIG_SYS_MONITOR_BASE_EARLY@h
217         ori     r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l
218         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
219         mtlr    r3
220         blr
221
222 in_flash:
223         /* let the C-code set up the rest                       */
224         /*                                                      */
225         /* Be careful to keep code relocatable !                */
226         /*------------------------------------------------------*/
227         /* perform low-level init */
228
229         /* enable extended addressing */
230         bl      enable_ext_addr
231
232         /* setup the bats */
233         bl      early_bats
234
235         /*
236          * Cache must be enabled here for stack-in-cache trick.
237          * This means we need to enable the BATS.
238          * Cache should be turned on after BATs, since by default
239          * everything is write-through.
240          */
241
242         /* enable address translation */
243         mfmsr   r5
244         ori     r5, r5, (MSR_IR | MSR_DR)
245         lis     r3,addr_trans_enabled@h
246         ori     r3, r3, addr_trans_enabled@l
247         mtspr   SPRN_SRR0,r3
248         mtspr   SPRN_SRR1,r5
249         rfi
250
251 addr_trans_enabled:
252         /* enable and invalidate the data cache */
253 /*      bl      l1dcache_enable */
254         bl      dcache_enable
255         sync
256
257 #if 1
258         bl      icache_enable
259 #endif
260
261 #ifdef CONFIG_SYS_INIT_RAM_LOCK
262         bl      lock_ram_in_cache
263         sync
264 #endif
265
266 #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
267         bl      setup_ccsrbar
268 #endif
269
270         /* set up the stack pointer in our newly created
271          * cache-ram (r1) */
272         lis     r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
273         ori     r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
274
275         li      r0, 0           /* Make room for stack frame header and */
276         stwu    r0, -4(r1)      /* clear final stack frame so that      */
277         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
278
279         GET_GOT                 /* initialize GOT access        */
280
281         /* run low-level CPU init code     (from Flash) */
282         bl      cpu_init_f
283         sync
284
285 #ifdef  RUN_DIAG
286
287         /* Load PX_AUX register address in r4 */
288         lis     r4, PIXIS_BASE@h
289         ori     r4, r4, 0x6
290         /* Load contents of PX_AUX in r3 bits 24 to 31*/
291         lbz     r3, 0(r4)
292
293         /* Mask and obtain the bit in r3 */
294         rlwinm. r3, r3, 0, 24, 24
295         /* If not zero, jump and continue with u-boot */
296         bne     diag_done
297
298         /* Load back contents of PX_AUX in r3 bits 24 to 31 */
299         lbz     r3, 0(r4)
300         /* Set the MSB of the register value */
301         ori     r3, r3, 0x80
302         /* Write value in r3 back to PX_AUX */
303         stb     r3, 0(r4)
304
305         /* Get the address to jump to in r3*/
306         lis     r3, CONFIG_SYS_DIAG_ADDR@h
307         ori     r3, r3, CONFIG_SYS_DIAG_ADDR@l
308
309         /* Load the LR with the branch address */
310         mtlr    r3
311
312         /* Branch to diagnostic */
313         blr
314
315 diag_done:
316 #endif
317
318 /*      bl      l2cache_enable */
319         mr      r3, r21
320
321         /* r3: BOOTFLAG */
322         /* run 1st part of board init code (from Flash)   */
323         bl      board_init_f
324         sync
325
326         /* NOTREACHED */
327
328         .globl  invalidate_bats
329 invalidate_bats:
330
331         li      r0, 0
332         /* invalidate BATs */
333         mtspr   IBAT0U, r0
334         mtspr   IBAT1U, r0
335         mtspr   IBAT2U, r0
336         mtspr   IBAT3U, r0
337         mtspr   IBAT4U, r0
338         mtspr   IBAT5U, r0
339         mtspr   IBAT6U, r0
340         mtspr   IBAT7U, r0
341
342         isync
343         mtspr   DBAT0U, r0
344         mtspr   DBAT1U, r0
345         mtspr   DBAT2U, r0
346         mtspr   DBAT3U, r0
347         mtspr   DBAT4U, r0
348         mtspr   DBAT5U, r0
349         mtspr   DBAT6U, r0
350         mtspr   DBAT7U, r0
351
352         isync
353         sync
354         blr
355
356 /*
357  * early_bats:
358  *
359  * Set up bats needed early on - this is usually the BAT for the
360  * stack-in-cache, the Flash, and CCSR space
361  */
362         .globl  early_bats
363 early_bats:
364         /* IBAT 3 */
365         lis     r4, CONFIG_SYS_IBAT3L@h
366         ori     r4, r4, CONFIG_SYS_IBAT3L@l
367         lis     r3, CONFIG_SYS_IBAT3U@h
368         ori     r3, r3, CONFIG_SYS_IBAT3U@l
369         mtspr   IBAT3L, r4
370         mtspr   IBAT3U, r3
371         isync
372
373         /* DBAT 3 */
374         lis     r4, CONFIG_SYS_DBAT3L@h
375         ori     r4, r4, CONFIG_SYS_DBAT3L@l
376         lis     r3, CONFIG_SYS_DBAT3U@h
377         ori     r3, r3, CONFIG_SYS_DBAT3U@l
378         mtspr   DBAT3L, r4
379         mtspr   DBAT3U, r3
380         isync
381
382         /* IBAT 5 */
383         lis     r4, CONFIG_SYS_IBAT5L@h
384         ori     r4, r4, CONFIG_SYS_IBAT5L@l
385         lis     r3, CONFIG_SYS_IBAT5U@h
386         ori     r3, r3, CONFIG_SYS_IBAT5U@l
387         mtspr   IBAT5L, r4
388         mtspr   IBAT5U, r3
389         isync
390
391         /* DBAT 5 */
392         lis     r4, CONFIG_SYS_DBAT5L@h
393         ori     r4, r4, CONFIG_SYS_DBAT5L@l
394         lis     r3, CONFIG_SYS_DBAT5U@h
395         ori     r3, r3, CONFIG_SYS_DBAT5U@l
396         mtspr   DBAT5L, r4
397         mtspr   DBAT5U, r3
398         isync
399
400         /* IBAT 6 */
401         lis     r4, CONFIG_SYS_IBAT6L_EARLY@h
402         ori     r4, r4, CONFIG_SYS_IBAT6L_EARLY@l
403         lis     r3, CONFIG_SYS_IBAT6U_EARLY@h
404         ori     r3, r3, CONFIG_SYS_IBAT6U_EARLY@l
405         mtspr   IBAT6L, r4
406         mtspr   IBAT6U, r3
407         isync
408
409         /* DBAT 6 */
410         lis     r4, CONFIG_SYS_DBAT6L_EARLY@h
411         ori     r4, r4, CONFIG_SYS_DBAT6L_EARLY@l
412         lis     r3, CONFIG_SYS_DBAT6U_EARLY@h
413         ori     r3, r3, CONFIG_SYS_DBAT6U_EARLY@l
414         mtspr   DBAT6L, r4
415         mtspr   DBAT6U, r3
416         isync
417
418 #if(CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
419         /* IBAT 7 */
420         lis     r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@h
421         ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@l
422         lis     r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@h
423         ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@l
424         mtspr   IBAT7L, r4
425         mtspr   IBAT7U, r3
426         isync
427
428         /* DBAT 7 */
429         lis     r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@h
430         ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@l
431         lis     r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@h
432         ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@l
433         mtspr   DBAT7L, r4
434         mtspr   DBAT7U, r3
435         isync
436 #endif
437         blr
438
439         .globl clear_tlbs
440 clear_tlbs:
441         addis   r3, 0, 0x0000
442         addis   r5, 0, 0x4
443         isync
444 tlblp:
445         tlbie   r3
446         sync
447         addi    r3, r3, 0x1000
448         cmp     0, 0, r3, r5
449         blt tlblp
450         blr
451
452         .globl disable_addr_trans
453 disable_addr_trans:
454         /* disable address translation */
455         mflr    r4
456         mfmsr   r3
457         andi.   r0, r3, (MSR_IR | MSR_DR)
458         beqlr
459         andc    r3, r3, r0
460         mtspr   SRR0, r4
461         mtspr   SRR1, r3
462         rfi
463
464 /*
465  * This code finishes saving the registers to the exception frame
466  * and jumps to the appropriate handler for the exception.
467  * Register r21 is pointer into trap frame, r1 has new stack pointer.
468  */
469         .globl  transfer_to_handler
470 transfer_to_handler:
471         stw     r22,_NIP(r21)
472         lis     r22,MSR_POW@h
473         andc    r23,r23,r22
474         stw     r23,_MSR(r21)
475         SAVE_GPR(7, r21)
476         SAVE_4GPRS(8, r21)
477         SAVE_8GPRS(12, r21)
478         SAVE_8GPRS(24, r21)
479         mflr    r23
480         andi.   r24,r23,0x3f00          /* get vector offset */
481         stw     r24,TRAP(r21)
482         li      r22,0
483         stw     r22,RESULT(r21)
484         mtspr   SPRG2,r22               /* r1 is now kernel sp */
485         lwz     r24,0(r23)              /* virtual address of handler */
486         lwz     r23,4(r23)              /* where to go when done */
487         mtspr   SRR0,r24
488         mtspr   SRR1,r20
489         mtlr    r23
490         SYNC
491         rfi                             /* jump to handler, enable MMU */
492
493 int_return:
494         mfmsr   r28             /* Disable interrupts */
495         li      r4,0
496         ori     r4,r4,MSR_EE
497         andc    r28,r28,r4
498         SYNC                    /* Some chip revs need this... */
499         mtmsr   r28
500         SYNC
501         lwz     r2,_CTR(r1)
502         lwz     r0,_LINK(r1)
503         mtctr   r2
504         mtlr    r0
505         lwz     r2,_XER(r1)
506         lwz     r0,_CCR(r1)
507         mtspr   XER,r2
508         mtcrf   0xFF,r0
509         REST_10GPRS(3, r1)
510         REST_10GPRS(13, r1)
511         REST_8GPRS(23, r1)
512         REST_GPR(31, r1)
513         lwz     r2,_NIP(r1)     /* Restore environment */
514         lwz     r0,_MSR(r1)
515         mtspr   SRR0,r2
516         mtspr   SRR1,r0
517         lwz     r0,GPR0(r1)
518         lwz     r2,GPR2(r1)
519         lwz     r1,GPR1(r1)
520         SYNC
521         rfi
522
523         .globl  dc_read
524 dc_read:
525         blr
526
527         .globl get_pvr
528 get_pvr:
529         mfspr   r3, PVR
530         blr
531
532         .globl get_svr
533 get_svr:
534         mfspr   r3, SVR
535         blr
536
537
538 /*
539  * Function:    in8
540  * Description: Input 8 bits
541  */
542         .globl  in8
543 in8:
544         lbz     r3,0x0000(r3)
545         blr
546
547 /*
548  * Function:    out8
549  * Description: Output 8 bits
550  */
551         .globl  out8
552 out8:
553         stb     r4,0x0000(r3)
554         blr
555
556 /*
557  * Function:    out16
558  * Description: Output 16 bits
559  */
560         .globl  out16
561 out16:
562         sth     r4,0x0000(r3)
563         blr
564
565 /*
566  * Function:    out16r
567  * Description: Byte reverse and output 16 bits
568  */
569         .globl  out16r
570 out16r:
571         sthbrx  r4,r0,r3
572         blr
573
574 /*
575  * Function:    out32
576  * Description: Output 32 bits
577  */
578         .globl  out32
579 out32:
580         stw     r4,0x0000(r3)
581         blr
582
583 /*
584  * Function:    out32r
585  * Description: Byte reverse and output 32 bits
586  */
587         .globl  out32r
588 out32r:
589         stwbrx  r4,r0,r3
590         blr
591
592 /*
593  * Function:    in16
594  * Description: Input 16 bits
595  */
596         .globl  in16
597 in16:
598         lhz     r3,0x0000(r3)
599         blr
600
601 /*
602  * Function:    in16r
603  * Description: Input 16 bits and byte reverse
604  */
605         .globl  in16r
606 in16r:
607         lhbrx   r3,r0,r3
608         blr
609
610 /*
611  * Function:    in32
612  * Description: Input 32 bits
613  */
614         .globl  in32
615 in32:
616         lwz     3,0x0000(3)
617         blr
618
619 /*
620  * Function:    in32r
621  * Description: Input 32 bits and byte reverse
622  */
623         .globl  in32r
624 in32r:
625         lwbrx   r3,r0,r3
626         blr
627
628 /*
629  * void relocate_code (addr_sp, gd, addr_moni)
630  *
631  * This "function" does not return, instead it continues in RAM
632  * after relocating the monitor code.
633  *
634  * r3 = dest
635  * r4 = src
636  * r5 = length in bytes
637  * r6 = cachelinesize
638  */
639         .globl  relocate_code
640 relocate_code:
641
642         mr      r1,  r3         /* Set new stack pointer                */
643         mr      r9,  r4         /* Save copy of Global Data pointer     */
644         mr      r10, r5         /* Save copy of Destination Address     */
645
646         mr      r3,  r5                         /* Destination Address  */
647         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
648         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
649         lwz     r5, GOT(__init_end)
650         sub     r5, r5, r4
651         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
652
653         /*
654          * Fix GOT pointer:
655          *
656          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
657          *
658          * Offset:
659          */
660         sub     r15, r10, r4
661
662         /* First our own GOT */
663         add     r14, r14, r15
664         /* then the one used by the C code */
665         add     r30, r30, r15
666
667         /*
668          * Now relocate code
669          */
670         cmplw   cr1,r3,r4
671         addi    r0,r5,3
672         srwi.   r0,r0,2
673         beq     cr1,4f          /* In place copy is not necessary       */
674         beq     7f              /* Protect against 0 count              */
675         mtctr   r0
676         bge     cr1,2f
677
678         la      r8,-4(r4)
679         la      r7,-4(r3)
680 1:      lwzu    r0,4(r8)
681         stwu    r0,4(r7)
682         bdnz    1b
683         b       4f
684
685 2:      slwi    r0,r0,2
686         add     r8,r4,r0
687         add     r7,r3,r0
688 3:      lwzu    r0,-4(r8)
689         stwu    r0,-4(r7)
690         bdnz    3b
691 /*
692  * Now flush the cache: note that we must start from a cache aligned
693  * address. Otherwise we might miss one cache line.
694  */
695 4:      cmpwi   r6,0
696         add     r5,r3,r5
697         beq     7f              /* Always flush prefetch queue in any case */
698         subi    r0,r6,1
699         andc    r3,r3,r0
700         mr      r4,r3
701 5:      dcbst   0,r4
702         add     r4,r4,r6
703         cmplw   r4,r5
704         blt     5b
705         sync                    /* Wait for all dcbst to complete on bus */
706         mr      r4,r3
707 6:      icbi    0,r4
708         add     r4,r4,r6
709         cmplw   r4,r5
710         blt     6b
711 7:      sync                    /* Wait for all icbi to complete on bus */
712         isync
713
714 /*
715  * We are done. Do not return, instead branch to second part of board
716  * initialization, now running from RAM.
717  */
718         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
719         mtlr    r0
720         blr
721
722 in_ram:
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         cmpwi   r0,0
737         beq-    2f
738         add     r0,r0,r11
739         stw     r0,0(r3)
740 2:      bdnz    1b
741
742         /*
743          * Now adjust the fixups and the pointers to the fixups
744          * in case we need to move ourselves again.
745          */
746         li      r0,__fixup_entries@sectoff@l
747         lwz     r3,GOT(_FIXUP_TABLE_)
748         cmpwi   r0,0
749         mtctr   r0
750         addi    r3,r3,-4
751         beq     4f
752 3:      lwzu    r4,4(r3)
753         lwzux   r0,r4,r11
754         add     r0,r0,r11
755         stw     r10,0(r3)
756         stw     r0,0(r4)
757         bdnz    3b
758 4:
759 /* clear_bss: */
760         /*
761          * Now clear BSS segment
762          */
763         lwz     r3,GOT(__bss_start)
764         lwz     r4,GOT(_end)
765
766         cmplw   0, r3, r4
767         beq     6f
768
769         li      r0, 0
770 5:
771         stw     r0, 0(r3)
772         addi    r3, r3, 4
773         cmplw   0, r3, r4
774         bne     5b
775 6:
776         mr      r3, r9          /* Init Date pointer            */
777         mr      r4, r10         /* Destination Address          */
778         bl      board_init_r
779
780         /* not reached - end relocate_code */
781 /*-----------------------------------------------------------------------*/
782
783         /*
784          * Copy exception vector code to low memory
785          *
786          * r3: dest_addr
787          * r7: source address, r8: end address, r9: target address
788          */
789         .globl  trap_init
790 trap_init:
791         lwz     r7, GOT(_start)
792         lwz     r8, GOT(_end_of_vectors)
793
794         li      r9, 0x100               /* reset vector always at 0x100 */
795
796         cmplw   0, r7, r8
797         bgelr                           /* return if r7>=r8 - just in case */
798
799         mflr    r4                      /* save link register           */
800 1:
801         lwz     r0, 0(r7)
802         stw     r0, 0(r9)
803         addi    r7, r7, 4
804         addi    r9, r9, 4
805         cmplw   0, r7, r8
806         bne     1b
807
808         /*
809          * relocate `hdlr' and `int_return' entries
810          */
811         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
812         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
813 2:
814         bl      trap_reloc
815         addi    r7, r7, 0x100           /* next exception vector        */
816         cmplw   0, r7, r8
817         blt     2b
818
819         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
820         bl      trap_reloc
821
822         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
823         bl      trap_reloc
824
825         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
826         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
827 3:
828         bl      trap_reloc
829         addi    r7, r7, 0x100           /* next exception vector        */
830         cmplw   0, r7, r8
831         blt     3b
832
833         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
834         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
835 4:
836         bl      trap_reloc
837         addi    r7, r7, 0x100           /* next exception vector        */
838         cmplw   0, r7, r8
839         blt     4b
840
841         /* enable execptions from RAM vectors */
842         mfmsr   r7
843         li      r8,MSR_IP
844         andc    r7,r7,r8
845         ori     r7,r7,MSR_ME            /* Enable Machine Check */
846         mtmsr   r7
847
848         mtlr    r4                      /* restore link register        */
849         blr
850
851         /*
852          * Function: relocate entries for one exception vector
853          */
854 trap_reloc:
855         lwz     r0, 0(r7)               /* hdlr ...                     */
856         add     r0, r0, r3              /*  ... += dest_addr            */
857         stw     r0, 0(r7)
858
859         lwz     r0, 4(r7)               /* int_return ...               */
860         add     r0, r0, r3              /*  ... += dest_addr            */
861         stw     r0, 4(r7)
862
863         sync
864         isync
865
866         blr
867
868 .globl enable_ext_addr
869 enable_ext_addr:
870         mfspr   r0, HID0
871         lis     r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
872         ori     r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
873         mtspr   HID0, r0
874         sync
875         isync
876         blr
877
878 #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
879 .globl setup_ccsrbar
880 setup_ccsrbar:
881         /* Special sequence needed to update CCSRBAR itself */
882         lis     r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
883         ori     r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
884
885         lis     r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
886         ori     r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
887         srwi    r5,r5,12
888         li      r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
889         rlwimi  r5,r6,20,8,11
890         stw     r5, 0(r4) /* Store physical value of CCSR */
891         isync
892
893         lis     r5, TEXT_BASE@h
894         ori     r5,r5,TEXT_BASE@l
895         lwz     r5, 0(r5)
896         isync
897
898         /* Use VA of CCSR to do read */
899         lis     r3, CONFIG_SYS_CCSRBAR@h
900         lwz     r5, CONFIG_SYS_CCSRBAR@l(r3)
901         isync
902
903         blr
904 #endif
905
906 #ifdef CONFIG_SYS_INIT_RAM_LOCK
907 lock_ram_in_cache:
908         /* Allocate Initial RAM in data cache.
909          */
910         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
911         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
912         li      r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
913                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
914         mtctr   r4
915 1:
916         dcbz    r0, r3
917         addi    r3, r3, 32
918         bdnz    1b
919 #if 1
920 /* Lock the data cache */
921         mfspr   r0, HID0
922         ori     r0, r0, 0x1000
923         sync
924         mtspr   HID0, r0
925         sync
926         blr
927 #endif
928 #if 0
929         /* Lock the first way of the data cache */
930         mfspr   r0, LDSTCR
931         ori     r0, r0, 0x0080
932 #if defined(CONFIG_ALTIVEC)
933         dssall
934 #endif
935         sync
936         mtspr   LDSTCR, r0
937         sync
938         isync
939         blr
940 #endif
941
942 .globl unlock_ram_in_cache
943 unlock_ram_in_cache:
944         /* invalidate the INIT_RAM section */
945         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
946         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
947         li      r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
948                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
949         mtctr   r4
950 1:      icbi    r0, r3
951         addi    r3, r3, 32
952         bdnz    1b
953         sync                    /* Wait for all icbi to complete on bus */
954         isync
955 #if 1
956 /* Unlock the data cache and invalidate it */
957         mfspr   r0, HID0
958         li      r3,0x1000
959         andc    r0,r0,r3
960         li      r3,0x0400
961         or      r0,r0,r3
962         sync
963         mtspr   HID0, r0
964         sync
965         blr
966 #endif
967 #if 0
968         /* Unlock the first way of the data cache */
969         mfspr   r0, LDSTCR
970         li      r3,0x0080
971         andc    r0,r0,r3
972 #ifdef CONFIG_ALTIVEC
973         dssall
974 #endif
975         sync
976         mtspr   LDSTCR, r0
977         sync
978         isync
979         li      r3,0x0400
980         or      r0,r0,r3
981         sync
982         mtspr   HID0, r0
983         sync
984         blr
985 #endif
986 #endif