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