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