89eea8cbe80673747dd7d49cd2fb85556291a206
[oweals/u-boot.git] / cpu / mpc85xx / start.S
1 /*
2  * Copyright 2004, 2007 Freescale Semiconductor.
3  * Copyright (C) 2003  Motorola,Inc.
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 <timestamp.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
88 /* clear registers/arrays not reset by hardware */
89
90         /* L1 */
91         li      r0,2
92         mtspr   L1CSR0,r0       /* invalidate d-cache */
93         mtspr   L1CSR1,r0       /* invalidate i-cache */
94
95         mfspr   r1,DBSR
96         mtspr   DBSR,r1         /* Clear all valid bits */
97
98         /*
99          *      Enable L1 Caches early
100          *
101          */
102
103         lis     r2,L1CSR0_CPE@H /* enable parity */
104         ori     r2,r2,L1CSR0_DCE
105         mtspr   L1CSR0,r2       /* enable L1 Dcache */
106         isync
107         mtspr   L1CSR1,r2       /* enable L1 Icache */
108         isync
109         msync
110
111         /* Setup interrupt vectors */
112         lis     r1,TEXT_BASE@h
113         mtspr   IVPR,r1
114
115         li      r1,0x0100
116         mtspr   IVOR0,r1        /* 0: Critical input */
117         li      r1,0x0200
118         mtspr   IVOR1,r1        /* 1: Machine check */
119         li      r1,0x0300
120         mtspr   IVOR2,r1        /* 2: Data storage */
121         li      r1,0x0400
122         mtspr   IVOR3,r1        /* 3: Instruction storage */
123         li      r1,0x0500
124         mtspr   IVOR4,r1        /* 4: External interrupt */
125         li      r1,0x0600
126         mtspr   IVOR5,r1        /* 5: Alignment */
127         li      r1,0x0700
128         mtspr   IVOR6,r1        /* 6: Program check */
129         li      r1,0x0800
130         mtspr   IVOR7,r1        /* 7: floating point unavailable */
131         li      r1,0x0900
132         mtspr   IVOR8,r1        /* 8: System call */
133         /* 9: Auxiliary processor unavailable(unsupported) */
134         li      r1,0x0a00
135         mtspr   IVOR10,r1       /* 10: Decrementer */
136         li      r1,0x0b00
137         mtspr   IVOR11,r1       /* 11: Interval timer */
138         li      r1,0x0c00
139         mtspr   IVOR12,r1       /* 12: Watchdog timer */
140         li      r1,0x0d00
141         mtspr   IVOR13,r1       /* 13: Data TLB error */
142         li      r1,0x0e00
143         mtspr   IVOR14,r1       /* 14: Instruction TLB error */
144         li      r1,0x0f00
145         mtspr   IVOR15,r1       /* 15: Debug */
146
147         /* Clear and set up some registers. */
148         li      r0,0x0000
149         lis     r1,0xffff
150         mtspr   DEC,r0                  /* prevent dec exceptions */
151         mttbl   r0                      /* prevent fit & wdt exceptions */
152         mttbu   r0
153         mtspr   TSR,r1                  /* clear all timer exception status */
154         mtspr   TCR,r0                  /* disable all */
155         mtspr   ESR,r0                  /* clear exception syndrome register */
156         mtspr   MCSR,r0                 /* machine check syndrome register */
157         mtxer   r0                      /* clear integer exception register */
158
159         /* Enable Time Base and Select Time Base Clock */
160         lis     r0,HID0_EMCP@h          /* Enable machine check */
161 #if defined(CONFIG_ENABLE_36BIT_PHYS)
162         ori     r0,r0,HID0_ENMAS7@l     /* Enable MAS7 */
163 #endif
164 #ifndef CONFIG_E500MC
165         ori     r0,r0,HID0_TBEN@l       /* Enable Timebase */
166 #endif
167         mtspr   HID0,r0
168
169 #ifndef CONFIG_E500MC
170         li      r0,(HID1_ASTME|HID1_ABE)@l      /* Addr streaming & broadcast */
171         mtspr   HID1,r0
172 #endif
173
174         /* Enable Branch Prediction */
175 #if defined(CONFIG_BTB)
176         li      r0,0x201                /* BBFI = 1, BPEN = 1 */
177         mtspr   BUCSR,r0
178 #endif
179
180 #if defined(CONFIG_SYS_INIT_DBCR)
181         lis     r1,0xffff
182         ori     r1,r1,0xffff
183         mtspr   DBSR,r1                 /* Clear all status bits */
184         lis     r0,CONFIG_SYS_INIT_DBCR@h       /* DBCR0[IDM] must be set */
185         ori     r0,r0,CONFIG_SYS_INIT_DBCR@l
186         mtspr   DBCR0,r0
187 #endif
188
189         /* create a temp mapping in AS=1 to the 4M boot window */
190         lis     r6,FSL_BOOKE_MAS0(1, 15, 0)@h
191         ori     r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
192
193         lis     r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h
194         ori     r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l
195
196         lis     r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h
197         ori     r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l
198
199         /* The 85xx has the default boot window 0xff800000 - 0xffffffff */
200         lis     r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
201         ori     r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
202
203         mtspr   MAS0,r6
204         mtspr   MAS1,r7
205         mtspr   MAS2,r8
206         mtspr   MAS3,r9
207         isync
208         msync
209         tlbwe
210
211         /* create a temp mapping in AS=1 to the stack */
212         lis     r6,FSL_BOOKE_MAS0(1, 14, 0)@h
213         ori     r6,r6,FSL_BOOKE_MAS0(1, 14, 0)@l
214
215         lis     r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@h
216         ori     r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@l
217
218         lis     r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@h
219         ori     r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@l
220
221         lis     r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
222         ori     r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
223
224         mtspr   MAS0,r6
225         mtspr   MAS1,r7
226         mtspr   MAS2,r8
227         mtspr   MAS3,r9
228         isync
229         msync
230         tlbwe
231
232         lis     r6,MSR_CE|MSR_ME|MSR_DE|MSR_IS|MSR_DS@h
233         ori     r6,r6,MSR_CE|MSR_ME|MSR_DE|MSR_IS|MSR_DS@l
234         lis     r7,switch_as@h
235         ori     r7,r7,switch_as@l
236
237         mtspr   SPRN_SRR0,r7
238         mtspr   SPRN_SRR1,r6
239         rfi
240
241 switch_as:
242 /* L1 DCache is used for initial RAM */
243
244         /* Allocate Initial RAM in data cache.
245          */
246         lis     r3,CONFIG_SYS_INIT_RAM_ADDR@h
247         ori     r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
248         mfspr   r2, L1CFG0
249         andi.   r2, r2, 0x1ff
250         /* cache size * 1024 / (2 * L1 line size) */
251         slwi    r2, r2, (10 - 1 - L1_CACHE_SHIFT)
252         mtctr   r2
253         li      r0,0
254 1:
255         dcbz    r0,r3
256         dcbtls  0,r0,r3
257         addi    r3,r3,CONFIG_SYS_CACHELINE_SIZE
258         bdnz    1b
259
260         /* Jump out the last 4K page and continue to 'normal' start */
261 #ifdef CONFIG_SYS_RAMBOOT
262         b       _start_cont
263 #else
264         /* Calculate absolute address in FLASH and jump there           */
265         /*--------------------------------------------------------------*/
266         lis     r3,CONFIG_SYS_MONITOR_BASE@h
267         ori     r3,r3,CONFIG_SYS_MONITOR_BASE@l
268         addi    r3,r3,_start_cont - _start + _START_OFFSET
269         mtlr    r3
270         blr
271 #endif
272
273         .text
274         .globl  _start
275 _start:
276         .long   0x27051956              /* U-BOOT Magic Number */
277         .globl  version_string
278 version_string:
279         .ascii U_BOOT_VERSION
280         .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
281         .ascii CONFIG_IDENT_STRING, "\0"
282
283         .align  4
284         .globl  _start_cont
285 _start_cont:
286         /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
287         lis     r1,CONFIG_SYS_INIT_RAM_ADDR@h
288         ori     r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l
289
290         li      r0,0
291         stwu    r0,-4(r1)
292         stwu    r0,-4(r1)               /* Terminate call chain */
293
294         stwu    r1,-8(r1)               /* Save back chain and move SP */
295         lis     r0,RESET_VECTOR@h       /* Address of reset vector */
296         ori     r0,r0,RESET_VECTOR@l
297         stwu    r1,-8(r1)               /* Save back chain and move SP */
298         stw     r0,+12(r1)              /* Save return addr (underflow vect) */
299
300         GET_GOT
301         bl      cpu_init_early_f
302
303         /* switch back to AS = 0 */
304         lis     r3,(MSR_CE|MSR_ME|MSR_DE)@h
305         ori     r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
306         mtmsr   r3
307         isync
308
309         bl      cpu_init_f
310         bl      board_init_f
311         isync
312
313         . = EXC_OFF_SYS_RESET
314         .globl  _start_of_vectors
315 _start_of_vectors:
316
317 /* Critical input. */
318         CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
319
320 /* Machine check */
321         MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
322
323 /* Data Storage exception. */
324         STD_EXCEPTION(0x0300, DataStorage, UnknownException)
325
326 /* Instruction Storage exception. */
327         STD_EXCEPTION(0x0400, InstStorage, UnknownException)
328
329 /* External Interrupt exception. */
330         STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
331
332 /* Alignment exception. */
333         . = 0x0600
334 Alignment:
335         EXCEPTION_PROLOG(SRR0, SRR1)
336         mfspr   r4,DAR
337         stw     r4,_DAR(r21)
338         mfspr   r5,DSISR
339         stw     r5,_DSISR(r21)
340         addi    r3,r1,STACK_FRAME_OVERHEAD
341         li      r20,MSR_KERNEL
342         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
343         lwz     r6,GOT(transfer_to_handler)
344         mtlr    r6
345         blrl
346 .L_Alignment:
347         .long   AlignmentException - _start + _START_OFFSET
348         .long   int_return - _start + _START_OFFSET
349
350 /* Program check exception */
351         . = 0x0700
352 ProgramCheck:
353         EXCEPTION_PROLOG(SRR0, SRR1)
354         addi    r3,r1,STACK_FRAME_OVERHEAD
355         li      r20,MSR_KERNEL
356         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
357         lwz     r6,GOT(transfer_to_handler)
358         mtlr    r6
359         blrl
360 .L_ProgramCheck:
361         .long   ProgramCheckException - _start + _START_OFFSET
362         .long   int_return - _start + _START_OFFSET
363
364         /* No FPU on MPC85xx.  This exception is not supposed to happen.
365         */
366         STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
367
368         . = 0x0900
369 /*
370  * r0 - SYSCALL number
371  * r3-... arguments
372  */
373 SystemCall:
374         addis   r11,r0,0        /* get functions table addr */
375         ori     r11,r11,0       /* Note: this code is patched in trap_init */
376         addis   r12,r0,0        /* get number of functions */
377         ori     r12,r12,0
378
379         cmplw   0,r0,r12
380         bge     1f
381
382         rlwinm  r0,r0,2,0,31    /* fn_addr = fn_tbl[r0] */
383         add     r11,r11,r0
384         lwz     r11,0(r11)
385
386         li      r20,0xd00-4     /* Get stack pointer */
387         lwz     r12,0(r20)
388         subi    r12,r12,12      /* Adjust stack pointer */
389         li      r0,0xc00+_end_back-SystemCall
390         cmplw   0,r0,r12        /* Check stack overflow */
391         bgt     1f
392         stw     r12,0(r20)
393
394         mflr    r0
395         stw     r0,0(r12)
396         mfspr   r0,SRR0
397         stw     r0,4(r12)
398         mfspr   r0,SRR1
399         stw     r0,8(r12)
400
401         li      r12,0xc00+_back-SystemCall
402         mtlr    r12
403         mtspr   SRR0,r11
404
405 1:      SYNC
406         rfi
407 _back:
408
409         mfmsr   r11                     /* Disable interrupts */
410         li      r12,0
411         ori     r12,r12,MSR_EE
412         andc    r11,r11,r12
413         SYNC                            /* Some chip revs need this... */
414         mtmsr   r11
415         SYNC
416
417         li      r12,0xd00-4             /* restore regs */
418         lwz     r12,0(r12)
419
420         lwz     r11,0(r12)
421         mtlr    r11
422         lwz     r11,4(r12)
423         mtspr   SRR0,r11
424         lwz     r11,8(r12)
425         mtspr   SRR1,r11
426
427         addi    r12,r12,12              /* Adjust stack pointer */
428         li      r20,0xd00-4
429         stw     r12,0(r20)
430
431         SYNC
432         rfi
433 _end_back:
434
435         STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
436         STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
437         STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
438
439         STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
440         STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
441
442         CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
443
444         .globl  _end_of_vectors
445 _end_of_vectors:
446
447
448         . = . + (0x100 - ( . & 0xff ))  /* align for debug */
449
450 /*
451  * This code finishes saving the registers to the exception frame
452  * and jumps to the appropriate handler for the exception.
453  * Register r21 is pointer into trap frame, r1 has new stack pointer.
454  */
455         .globl  transfer_to_handler
456 transfer_to_handler:
457         stw     r22,_NIP(r21)
458         lis     r22,MSR_POW@h
459         andc    r23,r23,r22
460         stw     r23,_MSR(r21)
461         SAVE_GPR(7, r21)
462         SAVE_4GPRS(8, r21)
463         SAVE_8GPRS(12, r21)
464         SAVE_8GPRS(24, r21)
465
466         mflr    r23
467         andi.   r24,r23,0x3f00          /* get vector offset */
468         stw     r24,TRAP(r21)
469         li      r22,0
470         stw     r22,RESULT(r21)
471         mtspr   SPRG2,r22               /* r1 is now kernel sp */
472
473         lwz     r24,0(r23)              /* virtual address of handler */
474         lwz     r23,4(r23)              /* where to go when done */
475         mtspr   SRR0,r24
476         mtspr   SRR1,r20
477         mtlr    r23
478         SYNC
479         rfi                             /* jump to handler, enable MMU */
480
481 int_return:
482         mfmsr   r28             /* Disable interrupts */
483         li      r4,0
484         ori     r4,r4,MSR_EE
485         andc    r28,r28,r4
486         SYNC                    /* Some chip revs need this... */
487         mtmsr   r28
488         SYNC
489         lwz     r2,_CTR(r1)
490         lwz     r0,_LINK(r1)
491         mtctr   r2
492         mtlr    r0
493         lwz     r2,_XER(r1)
494         lwz     r0,_CCR(r1)
495         mtspr   XER,r2
496         mtcrf   0xFF,r0
497         REST_10GPRS(3, r1)
498         REST_10GPRS(13, r1)
499         REST_8GPRS(23, r1)
500         REST_GPR(31, r1)
501         lwz     r2,_NIP(r1)     /* Restore environment */
502         lwz     r0,_MSR(r1)
503         mtspr   SRR0,r2
504         mtspr   SRR1,r0
505         lwz     r0,GPR0(r1)
506         lwz     r2,GPR2(r1)
507         lwz     r1,GPR1(r1)
508         SYNC
509         rfi
510
511 crit_return:
512         mfmsr   r28             /* Disable interrupts */
513         li      r4,0
514         ori     r4,r4,MSR_EE
515         andc    r28,r28,r4
516         SYNC                    /* Some chip revs need this... */
517         mtmsr   r28
518         SYNC
519         lwz     r2,_CTR(r1)
520         lwz     r0,_LINK(r1)
521         mtctr   r2
522         mtlr    r0
523         lwz     r2,_XER(r1)
524         lwz     r0,_CCR(r1)
525         mtspr   XER,r2
526         mtcrf   0xFF,r0
527         REST_10GPRS(3, r1)
528         REST_10GPRS(13, r1)
529         REST_8GPRS(23, r1)
530         REST_GPR(31, r1)
531         lwz     r2,_NIP(r1)     /* Restore environment */
532         lwz     r0,_MSR(r1)
533         mtspr   SPRN_CSRR0,r2
534         mtspr   SPRN_CSRR1,r0
535         lwz     r0,GPR0(r1)
536         lwz     r2,GPR2(r1)
537         lwz     r1,GPR1(r1)
538         SYNC
539         rfci
540
541 mck_return:
542         mfmsr   r28             /* Disable interrupts */
543         li      r4,0
544         ori     r4,r4,MSR_EE
545         andc    r28,r28,r4
546         SYNC                    /* Some chip revs need this... */
547         mtmsr   r28
548         SYNC
549         lwz     r2,_CTR(r1)
550         lwz     r0,_LINK(r1)
551         mtctr   r2
552         mtlr    r0
553         lwz     r2,_XER(r1)
554         lwz     r0,_CCR(r1)
555         mtspr   XER,r2
556         mtcrf   0xFF,r0
557         REST_10GPRS(3, r1)
558         REST_10GPRS(13, r1)
559         REST_8GPRS(23, r1)
560         REST_GPR(31, r1)
561         lwz     r2,_NIP(r1)     /* Restore environment */
562         lwz     r0,_MSR(r1)
563         mtspr   SPRN_MCSRR0,r2
564         mtspr   SPRN_MCSRR1,r0
565         lwz     r0,GPR0(r1)
566         lwz     r2,GPR2(r1)
567         lwz     r1,GPR1(r1)
568         SYNC
569         rfmci
570
571 /* Cache functions.
572 */
573 .globl invalidate_icache
574 invalidate_icache:
575         mfspr   r0,L1CSR1
576         ori     r0,r0,L1CSR1_ICFI
577         msync
578         isync
579         mtspr   L1CSR1,r0
580         isync
581         blr                             /* entire I cache */
582
583 .globl invalidate_dcache
584 invalidate_dcache:
585         mfspr   r0,L1CSR0
586         ori     r0,r0,L1CSR0_DCFI
587         msync
588         isync
589         mtspr   L1CSR0,r0
590         isync
591         blr
592
593         .globl  icache_enable
594 icache_enable:
595         mflr    r8
596         bl      invalidate_icache
597         mtlr    r8
598         isync
599         mfspr   r4,L1CSR1
600         ori     r4,r4,0x0001
601         oris    r4,r4,0x0001
602         mtspr   L1CSR1,r4
603         isync
604         blr
605
606         .globl  icache_disable
607 icache_disable:
608         mfspr   r0,L1CSR1
609         lis     r3,0
610         ori     r3,r3,L1CSR1_ICE
611         andc    r0,r0,r3
612         mtspr   L1CSR1,r0
613         isync
614         blr
615
616         .globl  icache_status
617 icache_status:
618         mfspr   r3,L1CSR1
619         andi.   r3,r3,L1CSR1_ICE
620         blr
621
622         .globl  dcache_enable
623 dcache_enable:
624         mflr    r8
625         bl      invalidate_dcache
626         mtlr    r8
627         isync
628         mfspr   r0,L1CSR0
629         ori     r0,r0,0x0001
630         oris    r0,r0,0x0001
631         msync
632         isync
633         mtspr   L1CSR0,r0
634         isync
635         blr
636
637         .globl  dcache_disable
638 dcache_disable:
639         mfspr   r3,L1CSR0
640         lis     r4,0
641         ori     r4,r4,L1CSR0_DCE
642         andc    r3,r3,r4
643         mtspr   L1CSR0,r0
644         isync
645         blr
646
647         .globl  dcache_status
648 dcache_status:
649         mfspr   r3,L1CSR0
650         andi.   r3,r3,L1CSR0_DCE
651         blr
652
653         .globl get_pir
654 get_pir:
655         mfspr   r3,PIR
656         blr
657
658         .globl get_pvr
659 get_pvr:
660         mfspr   r3,PVR
661         blr
662
663         .globl get_svr
664 get_svr:
665         mfspr   r3,SVR
666         blr
667
668         .globl wr_tcr
669 wr_tcr:
670         mtspr   TCR,r3
671         blr
672
673 /*------------------------------------------------------------------------------- */
674 /* Function:     in8 */
675 /* Description:  Input 8 bits */
676 /*------------------------------------------------------------------------------- */
677         .globl  in8
678 in8:
679         lbz     r3,0x0000(r3)
680         blr
681
682 /*------------------------------------------------------------------------------- */
683 /* Function:     out8 */
684 /* Description:  Output 8 bits */
685 /*------------------------------------------------------------------------------- */
686         .globl  out8
687 out8:
688         stb     r4,0x0000(r3)
689         sync
690         blr
691
692 /*------------------------------------------------------------------------------- */
693 /* Function:     out16 */
694 /* Description:  Output 16 bits */
695 /*------------------------------------------------------------------------------- */
696         .globl  out16
697 out16:
698         sth     r4,0x0000(r3)
699         sync
700         blr
701
702 /*------------------------------------------------------------------------------- */
703 /* Function:     out16r */
704 /* Description:  Byte reverse and output 16 bits */
705 /*------------------------------------------------------------------------------- */
706         .globl  out16r
707 out16r:
708         sthbrx  r4,r0,r3
709         sync
710         blr
711
712 /*------------------------------------------------------------------------------- */
713 /* Function:     out32 */
714 /* Description:  Output 32 bits */
715 /*------------------------------------------------------------------------------- */
716         .globl  out32
717 out32:
718         stw     r4,0x0000(r3)
719         sync
720         blr
721
722 /*------------------------------------------------------------------------------- */
723 /* Function:     out32r */
724 /* Description:  Byte reverse and output 32 bits */
725 /*------------------------------------------------------------------------------- */
726         .globl  out32r
727 out32r:
728         stwbrx  r4,r0,r3
729         sync
730         blr
731
732 /*------------------------------------------------------------------------------- */
733 /* Function:     in16 */
734 /* Description:  Input 16 bits */
735 /*------------------------------------------------------------------------------- */
736         .globl  in16
737 in16:
738         lhz     r3,0x0000(r3)
739         blr
740
741 /*------------------------------------------------------------------------------- */
742 /* Function:     in16r */
743 /* Description:  Input 16 bits and byte reverse */
744 /*------------------------------------------------------------------------------- */
745         .globl  in16r
746 in16r:
747         lhbrx   r3,r0,r3
748         blr
749
750 /*------------------------------------------------------------------------------- */
751 /* Function:     in32 */
752 /* Description:  Input 32 bits */
753 /*------------------------------------------------------------------------------- */
754         .globl  in32
755 in32:
756         lwz     3,0x0000(3)
757         blr
758
759 /*------------------------------------------------------------------------------- */
760 /* Function:     in32r */
761 /* Description:  Input 32 bits and byte reverse */
762 /*------------------------------------------------------------------------------- */
763         .globl  in32r
764 in32r:
765         lwbrx   r3,r0,r3
766         blr
767
768 /*------------------------------------------------------------------------------*/
769
770 /*
771  * void relocate_code (addr_sp, gd, addr_moni)
772  *
773  * This "function" does not return, instead it continues in RAM
774  * after relocating the monitor code.
775  *
776  * r3 = dest
777  * r4 = src
778  * r5 = length in bytes
779  * r6 = cachelinesize
780  */
781         .globl  relocate_code
782 relocate_code:
783         mr      r1,r3           /* Set new stack pointer                */
784         mr      r9,r4           /* Save copy of Init Data pointer       */
785         mr      r10,r5          /* Save copy of Destination Address     */
786
787         mr      r3,r5                           /* Destination Address  */
788         lis     r4,CONFIG_SYS_MONITOR_BASE@h            /* Source      Address  */
789         ori     r4,r4,CONFIG_SYS_MONITOR_BASE@l
790         lwz     r5,GOT(__init_end)
791         sub     r5,r5,r4
792         li      r6,CONFIG_SYS_CACHELINE_SIZE            /* Cache Line Size      */
793
794         /*
795          * Fix GOT pointer:
796          *
797          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
798          *
799          * Offset:
800          */
801         sub     r15,r10,r4
802
803         /* First our own GOT */
804         add     r14,r14,r15
805         /* the the one used by the C code */
806         add     r30,r30,r15
807
808         /*
809          * Now relocate code
810          */
811
812         cmplw   cr1,r3,r4
813         addi    r0,r5,3
814         srwi.   r0,r0,2
815         beq     cr1,4f          /* In place copy is not necessary       */
816         beq     7f              /* Protect against 0 count              */
817         mtctr   r0
818         bge     cr1,2f
819
820         la      r8,-4(r4)
821         la      r7,-4(r3)
822 1:      lwzu    r0,4(r8)
823         stwu    r0,4(r7)
824         bdnz    1b
825         b       4f
826
827 2:      slwi    r0,r0,2
828         add     r8,r4,r0
829         add     r7,r3,r0
830 3:      lwzu    r0,-4(r8)
831         stwu    r0,-4(r7)
832         bdnz    3b
833
834 /*
835  * Now flush the cache: note that we must start from a cache aligned
836  * address. Otherwise we might miss one cache line.
837  */
838 4:      cmpwi   r6,0
839         add     r5,r3,r5
840         beq     7f              /* Always flush prefetch queue in any case */
841         subi    r0,r6,1
842         andc    r3,r3,r0
843         mr      r4,r3
844 5:      dcbst   0,r4
845         add     r4,r4,r6
846         cmplw   r4,r5
847         blt     5b
848         sync                    /* Wait for all dcbst to complete on bus */
849         mr      r4,r3
850 6:      icbi    0,r4
851         add     r4,r4,r6
852         cmplw   r4,r5
853         blt     6b
854 7:      sync                    /* Wait for all icbi to complete on bus */
855         isync
856
857         /*
858          * Re-point the IVPR at RAM
859          */
860         mtspr   IVPR,r10
861
862 /*
863  * We are done. Do not return, instead branch to second part of board
864  * initialization, now running from RAM.
865  */
866
867         addi    r0,r10,in_ram - _start + _START_OFFSET
868         mtlr    r0
869         blr                             /* NEVER RETURNS! */
870         .globl  in_ram
871 in_ram:
872
873         /*
874          * Relocation Function, r14 point to got2+0x8000
875          *
876          * Adjust got2 pointers, no need to check for 0, this code
877          * already puts a few entries in the table.
878          */
879         li      r0,__got2_entries@sectoff@l
880         la      r3,GOT(_GOT2_TABLE_)
881         lwz     r11,GOT(_GOT2_TABLE_)
882         mtctr   r0
883         sub     r11,r3,r11
884         addi    r3,r3,-4
885 1:      lwzu    r0,4(r3)
886         add     r0,r0,r11
887         stw     r0,0(r3)
888         bdnz    1b
889
890         /*
891          * Now adjust the fixups and the pointers to the fixups
892          * in case we need to move ourselves again.
893          */
894 2:      li      r0,__fixup_entries@sectoff@l
895         lwz     r3,GOT(_FIXUP_TABLE_)
896         cmpwi   r0,0
897         mtctr   r0
898         addi    r3,r3,-4
899         beq     4f
900 3:      lwzu    r4,4(r3)
901         lwzux   r0,r4,r11
902         add     r0,r0,r11
903         stw     r10,0(r3)
904         stw     r0,0(r4)
905         bdnz    3b
906 4:
907 clear_bss:
908         /*
909          * Now clear BSS segment
910          */
911         lwz     r3,GOT(__bss_start)
912         lwz     r4,GOT(_end)
913
914         cmplw   0,r3,r4
915         beq     6f
916
917         li      r0,0
918 5:
919         stw     r0,0(r3)
920         addi    r3,r3,4
921         cmplw   0,r3,r4
922         bne     5b
923 6:
924
925         mr      r3,r9           /* Init Data pointer            */
926         mr      r4,r10          /* Destination Address          */
927         bl      board_init_r
928
929         /*
930          * Copy exception vector code to low memory
931          *
932          * r3: dest_addr
933          * r7: source address, r8: end address, r9: target address
934          */
935         .globl  trap_init
936 trap_init:
937         lwz     r7,GOT(_start_of_vectors)
938         lwz     r8,GOT(_end_of_vectors)
939
940         li      r9,0x100                /* reset vector always at 0x100 */
941
942         cmplw   0,r7,r8
943         bgelr                           /* return if r7>=r8 - just in case */
944
945         mflr    r4                      /* save link register           */
946 1:
947         lwz     r0,0(r7)
948         stw     r0,0(r9)
949         addi    r7,r7,4
950         addi    r9,r9,4
951         cmplw   0,r7,r8
952         bne     1b
953
954         /*
955          * relocate `hdlr' and `int_return' entries
956          */
957         li      r7,.L_CriticalInput - _start + _START_OFFSET
958         bl      trap_reloc
959         li      r7,.L_MachineCheck - _start + _START_OFFSET
960         bl      trap_reloc
961         li      r7,.L_DataStorage - _start + _START_OFFSET
962         bl      trap_reloc
963         li      r7,.L_InstStorage - _start + _START_OFFSET
964         bl      trap_reloc
965         li      r7,.L_ExtInterrupt - _start + _START_OFFSET
966         bl      trap_reloc
967         li      r7,.L_Alignment - _start + _START_OFFSET
968         bl      trap_reloc
969         li      r7,.L_ProgramCheck - _start + _START_OFFSET
970         bl      trap_reloc
971         li      r7,.L_FPUnavailable - _start + _START_OFFSET
972         bl      trap_reloc
973         li      r7,.L_Decrementer - _start + _START_OFFSET
974         bl      trap_reloc
975         li      r7,.L_IntervalTimer - _start + _START_OFFSET
976         li      r8,_end_of_vectors - _start + _START_OFFSET
977 2:
978         bl      trap_reloc
979         addi    r7,r7,0x100             /* next exception vector        */
980         cmplw   0,r7,r8
981         blt     2b
982
983         lis     r7,0x0
984         mtspr   IVPR,r7
985
986         mtlr    r4                      /* restore link register        */
987         blr
988
989         /*
990          * Function: relocate entries for one exception vector
991          */
992 trap_reloc:
993         lwz     r0,0(r7)                /* hdlr ...                     */
994         add     r0,r0,r3                /*  ... += dest_addr            */
995         stw     r0,0(r7)
996
997         lwz     r0,4(r7)                /* int_return ...               */
998         add     r0,r0,r3                /*  ... += dest_addr            */
999         stw     r0,4(r7)
1000
1001         blr
1002
1003 .globl unlock_ram_in_cache
1004 unlock_ram_in_cache:
1005         /* invalidate the INIT_RAM section */
1006         lis     r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@h
1007         ori     r3,r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@l
1008         mfspr   r4,L1CFG0
1009         andi.   r4,r4,0x1ff
1010         slwi    r4,r4,(10 - 1 - L1_CACHE_SHIFT)
1011         mtctr   r4
1012 1:      dcbi    r0,r3
1013         addi    r3,r3,CONFIG_SYS_CACHELINE_SIZE
1014         bdnz    1b
1015         sync
1016
1017         /* Invalidate the TLB entries for the cache */
1018         lis     r3,CONFIG_SYS_INIT_RAM_ADDR@h
1019         ori     r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
1020         tlbivax 0,r3
1021         addi    r3,r3,0x1000
1022         tlbivax 0,r3
1023         addi    r3,r3,0x1000
1024         tlbivax 0,r3
1025         addi    r3,r3,0x1000
1026         tlbivax 0,r3
1027         isync
1028         blr
1029
1030 .globl flush_dcache
1031 flush_dcache:
1032         mfspr   r3,SPRN_L1CFG0
1033
1034         rlwinm  r5,r3,9,3       /* Extract cache block size */
1035         twlgti  r5,1            /* Only 32 and 64 byte cache blocks
1036                                  * are currently defined.
1037                                  */
1038         li      r4,32
1039         subfic  r6,r5,2         /* r6 = log2(1KiB / cache block size) -
1040                                  *      log2(number of ways)
1041                                  */
1042         slw     r5,r4,r5        /* r5 = cache block size */
1043
1044         rlwinm  r7,r3,0,0xff    /* Extract number of KiB in the cache */
1045         mulli   r7,r7,13        /* An 8-way cache will require 13
1046                                  * loads per set.
1047                                  */
1048         slw     r7,r7,r6
1049
1050         /* save off HID0 and set DCFA */
1051         mfspr   r8,SPRN_HID0
1052         ori     r9,r8,HID0_DCFA@l
1053         mtspr   SPRN_HID0,r9
1054         isync
1055
1056         lis     r4,0
1057         mtctr   r7
1058
1059 1:      lwz     r3,0(r4)        /* Load... */
1060         add     r4,r4,r5
1061         bdnz    1b
1062
1063         msync
1064         lis     r4,0
1065         mtctr   r7
1066
1067 1:      dcbf    0,r4            /* ...and flush. */
1068         add     r4,r4,r5
1069         bdnz    1b
1070
1071         /* restore HID0 */
1072         mtspr   SPRN_HID0,r8
1073         isync
1074
1075         blr