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