blob: f316b3ec13fe59ea4012714d58617b82e12f7d66 [file] [log] [blame]
Jon Loeligerdebb7352006-04-26 17:58:56 -05001#include <config.h>
2#include <mpc86xx.h>
3#include <version.h>
4
5#include <ppc_asm.tmpl>
6#include <ppc_defs.h>
7
8#include <asm/cache.h>
9#include <asm/mmu.h>
10
11#ifndef CACHE_LINE_SIZE
12# define CACHE_LINE_SIZE L1_CACHE_BYTES
13#endif
14
15#if CACHE_LINE_SIZE == 128
16#define LG_CACHE_LINE_SIZE 7
17#elif CACHE_LINE_SIZE == 32
18#define LG_CACHE_LINE_SIZE 5
19#elif CACHE_LINE_SIZE == 16
20#define LG_CACHE_LINE_SIZE 4
21#elif CACHE_LINE_SIZE == 8
22#define LG_CACHE_LINE_SIZE 3
23#else
24# error "Invalid cache line size!"
25#endif
26
27/*
28 * Most of this code is taken from 74xx_7xx/cache.S
29 * and then cleaned up a bit
30 */
Jon Loeligercccce5d2006-05-19 13:14:15 -050031
Jon Loeligerdebb7352006-04-26 17:58:56 -050032/*
33 * Invalidate L1 instruction cache.
34 */
35_GLOBAL(invalidate_l1_instruction_cache)
36 /* use invalidate-all bit in HID0 */
37 mfspr r3,HID0
38 ori r3,r3,HID0_ICFI
39 mtspr HID0,r3
40 isync
41 blr
42
43/*
44 * Invalidate L1 data cache.
45 */
46_GLOBAL(invalidate_l1_data_cache)
47 mfspr r3,HID0
48 ori r3,r3,HID0_DCFI
49 mtspr HID0,r3
50 isync
51 blr
52
53/*
54 * Flush data cache.
55 */
56_GLOBAL(flush_data_cache)
57 lis r3,0
58 lis r5,CACHE_LINE_SIZE
59flush:
60 cmp 0,1,r3,r5
61 bge done
62 lwz r5,0(r3)
63 lis r5,CACHE_LINE_SIZE
64 addi r3,r3,0x4
65 b flush
66done:
67 blr
68/*
69 * Write any modified data cache blocks out to memory
70 * and invalidate the corresponding instruction cache blocks.
71 * This is a no-op on the 601.
72 *
73 * flush_icache_range(unsigned long start, unsigned long stop)
74 */
75_GLOBAL(flush_icache_range)
76 li r5,CACHE_LINE_SIZE-1
77 andc r3,r3,r5
78 subf r4,r3,r4
79 add r4,r4,r5
80 srwi. r4,r4,LG_CACHE_LINE_SIZE
81 beqlr
82 mtctr r4
83 mr r6,r3
841: dcbst 0,r3
85 addi r3,r3,CACHE_LINE_SIZE
86 bdnz 1b
87 sync /* wait for dcbst's to get to ram */
88 mtctr r4
892: icbi 0,r6
90 addi r6,r6,CACHE_LINE_SIZE
91 bdnz 2b
92 sync /* additional sync needed on g4 */
93 isync
94 blr
95/*
96 * Write any modified data cache blocks out to memory.
97 * Does not invalidate the corresponding cache lines (especially for
98 * any corresponding instruction cache).
99 *
100 * clean_dcache_range(unsigned long start, unsigned long stop)
101 */
102_GLOBAL(clean_dcache_range)
103 li r5,CACHE_LINE_SIZE-1
104 andc r3,r3,r5 /* align r3 down to cache line */
105 subf r4,r3,r4 /* r4 = offset of stop from start of cache line */
106 add r4,r4,r5 /* r4 += cache_line_size-1 */
107 srwi. r4,r4,LG_CACHE_LINE_SIZE /* r4 = number of cache lines to flush */
108 beqlr /* if r4 == 0 return */
109 mtctr r4 /* ctr = r4 */
110
111 sync
1121: dcbst 0,r3
113 addi r3,r3,CACHE_LINE_SIZE
114 bdnz 1b
115 sync /* wait for dcbst's to get to ram */
116 blr
117
118/*
119 * Write any modified data cache blocks out to memory
120 * and invalidate the corresponding instruction cache blocks.
121 *
122 * flush_dcache_range(unsigned long start, unsigned long stop)
123 */
124_GLOBAL(flush_dcache_range)
125 li r5,CACHE_LINE_SIZE-1
126 andc r3,r3,r5
127 subf r4,r3,r4
128 add r4,r4,r5
129 srwi. r4,r4,LG_CACHE_LINE_SIZE
130 beqlr
131 mtctr r4
132
133 sync
1341: dcbf 0,r3
135 addi r3,r3,CACHE_LINE_SIZE
136 bdnz 1b
137 sync /* wait for dcbf's to get to ram */
138 blr
139
140/*
141 * Like above, but invalidate the D-cache. This is used by the 8xx
142 * to invalidate the cache so the PPC core doesn't get stale data
143 * from the CPM (no cache snooping here :-).
144 *
145 * invalidate_dcache_range(unsigned long start, unsigned long stop)
146 */
147_GLOBAL(invalidate_dcache_range)
148 li r5,CACHE_LINE_SIZE-1
149 andc r3,r3,r5
150 subf r4,r3,r4
151 add r4,r4,r5
152 srwi. r4,r4,LG_CACHE_LINE_SIZE
153 beqlr
154 mtctr r4
155
156 sync
1571: dcbi 0,r3
158 addi r3,r3,CACHE_LINE_SIZE
159 bdnz 1b
160 sync /* wait for dcbi's to get to ram */
161 blr
162
163/*
164 * Flush a particular page from the data cache to RAM.
165 * Note: this is necessary because the instruction cache does *not*
166 * snoop from the data cache.
167 *
168 * void __flush_page_to_ram(void *page)
169 */
170_GLOBAL(__flush_page_to_ram)
171 rlwinm r3,r3,0,0,19 /* Get page base address */
172 li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
173 mtctr r4
174 mr r6,r3
1750: dcbst 0,r3 /* Write line to ram */
176 addi r3,r3,CACHE_LINE_SIZE
177 bdnz 0b
178 sync
179 mtctr r4
1801: icbi 0,r6
181 addi r6,r6,CACHE_LINE_SIZE
182 bdnz 1b
183 sync
184 isync
185 blr
186
187/*
188 * Flush a particular page from the instruction cache.
189 * Note: this is necessary because the instruction cache does *not*
190 * snoop from the data cache.
191 *
192 * void __flush_icache_page(void *page)
193 */
194_GLOBAL(__flush_icache_page)
195 li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
196 mtctr r4
1971: icbi 0,r3
198 addi r3,r3,CACHE_LINE_SIZE
199 bdnz 1b
200 sync
201 isync
202 blr
203
204/*
205 * Clear a page using the dcbz instruction, which doesn't cause any
206 * memory traffic (except to write out any cache lines which get
207 * displaced). This only works on cacheable memory.
208 */
209_GLOBAL(clear_page)
210 li r0,4096/CACHE_LINE_SIZE
211 mtctr r0
2121: dcbz 0,r3
213 addi r3,r3,CACHE_LINE_SIZE
214 bdnz 1b
215 blr
216
217/*
218 * Enable L1 Instruction cache
219 */
220_GLOBAL(icache_enable)
221 mfspr r3, HID0
222 li r5, HID0_ICFI|HID0_ILOCK
223 andc r3, r3, r5
224 ori r3, r3, HID0_ICE
225 ori r5, r3, HID0_ICFI
226 mtspr HID0, r5
227 mtspr HID0, r3
228 isync
229 blr
230
231/*
232 * Disable L1 Instruction cache
233 */
234_GLOBAL(icache_disable)
235 mfspr r3, HID0
236 li r5, 0
237 ori r5, r5, HID0_ICE
238 andc r3, r3, r5
239 mtspr HID0, r3
240 isync
241 blr
242
243/*
244 * Is instruction cache enabled?
245 */
246_GLOBAL(icache_status)
247 mfspr r3, HID0
248 andi. r3, r3, HID0_ICE
249 blr
250
251
252_GLOBAL(l1dcache_enable)
253 mfspr r3, HID0
254 li r5, HID0_DCFI|HID0_DLOCK
255 andc r3, r3, r5
256 mtspr HID0, r3 /* no invalidate, unlock */
257 ori r3, r3, HID0_DCE
258 ori r5, r3, HID0_DCFI
259 mtspr HID0, r5 /* enable + invalidate */
260 mtspr HID0, r3 /* enable */
261 sync
262 blr
263
264/*
265 * Enable data cache(s) - L1 and optionally L2
266 * Calls l2cache_enable. LR saved in r5
267 */
268_GLOBAL(dcache_enable)
269 mfspr r3, HID0
270 li r5, HID0_DCFI|HID0_DLOCK
271 andc r3, r3, r5
272 mtspr HID0, r3 /* no invalidate, unlock */
273 ori r3, r3, HID0_DCE
274 ori r5, r3, HID0_DCFI
275 mtspr HID0, r5 /* enable + invalidate */
276 mtspr HID0, r3 /* enable */
277 sync
278#ifdef CFG_L2
279 mflr r5
280 bl l2cache_enable /* uses r3 and r4 */
281 sync
282 mtlr r5
283#endif
284 blr
285
286
287/*
288 * Disable data cache(s) - L1 and optionally L2
289 * Calls flush_data_cache and l2cache_disable_no_flush.
290 * LR saved in r4
291 */
292_GLOBAL(dcache_disable)
293 mflr r4 /* save link register */
294 bl flush_data_cache /* uses r3 and r5 */
295 sync
296 mfspr r3, HID0
297 li r5, HID0_DCFI|HID0_DLOCK
298 andc r3, r3, r5
299 mtspr HID0, r3 /* no invalidate, unlock */
300 li r5, HID0_DCE|HID0_DCFI
301 andc r3, r3, r5 /* no enable, no invalidate */
302 mtspr HID0, r3
303 sync
304#ifdef CFG_L2
305 bl l2cache_disable_no_flush /* uses r3 */
306#endif
307 mtlr r4 /* restore link register */
308 blr
309
310/*
311 * Is data cache enabled?
312 */
313_GLOBAL(dcache_status)
314 mfspr r3, HID0
315 andi. r3, r3, HID0_DCE
316 blr
317
318/*
Jon Loeligercccce5d2006-05-19 13:14:15 -0500319 * Invalidate L2 cache using L2I, assume L2 is enabled
Jon Loeligerdebb7352006-04-26 17:58:56 -0500320 */
321_GLOBAL(l2cache_invalidate)
Jon Loeligercccce5d2006-05-19 13:14:15 -0500322 mfspr r3, l2cr
323 rlwinm. r3, r3, 0, 0, 0
324 beq 1f
325
326 mfspr r3, l2cr
327 rlwinm r3, r3, 0, 1, 31
328
329#ifdef CONFIG_ALTIVEC
330 dssall
331#endif
Jon Loeligerdebb7352006-04-26 17:58:56 -0500332 sync
333 mtspr l2cr, r3
334 sync
Jon Loeligercccce5d2006-05-19 13:14:15 -05003351: mfspr r3, l2cr
336 oris r3, r3, L2CR_L2I@h
337 mtspr l2cr, r3
338
Jon Loeligerdebb7352006-04-26 17:58:56 -0500339invl2:
340 mfspr r3, l2cr
Jon Loeligercccce5d2006-05-19 13:14:15 -0500341 andi. r3, r3, L2CR_L2I@h
Jon Loeligerdebb7352006-04-26 17:58:56 -0500342 bne invl2
Jon Loeligerdebb7352006-04-26 17:58:56 -0500343 blr
344
345/*
346 * Enable L2 cache
347 * Calls l2cache_invalidate. LR is saved in r4
348 */
349_GLOBAL(l2cache_enable)
350 mflr r4 /* save link register */
351 bl l2cache_invalidate /* uses r3 */
352 sync
353 lis r3, L2_ENABLE@h
354 ori r3, r3, L2_ENABLE@l
355 mtspr l2cr, r3
356 isync
357 mtlr r4 /* restore link register */
358 blr
359
360/*
361 * Disable L2 cache
362 * Calls flush_data_cache. LR is saved in r4
363 */
364_GLOBAL(l2cache_disable)
365 mflr r4 /* save link register */
366 bl flush_data_cache /* uses r3 and r5 */
367 sync
368 mtlr r4 /* restore link register */
369l2cache_disable_no_flush: /* provide way to disable L2 w/o flushing */
370 lis r3, L2_INIT@h
371 ori r3, r3, L2_INIT@l
372 mtspr l2cr, r3
373 isync
374 blr