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