]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc86xx/start.S
powerpc 86xx: Handle CCSR relocation earlier
[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         /* if this is a multi-core system we need to check which cpu
184          * this is, if it is not cpu 0 send the cpu to the linux reset
185          * vector */
186 #if (CONFIG_NUM_CPUS > 1)
187         mfspr   r0, MSSCR0
188         andi.   r0, r0, 0x0020
189         rlwinm  r0,r0,27,31,31
190         mtspr   PIR, r0
191         beq     1f
192
193         bl      secondary_cpu_setup
194 #endif
195
196 1:
197 #ifdef CONFIG_SYS_RAMBOOT
198         /* disable everything */
199         li      r0, 0
200         mtspr   HID0, r0
201         sync
202         mtmsr   0
203 #endif
204
205         /* Invalidate BATs */
206         bl      invalidate_bats
207         sync
208         /* Invalidate all of TLB before MMU turn on */
209         bl      clear_tlbs
210         sync
211
212 #ifdef CONFIG_SYS_L2
213         /* init the L2 cache */
214         lis     r3, L2_INIT@h
215         ori     r3, r3, L2_INIT@l
216         mtspr   l2cr, r3
217         /* invalidate the L2 cache */
218         bl      l2cache_invalidate
219         sync
220 #endif
221
222 #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
223         /* setup ccsrbar now while we're in real mode */
224         bl      setup_ccsrbar
225 #endif
226
227         /*
228          * Calculate absolute address in FLASH and jump there
229          *------------------------------------------------------*/
230         lis     r3, CONFIG_SYS_MONITOR_BASE@h
231         ori     r3, r3, CONFIG_SYS_MONITOR_BASE@l
232         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
233         mtlr    r3
234         blr
235
236 in_flash:
237         /* let the C-code set up the rest                       */
238         /*                                                      */
239         /* Be careful to keep code relocatable !                */
240         /*------------------------------------------------------*/
241         /* perform low-level init */
242
243         /* enable extended addressing */
244         bl      enable_ext_addr
245
246         /* setup the bats */
247         bl      early_bats
248
249         /*
250          * Cache must be enabled here for stack-in-cache trick.
251          * This means we need to enable the BATS.
252          * Cache should be turned on after BATs, since by default
253          * everything is write-through.
254          */
255
256         /* enable address translation */
257         bl      enable_addr_trans
258         sync
259
260         /* enable and invalidate the data cache */
261 /*      bl      l1dcache_enable */
262         bl      dcache_enable
263         sync
264
265 #if 1
266         bl      icache_enable
267 #endif
268
269 #ifdef CONFIG_SYS_INIT_RAM_LOCK
270         bl      lock_ram_in_cache
271         sync
272 #endif
273
274         /* set up the stack pointer in our newly created
275          * cache-ram (r1) */
276         lis     r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
277         ori     r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
278
279         li      r0, 0           /* Make room for stack frame header and */
280         stwu    r0, -4(r1)      /* clear final stack frame so that      */
281         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
282
283         GET_GOT                 /* initialize GOT access        */
284
285         /* setup the rest of the bats */
286         bl      setup_bats
287         sync
288
289
290         /* run low-level CPU init code     (from Flash) */
291         bl      cpu_init_f
292         sync
293
294 #ifdef  RUN_DIAG
295
296         /* Load PX_AUX register address in r4 */
297         lis     r4, 0xf810
298         ori     r4, r4, 0x6
299         /* Load contents of PX_AUX in r3 bits 24 to 31*/
300         lbz     r3, 0(r4)
301
302         /* Mask and obtain the bit in r3 */
303         rlwinm. r3, r3, 0, 24, 24
304         /* If not zero, jump and continue with u-boot */
305         bne     diag_done
306
307         /* Load back contents of PX_AUX in r3 bits 24 to 31 */
308         lbz     r3, 0(r4)
309         /* Set the MSB of the register value */
310         ori     r3, r3, 0x80
311         /* Write value in r3 back to PX_AUX */
312         stb     r3, 0(r4)
313
314         /* Get the address to jump to in r3*/
315         lis     r3, CONFIG_SYS_DIAG_ADDR@h
316         ori     r3, r3, CONFIG_SYS_DIAG_ADDR@l
317
318         /* Load the LR with the branch address */
319         mtlr    r3
320
321         /* Branch to diagnostic */
322         blr
323
324 diag_done:
325 #endif
326
327 /*      bl      l2cache_enable */
328         mr      r3, r21
329
330         /* r3: BOOTFLAG */
331         /* run 1st part of board init code (from Flash)   */
332         bl      board_init_f
333         sync
334
335         /* NOTREACHED */
336
337         .globl  invalidate_bats
338 invalidate_bats:
339
340         li      r0, 0
341         /* invalidate BATs */
342         mtspr   IBAT0U, r0
343         mtspr   IBAT1U, r0
344         mtspr   IBAT2U, r0
345         mtspr   IBAT3U, r0
346         mtspr   IBAT4U, r0
347         mtspr   IBAT5U, r0
348         mtspr   IBAT6U, r0
349         mtspr   IBAT7U, r0
350
351         isync
352         mtspr   DBAT0U, r0
353         mtspr   DBAT1U, r0
354         mtspr   DBAT2U, r0
355         mtspr   DBAT3U, r0
356         mtspr   DBAT4U, r0
357         mtspr   DBAT5U, r0
358         mtspr   DBAT6U, r0
359         mtspr   DBAT7U, r0
360
361         isync
362         sync
363         blr
364
365 /*
366  * early_bats:
367  *
368  * Set up bats needed early on - this is usually the BAT for the
369  * stack-in-cache, the Flash, and CCSR space
370  */
371         .globl  early_bats
372 early_bats:
373         /* IBAT 3 */
374         lis     r4, CONFIG_SYS_IBAT3L@h
375         ori     r4, r4, CONFIG_SYS_IBAT3L@l
376         lis     r3, CONFIG_SYS_IBAT3U@h
377         ori     r3, r3, CONFIG_SYS_IBAT3U@l
378         mtspr   IBAT3L, r4
379         mtspr   IBAT3U, r3
380         isync
381
382         /* DBAT 3 */
383         lis     r4, CONFIG_SYS_DBAT3L@h
384         ori     r4, r4, CONFIG_SYS_DBAT3L@l
385         lis     r3, CONFIG_SYS_DBAT3U@h
386         ori     r3, r3, CONFIG_SYS_DBAT3U@l
387         mtspr   DBAT3L, r4
388         mtspr   DBAT3U, r3
389         isync
390
391         /* IBAT 5 */
392         lis     r4, CONFIG_SYS_IBAT5L@h
393         ori     r4, r4, CONFIG_SYS_IBAT5L@l
394         lis     r3, CONFIG_SYS_IBAT5U@h
395         ori     r3, r3, CONFIG_SYS_IBAT5U@l
396         mtspr   IBAT5L, r4
397         mtspr   IBAT5U, r3
398         isync
399
400         /* DBAT 5 */
401         lis     r4, CONFIG_SYS_DBAT5L@h
402         ori     r4, r4, CONFIG_SYS_DBAT5L@l
403         lis     r3, CONFIG_SYS_DBAT5U@h
404         ori     r3, r3, CONFIG_SYS_DBAT5U@l
405         mtspr   DBAT5L, r4
406         mtspr   DBAT5U, r3
407         isync
408
409         /* IBAT 6 */
410         lis     r4, CONFIG_SYS_IBAT6L@h
411         ori     r4, r4, CONFIG_SYS_IBAT6L@l
412         lis     r3, CONFIG_SYS_IBAT6U@h
413         ori     r3, r3, CONFIG_SYS_IBAT6U@l
414         mtspr   IBAT6L, r4
415         mtspr   IBAT6U, r3
416         isync
417
418         /* DBAT 6 */
419         lis     r4, CONFIG_SYS_DBAT6L@h
420         ori     r4, r4, CONFIG_SYS_DBAT6L@l
421         lis     r3, CONFIG_SYS_DBAT6U@h
422         ori     r3, r3, CONFIG_SYS_DBAT6U@l
423         mtspr   DBAT6L, r4
424         mtspr   DBAT6U, r3
425         isync
426         blr
427
428         .globl clear_tlbs
429 clear_tlbs:
430         addis   r3, 0, 0x0000
431         addis   r5, 0, 0x4
432         isync
433 tlblp:
434         tlbie   r3
435         sync
436         addi    r3, r3, 0x1000
437         cmp     0, 0, r3, r5
438         blt tlblp
439         blr
440
441         .globl enable_addr_trans
442 enable_addr_trans:
443         /* enable address translation */
444         mfmsr   r5
445         ori     r5, r5, (MSR_IR | MSR_DR)
446         mtmsr   r5
447         isync
448         blr
449
450         .globl disable_addr_trans
451 disable_addr_trans:
452         /* disable address translation */
453         mflr    r4
454         mfmsr   r3
455         andi.   r0, r3, (MSR_IR | MSR_DR)
456         beqlr
457         andc    r3, r3, r0
458         mtspr   SRR0, r4
459         mtspr   SRR1, r3
460         rfi
461
462 /*
463  * This code finishes saving the registers to the exception frame
464  * and jumps to the appropriate handler for the exception.
465  * Register r21 is pointer into trap frame, r1 has new stack pointer.
466  */
467         .globl  transfer_to_handler
468 transfer_to_handler:
469         stw     r22,_NIP(r21)
470         lis     r22,MSR_POW@h
471         andc    r23,r23,r22
472         stw     r23,_MSR(r21)
473         SAVE_GPR(7, r21)
474         SAVE_4GPRS(8, r21)
475         SAVE_8GPRS(12, r21)
476         SAVE_8GPRS(24, r21)
477         mflr    r23
478         andi.   r24,r23,0x3f00          /* get vector offset */
479         stw     r24,TRAP(r21)
480         li      r22,0
481         stw     r22,RESULT(r21)
482         mtspr   SPRG2,r22               /* r1 is now kernel sp */
483         lwz     r24,0(r23)              /* virtual address of handler */
484         lwz     r23,4(r23)              /* where to go when done */
485         mtspr   SRR0,r24
486         mtspr   SRR1,r20
487         mtlr    r23
488         SYNC
489         rfi                             /* jump to handler, enable MMU */
490
491 int_return:
492         mfmsr   r28             /* Disable interrupts */
493         li      r4,0
494         ori     r4,r4,MSR_EE
495         andc    r28,r28,r4
496         SYNC                    /* Some chip revs need this... */
497         mtmsr   r28
498         SYNC
499         lwz     r2,_CTR(r1)
500         lwz     r0,_LINK(r1)
501         mtctr   r2
502         mtlr    r0
503         lwz     r2,_XER(r1)
504         lwz     r0,_CCR(r1)
505         mtspr   XER,r2
506         mtcrf   0xFF,r0
507         REST_10GPRS(3, r1)
508         REST_10GPRS(13, r1)
509         REST_8GPRS(23, r1)
510         REST_GPR(31, r1)
511         lwz     r2,_NIP(r1)     /* Restore environment */
512         lwz     r0,_MSR(r1)
513         mtspr   SRR0,r2
514         mtspr   SRR1,r0
515         lwz     r0,GPR0(r1)
516         lwz     r2,GPR2(r1)
517         lwz     r1,GPR1(r1)
518         SYNC
519         rfi
520
521         .globl  dc_read
522 dc_read:
523         blr
524
525         .globl get_pvr
526 get_pvr:
527         mfspr   r3, PVR
528         blr
529
530         .globl get_svr
531 get_svr:
532         mfspr   r3, SVR
533         blr
534
535
536 /*
537  * Function:    in8
538  * Description: Input 8 bits
539  */
540         .globl  in8
541 in8:
542         lbz     r3,0x0000(r3)
543         blr
544
545 /*
546  * Function:    out8
547  * Description: Output 8 bits
548  */
549         .globl  out8
550 out8:
551         stb     r4,0x0000(r3)
552         blr
553
554 /*
555  * Function:    out16
556  * Description: Output 16 bits
557  */
558         .globl  out16
559 out16:
560         sth     r4,0x0000(r3)
561         blr
562
563 /*
564  * Function:    out16r
565  * Description: Byte reverse and output 16 bits
566  */
567         .globl  out16r
568 out16r:
569         sthbrx  r4,r0,r3
570         blr
571
572 /*
573  * Function:    out32
574  * Description: Output 32 bits
575  */
576         .globl  out32
577 out32:
578         stw     r4,0x0000(r3)
579         blr
580
581 /*
582  * Function:    out32r
583  * Description: Byte reverse and output 32 bits
584  */
585         .globl  out32r
586 out32r:
587         stwbrx  r4,r0,r3
588         blr
589
590 /*
591  * Function:    in16
592  * Description: Input 16 bits
593  */
594         .globl  in16
595 in16:
596         lhz     r3,0x0000(r3)
597         blr
598
599 /*
600  * Function:    in16r
601  * Description: Input 16 bits and byte reverse
602  */
603         .globl  in16r
604 in16r:
605         lhbrx   r3,r0,r3
606         blr
607
608 /*
609  * Function:    in32
610  * Description: Input 32 bits
611  */
612         .globl  in32
613 in32:
614         lwz     3,0x0000(3)
615         blr
616
617 /*
618  * Function:    in32r
619  * Description: Input 32 bits and byte reverse
620  */
621         .globl  in32r
622 in32r:
623         lwbrx   r3,r0,r3
624         blr
625
626 /*
627  * void relocate_code (addr_sp, gd, addr_moni)
628  *
629  * This "function" does not return, instead it continues in RAM
630  * after relocating the monitor code.
631  *
632  * r3 = dest
633  * r4 = src
634  * r5 = length in bytes
635  * r6 = cachelinesize
636  */
637         .globl  relocate_code
638 relocate_code:
639
640         mr      r1,  r3         /* Set new stack pointer                */
641         mr      r9,  r4         /* Save copy of Global Data pointer     */
642         mr      r10, r5         /* Save copy of Destination Address     */
643
644         mr      r3,  r5                         /* Destination Address  */
645         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
646         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
647         lwz     r5, GOT(__init_end)
648         sub     r5, r5, r4
649         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
650
651         /*
652          * Fix GOT pointer:
653          *
654          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
655          *
656          * Offset:
657          */
658         sub     r15, r10, r4
659
660         /* First our own GOT */
661         add     r14, r14, r15
662         /* then the one used by the C code */
663         add     r30, r30, r15
664
665         /*
666          * Now relocate code
667          */
668         cmplw   cr1,r3,r4
669         addi    r0,r5,3
670         srwi.   r0,r0,2
671         beq     cr1,4f          /* In place copy is not necessary       */
672         beq     7f              /* Protect against 0 count              */
673         mtctr   r0
674         bge     cr1,2f
675
676         la      r8,-4(r4)
677         la      r7,-4(r3)
678 1:      lwzu    r0,4(r8)
679         stwu    r0,4(r7)
680         bdnz    1b
681         b       4f
682
683 2:      slwi    r0,r0,2
684         add     r8,r4,r0
685         add     r7,r3,r0
686 3:      lwzu    r0,-4(r8)
687         stwu    r0,-4(r7)
688         bdnz    3b
689 /*
690  * Now flush the cache: note that we must start from a cache aligned
691  * address. Otherwise we might miss one cache line.
692  */
693 4:      cmpwi   r6,0
694         add     r5,r3,r5
695         beq     7f              /* Always flush prefetch queue in any case */
696         subi    r0,r6,1
697         andc    r3,r3,r0
698         mr      r4,r3
699 5:      dcbst   0,r4
700         add     r4,r4,r6
701         cmplw   r4,r5
702         blt     5b
703         sync                    /* Wait for all dcbst to complete on bus */
704         mr      r4,r3
705 6:      icbi    0,r4
706         add     r4,r4,r6
707         cmplw   r4,r5
708         blt     6b
709 7:      sync                    /* Wait for all icbi to complete on bus */
710         isync
711
712 /*
713  * We are done. Do not return, instead branch to second part of board
714  * initialization, now running from RAM.
715  */
716         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
717         mtlr    r0
718         blr
719
720 in_ram:
721         /*
722          * Relocation Function, r14 point to got2+0x8000
723          *
724          * Adjust got2 pointers, no need to check for 0, this code
725          * already puts a few entries in the table.
726          */
727         li      r0,__got2_entries@sectoff@l
728         la      r3,GOT(_GOT2_TABLE_)
729         lwz     r11,GOT(_GOT2_TABLE_)
730         mtctr   r0
731         sub     r11,r3,r11
732         addi    r3,r3,-4
733 1:      lwzu    r0,4(r3)
734         add     r0,r0,r11
735         stw     r0,0(r3)
736         bdnz    1b
737
738         /*
739          * Now adjust the fixups and the pointers to the fixups
740          * in case we need to move ourselves again.
741          */
742 2:      li      r0,__fixup_entries@sectoff@l
743         lwz     r3,GOT(_FIXUP_TABLE_)
744         cmpwi   r0,0
745         mtctr   r0
746         addi    r3,r3,-4
747         beq     4f
748 3:      lwzu    r4,4(r3)
749         lwzux   r0,r4,r11
750         add     r0,r0,r11
751         stw     r10,0(r3)
752         stw     r0,0(r4)
753         bdnz    3b
754 4:
755 /* clear_bss: */
756         /*
757          * Now clear BSS segment
758          */
759         lwz     r3,GOT(__bss_start)
760         lwz     r4,GOT(_end)
761
762         cmplw   0, r3, r4
763         beq     6f
764
765         li      r0, 0
766 5:
767         stw     r0, 0(r3)
768         addi    r3, r3, 4
769         cmplw   0, r3, r4
770         bne     5b
771 6:
772         mr      r3, r9          /* Init Date pointer            */
773         mr      r4, r10         /* Destination Address          */
774         bl      board_init_r
775
776         /* not reached - end relocate_code */
777 /*-----------------------------------------------------------------------*/
778
779         /*
780          * Copy exception vector code to low memory
781          *
782          * r3: dest_addr
783          * r7: source address, r8: end address, r9: target address
784          */
785         .globl  trap_init
786 trap_init:
787         lwz     r7, GOT(_start)
788         lwz     r8, GOT(_end_of_vectors)
789
790         li      r9, 0x100               /* reset vector always at 0x100 */
791
792         cmplw   0, r7, r8
793         bgelr                           /* return if r7>=r8 - just in case */
794
795         mflr    r4                      /* save link register           */
796 1:
797         lwz     r0, 0(r7)
798         stw     r0, 0(r9)
799         addi    r7, r7, 4
800         addi    r9, r9, 4
801         cmplw   0, r7, r8
802         bne     1b
803
804         /*
805          * relocate `hdlr' and `int_return' entries
806          */
807         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
808         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
809 2:
810         bl      trap_reloc
811         addi    r7, r7, 0x100           /* next exception vector        */
812         cmplw   0, r7, r8
813         blt     2b
814
815         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
816         bl      trap_reloc
817
818         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
819         bl      trap_reloc
820
821         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
822         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
823 3:
824         bl      trap_reloc
825         addi    r7, r7, 0x100           /* next exception vector        */
826         cmplw   0, r7, r8
827         blt     3b
828
829         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
830         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
831 4:
832         bl      trap_reloc
833         addi    r7, r7, 0x100           /* next exception vector        */
834         cmplw   0, r7, r8
835         blt     4b
836
837         /* enable execptions from RAM vectors */
838         mfmsr   r7
839         li      r8,MSR_IP
840         andc    r7,r7,r8
841         ori     r7,r7,MSR_ME            /* Enable Machine Check */
842         mtmsr   r7
843
844         mtlr    r4                      /* restore link register        */
845         blr
846
847         /*
848          * Function: relocate entries for one exception vector
849          */
850 trap_reloc:
851         lwz     r0, 0(r7)               /* hdlr ...                     */
852         add     r0, r0, r3              /*  ... += dest_addr            */
853         stw     r0, 0(r7)
854
855         lwz     r0, 4(r7)               /* int_return ...               */
856         add     r0, r0, r3              /*  ... += dest_addr            */
857         stw     r0, 4(r7)
858
859         sync
860         isync
861
862         blr
863
864 .globl enable_ext_addr
865 enable_ext_addr:
866         mfspr   r0, HID0
867         lis     r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
868         ori     r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
869         mtspr   HID0, r0
870         sync
871         isync
872         blr
873
874 #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
875 .globl setup_ccsrbar
876 setup_ccsrbar:
877         /* Special sequence needed to update CCSRBAR itself */
878         lis     r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
879         ori     r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
880
881         lis     r5, CONFIG_SYS_CCSRBAR@h
882         ori     r5, r5, CONFIG_SYS_CCSRBAR@l
883         srwi    r6,r5,12
884         stw     r6, 0(r4)
885         isync
886
887         lis     r5, 0xffff
888         ori     r5,r5,0xf000
889         lwz     r5, 0(r5)
890         isync
891
892         lis     r3, CONFIG_SYS_CCSRBAR@h
893         lwz     r5, CONFIG_SYS_CCSRBAR@l(r3)
894         isync
895
896         blr
897 #endif
898
899 #ifdef CONFIG_SYS_INIT_RAM_LOCK
900 lock_ram_in_cache:
901         /* Allocate Initial RAM in data cache.
902          */
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:
909         dcbz    r0, r3
910         addi    r3, r3, 32
911         bdnz    1b
912 #if 1
913 /* Lock the data cache */
914         mfspr   r0, HID0
915         ori     r0, r0, 0x1000
916         sync
917         mtspr   HID0, r0
918         sync
919         blr
920 #endif
921 #if 0
922         /* Lock the first way of the data cache */
923         mfspr   r0, LDSTCR
924         ori     r0, r0, 0x0080
925 #if defined(CONFIG_ALTIVEC)
926         dssall
927 #endif
928         sync
929         mtspr   LDSTCR, r0
930         sync
931         isync
932         blr
933 #endif
934
935 .globl unlock_ram_in_cache
936 unlock_ram_in_cache:
937         /* invalidate the INIT_RAM section */
938         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
939         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
940         li      r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
941                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
942         mtctr   r4
943 1:      icbi    r0, r3
944         addi    r3, r3, 32
945         bdnz    1b
946         sync                    /* Wait for all icbi to complete on bus */
947         isync
948 #if 1
949 /* Unlock the data cache and invalidate it */
950         mfspr   r0, HID0
951         li      r3,0x1000
952         andc    r0,r0,r3
953         li      r3,0x0400
954         or      r0,r0,r3
955         sync
956         mtspr   HID0, r0
957         sync
958         blr
959 #endif
960 #if 0
961         /* Unlock the first way of the data cache */
962         mfspr   r0, LDSTCR
963         li      r3,0x0080
964         andc    r0,r0,r3
965 #ifdef CONFIG_ALTIVEC
966         dssall
967 #endif
968         sync
969         mtspr   LDSTCR, r0
970         sync
971         isync
972         li      r3,0x0400
973         or      r0,r0,r3
974         sync
975         mtspr   HID0, r0
976         sync
977         blr
978 #endif
979 #endif
980
981 /* If this is a multi-cpu system then we need to handle the
982  * 2nd cpu.  The assumption is that the 2nd cpu is being
983  * held in boot holdoff mode until the 1st cpu unlocks it
984  * from Linux.  We'll do some basic cpu init and then pass
985  * it to the Linux Reset Vector.
986  * Sri:  Much of this initialization is not required. Linux
987  * rewrites the bats, and the sprs and also enables the L1 cache.
988  */
989 #if (CONFIG_NUM_CPUS > 1)
990 .globl secondary_cpu_setup
991 secondary_cpu_setup:
992         /* Do only core setup on all cores except cpu0 */
993         bl      invalidate_bats
994         sync
995         bl      enable_ext_addr
996
997 #ifdef CONFIG_SYS_L2
998         /* init the L2 cache */
999         addis   r3, r0, L2_INIT@h
1000         ori     r3, r3, L2_INIT@l
1001         sync
1002         mtspr   l2cr, r3
1003 #ifdef CONFIG_ALTIVEC
1004         dssall
1005 #endif
1006         /* invalidate the L2 cache */
1007         bl      l2cache_invalidate
1008         sync
1009 #endif
1010
1011         /* enable and invalidate the data cache */
1012         bl      dcache_enable
1013         sync
1014
1015         /* enable and invalidate the instruction cache*/
1016         bl      icache_enable
1017         sync
1018
1019         /* TBEN in HID0 */
1020         mfspr   r4, HID0
1021         oris    r4, r4, 0x0400
1022         mtspr   HID0, r4
1023         sync
1024         isync
1025
1026         /* MCP|SYNCBE|ABE in HID1 */
1027         mfspr   r4, HID1
1028         oris    r4, r4, 0x8000
1029         ori     r4, r4, 0x0C00
1030         mtspr   HID1, r4
1031         sync
1032         isync
1033
1034         lis     r3, CONFIG_LINUX_RESET_VEC@h
1035         ori     r3, r3, CONFIG_LINUX_RESET_VEC@l
1036         mtlr    r3
1037         blr
1038
1039         /* Never Returns, Running in Linux Now */
1040 #endif