]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/74xx_7xx/start.S
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / powerpc / cpu / 74xx_7xx / start.S
1 /*
2  *  Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
3  *  Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
4  *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
5  *  Copyright (C) 2001  Josh Huber <huber@mclx.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 /*  U-Boot - Startup Code for PowerPC based Embedded Boards
11  *
12  *
13  *  The processor starts at 0xfff00100 and the code is executed
14  *  from flash. The code is organized to be at an other address
15  *  in memory, but as long we don't jump around before relocating.
16  *  board_init lies at a quite high address and when the cpu has
17  *  jumped there, everything is ok.
18  */
19 #include <asm-offsets.h>
20 #include <config.h>
21 #include <74xx_7xx.h>
22 #include <version.h>
23
24 #include <ppc_asm.tmpl>
25 #include <ppc_defs.h>
26
27 #include <asm/cache.h>
28 #include <asm/mmu.h>
29 #include <asm/u-boot.h>
30
31 #if !defined(CONFIG_DB64360) && \
32     !defined(CONFIG_DB64460) && \
33     !defined(CONFIG_CPCI750) && \
34     !defined(CONFIG_P3Mx)
35 #include <galileo/gt64260R.h>
36 #endif
37
38 /* We don't want the  MMU yet.
39 */
40 #undef  MSR_KERNEL
41 /* Machine Check and Recoverable Interr. */
42 #define MSR_KERNEL ( MSR_ME | MSR_RI )
43
44 /*
45  * Set up GOT: Global Offset Table
46  *
47  * Use r12 to access the GOT
48  */
49         START_GOT
50         GOT_ENTRY(_GOT2_TABLE_)
51         GOT_ENTRY(_FIXUP_TABLE_)
52
53         GOT_ENTRY(_start)
54         GOT_ENTRY(_start_of_vectors)
55         GOT_ENTRY(_end_of_vectors)
56         GOT_ENTRY(transfer_to_handler)
57
58         GOT_ENTRY(__init_end)
59         GOT_ENTRY(__bss_end)
60         GOT_ENTRY(__bss_start)
61         END_GOT
62
63 /*
64  * r3 - 1st arg to board_init(): IMMP pointer
65  * r4 - 2nd arg to board_init(): boot flag
66  */
67         .text
68         .long   0x27051956              /* U-Boot Magic Number          */
69         .globl  version_string
70 version_string:
71         .ascii U_BOOT_VERSION_STRING, "\0"
72
73         . = EXC_OFF_SYS_RESET
74         .globl  _start
75 _start:
76         b       boot_cold
77
78         /* the boot code is located below the exception table */
79
80         .globl  _start_of_vectors
81 _start_of_vectors:
82
83 /* Machine check */
84         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
85
86 /* Data Storage exception.  "Never" generated on the 860. */
87         STD_EXCEPTION(0x300, DataStorage, UnknownException)
88
89 /* Instruction Storage exception.  "Never" generated on the 860. */
90         STD_EXCEPTION(0x400, InstStorage, UnknownException)
91
92 /* External Interrupt exception. */
93         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
94
95 /* Alignment exception. */
96         . = 0x600
97 Alignment:
98         EXCEPTION_PROLOG(SRR0, SRR1)
99         mfspr   r4,DAR
100         stw     r4,_DAR(r21)
101         mfspr   r5,DSISR
102         stw     r5,_DSISR(r21)
103         addi    r3,r1,STACK_FRAME_OVERHEAD
104         EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
105
106 /* Program check exception */
107         . = 0x700
108 ProgramCheck:
109         EXCEPTION_PROLOG(SRR0, SRR1)
110         addi    r3,r1,STACK_FRAME_OVERHEAD
111         EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
112                 MSR_KERNEL, COPY_EE)
113
114         /* No FPU on MPC8xx.  This exception is not supposed to happen.
115         */
116         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
117
118         /* I guess we could implement decrementer, and may have
119          * to someday for timekeeping.
120          */
121         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
122         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
123         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
124         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
125         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
126
127         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
128         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
129
130         /*
131          * On the MPC8xx, this is a software emulation interrupt. It
132          * occurs for all unimplemented and illegal instructions.
133          */
134         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
135
136         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
137         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
138         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
139         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
140
141         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
142         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
143         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
144         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
145         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
146         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
147         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
148
149         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
150         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
151         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
152         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
153
154         .globl  _end_of_vectors
155 _end_of_vectors:
156
157         . = 0x2000
158
159 boot_cold:
160         /* disable everything */
161         li      r0, 0
162         mtspr   HID0, r0
163         sync
164         mtmsr   0
165         bl      invalidate_bats
166         sync
167
168 #ifdef CONFIG_SYS_L2
169         /* init the L2 cache */
170         addis   r3, r0, L2_INIT@h
171         ori     r3, r3, L2_INIT@l
172         sync
173         mtspr   l2cr, r3
174 #endif
175 #if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
176         .long   0x7e00066c
177                 /*
178                  * dssall instruction, gas doesn't have it yet
179                  * ...for altivec, data stream stop all this probably
180                  * isn't needed unless we warm (software) reboot U-Boot
181                  */
182 #endif
183
184 #ifdef CONFIG_SYS_L2
185         /* invalidate the L2 cache */
186         bl      l2cache_invalidate
187         sync
188 #endif
189 #ifdef CONFIG_SYS_BOARD_ASM_INIT
190         /* do early init */
191         bl      board_asm_init
192 #endif
193
194         /*
195          * Calculate absolute address in FLASH and jump there
196          *------------------------------------------------------*/
197         lis     r3, CONFIG_SYS_MONITOR_BASE@h
198         ori     r3, r3, CONFIG_SYS_MONITOR_BASE@l
199         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
200         mtlr    r3
201         blr
202
203 in_flash:
204         /* let the C-code set up the rest                       */
205         /*                                                      */
206         /* Be careful to keep code relocatable !                */
207         /*------------------------------------------------------*/
208
209         /* perform low-level init */
210         /* sdram init, galileo init, etc */
211         /* r3:  NHR bit from HID0 */
212
213         /* setup the bats */
214         bl      setup_bats
215         sync
216
217         /*
218          * Cache must be enabled here for stack-in-cache trick.
219          * This means we need to enable the BATS.
220          * This means:
221          *   1) for the EVB, original gt regs need to be mapped
222          *   2) need to have an IBAT for the 0xf region,
223          *      we are running there!
224          * Cache should be turned on after BATs, since by default
225          * everything is write-through.
226          * The init-mem BAT can be reused after reloc. The old
227          * gt-regs BAT can be reused after board_init_f calls
228          * board_early_init_f (EVB only).
229          */
230 #if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC) && !defined(CONFIG_P3Mx)
231         /* enable address translation */
232         bl      enable_addr_trans
233         sync
234
235         /* enable and invalidate the data cache */
236         bl      l1dcache_enable
237         sync
238 #endif
239 #ifdef CONFIG_SYS_INIT_RAM_LOCK
240         bl      lock_ram_in_cache
241         sync
242 #endif
243
244         /* set up the stack pointer in our newly created
245          * cache-ram (r1) */
246         lis     r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
247         ori     r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
248
249         li      r0, 0           /* Make room for stack frame header and */
250         stwu    r0, -4(r1)      /* clear final stack frame so that      */
251         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
252
253         GET_GOT                 /* initialize GOT access        */
254
255         /* run low-level CPU init code     (from Flash) */
256         bl      cpu_init_f
257         sync
258
259         /* run 1st part of board init code (from Flash)   */
260         bl      board_init_f
261         sync
262
263         /* NOTREACHED - board_init_f() does not return */
264
265         .globl  invalidate_bats
266 invalidate_bats:
267         /* invalidate BATs */
268         mtspr   IBAT0U, r0
269         mtspr   IBAT1U, r0
270         mtspr   IBAT2U, r0
271         mtspr   IBAT3U, r0
272 #ifdef CONFIG_HIGH_BATS
273         mtspr   IBAT4U, r0
274         mtspr   IBAT5U, r0
275         mtspr   IBAT6U, r0
276         mtspr   IBAT7U, r0
277 #endif
278         isync
279         mtspr   DBAT0U, r0
280         mtspr   DBAT1U, r0
281         mtspr   DBAT2U, r0
282         mtspr   DBAT3U, r0
283 #ifdef CONFIG_HIGH_BATS
284         mtspr   DBAT4U, r0
285         mtspr   DBAT5U, r0
286         mtspr   DBAT6U, r0
287         mtspr   DBAT7U, r0
288 #endif
289         isync
290         sync
291         blr
292
293         /* setup_bats - set them up to some initial state */
294         .globl  setup_bats
295 setup_bats:
296         addis   r0, r0, 0x0000
297
298         /* IBAT 0 */
299         addis   r4, r0, CONFIG_SYS_IBAT0L@h
300         ori     r4, r4, CONFIG_SYS_IBAT0L@l
301         addis   r3, r0, CONFIG_SYS_IBAT0U@h
302         ori     r3, r3, CONFIG_SYS_IBAT0U@l
303         mtspr   IBAT0L, r4
304         mtspr   IBAT0U, r3
305         isync
306
307         /* DBAT 0 */
308         addis   r4, r0, CONFIG_SYS_DBAT0L@h
309         ori     r4, r4, CONFIG_SYS_DBAT0L@l
310         addis   r3, r0, CONFIG_SYS_DBAT0U@h
311         ori     r3, r3, CONFIG_SYS_DBAT0U@l
312         mtspr   DBAT0L, r4
313         mtspr   DBAT0U, r3
314         isync
315
316         /* IBAT 1 */
317         addis   r4, r0, CONFIG_SYS_IBAT1L@h
318         ori     r4, r4, CONFIG_SYS_IBAT1L@l
319         addis   r3, r0, CONFIG_SYS_IBAT1U@h
320         ori     r3, r3, CONFIG_SYS_IBAT1U@l
321         mtspr   IBAT1L, r4
322         mtspr   IBAT1U, r3
323         isync
324
325         /* DBAT 1 */
326         addis   r4, r0, CONFIG_SYS_DBAT1L@h
327         ori     r4, r4, CONFIG_SYS_DBAT1L@l
328         addis   r3, r0, CONFIG_SYS_DBAT1U@h
329         ori     r3, r3, CONFIG_SYS_DBAT1U@l
330         mtspr   DBAT1L, r4
331         mtspr   DBAT1U, r3
332         isync
333
334         /* IBAT 2 */
335         addis   r4, r0, CONFIG_SYS_IBAT2L@h
336         ori     r4, r4, CONFIG_SYS_IBAT2L@l
337         addis   r3, r0, CONFIG_SYS_IBAT2U@h
338         ori     r3, r3, CONFIG_SYS_IBAT2U@l
339         mtspr   IBAT2L, r4
340         mtspr   IBAT2U, r3
341         isync
342
343         /* DBAT 2 */
344         addis   r4, r0, CONFIG_SYS_DBAT2L@h
345         ori     r4, r4, CONFIG_SYS_DBAT2L@l
346         addis   r3, r0, CONFIG_SYS_DBAT2U@h
347         ori     r3, r3, CONFIG_SYS_DBAT2U@l
348         mtspr   DBAT2L, r4
349         mtspr   DBAT2U, r3
350         isync
351
352         /* IBAT 3 */
353         addis   r4, r0, CONFIG_SYS_IBAT3L@h
354         ori     r4, r4, CONFIG_SYS_IBAT3L@l
355         addis   r3, r0, CONFIG_SYS_IBAT3U@h
356         ori     r3, r3, CONFIG_SYS_IBAT3U@l
357         mtspr   IBAT3L, r4
358         mtspr   IBAT3U, r3
359         isync
360
361         /* DBAT 3 */
362         addis   r4, r0, CONFIG_SYS_DBAT3L@h
363         ori     r4, r4, CONFIG_SYS_DBAT3L@l
364         addis   r3, r0, CONFIG_SYS_DBAT3U@h
365         ori     r3, r3, CONFIG_SYS_DBAT3U@l
366         mtspr   DBAT3L, r4
367         mtspr   DBAT3U, r3
368         isync
369
370 #ifdef CONFIG_HIGH_BATS
371         /* IBAT 4 */
372         addis   r4, r0, CONFIG_SYS_IBAT4L@h
373         ori     r4, r4, CONFIG_SYS_IBAT4L@l
374         addis   r3, r0, CONFIG_SYS_IBAT4U@h
375         ori     r3, r3, CONFIG_SYS_IBAT4U@l
376         mtspr   IBAT4L, r4
377         mtspr   IBAT4U, r3
378         isync
379
380         /* DBAT 4 */
381         addis   r4, r0, CONFIG_SYS_DBAT4L@h
382         ori     r4, r4, CONFIG_SYS_DBAT4L@l
383         addis   r3, r0, CONFIG_SYS_DBAT4U@h
384         ori     r3, r3, CONFIG_SYS_DBAT4U@l
385         mtspr   DBAT4L, r4
386         mtspr   DBAT4U, r3
387         isync
388
389         /* IBAT 5 */
390         addis   r4, r0, CONFIG_SYS_IBAT5L@h
391         ori     r4, r4, CONFIG_SYS_IBAT5L@l
392         addis   r3, r0, CONFIG_SYS_IBAT5U@h
393         ori     r3, r3, CONFIG_SYS_IBAT5U@l
394         mtspr   IBAT5L, r4
395         mtspr   IBAT5U, r3
396         isync
397
398         /* DBAT 5 */
399         addis   r4, r0, CONFIG_SYS_DBAT5L@h
400         ori     r4, r4, CONFIG_SYS_DBAT5L@l
401         addis   r3, r0, CONFIG_SYS_DBAT5U@h
402         ori     r3, r3, CONFIG_SYS_DBAT5U@l
403         mtspr   DBAT5L, r4
404         mtspr   DBAT5U, r3
405         isync
406
407         /* IBAT 6 */
408         addis   r4, r0, CONFIG_SYS_IBAT6L@h
409         ori     r4, r4, CONFIG_SYS_IBAT6L@l
410         addis   r3, r0, CONFIG_SYS_IBAT6U@h
411         ori     r3, r3, CONFIG_SYS_IBAT6U@l
412         mtspr   IBAT6L, r4
413         mtspr   IBAT6U, r3
414         isync
415
416         /* DBAT 6 */
417         addis   r4, r0, CONFIG_SYS_DBAT6L@h
418         ori     r4, r4, CONFIG_SYS_DBAT6L@l
419         addis   r3, r0, CONFIG_SYS_DBAT6U@h
420         ori     r3, r3, CONFIG_SYS_DBAT6U@l
421         mtspr   DBAT6L, r4
422         mtspr   DBAT6U, r3
423         isync
424
425         /* IBAT 7 */
426         addis   r4, r0, CONFIG_SYS_IBAT7L@h
427         ori     r4, r4, CONFIG_SYS_IBAT7L@l
428         addis   r3, r0, CONFIG_SYS_IBAT7U@h
429         ori     r3, r3, CONFIG_SYS_IBAT7U@l
430         mtspr   IBAT7L, r4
431         mtspr   IBAT7U, r3
432         isync
433
434         /* DBAT 7 */
435         addis   r4, r0, CONFIG_SYS_DBAT7L@h
436         ori     r4, r4, CONFIG_SYS_DBAT7L@l
437         addis   r3, r0, CONFIG_SYS_DBAT7U@h
438         ori     r3, r3, CONFIG_SYS_DBAT7U@l
439         mtspr   DBAT7L, r4
440         mtspr   DBAT7U, r3
441         isync
442 #endif
443
444         /* bats are done, now invalidate the TLBs */
445
446         addis   r3, 0, 0x0000
447         addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
448
449         isync
450
451 tlblp:
452         tlbie   r3
453         sync
454         addi    r3, r3, 0x1000
455         cmp     0, 0, r3, r5
456         blt tlblp
457
458         blr
459
460         .globl enable_addr_trans
461 enable_addr_trans:
462         /* enable address translation */
463         mfmsr   r5
464         ori     r5, r5, (MSR_IR | MSR_DR)
465         mtmsr   r5
466         isync
467         blr
468
469         .globl disable_addr_trans
470 disable_addr_trans:
471         /* disable address translation */
472         mflr    r4
473         mfmsr   r3
474         andi.   r0, r3, (MSR_IR | MSR_DR)
475         beqlr
476         andc    r3, r3, r0
477         mtspr   SRR0, r4
478         mtspr   SRR1, r3
479         rfi
480
481 /*
482  * This code finishes saving the registers to the exception frame
483  * and jumps to the appropriate handler for the exception.
484  * Register r21 is pointer into trap frame, r1 has new stack pointer.
485  */
486         .globl  transfer_to_handler
487 transfer_to_handler:
488         stw     r22,_NIP(r21)
489         lis     r22,MSR_POW@h
490         andc    r23,r23,r22
491         stw     r23,_MSR(r21)
492         SAVE_GPR(7, r21)
493         SAVE_4GPRS(8, r21)
494         SAVE_8GPRS(12, r21)
495         SAVE_8GPRS(24, r21)
496         mflr    r23
497         andi.   r24,r23,0x3f00          /* get vector offset */
498         stw     r24,TRAP(r21)
499         li      r22,0
500         stw     r22,RESULT(r21)
501         mtspr   SPRG2,r22               /* r1 is now kernel sp */
502         lwz     r24,0(r23)              /* virtual address of handler */
503         lwz     r23,4(r23)              /* where to go when done */
504         mtspr   SRR0,r24
505         mtspr   SRR1,r20
506         mtlr    r23
507         SYNC
508         rfi                             /* jump to handler, enable MMU */
509
510 int_return:
511         mfmsr   r28             /* Disable interrupts */
512         li      r4,0
513         ori     r4,r4,MSR_EE
514         andc    r28,r28,r4
515         SYNC                    /* Some chip revs need this... */
516         mtmsr   r28
517         SYNC
518         lwz     r2,_CTR(r1)
519         lwz     r0,_LINK(r1)
520         mtctr   r2
521         mtlr    r0
522         lwz     r2,_XER(r1)
523         lwz     r0,_CCR(r1)
524         mtspr   XER,r2
525         mtcrf   0xFF,r0
526         REST_10GPRS(3, r1)
527         REST_10GPRS(13, r1)
528         REST_8GPRS(23, r1)
529         REST_GPR(31, r1)
530         lwz     r2,_NIP(r1)     /* Restore environment */
531         lwz     r0,_MSR(r1)
532         mtspr   SRR0,r2
533         mtspr   SRR1,r0
534         lwz     r0,GPR0(r1)
535         lwz     r2,GPR2(r1)
536         lwz     r1,GPR1(r1)
537         SYNC
538         rfi
539
540         .globl  dc_read
541 dc_read:
542         blr
543
544         .globl get_pvr
545 get_pvr:
546         mfspr   r3, PVR
547         blr
548
549 /*-----------------------------------------------------------------------*/
550 /*
551  * void relocate_code (addr_sp, gd, addr_moni)
552  *
553  * This "function" does not return, instead it continues in RAM
554  * after relocating the monitor code.
555  *
556  * r3 = dest
557  * r4 = src
558  * r5 = length in bytes
559  * r6 = cachelinesize
560  */
561         .globl  relocate_code
562 relocate_code:
563         mr      r1,  r3         /* Set new stack pointer                */
564         mr      r9,  r4         /* Save copy of Global Data pointer     */
565         mr      r10, r5         /* Save copy of Destination Address     */
566
567         GET_GOT
568         mr      r3,  r5                         /* Destination Address  */
569         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
570         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
571         lwz     r5, GOT(__init_end)
572         sub     r5, r5, r4
573         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
574
575         /*
576          * Fix GOT pointer:
577          *
578          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
579          *
580          * Offset:
581          */
582         sub     r15, r10, r4
583
584         /* First our own GOT */
585         add     r12, r12, r15
586         /* then the one used by the C code */
587         add     r30, r30, r15
588
589         /*
590          * Now relocate code
591          */
592 #ifdef CONFIG_ECC
593         bl      board_relocate_rom
594         sync
595         mr      r3, r10                         /* Destination Address  */
596         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
597         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
598         lwz     r5, GOT(__init_end)
599         sub     r5, r5, r4
600         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
601 #else
602         cmplw   cr1,r3,r4
603         addi    r0,r5,3
604         srwi.   r0,r0,2
605         beq     cr1,4f          /* In place copy is not necessary       */
606         beq     7f              /* Protect against 0 count              */
607         mtctr   r0
608         bge     cr1,2f
609
610         la      r8,-4(r4)
611         la      r7,-4(r3)
612 1:      lwzu    r0,4(r8)
613         stwu    r0,4(r7)
614         bdnz    1b
615         b       4f
616
617 2:      slwi    r0,r0,2
618         add     r8,r4,r0
619         add     r7,r3,r0
620 3:      lwzu    r0,-4(r8)
621         stwu    r0,-4(r7)
622         bdnz    3b
623 #endif
624 /*
625  * Now flush the cache: note that we must start from a cache aligned
626  * address. Otherwise we might miss one cache line.
627  */
628 4:      cmpwi   r6,0
629         add     r5,r3,r5
630         beq     7f              /* Always flush prefetch queue in any case */
631         subi    r0,r6,1
632         andc    r3,r3,r0
633         mr      r4,r3
634 5:      dcbst   0,r4
635         add     r4,r4,r6
636         cmplw   r4,r5
637         blt     5b
638         sync                    /* Wait for all dcbst to complete on bus */
639         mr      r4,r3
640 6:      icbi    0,r4
641         add     r4,r4,r6
642         cmplw   r4,r5
643         blt     6b
644 7:      sync                    /* Wait for all icbi to complete on bus */
645         isync
646
647 /*
648  * We are done. Do not return, instead branch to second part of board
649  * initialization, now running from RAM.
650  */
651         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
652         mtlr    r0
653         blr
654
655 in_ram:
656 #ifdef CONFIG_ECC
657         bl      board_init_ecc
658 #endif
659         /*
660          * Relocation Function, r12 point to got2+0x8000
661          *
662          * Adjust got2 pointers, no need to check for 0, this code
663          * already puts a few entries in the table.
664          */
665         li      r0,__got2_entries@sectoff@l
666         la      r3,GOT(_GOT2_TABLE_)
667         lwz     r11,GOT(_GOT2_TABLE_)
668         mtctr   r0
669         sub     r11,r3,r11
670         addi    r3,r3,-4
671 1:      lwzu    r0,4(r3)
672         cmpwi   r0,0
673         beq-    2f
674         add     r0,r0,r11
675         stw     r0,0(r3)
676 2:      bdnz    1b
677
678         /*
679          * Now adjust the fixups and the pointers to the fixups
680          * in case we need to move ourselves again.
681          */
682         li      r0,__fixup_entries@sectoff@l
683         lwz     r3,GOT(_FIXUP_TABLE_)
684         cmpwi   r0,0
685         mtctr   r0
686         addi    r3,r3,-4
687         beq     4f
688 3:      lwzu    r4,4(r3)
689         lwzux   r0,r4,r11
690         cmpwi   r0,0
691         add     r0,r0,r11
692         stw     r4,0(r3)
693         beq-    5f
694         stw     r0,0(r4)
695 5:      bdnz    3b
696 4:
697 /* clear_bss: */
698         /*
699          * Now clear BSS segment
700          */
701         lwz     r3,GOT(__bss_start)
702         lwz     r4,GOT(__bss_end)
703
704         cmplw   0, r3, r4
705         beq     6f
706
707         li      r0, 0
708 5:
709         stw     r0, 0(r3)
710         addi    r3, r3, 4
711         cmplw   0, r3, r4
712         bne     5b
713 6:
714         mr      r3, r10         /* Destination Address          */
715 #if defined(CONFIG_DB64360)     || \
716     defined(CONFIG_DB64460)     || \
717     defined(CONFIG_CPCI750)     || \
718     defined(CONFIG_PPMC7XX)     || \
719     defined(CONFIG_P3Mx)
720         mr      r4, r9          /* Use RAM copy of the global data */
721 #endif
722         bl      after_reloc
723
724         /* not reached - end relocate_code */
725 /*-----------------------------------------------------------------------*/
726
727         /*
728          * Copy exception vector code to low memory
729          *
730          * r3: dest_addr
731          * r7: source address, r8: end address, r9: target address
732          */
733         .globl  trap_init
734 trap_init:
735         mflr    r4                      /* save link register           */
736         GET_GOT
737         lwz     r7, GOT(_start)
738         lwz     r8, GOT(_end_of_vectors)
739
740         li      r9, 0x100               /* reset vector always at 0x100 */
741
742         cmplw   0, r7, r8
743         bgelr                           /* return if r7>=r8 - just in case */
744 1:
745         lwz     r0, 0(r7)
746         stw     r0, 0(r9)
747         addi    r7, r7, 4
748         addi    r9, r9, 4
749         cmplw   0, r7, r8
750         bne     1b
751
752         /*
753          * relocate `hdlr' and `int_return' entries
754          */
755         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
756         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
757 2:
758         bl      trap_reloc
759         addi    r7, r7, 0x100           /* next exception vector        */
760         cmplw   0, r7, r8
761         blt     2b
762
763         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
764         bl      trap_reloc
765
766         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
767         bl      trap_reloc
768
769         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
770         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
771 3:
772         bl      trap_reloc
773         addi    r7, r7, 0x100           /* next exception vector        */
774         cmplw   0, r7, r8
775         blt     3b
776
777         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
778         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
779 4:
780         bl      trap_reloc
781         addi    r7, r7, 0x100           /* next exception vector        */
782         cmplw   0, r7, r8
783         blt     4b
784
785         /* enable execptions from RAM vectors */
786         mfmsr   r7
787         li      r8,MSR_IP
788         andc    r7,r7,r8
789         mtmsr   r7
790
791         mtlr    r4                      /* restore link register        */
792         blr
793
794 #ifdef CONFIG_SYS_INIT_RAM_LOCK
795 lock_ram_in_cache:
796         /* Allocate Initial RAM in data cache.
797          */
798         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
799         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
800         li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
801                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
802         mtctr   r4
803 1:
804         dcbz    r0, r3
805         addi    r3, r3, 32
806         bdnz    1b
807
808         /* Lock the data cache */
809         mfspr   r0, HID0
810         ori     r0, r0, 0x1000
811         sync
812         mtspr   HID0, r0
813         sync
814         blr
815
816 .globl unlock_ram_in_cache
817 unlock_ram_in_cache:
818         /* invalidate the INIT_RAM section */
819         lis     r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
820         ori     r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
821         li      r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
822                      (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
823         mtctr   r4
824 1:      icbi    r0, r3
825         addi    r3, r3, 32
826         bdnz    1b
827         sync                    /* Wait for all icbi to complete on bus */
828         isync
829
830         /* Unlock the data cache and invalidate it */
831         mfspr   r0, HID0
832         li      r3,0x1000
833         andc    r0,r0,r3
834         li      r3,0x0400
835         or      r0,r0,r3
836         sync
837         mtspr   HID0, r0
838         sync
839         blr
840 #endif