]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc86xx/start.S
mpc8641: Change 32-bit memory map
[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_EARLY@h
221         ori     r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@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         mfmsr   r5
248         ori     r5, r5, (MSR_IR | MSR_DR)
249         lis     r3,addr_trans_enabled@h
250         ori     r3, r3, addr_trans_enabled@l
251         mtspr   SPRN_SRR0,r3
252         mtspr   SPRN_SRR1,r5
253         rfi
254
255 addr_trans_enabled:
256         /* enable and invalidate the data cache */
257 /*      bl      l1dcache_enable */
258         bl      dcache_enable
259         sync
260
261 #if 1
262         bl      icache_enable
263 #endif
264
265 #ifdef CONFIG_SYS_INIT_RAM_LOCK
266         bl      lock_ram_in_cache
267         sync
268 #endif
269
270         /* set up the stack pointer in our newly created
271          * cache-ram (r1) */
272         lis     r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
273         ori     r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
274
275         li      r0, 0           /* Make room for stack frame header and */
276         stwu    r0, -4(r1)      /* clear final stack frame so that      */
277         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
278
279         GET_GOT                 /* initialize GOT access        */
280
281         /* run low-level CPU init code     (from Flash) */
282         bl      cpu_init_f
283         sync
284
285 #ifdef  RUN_DIAG
286
287         /* Load PX_AUX register address in r4 */
288         lis     r4, PIXIS_BASE@h
289         ori     r4, r4, 0x6
290         /* Load contents of PX_AUX in r3 bits 24 to 31*/
291         lbz     r3, 0(r4)
292
293         /* Mask and obtain the bit in r3 */
294         rlwinm. r3, r3, 0, 24, 24
295         /* If not zero, jump and continue with u-boot */
296         bne     diag_done
297
298         /* Load back contents of PX_AUX in r3 bits 24 to 31 */
299         lbz     r3, 0(r4)
300         /* Set the MSB of the register value */
301         ori     r3, r3, 0x80
302         /* Write value in r3 back to PX_AUX */
303         stb     r3, 0(r4)
304
305         /* Get the address to jump to in r3*/
306         lis     r3, CONFIG_SYS_DIAG_ADDR@h
307         ori     r3, r3, CONFIG_SYS_DIAG_ADDR@l
308
309         /* Load the LR with the branch address */
310         mtlr    r3
311
312         /* Branch to diagnostic */
313         blr
314
315 diag_done:
316 #endif
317
318 /*      bl      l2cache_enable */
319         mr      r3, r21
320
321         /* r3: BOOTFLAG */
322         /* run 1st part of board init code (from Flash)   */
323         bl      board_init_f
324         sync
325
326         /* NOTREACHED */
327
328         .globl  invalidate_bats
329 invalidate_bats:
330
331         li      r0, 0
332         /* invalidate BATs */
333         mtspr   IBAT0U, r0
334         mtspr   IBAT1U, r0
335         mtspr   IBAT2U, r0
336         mtspr   IBAT3U, r0
337         mtspr   IBAT4U, r0
338         mtspr   IBAT5U, r0
339         mtspr   IBAT6U, r0
340         mtspr   IBAT7U, r0
341
342         isync
343         mtspr   DBAT0U, r0
344         mtspr   DBAT1U, r0
345         mtspr   DBAT2U, r0
346         mtspr   DBAT3U, r0
347         mtspr   DBAT4U, r0
348         mtspr   DBAT5U, r0
349         mtspr   DBAT6U, r0
350         mtspr   DBAT7U, r0
351
352         isync
353         sync
354         blr
355
356 /*
357  * early_bats:
358  *
359  * Set up bats needed early on - this is usually the BAT for the
360  * stack-in-cache, the Flash, and CCSR space
361  */
362         .globl  early_bats
363 early_bats:
364         /* IBAT 3 */
365         lis     r4, CONFIG_SYS_IBAT3L@h
366         ori     r4, r4, CONFIG_SYS_IBAT3L@l
367         lis     r3, CONFIG_SYS_IBAT3U@h
368         ori     r3, r3, CONFIG_SYS_IBAT3U@l
369         mtspr   IBAT3L, r4
370         mtspr   IBAT3U, r3
371         isync
372
373         /* DBAT 3 */
374         lis     r4, CONFIG_SYS_DBAT3L@h
375         ori     r4, r4, CONFIG_SYS_DBAT3L@l
376         lis     r3, CONFIG_SYS_DBAT3U@h
377         ori     r3, r3, CONFIG_SYS_DBAT3U@l
378         mtspr   DBAT3L, r4
379         mtspr   DBAT3U, r3
380         isync
381
382         /* IBAT 5 */
383         lis     r4, CONFIG_SYS_IBAT5L@h
384         ori     r4, r4, CONFIG_SYS_IBAT5L@l
385         lis     r3, CONFIG_SYS_IBAT5U@h
386         ori     r3, r3, CONFIG_SYS_IBAT5U@l
387         mtspr   IBAT5L, r4
388         mtspr   IBAT5U, r3
389         isync
390
391         /* DBAT 5 */
392         lis     r4, CONFIG_SYS_DBAT5L@h
393         ori     r4, r4, CONFIG_SYS_DBAT5L@l
394         lis     r3, CONFIG_SYS_DBAT5U@h
395         ori     r3, r3, CONFIG_SYS_DBAT5U@l
396         mtspr   DBAT5L, r4
397         mtspr   DBAT5U, r3
398         isync
399
400         /* IBAT 6 */
401         lis     r4, CONFIG_SYS_IBAT6L_EARLY@h
402         ori     r4, r4, CONFIG_SYS_IBAT6L_EARLY@l
403         lis     r3, CONFIG_SYS_IBAT6U_EARLY@h
404         ori     r3, r3, CONFIG_SYS_IBAT6U_EARLY@l
405         mtspr   IBAT6L, r4
406         mtspr   IBAT6U, r3
407         isync
408
409         /* DBAT 6 */
410         lis     r4, CONFIG_SYS_DBAT6L_EARLY@h
411         ori     r4, r4, CONFIG_SYS_DBAT6L_EARLY@l
412         lis     r3, CONFIG_SYS_DBAT6U_EARLY@h
413         ori     r3, r3, CONFIG_SYS_DBAT6U_EARLY@l
414         mtspr   DBAT6L, r4
415         mtspr   DBAT6U, r3
416         isync
417         blr
418
419         .globl clear_tlbs
420 clear_tlbs:
421         addis   r3, 0, 0x0000
422         addis   r5, 0, 0x4
423         isync
424 tlblp:
425         tlbie   r3
426         sync
427         addi    r3, r3, 0x1000
428         cmp     0, 0, r3, r5
429         blt tlblp
430         blr
431
432         .globl disable_addr_trans
433 disable_addr_trans:
434         /* disable address translation */
435         mflr    r4
436         mfmsr   r3
437         andi.   r0, r3, (MSR_IR | MSR_DR)
438         beqlr
439         andc    r3, r3, r0
440         mtspr   SRR0, r4
441         mtspr   SRR1, r3
442         rfi
443
444 /*
445  * This code finishes saving the registers to the exception frame
446  * and jumps to the appropriate handler for the exception.
447  * Register r21 is pointer into trap frame, r1 has new stack pointer.
448  */
449         .globl  transfer_to_handler
450 transfer_to_handler:
451         stw     r22,_NIP(r21)
452         lis     r22,MSR_POW@h
453         andc    r23,r23,r22
454         stw     r23,_MSR(r21)
455         SAVE_GPR(7, r21)
456         SAVE_4GPRS(8, r21)
457         SAVE_8GPRS(12, r21)
458         SAVE_8GPRS(24, r21)
459         mflr    r23
460         andi.   r24,r23,0x3f00          /* get vector offset */
461         stw     r24,TRAP(r21)
462         li      r22,0
463         stw     r22,RESULT(r21)
464         mtspr   SPRG2,r22               /* r1 is now kernel sp */
465         lwz     r24,0(r23)              /* virtual address of handler */
466         lwz     r23,4(r23)              /* where to go when done */
467         mtspr   SRR0,r24
468         mtspr   SRR1,r20
469         mtlr    r23
470         SYNC
471         rfi                             /* jump to handler, enable MMU */
472
473 int_return:
474         mfmsr   r28             /* Disable interrupts */
475         li      r4,0
476         ori     r4,r4,MSR_EE
477         andc    r28,r28,r4
478         SYNC                    /* Some chip revs need this... */
479         mtmsr   r28
480         SYNC
481         lwz     r2,_CTR(r1)
482         lwz     r0,_LINK(r1)
483         mtctr   r2
484         mtlr    r0
485         lwz     r2,_XER(r1)
486         lwz     r0,_CCR(r1)
487         mtspr   XER,r2
488         mtcrf   0xFF,r0
489         REST_10GPRS(3, r1)
490         REST_10GPRS(13, r1)
491         REST_8GPRS(23, r1)
492         REST_GPR(31, r1)
493         lwz     r2,_NIP(r1)     /* Restore environment */
494         lwz     r0,_MSR(r1)
495         mtspr   SRR0,r2
496         mtspr   SRR1,r0
497         lwz     r0,GPR0(r1)
498         lwz     r2,GPR2(r1)
499         lwz     r1,GPR1(r1)
500         SYNC
501         rfi
502
503         .globl  dc_read
504 dc_read:
505         blr
506
507         .globl get_pvr
508 get_pvr:
509         mfspr   r3, PVR
510         blr
511
512         .globl get_svr
513 get_svr:
514         mfspr   r3, SVR
515         blr
516
517
518 /*
519  * Function:    in8
520  * Description: Input 8 bits
521  */
522         .globl  in8
523 in8:
524         lbz     r3,0x0000(r3)
525         blr
526
527 /*
528  * Function:    out8
529  * Description: Output 8 bits
530  */
531         .globl  out8
532 out8:
533         stb     r4,0x0000(r3)
534         blr
535
536 /*
537  * Function:    out16
538  * Description: Output 16 bits
539  */
540         .globl  out16
541 out16:
542         sth     r4,0x0000(r3)
543         blr
544
545 /*
546  * Function:    out16r
547  * Description: Byte reverse and output 16 bits
548  */
549         .globl  out16r
550 out16r:
551         sthbrx  r4,r0,r3
552         blr
553
554 /*
555  * Function:    out32
556  * Description: Output 32 bits
557  */
558         .globl  out32
559 out32:
560         stw     r4,0x0000(r3)
561         blr
562
563 /*
564  * Function:    out32r
565  * Description: Byte reverse and output 32 bits
566  */
567         .globl  out32r
568 out32r:
569         stwbrx  r4,r0,r3
570         blr
571
572 /*
573  * Function:    in16
574  * Description: Input 16 bits
575  */
576         .globl  in16
577 in16:
578         lhz     r3,0x0000(r3)
579         blr
580
581 /*
582  * Function:    in16r
583  * Description: Input 16 bits and byte reverse
584  */
585         .globl  in16r
586 in16r:
587         lhbrx   r3,r0,r3
588         blr
589
590 /*
591  * Function:    in32
592  * Description: Input 32 bits
593  */
594         .globl  in32
595 in32:
596         lwz     3,0x0000(3)
597         blr
598
599 /*
600  * Function:    in32r
601  * Description: Input 32 bits and byte reverse
602  */
603         .globl  in32r
604 in32r:
605         lwbrx   r3,r0,r3
606         blr
607
608 /*
609  * void relocate_code (addr_sp, gd, addr_moni)
610  *
611  * This "function" does not return, instead it continues in RAM
612  * after relocating the monitor code.
613  *
614  * r3 = dest
615  * r4 = src
616  * r5 = length in bytes
617  * r6 = cachelinesize
618  */
619         .globl  relocate_code
620 relocate_code:
621
622         mr      r1,  r3         /* Set new stack pointer                */
623         mr      r9,  r4         /* Save copy of Global Data pointer     */
624         mr      r10, r5         /* Save copy of Destination Address     */
625
626         mr      r3,  r5                         /* Destination Address  */
627         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
628         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
629         lwz     r5, GOT(__init_end)
630         sub     r5, r5, r4
631         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
632
633         /*
634          * Fix GOT pointer:
635          *
636          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
637          *
638          * Offset:
639          */
640         sub     r15, r10, r4
641
642         /* First our own GOT */
643         add     r14, r14, r15
644         /* then the one used by the C code */
645         add     r30, r30, r15
646
647         /*
648          * Now relocate code
649          */
650         cmplw   cr1,r3,r4
651         addi    r0,r5,3
652         srwi.   r0,r0,2
653         beq     cr1,4f          /* In place copy is not necessary       */
654         beq     7f              /* Protect against 0 count              */
655         mtctr   r0
656         bge     cr1,2f
657
658         la      r8,-4(r4)
659         la      r7,-4(r3)
660 1:      lwzu    r0,4(r8)
661         stwu    r0,4(r7)
662         bdnz    1b
663         b       4f
664
665 2:      slwi    r0,r0,2
666         add     r8,r4,r0
667         add     r7,r3,r0
668 3:      lwzu    r0,-4(r8)
669         stwu    r0,-4(r7)
670         bdnz    3b
671 /*
672  * Now flush the cache: note that we must start from a cache aligned
673  * address. Otherwise we might miss one cache line.
674  */
675 4:      cmpwi   r6,0
676         add     r5,r3,r5
677         beq     7f              /* Always flush prefetch queue in any case */
678         subi    r0,r6,1
679         andc    r3,r3,r0
680         mr      r4,r3
681 5:      dcbst   0,r4
682         add     r4,r4,r6
683         cmplw   r4,r5
684         blt     5b
685         sync                    /* Wait for all dcbst to complete on bus */
686         mr      r4,r3
687 6:      icbi    0,r4
688         add     r4,r4,r6
689         cmplw   r4,r5
690         blt     6b
691 7:      sync                    /* Wait for all icbi to complete on bus */
692         isync
693
694 /*
695  * We are done. Do not return, instead branch to second part of board
696  * initialization, now running from RAM.
697  */
698         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
699         mtlr    r0
700         blr
701
702 in_ram:
703         /*
704          * Relocation Function, r14 point to got2+0x8000
705          *
706          * Adjust got2 pointers, no need to check for 0, this code
707          * already puts a few entries in the table.
708          */
709         li      r0,__got2_entries@sectoff@l
710         la      r3,GOT(_GOT2_TABLE_)
711         lwz     r11,GOT(_GOT2_TABLE_)
712         mtctr   r0
713         sub     r11,r3,r11
714         addi    r3,r3,-4
715 1:      lwzu    r0,4(r3)
716         add     r0,r0,r11
717         stw     r0,0(r3)
718         bdnz    1b
719
720         /*
721          * Now adjust the fixups and the pointers to the fixups
722          * in case we need to move ourselves again.
723          */
724 2:      li      r0,__fixup_entries@sectoff@l
725         lwz     r3,GOT(_FIXUP_TABLE_)
726         cmpwi   r0,0
727         mtctr   r0
728         addi    r3,r3,-4
729         beq     4f
730 3:      lwzu    r4,4(r3)
731         lwzux   r0,r4,r11
732         add     r0,r0,r11
733         stw     r10,0(r3)
734         stw     r0,0(r4)
735         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         lwz     r7, GOT(_start)
770         lwz     r8, GOT(_end_of_vectors)
771
772         li      r9, 0x100               /* reset vector always at 0x100 */
773
774         cmplw   0, r7, r8
775         bgelr                           /* return if r7>=r8 - just in case */
776
777         mflr    r4                      /* save link register           */
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         /*
830          * Function: relocate entries for one exception vector
831          */
832 trap_reloc:
833         lwz     r0, 0(r7)               /* hdlr ...                     */
834         add     r0, r0, r3              /*  ... += dest_addr            */
835         stw     r0, 0(r7)
836
837         lwz     r0, 4(r7)               /* int_return ...               */
838         add     r0, r0, r3              /*  ... += dest_addr            */
839         stw     r0, 4(r7)
840
841         sync
842         isync
843
844         blr
845
846 .globl enable_ext_addr
847 enable_ext_addr:
848         mfspr   r0, HID0
849         lis     r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
850         ori     r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
851         mtspr   HID0, r0
852         sync
853         isync
854         blr
855
856 #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
857 .globl setup_ccsrbar
858 setup_ccsrbar:
859         /* Special sequence needed to update CCSRBAR itself */
860         lis     r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
861         ori     r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
862
863         lis     r5, CONFIG_SYS_CCSRBAR@h
864         ori     r5, r5, CONFIG_SYS_CCSRBAR@l
865         srwi    r6,r5,12
866         stw     r6, 0(r4)
867         isync
868
869         lis     r5, 0xffff
870         ori     r5,r5,0xf000
871         lwz     r5, 0(r5)
872         isync
873
874         lis     r3, CONFIG_SYS_CCSRBAR@h
875         lwz     r5, CONFIG_SYS_CCSRBAR@l(r3)
876         isync
877
878         blr
879 #endif
880
881 #ifdef CONFIG_SYS_INIT_RAM_LOCK
882 lock_ram_in_cache:
883         /* Allocate Initial RAM in data cache.
884          */
885         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
886         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
887         li      r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
888                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
889         mtctr   r4
890 1:
891         dcbz    r0, r3
892         addi    r3, r3, 32
893         bdnz    1b
894 #if 1
895 /* Lock the data cache */
896         mfspr   r0, HID0
897         ori     r0, r0, 0x1000
898         sync
899         mtspr   HID0, r0
900         sync
901         blr
902 #endif
903 #if 0
904         /* Lock the first way of the data cache */
905         mfspr   r0, LDSTCR
906         ori     r0, r0, 0x0080
907 #if defined(CONFIG_ALTIVEC)
908         dssall
909 #endif
910         sync
911         mtspr   LDSTCR, r0
912         sync
913         isync
914         blr
915 #endif
916
917 .globl unlock_ram_in_cache
918 unlock_ram_in_cache:
919         /* invalidate the INIT_RAM section */
920         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
921         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
922         li      r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
923                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
924         mtctr   r4
925 1:      icbi    r0, r3
926         addi    r3, r3, 32
927         bdnz    1b
928         sync                    /* Wait for all icbi to complete on bus */
929         isync
930 #if 1
931 /* Unlock the data cache and invalidate it */
932         mfspr   r0, HID0
933         li      r3,0x1000
934         andc    r0,r0,r3
935         li      r3,0x0400
936         or      r0,r0,r3
937         sync
938         mtspr   HID0, r0
939         sync
940         blr
941 #endif
942 #if 0
943         /* Unlock the first way of the data cache */
944         mfspr   r0, LDSTCR
945         li      r3,0x0080
946         andc    r0,r0,r3
947 #ifdef CONFIG_ALTIVEC
948         dssall
949 #endif
950         sync
951         mtspr   LDSTCR, r0
952         sync
953         isync
954         li      r3,0x0400
955         or      r0,r0,r3
956         sync
957         mtspr   HID0, r0
958         sync
959         blr
960 #endif
961 #endif
962
963