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