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