diff options
Diffstat (limited to 'arch/powerpc/kernel/l2cr_6xx.S')
-rw-r--r-- | arch/powerpc/kernel/l2cr_6xx.S | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/l2cr_6xx.S b/arch/powerpc/kernel/l2cr_6xx.S new file mode 100644 index 000000000000..d7f4e982b539 --- /dev/null +++ b/arch/powerpc/kernel/l2cr_6xx.S | |||
@@ -0,0 +1,471 @@ | |||
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 | BEGIN_FTR_SECTION | ||
160 | /* Disable L2 prefetch on some 745x and try to ensure | ||
161 | * L2 prefetch engines are idle. As explained by errata | ||
162 | * text, we can't be sure they are, we just hope very hard | ||
163 | * that well be enough (sic !). At least I noticed Apple | ||
164 | * doesn't even bother doing the dcbf's here... | ||
165 | */ | ||
166 | mfspr r4,SPRN_MSSCR0 | ||
167 | rlwinm r4,r4,0,0,29 | ||
168 | sync | ||
169 | mtspr SPRN_MSSCR0,r4 | ||
170 | sync | ||
171 | isync | ||
172 | lis r4,KERNELBASE@h | ||
173 | dcbf 0,r4 | ||
174 | dcbf 0,r4 | ||
175 | dcbf 0,r4 | ||
176 | dcbf 0,r4 | ||
177 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
178 | |||
179 | /* TODO: use HW flush assist when available */ | ||
180 | |||
181 | lis r4,0x0002 | ||
182 | mtctr r4 | ||
183 | li r4,0 | ||
184 | 1: | ||
185 | lwzx r0,r0,r4 | ||
186 | addi r4,r4,32 /* Go to start of next cache line */ | ||
187 | bdnz 1b | ||
188 | isync | ||
189 | |||
190 | /* Now, flush the first 4MB of memory */ | ||
191 | lis r4,0x0002 | ||
192 | mtctr r4 | ||
193 | li r4,0 | ||
194 | sync | ||
195 | 1: | ||
196 | dcbf 0,r4 | ||
197 | addi r4,r4,32 /* Go to start of next cache line */ | ||
198 | bdnz 1b | ||
199 | |||
200 | 2: | ||
201 | /* Set up the L2CR configuration bits (and switch L2 off) */ | ||
202 | /* CPU errata: Make sure the mtspr below is already in the | ||
203 | * L1 icache | ||
204 | */ | ||
205 | b 20f | ||
206 | .balign L1_CACHE_BYTES | ||
207 | 22: | ||
208 | sync | ||
209 | mtspr SPRN_L2CR,r3 | ||
210 | sync | ||
211 | b 23f | ||
212 | 20: | ||
213 | b 21f | ||
214 | 21: sync | ||
215 | isync | ||
216 | b 22b | ||
217 | |||
218 | 23: | ||
219 | /* Perform a global invalidation */ | ||
220 | oris r3,r3,0x0020 | ||
221 | sync | ||
222 | mtspr SPRN_L2CR,r3 | ||
223 | sync | ||
224 | isync /* For errata */ | ||
225 | |||
226 | BEGIN_FTR_SECTION | ||
227 | /* On the 7450, we wait for the L2I bit to clear...... | ||
228 | */ | ||
229 | 10: mfspr r3,SPRN_L2CR | ||
230 | andis. r4,r3,0x0020 | ||
231 | bne 10b | ||
232 | b 11f | ||
233 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
234 | |||
235 | /* Wait for the invalidation to complete */ | ||
236 | 3: mfspr r3,SPRN_L2CR | ||
237 | rlwinm. r4,r3,0,31,31 | ||
238 | bne 3b | ||
239 | |||
240 | 11: rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */ | ||
241 | sync | ||
242 | mtspr SPRN_L2CR,r3 | ||
243 | sync | ||
244 | |||
245 | /* See if we need to enable the cache */ | ||
246 | cmplwi r5,0 | ||
247 | beq 4f | ||
248 | |||
249 | /* Enable the cache */ | ||
250 | oris r3,r3,0x8000 | ||
251 | mtspr SPRN_L2CR,r3 | ||
252 | sync | ||
253 | |||
254 | /* Enable L2 HW prefetch on 744x/745x */ | ||
255 | BEGIN_FTR_SECTION | ||
256 | mfspr r3,SPRN_MSSCR0 | ||
257 | ori r3,r3,3 | ||
258 | sync | ||
259 | mtspr SPRN_MSSCR0,r3 | ||
260 | sync | ||
261 | isync | ||
262 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
263 | 4: | ||
264 | |||
265 | /* Restore HID0[DPM] to whatever it was before */ | ||
266 | sync | ||
267 | mtspr 1008,r8 | ||
268 | sync | ||
269 | |||
270 | /* Restore MSR (restores EE and DR bits to original state) */ | ||
271 | SYNC | ||
272 | mtmsr r7 | ||
273 | isync | ||
274 | |||
275 | mtlr r9 | ||
276 | blr | ||
277 | |||
278 | _GLOBAL(_get_L2CR) | ||
279 | /* Return the L2CR contents */ | ||
280 | li r3,0 | ||
281 | BEGIN_FTR_SECTION | ||
282 | mfspr r3,SPRN_L2CR | ||
283 | END_FTR_SECTION_IFSET(CPU_FTR_L2CR) | ||
284 | blr | ||
285 | |||
286 | |||
287 | /* | ||
288 | * Here is a similar routine for dealing with the L3 cache | ||
289 | * on the 745x family of chips | ||
290 | */ | ||
291 | |||
292 | _GLOBAL(_set_L3CR) | ||
293 | /* Make sure this is a 745x chip */ | ||
294 | BEGIN_FTR_SECTION | ||
295 | li r3,-1 | ||
296 | blr | ||
297 | END_FTR_SECTION_IFCLR(CPU_FTR_L3CR) | ||
298 | |||
299 | /* Turn off interrupts and data relocation. */ | ||
300 | mfmsr r7 /* Save MSR in r7 */ | ||
301 | rlwinm r4,r7,0,17,15 | ||
302 | rlwinm r4,r4,0,28,26 /* Turn off DR bit */ | ||
303 | sync | ||
304 | mtmsr r4 | ||
305 | isync | ||
306 | |||
307 | /* Stop DST streams */ | ||
308 | DSSALL | ||
309 | sync | ||
310 | |||
311 | /* Get the current enable bit of the L3CR into r4 */ | ||
312 | mfspr r4,SPRN_L3CR | ||
313 | |||
314 | /* Tweak some bits */ | ||
315 | rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ | ||
316 | rlwinm r3,r3,0,22,20 /* Turn off the invalidate bit */ | ||
317 | rlwinm r3,r3,0,2,31 /* Turn off the enable & PE bits */ | ||
318 | rlwinm r3,r3,0,5,3 /* Turn off the clken bit */ | ||
319 | /* Check to see if we need to flush */ | ||
320 | rlwinm. r4,r4,0,0,0 | ||
321 | beq 2f | ||
322 | |||
323 | /* Flush the cache. | ||
324 | */ | ||
325 | |||
326 | /* TODO: use HW flush assist */ | ||
327 | |||
328 | lis r4,0x0008 | ||
329 | mtctr r4 | ||
330 | li r4,0 | ||
331 | 1: | ||
332 | lwzx r0,r0,r4 | ||
333 | dcbf 0,r4 | ||
334 | addi r4,r4,32 /* Go to start of next cache line */ | ||
335 | bdnz 1b | ||
336 | |||
337 | 2: | ||
338 | /* Set up the L3CR configuration bits (and switch L3 off) */ | ||
339 | sync | ||
340 | mtspr SPRN_L3CR,r3 | ||
341 | sync | ||
342 | |||
343 | oris r3,r3,L3CR_L3RES@h /* Set reserved bit 5 */ | ||
344 | mtspr SPRN_L3CR,r3 | ||
345 | sync | ||
346 | oris r3,r3,L3CR_L3CLKEN@h /* Set clken */ | ||
347 | mtspr SPRN_L3CR,r3 | ||
348 | sync | ||
349 | |||
350 | /* Wait for stabilize */ | ||
351 | li r0,256 | ||
352 | mtctr r0 | ||
353 | 1: bdnz 1b | ||
354 | |||
355 | /* Perform a global invalidation */ | ||
356 | ori r3,r3,0x0400 | ||
357 | sync | ||
358 | mtspr SPRN_L3CR,r3 | ||
359 | sync | ||
360 | isync | ||
361 | |||
362 | /* We wait for the L3I bit to clear...... */ | ||
363 | 10: mfspr r3,SPRN_L3CR | ||
364 | andi. r4,r3,0x0400 | ||
365 | bne 10b | ||
366 | |||
367 | /* Clear CLKEN */ | ||
368 | rlwinm r3,r3,0,5,3 /* Turn off the clken bit */ | ||
369 | mtspr SPRN_L3CR,r3 | ||
370 | sync | ||
371 | |||
372 | /* Wait for stabilize */ | ||
373 | li r0,256 | ||
374 | mtctr r0 | ||
375 | 1: bdnz 1b | ||
376 | |||
377 | /* See if we need to enable the cache */ | ||
378 | cmplwi r5,0 | ||
379 | beq 4f | ||
380 | |||
381 | /* Enable the cache */ | ||
382 | oris r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h | ||
383 | mtspr SPRN_L3CR,r3 | ||
384 | sync | ||
385 | |||
386 | /* Wait for stabilize */ | ||
387 | li r0,256 | ||
388 | mtctr r0 | ||
389 | 1: bdnz 1b | ||
390 | |||
391 | /* Restore MSR (restores EE and DR bits to original state) */ | ||
392 | 4: SYNC | ||
393 | mtmsr r7 | ||
394 | isync | ||
395 | blr | ||
396 | |||
397 | _GLOBAL(_get_L3CR) | ||
398 | /* Return the L3CR contents */ | ||
399 | li r3,0 | ||
400 | BEGIN_FTR_SECTION | ||
401 | mfspr r3,SPRN_L3CR | ||
402 | END_FTR_SECTION_IFSET(CPU_FTR_L3CR) | ||
403 | blr | ||
404 | |||
405 | /* --- End of PowerLogix code --- | ||
406 | */ | ||
407 | |||
408 | |||
409 | /* flush_disable_L1() - Flush and disable L1 cache | ||
410 | * | ||
411 | * clobbers r0, r3, ctr, cr0 | ||
412 | * Must be called with interrupts disabled and MMU enabled. | ||
413 | */ | ||
414 | _GLOBAL(__flush_disable_L1) | ||
415 | /* Stop pending alitvec streams and memory accesses */ | ||
416 | BEGIN_FTR_SECTION | ||
417 | DSSALL | ||
418 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
419 | sync | ||
420 | |||
421 | /* Load counter to 0x4000 cache lines (512k) and | ||
422 | * load cache with datas | ||
423 | */ | ||
424 | li r3,0x4000 /* 512kB / 32B */ | ||
425 | mtctr r3 | ||
426 | lis r3,KERNELBASE@h | ||
427 | 1: | ||
428 | lwz r0,0(r3) | ||
429 | addi r3,r3,0x0020 /* Go to start of next cache line */ | ||
430 | bdnz 1b | ||
431 | isync | ||
432 | sync | ||
433 | |||
434 | /* Now flush those cache lines */ | ||
435 | li r3,0x4000 /* 512kB / 32B */ | ||
436 | mtctr r3 | ||
437 | lis r3,KERNELBASE@h | ||
438 | 1: | ||
439 | dcbf 0,r3 | ||
440 | addi r3,r3,0x0020 /* Go to start of next cache line */ | ||
441 | bdnz 1b | ||
442 | sync | ||
443 | |||
444 | /* We can now disable the L1 cache (HID0:DCE, HID0:ICE) */ | ||
445 | mfspr r3,SPRN_HID0 | ||
446 | rlwinm r3,r3,0,18,15 | ||
447 | mtspr SPRN_HID0,r3 | ||
448 | sync | ||
449 | isync | ||
450 | blr | ||
451 | |||
452 | /* inval_enable_L1 - Invalidate and enable L1 cache | ||
453 | * | ||
454 | * Assumes L1 is already disabled and MSR:EE is off | ||
455 | * | ||
456 | * clobbers r3 | ||
457 | */ | ||
458 | _GLOBAL(__inval_enable_L1) | ||
459 | /* Enable and then Flash inval the instruction & data cache */ | ||
460 | mfspr r3,SPRN_HID0 | ||
461 | ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI | ||
462 | sync | ||
463 | isync | ||
464 | mtspr SPRN_HID0,r3 | ||
465 | xori r3,r3, HID0_ICFI|HID0_DCI | ||
466 | mtspr SPRN_HID0,r3 | ||
467 | sync | ||
468 | |||
469 | blr | ||
470 | |||
471 | |||