]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - arch/powerpc/platforms/powermac/cache.S
Remove obsolete #include <linux/config.h>
[mirror_ubuntu-jammy-kernel.git] / arch / powerpc / platforms / powermac / cache.S
1 /*
2 * This file contains low-level cache management functions
3 * used for sleep and CPU speed changes on Apple machines.
4 * (In fact the only thing that is Apple-specific is that we assume
5 * that we can read from ROM at physical address 0xfff00000.)
6 *
7 * Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and
8 * Benjamin Herrenschmidt (benh@kernel.crashing.org)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 *
15 */
16
17 #include <asm/processor.h>
18 #include <asm/ppc_asm.h>
19 #include <asm/cputable.h>
20
21 /*
22 * Flush and disable all data caches (dL1, L2, L3). This is used
23 * when going to sleep, when doing a PMU based cpufreq transition,
24 * or when "offlining" a CPU on SMP machines. This code is over
25 * paranoid, but I've had enough issues with various CPU revs and
26 * bugs that I decided it was worth beeing over cautious
27 */
28
29 _GLOBAL(flush_disable_caches)
30 #ifndef CONFIG_6xx
31 blr
32 #else
33 BEGIN_FTR_SECTION
34 b flush_disable_745x
35 END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
36 BEGIN_FTR_SECTION
37 b flush_disable_75x
38 END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
39 b __flush_disable_L1
40
41 /* This is the code for G3 and 74[01]0 */
42 flush_disable_75x:
43 mflr r10
44
45 /* Turn off EE and DR in MSR */
46 mfmsr r11
47 rlwinm r0,r11,0,~MSR_EE
48 rlwinm r0,r0,0,~MSR_DR
49 sync
50 mtmsr r0
51 isync
52
53 /* Stop DST streams */
54 BEGIN_FTR_SECTION
55 DSSALL
56 sync
57 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
58
59 /* Stop DPM */
60 mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */
61 rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */
62 sync
63 mtspr SPRN_HID0,r4 /* Disable DPM */
64 sync
65
66 /* Disp-flush L1. We have a weird problem here that I never
67 * totally figured out. On 750FX, using the ROM for the flush
68 * results in a non-working flush. We use that workaround for
69 * now until I finally understand what's going on. --BenH
70 */
71
72 /* ROM base by default */
73 lis r4,0xfff0
74 mfpvr r3
75 srwi r3,r3,16
76 cmplwi cr0,r3,0x7000
77 bne+ 1f
78 /* RAM base on 750FX */
79 li r4,0
80 1: li r4,0x4000
81 mtctr r4
82 1: lwz r0,0(r4)
83 addi r4,r4,32
84 bdnz 1b
85 sync
86 isync
87
88 /* Disable / invalidate / enable L1 data */
89 mfspr r3,SPRN_HID0
90 rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE)
91 mtspr SPRN_HID0,r3
92 sync
93 isync
94 ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI)
95 sync
96 isync
97 mtspr SPRN_HID0,r3
98 xori r3,r3,(HID0_DCI|HID0_ICFI)
99 mtspr SPRN_HID0,r3
100 sync
101
102 /* Get the current enable bit of the L2CR into r4 */
103 mfspr r5,SPRN_L2CR
104 /* Set to data-only (pre-745x bit) */
105 oris r3,r5,L2CR_L2DO@h
106 b 2f
107 /* When disabling L2, code must be in L1 */
108 .balign 32
109 1: mtspr SPRN_L2CR,r3
110 3: sync
111 isync
112 b 1f
113 2: b 3f
114 3: sync
115 isync
116 b 1b
117 1: /* disp-flush L2. The interesting thing here is that the L2 can be
118 * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory
119 * but that is probbaly fine. We disp-flush over 4Mb to be safe
120 */
121 lis r4,2
122 mtctr r4
123 lis r4,0xfff0
124 1: lwz r0,0(r4)
125 addi r4,r4,32
126 bdnz 1b
127 sync
128 isync
129 lis r4,2
130 mtctr r4
131 lis r4,0xfff0
132 1: dcbf 0,r4
133 addi r4,r4,32
134 bdnz 1b
135 sync
136 isync
137
138 /* now disable L2 */
139 rlwinm r5,r5,0,~L2CR_L2E
140 b 2f
141 /* When disabling L2, code must be in L1 */
142 .balign 32
143 1: mtspr SPRN_L2CR,r5
144 3: sync
145 isync
146 b 1f
147 2: b 3f
148 3: sync
149 isync
150 b 1b
151 1: sync
152 isync
153 /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */
154 oris r4,r5,L2CR_L2I@h
155 mtspr SPRN_L2CR,r4
156 sync
157 isync
158
159 /* Wait for the invalidation to complete */
160 1: mfspr r3,SPRN_L2CR
161 rlwinm. r0,r3,0,31,31
162 bne 1b
163
164 /* Clear L2I */
165 xoris r4,r4,L2CR_L2I@h
166 sync
167 mtspr SPRN_L2CR,r4
168 sync
169
170 /* now disable the L1 data cache */
171 mfspr r0,SPRN_HID0
172 rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE)
173 mtspr SPRN_HID0,r0
174 sync
175 isync
176
177 /* Restore HID0[DPM] to whatever it was before */
178 sync
179 mfspr r0,SPRN_HID0
180 rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */
181 mtspr SPRN_HID0,r0
182 sync
183
184 /* restore DR and EE */
185 sync
186 mtmsr r11
187 isync
188
189 mtlr r10
190 blr
191
192 /* This code is for 745x processors */
193 flush_disable_745x:
194 /* Turn off EE and DR in MSR */
195 mfmsr r11
196 rlwinm r0,r11,0,~MSR_EE
197 rlwinm r0,r0,0,~MSR_DR
198 sync
199 mtmsr r0
200 isync
201
202 /* Stop prefetch streams */
203 DSSALL
204 sync
205
206 /* Disable L2 prefetching */
207 mfspr r0,SPRN_MSSCR0
208 rlwinm r0,r0,0,0,29
209 mtspr SPRN_MSSCR0,r0
210 sync
211 isync
212 lis r4,0
213 dcbf 0,r4
214 dcbf 0,r4
215 dcbf 0,r4
216 dcbf 0,r4
217 dcbf 0,r4
218 dcbf 0,r4
219 dcbf 0,r4
220 dcbf 0,r4
221
222 /* Due to a bug with the HW flush on some CPU revs, we occasionally
223 * experience data corruption. I'm adding a displacement flush along
224 * with a dcbf loop over a few Mb to "help". The problem isn't totally
225 * fixed by this in theory, but at least, in practice, I couldn't reproduce
226 * it even with a big hammer...
227 */
228
229 lis r4,0x0002
230 mtctr r4
231 li r4,0
232 1:
233 lwz r0,0(r4)
234 addi r4,r4,32 /* Go to start of next cache line */
235 bdnz 1b
236 isync
237
238 /* Now, flush the first 4MB of memory */
239 lis r4,0x0002
240 mtctr r4
241 li r4,0
242 sync
243 1:
244 dcbf 0,r4
245 addi r4,r4,32 /* Go to start of next cache line */
246 bdnz 1b
247
248 /* Flush and disable the L1 data cache */
249 mfspr r6,SPRN_LDSTCR
250 lis r3,0xfff0 /* read from ROM for displacement flush */
251 li r4,0xfe /* start with only way 0 unlocked */
252 li r5,128 /* 128 lines in each way */
253 1: mtctr r5
254 rlwimi r6,r4,0,24,31
255 mtspr SPRN_LDSTCR,r6
256 sync
257 isync
258 2: lwz r0,0(r3) /* touch each cache line */
259 addi r3,r3,32
260 bdnz 2b
261 rlwinm r4,r4,1,24,30 /* move on to the next way */
262 ori r4,r4,1
263 cmpwi r4,0xff /* all done? */
264 bne 1b
265 /* now unlock the L1 data cache */
266 li r4,0
267 rlwimi r6,r4,0,24,31
268 sync
269 mtspr SPRN_LDSTCR,r6
270 sync
271 isync
272
273 /* Flush the L2 cache using the hardware assist */
274 mfspr r3,SPRN_L2CR
275 cmpwi r3,0 /* check if it is enabled first */
276 bge 4f
277 oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h
278 b 2f
279 /* When disabling/locking L2, code must be in L1 */
280 .balign 32
281 1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */
282 3: sync
283 isync
284 b 1f
285 2: b 3f
286 3: sync
287 isync
288 b 1b
289 1: sync
290 isync
291 ori r0,r3,L2CR_L2HWF_745x
292 sync
293 mtspr SPRN_L2CR,r0 /* set the hardware flush bit */
294 3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */
295 andi. r0,r0,L2CR_L2HWF_745x
296 bne 3b
297 sync
298 rlwinm r3,r3,0,~L2CR_L2E
299 b 2f
300 /* When disabling L2, code must be in L1 */
301 .balign 32
302 1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */
303 3: sync
304 isync
305 b 1f
306 2: b 3f
307 3: sync
308 isync
309 b 1b
310 1: sync
311 isync
312 oris r4,r3,L2CR_L2I@h
313 mtspr SPRN_L2CR,r4
314 sync
315 isync
316 1: mfspr r4,SPRN_L2CR
317 andis. r0,r4,L2CR_L2I@h
318 bne 1b
319 sync
320
321 BEGIN_FTR_SECTION
322 /* Flush the L3 cache using the hardware assist */
323 4: mfspr r3,SPRN_L3CR
324 cmpwi r3,0 /* check if it is enabled */
325 bge 6f
326 oris r0,r3,L3CR_L3IO@h
327 ori r0,r0,L3CR_L3DO
328 sync
329 mtspr SPRN_L3CR,r0 /* lock the L3 cache */
330 sync
331 isync
332 ori r0,r0,L3CR_L3HWF
333 sync
334 mtspr SPRN_L3CR,r0 /* set the hardware flush bit */
335 5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */
336 andi. r0,r0,L3CR_L3HWF
337 bne 5b
338 rlwinm r3,r3,0,~L3CR_L3E
339 sync
340 mtspr SPRN_L3CR,r3 /* disable the L3 cache */
341 sync
342 ori r4,r3,L3CR_L3I
343 mtspr SPRN_L3CR,r4
344 1: mfspr r4,SPRN_L3CR
345 andi. r0,r4,L3CR_L3I
346 bne 1b
347 sync
348 END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
349
350 6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */
351 rlwinm r0,r0,0,~HID0_DCE
352 mtspr SPRN_HID0,r0
353 sync
354 isync
355 mtmsr r11 /* restore DR and EE */
356 isync
357 blr
358 #endif /* CONFIG_6xx */