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