Merge with rsync://git-user@source.denx.net/git/u-boot.git
[oweals/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 #if defined(CONFIG_ENABLE_36BIT_PHYS)
178         mtspr   MAS7,r0
179 #endif
180         isync
181
182         /* Setup interrupt vectors */
183         lis     r1,TEXT_BASE@h
184         mtspr IVPR, r1
185
186         li      r1,0x0100
187         mtspr   IVOR0,r1        /* 0: Critical input */
188         li      r1,0x0200
189         mtspr   IVOR1,r1        /* 1: Machine check */
190         li      r1,0x0300
191         mtspr   IVOR2,r1        /* 2: Data storage */
192         li      r1,0x0400
193         mtspr   IVOR3,r1        /* 3: Instruction storage */
194         li      r1,0x0500
195         mtspr   IVOR4,r1        /* 4: External interrupt */
196         li      r1,0x0600
197         mtspr   IVOR5,r1        /* 5: Alignment */
198         li      r1,0x0700
199         mtspr   IVOR6,r1        /* 6: Program check */
200         li      r1,0x0800
201         mtspr   IVOR7,r1        /* 7: floating point unavailable */
202         li      r1,0x0900
203         mtspr   IVOR8,r1        /* 8: System call */
204         /* 9: Auxiliary processor unavailable(unsupported) */
205         li      r1,0x0a00
206         mtspr   IVOR10,r1       /* 10: Decrementer */
207         li      r1,0x0b00
208         mtspr   IVOR11,r1       /* 11: Interval timer */
209         li      r1,0x0c00
210         mtspr   IVOR12,r1       /* 11: Watchdog timer */
211         li      r10,0x0d00
212         mtspr   IVOR13,r1       /* 13: Data TLB error */
213         li      r1,0x0e00
214         mtspr   IVOR14,r1       /* 14: Instruction TLB error */
215         li      r1,0x0f00
216         mtspr   IVOR15,r1       /* 15: Debug */
217
218         /*
219          * Invalidate MMU L1/L2
220          *
221          * Note: There is a fixup earlier for Errata CPU4 on
222          * Rev 1 parts that must precede this MMU invalidation.
223          */
224         li      r2, 0x001e
225         mtspr   MMUCSR0, r2
226         isync
227
228         /*
229          * Invalidate all TLB0 entries.
230          */
231         li      r3,4
232         li      r4,0
233         tlbivax r4,r3
234         /*
235          * To avoid REV1 Errata CPU6 issues, make sure
236          * the instruction following tlbivax is not a store.
237          */
238
239         /*
240          * After reset, CCSRBAR is located at CFG_CCSRBAR_DEFAULT, i.e.
241          * 0xff700000-0xff800000. We need add a TLB1 entry for this 1MB
242          * region before we can access any CCSR registers such as L2
243          * registers, Local Access Registers,etc. We will also re-allocate
244          * CFG_CCSRBAR_DEFAULT to CFG_CCSRBAR immediately after TLB1 setup.
245          *
246          * Please refer to board-specif directory for TLB1 entry configuration.
247          * (e.g. board/<yourboard>/init.S)
248          *
249          */
250         bl      tlb1_entry
251         mr      r5,r0
252         li      r1,0x0020       /* max 16 TLB1 plus some TLB0 entries */
253         mtctr   r1
254         lwzu    r4,0(r5)        /* how many TLB1 entries we actually use */
255
256 0:      cmpwi   r4,0
257         beq     1f
258         lwzu    r0,4(r5)
259         lwzu    r1,4(r5)
260         lwzu    r2,4(r5)
261         lwzu    r3,4(r5)
262         mtspr   MAS0,r0
263         mtspr   MAS1,r1
264         mtspr   MAS2,r2
265         mtspr   MAS3,r3
266         isync
267         msync
268         tlbwe
269         isync
270         addi    r4,r4,-1
271         bdnz    0b
272
273 1:
274 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
275         /* Special sequence needed to update CCSRBAR itself */
276         lis     r4, CFG_CCSRBAR_DEFAULT@h
277         ori     r4, r4, CFG_CCSRBAR_DEFAULT@l
278
279         lis     r5, CFG_CCSRBAR@h
280         ori     r5, r5, CFG_CCSRBAR@l
281         srwi    r6,r5,12
282         stw     r6, 0(r4)
283         isync
284
285         lis     r5, 0xffff
286         ori     r5,r5,0xf000
287         lwz     r5, 0(r5)
288         isync
289
290         lis     r3, CFG_CCSRBAR@h
291         lwz     r5, CFG_CCSRBAR@l(r3)
292         isync
293 #endif
294
295
296         /* set up local access windows, defined at board/<boardname>/init.S */
297         lis     r7,CFG_CCSRBAR@h
298         ori     r7,r7,CFG_CCSRBAR@l
299
300         bl      law_entry
301         mr      r6,r0
302         li      r1,0x0007       /* 8 LAWs, but reserve one for boot-over-rio-or-pci */
303         mtctr   r1
304         lwzu    r5,0(r6)        /* how many windows we actually use */
305
306         li      r2,0x0c28       /* the first pair is reserved for boot-over-rio-or-pci */
307         li      r1,0x0c30
308
309 0:      cmpwi   r5,0
310         beq     1f
311         lwzu    r4,4(r6)
312         lwzu    r3,4(r6)
313         stwx    r4,r7,r2
314         stwx    r3,r7,r1
315         addi    r5,r5,-1
316         addi    r2,r2,0x0020
317         addi    r1,r1,0x0020
318         bdnz    0b
319
320         /* Jump out the last 4K page and continue to 'normal' start */
321 1:      bl      3f
322         b       _start
323
324 3:      li      r0,0
325         mtspr   SRR1,r0         /* Keep things disabled for now */
326         mflr    r1
327         mtspr   SRR0,r1
328         rfi
329
330 /*
331  * r3 - 1st arg to board_init(): IMMP pointer
332  * r4 - 2nd arg to board_init(): boot flag
333  */
334         .text
335         .long   0x27051956              /* U-BOOT Magic Number                  */
336         .globl  version_string
337 version_string:
338         .ascii U_BOOT_VERSION
339         .ascii " (", __DATE__, " - ", __TIME__, ")"
340         .ascii CONFIG_IDENT_STRING, "\0"
341
342         . = EXC_OFF_SYS_RESET
343         .globl  _start
344 _start:
345         /* Clear and set up some registers. */
346         li      r0,0x0000
347         lis     r1,0xffff
348         mtspr   DEC,r0                  /* prevent dec exceptions */
349         mttbl   r0                      /* prevent fit & wdt exceptions */
350         mttbu   r0
351         mtspr   TSR,r1                  /* clear all timer exception status */
352         mtspr   TCR,r0                  /* disable all */
353         mtspr   ESR,r0                  /* clear exception syndrome register */
354         mtspr   MCSR,r0                 /* machine check syndrome register */
355         mtxer   r0                      /* clear integer exception register */
356         lis     r1,0x0002               /* set CE bit (Critical Exceptions) */
357         ori     r1,r1,0x1200            /* set ME/DE bit */
358         mtmsr   r1                      /* change MSR */
359         isync
360
361         /* Enable Time Base and Select Time Base Clock */
362         lis     r0,HID0_EMCP@h          /* Enable machine check */
363         ori     r0,r0,0x4000            /* time base is processor clock */
364 #if defined(CONFIG_ENABLE_36BIT_PHYS)
365         ori     r0,r0,0x0080            /* enable MAS7 updates */
366 #endif
367         mtspr   HID0,r0
368
369 #if defined(CONFIG_ADDR_STREAMING)
370         li      r0,0x3000
371 #else
372         li      r0,0x1000
373 #endif
374         mtspr   HID1,r0
375
376         /* Enable Branch Prediction */
377 #if defined(CONFIG_BTB)
378         li      r0,0x201                /* BBFI = 1, BPEN = 1 */
379         mtspr   BUCSR,r0
380 #endif
381
382 #if defined(CFG_INIT_DBCR)
383         lis     r1,0xffff
384         ori     r1,r1,0xffff
385         mtspr   DBSR,r1                 /* Clear all status bits */
386         lis     r0,CFG_INIT_DBCR@h      /* DBCR0[IDM] must be set */
387         ori     r0,r0,CFG_INIT_DBCR@l
388         mtspr   DBCR0,r0
389 #endif
390
391 /* L1 DCache is used for initial RAM */
392         mfspr   r2, L1CSR0
393         ori     r2, r2, 0x0003
394         oris    r2, r2, 0x0001
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         isync
442
443 /* --FIXME-- machine check with MCSRRn and rfmci */
444
445         .globl  _start_of_vectors
446 _start_of_vectors:
447 #if 0
448 /* Critical input. */
449         CRIT_EXCEPTION(0x0100, CritcalInput, CritcalInputException)
450 #endif
451 /* Machine check --FIXME-- Should be MACH_EXCEPTION */
452         CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
453
454 /* Data Storage exception. */
455         STD_EXCEPTION(0x0300, DataStorage, UnknownException)
456
457 /* Instruction Storage exception. */
458         STD_EXCEPTION(0x0400, InstStorage, UnknownException)
459
460 /* External Interrupt exception. */
461         STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
462
463 /* Alignment exception. */
464         . = 0x0600
465 Alignment:
466         EXCEPTION_PROLOG
467         mfspr   r4,DAR
468         stw     r4,_DAR(r21)
469         mfspr   r5,DSISR
470         stw     r5,_DSISR(r21)
471         addi    r3,r1,STACK_FRAME_OVERHEAD
472         li      r20,MSR_KERNEL
473         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
474         lwz     r6,GOT(transfer_to_handler)
475         mtlr    r6
476         blrl
477 .L_Alignment:
478         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
479         .long   int_return - _start + EXC_OFF_SYS_RESET
480
481 /* Program check exception */
482         . = 0x0700
483 ProgramCheck:
484         EXCEPTION_PROLOG
485         addi    r3,r1,STACK_FRAME_OVERHEAD
486         li      r20,MSR_KERNEL
487         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
488         lwz     r6,GOT(transfer_to_handler)
489         mtlr    r6
490         blrl
491 .L_ProgramCheck:
492         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
493         .long   int_return - _start + EXC_OFF_SYS_RESET
494
495         /* No FPU on MPC85xx.  This exception is not supposed to happen.
496         */
497         STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
498
499         . = 0x0900
500 /*
501  * r0 - SYSCALL number
502  * r3-... arguments
503  */
504 SystemCall:
505         addis   r11,r0,0                /* get functions table addr */
506         ori     r11,r11,0               /* Note: this code is patched in trap_init */
507         addis   r12,r0,0                /* get number of functions */
508         ori     r12,r12,0
509
510         cmplw   0, r0, r12
511         bge     1f
512
513         rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
514         add     r11,r11,r0
515         lwz     r11,0(r11)
516
517         li      r20,0xd00-4             /* Get stack pointer */
518         lwz     r12,0(r20)
519         subi    r12,r12,12              /* Adjust stack pointer */
520         li      r0,0xc00+_end_back-SystemCall
521         cmplw   0, r0, r12              /* Check stack overflow */
522         bgt     1f
523         stw     r12,0(r20)
524
525         mflr    r0
526         stw     r0,0(r12)
527         mfspr   r0,SRR0
528         stw     r0,4(r12)
529         mfspr   r0,SRR1
530         stw     r0,8(r12)
531
532         li      r12,0xc00+_back-SystemCall
533         mtlr    r12
534         mtspr   SRR0,r11
535
536 1:      SYNC
537         rfi
538 _back:
539
540         mfmsr   r11                     /* Disable interrupts */
541         li      r12,0
542         ori     r12,r12,MSR_EE
543         andc    r11,r11,r12
544         SYNC                            /* Some chip revs need this... */
545         mtmsr   r11
546         SYNC
547
548         li      r12,0xd00-4             /* restore regs */
549         lwz     r12,0(r12)
550
551         lwz     r11,0(r12)
552         mtlr    r11
553         lwz     r11,4(r12)
554         mtspr   SRR0,r11
555         lwz     r11,8(r12)
556         mtspr   SRR1,r11
557
558         addi    r12,r12,12              /* Adjust stack pointer */
559         li      r20,0xd00-4
560         stw     r12,0(r20)
561
562         SYNC
563         rfi
564 _end_back:
565
566         STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
567         STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
568         STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
569
570         STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
571         STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
572
573         CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
574
575         .globl  _end_of_vectors
576 _end_of_vectors:
577
578
579         . = 0x2100
580
581 /*
582  * This code finishes saving the registers to the exception frame
583  * and jumps to the appropriate handler for the exception.
584  * Register r21 is pointer into trap frame, r1 has new stack pointer.
585  */
586         .globl  transfer_to_handler
587 transfer_to_handler:
588         stw     r22,_NIP(r21)
589         lis     r22,MSR_POW@h
590         andc    r23,r23,r22
591         stw     r23,_MSR(r21)
592         SAVE_GPR(7, r21)
593         SAVE_4GPRS(8, r21)
594         SAVE_8GPRS(12, r21)
595         SAVE_8GPRS(24, r21)
596
597         mflr    r23
598         andi.   r24,r23,0x3f00          /* get vector offset */
599         stw     r24,TRAP(r21)
600         li      r22,0
601         stw     r22,RESULT(r21)
602         mtspr   SPRG2,r22               /* r1 is now kernel sp */
603
604         lwz     r24,0(r23)              /* virtual address of handler */
605         lwz     r23,4(r23)              /* where to go when done */
606         mtspr   SRR0,r24
607         mtspr   SRR1,r20
608         mtlr    r23
609         SYNC
610         rfi                             /* jump to handler, enable MMU */
611
612 int_return:
613         mfmsr   r28             /* Disable interrupts */
614         li      r4,0
615         ori     r4,r4,MSR_EE
616         andc    r28,r28,r4
617         SYNC                    /* Some chip revs need this... */
618         mtmsr   r28
619         SYNC
620         lwz     r2,_CTR(r1)
621         lwz     r0,_LINK(r1)
622         mtctr   r2
623         mtlr    r0
624         lwz     r2,_XER(r1)
625         lwz     r0,_CCR(r1)
626         mtspr   XER,r2
627         mtcrf   0xFF,r0
628         REST_10GPRS(3, r1)
629         REST_10GPRS(13, r1)
630         REST_8GPRS(23, r1)
631         REST_GPR(31, r1)
632         lwz     r2,_NIP(r1)     /* Restore environment */
633         lwz     r0,_MSR(r1)
634         mtspr   SRR0,r2
635         mtspr   SRR1,r0
636         lwz     r0,GPR0(r1)
637         lwz     r2,GPR2(r1)
638         lwz     r1,GPR1(r1)
639         SYNC
640         rfi
641
642 crit_return:
643         mfmsr   r28             /* Disable interrupts */
644         li      r4,0
645         ori     r4,r4,MSR_EE
646         andc    r28,r28,r4
647         SYNC                    /* Some chip revs need this... */
648         mtmsr   r28
649         SYNC
650         lwz     r2,_CTR(r1)
651         lwz     r0,_LINK(r1)
652         mtctr   r2
653         mtlr    r0
654         lwz     r2,_XER(r1)
655         lwz     r0,_CCR(r1)
656         mtspr   XER,r2
657         mtcrf   0xFF,r0
658         REST_10GPRS(3, r1)
659         REST_10GPRS(13, r1)
660         REST_8GPRS(23, r1)
661         REST_GPR(31, r1)
662         lwz     r2,_NIP(r1)     /* Restore environment */
663         lwz     r0,_MSR(r1)
664         mtspr   990,r2          /* SRR2 */
665         mtspr   991,r0          /* SRR3 */
666         lwz     r0,GPR0(r1)
667         lwz     r2,GPR2(r1)
668         lwz     r1,GPR1(r1)
669         SYNC
670         rfci
671
672 /* Cache functions.
673 */
674 invalidate_icache:
675         mfspr   r0,L1CSR1
676         ori     r0,r0,0x0002
677         mtspr   L1CSR1,r0
678         isync
679         blr                             /*   entire I cache */
680
681 invalidate_dcache:
682         mfspr   r0,L1CSR0
683         ori     r0,r0,0x0002
684         msync
685         isync
686         mtspr   L1CSR0,r0
687         isync
688         blr
689
690         .globl  icache_enable
691 icache_enable:
692         mflr    r8
693         bl      invalidate_icache
694         mtlr    r8
695         isync
696         mfspr   r4,L1CSR1
697         ori     r4,r4,0x0001
698         oris    r4,r4,0x0001
699         mtspr   L1CSR1,r4
700         isync
701         blr
702
703         .globl  icache_disable
704 icache_disable:
705         mfspr   r0,L1CSR1
706         lis     r1,0xfffffffe@h
707         ori     r1,r1,0xfffffffe@l
708         and     r0,r0,r1
709         mtspr   L1CSR1,r0
710         isync
711         blr
712
713         .globl  icache_status
714 icache_status:
715         mfspr   r3,L1CSR1
716         srwi    r3, r3, 31      /* >>31 => select bit 0 */
717         blr
718
719         .globl  dcache_enable
720 dcache_enable:
721         mflr    r8
722         bl      invalidate_dcache
723         mtlr    r8
724         isync
725         mfspr   r0,L1CSR0
726         ori     r0,r0,0x0001
727         oris    r0,r0,0x0001
728         msync
729         isync
730         mtspr   L1CSR0,r0
731         isync
732         blr
733
734         .globl  dcache_disable
735 dcache_disable:
736         mfspr   r0,L1CSR0
737         lis     r1,0xfffffffe@h
738         ori     r1,r1,0xfffffffe@l
739         and     r0,r0,r1
740         msync
741         isync
742         mtspr   L1CSR0,r0
743         isync
744         blr
745
746         .globl  dcache_status
747 dcache_status:
748         mfspr   r3,L1CSR0
749         srwi    r3, r3, 31      /* >>31 => select bit 0 */
750         blr
751
752         .globl get_pir
753 get_pir:
754         mfspr   r3, PIR
755         blr
756
757         .globl get_pvr
758 get_pvr:
759         mfspr   r3, PVR
760         blr
761
762         .globl get_svr
763 get_svr:
764         mfspr   r3, SVR
765         blr
766
767         .globl wr_tcr
768 wr_tcr:
769         mtspr   TCR, r3
770         blr
771
772 /*------------------------------------------------------------------------------- */
773 /* Function:     in8 */
774 /* Description:  Input 8 bits */
775 /*------------------------------------------------------------------------------- */
776         .globl  in8
777 in8:
778         lbz     r3,0x0000(r3)
779         blr
780
781 /*------------------------------------------------------------------------------- */
782 /* Function:     out8 */
783 /* Description:  Output 8 bits */
784 /*------------------------------------------------------------------------------- */
785         .globl  out8
786 out8:
787         stb     r4,0x0000(r3)
788         blr
789
790 /*------------------------------------------------------------------------------- */
791 /* Function:     out16 */
792 /* Description:  Output 16 bits */
793 /*------------------------------------------------------------------------------- */
794         .globl  out16
795 out16:
796         sth     r4,0x0000(r3)
797         blr
798
799 /*------------------------------------------------------------------------------- */
800 /* Function:     out16r */
801 /* Description:  Byte reverse and output 16 bits */
802 /*------------------------------------------------------------------------------- */
803         .globl  out16r
804 out16r:
805         sthbrx  r4,r0,r3
806         blr
807
808 /*------------------------------------------------------------------------------- */
809 /* Function:     out32 */
810 /* Description:  Output 32 bits */
811 /*------------------------------------------------------------------------------- */
812         .globl  out32
813 out32:
814         stw     r4,0x0000(r3)
815         blr
816
817 /*------------------------------------------------------------------------------- */
818 /* Function:     out32r */
819 /* Description:  Byte reverse and output 32 bits */
820 /*------------------------------------------------------------------------------- */
821         .globl  out32r
822 out32r:
823         stwbrx  r4,r0,r3
824         blr
825
826 /*------------------------------------------------------------------------------- */
827 /* Function:     in16 */
828 /* Description:  Input 16 bits */
829 /*------------------------------------------------------------------------------- */
830         .globl  in16
831 in16:
832         lhz     r3,0x0000(r3)
833         blr
834
835 /*------------------------------------------------------------------------------- */
836 /* Function:     in16r */
837 /* Description:  Input 16 bits and byte reverse */
838 /*------------------------------------------------------------------------------- */
839         .globl  in16r
840 in16r:
841         lhbrx   r3,r0,r3
842         blr
843
844 /*------------------------------------------------------------------------------- */
845 /* Function:     in32 */
846 /* Description:  Input 32 bits */
847 /*------------------------------------------------------------------------------- */
848         .globl  in32
849 in32:
850         lwz     3,0x0000(3)
851         blr
852
853 /*------------------------------------------------------------------------------- */
854 /* Function:     in32r */
855 /* Description:  Input 32 bits and byte reverse */
856 /*------------------------------------------------------------------------------- */
857         .globl  in32r
858 in32r:
859         lwbrx   r3,r0,r3
860         blr
861
862 /*------------------------------------------------------------------------------- */
863 /* Function:     ppcDcbf */
864 /* Description:  Data Cache block flush */
865 /* Input:        r3 = effective address */
866 /* Output:       none. */
867 /*------------------------------------------------------------------------------- */
868         .globl  ppcDcbf
869 ppcDcbf:
870         dcbf    r0,r3
871         blr
872
873 /*------------------------------------------------------------------------------- */
874 /* Function:     ppcDcbi */
875 /* Description:  Data Cache block Invalidate */
876 /* Input:        r3 = effective address */
877 /* Output:       none. */
878 /*------------------------------------------------------------------------------- */
879         .globl  ppcDcbi
880 ppcDcbi:
881         dcbi    r0,r3
882         blr
883
884 /*--------------------------------------------------------------------------
885  * Function:     ppcDcbz
886  * Description:  Data Cache block zero.
887  * Input:        r3 = effective address
888  * Output:       none.
889  *-------------------------------------------------------------------------- */
890
891         .globl  ppcDcbz
892 ppcDcbz:
893         dcbz    r0,r3
894         blr
895
896 /*------------------------------------------------------------------------------- */
897 /* Function:     ppcSync */
898 /* Description:  Processor Synchronize */
899 /* Input:        none. */
900 /* Output:       none. */
901 /*------------------------------------------------------------------------------- */
902         .globl  ppcSync
903 ppcSync:
904         sync
905         blr
906
907 /*------------------------------------------------------------------------------*/
908
909 /*
910  * void relocate_code (addr_sp, gd, addr_moni)
911  *
912  * This "function" does not return, instead it continues in RAM
913  * after relocating the monitor code.
914  *
915  * r3 = dest
916  * r4 = src
917  * r5 = length in bytes
918  * r6 = cachelinesize
919  */
920         .globl  relocate_code
921 relocate_code:
922         mr      r1,  r3         /* Set new stack pointer                */
923         mr      r9,  r4         /* Save copy of Init Data pointer       */
924         mr      r10, r5         /* Save copy of Destination Address     */
925
926         mr      r3,  r5                         /* Destination Address  */
927         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
928         ori     r4, r4, CFG_MONITOR_BASE@l
929         lwz     r5,GOT(__init_end)
930         sub     r5,r5,r4
931         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
932
933         /*
934          * Fix GOT pointer:
935          *
936          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
937          *
938          * Offset:
939          */
940         sub     r15, r10, r4
941
942         /* First our own GOT */
943         add     r14, r14, r15
944         /* the the one used by the C code */
945         add     r30, r30, r15
946
947         /*
948          * Now relocate code
949          */
950
951         cmplw   cr1,r3,r4
952         addi    r0,r5,3
953         srwi.   r0,r0,2
954         beq     cr1,4f          /* In place copy is not necessary       */
955         beq     7f              /* Protect against 0 count              */
956         mtctr   r0
957         bge     cr1,2f
958
959         la      r8,-4(r4)
960         la      r7,-4(r3)
961 1:      lwzu    r0,4(r8)
962         stwu    r0,4(r7)
963         bdnz    1b
964         b       4f
965
966 2:      slwi    r0,r0,2
967         add     r8,r4,r0
968         add     r7,r3,r0
969 3:      lwzu    r0,-4(r8)
970         stwu    r0,-4(r7)
971         bdnz    3b
972
973 /*
974  * Now flush the cache: note that we must start from a cache aligned
975  * address. Otherwise we might miss one cache line.
976  */
977 4:      cmpwi   r6,0
978         add     r5,r3,r5
979         beq     7f              /* Always flush prefetch queue in any case */
980         subi    r0,r6,1
981         andc    r3,r3,r0
982         mr      r4,r3
983 5:      dcbst   0,r4
984         add     r4,r4,r6
985         cmplw   r4,r5
986         blt     5b
987         sync                    /* Wait for all dcbst to complete on bus */
988         mr      r4,r3
989 6:      icbi    0,r4
990         add     r4,r4,r6
991         cmplw   r4,r5
992         blt     6b
993 7:      sync                    /* Wait for all icbi to complete on bus */
994         isync
995
996 /*
997  * We are done. Do not return, instead branch to second part of board
998  * initialization, now running from RAM.
999  */
1000
1001         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1002         mtlr    r0
1003         blr                             /* NEVER RETURNS! */
1004
1005 in_ram:
1006
1007         /*
1008          * Relocation Function, r14 point to got2+0x8000
1009          *
1010          * Adjust got2 pointers, no need to check for 0, this code
1011          * already puts a few entries in the table.
1012          */
1013         li      r0,__got2_entries@sectoff@l
1014         la      r3,GOT(_GOT2_TABLE_)
1015         lwz     r11,GOT(_GOT2_TABLE_)
1016         mtctr   r0
1017         sub     r11,r3,r11
1018         addi    r3,r3,-4
1019 1:      lwzu    r0,4(r3)
1020         add     r0,r0,r11
1021         stw     r0,0(r3)
1022         bdnz    1b
1023
1024         /*
1025          * Now adjust the fixups and the pointers to the fixups
1026          * in case we need to move ourselves again.
1027          */
1028 2:      li      r0,__fixup_entries@sectoff@l
1029         lwz     r3,GOT(_FIXUP_TABLE_)
1030         cmpwi   r0,0
1031         mtctr   r0
1032         addi    r3,r3,-4
1033         beq     4f
1034 3:      lwzu    r4,4(r3)
1035         lwzux   r0,r4,r11
1036         add     r0,r0,r11
1037         stw     r10,0(r3)
1038         stw     r0,0(r4)
1039         bdnz    3b
1040 4:
1041 clear_bss:
1042         /*
1043          * Now clear BSS segment
1044          */
1045         lwz     r3,GOT(__bss_start)
1046         lwz     r4,GOT(_end)
1047
1048         cmplw   0, r3, r4
1049         beq     6f
1050
1051         li      r0, 0
1052 5:
1053         stw     r0, 0(r3)
1054         addi    r3, r3, 4
1055         cmplw   0, r3, r4
1056         bne     5b
1057 6:
1058
1059         mr      r3, r9          /* Init Data pointer            */
1060         mr      r4, r10         /* Destination Address          */
1061         bl      board_init_r
1062
1063         /*
1064          * Copy exception vector code to low memory
1065          *
1066          * r3: dest_addr
1067          * r7: source address, r8: end address, r9: target address
1068          */
1069         .globl  trap_init
1070 trap_init:
1071         lwz     r7, GOT(_start)
1072         lwz     r8, GOT(_end_of_vectors)
1073
1074         li      r9, 0x100               /* reset vector always at 0x100 */
1075
1076         cmplw   0, r7, r8
1077         bgelr                           /* return if r7>=r8 - just in case */
1078
1079         mflr    r4                      /* save link register           */
1080 1:
1081         lwz     r0, 0(r7)
1082         stw     r0, 0(r9)
1083         addi    r7, r7, 4
1084         addi    r9, r9, 4
1085         cmplw   0, r7, r8
1086         bne     1b
1087
1088         /*
1089          * relocate `hdlr' and `int_return' entries
1090          */
1091         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1092         bl      trap_reloc
1093         li      r7, .L_DataStorage - _start + EXC_OFF_SYS_RESET
1094         bl      trap_reloc
1095         li      r7, .L_InstStorage - _start + EXC_OFF_SYS_RESET
1096         bl      trap_reloc
1097         li      r7, .L_ExtInterrupt - _start + EXC_OFF_SYS_RESET
1098         bl      trap_reloc
1099         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1100         bl      trap_reloc
1101         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1102         bl      trap_reloc
1103         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1104         bl      trap_reloc
1105         li      r7, .L_Decrementer - _start + EXC_OFF_SYS_RESET
1106         bl      trap_reloc
1107         li      r7, .L_IntervalTimer - _start + EXC_OFF_SYS_RESET
1108         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1109 2:
1110         bl      trap_reloc
1111         addi    r7, r7, 0x100           /* next exception vector        */
1112         cmplw   0, r7, r8
1113         blt     2b
1114
1115         lis     r7,0x0
1116         mtspr   IVPR, r7
1117
1118         mtlr    r4                      /* restore link register        */
1119         blr
1120
1121         /*
1122          * Function: relocate entries for one exception vector
1123          */
1124 trap_reloc:
1125         lwz     r0, 0(r7)               /* hdlr ...                     */
1126         add     r0, r0, r3              /*  ... += dest_addr            */
1127         stw     r0, 0(r7)
1128
1129         lwz     r0, 4(r7)               /* int_return ...               */
1130         add     r0, r0, r3              /*  ... += dest_addr            */
1131         stw     r0, 4(r7)
1132
1133         blr
1134
1135 #ifdef CFG_INIT_RAM_LOCK
1136 .globl unlock_ram_in_cache
1137 unlock_ram_in_cache:
1138         /* invalidate the INIT_RAM section */
1139         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1140         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1141         li      r2,512
1142         mtctr   r2
1143 1:      icbi    r0, r3
1144         dcbi    r0, r3
1145         addi    r3, r3, 32
1146         bdnz    1b
1147         sync                    /* Wait for all icbi to complete on bus */
1148         isync
1149         blr
1150 #endif