9207396cdfc752c14a723f6fb1e0f2e7b0948e4f
[platform/kernel/u-boot.git] / cpu / mpc85xx / start.S
1 /*
2  * Copyright 2004 Freescale Semiconductor.
3  * Copyright (C) 2003  Motorola,Inc.
4  * Xianghua Xiao<X.Xiao@motorola.com>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 /* U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards
26  *
27  * The processor starts at 0xfffffffc and the code is first executed in the
28  * last 4K page(0xfffff000-0xffffffff) in flash/rom.
29  *
30  */
31
32 #include <config.h>
33 #include <mpc85xx.h>
34 #include <version.h>
35
36 #define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
37
38 #include <ppc_asm.tmpl>
39 #include <ppc_defs.h>
40
41 #include <asm/cache.h>
42 #include <asm/mmu.h>
43
44 #ifndef  CONFIG_IDENT_STRING
45 #define  CONFIG_IDENT_STRING ""
46 #endif
47
48 #undef  MSR_KERNEL
49 #define MSR_KERNEL ( MSR_ME  )  /* Machine Check */
50
51 /*
52  * Set up GOT: Global Offset Table
53  *
54  * Use r14 to access the GOT
55  */
56         START_GOT
57         GOT_ENTRY(_GOT2_TABLE_)
58         GOT_ENTRY(_FIXUP_TABLE_)
59
60         GOT_ENTRY(_start)
61         GOT_ENTRY(_start_of_vectors)
62         GOT_ENTRY(_end_of_vectors)
63         GOT_ENTRY(transfer_to_handler)
64
65         GOT_ENTRY(__init_end)
66         GOT_ENTRY(_end)
67         GOT_ENTRY(__bss_start)
68         END_GOT
69
70 /*
71  * e500 Startup -- after reset only the last 4KB of the effective
72  * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
73  * section is located at THIS LAST page and basically does three
74  * things: clear some registers, set up exception tables and
75  * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
76  * continue the boot procedure.
77
78  * Once the boot rom is mapped by TLB entries we can proceed
79  * with normal startup.
80  *
81  */
82
83     .section .bootpg,"ax"
84     .globl _start_e500
85
86 _start_e500:
87         mfspr   r0, PVR
88         lis     r1, PVR_85xx_REV1@h
89         ori     r1, r1, PVR_85xx_REV1@l
90         cmpw    r0, r1
91         bne     1f
92
93         /* Semi-bogus errata fixup for Rev 1 */
94         li      r0,0x2000
95         mtspr   977,r0
96
97         /*
98          * Before invalidating MMU L1/L2, read TLB1 Entry 0 and then
99          * write it back immediately to fixup a Rev 1 bug (Errata CPU4)
100          * for this initial TLB1 entry 0, otherwise the TLB1 entry 0
101          * will be invalidated (incorrectly).
102          */
103         lis     r2,0x1000
104         mtspr   MAS0,r2
105         tlbre
106         tlbwe
107         isync
108
109 1:
110         /*
111          * Clear and set up some registers.
112          * Note: Some registers need strict synchronization by
113          * sync/mbar/msync/isync when being "mtspr".
114          * BookE: isync before PID,tlbivax,tlbwe
115          * BookE: isync after MSR,PID; msync_isync after tlbivax & tlbwe
116          * E500:  msync,isync before L1CSR0
117          * E500:  isync after BBEAR,BBTAR,BUCSR,DBCR0,DBCR1,HID0,HID1,
118          *        L1CSR0, L1CSR1, MAS[0,1,2,3,4,6],MMUCSR0, PID[0,1,2],
119          *        SPEFCSR
120          */
121
122         /* invalidate d-cache */
123         mfspr   r0,L1CSR0
124         ori     r0,r0,0x0002
125         msync
126         isync
127         mtspr   L1CSR0,r0
128         isync
129
130         /* disable d-cache */
131         li      r0,0x0
132         mtspr   L1CSR0,r0
133
134         /* invalidate i-cache */
135         mfspr   r0,L1CSR1
136         ori     r0,r0,0x0002
137         mtspr   L1CSR1,r0
138         isync
139
140         /* disable i-cache */
141         li      r0,0x0
142         mtspr   L1CSR1,r0
143         isync
144
145         /* clear registers */
146         li      r0,0
147         mtspr   SRR0,r0
148         mtspr   SRR1,r0
149         mtspr   CSRR0,r0
150         mtspr   CSRR1,r0
151         mtspr   MCSRR0,r0
152         mtspr   MCSRR1,r0
153
154         mtspr   ESR,r0
155         mtspr   MCSR,r0
156         mtspr   DEAR,r0
157
158         mtspr   DBCR0,r0
159         mtspr   DBCR1,r0
160         mtspr   DBCR2,r0
161         mtspr   IAC1,r0
162         mtspr   IAC2,r0
163         mtspr   DAC1,r0
164         mtspr   DAC2,r0
165
166         mfspr   r1,DBSR
167         mtspr   DBSR,r1         /* Clear all valid bits */
168
169         mtspr   PID0,r0
170         mtspr   PID1,r0
171         mtspr   PID2,r0
172         mtspr   TCR,r0
173
174         mtspr   BUCSR,r0        /* disable branch prediction */
175         mtspr   MAS4,r0
176         mtspr   MAS6,r0
177         isync
178
179         /* Setup interrupt vectors */
180         lis     r1,0xfff8
181         mtspr IVPR, r1
182
183         li      r1,0x0100
184         mtspr   IVOR0,r1        /* 0: Critical input */
185         li      r1,0x0200
186         mtspr   IVOR1,r1        /* 1: Machine check */
187         li      r1,0x0300
188         mtspr   IVOR2,r1        /* 2: Data storage */
189         li      r1,0x0400
190         mtspr   IVOR3,r1        /* 3: Instruction storage */
191         li      r1,0x0500
192         mtspr   IVOR4,r1        /* 4: External interrupt */
193         li      r1,0x0600
194         mtspr   IVOR5,r1        /* 5: Alignment */
195         li      r1,0x0700
196         mtspr   IVOR6,r1        /* 6: Program check */
197         li      r1,0x0800
198         mtspr   IVOR7,r1        /* 7: floating point unavailable */
199         li      r1,0x0c00
200         mtspr   IVOR8,r1        /* 8: System call */
201         /* 9: Auxiliary processor unavailable(unsupported) */
202         li      r1,0x1000
203         mtspr   IVOR10,r1       /* 10: Decrementer */
204         li      r1,0x1400
205         mtspr   IVOR13,r1       /* 13: Data TLB error */
206         li      r1,0x1300
207         mtspr   IVOR14,r1       /* 14: Instruction TLB error */
208         li      r1,0x2000
209         mtspr   IVOR15,r1       /* 15: Debug */
210
211         /*
212          * Invalidate MMU L1/L2
213          *
214          * Note: There is a fixup earlier for Errata CPU4 on
215          * Rev 1 parts that must precede this MMU invalidation.
216          */
217         li      r2, 0x001e
218         mtspr   MMUCSR0, r2
219         isync
220
221         /*
222          * Invalidate all TLB0 entries.
223          */
224         li      r3,4
225         li      r4,0
226         tlbivax r4,r3
227         /*
228          * To avoid REV1 Errata CPU6 issues, make sure
229          * the instruction following tlbivax is not a store.
230          */
231
232         /*
233          * After reset, CCSRBAR is located at CFG_CCSRBAR_DEFAULT, i.e.
234          * 0xff700000-0xff800000. We need add a TLB1 entry for this 1MB
235          * region before we can access any CCSR registers such as L2
236          * registers, Local Access Registers,etc. We will also re-allocate
237          * CFG_CCSRBAR_DEFAULT to CFG_CCSRBAR immediately after TLB1 setup.
238          *
239          * Please refer to board-specif directory for TLB1 entry configuration.
240          * (e.g. board/<yourboard>/init.S)
241          *
242          */
243         bl      tlb1_entry
244         mr      r5,r0
245         li      r1,0x0020       /* max 16 TLB1 plus some TLB0 entries */
246         mtctr   r1
247         lwzu    r4,0(r5)        /* how many TLB1 entries we actually use */
248
249 0:      cmpwi   r4,0
250         beq     1f
251         lwzu    r0,4(r5)
252         lwzu    r1,4(r5)
253         lwzu    r2,4(r5)
254         lwzu    r3,4(r5)
255         mtspr   MAS0,r0
256         mtspr   MAS1,r1
257         mtspr   MAS2,r2
258         mtspr   MAS3,r3
259         isync
260         msync
261         tlbwe
262         isync
263         addi    r4,r4,-1
264         bdnz    0b
265
266 1:
267 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
268         /* Special sequence needed to update CCSRBAR itself */
269         lis     r4, CFG_CCSRBAR_DEFAULT@h
270         ori     r4, r4, CFG_CCSRBAR_DEFAULT@l
271
272         lis     r5, CFG_CCSRBAR@h
273         ori     r5, r5, CFG_CCSRBAR@l
274         srwi    r6,r5,12
275         stw     r6, 0(r4)
276         isync
277
278         lis     r5, 0xffff
279         ori     r5,r5,0xf000
280         lwz     r5, 0(r5)
281         isync
282
283         lis     r3, CFG_CCSRBAR@h
284         lwz     r5, CFG_CCSRBAR@l(r3)
285         isync
286 #endif
287
288
289         /* set up local access windows, defined at board/<boardname>/init.S */
290         lis     r7,CFG_CCSRBAR@h
291         ori     r7,r7,CFG_CCSRBAR@l
292
293         bl      law_entry
294         mr      r6,r0
295         li      r1,0x0007       /* 8 LAWs, but reserve one for boot-over-rio-or-pci */
296         mtctr   r1
297         lwzu    r5,0(r6)        /* how many windows we actually use */
298
299         li      r2,0x0c28       /* the first pair is reserved for boot-over-rio-or-pci */
300         li      r1,0x0c30
301
302 0:      cmpwi   r5,0
303         beq     1f
304         lwzu    r4,4(r6)
305         lwzu    r3,4(r6)
306         stwx    r4,r7,r2
307         stwx    r3,r7,r1
308         addi    r5,r5,-1
309         addi    r2,r2,0x0020
310         addi    r1,r1,0x0020
311         bdnz    0b
312
313         /* Jump out the last 4K page and continue to 'normal' start */
314 1:      bl      3f
315         b       _start
316
317 3:      li      r0,0
318         mtspr   SRR1,r0         /* Keep things disabled for now */
319         mflr    r1
320         mtspr   SRR0,r1
321         rfi
322
323 /*
324  * r3 - 1st arg to board_init(): IMMP pointer
325  * r4 - 2nd arg to board_init(): boot flag
326  */
327         .text
328         .long   0x27051956              /* U-BOOT Magic Number                  */
329         .globl  version_string
330 version_string:
331         .ascii U_BOOT_VERSION
332         .ascii " (", __DATE__, " - ", __TIME__, ")"
333         .ascii CONFIG_IDENT_STRING, "\0"
334
335         . = EXC_OFF_SYS_RESET
336         .globl  _start
337 _start:
338         /* Clear and set up some registers. */
339         li      r0,0x0000
340         lis     r1,0xffff
341         mtspr   DEC,r0                  /* prevent dec exceptions */
342         mttbl   r0                      /* prevent fit & wdt exceptions */
343         mttbu   r0
344         mtspr   TSR,r1                  /* clear all timer exception status */
345         mtspr   TCR,r0                  /* disable all */
346         mtspr   ESR,r0                  /* clear exception syndrome register */
347         mtspr   MCSR,r0                 /* machine check syndrome register */
348         mtxer   r0                      /* clear integer exception register */
349         lis     r1,0x0002               /* set CE bit (Critical Exceptions) */
350         ori     r1,r1,0x1200            /* set ME/DE bit */
351         mtmsr   r1                      /* change MSR */
352         isync
353
354         /* Enable Time Base and Select Time Base Clock */
355         lis     r0,HID0_EMCP@h          /* Enable machine check */
356         ori     r0,r0,0x4000            /* time base is processor clock */
357         mtspr   HID0,r0
358
359 #if defined(CONFIG_ADDR_STREAMING)
360         li      r0,0x3000
361 #else
362         li      r0,0x1000
363 #endif
364         mtspr   HID1,r0
365
366         /* Enable Branch Prediction */
367 #if defined(CONFIG_BTB)
368         li      r0,0x201                /* BBFI = 1, BPEN = 1 */
369         mtspr   BUCSR,r0
370 #endif
371
372 #if defined(CFG_INIT_DBCR)
373         lis     r1,0xffff
374         ori     r1,r1,0xffff
375         mtspr   DBSR,r1                 /* Clear all status bits */
376         lis     r0,CFG_INIT_DBCR@h      /* DBCR0[IDM] must be set */
377         ori     r0,r0,CFG_INIT_DBCR@l
378         mtspr   DBCR0,r0
379 #endif
380
381 /* L1 DCache is used for initial RAM */
382         mfspr   r2, L1CSR0
383         ori     r2, r2, 0x0003
384         oris    r2, r2, 0x0001
385         mtspr   L1CSR0, r2      /* enable/invalidate L1 Dcache */
386         isync
387
388         /* Allocate Initial RAM in data cache.
389          */
390         lis     r3, CFG_INIT_RAM_ADDR@h
391         ori     r3, r3, CFG_INIT_RAM_ADDR@l
392         li      r2, 512 /* 512*32=16K */
393         mtctr   r2
394         li      r0, 0
395 1:
396         dcbz    r0, r3
397         dcbtls  0,r0, r3
398         addi    r3, r3, 32
399         bdnz    1b
400
401 #ifndef CFG_RAMBOOT
402         /* Calculate absolute address in FLASH and jump there           */
403         /*--------------------------------------------------------------*/
404         lis     r3, CFG_MONITOR_BASE@h
405         ori     r3, r3, CFG_MONITOR_BASE@l
406         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
407         mtlr    r3
408         blr
409
410 in_flash:
411 #endif  /* CFG_RAMBOOT */
412
413         /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
414         lis     r1,CFG_INIT_RAM_ADDR@h
415         ori     r1,r1,CFG_INIT_SP_OFFSET@l
416
417         li      r0,0
418         stwu    r0,-4(r1)
419         stwu    r0,-4(r1)               /* Terminate call chain */
420
421         stwu    r1,-8(r1)               /* Save back chain and move SP */
422         lis     r0,RESET_VECTOR@h       /* Address of reset vector */
423         ori     r0,r0, RESET_VECTOR@l
424         stwu    r1,-8(r1)               /* Save back chain and move SP */
425         stw     r0,+12(r1)              /* Save return addr (underflow vect) */
426
427         GET_GOT
428         bl      cpu_init_f
429         bl      icache_enable
430         bl      board_init_f
431         isync
432
433 /* --FIXME-- machine check with MCSRRn and rfmci */
434
435         .globl  _start_of_vectors
436 _start_of_vectors:
437 #if 0
438 /* Critical input. */
439         CRIT_EXCEPTION(0x0100, CritcalInput, CritcalInputException)
440 #endif
441 /* Machine check --FIXME-- Should be MACH_EXCEPTION */
442         CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
443
444 /* Data Storage exception. */
445         STD_EXCEPTION(0x0300, DataStorage, UnknownException)
446
447 /* Instruction Storage exception. */
448         STD_EXCEPTION(0x0400, InstStorage, UnknownException)
449
450 /* External Interrupt exception. */
451         STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
452
453 /* Alignment exception. */
454         . = 0x0600
455 Alignment:
456         EXCEPTION_PROLOG
457         mfspr   r4,DAR
458         stw     r4,_DAR(r21)
459         mfspr   r5,DSISR
460         stw     r5,_DSISR(r21)
461         addi    r3,r1,STACK_FRAME_OVERHEAD
462         li      r20,MSR_KERNEL
463         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
464         lwz     r6,GOT(transfer_to_handler)
465         mtlr    r6
466         blrl
467 .L_Alignment:
468         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
469         .long   int_return - _start + EXC_OFF_SYS_RESET
470
471 /* Program check exception */
472         . = 0x0700
473 ProgramCheck:
474         EXCEPTION_PROLOG
475         addi    r3,r1,STACK_FRAME_OVERHEAD
476         li      r20,MSR_KERNEL
477         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
478         lwz     r6,GOT(transfer_to_handler)
479         mtlr    r6
480         blrl
481 .L_ProgramCheck:
482         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
483         .long   int_return - _start + EXC_OFF_SYS_RESET
484
485         /* No FPU on MPC85xx.  This exception is not supposed to happen.
486         */
487         STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
488         STD_EXCEPTION(0x0900, Decrementer, timer_interrupt)
489         STD_EXCEPTION(0x0a00, Trap_0a, UnknownException)
490         STD_EXCEPTION(0x0b00, Trap_0b, UnknownException)
491
492         . = 0x0c00
493 /*
494  * r0 - SYSCALL number
495  * r3-... arguments
496  */
497 SystemCall:
498         addis   r11,r0,0                /* get functions table addr */
499         ori     r11,r11,0               /* Note: this code is patched in trap_init */
500         addis   r12,r0,0                /* get number of functions */
501         ori     r12,r12,0
502
503         cmplw   0, r0, r12
504         bge     1f
505
506         rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
507         add     r11,r11,r0
508         lwz     r11,0(r11)
509
510         li      r20,0xd00-4             /* Get stack pointer */
511         lwz     r12,0(r20)
512         subi    r12,r12,12              /* Adjust stack pointer */
513         li      r0,0xc00+_end_back-SystemCall
514         cmplw   0, r0, r12              /* Check stack overflow */
515         bgt     1f
516         stw     r12,0(r20)
517
518         mflr    r0
519         stw     r0,0(r12)
520         mfspr   r0,SRR0
521         stw     r0,4(r12)
522         mfspr   r0,SRR1
523         stw     r0,8(r12)
524
525         li      r12,0xc00+_back-SystemCall
526         mtlr    r12
527         mtspr   SRR0,r11
528
529 1:      SYNC
530         rfi
531 _back:
532
533         mfmsr   r11                     /* Disable interrupts */
534         li      r12,0
535         ori     r12,r12,MSR_EE
536         andc    r11,r11,r12
537         SYNC                            /* Some chip revs need this... */
538         mtmsr   r11
539         SYNC
540
541         li      r12,0xd00-4             /* restore regs */
542         lwz     r12,0(r12)
543
544         lwz     r11,0(r12)
545         mtlr    r11
546         lwz     r11,4(r12)
547         mtspr   SRR0,r11
548         lwz     r11,8(r12)
549         mtspr   SRR1,r11
550
551         addi    r12,r12,12              /* Adjust stack pointer */
552         li      r20,0xd00-4
553         stw     r12,0(r20)
554
555         SYNC
556         rfi
557 _end_back:
558
559         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
560
561         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
562         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
563
564         STD_EXCEPTION(0x1000, PIT, PITException)
565
566         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
567         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
568         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
569         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
570
571         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
572         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
573         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
574         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
575         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
576         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
577         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
578
579         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
580         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
581         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
582         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
583
584         CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
585
586         .globl  _end_of_vectors
587 _end_of_vectors:
588
589
590         . = 0x2100
591
592 /*
593  * This code finishes saving the registers to the exception frame
594  * and jumps to the appropriate handler for the exception.
595  * Register r21 is pointer into trap frame, r1 has new stack pointer.
596  */
597         .globl  transfer_to_handler
598 transfer_to_handler:
599         stw     r22,_NIP(r21)
600         lis     r22,MSR_POW@h
601         andc    r23,r23,r22
602         stw     r23,_MSR(r21)
603         SAVE_GPR(7, r21)
604         SAVE_4GPRS(8, r21)
605         SAVE_8GPRS(12, r21)
606         SAVE_8GPRS(24, r21)
607
608         mflr    r23
609         andi.   r24,r23,0x3f00          /* get vector offset */
610         stw     r24,TRAP(r21)
611         li      r22,0
612         stw     r22,RESULT(r21)
613         mtspr   SPRG2,r22               /* r1 is now kernel sp */
614
615         lwz     r24,0(r23)              /* virtual address of handler */
616         lwz     r23,4(r23)              /* where to go when done */
617         mtspr   SRR0,r24
618         mtspr   SRR1,r20
619         mtlr    r23
620         SYNC
621         rfi                             /* jump to handler, enable MMU */
622
623 int_return:
624         mfmsr   r28             /* Disable interrupts */
625         li      r4,0
626         ori     r4,r4,MSR_EE
627         andc    r28,r28,r4
628         SYNC                    /* Some chip revs need this... */
629         mtmsr   r28
630         SYNC
631         lwz     r2,_CTR(r1)
632         lwz     r0,_LINK(r1)
633         mtctr   r2
634         mtlr    r0
635         lwz     r2,_XER(r1)
636         lwz     r0,_CCR(r1)
637         mtspr   XER,r2
638         mtcrf   0xFF,r0
639         REST_10GPRS(3, r1)
640         REST_10GPRS(13, r1)
641         REST_8GPRS(23, r1)
642         REST_GPR(31, r1)
643         lwz     r2,_NIP(r1)     /* Restore environment */
644         lwz     r0,_MSR(r1)
645         mtspr   SRR0,r2
646         mtspr   SRR1,r0
647         lwz     r0,GPR0(r1)
648         lwz     r2,GPR2(r1)
649         lwz     r1,GPR1(r1)
650         SYNC
651         rfi
652
653 crit_return:
654         mfmsr   r28             /* Disable interrupts */
655         li      r4,0
656         ori     r4,r4,MSR_EE
657         andc    r28,r28,r4
658         SYNC                    /* Some chip revs need this... */
659         mtmsr   r28
660         SYNC
661         lwz     r2,_CTR(r1)
662         lwz     r0,_LINK(r1)
663         mtctr   r2
664         mtlr    r0
665         lwz     r2,_XER(r1)
666         lwz     r0,_CCR(r1)
667         mtspr   XER,r2
668         mtcrf   0xFF,r0
669         REST_10GPRS(3, r1)
670         REST_10GPRS(13, r1)
671         REST_8GPRS(23, r1)
672         REST_GPR(31, r1)
673         lwz     r2,_NIP(r1)     /* Restore environment */
674         lwz     r0,_MSR(r1)
675         mtspr   990,r2          /* SRR2 */
676         mtspr   991,r0          /* SRR3 */
677         lwz     r0,GPR0(r1)
678         lwz     r2,GPR2(r1)
679         lwz     r1,GPR1(r1)
680         SYNC
681         rfci
682
683 /* Cache functions.
684 */
685 invalidate_icache:
686         mfspr   r0,L1CSR1
687         ori     r0,r0,0x0002
688         mtspr   L1CSR1,r0
689         isync
690         blr                             /*   entire I cache */
691
692 invalidate_dcache:
693         mfspr   r0,L1CSR0
694         ori     r0,r0,0x0002
695         msync
696         isync
697         mtspr   L1CSR0,r0
698         isync
699         blr
700
701         .globl  icache_enable
702 icache_enable:
703         mflr    r8
704         bl      invalidate_icache
705         mtlr    r8
706         isync
707         mfspr   r4,L1CSR1
708         ori     r4,r4,0x0001
709         oris    r4,r4,0x0001
710         mtspr   L1CSR1,r4
711         isync
712         blr
713
714         .globl  icache_disable
715 icache_disable:
716         mfspr   r0,L1CSR1
717         lis     r1,0xfffffffe@h
718         ori     r1,r1,0xfffffffe@l
719         and     r0,r0,r1
720         mtspr   L1CSR1,r0
721         isync
722         blr
723
724         .globl  icache_status
725 icache_status:
726         mfspr   r3,L1CSR1
727         srwi    r3, r3, 31      /* >>31 => select bit 0 */
728         blr
729
730         .globl  dcache_enable
731 dcache_enable:
732         mflr    r8
733         bl      invalidate_dcache
734         mtlr    r8
735         isync
736         mfspr   r0,L1CSR0
737         ori     r0,r0,0x0001
738         oris    r0,r0,0x0001
739         msync
740         isync
741         mtspr   L1CSR0,r0
742         isync
743         blr
744
745         .globl  dcache_disable
746 dcache_disable:
747         mfspr   r0,L1CSR0
748         lis     r1,0xfffffffe@h
749         ori     r1,r1,0xfffffffe@l
750         and     r0,r0,r1
751         msync
752         isync
753         mtspr   L1CSR0,r0
754         isync
755         blr
756
757         .globl  dcache_status
758 dcache_status:
759         mfspr   r3,L1CSR0
760         srwi    r3, r3, 31      /* >>31 => select bit 0 */
761         blr
762
763         .globl get_pir
764 get_pir:
765         mfspr   r3, PIR
766         blr
767
768         .globl get_pvr
769 get_pvr:
770         mfspr   r3, PVR
771         blr
772
773         .globl get_svr
774 get_svr:
775         mfspr   r3, SVR
776         blr
777
778         .globl wr_tcr
779 wr_tcr:
780         mtspr   TCR, r3
781         blr
782
783 /*------------------------------------------------------------------------------- */
784 /* Function:     in8 */
785 /* Description:  Input 8 bits */
786 /*------------------------------------------------------------------------------- */
787         .globl  in8
788 in8:
789         lbz     r3,0x0000(r3)
790         blr
791
792 /*------------------------------------------------------------------------------- */
793 /* Function:     out8 */
794 /* Description:  Output 8 bits */
795 /*------------------------------------------------------------------------------- */
796         .globl  out8
797 out8:
798         stb     r4,0x0000(r3)
799         blr
800
801 /*------------------------------------------------------------------------------- */
802 /* Function:     out16 */
803 /* Description:  Output 16 bits */
804 /*------------------------------------------------------------------------------- */
805         .globl  out16
806 out16:
807         sth     r4,0x0000(r3)
808         blr
809
810 /*------------------------------------------------------------------------------- */
811 /* Function:     out16r */
812 /* Description:  Byte reverse and output 16 bits */
813 /*------------------------------------------------------------------------------- */
814         .globl  out16r
815 out16r:
816         sthbrx  r4,r0,r3
817         blr
818
819 /*------------------------------------------------------------------------------- */
820 /* Function:     out32 */
821 /* Description:  Output 32 bits */
822 /*------------------------------------------------------------------------------- */
823         .globl  out32
824 out32:
825         stw     r4,0x0000(r3)
826         blr
827
828 /*------------------------------------------------------------------------------- */
829 /* Function:     out32r */
830 /* Description:  Byte reverse and output 32 bits */
831 /*------------------------------------------------------------------------------- */
832         .globl  out32r
833 out32r:
834         stwbrx  r4,r0,r3
835         blr
836
837 /*------------------------------------------------------------------------------- */
838 /* Function:     in16 */
839 /* Description:  Input 16 bits */
840 /*------------------------------------------------------------------------------- */
841         .globl  in16
842 in16:
843         lhz     r3,0x0000(r3)
844         blr
845
846 /*------------------------------------------------------------------------------- */
847 /* Function:     in16r */
848 /* Description:  Input 16 bits and byte reverse */
849 /*------------------------------------------------------------------------------- */
850         .globl  in16r
851 in16r:
852         lhbrx   r3,r0,r3
853         blr
854
855 /*------------------------------------------------------------------------------- */
856 /* Function:     in32 */
857 /* Description:  Input 32 bits */
858 /*------------------------------------------------------------------------------- */
859         .globl  in32
860 in32:
861         lwz     3,0x0000(3)
862         blr
863
864 /*------------------------------------------------------------------------------- */
865 /* Function:     in32r */
866 /* Description:  Input 32 bits and byte reverse */
867 /*------------------------------------------------------------------------------- */
868         .globl  in32r
869 in32r:
870         lwbrx   r3,r0,r3
871         blr
872
873 /*------------------------------------------------------------------------------- */
874 /* Function:     ppcDcbf */
875 /* Description:  Data Cache block flush */
876 /* Input:        r3 = effective address */
877 /* Output:       none. */
878 /*------------------------------------------------------------------------------- */
879         .globl  ppcDcbf
880 ppcDcbf:
881         dcbf    r0,r3
882         blr
883
884 /*------------------------------------------------------------------------------- */
885 /* Function:     ppcDcbi */
886 /* Description:  Data Cache block Invalidate */
887 /* Input:        r3 = effective address */
888 /* Output:       none. */
889 /*------------------------------------------------------------------------------- */
890         .globl  ppcDcbi
891 ppcDcbi:
892         dcbi    r0,r3
893         blr
894
895 /*--------------------------------------------------------------------------
896  * Function:     ppcDcbz
897  * Description:  Data Cache block zero.
898  * Input:        r3 = effective address
899  * Output:       none.
900  *-------------------------------------------------------------------------- */
901
902         .globl  ppcDcbz
903 ppcDcbz:
904         dcbz    r0,r3
905         blr
906
907 /*------------------------------------------------------------------------------- */
908 /* Function:     ppcSync */
909 /* Description:  Processor Synchronize */
910 /* Input:        none. */
911 /* Output:       none. */
912 /*------------------------------------------------------------------------------- */
913         .globl  ppcSync
914 ppcSync:
915         sync
916         blr
917
918 /*------------------------------------------------------------------------------*/
919
920 /*
921  * void relocate_code (addr_sp, gd, addr_moni)
922  *
923  * This "function" does not return, instead it continues in RAM
924  * after relocating the monitor code.
925  *
926  * r3 = dest
927  * r4 = src
928  * r5 = length in bytes
929  * r6 = cachelinesize
930  */
931         .globl  relocate_code
932 relocate_code:
933         mr      r1,  r3         /* Set new stack pointer                */
934         mr      r9,  r4         /* Save copy of Init Data pointer       */
935         mr      r10, r5         /* Save copy of Destination Address     */
936
937         mr      r3,  r5                         /* Destination Address  */
938         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
939         ori     r4, r4, CFG_MONITOR_BASE@l
940         lwz     r5,GOT(__init_end)
941         sub     r5,r5,r4
942         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
943
944         /*
945          * Fix GOT pointer:
946          *
947          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
948          *
949          * Offset:
950          */
951         sub     r15, r10, r4
952
953         /* First our own GOT */
954         add     r14, r14, r15
955         /* the the one used by the C code */
956         add     r30, r30, r15
957
958         /*
959          * Now relocate code
960          */
961
962         cmplw   cr1,r3,r4
963         addi    r0,r5,3
964         srwi.   r0,r0,2
965         beq     cr1,4f          /* In place copy is not necessary       */
966         beq     7f              /* Protect against 0 count              */
967         mtctr   r0
968         bge     cr1,2f
969
970         la      r8,-4(r4)
971         la      r7,-4(r3)
972 1:      lwzu    r0,4(r8)
973         stwu    r0,4(r7)
974         bdnz    1b
975         b       4f
976
977 2:      slwi    r0,r0,2
978         add     r8,r4,r0
979         add     r7,r3,r0
980 3:      lwzu    r0,-4(r8)
981         stwu    r0,-4(r7)
982         bdnz    3b
983
984 /*
985  * Now flush the cache: note that we must start from a cache aligned
986  * address. Otherwise we might miss one cache line.
987  */
988 4:      cmpwi   r6,0
989         add     r5,r3,r5
990         beq     7f              /* Always flush prefetch queue in any case */
991         subi    r0,r6,1
992         andc    r3,r3,r0
993         mr      r4,r3
994 5:      dcbst   0,r4
995         add     r4,r4,r6
996         cmplw   r4,r5
997         blt     5b
998         sync                    /* Wait for all dcbst to complete on bus */
999         mr      r4,r3
1000 6:      icbi    0,r4
1001         add     r4,r4,r6
1002         cmplw   r4,r5
1003         blt     6b
1004 7:      sync                    /* Wait for all icbi to complete on bus */
1005         isync
1006
1007 /*
1008  * We are done. Do not return, instead branch to second part of board
1009  * initialization, now running from RAM.
1010  */
1011
1012         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1013         mtlr    r0
1014         blr                             /* NEVER RETURNS! */
1015
1016 in_ram:
1017
1018         /*
1019          * Relocation Function, r14 point to got2+0x8000
1020          *
1021          * Adjust got2 pointers, no need to check for 0, this code
1022          * already puts a few entries in the table.
1023          */
1024         li      r0,__got2_entries@sectoff@l
1025         la      r3,GOT(_GOT2_TABLE_)
1026         lwz     r11,GOT(_GOT2_TABLE_)
1027         mtctr   r0
1028         sub     r11,r3,r11
1029         addi    r3,r3,-4
1030 1:      lwzu    r0,4(r3)
1031         add     r0,r0,r11
1032         stw     r0,0(r3)
1033         bdnz    1b
1034
1035         /*
1036          * Now adjust the fixups and the pointers to the fixups
1037          * in case we need to move ourselves again.
1038          */
1039 2:      li      r0,__fixup_entries@sectoff@l
1040         lwz     r3,GOT(_FIXUP_TABLE_)
1041         cmpwi   r0,0
1042         mtctr   r0
1043         addi    r3,r3,-4
1044         beq     4f
1045 3:      lwzu    r4,4(r3)
1046         lwzux   r0,r4,r11
1047         add     r0,r0,r11
1048         stw     r10,0(r3)
1049         stw     r0,0(r4)
1050         bdnz    3b
1051 4:
1052 clear_bss:
1053         /*
1054          * Now clear BSS segment
1055          */
1056         lwz     r3,GOT(__bss_start)
1057         lwz     r4,GOT(_end)
1058
1059         cmplw   0, r3, r4
1060         beq     6f
1061
1062         li      r0, 0
1063 5:
1064         stw     r0, 0(r3)
1065         addi    r3, r3, 4
1066         cmplw   0, r3, r4
1067         bne     5b
1068 6:
1069
1070         mr      r3, r9          /* Init Data pointer            */
1071         mr      r4, r10         /* Destination Address          */
1072         bl      board_init_r
1073
1074         /*
1075          * Copy exception vector code to low memory
1076          *
1077          * r3: dest_addr
1078          * r7: source address, r8: end address, r9: target address
1079          */
1080         .globl  trap_init
1081 trap_init:
1082         lwz     r7, GOT(_start)
1083         lwz     r8, GOT(_end_of_vectors)
1084
1085         li      r9, 0x100               /* reset vector always at 0x100 */
1086
1087         cmplw   0, r7, r8
1088         bgelr                           /* return if r7>=r8 - just in case */
1089
1090         mflr    r4                      /* save link register           */
1091 1:
1092         lwz     r0, 0(r7)
1093         stw     r0, 0(r9)
1094         addi    r7, r7, 4
1095         addi    r9, r9, 4
1096         cmplw   0, r7, r8
1097         bne     1b
1098
1099         /*
1100          * relocate `hdlr' and `int_return' entries
1101          */
1102         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1103         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
1104 2:
1105         bl      trap_reloc
1106         addi    r7, r7, 0x100           /* next exception vector        */
1107         cmplw   0, r7, r8
1108         blt     2b
1109
1110         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1111         bl      trap_reloc
1112
1113         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1114         bl      trap_reloc
1115
1116         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1117         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1118 3:
1119         bl      trap_reloc
1120         addi    r7, r7, 0x100           /* next exception vector        */
1121         cmplw   0, r7, r8
1122         blt     3b
1123
1124         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1125         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1126 4:
1127         bl      trap_reloc
1128         addi    r7, r7, 0x100           /* next exception vector        */
1129         cmplw   0, r7, r8
1130         blt     4b
1131
1132         mtlr    r4                      /* restore link register        */
1133         blr
1134
1135         /*
1136          * Function: relocate entries for one exception vector
1137          */
1138 trap_reloc:
1139         lwz     r0, 0(r7)               /* hdlr ...                     */
1140         add     r0, r0, r3              /*  ... += dest_addr            */
1141         stw     r0, 0(r7)
1142
1143         lwz     r0, 4(r7)               /* int_return ...               */
1144         add     r0, r0, r3              /*  ... += dest_addr            */
1145         stw     r0, 4(r7)
1146
1147         blr
1148
1149 #ifdef CFG_INIT_RAM_LOCK
1150 .globl unlock_ram_in_cache
1151 unlock_ram_in_cache:
1152         /* invalidate the INIT_RAM section */
1153         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1154         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1155         li      r2,512
1156         mtctr   r2
1157 1:      icbi    r0, r3
1158         dcbi    r0, r3
1159         addi    r3, r3, 32
1160         bdnz    1b
1161         sync                    /* Wait for all icbi to complete on bus */
1162         isync
1163         blr
1164 #endif