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