vserver 1.9.5.x5
[linux-2.6.git] / arch / ppc / boot / common / util.S
1 /*
2  * arch/ppc/boot/common/util.S
3  *
4  * Useful bootup functions, which are more easily done in asm than C.
5  *
6  * NOTE:  Be very very careful about the registers you use here.
7  *      We don't follow any ABI calling convention among the
8  *      assembler functions that call each other, especially early
9  *      in the initialization.  Please preserve at least r3 and r4
10  *      for these early functions, as they often contain information
11  *      passed from boot roms into the C decompress function.
12  *
13  * Author: Tom Rini
14  *         trini@mvista.com
15  * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
16  *
17  * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
18  * the terms of the GNU General Public License version 2.  This program
19  * is licensed "as is" without any warranty of any kind, whether express
20  * or implied.
21  */
22
23 #include <asm/processor.h>
24 #include <asm/cache.h>
25 #include <asm/ppc_asm.h>
26
27
28         .text
29
30 #ifdef CONFIG_6xx
31         .globl  disable_6xx_mmu
32 disable_6xx_mmu:
33         /* Establish default MSR value, exception prefix 0xFFF.
34          * If necessary, this function must fix up the LR if we
35          * return to a different address space once the MMU is
36          * disabled.
37          */
38         li      r8,MSR_IP|MSR_FP
39         mtmsr   r8
40         isync
41
42         /* Test for a 601 */
43         mfpvr   r10
44         srwi    r10,r10,16
45         cmpwi   0,r10,1         /* 601 ? */
46         beq     .clearbats_601
47
48         /* Clear BATs */
49         li      r8,0
50         mtspr   DBAT0U,r8
51         mtspr   DBAT0L,r8
52         mtspr   DBAT1U,r8
53         mtspr   DBAT1L,r8
54         mtspr   DBAT2U,r8
55         mtspr   DBAT2L,r8
56         mtspr   DBAT3U,r8
57         mtspr   DBAT3L,r8
58 .clearbats_601:
59         mtspr   IBAT0U,r8
60         mtspr   IBAT0L,r8
61         mtspr   IBAT1U,r8
62         mtspr   IBAT1L,r8
63         mtspr   IBAT2U,r8
64         mtspr   IBAT2L,r8
65         mtspr   IBAT3U,r8
66         mtspr   IBAT3L,r8
67         isync
68         sync
69         sync
70
71         /* Set segment registers */
72         li      r8,16           /* load up segment register values */
73         mtctr   r8              /* for context 0 */
74         lis     r8,0x2000       /* Ku = 1, VSID = 0 */
75         li      r10,0
76 3:      mtsrin  r8,r10
77         addi    r8,r8,0x111     /* increment VSID */
78         addis   r10,r10,0x1000  /* address of next segment */
79         bdnz    3b
80         blr
81
82         .globl  disable_6xx_l1cache
83 disable_6xx_l1cache:
84         /* Enable, invalidate and then disable the L1 icache/dcache. */
85         li      r8,0
86         ori     r8,r8,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
87         mfspr   r11,HID0
88         or      r11,r11,r8
89         andc    r10,r11,r8
90         isync
91         mtspr   HID0,r8
92         sync
93         isync
94         mtspr   HID0,r10
95         sync
96         isync
97         blr
98 #endif
99
100         .globl  _setup_L2CR
101 _setup_L2CR:
102 /*
103  * We should be skipping this section on CPUs where this results in an
104  * illegal instruction.  If not, please send trini@kernel.crashing.org
105  * the PVR of your CPU.
106  */
107         /* Invalidate/disable L2 cache */
108         sync
109         isync
110         mfspr   r8,L2CR
111         rlwinm  r8,r8,0,1,31
112         oris    r8,r8,L2CR_L2I@h
113         sync
114         isync
115         mtspr   L2CR,r8
116         sync
117         isync
118
119         /* Wait for the invalidation to complete */
120         mfspr   r8,PVR
121         srwi    r8,r8,16
122         cmplwi  cr0,r8,0x8000                   /* 7450 */
123         cmplwi  cr1,r8,0x8001                   /* 7455 */
124         cmplwi  cr2,r8,0x8002                   /* 7457 */
125         cror    4*cr0+eq,4*cr0+eq,4*cr1+eq      /* Now test if any are true. */
126         cror    4*cr0+eq,4*cr0+eq,4*cr2+eq
127         bne     2f
128
129 1:      mfspr   r8,L2CR         /* On 745x, poll L2I bit (bit 10) */
130         rlwinm. r9,r8,0,10,10
131         bne     1b
132         b       3f
133
134 2:      mfspr   r8,L2CR         /* On 75x & 74[01]0, poll L2IP bit (bit 31) */
135         rlwinm. r9,r8,0,31,31
136         bne     2b
137
138 3:      rlwinm  r8,r8,0,11,9    /* Turn off L2I bit */
139         sync
140         isync
141         mtspr   L2CR,r8
142         sync
143         isync
144         blr
145
146         .globl  _setup_L3CR
147 _setup_L3CR:
148         /* Invalidate/disable L3 cache */
149         sync
150         isync
151         mfspr   r8,L3CR
152         rlwinm  r8,r8,0,1,31
153         ori     r8,r8,L3CR_L3I@l
154         sync
155         isync
156         mtspr   L3CR,r8
157         sync
158         isync
159
160         /* Wait for the invalidation to complete */
161 1:      mfspr   r8,L3CR
162         rlwinm. r9,r8,0,21,21
163         bne     1b
164
165         rlwinm  r8,r8,0,22,20           /* Turn off L3I bit */
166         sync
167         isync
168         mtspr   L3CR,r8
169         sync
170         isync
171         blr
172
173
174 /* udelay (on non-601 processors) needs to know the period of the
175  * timebase in nanoseconds.  This used to be hardcoded to be 60ns
176  * (period of 66MHz/4).  Now a variable is used that is initialized to
177  * 60 for backward compatibility, but it can be overridden as necessary
178  * with code something like this:
179  *    extern unsigned long timebase_period_ns;
180  *    timebase_period_ns = 1000000000 / bd->bi_tbfreq;
181  */
182         .data
183         .globl timebase_period_ns
184 timebase_period_ns:
185         .long   60
186
187         .text
188 /*
189  * Delay for a number of microseconds
190  */
191         .globl  udelay
192 udelay:
193         mfspr   r4,PVR
194         srwi    r4,r4,16
195         cmpwi   0,r4,1          /* 601 ? */
196         bne     .udelay_not_601
197 00:     li      r0,86   /* Instructions / microsecond? */
198         mtctr   r0
199 10:     addi    r0,r0,0 /* NOP */
200         bdnz    10b
201         subic.  r3,r3,1
202         bne     00b
203         blr
204
205 .udelay_not_601:
206         mulli   r4,r3,1000      /* nanoseconds */
207         /*  Change r4 to be the number of ticks using:  
208          *      (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
209          *  timebase_period_ns defaults to 60 (16.6MHz) */
210         lis     r5,timebase_period_ns@ha
211         lwz     r5,timebase_period_ns@l(r5)
212         add     r4,r4,r5
213         addi    r4,r4,-1
214         divw    r4,r4,r5        /* BUS ticks */
215 1:      mftbu   r5
216         mftb    r6
217         mftbu   r7
218         cmpw    0,r5,r7
219         bne     1b              /* Get [synced] base time */
220         addc    r9,r6,r4        /* Compute end time */
221         addze   r8,r5
222 2:      mftbu   r5
223         cmpw    0,r5,r8
224         blt     2b
225         bgt     3f
226         mftb    r6
227         cmpw    0,r6,r9
228         blt     2b
229 3:      blr
230
231         .section ".relocate_code","xa"
232 /*
233  * Flush and enable instruction cache
234  * First, flush the data cache in case it was enabled and may be
235  * holding instructions for copy back.
236  */
237 _GLOBAL(flush_instruction_cache)
238         mflr    r6
239         bl      flush_data_cache
240
241 #ifdef CONFIG_8xx
242         lis     r3, IDC_INVALL@h
243         mtspr   IC_CST, r3
244         lis     r3, IDC_ENABLE@h
245         mtspr   IC_CST, r3
246         lis     r3, IDC_DISABLE@h
247         mtspr   DC_CST, r3
248 #elif CONFIG_4xx
249         lis     r3,start@h              # r9 = &_start
250         lis     r4,_etext@ha
251         addi    r4,r4,_etext@l          # r8 = &_etext
252 1:      dcbf    r0,r3                   # Flush the data cache
253         icbi    r0,r3                   # Invalidate the instruction cache
254         addi    r3,r3,0x10              # Increment by one cache line
255         cmplwi  cr0,r3,r4               # Are we at the end yet?
256         blt     1b                      # No, keep flushing and invalidating
257 #else
258         /* Enable, invalidate and then disable the L1 icache/dcache. */
259         li      r3,0
260         ori     r3,r3,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
261         mfspr   r4,HID0
262         or      r5,r4,r3
263         isync
264         mtspr   HID0,r5
265         sync
266         isync
267         ori     r5,r4,HID0_ICE  /* Enable cache */
268         mtspr   HID0,r5
269         sync
270         isync
271 #endif
272         mtlr    r6
273         blr
274
275 #define NUM_CACHE_LINES 128*8
276 #define cache_flush_buffer 0x1000
277
278 /*
279  * Flush data cache
280  * Do this by just reading lots of stuff into the cache.
281  */
282 _GLOBAL(flush_data_cache)
283         lis     r3,cache_flush_buffer@h
284         ori     r3,r3,cache_flush_buffer@l
285         li      r4,NUM_CACHE_LINES
286         mtctr   r4
287 00:     lwz     r4,0(r3)
288         addi    r3,r3,L1_CACHE_BYTES    /* Next line, please */
289         bdnz    00b
290 10:     blr
291
292         .previous
293