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