diff options
Diffstat (limited to 'arch/ppc/kernel/l2cr.S')
-rw-r--r-- | arch/ppc/kernel/l2cr.S | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S new file mode 100644 index 000000000000..c39441048266 --- /dev/null +++ b/arch/ppc/kernel/l2cr.S | |||
@@ -0,0 +1,442 @@ | |||
1 | /* | ||
2 | L2CR functions | ||
3 | Copyright © 1997-1998 by PowerLogix R & D, Inc. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | /* | ||
20 | Thur, Dec. 12, 1998. | ||
21 | - First public release, contributed by PowerLogix. | ||
22 | *********** | ||
23 | Sat, Aug. 7, 1999. | ||
24 | - Terry: Made sure code disabled interrupts before running. (Previously | ||
25 | it was assumed interrupts were already disabled). | ||
26 | - Terry: Updated for tentative G4 support. 4MB of memory is now flushed | ||
27 | instead of 2MB. (Prob. only 3 is necessary). | ||
28 | - Terry: Updated for workaround to HID0[DPM] processor bug | ||
29 | during global invalidates. | ||
30 | *********** | ||
31 | Thu, July 13, 2000. | ||
32 | - Terry: Added isync to correct for an errata. | ||
33 | |||
34 | 22 August 2001. | ||
35 | - DanM: Finally added the 7450 patch I've had for the past | ||
36 | several months. The L2CR is similar, but I'm going | ||
37 | to assume the user of this functions knows what they | ||
38 | are doing. | ||
39 | |||
40 | Author: Terry Greeniaus (tgree@phys.ualberta.ca) | ||
41 | Please e-mail updates to this file to me, thanks! | ||
42 | */ | ||
43 | #include <linux/config.h> | ||
44 | #include <asm/processor.h> | ||
45 | #include <asm/cputable.h> | ||
46 | #include <asm/ppc_asm.h> | ||
47 | #include <asm/cache.h> | ||
48 | #include <asm/page.h> | ||
49 | |||
50 | /* Usage: | ||
51 | |||
52 | When setting the L2CR register, you must do a few special | ||
53 | things. If you are enabling the cache, you must perform a | ||
54 | global invalidate. If you are disabling the cache, you must | ||
55 | flush the cache contents first. This routine takes care of | ||
56 | doing these things. When first enabling the cache, make sure | ||
57 | you pass in the L2CR you want, as well as passing in the | ||
58 | global invalidate bit set. A global invalidate will only be | ||
59 | performed if the L2I bit is set in applyThis. When enabling | ||
60 | the cache, you should also set the L2E bit in applyThis. If | ||
61 | you want to modify the L2CR contents after the cache has been | ||
62 | enabled, the recommended procedure is to first call | ||
63 | __setL2CR(0) to disable the cache and then call it again with | ||
64 | the new values for L2CR. Examples: | ||
65 | |||
66 | _setL2CR(0) - disables the cache | ||
67 | _setL2CR(0xB3A04000) - enables my G3 upgrade card: | ||
68 | - L2E set to turn on the cache | ||
69 | - L2SIZ set to 1MB | ||
70 | - L2CLK set to 1:1 | ||
71 | - L2RAM set to pipelined synchronous late-write | ||
72 | - L2I set to perform a global invalidation | ||
73 | - L2OH set to 0.5 nS | ||
74 | - L2DF set because this upgrade card | ||
75 | requires it | ||
76 | |||
77 | A similar call should work for your card. You need to know | ||
78 | the correct setting for your card and then place them in the | ||
79 | fields I have outlined above. Other fields support optional | ||
80 | features, such as L2DO which caches only data, or L2TS which | ||
81 | causes cache pushes from the L1 cache to go to the L2 cache | ||
82 | instead of to main memory. | ||
83 | |||
84 | IMPORTANT: | ||
85 | Starting with the 7450, the bits in this register have moved | ||
86 | or behave differently. The Enable, Parity Enable, Size, | ||
87 | and L2 Invalidate are the only bits that have not moved. | ||
88 | The size is read-only for these processors with internal L2 | ||
89 | cache, and the invalidate is a control as well as status. | ||
90 | -- Dan | ||
91 | |||
92 | */ | ||
93 | /* | ||
94 | * Summary: this procedure ignores the L2I bit in the value passed in, | ||
95 | * flushes the cache if it was already enabled, always invalidates the | ||
96 | * cache, then enables the cache if the L2E bit is set in the value | ||
97 | * passed in. | ||
98 | * -- paulus. | ||
99 | */ | ||
100 | _GLOBAL(_set_L2CR) | ||
101 | /* Make sure this is a 750 or 7400 chip */ | ||
102 | BEGIN_FTR_SECTION | ||
103 | li r3,-1 | ||
104 | blr | ||
105 | END_FTR_SECTION_IFCLR(CPU_FTR_L2CR) | ||
106 | |||
107 | mflr r9 | ||
108 | |||
109 | /* Stop DST streams */ | ||
110 | BEGIN_FTR_SECTION | ||
111 | DSSALL | ||
112 | sync | ||
113 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
114 | |||
115 | /* Turn off interrupts and data relocation. */ | ||
116 | mfmsr r7 /* Save MSR in r7 */ | ||
117 | rlwinm r4,r7,0,17,15 | ||
118 | rlwinm r4,r4,0,28,26 /* Turn off DR bit */ | ||
119 | sync | ||
120 | mtmsr r4 | ||
121 | isync | ||
122 | |||
123 | /* Before we perform the global invalidation, we must disable dynamic | ||
124 | * power management via HID0[DPM] to work around a processor bug where | ||
125 | * DPM can possibly interfere with the state machine in the processor | ||
126 | * that invalidates the L2 cache tags. | ||
127 | */ | ||
128 | mfspr r8,SPRN_HID0 /* Save HID0 in r8 */ | ||
129 | rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ | ||
130 | sync | ||
131 | mtspr SPRN_HID0,r4 /* Disable DPM */ | ||
132 | sync | ||
133 | |||
134 | /* Get the current enable bit of the L2CR into r4 */ | ||
135 | mfspr r4,SPRN_L2CR | ||
136 | |||
137 | /* Tweak some bits */ | ||
138 | rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ | ||
139 | rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ | ||
140 | rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ | ||
141 | |||
142 | /* Check to see if we need to flush */ | ||
143 | rlwinm. r4,r4,0,0,0 | ||
144 | beq 2f | ||
145 | |||
146 | /* Flush the cache. First, read the first 4MB of memory (physical) to | ||
147 | * put new data in the cache. (Actually we only need | ||
148 | * the size of the L2 cache plus the size of the L1 cache, but 4MB will | ||
149 | * cover everything just to be safe). | ||
150 | */ | ||
151 | |||
152 | /**** Might be a good idea to set L2DO here - to prevent instructions | ||
153 | from getting into the cache. But since we invalidate | ||
154 | the next time we enable the cache it doesn't really matter. | ||
155 | Don't do this unless you accomodate all processor variations. | ||
156 | The bit moved on the 7450..... | ||
157 | ****/ | ||
158 | |||
159 | /* TODO: use HW flush assist when available */ | ||
160 | |||
161 | lis r4,0x0002 | ||
162 | mtctr r4 | ||
163 | li r4,0 | ||
164 | 1: | ||
165 | lwzx r0,r0,r4 | ||
166 | addi r4,r4,32 /* Go to start of next cache line */ | ||
167 | bdnz 1b | ||
168 | isync | ||
169 | |||
170 | /* Now, flush the first 4MB of memory */ | ||
171 | lis r4,0x0002 | ||
172 | mtctr r4 | ||
173 | li r4,0 | ||
174 | sync | ||
175 | 1: | ||
176 | dcbf 0,r4 | ||
177 | addi r4,r4,32 /* Go to start of next cache line */ | ||
178 | bdnz 1b | ||
179 | |||
180 | 2: | ||
181 | /* Set up the L2CR configuration bits (and switch L2 off) */ | ||
182 | /* CPU errata: Make sure the mtspr below is already in the | ||
183 | * L1 icache | ||
184 | */ | ||
185 | b 20f | ||
186 | .balign L1_CACHE_LINE_SIZE | ||
187 | 22: | ||
188 | sync | ||
189 | mtspr SPRN_L2CR,r3 | ||
190 | sync | ||
191 | b 23f | ||
192 | 20: | ||
193 | b 21f | ||
194 | 21: sync | ||
195 | isync | ||
196 | b 22b | ||
197 | |||
198 | 23: | ||
199 | /* Perform a global invalidation */ | ||
200 | oris r3,r3,0x0020 | ||
201 | sync | ||
202 | mtspr SPRN_L2CR,r3 | ||
203 | sync | ||
204 | isync /* For errata */ | ||
205 | |||
206 | BEGIN_FTR_SECTION | ||
207 | /* On the 7450, we wait for the L2I bit to clear...... | ||
208 | */ | ||
209 | 10: mfspr r3,SPRN_L2CR | ||
210 | andis. r4,r3,0x0020 | ||
211 | bne 10b | ||
212 | b 11f | ||
213 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
214 | |||
215 | /* Wait for the invalidation to complete */ | ||
216 | 3: mfspr r3,SPRN_L2CR | ||
217 | rlwinm. r4,r3,0,31,31 | ||
218 | bne 3b | ||
219 | |||
220 | 11: rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */ | ||
221 | sync | ||
222 | mtspr SPRN_L2CR,r3 | ||
223 | sync | ||
224 | |||
225 | /* See if we need to enable the cache */ | ||
226 | cmplwi r5,0 | ||
227 | beq 4f | ||
228 | |||
229 | /* Enable the cache */ | ||
230 | oris r3,r3,0x8000 | ||
231 | mtspr SPRN_L2CR,r3 | ||
232 | sync | ||
233 | |||
234 | 4: | ||
235 | |||
236 | /* Restore HID0[DPM] to whatever it was before */ | ||
237 | sync | ||
238 | mtspr 1008,r8 | ||
239 | sync | ||
240 | |||
241 | /* Restore MSR (restores EE and DR bits to original state) */ | ||
242 | SYNC | ||
243 | mtmsr r7 | ||
244 | isync | ||
245 | |||
246 | mtlr r9 | ||
247 | blr | ||
248 | |||
249 | _GLOBAL(_get_L2CR) | ||
250 | /* Return the L2CR contents */ | ||
251 | li r3,0 | ||
252 | BEGIN_FTR_SECTION | ||
253 | mfspr r3,SPRN_L2CR | ||
254 | END_FTR_SECTION_IFSET(CPU_FTR_L2CR) | ||
255 | blr | ||
256 | |||
257 | |||
258 | /* | ||
259 | * Here is a similar routine for dealing with the L3 cache | ||
260 | * on the 745x family of chips | ||
261 | */ | ||
262 | |||
263 | _GLOBAL(_set_L3CR) | ||
264 | /* Make sure this is a 745x chip */ | ||
265 | BEGIN_FTR_SECTION | ||
266 | li r3,-1 | ||
267 | blr | ||
268 | END_FTR_SECTION_IFCLR(CPU_FTR_L3CR) | ||
269 | |||
270 | /* Turn off interrupts and data relocation. */ | ||
271 | mfmsr r7 /* Save MSR in r7 */ | ||
272 | rlwinm r4,r7,0,17,15 | ||
273 | rlwinm r4,r4,0,28,26 /* Turn off DR bit */ | ||
274 | sync | ||
275 | mtmsr r4 | ||
276 | isync | ||
277 | |||
278 | /* Stop DST streams */ | ||
279 | DSSALL | ||
280 | sync | ||
281 | |||
282 | /* Get the current enable bit of the L3CR into r4 */ | ||
283 | mfspr r4,SPRN_L3CR | ||
284 | |||
285 | /* Tweak some bits */ | ||
286 | rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ | ||
287 | rlwinm r3,r3,0,22,20 /* Turn off the invalidate bit */ | ||
288 | rlwinm r3,r3,0,2,31 /* Turn off the enable & PE bits */ | ||
289 | rlwinm r3,r3,0,5,3 /* Turn off the clken bit */ | ||
290 | /* Check to see if we need to flush */ | ||
291 | rlwinm. r4,r4,0,0,0 | ||
292 | beq 2f | ||
293 | |||
294 | /* Flush the cache. | ||
295 | */ | ||
296 | |||
297 | /* TODO: use HW flush assist */ | ||
298 | |||
299 | lis r4,0x0008 | ||
300 | mtctr r4 | ||
301 | li r4,0 | ||
302 | 1: | ||
303 | lwzx r0,r0,r4 | ||
304 | dcbf 0,r4 | ||
305 | addi r4,r4,32 /* Go to start of next cache line */ | ||
306 | bdnz 1b | ||
307 | |||
308 | 2: | ||
309 | /* Set up the L3CR configuration bits (and switch L3 off) */ | ||
310 | sync | ||
311 | mtspr SPRN_L3CR,r3 | ||
312 | sync | ||
313 | |||
314 | oris r3,r3,L3CR_L3RES@h /* Set reserved bit 5 */ | ||
315 | mtspr SPRN_L3CR,r3 | ||
316 | sync | ||
317 | oris r3,r3,L3CR_L3CLKEN@h /* Set clken */ | ||
318 | mtspr SPRN_L3CR,r3 | ||
319 | sync | ||
320 | |||
321 | /* Wait for stabilize */ | ||
322 | li r0,256 | ||
323 | mtctr r0 | ||
324 | 1: bdnz 1b | ||
325 | |||
326 | /* Perform a global invalidation */ | ||
327 | ori r3,r3,0x0400 | ||
328 | sync | ||
329 | mtspr SPRN_L3CR,r3 | ||
330 | sync | ||
331 | isync | ||
332 | |||
333 | /* We wait for the L3I bit to clear...... */ | ||
334 | 10: mfspr r3,SPRN_L3CR | ||
335 | andi. r4,r3,0x0400 | ||
336 | bne 10b | ||
337 | |||
338 | /* Clear CLKEN */ | ||
339 | rlwinm r3,r3,0,5,3 /* Turn off the clken bit */ | ||
340 | mtspr SPRN_L3CR,r3 | ||
341 | sync | ||
342 | |||
343 | /* Wait for stabilize */ | ||
344 | li r0,256 | ||
345 | mtctr r0 | ||
346 | 1: bdnz 1b | ||
347 | |||
348 | /* See if we need to enable the cache */ | ||
349 | cmplwi r5,0 | ||
350 | beq 4f | ||
351 | |||
352 | /* Enable the cache */ | ||
353 | oris r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h | ||
354 | mtspr SPRN_L3CR,r3 | ||
355 | sync | ||
356 | |||
357 | /* Wait for stabilize */ | ||
358 | li r0,256 | ||
359 | mtctr r0 | ||
360 | 1: bdnz 1b | ||
361 | |||
362 | /* Restore MSR (restores EE and DR bits to original state) */ | ||
363 | 4: SYNC | ||
364 | mtmsr r7 | ||
365 | isync | ||
366 | blr | ||
367 | |||
368 | _GLOBAL(_get_L3CR) | ||
369 | /* Return the L3CR contents */ | ||
370 | li r3,0 | ||
371 | BEGIN_FTR_SECTION | ||
372 | mfspr r3,SPRN_L3CR | ||
373 | END_FTR_SECTION_IFSET(CPU_FTR_L3CR) | ||
374 | blr | ||
375 | |||
376 | /* --- End of PowerLogix code --- | ||
377 | */ | ||
378 | |||
379 | |||
380 | /* flush_disable_L1() - Flush and disable L1 cache | ||
381 | * | ||
382 | * clobbers r0, r3, ctr, cr0 | ||
383 | * Must be called with interrupts disabled and MMU enabled. | ||
384 | */ | ||
385 | _GLOBAL(__flush_disable_L1) | ||
386 | /* Stop pending alitvec streams and memory accesses */ | ||
387 | BEGIN_FTR_SECTION | ||
388 | DSSALL | ||
389 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
390 | sync | ||
391 | |||
392 | /* Load counter to 0x4000 cache lines (512k) and | ||
393 | * load cache with datas | ||
394 | */ | ||
395 | li r3,0x4000 /* 512kB / 32B */ | ||
396 | mtctr r3 | ||
397 | lis r3,KERNELBASE@h | ||
398 | 1: | ||
399 | lwz r0,0(r3) | ||
400 | addi r3,r3,0x0020 /* Go to start of next cache line */ | ||
401 | bdnz 1b | ||
402 | isync | ||
403 | sync | ||
404 | |||
405 | /* Now flush those cache lines */ | ||
406 | li r3,0x4000 /* 512kB / 32B */ | ||
407 | mtctr r3 | ||
408 | lis r3,KERNELBASE@h | ||
409 | 1: | ||
410 | dcbf 0,r3 | ||
411 | addi r3,r3,0x0020 /* Go to start of next cache line */ | ||
412 | bdnz 1b | ||
413 | sync | ||
414 | |||
415 | /* We can now disable the L1 cache (HID0:DCE, HID0:ICE) */ | ||
416 | mfspr r3,SPRN_HID0 | ||
417 | rlwinm r3,r3,0,18,15 | ||
418 | mtspr SPRN_HID0,r3 | ||
419 | sync | ||
420 | isync | ||
421 | blr | ||
422 | |||
423 | /* inval_enable_L1 - Invalidate and enable L1 cache | ||
424 | * | ||
425 | * Assumes L1 is already disabled and MSR:EE is off | ||
426 | * | ||
427 | * clobbers r3 | ||
428 | */ | ||
429 | _GLOBAL(__inval_enable_L1) | ||
430 | /* Enable and then Flash inval the instruction & data cache */ | ||
431 | mfspr r3,SPRN_HID0 | ||
432 | ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI | ||
433 | sync | ||
434 | isync | ||
435 | mtspr SPRN_HID0,r3 | ||
436 | xori r3,r3, HID0_ICFI|HID0_DCI | ||
437 | mtspr SPRN_HID0,r3 | ||
438 | sync | ||
439 | |||
440 | blr | ||
441 | |||
442 | |||