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