make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / include / asm-mips64 / 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  *
10  * FIXME: Handle split L2 caches.
11  */
12 #ifndef _ASM_R4KCACHE_H
13 #define _ASM_R4KCACHE_H
14
15 #include <asm/asm.h>
16 #include <asm/r4kcacheops.h>
17
18 static inline void flush_icache_line_indexed(unsigned long addr)
19 {
20         __asm__ __volatile__(
21                 ".set noreorder\n\t"
22                 "cache %1, (%0)\n\t"
23                 ".set reorder"
24                 :
25                 : "r" (addr), "i" (Index_Invalidate_I));
26 }
27
28 static inline void flush_dcache_line_indexed(unsigned long addr)
29 {
30         __asm__ __volatile__(
31                 ".set noreorder\n\t"
32                 "cache %1, (%0)\n\t"
33                 ".set reorder"
34                 :
35                 : "r" (addr), "i" (Index_Writeback_Inv_D));
36 }
37
38 static inline void flush_scache_line_indexed(unsigned long addr)
39 {
40         __asm__ __volatile__(
41                 ".set noreorder\n\t"
42                 "cache %1, (%0)\n\t"
43                 ".set reorder"
44                 :
45                 : "r" (addr), "i" (Index_Writeback_Inv_SD));
46 }
47
48 static inline void flush_icache_line(unsigned long addr)
49 {
50         __asm__ __volatile__(
51                 ".set noreorder\n\t"
52                 "cache %1, (%0)\n\t"
53                 ".set reorder"
54                 :
55                 : "r" (addr), "i" (Hit_Invalidate_I));
56 }
57
58 static inline void flush_dcache_line(unsigned long addr)
59 {
60         __asm__ __volatile__(
61                 ".set noreorder\n\t"
62                 "cache %1, (%0)\n\t"
63                 ".set reorder"
64                 :
65                 : "r" (addr), "i" (Hit_Writeback_Inv_D));
66 }
67
68 static inline void invalidate_dcache_line(unsigned long addr)
69 {
70         __asm__ __volatile__(
71                 ".set noreorder\n\t"
72                 "cache %1, (%0)\n\t"
73                 ".set reorder"
74                 :
75                 : "r" (addr), "i" (Hit_Invalidate_D));
76 }
77
78 static inline void invalidate_scache_line(unsigned long addr)
79 {
80         __asm__ __volatile__(
81                 ".set noreorder\n\t"
82                 "cache %1, (%0)\n\t"
83                 ".set reorder"
84                 :
85                 : "r" (addr), "i" (Hit_Invalidate_SD));
86 }
87
88 static inline void flush_scache_line(unsigned long addr)
89 {
90         __asm__ __volatile__(
91                 ".set noreorder\n\t"
92                 "cache %1, (%0)\n\t"
93                 ".set reorder"
94                 :
95                 : "r" (addr), "i" (Hit_Writeback_Inv_SD));
96 }
97
98 /*
99  * The next two are for badland addresses like signal trampolines.
100  */
101 static inline void protected_flush_icache_line(unsigned long addr)
102 {
103         __asm__ __volatile__(
104                 ".set noreorder\n\t"
105                 "1:\tcache %1,(%0)\n"
106                 "2:\t.set reorder\n\t"
107                 ".section\t__ex_table,\"a\"\n\t"
108                 ".dword\t1b,2b\n\t"
109                 ".previous"
110                 :
111                 : "r" (addr), "i" (Hit_Invalidate_I));
112 }
113
114 static inline void protected_writeback_dcache_line(unsigned long addr)
115 {
116         __asm__ __volatile__(
117                 ".set noreorder\n\t"
118                 "1:\tcache %1,(%0)\n"
119                 "2:\t.set reorder\n\t"
120                 ".section\t__ex_table,\"a\"\n\t"
121                 ".dword\t1b,2b\n\t"
122                 ".previous"
123                 :
124                 : "r" (addr), "i" (Hit_Writeback_D));
125 }
126
127 #define cache16_unroll32(base,op)                               \
128         __asm__ __volatile__("                                  \
129                 .set noreorder;                                 \
130                 cache %1, 0x000(%0); cache %1, 0x010(%0);       \
131                 cache %1, 0x020(%0); cache %1, 0x030(%0);       \
132                 cache %1, 0x040(%0); cache %1, 0x050(%0);       \
133                 cache %1, 0x060(%0); cache %1, 0x070(%0);       \
134                 cache %1, 0x080(%0); cache %1, 0x090(%0);       \
135                 cache %1, 0x0a0(%0); cache %1, 0x0b0(%0);       \
136                 cache %1, 0x0c0(%0); cache %1, 0x0d0(%0);       \
137                 cache %1, 0x0e0(%0); cache %1, 0x0f0(%0);       \
138                 cache %1, 0x100(%0); cache %1, 0x110(%0);       \
139                 cache %1, 0x120(%0); cache %1, 0x130(%0);       \
140                 cache %1, 0x140(%0); cache %1, 0x150(%0);       \
141                 cache %1, 0x160(%0); cache %1, 0x170(%0);       \
142                 cache %1, 0x180(%0); cache %1, 0x190(%0);       \
143                 cache %1, 0x1a0(%0); cache %1, 0x1b0(%0);       \
144                 cache %1, 0x1c0(%0); cache %1, 0x1d0(%0);       \
145                 cache %1, 0x1e0(%0); cache %1, 0x1f0(%0);       \
146                 .set reorder"                                   \
147                 :                                               \
148                 : "r" (base),                                   \
149                   "i" (op));
150
151 static inline void blast_dcache16(void)
152 {
153         unsigned long start = KSEG0;
154         unsigned long end = (start + dcache_size);
155
156         while(start < end) {
157                 cache16_unroll32(start,Index_Writeback_Inv_D);
158                 start += 0x200;
159         }
160 }
161
162 static inline void blast_dcache16_page(unsigned long page)
163 {
164         unsigned long start = page;
165         unsigned long end = (start + PAGE_SIZE);
166
167         while(start < end) {
168                 cache16_unroll32(start,Hit_Writeback_Inv_D);
169                 start += 0x200;
170         }
171 }
172
173 static inline void blast_dcache16_page_indexed(unsigned long page)
174 {
175         unsigned long start = page;
176         unsigned long end = (start + PAGE_SIZE);
177
178         while(start < end) {
179                 cache16_unroll32(start,Index_Writeback_Inv_D);
180                 start += 0x200;
181         }
182 }
183
184 static inline void blast_icache16(void)
185 {
186         unsigned long start = KSEG0;
187         unsigned long end = (start + icache_size);
188
189         while(start < end) {
190                 cache16_unroll32(start,Index_Invalidate_I);
191                 start += 0x200;
192         }
193 }
194
195 static inline void blast_icache16_page(unsigned long page)
196 {
197         unsigned long start = page;
198         unsigned long end = (start + PAGE_SIZE);
199
200         while(start < end) {
201                 cache16_unroll32(start,Hit_Invalidate_I);
202                 start += 0x200;
203         }
204 }
205
206 static inline void blast_icache16_page_indexed(unsigned long page)
207 {
208         unsigned long start = page;
209         unsigned long end = (start + PAGE_SIZE);
210
211         while(start < end) {
212                 cache16_unroll32(start,Index_Invalidate_I);
213                 start += 0x200;
214         }
215 }
216
217 static inline void blast_scache16(void)
218 {
219         unsigned long start = KSEG0;
220         unsigned long end = KSEG0 + scache_size;
221
222         while(start < end) {
223                 cache16_unroll32(start,Index_Writeback_Inv_SD);
224                 start += 0x200;
225         }
226 }
227
228 static inline void blast_scache16_page(unsigned long page)
229 {
230         unsigned long start = page;
231         unsigned long end = page + PAGE_SIZE;
232
233         while(start < end) {
234                 cache16_unroll32(start,Hit_Writeback_Inv_SD);
235                 start += 0x200;
236         }
237 }
238
239 static inline void blast_scache16_page_indexed(unsigned long page)
240 {
241         unsigned long start = page;
242         unsigned long end = page + PAGE_SIZE;
243
244         while(start < end) {
245                 cache16_unroll32(start,Index_Writeback_Inv_SD);
246                 start += 0x200;
247         }
248 }
249
250 #define cache32_unroll32(base,op)                               \
251         __asm__ __volatile__("                                  \
252                 .set noreorder;                                 \
253                 cache %1, 0x000(%0); cache %1, 0x020(%0);       \
254                 cache %1, 0x040(%0); cache %1, 0x060(%0);       \
255                 cache %1, 0x080(%0); cache %1, 0x0a0(%0);       \
256                 cache %1, 0x0c0(%0); cache %1, 0x0e0(%0);       \
257                 cache %1, 0x100(%0); cache %1, 0x120(%0);       \
258                 cache %1, 0x140(%0); cache %1, 0x160(%0);       \
259                 cache %1, 0x180(%0); cache %1, 0x1a0(%0);       \
260                 cache %1, 0x1c0(%0); cache %1, 0x1e0(%0);       \
261                 cache %1, 0x200(%0); cache %1, 0x220(%0);       \
262                 cache %1, 0x240(%0); cache %1, 0x260(%0);       \
263                 cache %1, 0x280(%0); cache %1, 0x2a0(%0);       \
264                 cache %1, 0x2c0(%0); cache %1, 0x2e0(%0);       \
265                 cache %1, 0x300(%0); cache %1, 0x320(%0);       \
266                 cache %1, 0x340(%0); cache %1, 0x360(%0);       \
267                 cache %1, 0x380(%0); cache %1, 0x3a0(%0);       \
268                 cache %1, 0x3c0(%0); cache %1, 0x3e0(%0);       \
269                 .set reorder"                                   \
270                 :                                               \
271                 : "r" (base),                                   \
272                   "i" (op));
273
274 static inline void blast_dcache32(void)
275 {
276         unsigned long start = KSEG0;
277         unsigned long end = (start + dcache_size);
278
279         while(start < end) {
280                 cache32_unroll32(start,Index_Writeback_Inv_D);
281                 start += 0x400;
282         }
283 }
284
285 /*
286  * Call this function only with interrupts disabled or R4600 V2.0 may blow
287  * up on you.
288  *
289  * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D,
290  * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Excl_D will only
291  * operate correctly if the internal data cache refill buffer is empty.  These
292  * CACHE instructions should be separated from any potential data cache miss
293  * by a load instruction to an uncached address to empty the response buffer."
294  * (Revision 2.0 device errata from IDT available on http://www.idt.com/
295  * in .pdf format.)
296  */
297 static inline void blast_dcache32_page(unsigned long page)
298 {
299         unsigned long start = page;
300         unsigned long end = (start + PAGE_SIZE);
301
302         /*
303          * Sigh ... workaround for R4600 v1.7 bug.  Explanation see above.
304          */
305         *(volatile unsigned long *)KSEG1;
306
307         __asm__ __volatile__("nop;nop;nop;nop");
308         while(start < end) {
309                 cache32_unroll32(start,Hit_Writeback_Inv_D);
310                 start += 0x400;
311         }
312 }
313
314 static inline void blast_dcache32_page_indexed(unsigned long page)
315 {
316         unsigned long start = page;
317         unsigned long end = (start + PAGE_SIZE);
318
319         while(start < end) {
320                 cache32_unroll32(start,Index_Writeback_Inv_D);
321                 start += 0x400;
322         }
323 }
324
325 static inline void blast_icache32(void)
326 {
327         unsigned long start = KSEG0;
328         unsigned long end = (start + icache_size);
329
330         while(start < end) {
331                 cache32_unroll32(start,Index_Invalidate_I);
332                 start += 0x400;
333         }
334 }
335
336 static inline void blast_icache32_page(unsigned long page)
337 {
338         unsigned long start = page;
339         unsigned long end = (start + PAGE_SIZE);
340
341         while(start < end) {
342                 cache32_unroll32(start,Hit_Invalidate_I);
343                 start += 0x400;
344         }
345 }
346
347 static inline void blast_icache32_page_indexed(unsigned long page)
348 {
349         unsigned long start = page;
350         unsigned long end = (start + PAGE_SIZE);
351
352         while(start < end) {
353                 cache32_unroll32(start,Index_Invalidate_I);
354                 start += 0x400;
355         }
356 }
357
358 static inline void blast_scache32(void)
359 {
360         unsigned long start = KSEG0;
361         unsigned long end = KSEG0 + scache_size;
362
363         while(start < end) {
364                 cache32_unroll32(start,Index_Writeback_Inv_SD);
365                 start += 0x400;
366         }
367 }
368
369 static inline void blast_scache32_page(unsigned long page)
370 {
371         unsigned long start = page;
372         unsigned long end = page + PAGE_SIZE;
373
374         while(start < end) {
375                 cache32_unroll32(start,Hit_Writeback_Inv_SD);
376                 start += 0x400;
377         }
378 }
379
380 static inline void blast_scache32_page_indexed(unsigned long page)
381 {
382         unsigned long start = page;
383         unsigned long end = page + PAGE_SIZE;
384
385         while(start < end) {
386                 cache32_unroll32(start,Index_Writeback_Inv_SD);
387                 start += 0x400;
388         }
389 }
390
391 #define cache64_unroll32(base,op)                               \
392         __asm__ __volatile__("                                  \
393                 .set noreorder;                                 \
394                 cache %1, 0x000(%0); cache %1, 0x040(%0);       \
395                 cache %1, 0x080(%0); cache %1, 0x0c0(%0);       \
396                 cache %1, 0x100(%0); cache %1, 0x140(%0);       \
397                 cache %1, 0x180(%0); cache %1, 0x1c0(%0);       \
398                 cache %1, 0x200(%0); cache %1, 0x240(%0);       \
399                 cache %1, 0x280(%0); cache %1, 0x2c0(%0);       \
400                 cache %1, 0x300(%0); cache %1, 0x340(%0);       \
401                 cache %1, 0x380(%0); cache %1, 0x3c0(%0);       \
402                 cache %1, 0x400(%0); cache %1, 0x440(%0);       \
403                 cache %1, 0x480(%0); cache %1, 0x4c0(%0);       \
404                 cache %1, 0x500(%0); cache %1, 0x540(%0);       \
405                 cache %1, 0x580(%0); cache %1, 0x5c0(%0);       \
406                 cache %1, 0x600(%0); cache %1, 0x640(%0);       \
407                 cache %1, 0x680(%0); cache %1, 0x6c0(%0);       \
408                 cache %1, 0x700(%0); cache %1, 0x740(%0);       \
409                 cache %1, 0x780(%0); cache %1, 0x7c0(%0);       \
410                 .set reorder"                                   \
411                 :                                               \
412                 : "r" (base),                                   \
413                   "i" (op));
414
415 static inline void blast_scache64(void)
416 {
417         unsigned long start = KSEG0;
418         unsigned long end = KSEG0 + scache_size;
419
420         while(start < end) {
421                 cache64_unroll32(start,Index_Writeback_Inv_SD);
422                 start += 0x800;
423         }
424 }
425
426 static inline void blast_scache64_page(unsigned long page)
427 {
428         unsigned long start = page;
429         unsigned long end = page + PAGE_SIZE;
430
431         while(start < end) {
432                 cache64_unroll32(start,Hit_Writeback_Inv_SD);
433                 start += 0x800;
434         }
435 }
436
437 static inline void blast_scache64_page_indexed(unsigned long page)
438 {
439         unsigned long start = page;
440         unsigned long end = page + PAGE_SIZE;
441
442         while(start < end) {
443                 cache64_unroll32(start,Index_Writeback_Inv_SD);
444                 start += 0x800;
445         }
446 }
447
448 #define cache128_unroll32(base,op)                              \
449         __asm__ __volatile__("                                  \
450                 .set noreorder;                                 \
451                 cache %1, 0x000(%0); cache %1, 0x080(%0);       \
452                 cache %1, 0x100(%0); cache %1, 0x180(%0);       \
453                 cache %1, 0x200(%0); cache %1, 0x280(%0);       \
454                 cache %1, 0x300(%0); cache %1, 0x380(%0);       \
455                 cache %1, 0x400(%0); cache %1, 0x480(%0);       \
456                 cache %1, 0x500(%0); cache %1, 0x580(%0);       \
457                 cache %1, 0x600(%0); cache %1, 0x680(%0);       \
458                 cache %1, 0x700(%0); cache %1, 0x780(%0);       \
459                 cache %1, 0x800(%0); cache %1, 0x880(%0);       \
460                 cache %1, 0x900(%0); cache %1, 0x980(%0);       \
461                 cache %1, 0xa00(%0); cache %1, 0xa80(%0);       \
462                 cache %1, 0xb00(%0); cache %1, 0xb80(%0);       \
463                 cache %1, 0xc00(%0); cache %1, 0xc80(%0);       \
464                 cache %1, 0xd00(%0); cache %1, 0xd80(%0);       \
465                 cache %1, 0xe00(%0); cache %1, 0xe80(%0);       \
466                 cache %1, 0xf00(%0); cache %1, 0xf80(%0);       \
467                 .set reorder"                                   \
468                 :                                               \
469                 : "r" (base),                                   \
470                   "i" (op));
471
472 static inline void blast_scache128(void)
473 {
474         unsigned long start = KSEG0;
475         unsigned long end = KSEG0 + scache_size;
476
477         while(start < end) {
478                 cache128_unroll32(start,Index_Writeback_Inv_SD);
479                 start += 0x1000;
480         }
481 }
482
483 static inline void blast_scache128_page(unsigned long page)
484 {
485         cache128_unroll32(page,Hit_Writeback_Inv_SD);
486 }
487
488 static inline void blast_scache128_page_indexed(unsigned long page)
489 {
490         cache128_unroll32(page,Index_Writeback_Inv_SD);
491 }
492
493 #endif /* __ASM_R4KCACHE_H */