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