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