]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/74xx_7xx/start.S
Patch by Tom Guilliams, 20 Jun 2003:
[karo-tx-uboot.git] / 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
163         . = 0xc00
164 /*
165  * r0 - SYSCALL number
166  * r3-... arguments
167  */
168 SystemCall:
169         addis   r11,r0,0                /* get functions table addr */
170         ori     r11,r11,0               /* Note: this code is patched in trap_init */
171         addis   r12,r0,0                /* get number of functions */
172         ori     r12,r12,0
173
174         cmplw   0, r0, r12
175         bge     1f
176
177         rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
178         add     r11,r11,r0
179         lwz     r11,0(r11)
180
181         li      r20,0xd00-4             /* Get stack pointer */
182         lwz     r12,0(r20)
183         subi    r12,r12,12              /* Adjust stack pointer */
184         li      r0,0xc00+_end_back-SystemCall
185         cmplw   0, r0, r12              /* Check stack overflow */
186         bgt     1f
187         stw     r12,0(r20)
188
189         mflr    r0
190         stw     r0,0(r12)
191         mfspr   r0,SRR0
192         stw     r0,4(r12)
193         mfspr   r0,SRR1
194         stw     r0,8(r12)
195
196         li      r12,0xc00+_back-SystemCall
197         mtlr    r12
198         mtspr   SRR0,r11
199
200 1:      SYNC
201         rfi
202
203 _back:
204
205         mfmsr   r11                     /* Disable interrupts */
206         li      r12,0
207         ori     r12,r12,MSR_EE
208         andc    r11,r11,r12
209         SYNC                            /* Some chip revs need this... */
210         mtmsr   r11
211         SYNC
212
213         li      r12,0xd00-4             /* restore regs */
214         lwz     r12,0(r12)
215
216         lwz     r11,0(r12)
217         mtlr    r11
218         lwz     r11,4(r12)
219         mtspr   SRR0,r11
220         lwz     r11,8(r12)
221         mtspr   SRR1,r11
222
223         addi    r12,r12,12              /* Adjust stack pointer */
224         li      r20,0xd00-4
225         stw     r12,0(r20)
226
227         SYNC
228         rfi
229 _end_back:
230
231         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
232
233         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
234         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
235
236         /*
237          * On the MPC8xx, this is a software emulation interrupt. It
238          * occurs for all unimplemented and illegal instructions.
239          */
240         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
241
242         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
243         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
244         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
245         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
246
247         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
248         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
249         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
250         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
251         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
252         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
253         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
254
255         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
256         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
257         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
258         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
259
260         .globl  _end_of_vectors
261 _end_of_vectors:
262
263         . = 0x2000
264
265 boot_cold:
266 boot_warm:
267         /* disable everything */
268         li      r0, 0
269         mtspr   HID0, r0
270         sync
271         mtmsr   0
272         bl      invalidate_bats
273         sync
274
275 #ifdef CFG_L2
276         /* init the L2 cache */
277         addis   r3, r0, L2_INIT@h
278         ori     r3, r3, L2_INIT@l
279         sync
280         mtspr   l2cr, r3
281 #endif
282 #if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
283         .long   0x7e00066c
284                 /*
285                  * dssall instruction, gas doesn't have it yet
286                  * ...for altivec, data stream stop all this probably
287                  * isn't needed unless we warm (software) reboot U-Boot
288                  */
289 #endif
290
291 #ifdef CFG_L2
292         /* invalidate the L2 cache */
293         bl      l2cache_invalidate
294         sync
295 #endif
296 #ifdef CFG_BOARD_ASM_INIT
297         /* do early init */
298         bl      board_asm_init
299 #endif
300
301         /*
302          * Calculate absolute address in FLASH and jump there
303          *------------------------------------------------------*/
304         lis     r3, CFG_MONITOR_BASE@h
305         ori     r3, r3, CFG_MONITOR_BASE@l
306         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
307         mtlr    r3
308         blr
309
310 in_flash:
311         /* let the C-code set up the rest                       */
312         /*                                                      */
313         /* Be careful to keep code relocatable !                */
314         /*------------------------------------------------------*/
315
316         /* perform low-level init */
317         /* sdram init, galileo init, etc */
318         /* r3:  NHR bit from HID0 */
319
320         /* setup the bats */
321         bl      setup_bats
322         sync
323
324         /*
325          * Cache must be enabled here for stack-in-cache trick.
326          * This means we need to enable the BATS.
327          * This means:
328          *   1) for the EVB, original gt regs need to be mapped
329          *   2) need to have an IBAT for the 0xf region,
330          *      we are running there!
331          * Cache should be turned on after BATs, since by default
332          * everything is write-through.
333          * The init-mem BAT can be reused after reloc. The old
334          * gt-regs BAT can be reused after board_init_f calls
335          * board_pre_init (EVB only).
336          */
337 #if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC)
338         /* enable address translation */
339         bl      enable_addr_trans
340         sync
341
342         /* enable and invalidate the data cache */
343         bl      l1dcache_enable
344         sync
345 #endif
346 #ifdef CFG_INIT_RAM_LOCK
347         bl      lock_ram_in_cache
348         sync
349 #endif
350
351         /* set up the stack pointer in our newly created
352          * cache-ram (r1) */
353         lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
354         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
355
356         li      r0, 0           /* Make room for stack frame header and */
357         stwu    r0, -4(r1)      /* clear final stack frame so that      */
358         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
359
360         GET_GOT                 /* initialize GOT access        */
361
362         /* run low-level CPU init code     (from Flash) */
363         bl      cpu_init_f
364         sync
365
366         mr      r3, r21
367
368         /* r3: BOOTFLAG */
369         /* run 1st part of board init code (from Flash)   */
370         bl      board_init_f
371         sync
372
373         /* NOTREACHED */
374
375         .globl  invalidate_bats
376 invalidate_bats:
377         /* invalidate BATs */
378         mtspr   IBAT0U, r0
379         mtspr   IBAT1U, r0
380         mtspr   IBAT2U, r0
381         mtspr   IBAT3U, r0
382 #ifdef CONFIG_750FX
383         mtspr   IBAT4U, r0
384         mtspr   IBAT5U, r0
385         mtspr   IBAT6U, r0
386         mtspr   IBAT7U, r0
387 #endif
388         isync
389         mtspr   DBAT0U, r0
390         mtspr   DBAT1U, r0
391         mtspr   DBAT2U, r0
392         mtspr   DBAT3U, r0
393 #ifdef CONFIG_750FX
394         mtspr   DBAT4U, r0
395         mtspr   DBAT5U, r0
396         mtspr   DBAT6U, r0
397         mtspr   DBAT7U, r0
398 #endif
399         isync
400         sync
401         blr
402
403         /* setup_bats - set them up to some initial state */
404         .globl  setup_bats
405 setup_bats:
406         addis   r0, r0, 0x0000
407
408         /* IBAT 0 */
409         addis   r4, r0, CFG_IBAT0L@h
410         ori     r4, r4, CFG_IBAT0L@l
411         addis   r3, r0, CFG_IBAT0U@h
412         ori     r3, r3, CFG_IBAT0U@l
413         mtspr   IBAT0L, r4
414         mtspr   IBAT0U, r3
415         isync
416
417         /* DBAT 0 */
418         addis   r4, r0, CFG_DBAT0L@h
419         ori     r4, r4, CFG_DBAT0L@l
420         addis   r3, r0, CFG_DBAT0U@h
421         ori     r3, r3, CFG_DBAT0U@l
422         mtspr   DBAT0L, r4
423         mtspr   DBAT0U, r3
424         isync
425
426         /* IBAT 1 */
427         addis   r4, r0, CFG_IBAT1L@h
428         ori     r4, r4, CFG_IBAT1L@l
429         addis   r3, r0, CFG_IBAT1U@h
430         ori     r3, r3, CFG_IBAT1U@l
431         mtspr   IBAT1L, r4
432         mtspr   IBAT1U, r3
433         isync
434
435         /* DBAT 1 */
436         addis   r4, r0, CFG_DBAT1L@h
437         ori     r4, r4, CFG_DBAT1L@l
438         addis   r3, r0, CFG_DBAT1U@h
439         ori     r3, r3, CFG_DBAT1U@l
440         mtspr   DBAT1L, r4
441         mtspr   DBAT1U, r3
442         isync
443
444         /* IBAT 2 */
445         addis   r4, r0, CFG_IBAT2L@h
446         ori     r4, r4, CFG_IBAT2L@l
447         addis   r3, r0, CFG_IBAT2U@h
448         ori     r3, r3, CFG_IBAT2U@l
449         mtspr   IBAT2L, r4
450         mtspr   IBAT2U, r3
451         isync
452
453         /* DBAT 2 */
454         addis   r4, r0, CFG_DBAT2L@h
455         ori     r4, r4, CFG_DBAT2L@l
456         addis   r3, r0, CFG_DBAT2U@h
457         ori     r3, r3, CFG_DBAT2U@l
458         mtspr   DBAT2L, r4
459         mtspr   DBAT2U, r3
460         isync
461
462         /* IBAT 3 */
463         addis   r4, r0, CFG_IBAT3L@h
464         ori     r4, r4, CFG_IBAT3L@l
465         addis   r3, r0, CFG_IBAT3U@h
466         ori     r3, r3, CFG_IBAT3U@l
467         mtspr   IBAT3L, r4
468         mtspr   IBAT3U, r3
469         isync
470
471         /* DBAT 3 */
472         addis   r4, r0, CFG_DBAT3L@h
473         ori     r4, r4, CFG_DBAT3L@l
474         addis   r3, r0, CFG_DBAT3U@h
475         ori     r3, r3, CFG_DBAT3U@l
476         mtspr   DBAT3L, r4
477         mtspr   DBAT3U, r3
478         isync
479
480 #ifdef CONFIG_750FX
481         /* IBAT 4 */
482         addis   r4, r0, CFG_IBAT4L@h
483         ori     r4, r4, CFG_IBAT4L@l
484         addis   r3, r0, CFG_IBAT4U@h
485         ori     r3, r3, CFG_IBAT4U@l
486         mtspr   IBAT4L, r4
487         mtspr   IBAT4U, r3
488         isync
489
490         /* DBAT 4 */
491         addis   r4, r0, CFG_DBAT4L@h
492         ori     r4, r4, CFG_DBAT4L@l
493         addis   r3, r0, CFG_DBAT4U@h
494         ori     r3, r3, CFG_DBAT4U@l
495         mtspr   DBAT4L, r4
496         mtspr   DBAT4U, r3
497         isync
498
499         /* IBAT 5 */
500         addis   r4, r0, CFG_IBAT5L@h
501         ori     r4, r4, CFG_IBAT5L@l
502         addis   r3, r0, CFG_IBAT5U@h
503         ori     r3, r3, CFG_IBAT5U@l
504         mtspr   IBAT5L, r4
505         mtspr   IBAT5U, r3
506         isync
507
508         /* DBAT 5 */
509         addis   r4, r0, CFG_DBAT5L@h
510         ori     r4, r4, CFG_DBAT5L@l
511         addis   r3, r0, CFG_DBAT5U@h
512         ori     r3, r3, CFG_DBAT5U@l
513         mtspr   DBAT5L, r4
514         mtspr   DBAT5U, r3
515         isync
516
517         /* IBAT 6 */
518         addis   r4, r0, CFG_IBAT6L@h
519         ori     r4, r4, CFG_IBAT6L@l
520         addis   r3, r0, CFG_IBAT6U@h
521         ori     r3, r3, CFG_IBAT6U@l
522         mtspr   IBAT6L, r4
523         mtspr   IBAT6U, r3
524         isync
525
526         /* DBAT 6 */
527         addis   r4, r0, CFG_DBAT6L@h
528         ori     r4, r4, CFG_DBAT6L@l
529         addis   r3, r0, CFG_DBAT6U@h
530         ori     r3, r3, CFG_DBAT6U@l
531         mtspr   DBAT6L, r4
532         mtspr   DBAT6U, r3
533         isync
534
535         /* IBAT 7 */
536         addis   r4, r0, CFG_IBAT7L@h
537         ori     r4, r4, CFG_IBAT7L@l
538         addis   r3, r0, CFG_IBAT7U@h
539         ori     r3, r3, CFG_IBAT7U@l
540         mtspr   IBAT7L, r4
541         mtspr   IBAT7U, r3
542         isync
543
544         /* DBAT 7 */
545         addis   r4, r0, CFG_DBAT7L@h
546         ori     r4, r4, CFG_DBAT7L@l
547         addis   r3, r0, CFG_DBAT7U@h
548         ori     r3, r3, CFG_DBAT7U@l
549         mtspr   DBAT7L, r4
550         mtspr   DBAT7U, r3
551         isync
552 #endif
553
554         /* bats are done, now invalidate the TLBs */
555
556         addis   r3, 0, 0x0000
557         addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
558
559         isync
560
561 tlblp:
562         tlbie   r3
563         sync
564         addi    r3, r3, 0x1000
565         cmp     0, 0, r3, r5
566         blt tlblp
567
568         blr
569
570         .globl enable_addr_trans
571 enable_addr_trans:
572         /* enable address translation */
573         mfmsr   r5
574         ori     r5, r5, (MSR_IR | MSR_DR)
575         mtmsr   r5
576         isync
577         blr
578
579         .globl disable_addr_trans
580 disable_addr_trans:
581         /* disable address translation */
582         mflr    r4
583         mfmsr   r3
584         andi.   r0, r3, (MSR_IR | MSR_DR)
585         beqlr
586         andc    r3, r3, r0
587         mtspr   SRR0, r4
588         mtspr   SRR1, r3
589         rfi
590
591 /*
592  * This code finishes saving the registers to the exception frame
593  * and jumps to the appropriate handler for the exception.
594  * Register r21 is pointer into trap frame, r1 has new stack pointer.
595  */
596         .globl  transfer_to_handler
597 transfer_to_handler:
598         stw     r22,_NIP(r21)
599         lis     r22,MSR_POW@h
600         andc    r23,r23,r22
601         stw     r23,_MSR(r21)
602         SAVE_GPR(7, r21)
603         SAVE_4GPRS(8, r21)
604         SAVE_8GPRS(12, r21)
605         SAVE_8GPRS(24, r21)
606         mflr    r23
607         andi.   r24,r23,0x3f00          /* get vector offset */
608         stw     r24,TRAP(r21)
609         li      r22,0
610         stw     r22,RESULT(r21)
611         mtspr   SPRG2,r22               /* r1 is now kernel sp */
612         lwz     r24,0(r23)              /* virtual address of handler */
613         lwz     r23,4(r23)              /* where to go when done */
614         mtspr   SRR0,r24
615         mtspr   SRR1,r20
616         mtlr    r23
617         SYNC
618         rfi                             /* jump to handler, enable MMU */
619
620 int_return:
621         mfmsr   r28             /* Disable interrupts */
622         li      r4,0
623         ori     r4,r4,MSR_EE
624         andc    r28,r28,r4
625         SYNC                    /* Some chip revs need this... */
626         mtmsr   r28
627         SYNC
628         lwz     r2,_CTR(r1)
629         lwz     r0,_LINK(r1)
630         mtctr   r2
631         mtlr    r0
632         lwz     r2,_XER(r1)
633         lwz     r0,_CCR(r1)
634         mtspr   XER,r2
635         mtcrf   0xFF,r0
636         REST_10GPRS(3, r1)
637         REST_10GPRS(13, r1)
638         REST_8GPRS(23, r1)
639         REST_GPR(31, r1)
640         lwz     r2,_NIP(r1)     /* Restore environment */
641         lwz     r0,_MSR(r1)
642         mtspr   SRR0,r2
643         mtspr   SRR1,r0
644         lwz     r0,GPR0(r1)
645         lwz     r2,GPR2(r1)
646         lwz     r1,GPR1(r1)
647         SYNC
648         rfi
649
650         .globl  dc_read
651 dc_read:
652         blr
653
654         .globl get_pvr
655 get_pvr:
656         mfspr   r3, PVR
657         blr
658
659 /*-----------------------------------------------------------------------*/
660 /*
661  * void relocate_code (addr_sp, gd, addr_moni)
662  *
663  * This "function" does not return, instead it continues in RAM
664  * after relocating the monitor code.
665  *
666  * r3 = dest
667  * r4 = src
668  * r5 = length in bytes
669  * r6 = cachelinesize
670  */
671         .globl  relocate_code
672 relocate_code:
673         mr      r1,  r3         /* Set new stack pointer                */
674         mr      r9,  r4         /* Save copy of Global Data pointer     */
675         mr      r10, r5         /* Save copy of Destination Address     */
676
677         mr      r3,  r5                         /* Destination Address  */
678         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
679         ori     r4, r4, CFG_MONITOR_BASE@l
680         lwz     r5, GOT(__init_end)
681         sub     r5, r5, r4
682         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
683
684         /*
685          * Fix GOT pointer:
686          *
687          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
688          *
689          * Offset:
690          */
691         sub     r15, r10, r4
692
693         /* First our own GOT */
694         add     r14, r14, r15
695         /* then the one used by the C code */
696         add     r30, r30, r15
697
698         /*
699          * Now relocate code
700          */
701 #ifdef CONFIG_ECC
702         bl      board_relocate_rom
703         sync
704         mr      r3, r10                         /* Destination Address  */
705         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
706         ori     r4, r4, CFG_MONITOR_BASE@l
707         lwz     r5, GOT(__init_end)
708         sub     r5, r5, r4
709         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
710 #else
711         cmplw   cr1,r3,r4
712         addi    r0,r5,3
713         srwi.   r0,r0,2
714         beq     cr1,4f          /* In place copy is not necessary       */
715         beq     7f              /* Protect against 0 count              */
716         mtctr   r0
717         bge     cr1,2f
718
719         la      r8,-4(r4)
720         la      r7,-4(r3)
721 1:      lwzu    r0,4(r8)
722         stwu    r0,4(r7)
723         bdnz    1b
724         b       4f
725
726 2:      slwi    r0,r0,2
727         add     r8,r4,r0
728         add     r7,r3,r0
729 3:      lwzu    r0,-4(r8)
730         stwu    r0,-4(r7)
731         bdnz    3b
732 #endif
733 /*
734  * Now flush the cache: note that we must start from a cache aligned
735  * address. Otherwise we might miss one cache line.
736  */
737 4:      cmpwi   r6,0
738         add     r5,r3,r5
739         beq     7f              /* Always flush prefetch queue in any case */
740         subi    r0,r6,1
741         andc    r3,r3,r0
742         mr      r4,r3
743 5:      dcbst   0,r4
744         add     r4,r4,r6
745         cmplw   r4,r5
746         blt     5b
747         sync                    /* Wait for all dcbst to complete on bus */
748         mr      r4,r3
749 6:      icbi    0,r4
750         add     r4,r4,r6
751         cmplw   r4,r5
752         blt     6b
753 7:      sync                    /* Wait for all icbi to complete on bus */
754         isync
755
756 /*
757  * We are done. Do not return, instead branch to second part of board
758  * initialization, now running from RAM.
759  */
760         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
761         mtlr    r0
762         blr
763
764 in_ram:
765 #ifdef CONFIG_ECC
766         bl      board_init_ecc
767 #endif
768         /*
769          * Relocation Function, r14 point to got2+0x8000
770          *
771          * Adjust got2 pointers, no need to check for 0, this code
772          * already puts a few entries in the table.
773          */
774         li      r0,__got2_entries@sectoff@l
775         la      r3,GOT(_GOT2_TABLE_)
776         lwz     r11,GOT(_GOT2_TABLE_)
777         mtctr   r0
778         sub     r11,r3,r11
779         addi    r3,r3,-4
780 1:      lwzu    r0,4(r3)
781         add     r0,r0,r11
782         stw     r0,0(r3)
783         bdnz    1b
784
785         /*
786          * Now adjust the fixups and the pointers to the fixups
787          * in case we need to move ourselves again.
788          */
789 2:      li      r0,__fixup_entries@sectoff@l
790         lwz     r3,GOT(_FIXUP_TABLE_)
791         cmpwi   r0,0
792         mtctr   r0
793         addi    r3,r3,-4
794         beq     4f
795 3:      lwzu    r4,4(r3)
796         lwzux   r0,r4,r11
797         add     r0,r0,r11
798         stw     r10,0(r3)
799         stw     r0,0(r4)
800         bdnz    3b
801 4:
802 /* clear_bss: */
803         /*
804          * Now clear BSS segment
805          */
806         lwz     r3,GOT(__bss_start)
807         lwz     r4,GOT(_end)
808
809         cmplw   0, r3, r4
810         beq     6f
811
812         li      r0, 0
813 5:
814         stw     r0, 0(r3)
815         addi    r3, r3, 4
816         cmplw   0, r3, r4
817         bne     5b
818 6:
819         mr      r3, r10         /* Destination Address          */
820 #ifdef CONFIG_AMIGAONEG3SE
821         mr      r4, r9          /* Use RAM copy of the global data */
822 #endif
823         bl      after_reloc
824
825         /* not reached - end relocate_code */
826 /*-----------------------------------------------------------------------*/
827
828         /*
829          * Copy exception vector code to low memory
830          *
831          * r3: dest_addr
832          * r7: source address, r8: end address, r9: target address
833          */
834         .globl  trap_init
835 trap_init:
836         lwz     r7, GOT(_start)
837         lwz     r8, GOT(_end_of_vectors)
838
839         li      r9, 0x100               /* reset vector always at 0x100 */
840
841         cmplw   0, r7, r8
842         bgelr                           /* return if r7>=r8 - just in case */
843
844         mflr    r4                      /* save link register           */
845 1:
846         lwz     r0, 0(r7)
847         stw     r0, 0(r9)
848         addi    r7, r7, 4
849         addi    r9, r9, 4
850         cmplw   0, r7, r8
851         bne     1b
852
853         /*
854          * relocate `hdlr' and `int_return' entries
855          */
856         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
857         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
858 2:
859         bl      trap_reloc
860         addi    r7, r7, 0x100           /* next exception vector        */
861         cmplw   0, r7, r8
862         blt     2b
863
864         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
865         bl      trap_reloc
866
867         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
868         bl      trap_reloc
869
870         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
871         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
872 3:
873         bl      trap_reloc
874         addi    r7, r7, 0x100           /* next exception vector        */
875         cmplw   0, r7, r8
876         blt     3b
877
878         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
879         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
880 4:
881         bl      trap_reloc
882         addi    r7, r7, 0x100           /* next exception vector        */
883         cmplw   0, r7, r8
884         blt     4b
885
886         /* enable execptions from RAM vectors */
887         mfmsr   r7
888         li      r8,MSR_IP
889         andc    r7,r7,r8
890         mtmsr   r7
891
892         mtlr    r4                      /* restore link register        */
893         blr
894
895         /*
896          * Function: relocate entries for one exception vector
897          */
898 trap_reloc:
899         lwz     r0, 0(r7)               /* hdlr ...                     */
900         add     r0, r0, r3              /*  ... += dest_addr            */
901         stw     r0, 0(r7)
902
903         lwz     r0, 4(r7)               /* int_return ...               */
904         add     r0, r0, r3              /*  ... += dest_addr            */
905         stw     r0, 4(r7)
906
907         sync
908         isync
909
910         blr
911
912 #ifdef CFG_INIT_RAM_LOCK
913 lock_ram_in_cache:
914         /* Allocate Initial RAM in data cache.
915          */
916         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
917         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
918         li      r2, ((CFG_INIT_RAM_END & ~31) + \
919                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
920         mtctr   r2
921 1:
922         dcbz    r0, r3
923         addi    r3, r3, 32
924         bdnz    1b
925
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
934 .globl unlock_ram_in_cache
935 unlock_ram_in_cache:
936         /* invalidate the INIT_RAM section */
937         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
938         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
939         li      r2, ((CFG_INIT_RAM_END & ~31) + \
940                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
941         mtctr   r2
942 1:      icbi    r0, r3
943         addi    r3, r3, 32
944         bdnz    1b
945         sync                    /* Wait for all icbi to complete on bus */
946         isync
947
948         /* Unlock the data cache and invalidate it */
949         mfspr   r0, HID0
950         li      r3,0x1000
951         andc    r0,r0,r3
952         li      r3,0x0400
953         or      r0,r0,r3
954         sync
955         mtspr   HID0, r0
956         sync
957         blr
958 #endif