SPDX: Convert all of our single license tags to Linux Kernel style
[oweals/u-boot.git] / arch / powerpc / cpu / mpc86xx / start.S
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Copyright 2004, 2007, 2011 Freescale Semiconductor.
4  * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
5  */
6
7 /*  U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
8  *
9  *
10  *  The processor starts at 0xfff00100 and the code is executed
11  *  from flash. The code is organized to be at an other address
12  *  in memory, but as long we don't jump around before relocating.
13  *  board_init lies at a quite high address and when the cpu has
14  *  jumped there, everything is ok.
15  */
16 #include <asm-offsets.h>
17 #include <config.h>
18 #include <mpc86xx.h>
19 #include <version.h>
20
21 #include <ppc_asm.tmpl>
22 #include <ppc_defs.h>
23
24 #include <asm/cache.h>
25 #include <asm/mmu.h>
26 #include <asm/u-boot.h>
27
28 /*
29  * Need MSR_DR | MSR_IR enabled to access I/O (printf) in exceptions
30  */
31
32 /*
33  * Set up GOT: Global Offset Table
34  *
35  * Use r12 to access the GOT
36  */
37         START_GOT
38         GOT_ENTRY(_GOT2_TABLE_)
39         GOT_ENTRY(_FIXUP_TABLE_)
40
41         GOT_ENTRY(_start)
42         GOT_ENTRY(_start_of_vectors)
43         GOT_ENTRY(_end_of_vectors)
44         GOT_ENTRY(transfer_to_handler)
45
46         GOT_ENTRY(__init_end)
47         GOT_ENTRY(__bss_end)
48         GOT_ENTRY(__bss_start)
49         END_GOT
50
51 /*
52  * r3 - 1st arg to board_init(): IMMP pointer
53  * r4 - 2nd arg to board_init(): boot flag
54  */
55         .text
56         .long   0x27051956              /* U-Boot Magic Number */
57         .globl  version_string
58 version_string:
59         .ascii U_BOOT_VERSION_STRING, "\0"
60
61         . = EXC_OFF_SYS_RESET
62         .globl  _start
63 _start:
64         b       boot_cold
65
66         /* the boot code is located below the exception table */
67
68         .globl  _start_of_vectors
69 _start_of_vectors:
70
71 /* Machine check */
72         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
73
74 /* Data Storage exception. */
75         STD_EXCEPTION(0x300, DataStorage, UnknownException)
76
77 /* Instruction Storage exception. */
78         STD_EXCEPTION(0x400, InstStorage, UnknownException)
79
80 /* External Interrupt exception. */
81         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
82
83 /* Alignment exception. */
84         . = 0x600
85 Alignment:
86         EXCEPTION_PROLOG(SRR0, SRR1)
87         mfspr   r4,DAR
88         stw     r4,_DAR(r21)
89         mfspr   r5,DSISR
90         stw     r5,_DSISR(r21)
91         addi    r3,r1,STACK_FRAME_OVERHEAD
92         EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
93
94 /* Program check exception */
95         . = 0x700
96 ProgramCheck:
97         EXCEPTION_PROLOG(SRR0, SRR1)
98         addi    r3,r1,STACK_FRAME_OVERHEAD
99         EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
100                 MSR_KERNEL, COPY_EE)
101
102         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
103
104         /* I guess we could implement decrementer, and may have
105          * to someday for timekeeping.
106          */
107         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
108         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
109         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
110         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
111         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
112         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
113         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
114         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
115         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
116         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
117         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
118         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
119         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
120         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
121         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
122         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
123         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
124         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
125         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
126         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
127         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
128         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
129         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
130
131         .globl  _end_of_vectors
132 _end_of_vectors:
133
134         . = 0x2000
135
136 boot_cold:
137         /*
138          * NOTE: Only Cpu 0 will ever come here.  Other cores go to an
139          * address specified by the BPTR
140          */
141 1:
142 #ifdef CONFIG_SYS_RAMBOOT
143         /* disable everything */
144         li      r0, 0
145         mtspr   HID0, r0
146         sync
147         mtmsr   0
148 #endif
149
150         /* Invalidate BATs */
151         bl      invalidate_bats
152         sync
153         /* Invalidate all of TLB before MMU turn on */
154         bl      clear_tlbs
155         sync
156
157 #ifdef CONFIG_SYS_L2
158         /* init the L2 cache */
159         lis     r3, L2_INIT@h
160         ori     r3, r3, L2_INIT@l
161         mtspr   l2cr, r3
162         /* invalidate the L2 cache */
163         bl      l2cache_invalidate
164         sync
165 #endif
166
167         /*
168          * Calculate absolute address in FLASH and jump there
169          *------------------------------------------------------*/
170         lis     r3, CONFIG_SYS_MONITOR_BASE_EARLY@h
171         ori     r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l
172         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
173         mtlr    r3
174         blr
175
176 in_flash:
177         /* let the C-code set up the rest                       */
178         /*                                                      */
179         /* Be careful to keep code relocatable !                */
180         /*------------------------------------------------------*/
181         /* perform low-level init */
182
183         /* enable extended addressing */
184         bl      enable_ext_addr
185
186         /* setup the bats */
187         bl      early_bats
188
189         /*
190          * Cache must be enabled here for stack-in-cache trick.
191          * This means we need to enable the BATS.
192          * Cache should be turned on after BATs, since by default
193          * everything is write-through.
194          */
195
196         /* enable address translation */
197         mfmsr   r5
198         ori     r5, r5, (MSR_IR | MSR_DR)
199         lis     r3,addr_trans_enabled@h
200         ori     r3, r3, addr_trans_enabled@l
201         mtspr   SPRN_SRR0,r3
202         mtspr   SPRN_SRR1,r5
203         rfi
204
205 addr_trans_enabled:
206         /* enable and invalidate the data cache */
207 /*      bl      l1dcache_enable */
208         bl      dcache_enable
209         sync
210
211 #if 1
212         bl      icache_enable
213 #endif
214
215 #ifdef CONFIG_SYS_INIT_RAM_LOCK
216         bl      lock_ram_in_cache
217         sync
218 #endif
219
220 #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
221         bl      setup_ccsrbar
222 #endif
223
224         /* set up the stack pointer in our newly created
225          * cache-ram (r1) */
226         lis     r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
227         ori     r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
228
229         li      r0, 0           /* Make room for stack frame header and */
230         stwu    r0, -4(r1)      /* clear final stack frame so that      */
231         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
232
233         GET_GOT                 /* initialize GOT access        */
234
235         /* run low-level CPU init code     (from Flash) */
236         bl      cpu_init_f
237         sync
238
239 #ifdef  RUN_DIAG
240
241         /* Load PX_AUX register address in r4 */
242         lis     r4, PIXIS_BASE@h
243         ori     r4, r4, 0x6
244         /* Load contents of PX_AUX in r3 bits 24 to 31*/
245         lbz     r3, 0(r4)
246
247         /* Mask and obtain the bit in r3 */
248         rlwinm. r3, r3, 0, 24, 24
249         /* If not zero, jump and continue with u-boot */
250         bne     diag_done
251
252         /* Load back contents of PX_AUX in r3 bits 24 to 31 */
253         lbz     r3, 0(r4)
254         /* Set the MSB of the register value */
255         ori     r3, r3, 0x80
256         /* Write value in r3 back to PX_AUX */
257         stb     r3, 0(r4)
258
259         /* Get the address to jump to in r3*/
260         lis     r3, CONFIG_SYS_DIAG_ADDR@h
261         ori     r3, r3, CONFIG_SYS_DIAG_ADDR@l
262
263         /* Load the LR with the branch address */
264         mtlr    r3
265
266         /* Branch to diagnostic */
267         blr
268
269 diag_done:
270 #endif
271
272 /*      bl      l2cache_enable */
273
274         /* run 1st part of board init code (from Flash)   */
275         li      r3, 0           /* clear boot_flag for calling board_init_f */
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
548 /*
549  * Function:    in8
550  * Description: Input 8 bits
551  */
552         .globl  in8
553 in8:
554         lbz     r3,0x0000(r3)
555         blr
556
557 /*
558  * Function:    out8
559  * Description: Output 8 bits
560  */
561         .globl  out8
562 out8:
563         stb     r4,0x0000(r3)
564         blr
565
566 /*
567  * Function:    out16
568  * Description: Output 16 bits
569  */
570         .globl  out16
571 out16:
572         sth     r4,0x0000(r3)
573         blr
574
575 /*
576  * Function:    out16r
577  * Description: Byte reverse and output 16 bits
578  */
579         .globl  out16r
580 out16r:
581         sthbrx  r4,r0,r3
582         blr
583
584 /*
585  * Function:    out32
586  * Description: Output 32 bits
587  */
588         .globl  out32
589 out32:
590         stw     r4,0x0000(r3)
591         blr
592
593 /*
594  * Function:    out32r
595  * Description: Byte reverse and output 32 bits
596  */
597         .globl  out32r
598 out32r:
599         stwbrx  r4,r0,r3
600         blr
601
602 /*
603  * Function:    in16
604  * Description: Input 16 bits
605  */
606         .globl  in16
607 in16:
608         lhz     r3,0x0000(r3)
609         blr
610
611 /*
612  * Function:    in16r
613  * Description: Input 16 bits and byte reverse
614  */
615         .globl  in16r
616 in16r:
617         lhbrx   r3,r0,r3
618         blr
619
620 /*
621  * Function:    in32
622  * Description: Input 32 bits
623  */
624         .globl  in32
625 in32:
626         lwz     3,0x0000(3)
627         blr
628
629 /*
630  * Function:    in32r
631  * Description: Input 32 bits and byte reverse
632  */
633         .globl  in32r
634 in32r:
635         lwbrx   r3,r0,r3
636         blr
637
638 /*
639  * void relocate_code (addr_sp, gd, addr_moni)
640  *
641  * This "function" does not return, instead it continues in RAM
642  * after relocating the monitor code.
643  *
644  * r3 = dest
645  * r4 = src
646  * r5 = length in bytes
647  * r6 = cachelinesize
648  */
649         .globl  relocate_code
650 relocate_code:
651
652         mr      r1,  r3         /* Set new stack pointer                */
653         mr      r9,  r4         /* Save copy of Global Data pointer     */
654         mr      r10, r5         /* Save copy of Destination Address     */
655
656         GET_GOT
657         mr      r3,  r5                         /* Destination Address  */
658         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
659         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
660         lwz     r5, GOT(__init_end)
661         sub     r5, r5, r4
662         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
663
664         /*
665          * Fix GOT pointer:
666          *
667          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
668          *
669          * Offset:
670          */
671         sub     r15, r10, r4
672
673         /* First our own GOT */
674         add     r12, r12, r15
675         /* then the one used by the C code */
676         add     r30, r30, r15
677
678         /*
679          * Now relocate code
680          */
681         cmplw   cr1,r3,r4
682         addi    r0,r5,3
683         srwi.   r0,r0,2
684         beq     cr1,4f          /* In place copy is not necessary       */
685         beq     7f              /* Protect against 0 count              */
686         mtctr   r0
687         bge     cr1,2f
688
689         la      r8,-4(r4)
690         la      r7,-4(r3)
691 1:      lwzu    r0,4(r8)
692         stwu    r0,4(r7)
693         bdnz    1b
694         b       4f
695
696 2:      slwi    r0,r0,2
697         add     r8,r4,r0
698         add     r7,r3,r0
699 3:      lwzu    r0,-4(r8)
700         stwu    r0,-4(r7)
701         bdnz    3b
702 /*
703  * Now flush the cache: note that we must start from a cache aligned
704  * address. Otherwise we might miss one cache line.
705  */
706 4:      cmpwi   r6,0
707         add     r5,r3,r5
708         beq     7f              /* Always flush prefetch queue in any case */
709         subi    r0,r6,1
710         andc    r3,r3,r0
711         mr      r4,r3
712 5:      dcbst   0,r4
713         add     r4,r4,r6
714         cmplw   r4,r5
715         blt     5b
716         sync                    /* Wait for all dcbst to complete on bus */
717         mr      r4,r3
718 6:      icbi    0,r4
719         add     r4,r4,r6
720         cmplw   r4,r5
721         blt     6b
722 7:      sync                    /* Wait for all icbi to complete on bus */
723         isync
724
725 /*
726  * We are done. Do not return, instead branch to second part of board
727  * initialization, now running from RAM.
728  */
729         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
730         mtlr    r0
731         blr
732
733 in_ram:
734         /*
735          * Relocation Function, r12 point to got2+0x8000
736          *
737          * Adjust got2 pointers, no need to check for 0, this code
738          * already puts a few entries in the table.
739          */
740         li      r0,__got2_entries@sectoff@l
741         la      r3,GOT(_GOT2_TABLE_)
742         lwz     r11,GOT(_GOT2_TABLE_)
743         mtctr   r0
744         sub     r11,r3,r11
745         addi    r3,r3,-4
746 1:      lwzu    r0,4(r3)
747         cmpwi   r0,0
748         beq-    2f
749         add     r0,r0,r11
750         stw     r0,0(r3)
751 2:      bdnz    1b
752
753         /*
754          * Now adjust the fixups and the pointers to the fixups
755          * in case we need to move ourselves again.
756          */
757         li      r0,__fixup_entries@sectoff@l
758         lwz     r3,GOT(_FIXUP_TABLE_)
759         cmpwi   r0,0
760         mtctr   r0
761         addi    r3,r3,-4
762         beq     4f
763 3:      lwzu    r4,4(r3)
764         lwzux   r0,r4,r11
765         cmpwi   r0,0
766         add     r0,r0,r11
767         stw     r4,0(r3)
768         beq-    5f
769         stw     r0,0(r4)
770 5:      bdnz    3b
771 4:
772 /* clear_bss: */
773         /*
774          * Now clear BSS segment
775          */
776         lwz     r3,GOT(__bss_start)
777         lwz     r4,GOT(__bss_end)
778
779         cmplw   0, r3, r4
780         beq     6f
781
782         li      r0, 0
783 5:
784         stw     r0, 0(r3)
785         addi    r3, r3, 4
786         cmplw   0, r3, r4
787         bne     5b
788 6:
789         mr      r3, r9          /* Init Date pointer            */
790         mr      r4, r10         /* Destination Address          */
791         bl      board_init_r
792
793         /* not reached - end relocate_code */
794 /*-----------------------------------------------------------------------*/
795
796         /*
797          * Copy exception vector code to low memory
798          *
799          * r3: dest_addr
800          * r7: source address, r8: end address, r9: target address
801          */
802         .globl  trap_init
803 trap_init:
804         mflr    r4                      /* save link register           */
805         GET_GOT
806         lwz     r7, GOT(_start)
807         lwz     r8, GOT(_end_of_vectors)
808
809         li      r9, 0x100               /* reset vector always at 0x100 */
810
811         cmplw   0, r7, r8
812         bgelr                           /* return if r7>=r8 - just in case */
813 1:
814         lwz     r0, 0(r7)
815         stw     r0, 0(r9)
816         addi    r7, r7, 4
817         addi    r9, r9, 4
818         cmplw   0, r7, r8
819         bne     1b
820
821         /*
822          * relocate `hdlr' and `int_return' entries
823          */
824         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
825         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
826 2:
827         bl      trap_reloc
828         addi    r7, r7, 0x100           /* next exception vector        */
829         cmplw   0, r7, r8
830         blt     2b
831
832         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
833         bl      trap_reloc
834
835         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
836         bl      trap_reloc
837
838         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
839         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
840 3:
841         bl      trap_reloc
842         addi    r7, r7, 0x100           /* next exception vector        */
843         cmplw   0, r7, r8
844         blt     3b
845
846         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
847         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
848 4:
849         bl      trap_reloc
850         addi    r7, r7, 0x100           /* next exception vector        */
851         cmplw   0, r7, r8
852         blt     4b
853
854         /* enable execptions from RAM vectors */
855         mfmsr   r7
856         li      r8,MSR_IP
857         andc    r7,r7,r8
858         ori     r7,r7,MSR_ME            /* Enable Machine Check */
859         mtmsr   r7
860
861         mtlr    r4                      /* restore link register        */
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_PHYS_LOW@h
882         ori     r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
883         srwi    r5,r5,12
884         li      r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
885         rlwimi  r5,r6,20,8,11
886         stw     r5, 0(r4) /* Store physical value of CCSR */
887         isync
888
889         lis     r5, CONFIG_SYS_TEXT_BASE@h
890         ori     r5,r5,CONFIG_SYS_TEXT_BASE@l
891         lwz     r5, 0(r5)
892         isync
893
894         /* Use VA of CCSR to do read */
895         lis     r3, CONFIG_SYS_CCSRBAR@h
896         lwz     r5, CONFIG_SYS_CCSRBAR@l(r3)
897         isync
898
899         blr
900 #endif
901
902 #ifdef CONFIG_SYS_INIT_RAM_LOCK
903 lock_ram_in_cache:
904         /* Allocate Initial RAM in data cache.
905          */
906         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
907         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
908         li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
909                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
910         mtctr   r4
911 1:
912         dcbz    r0, r3
913         addi    r3, r3, 32
914         bdnz    1b
915 #if 1
916 /* Lock the data cache */
917         mfspr   r0, HID0
918         ori     r0, r0, 0x1000
919         sync
920         mtspr   HID0, r0
921         sync
922         blr
923 #endif
924 #if 0
925         /* Lock the first way of the data cache */
926         mfspr   r0, LDSTCR
927         ori     r0, r0, 0x0080
928 #if defined(CONFIG_ALTIVEC)
929         dssall
930 #endif
931         sync
932         mtspr   LDSTCR, r0
933         sync
934         isync
935         blr
936 #endif
937
938 .globl unlock_ram_in_cache
939 unlock_ram_in_cache:
940         /* invalidate the INIT_RAM section */
941         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
942         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
943         li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
944                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
945         mtctr   r4
946 1:      icbi    r0, r3
947         addi    r3, r3, 32
948         bdnz    1b
949         sync                    /* Wait for all icbi to complete on bus */
950         isync
951 #if 1
952 /* Unlock the data cache and invalidate it */
953         mfspr   r0, HID0
954         li      r3,0x1000
955         andc    r0,r0,r3
956         li      r3,0x0400
957         or      r0,r0,r3
958         sync
959         mtspr   HID0, r0
960         sync
961         blr
962 #endif
963 #if 0
964         /* Unlock the first way of the data cache */
965         mfspr   r0, LDSTCR
966         li      r3,0x0080
967         andc    r0,r0,r3
968 #ifdef CONFIG_ALTIVEC
969         dssall
970 #endif
971         sync
972         mtspr   LDSTCR, r0
973         sync
974         isync
975         li      r3,0x0400
976         or      r0,r0,r3
977         sync
978         mtspr   HID0, r0
979         sync
980         blr
981 #endif
982 #endif