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