Pull novell-bugzilla-156426 into release branch
[pandora-kernel.git] / arch / powerpc / kernel / l2cr_6xx.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 #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