Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / ppc / kernel / l2cr.S
blobc39441048266f7ba918f3793f41fa8588267d309
1 /*
2         L2CR functions
3         Copyright © 1997-1998 by PowerLogix R & D, Inc.
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.
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.
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.
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.
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.
40         Author: Terry Greeniaus (tgree@phys.ualberta.ca)
41         Please e-mail updates to this file to me, thanks!
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>
50 /* Usage:
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:
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
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.
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
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)
107         mflr    r9
109         /* Stop DST streams */
110 BEGIN_FTR_SECTION
111         DSSALL
112         sync
113 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
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
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
134         /* Get the current enable bit of the L2CR into r4 */
135         mfspr   r4,SPRN_L2CR
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 */
142         /* Check to see if we need to flush */
143         rlwinm. r4,r4,0,0,0
144         beq     2f
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          */
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           ****/
159         /* TODO: use HW flush assist when available */
161         lis     r4,0x0002
162         mtctr   r4
163         li      r4,0
165         lwzx    r0,r0,r4
166         addi    r4,r4,32                /* Go to start of next cache line */
167         bdnz    1b
168         isync
170         /* Now, flush the first 4MB of memory */
171         lis     r4,0x0002
172         mtctr   r4
173         li      r4,0
174         sync
176         dcbf    0,r4
177         addi    r4,r4,32                /* Go to start of next cache line */
178         bdnz    1b
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
188         sync
189         mtspr   SPRN_L2CR,r3
190         sync
191         b       23f
193         b       21f
194 21:     sync
195         isync
196         b       22b
199         /* Perform a global invalidation */
200         oris    r3,r3,0x0020
201         sync
202         mtspr   SPRN_L2CR,r3
203         sync
204         isync                           /* For errata */
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)
215         /* Wait for the invalidation to complete */
216 3:      mfspr   r3,SPRN_L2CR
217         rlwinm. r4,r3,0,31,31
218         bne     3b
220 11:     rlwinm  r3,r3,0,11,9            /* Turn off the L2I bit */
221         sync
222         mtspr   SPRN_L2CR,r3
223         sync
225         /* See if we need to enable the cache */
226         cmplwi  r5,0
227         beq     4f
229         /* Enable the cache */
230         oris    r3,r3,0x8000
231         mtspr   SPRN_L2CR,r3
232         sync
236         /* Restore HID0[DPM] to whatever it was before */
237         sync
238         mtspr   1008,r8
239         sync
241         /* Restore MSR (restores EE and DR bits to original state) */
242         SYNC
243         mtmsr   r7
244         isync
246         mtlr    r9
247         blr
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
259  * Here is a similar routine for dealing with the L3 cache
260  * on the 745x family of chips
261  */
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)
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
278         /* Stop DST streams */
279         DSSALL
280         sync
282         /* Get the current enable bit of the L3CR into r4 */
283         mfspr   r4,SPRN_L3CR
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
294         /* Flush the cache.
295          */
297         /* TODO: use HW flush assist */
299         lis     r4,0x0008
300         mtctr   r4
301         li      r4,0
303         lwzx    r0,r0,r4
304         dcbf    0,r4
305         addi    r4,r4,32                /* Go to start of next cache line */
306         bdnz    1b
309         /* Set up the L3CR configuration bits (and switch L3 off) */
310         sync
311         mtspr   SPRN_L3CR,r3
312         sync
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
321         /* Wait for stabilize */
322         li      r0,256
323         mtctr   r0
324 1:      bdnz    1b
326         /* Perform a global invalidation */
327         ori     r3,r3,0x0400
328         sync
329         mtspr   SPRN_L3CR,r3
330         sync
331         isync
333         /* We wait for the L3I bit to clear...... */
334 10:     mfspr   r3,SPRN_L3CR
335         andi.   r4,r3,0x0400
336         bne     10b
338         /* Clear CLKEN */
339         rlwinm  r3,r3,0,5,3             /* Turn off the clken bit */
340         mtspr   SPRN_L3CR,r3
341         sync
343         /* Wait for stabilize */
344         li      r0,256
345         mtctr   r0
346 1:      bdnz    1b
348         /* See if we need to enable the cache */
349         cmplwi  r5,0
350         beq     4f
352         /* Enable the cache */
353         oris    r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h
354         mtspr   SPRN_L3CR,r3
355         sync
357         /* Wait for stabilize */
358         li      r0,256
359         mtctr   r0
360 1:      bdnz    1b
362         /* Restore MSR (restores EE and DR bits to original state) */
363 4:      SYNC
364         mtmsr   r7
365         isync
366         blr
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
376 /* --- End of PowerLogix code ---
377  */
380 /* flush_disable_L1()   - Flush and disable L1 cache
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
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
399         lwz     r0,0(r3)
400         addi    r3,r3,0x0020    /* Go to start of next cache line */
401         bdnz    1b
402         isync
403         sync
405         /* Now flush those cache lines */
406         li      r3,0x4000       /* 512kB / 32B */
407         mtctr   r3
408         lis     r3,KERNELBASE@h
410         dcbf    0,r3
411         addi    r3,r3,0x0020    /* Go to start of next cache line */
412         bdnz    1b
413         sync
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
423 /* inval_enable_L1      - Invalidate and enable L1 cache
425  * Assumes L1 is already disabled and MSR:EE is off
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
440         blr