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