* Patch by Travis Sawyer, 09 Feb 2004:
[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,0x3000
366 #else
367         li      r0,0x1000
368 #endif
369         mtspr   HID1,r0
370         isync
371
372         /* Enable Branch Prediction */
373 #if defined(CONFIG_BTB)
374         li      r0,0x201                /* BBFI = 1, BPEN = 1 */
375         mtspr   BUCSR,r0
376         isync
377 #endif
378
379 #if defined(CFG_INIT_DBCR)
380         lis     r1,0xffff
381         ori     r1,r1,0xffff
382         mtspr   dbsr,r1                 /* Clear all status bits */
383         lis     r0,CFG_INIT_DBCR@h      /* DBCR0[IDM] must be set */
384         ori     r0,r0,CFG_INIT_DBCR@l
385         mtspr   dbcr0,r0
386         isync
387 #endif
388
389 /* L1 DCache is used for initial RAM */
390         mfspr   r2, L1CSR0
391         ori     r2, r2, 0x0003
392         oris    r2, r2, 0x0001
393         msync
394         isync
395         mtspr   L1CSR0, r2      /* enable/invalidate L1 Dcache */
396         isync
397
398         /* Allocate Initial RAM in data cache.
399          */
400         lis     r3, CFG_INIT_RAM_ADDR@h
401         ori     r3, r3, CFG_INIT_RAM_ADDR@l
402         li      r2, 512 /* 512*32=16K */
403         mtctr   r2
404         li      r0, 0
405 1:
406         dcbz    r0, r3
407         dcbtls  0,r0, r3
408         addi    r3, r3, 32
409         bdnz    1b
410
411 #ifndef CFG_RAMBOOT
412         /* Calculate absolute address in FLASH and jump there           */
413         /*--------------------------------------------------------------*/
414         lis     r3, CFG_MONITOR_BASE@h
415         ori     r3, r3, CFG_MONITOR_BASE@l
416         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
417         mtlr    r3
418         blr
419
420 in_flash:
421 #endif  /* CFG_RAMBOOT */
422
423         /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
424         lis     r1,CFG_INIT_RAM_ADDR@h
425         ori     r1,r1,CFG_INIT_SP_OFFSET@l
426
427         li      r0,0
428         stwu    r0,-4(r1)
429         stwu    r0,-4(r1)               /* Terminate call chain */
430
431         stwu    r1,-8(r1)               /* Save back chain and move SP */
432         lis     r0,RESET_VECTOR@h       /* Address of reset vector */
433         ori     r0,r0, RESET_VECTOR@l
434         stwu    r1,-8(r1)               /* Save back chain and move SP */
435         stw     r0,+12(r1)              /* Save return addr (underflow vect) */
436
437         GET_GOT
438         bl      cpu_init_f
439         bl      icache_enable
440         bl      board_init_f
441         sync
442
443
444 /* --FIXME-- machine check with MCSRRn and rfmci */
445
446         .globl  _start_of_vectors
447 _start_of_vectors:
448 #if 0
449 /* Critical input. */
450         CRIT_EXCEPTION(0x0100, CritcalInput, CritcalInputException)
451 #endif
452 /* Machine check --FIXME-- Should be MACH_EXCEPTION */
453         CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
454
455 /* Data Storage exception. */
456         STD_EXCEPTION(0x0300, DataStorage, UnknownException)
457
458 /* Instruction Storage exception. */
459         STD_EXCEPTION(0x0400, InstStorage, UnknownException)
460
461 /* External Interrupt exception. */
462         STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
463
464 /* Alignment exception. */
465         . = 0x0600
466 Alignment:
467         EXCEPTION_PROLOG
468         mfspr   r4,DAR
469         stw     r4,_DAR(r21)
470         mfspr   r5,DSISR
471         stw     r5,_DSISR(r21)
472         addi    r3,r1,STACK_FRAME_OVERHEAD
473         li      r20,MSR_KERNEL
474         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
475         lwz     r6,GOT(transfer_to_handler)
476         mtlr    r6
477         blrl
478 .L_Alignment:
479         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
480         .long   int_return - _start + EXC_OFF_SYS_RESET
481
482 /* Program check exception */
483         . = 0x0700
484 ProgramCheck:
485         EXCEPTION_PROLOG
486         addi    r3,r1,STACK_FRAME_OVERHEAD
487         li      r20,MSR_KERNEL
488         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
489         lwz     r6,GOT(transfer_to_handler)
490         mtlr    r6
491         blrl
492 .L_ProgramCheck:
493         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
494         .long   int_return - _start + EXC_OFF_SYS_RESET
495
496         /* No FPU on MPC85xx.  This exception is not supposed to happen.
497         */
498         STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
499         STD_EXCEPTION(0x0900, Decrementer, timer_interrupt)
500         STD_EXCEPTION(0x0a00, Trap_0a, UnknownException)
501         STD_EXCEPTION(0x0b00, Trap_0b, UnknownException)
502
503         . = 0x0c00
504 /*
505  * r0 - SYSCALL number
506  * r3-... arguments
507  */
508 SystemCall:
509         addis   r11,r0,0                /* get functions table addr */
510         ori     r11,r11,0               /* Note: this code is patched in trap_init */
511         addis   r12,r0,0                /* get number of functions */
512         ori     r12,r12,0
513
514         cmplw   0, r0, r12
515         bge     1f
516
517         rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
518         add     r11,r11,r0
519         lwz     r11,0(r11)
520
521         li      r20,0xd00-4             /* Get stack pointer */
522         lwz     r12,0(r20)
523         subi    r12,r12,12              /* Adjust stack pointer */
524         li      r0,0xc00+_end_back-SystemCall
525         cmplw   0, r0, r12              /* Check stack overflow */
526         bgt     1f
527         stw     r12,0(r20)
528
529         mflr    r0
530         stw     r0,0(r12)
531         mfspr   r0,SRR0
532         stw     r0,4(r12)
533         mfspr   r0,SRR1
534         stw     r0,8(r12)
535
536         li      r12,0xc00+_back-SystemCall
537         mtlr    r12
538         mtspr   SRR0,r11
539
540 1:      SYNC
541         rfi
542 _back:
543
544         mfmsr   r11                     /* Disable interrupts */
545         li      r12,0
546         ori     r12,r12,MSR_EE
547         andc    r11,r11,r12
548         SYNC                            /* Some chip revs need this... */
549         mtmsr   r11
550         SYNC
551
552         li      r12,0xd00-4             /* restore regs */
553         lwz     r12,0(r12)
554
555         lwz     r11,0(r12)
556         mtlr    r11
557         lwz     r11,4(r12)
558         mtspr   SRR0,r11
559         lwz     r11,8(r12)
560         mtspr   SRR1,r11
561
562         addi    r12,r12,12              /* Adjust stack pointer */
563         li      r20,0xd00-4
564         stw     r12,0(r20)
565
566         SYNC
567         rfi
568 _end_back:
569
570         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
571
572         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
573         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
574
575         STD_EXCEPTION(0x1000, PIT, PITException)
576
577         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
578         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
579         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
580         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
581
582         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
583         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
584         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
585         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
586         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
587         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
588         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
589
590         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
591         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
592         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
593         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
594
595         CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
596
597         .globl  _end_of_vectors
598 _end_of_vectors:
599
600
601         . = 0x2100
602
603 /*
604  * This code finishes saving the registers to the exception frame
605  * and jumps to the appropriate handler for the exception.
606  * Register r21 is pointer into trap frame, r1 has new stack pointer.
607  */
608         .globl  transfer_to_handler
609 transfer_to_handler:
610         stw     r22,_NIP(r21)
611         lis     r22,MSR_POW@h
612         andc    r23,r23,r22
613         stw     r23,_MSR(r21)
614         SAVE_GPR(7, r21)
615         SAVE_4GPRS(8, r21)
616         SAVE_8GPRS(12, r21)
617         SAVE_8GPRS(24, r21)
618
619         mflr    r23
620         andi.   r24,r23,0x3f00          /* get vector offset */
621         stw     r24,TRAP(r21)
622         li      r22,0
623         stw     r22,RESULT(r21)
624         mtspr   SPRG2,r22               /* r1 is now kernel sp */
625
626         lwz     r24,0(r23)              /* virtual address of handler */
627         lwz     r23,4(r23)              /* where to go when done */
628         mtspr   SRR0,r24
629         mtspr   SRR1,r20
630         mtlr    r23
631         SYNC
632         rfi                             /* jump to handler, enable MMU */
633
634 int_return:
635         mfmsr   r28             /* Disable interrupts */
636         li      r4,0
637         ori     r4,r4,MSR_EE
638         andc    r28,r28,r4
639         SYNC                    /* Some chip revs need this... */
640         mtmsr   r28
641         SYNC
642         lwz     r2,_CTR(r1)
643         lwz     r0,_LINK(r1)
644         mtctr   r2
645         mtlr    r0
646         lwz     r2,_XER(r1)
647         lwz     r0,_CCR(r1)
648         mtspr   XER,r2
649         mtcrf   0xFF,r0
650         REST_10GPRS(3, r1)
651         REST_10GPRS(13, r1)
652         REST_8GPRS(23, r1)
653         REST_GPR(31, r1)
654         lwz     r2,_NIP(r1)     /* Restore environment */
655         lwz     r0,_MSR(r1)
656         mtspr   SRR0,r2
657         mtspr   SRR1,r0
658         lwz     r0,GPR0(r1)
659         lwz     r2,GPR2(r1)
660         lwz     r1,GPR1(r1)
661         SYNC
662         rfi
663
664 crit_return:
665         mfmsr   r28             /* Disable interrupts */
666         li      r4,0
667         ori     r4,r4,MSR_EE
668         andc    r28,r28,r4
669         SYNC                    /* Some chip revs need this... */
670         mtmsr   r28
671         SYNC
672         lwz     r2,_CTR(r1)
673         lwz     r0,_LINK(r1)
674         mtctr   r2
675         mtlr    r0
676         lwz     r2,_XER(r1)
677         lwz     r0,_CCR(r1)
678         mtspr   XER,r2
679         mtcrf   0xFF,r0
680         REST_10GPRS(3, r1)
681         REST_10GPRS(13, r1)
682         REST_8GPRS(23, r1)
683         REST_GPR(31, r1)
684         lwz     r2,_NIP(r1)     /* Restore environment */
685         lwz     r0,_MSR(r1)
686         mtspr   990,r2          /* SRR2 */
687         mtspr   991,r0          /* SRR3 */
688         lwz     r0,GPR0(r1)
689         lwz     r2,GPR2(r1)
690         lwz     r1,GPR1(r1)
691         SYNC
692         rfci
693
694 /* Cache functions.
695 */
696 invalidate_icache:
697         mfspr   r0,L1CSR1
698         ori     r0,r0,0x0002
699         mtspr   L1CSR1,r0
700         isync
701         blr                             /*   entire I cache */
702
703 invalidate_dcache:
704         mfspr   r0,L1CSR0
705         ori     r0,r0,0x0002
706         msync
707         isync
708         mtspr   L1CSR0,r0
709         isync
710         blr
711
712         .globl  icache_enable
713 icache_enable:
714         mflr    r8
715         bl      invalidate_icache
716         mtlr    r8
717         isync
718         mfspr   r4,L1CSR1
719         ori     r4,r4,0x0001
720         oris    r4,r4,0x0001
721         mtspr   L1CSR1,r4
722         isync
723         blr
724
725         .globl  icache_disable
726 icache_disable:
727         mfspr   r0,L1CSR1
728         lis     r1,0xfffffffe@h
729         ori     r1,r1,0xfffffffe@l
730         and     r0,r0,r1
731         mtspr   L1CSR1,r0
732         isync
733         blr
734
735         .globl  icache_status
736 icache_status:
737         mfspr   r3,L1CSR1
738         srwi    r3, r3, 31      /* >>31 => select bit 0 */
739         blr
740
741         .globl  dcache_enable
742 dcache_enable:
743         mflr    r8
744         bl      invalidate_dcache
745         mtlr    r8
746         isync
747         mfspr   r0,L1CSR0
748         ori     r0,r0,0x0001
749         oris    r0,r0,0x0001
750         msync
751         isync
752         mtspr   L1CSR0,r0
753         isync
754         blr
755
756         .globl  dcache_disable
757 dcache_disable:
758         mfspr   r0,L1CSR0
759         lis     r1,0xfffffffe@h
760         ori     r1,r1,0xfffffffe@l
761         and     r0,r0,r1
762         msync
763         isync
764         mtspr   L1CSR0,r0
765         isync
766         blr
767
768         .globl  dcache_status
769 dcache_status:
770         mfspr   r3,L1CSR0
771         srwi    r3, r3, 31      /* >>31 => select bit 0 */
772         blr
773
774         .globl get_pir
775 get_pir:
776         mfspr   r3, PIR
777         blr
778
779         .globl get_pvr
780 get_pvr:
781         mfspr   r3, PVR
782         blr
783
784         .globl wr_tcr
785 wr_tcr:
786         mtspr   TCR, r3
787         blr
788
789 /*------------------------------------------------------------------------------- */
790 /* Function:     in8 */
791 /* Description:  Input 8 bits */
792 /*------------------------------------------------------------------------------- */
793         .globl  in8
794 in8:
795         lbz     r3,0x0000(r3)
796         blr
797
798 /*------------------------------------------------------------------------------- */
799 /* Function:     out8 */
800 /* Description:  Output 8 bits */
801 /*------------------------------------------------------------------------------- */
802         .globl  out8
803 out8:
804         stb     r4,0x0000(r3)
805         blr
806
807 /*------------------------------------------------------------------------------- */
808 /* Function:     out16 */
809 /* Description:  Output 16 bits */
810 /*------------------------------------------------------------------------------- */
811         .globl  out16
812 out16:
813         sth     r4,0x0000(r3)
814         blr
815
816 /*------------------------------------------------------------------------------- */
817 /* Function:     out16r */
818 /* Description:  Byte reverse and output 16 bits */
819 /*------------------------------------------------------------------------------- */
820         .globl  out16r
821 out16r:
822         sthbrx  r4,r0,r3
823         blr
824
825 /*------------------------------------------------------------------------------- */
826 /* Function:     out32 */
827 /* Description:  Output 32 bits */
828 /*------------------------------------------------------------------------------- */
829         .globl  out32
830 out32:
831         stw     r4,0x0000(r3)
832         blr
833
834 /*------------------------------------------------------------------------------- */
835 /* Function:     out32r */
836 /* Description:  Byte reverse and output 32 bits */
837 /*------------------------------------------------------------------------------- */
838         .globl  out32r
839 out32r:
840         stwbrx  r4,r0,r3
841         blr
842
843 /*------------------------------------------------------------------------------- */
844 /* Function:     in16 */
845 /* Description:  Input 16 bits */
846 /*------------------------------------------------------------------------------- */
847         .globl  in16
848 in16:
849         lhz     r3,0x0000(r3)
850         blr
851
852 /*------------------------------------------------------------------------------- */
853 /* Function:     in16r */
854 /* Description:  Input 16 bits and byte reverse */
855 /*------------------------------------------------------------------------------- */
856         .globl  in16r
857 in16r:
858         lhbrx   r3,r0,r3
859         blr
860
861 /*------------------------------------------------------------------------------- */
862 /* Function:     in32 */
863 /* Description:  Input 32 bits */
864 /*------------------------------------------------------------------------------- */
865         .globl  in32
866 in32:
867         lwz     3,0x0000(3)
868         blr
869
870 /*------------------------------------------------------------------------------- */
871 /* Function:     in32r */
872 /* Description:  Input 32 bits and byte reverse */
873 /*------------------------------------------------------------------------------- */
874         .globl  in32r
875 in32r:
876         lwbrx   r3,r0,r3
877         blr
878
879 /*------------------------------------------------------------------------------- */
880 /* Function:     ppcDcbf */
881 /* Description:  Data Cache block flush */
882 /* Input:        r3 = effective address */
883 /* Output:       none. */
884 /*------------------------------------------------------------------------------- */
885         .globl  ppcDcbf
886 ppcDcbf:
887         dcbf    r0,r3
888         blr
889
890 /*------------------------------------------------------------------------------- */
891 /* Function:     ppcDcbi */
892 /* Description:  Data Cache block Invalidate */
893 /* Input:        r3 = effective address */
894 /* Output:       none. */
895 /*------------------------------------------------------------------------------- */
896         .globl  ppcDcbi
897 ppcDcbi:
898         dcbi    r0,r3
899         blr
900
901 /*------------------------------------------------------------------------------- */
902 /* Function:     ppcSync */
903 /* Description:  Processor Synchronize */
904 /* Input:        none. */
905 /* Output:       none. */
906 /*------------------------------------------------------------------------------- */
907         .globl  ppcSync
908 ppcSync:
909         sync
910         blr
911
912 /*------------------------------------------------------------------------------*/
913
914 /*
915  * void relocate_code (addr_sp, gd, addr_moni)
916  *
917  * This "function" does not return, instead it continues in RAM
918  * after relocating the monitor code.
919  *
920  * r3 = dest
921  * r4 = src
922  * r5 = length in bytes
923  * r6 = cachelinesize
924  */
925         .globl  relocate_code
926 relocate_code:
927         mr      r1,  r3         /* Set new stack pointer                */
928         mr      r9,  r4         /* Save copy of Init Data pointer       */
929         mr      r10, r5         /* Save copy of Destination Address     */
930
931         mr      r3,  r5                         /* Destination Address  */
932         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
933         ori     r4, r4, CFG_MONITOR_BASE@l
934         lwz     r5,GOT(__init_end)
935         sub     r5,r5,r4
936         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
937
938         /*
939          * Fix GOT pointer:
940          *
941          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
942          *
943          * Offset:
944          */
945         sub     r15, r10, r4
946
947         /* First our own GOT */
948         add     r14, r14, r15
949         /* the the one used by the C code */
950         add     r30, r30, r15
951
952         /*
953          * Now relocate code
954          */
955
956         cmplw   cr1,r3,r4
957         addi    r0,r5,3
958         srwi.   r0,r0,2
959         beq     cr1,4f          /* In place copy is not necessary       */
960         beq     7f              /* Protect against 0 count              */
961         mtctr   r0
962         bge     cr1,2f
963
964         la      r8,-4(r4)
965         la      r7,-4(r3)
966 1:      lwzu    r0,4(r8)
967         stwu    r0,4(r7)
968         bdnz    1b
969         b       4f
970
971 2:      slwi    r0,r0,2
972         add     r8,r4,r0
973         add     r7,r3,r0
974 3:      lwzu    r0,-4(r8)
975         stwu    r0,-4(r7)
976         bdnz    3b
977
978 /*
979  * Now flush the cache: note that we must start from a cache aligned
980  * address. Otherwise we might miss one cache line.
981  */
982 4:      cmpwi   r6,0
983         add     r5,r3,r5
984         beq     7f              /* Always flush prefetch queue in any case */
985         subi    r0,r6,1
986         andc    r3,r3,r0
987         mr      r4,r3
988 5:      dcbst   0,r4
989         add     r4,r4,r6
990         cmplw   r4,r5
991         blt     5b
992         sync                    /* Wait for all dcbst to complete on bus */
993         mr      r4,r3
994 6:      icbi    0,r4
995         add     r4,r4,r6
996         cmplw   r4,r5
997         blt     6b
998 7:      sync                    /* Wait for all icbi to complete on bus */
999         isync
1000
1001 /*
1002  * We are done. Do not return, instead branch to second part of board
1003  * initialization, now running from RAM.
1004  */
1005
1006         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1007         mtlr    r0
1008         blr                             /* NEVER RETURNS! */
1009
1010 in_ram:
1011
1012         /*
1013          * Relocation Function, r14 point to got2+0x8000
1014          *
1015          * Adjust got2 pointers, no need to check for 0, this code
1016          * already puts a few entries in the table.
1017          */
1018         li      r0,__got2_entries@sectoff@l
1019         la      r3,GOT(_GOT2_TABLE_)
1020         lwz     r11,GOT(_GOT2_TABLE_)
1021         mtctr   r0
1022         sub     r11,r3,r11
1023         addi    r3,r3,-4
1024 1:      lwzu    r0,4(r3)
1025         add     r0,r0,r11
1026         stw     r0,0(r3)
1027         bdnz    1b
1028
1029         /*
1030          * Now adjust the fixups and the pointers to the fixups
1031          * in case we need to move ourselves again.
1032          */
1033 2:      li      r0,__fixup_entries@sectoff@l
1034         lwz     r3,GOT(_FIXUP_TABLE_)
1035         cmpwi   r0,0
1036         mtctr   r0
1037         addi    r3,r3,-4
1038         beq     4f
1039 3:      lwzu    r4,4(r3)
1040         lwzux   r0,r4,r11
1041         add     r0,r0,r11
1042         stw     r10,0(r3)
1043         stw     r0,0(r4)
1044         bdnz    3b
1045 4:
1046 clear_bss:
1047         /*
1048          * Now clear BSS segment
1049          */
1050         lwz     r3,GOT(__bss_start)
1051         lwz     r4,GOT(_end)
1052
1053         cmplw   0, r3, r4
1054         beq     6f
1055
1056         li      r0, 0
1057 5:
1058         stw     r0, 0(r3)
1059         addi    r3, r3, 4
1060         cmplw   0, r3, r4
1061         bne     5b
1062 6:
1063
1064         mr      r3, r9          /* Init Data pointer            */
1065         mr      r4, r10         /* Destination Address          */
1066         bl      board_init_r
1067
1068         /*
1069          * Copy exception vector code to low memory
1070          *
1071          * r3: dest_addr
1072          * r7: source address, r8: end address, r9: target address
1073          */
1074         .globl  trap_init
1075 trap_init:
1076         lwz     r7, GOT(_start)
1077         lwz     r8, GOT(_end_of_vectors)
1078
1079         li      r9, 0x100               /* reset vector always at 0x100 */
1080
1081         cmplw   0, r7, r8
1082         bgelr                           /* return if r7>=r8 - just in case */
1083
1084         mflr    r4                      /* save link register           */
1085 1:
1086         lwz     r0, 0(r7)
1087         stw     r0, 0(r9)
1088         addi    r7, r7, 4
1089         addi    r9, r9, 4
1090         cmplw   0, r7, r8
1091         bne     1b
1092
1093         /*
1094          * relocate `hdlr' and `int_return' entries
1095          */
1096         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1097         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
1098 2:
1099         bl      trap_reloc
1100         addi    r7, r7, 0x100           /* next exception vector        */
1101         cmplw   0, r7, r8
1102         blt     2b
1103
1104         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1105         bl      trap_reloc
1106
1107         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1108         bl      trap_reloc
1109
1110         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1111         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1112 3:
1113         bl      trap_reloc
1114         addi    r7, r7, 0x100           /* next exception vector        */
1115         cmplw   0, r7, r8
1116         blt     3b
1117
1118         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1119         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1120 4:
1121         bl      trap_reloc
1122         addi    r7, r7, 0x100           /* next exception vector        */
1123         cmplw   0, r7, r8
1124         blt     4b
1125
1126         mtlr    r4                      /* restore link register        */
1127         blr
1128
1129         /*
1130          * Function: relocate entries for one exception vector
1131          */
1132 trap_reloc:
1133         lwz     r0, 0(r7)               /* hdlr ...                     */
1134         add     r0, r0, r3              /*  ... += dest_addr            */
1135         stw     r0, 0(r7)
1136
1137         lwz     r0, 4(r7)               /* int_return ...               */
1138         add     r0, r0, r3              /*  ... += dest_addr            */
1139         stw     r0, 4(r7)
1140
1141         blr
1142
1143 #ifdef CFG_INIT_RAM_LOCK
1144 .globl unlock_ram_in_cache
1145 unlock_ram_in_cache:
1146         /* invalidate the INIT_RAM section */
1147         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1148         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1149         li      r2,512
1150         mtctr   r2
1151 1:      icbi    r0, r3
1152         dcbi    r0, r3
1153         addi    r3, r3, 32
1154         bdnz    1b
1155         sync                    /* Wait for all icbi to complete on bus */
1156         isync
1157         blr
1158 #endif