ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / include / asm-mips / r4kcache.h
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Inline assembly cache operations.
7  *
8  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
9  * Copyright (C) 1997 - 2002 Ralf Baechle (ralf@gnu.org)
10  * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
11  */
12 #ifndef _ASM_R4KCACHE_H
13 #define _ASM_R4KCACHE_H
14
15 #include <asm/asm.h>
16 #include <asm/cacheops.h>
17
18 /*
19  * This macro return a properly sign-extended address suitable as base address
20  * for indexed cache operations.  Two issues here:
21  *
22  *  - The MIPS32 and MIPS64 specs permit an implementation to directly derive
23  *    the index bits from the virtual address.  This breaks with tradition
24  *    set by the R4000.  To keep unpleassant surprises from happening we pick
25  *    an address in KSEG0 / CKSEG0.
26  *  - We need a properly sign extended address for 64-bit code.  To get away
27  *    without ifdefs we let the compiler do it by a type cast.
28  */
29 #define INDEX_BASE      ((int) KSEG0)
30
31 #define cache_op(op,addr)                                               \
32         __asm__ __volatile__(                                           \
33         "       .set    noreorder                               \n"     \
34         "       .set    mips3\n\t                               \n"     \
35         "       cache   %0, %1                                  \n"     \
36         "       .set    mips0                                   \n"     \
37         "       .set    reorder"                                        \
38         :                                                               \
39         : "i" (op), "m" (*(unsigned char *)(addr)))
40
41 static inline void flush_icache_line_indexed(unsigned long addr)
42 {
43         cache_op(Index_Invalidate_I, addr);
44 }
45
46 static inline void flush_dcache_line_indexed(unsigned long addr)
47 {
48         cache_op(Index_Writeback_Inv_D, addr);
49 }
50
51 static inline void flush_scache_line_indexed(unsigned long addr)
52 {
53         cache_op(Index_Writeback_Inv_SD, addr);
54 }
55
56 static inline void flush_icache_line(unsigned long addr)
57 {
58         cache_op(Hit_Invalidate_I, addr);
59 }
60
61 static inline void flush_dcache_line(unsigned long addr)
62 {
63         cache_op(Hit_Writeback_Inv_D, addr);
64 }
65
66 static inline void invalidate_dcache_line(unsigned long addr)
67 {
68         cache_op(Hit_Invalidate_D, addr);
69 }
70
71 static inline void invalidate_scache_line(unsigned long addr)
72 {
73         cache_op(Hit_Invalidate_SD, addr);
74 }
75
76 static inline void flush_scache_line(unsigned long addr)
77 {
78         cache_op(Hit_Writeback_Inv_SD, addr);
79 }
80
81 /*
82  * The next two are for badland addresses like signal trampolines.
83  */
84 static inline void protected_flush_icache_line(unsigned long addr)
85 {
86         __asm__ __volatile__(
87                 ".set noreorder\n\t"
88                 ".set mips3\n"
89                 "1:\tcache %0,(%1)\n"
90                 "2:\t.set mips0\n\t"
91                 ".set reorder\n\t"
92                 ".section\t__ex_table,\"a\"\n\t"
93                 STR(PTR)"\t1b,2b\n\t"
94                 ".previous"
95                 :
96                 : "i" (Hit_Invalidate_I), "r" (addr));
97 }
98
99 /*
100  * R10000 / R12000 hazard - these processors don't support the Hit_Writeback_D
101  * cacheop so we use Hit_Writeback_Inv_D which is supported by all R4000-style
102  * caches.  We're talking about one cacheline unnecessarily getting invalidated
103  * here so the penaltiy isn't overly hard.
104  */
105 static inline void protected_writeback_dcache_line(unsigned long addr)
106 {
107         __asm__ __volatile__(
108                 ".set noreorder\n\t"
109                 ".set mips3\n"
110                 "1:\tcache %0,(%1)\n"
111                 "2:\t.set mips0\n\t"
112                 ".set reorder\n\t"
113                 ".section\t__ex_table,\"a\"\n\t"
114                 STR(PTR)"\t1b,2b\n\t"
115                 ".previous"
116                 :
117                 : "i" (Hit_Writeback_Inv_D), "r" (addr));
118 }
119
120 /*
121  * This one is RM7000-specific
122  */
123 static inline void invalidate_tcache_page(unsigned long addr)
124 {
125         cache_op(Page_Invalidate_T, addr);
126 }
127
128 #define cache16_unroll32(base,op)                                       \
129         __asm__ __volatile__(                                           \
130         "       .set noreorder                                  \n"     \
131         "       .set mips3                                      \n"     \
132         "       cache %1, 0x000(%0); cache %1, 0x010(%0)        \n"     \
133         "       cache %1, 0x020(%0); cache %1, 0x030(%0)        \n"     \
134         "       cache %1, 0x040(%0); cache %1, 0x050(%0)        \n"     \
135         "       cache %1, 0x060(%0); cache %1, 0x070(%0)        \n"     \
136         "       cache %1, 0x080(%0); cache %1, 0x090(%0)        \n"     \
137         "       cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)        \n"     \
138         "       cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)        \n"     \
139         "       cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)        \n"     \
140         "       cache %1, 0x100(%0); cache %1, 0x110(%0)        \n"     \
141         "       cache %1, 0x120(%0); cache %1, 0x130(%0)        \n"     \
142         "       cache %1, 0x140(%0); cache %1, 0x150(%0)        \n"     \
143         "       cache %1, 0x160(%0); cache %1, 0x170(%0)        \n"     \
144         "       cache %1, 0x180(%0); cache %1, 0x190(%0)        \n"     \
145         "       cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)        \n"     \
146         "       cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)        \n"     \
147         "       cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)        \n"     \
148         "       .set mips0                                      \n"     \
149         "       .set reorder                                    \n"     \
150                 :                                                       \
151                 : "r" (base),                                           \
152                   "i" (op));
153
154 static inline void blast_dcache16(void)
155 {
156         unsigned long start = INDEX_BASE;
157         unsigned long end = start + current_cpu_data.dcache.waysize;
158         unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
159         unsigned long ws_end = current_cpu_data.dcache.ways << 
160                                current_cpu_data.dcache.waybit;
161         unsigned long ws, addr;
162
163         for (ws = 0; ws < ws_end; ws += ws_inc) 
164                 for (addr = start; addr < end; addr += 0x200)
165                         cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
166 }
167
168 static inline void blast_dcache16_page(unsigned long page)
169 {
170         unsigned long start = page;
171         unsigned long end = start + PAGE_SIZE;
172
173         do {
174                 cache16_unroll32(start,Hit_Writeback_Inv_D);
175                 start += 0x200;
176         } while (start < end);
177 }
178
179 static inline void blast_dcache16_page_indexed(unsigned long page)
180 {
181         unsigned long start = page;
182         unsigned long end = start + PAGE_SIZE;
183         unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
184         unsigned long ws_end = current_cpu_data.dcache.ways <<
185                                current_cpu_data.dcache.waybit;
186         unsigned long ws, addr;
187
188         for (ws = 0; ws < ws_end; ws += ws_inc) 
189                 for (addr = start; addr < end; addr += 0x200) 
190                         cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
191 }
192
193 static inline void blast_icache16(void)
194 {
195         unsigned long start = INDEX_BASE;
196         unsigned long end = start + current_cpu_data.icache.waysize;
197         unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
198         unsigned long ws_end = current_cpu_data.icache.ways <<
199                                current_cpu_data.icache.waybit;
200         unsigned long ws, addr;
201
202         for (ws = 0; ws < ws_end; ws += ws_inc) 
203                 for (addr = start; addr < end; addr += 0x200) 
204                         cache16_unroll32(addr|ws,Index_Invalidate_I);
205 }
206
207 static inline void blast_icache16_page(unsigned long page)
208 {
209         unsigned long start = page;
210         unsigned long end = start + PAGE_SIZE;
211
212         do {
213                 cache16_unroll32(start,Hit_Invalidate_I);
214                 start += 0x200;
215         } while (start < end);
216 }
217
218 static inline void blast_icache16_page_indexed(unsigned long page)
219 {
220         unsigned long start = page;
221         unsigned long end = start + PAGE_SIZE;
222         unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
223         unsigned long ws_end = current_cpu_data.icache.ways <<
224                                current_cpu_data.icache.waybit;
225         unsigned long ws, addr;
226
227         for (ws = 0; ws < ws_end; ws += ws_inc) 
228                 for (addr = start; addr < end; addr += 0x200) 
229                         cache16_unroll32(addr|ws,Index_Invalidate_I);
230 }
231
232 static inline void blast_scache16(void)
233 {
234         unsigned long start = INDEX_BASE;
235         unsigned long end = start + current_cpu_data.scache.waysize;
236         unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
237         unsigned long ws_end = current_cpu_data.scache.ways << 
238                                current_cpu_data.scache.waybit;
239         unsigned long ws, addr;
240
241         for (ws = 0; ws < ws_end; ws += ws_inc) 
242                 for (addr = start; addr < end; addr += 0x200)
243                         cache16_unroll32(addr|ws,Index_Writeback_Inv_SD);
244 }
245
246 static inline void blast_scache16_page(unsigned long page)
247 {
248         unsigned long start = page;
249         unsigned long end = page + PAGE_SIZE;
250
251         do {
252                 cache16_unroll32(start,Hit_Writeback_Inv_SD);
253                 start += 0x200;
254         } while (start < end);
255 }
256
257 static inline void blast_scache16_page_indexed(unsigned long page)
258 {
259         unsigned long start = page;
260         unsigned long end = start + PAGE_SIZE;
261         unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
262         unsigned long ws_end = current_cpu_data.scache.ways <<
263                                current_cpu_data.scache.waybit;
264         unsigned long ws, addr;
265
266         for (ws = 0; ws < ws_end; ws += ws_inc) 
267                 for (addr = start; addr < end; addr += 0x200) 
268                         cache16_unroll32(addr|ws,Index_Writeback_Inv_SD);
269 }
270
271 #define cache32_unroll32(base,op)                                       \
272         __asm__ __volatile__(                                           \
273         "       .set noreorder                                  \n"     \
274         "       .set mips3                                      \n"     \
275         "       cache %1, 0x000(%0); cache %1, 0x020(%0)        \n"     \
276         "       cache %1, 0x040(%0); cache %1, 0x060(%0)        \n"     \
277         "       cache %1, 0x080(%0); cache %1, 0x0a0(%0)        \n"     \
278         "       cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)        \n"     \
279         "       cache %1, 0x100(%0); cache %1, 0x120(%0)        \n"     \
280         "       cache %1, 0x140(%0); cache %1, 0x160(%0)        \n"     \
281         "       cache %1, 0x180(%0); cache %1, 0x1a0(%0)        \n"     \
282         "       cache %1, 0x1c0(%0); cache %1, 0x1e0(%0)        \n"     \
283         "       cache %1, 0x200(%0); cache %1, 0x220(%0)        \n"     \
284         "       cache %1, 0x240(%0); cache %1, 0x260(%0)        \n"     \
285         "       cache %1, 0x280(%0); cache %1, 0x2a0(%0)        \n"     \
286         "       cache %1, 0x2c0(%0); cache %1, 0x2e0(%0)        \n"     \
287         "       cache %1, 0x300(%0); cache %1, 0x320(%0)        \n"     \
288         "       cache %1, 0x340(%0); cache %1, 0x360(%0)        \n"     \
289         "       cache %1, 0x380(%0); cache %1, 0x3a0(%0)        \n"     \
290         "       cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)        \n"     \
291         "       .set mips0                                      \n"     \
292         "       .set reorder                                    \n"     \
293                 :                                                       \
294                 : "r" (base),                                           \
295                   "i" (op));
296
297 static inline void blast_dcache32(void)
298 {
299         unsigned long start = INDEX_BASE;
300         unsigned long end = start + current_cpu_data.dcache.waysize;
301         unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
302         unsigned long ws_end = current_cpu_data.dcache.ways <<
303                                current_cpu_data.dcache.waybit;
304         unsigned long ws, addr;
305
306         for (ws = 0; ws < ws_end; ws += ws_inc) 
307                 for (addr = start; addr < end; addr += 0x400) 
308                         cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
309 }
310
311 static inline void blast_dcache32_page(unsigned long page)
312 {
313         unsigned long start = page;
314         unsigned long end = start + PAGE_SIZE;
315
316         do {
317                 cache32_unroll32(start,Hit_Writeback_Inv_D);
318                 start += 0x400;
319         } while (start < end);
320 }
321
322 static inline void blast_dcache32_page_indexed(unsigned long page)
323 {
324         unsigned long start = page;
325         unsigned long end = start + PAGE_SIZE;
326         unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
327         unsigned long ws_end = current_cpu_data.dcache.ways <<
328                                current_cpu_data.dcache.waybit;
329         unsigned long ws, addr;
330
331         for (ws = 0; ws < ws_end; ws += ws_inc) 
332                 for (addr = start; addr < end; addr += 0x400) 
333                         cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
334 }
335
336 static inline void blast_icache32(void)
337 {
338         unsigned long start = INDEX_BASE;
339         unsigned long end = start + current_cpu_data.icache.waysize;
340         unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
341         unsigned long ws_end = current_cpu_data.icache.ways <<
342                                current_cpu_data.icache.waybit;
343         unsigned long ws, addr;
344
345         for (ws = 0; ws < ws_end; ws += ws_inc) 
346                 for (addr = start; addr < end; addr += 0x400) 
347                         cache32_unroll32(addr|ws,Index_Invalidate_I);
348 }
349
350 static inline void blast_icache32_page(unsigned long page)
351 {
352         unsigned long start = page;
353         unsigned long end = start + PAGE_SIZE;
354
355         do {
356                 cache32_unroll32(start,Hit_Invalidate_I);
357                 start += 0x400;
358         } while (start < end);
359 }
360
361 static inline void blast_icache32_page_indexed(unsigned long page)
362 {
363         unsigned long start = page;
364         unsigned long end = start + PAGE_SIZE;
365         unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
366         unsigned long ws_end = current_cpu_data.icache.ways <<
367                                current_cpu_data.icache.waybit;
368         unsigned long ws, addr;
369
370         for (ws = 0; ws < ws_end; ws += ws_inc)
371                 for (addr = start; addr < end; addr += 0x400) 
372                         cache32_unroll32(addr|ws,Index_Invalidate_I);
373 }
374
375 static inline void blast_scache32(void)
376 {
377         unsigned long start = INDEX_BASE;
378         unsigned long end = start + current_cpu_data.scache.waysize;
379         unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
380         unsigned long ws_end = current_cpu_data.scache.ways << 
381                                current_cpu_data.scache.waybit;
382         unsigned long ws, addr;
383
384         for (ws = 0; ws < ws_end; ws += ws_inc) 
385                 for (addr = start; addr < end; addr += 0x400)
386                         cache32_unroll32(addr|ws,Index_Writeback_Inv_SD);
387 }
388
389 static inline void blast_scache32_page(unsigned long page)
390 {
391         unsigned long start = page;
392         unsigned long end = page + PAGE_SIZE;
393
394         do {
395                 cache32_unroll32(start,Hit_Writeback_Inv_SD);
396                 start += 0x400;
397         } while (start < end);
398 }
399
400 static inline void blast_scache32_page_indexed(unsigned long page)
401 {
402         unsigned long start = page;
403         unsigned long end = start + PAGE_SIZE;
404         unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
405         unsigned long ws_end = current_cpu_data.scache.ways <<
406                                current_cpu_data.scache.waybit;
407         unsigned long ws, addr;
408
409         for (ws = 0; ws < ws_end; ws += ws_inc) 
410                 for (addr = start; addr < end; addr += 0x400) 
411                         cache32_unroll32(addr|ws,Index_Writeback_Inv_SD);
412 }
413
414 #define cache64_unroll32(base,op)                                       \
415         __asm__ __volatile__(                                           \
416         "       .set noreorder                                  \n"     \
417         "       .set mips3                                      \n"     \
418         "       cache %1, 0x000(%0); cache %1, 0x040(%0)        \n"     \
419         "       cache %1, 0x080(%0); cache %1, 0x0c0(%0)        \n"     \
420         "       cache %1, 0x100(%0); cache %1, 0x140(%0)        \n"     \
421         "       cache %1, 0x180(%0); cache %1, 0x1c0(%0)        \n"     \
422         "       cache %1, 0x200(%0); cache %1, 0x240(%0)        \n"     \
423         "       cache %1, 0x280(%0); cache %1, 0x2c0(%0)        \n"     \
424         "       cache %1, 0x300(%0); cache %1, 0x340(%0)        \n"     \
425         "       cache %1, 0x380(%0); cache %1, 0x3c0(%0)        \n"     \
426         "       cache %1, 0x400(%0); cache %1, 0x440(%0)        \n"     \
427         "       cache %1, 0x480(%0); cache %1, 0x4c0(%0)        \n"     \
428         "       cache %1, 0x500(%0); cache %1, 0x540(%0)        \n"     \
429         "       cache %1, 0x580(%0); cache %1, 0x5c0(%0)        \n"     \
430         "       cache %1, 0x600(%0); cache %1, 0x640(%0)        \n"     \
431         "       cache %1, 0x680(%0); cache %1, 0x6c0(%0)        \n"     \
432         "       cache %1, 0x700(%0); cache %1, 0x740(%0)        \n"     \
433         "       cache %1, 0x780(%0); cache %1, 0x7c0(%0)        \n"     \
434         "       .set mips0                                      \n"     \
435         "       .set reorder                                    \n"     \
436                 :                                                       \
437                 : "r" (base),                                           \
438                   "i" (op));
439
440 static inline void blast_icache64(void)
441 {
442         unsigned long start = INDEX_BASE;
443         unsigned long end = start + current_cpu_data.icache.waysize;
444         unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
445         unsigned long ws_end = current_cpu_data.icache.ways <<
446                                current_cpu_data.icache.waybit;
447         unsigned long ws, addr;
448
449         for (ws = 0; ws < ws_end; ws += ws_inc) 
450                 for (addr = start; addr < end; addr += 0x800) 
451                         cache64_unroll32(addr|ws,Index_Invalidate_I);
452 }
453
454 static inline void blast_icache64_page(unsigned long page)
455 {
456         unsigned long start = page;
457         unsigned long end = start + PAGE_SIZE;
458
459         do {
460                 cache64_unroll32(start,Hit_Invalidate_I);
461                 start += 0x800;
462         } while (start < end);
463 }
464
465 static inline void blast_icache64_page_indexed(unsigned long page)
466 {
467         unsigned long start = page;
468         unsigned long end = start + PAGE_SIZE;
469         unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
470         unsigned long ws_end = current_cpu_data.icache.ways <<
471                                current_cpu_data.icache.waybit;
472         unsigned long ws, addr;
473
474         for (ws = 0; ws < ws_end; ws += ws_inc)
475                 for (addr = start; addr < end; addr += 0x800) 
476                         cache64_unroll32(addr|ws,Index_Invalidate_I);
477 }
478
479 static inline void blast_scache64(void)
480 {
481         unsigned long start = INDEX_BASE;
482         unsigned long end = start + current_cpu_data.scache.waysize;
483         unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
484         unsigned long ws_end = current_cpu_data.scache.ways << 
485                                current_cpu_data.scache.waybit;
486         unsigned long ws, addr;
487
488         for (ws = 0; ws < ws_end; ws += ws_inc) 
489                 for (addr = start; addr < end; addr += 0x800)
490                         cache64_unroll32(addr|ws,Index_Writeback_Inv_SD);
491 }
492
493 static inline void blast_scache64_page(unsigned long page)
494 {
495         unsigned long start = page;
496         unsigned long end = page + PAGE_SIZE;
497
498         do {
499                 cache64_unroll32(start,Hit_Writeback_Inv_SD);
500                 start += 0x800;
501         } while (start < end);
502 }
503
504 static inline void blast_scache64_page_indexed(unsigned long page)
505 {
506         unsigned long start = page;
507         unsigned long end = start + PAGE_SIZE;
508         unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
509         unsigned long ws_end = current_cpu_data.scache.ways <<
510                                current_cpu_data.scache.waybit;
511         unsigned long ws, addr;
512
513         for (ws = 0; ws < ws_end; ws += ws_inc) 
514                 for (addr = start; addr < end; addr += 0x800) 
515                         cache64_unroll32(addr|ws,Index_Writeback_Inv_SD);
516 }
517
518 #define cache128_unroll32(base,op)                                      \
519         __asm__ __volatile__(                                           \
520         "       .set noreorder                                  \n"     \
521         "       .set mips3                                      \n"     \
522         "       cache %1, 0x000(%0); cache %1, 0x080(%0)        \n"     \
523         "       cache %1, 0x100(%0); cache %1, 0x180(%0)        \n"     \
524         "       cache %1, 0x200(%0); cache %1, 0x280(%0)        \n"     \
525         "       cache %1, 0x300(%0); cache %1, 0x380(%0)        \n"     \
526         "       cache %1, 0x400(%0); cache %1, 0x480(%0)        \n"     \
527         "       cache %1, 0x500(%0); cache %1, 0x580(%0)        \n"     \
528         "       cache %1, 0x600(%0); cache %1, 0x680(%0)        \n"     \
529         "       cache %1, 0x700(%0); cache %1, 0x780(%0)        \n"     \
530         "       cache %1, 0x800(%0); cache %1, 0x880(%0)        \n"     \
531         "       cache %1, 0x900(%0); cache %1, 0x980(%0)        \n"     \
532         "       cache %1, 0xa00(%0); cache %1, 0xa80(%0)        \n"     \
533         "       cache %1, 0xb00(%0); cache %1, 0xb80(%0)        \n"     \
534         "       cache %1, 0xc00(%0); cache %1, 0xc80(%0)        \n"     \
535         "       cache %1, 0xd00(%0); cache %1, 0xd80(%0)        \n"     \
536         "       cache %1, 0xe00(%0); cache %1, 0xe80(%0)        \n"     \
537         "       cache %1, 0xf00(%0); cache %1, 0xf80(%0)        \n"     \
538         "       .set mips0                                      \n"     \
539         "       .set reorder                                    \n"     \
540                 :                                                       \
541                 : "r" (base),                                           \
542                   "i" (op));
543
544 static inline void blast_scache128(void)
545 {
546         unsigned long start = INDEX_BASE;
547         unsigned long end = start + current_cpu_data.scache.waysize;
548         unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
549         unsigned long ws_end = current_cpu_data.scache.ways << 
550                                current_cpu_data.scache.waybit;
551         unsigned long ws, addr;
552
553         for (ws = 0; ws < ws_end; ws += ws_inc) 
554                 for (addr = start; addr < end; addr += 0x1000)
555                         cache128_unroll32(addr|ws,Index_Writeback_Inv_SD);
556 }
557
558 static inline void blast_scache128_page(unsigned long page)
559 {
560         unsigned long start = page;
561         unsigned long end = page + PAGE_SIZE;
562
563         do {
564                 cache128_unroll32(start,Hit_Writeback_Inv_SD);
565                 start += 0x1000;
566         } while (start < end);
567 }
568
569 static inline void blast_scache128_page_indexed(unsigned long page)
570 {
571         unsigned long start = page;
572         unsigned long end = start + PAGE_SIZE;
573         unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
574         unsigned long ws_end = current_cpu_data.scache.ways <<
575                                current_cpu_data.scache.waybit;
576         unsigned long ws, addr;
577
578         for (ws = 0; ws < ws_end; ws += ws_inc) 
579                 for (addr = start; addr < end; addr += 0x1000) 
580                         cache128_unroll32(addr|ws,Index_Writeback_Inv_SD);
581 }
582
583 #endif /* _ASM_R4KCACHE_H */