diff options
-rw-r--r-- | arch/mips/mm/c-r4k.c | 104 | ||||
-rw-r--r-- | arch/mips/mm/c-tx39.c | 70 | ||||
-rw-r--r-- | include/asm-mips/r4kcache.h | 74 |
3 files changed, 64 insertions, 184 deletions
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index e51c38cef88e..1b71d91e8268 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
@@ -471,61 +471,29 @@ struct flush_icache_range_args { | |||
471 | static inline void local_r4k_flush_icache_range(void *args) | 471 | static inline void local_r4k_flush_icache_range(void *args) |
472 | { | 472 | { |
473 | struct flush_icache_range_args *fir_args = args; | 473 | struct flush_icache_range_args *fir_args = args; |
474 | unsigned long dc_lsize = cpu_dcache_line_size(); | ||
475 | unsigned long ic_lsize = cpu_icache_line_size(); | ||
476 | unsigned long sc_lsize = cpu_scache_line_size(); | ||
477 | unsigned long start = fir_args->start; | 474 | unsigned long start = fir_args->start; |
478 | unsigned long end = fir_args->end; | 475 | unsigned long end = fir_args->end; |
479 | unsigned long addr, aend; | ||
480 | 476 | ||
481 | if (!cpu_has_ic_fills_f_dc) { | 477 | if (!cpu_has_ic_fills_f_dc) { |
482 | if (end - start > dcache_size) { | 478 | if (end - start > dcache_size) { |
483 | r4k_blast_dcache(); | 479 | r4k_blast_dcache(); |
484 | } else { | 480 | } else { |
485 | R4600_HIT_CACHEOP_WAR_IMPL; | 481 | R4600_HIT_CACHEOP_WAR_IMPL; |
486 | addr = start & ~(dc_lsize - 1); | 482 | protected_blast_dcache_range(start, end); |
487 | aend = (end - 1) & ~(dc_lsize - 1); | ||
488 | |||
489 | while (1) { | ||
490 | /* Hit_Writeback_Inv_D */ | ||
491 | protected_writeback_dcache_line(addr); | ||
492 | if (addr == aend) | ||
493 | break; | ||
494 | addr += dc_lsize; | ||
495 | } | ||
496 | } | 483 | } |
497 | 484 | ||
498 | if (!cpu_icache_snoops_remote_store) { | 485 | if (!cpu_icache_snoops_remote_store) { |
499 | if (end - start > scache_size) { | 486 | if (end - start > scache_size) |
500 | r4k_blast_scache(); | 487 | r4k_blast_scache(); |
501 | } else { | 488 | else |
502 | addr = start & ~(sc_lsize - 1); | 489 | protected_blast_scache_range(start, end); |
503 | aend = (end - 1) & ~(sc_lsize - 1); | ||
504 | |||
505 | while (1) { | ||
506 | /* Hit_Writeback_Inv_SD */ | ||
507 | protected_writeback_scache_line(addr); | ||
508 | if (addr == aend) | ||
509 | break; | ||
510 | addr += sc_lsize; | ||
511 | } | ||
512 | } | ||
513 | } | 490 | } |
514 | } | 491 | } |
515 | 492 | ||
516 | if (end - start > icache_size) | 493 | if (end - start > icache_size) |
517 | r4k_blast_icache(); | 494 | r4k_blast_icache(); |
518 | else { | 495 | else |
519 | addr = start & ~(ic_lsize - 1); | 496 | protected_blast_icache_range(start, end); |
520 | aend = (end - 1) & ~(ic_lsize - 1); | ||
521 | while (1) { | ||
522 | /* Hit_Invalidate_I */ | ||
523 | protected_flush_icache_line(addr); | ||
524 | if (addr == aend) | ||
525 | break; | ||
526 | addr += ic_lsize; | ||
527 | } | ||
528 | } | ||
529 | } | 497 | } |
530 | 498 | ||
531 | static void r4k_flush_icache_range(unsigned long start, unsigned long end) | 499 | static void r4k_flush_icache_range(unsigned long start, unsigned long end) |
@@ -619,27 +587,14 @@ static void r4k_flush_icache_page(struct vm_area_struct *vma, | |||
619 | 587 | ||
620 | static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) | 588 | static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) |
621 | { | 589 | { |
622 | unsigned long end, a; | ||
623 | |||
624 | /* Catch bad driver code */ | 590 | /* Catch bad driver code */ |
625 | BUG_ON(size == 0); | 591 | BUG_ON(size == 0); |
626 | 592 | ||
627 | if (cpu_has_subset_pcaches) { | 593 | if (cpu_has_subset_pcaches) { |
628 | unsigned long sc_lsize = cpu_scache_line_size(); | 594 | if (size >= scache_size) |
629 | |||
630 | if (size >= scache_size) { | ||
631 | r4k_blast_scache(); | 595 | r4k_blast_scache(); |
632 | return; | 596 | else |
633 | } | 597 | blast_scache_range(addr, addr + size); |
634 | |||
635 | a = addr & ~(sc_lsize - 1); | ||
636 | end = (addr + size - 1) & ~(sc_lsize - 1); | ||
637 | while (1) { | ||
638 | flush_scache_line(a); /* Hit_Writeback_Inv_SD */ | ||
639 | if (a == end) | ||
640 | break; | ||
641 | a += sc_lsize; | ||
642 | } | ||
643 | return; | 598 | return; |
644 | } | 599 | } |
645 | 600 | ||
@@ -651,17 +606,8 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) | |||
651 | if (size >= dcache_size) { | 606 | if (size >= dcache_size) { |
652 | r4k_blast_dcache(); | 607 | r4k_blast_dcache(); |
653 | } else { | 608 | } else { |
654 | unsigned long dc_lsize = cpu_dcache_line_size(); | ||
655 | |||
656 | R4600_HIT_CACHEOP_WAR_IMPL; | 609 | R4600_HIT_CACHEOP_WAR_IMPL; |
657 | a = addr & ~(dc_lsize - 1); | 610 | blast_dcache_range(addr, addr + size); |
658 | end = (addr + size - 1) & ~(dc_lsize - 1); | ||
659 | while (1) { | ||
660 | flush_dcache_line(a); /* Hit_Writeback_Inv_D */ | ||
661 | if (a == end) | ||
662 | break; | ||
663 | a += dc_lsize; | ||
664 | } | ||
665 | } | 611 | } |
666 | 612 | ||
667 | bc_wback_inv(addr, size); | 613 | bc_wback_inv(addr, size); |
@@ -669,44 +615,22 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) | |||
669 | 615 | ||
670 | static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) | 616 | static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) |
671 | { | 617 | { |
672 | unsigned long end, a; | ||
673 | |||
674 | /* Catch bad driver code */ | 618 | /* Catch bad driver code */ |
675 | BUG_ON(size == 0); | 619 | BUG_ON(size == 0); |
676 | 620 | ||
677 | if (cpu_has_subset_pcaches) { | 621 | if (cpu_has_subset_pcaches) { |
678 | unsigned long sc_lsize = cpu_scache_line_size(); | 622 | if (size >= scache_size) |
679 | |||
680 | if (size >= scache_size) { | ||
681 | r4k_blast_scache(); | 623 | r4k_blast_scache(); |
682 | return; | 624 | else |
683 | } | 625 | blast_scache_range(addr, addr + size); |
684 | |||
685 | a = addr & ~(sc_lsize - 1); | ||
686 | end = (addr + size - 1) & ~(sc_lsize - 1); | ||
687 | while (1) { | ||
688 | flush_scache_line(a); /* Hit_Writeback_Inv_SD */ | ||
689 | if (a == end) | ||
690 | break; | ||
691 | a += sc_lsize; | ||
692 | } | ||
693 | return; | 626 | return; |
694 | } | 627 | } |
695 | 628 | ||
696 | if (size >= dcache_size) { | 629 | if (size >= dcache_size) { |
697 | r4k_blast_dcache(); | 630 | r4k_blast_dcache(); |
698 | } else { | 631 | } else { |
699 | unsigned long dc_lsize = cpu_dcache_line_size(); | ||
700 | |||
701 | R4600_HIT_CACHEOP_WAR_IMPL; | 632 | R4600_HIT_CACHEOP_WAR_IMPL; |
702 | a = addr & ~(dc_lsize - 1); | 633 | blast_dcache_range(addr, addr + size); |
703 | end = (addr + size - 1) & ~(dc_lsize - 1); | ||
704 | while (1) { | ||
705 | flush_dcache_line(a); /* Hit_Writeback_Inv_D */ | ||
706 | if (a == end) | ||
707 | break; | ||
708 | a += dc_lsize; | ||
709 | } | ||
710 | } | 634 | } |
711 | 635 | ||
712 | bc_inv(addr, size); | 636 | bc_inv(addr, size); |
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 0a97a9434eba..7c572bea4a98 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c | |||
@@ -44,8 +44,6 @@ __asm__ __volatile__( \ | |||
44 | /* TX39H-style cache flush routines. */ | 44 | /* TX39H-style cache flush routines. */ |
45 | static void tx39h_flush_icache_all(void) | 45 | static void tx39h_flush_icache_all(void) |
46 | { | 46 | { |
47 | unsigned long start = KSEG0; | ||
48 | unsigned long end = (start + icache_size); | ||
49 | unsigned long flags, config; | 47 | unsigned long flags, config; |
50 | 48 | ||
51 | /* disable icache (set ICE#) */ | 49 | /* disable icache (set ICE#) */ |
@@ -53,33 +51,18 @@ static void tx39h_flush_icache_all(void) | |||
53 | config = read_c0_conf(); | 51 | config = read_c0_conf(); |
54 | write_c0_conf(config & ~TX39_CONF_ICE); | 52 | write_c0_conf(config & ~TX39_CONF_ICE); |
55 | TX39_STOP_STREAMING(); | 53 | TX39_STOP_STREAMING(); |
56 | 54 | blast_icache16(); | |
57 | /* invalidate icache */ | ||
58 | while (start < end) { | ||
59 | cache16_unroll32(start, Index_Invalidate_I); | ||
60 | start += 0x200; | ||
61 | } | ||
62 | |||
63 | write_c0_conf(config); | 55 | write_c0_conf(config); |
64 | local_irq_restore(flags); | 56 | local_irq_restore(flags); |
65 | } | 57 | } |
66 | 58 | ||
67 | static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size) | 59 | static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size) |
68 | { | 60 | { |
69 | unsigned long end, a; | ||
70 | unsigned long dc_lsize = current_cpu_data.dcache.linesz; | ||
71 | |||
72 | /* Catch bad driver code */ | 61 | /* Catch bad driver code */ |
73 | BUG_ON(size == 0); | 62 | BUG_ON(size == 0); |
74 | 63 | ||
75 | iob(); | 64 | iob(); |
76 | a = addr & ~(dc_lsize - 1); | 65 | blast_inv_dcache_range(addr, addr + size); |
77 | end = (addr + size - 1) & ~(dc_lsize - 1); | ||
78 | while (1) { | ||
79 | invalidate_dcache_line(a); /* Hit_Invalidate_D */ | ||
80 | if (a == end) break; | ||
81 | a += dc_lsize; | ||
82 | } | ||
83 | } | 66 | } |
84 | 67 | ||
85 | 68 | ||
@@ -241,42 +224,21 @@ static void tx39_flush_data_cache_page(unsigned long addr) | |||
241 | 224 | ||
242 | static void tx39_flush_icache_range(unsigned long start, unsigned long end) | 225 | static void tx39_flush_icache_range(unsigned long start, unsigned long end) |
243 | { | 226 | { |
244 | unsigned long dc_lsize = current_cpu_data.dcache.linesz; | ||
245 | unsigned long addr, aend; | ||
246 | |||
247 | if (end - start > dcache_size) | 227 | if (end - start > dcache_size) |
248 | tx39_blast_dcache(); | 228 | tx39_blast_dcache(); |
249 | else { | 229 | else |
250 | addr = start & ~(dc_lsize - 1); | 230 | protected_blast_dcache_range(start, end); |
251 | aend = (end - 1) & ~(dc_lsize - 1); | ||
252 | |||
253 | while (1) { | ||
254 | /* Hit_Writeback_Inv_D */ | ||
255 | protected_writeback_dcache_line(addr); | ||
256 | if (addr == aend) | ||
257 | break; | ||
258 | addr += dc_lsize; | ||
259 | } | ||
260 | } | ||
261 | 231 | ||
262 | if (end - start > icache_size) | 232 | if (end - start > icache_size) |
263 | tx39_blast_icache(); | 233 | tx39_blast_icache(); |
264 | else { | 234 | else { |
265 | unsigned long flags, config; | 235 | unsigned long flags, config; |
266 | addr = start & ~(dc_lsize - 1); | ||
267 | aend = (end - 1) & ~(dc_lsize - 1); | ||
268 | /* disable icache (set ICE#) */ | 236 | /* disable icache (set ICE#) */ |
269 | local_irq_save(flags); | 237 | local_irq_save(flags); |
270 | config = read_c0_conf(); | 238 | config = read_c0_conf(); |
271 | write_c0_conf(config & ~TX39_CONF_ICE); | 239 | write_c0_conf(config & ~TX39_CONF_ICE); |
272 | TX39_STOP_STREAMING(); | 240 | TX39_STOP_STREAMING(); |
273 | while (1) { | 241 | protected_blast_icache_range(start, end); |
274 | /* Hit_Invalidate_I */ | ||
275 | protected_flush_icache_line(addr); | ||
276 | if (addr == aend) | ||
277 | break; | ||
278 | addr += dc_lsize; | ||
279 | } | ||
280 | write_c0_conf(config); | 242 | write_c0_conf(config); |
281 | local_irq_restore(flags); | 243 | local_irq_restore(flags); |
282 | } | 244 | } |
@@ -311,7 +273,7 @@ static void tx39_flush_icache_page(struct vm_area_struct *vma, struct page *page | |||
311 | 273 | ||
312 | static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size) | 274 | static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size) |
313 | { | 275 | { |
314 | unsigned long end, a; | 276 | unsigned long end; |
315 | 277 | ||
316 | if (((size | addr) & (PAGE_SIZE - 1)) == 0) { | 278 | if (((size | addr) & (PAGE_SIZE - 1)) == 0) { |
317 | end = addr + size; | 279 | end = addr + size; |
@@ -322,20 +284,13 @@ static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size) | |||
322 | } else if (size > dcache_size) { | 284 | } else if (size > dcache_size) { |
323 | tx39_blast_dcache(); | 285 | tx39_blast_dcache(); |
324 | } else { | 286 | } else { |
325 | unsigned long dc_lsize = current_cpu_data.dcache.linesz; | 287 | blast_dcache_range(addr, addr + size); |
326 | a = addr & ~(dc_lsize - 1); | ||
327 | end = (addr + size - 1) & ~(dc_lsize - 1); | ||
328 | while (1) { | ||
329 | flush_dcache_line(a); /* Hit_Writeback_Inv_D */ | ||
330 | if (a == end) break; | ||
331 | a += dc_lsize; | ||
332 | } | ||
333 | } | 288 | } |
334 | } | 289 | } |
335 | 290 | ||
336 | static void tx39_dma_cache_inv(unsigned long addr, unsigned long size) | 291 | static void tx39_dma_cache_inv(unsigned long addr, unsigned long size) |
337 | { | 292 | { |
338 | unsigned long end, a; | 293 | unsigned long end; |
339 | 294 | ||
340 | if (((size | addr) & (PAGE_SIZE - 1)) == 0) { | 295 | if (((size | addr) & (PAGE_SIZE - 1)) == 0) { |
341 | end = addr + size; | 296 | end = addr + size; |
@@ -346,14 +301,7 @@ static void tx39_dma_cache_inv(unsigned long addr, unsigned long size) | |||
346 | } else if (size > dcache_size) { | 301 | } else if (size > dcache_size) { |
347 | tx39_blast_dcache(); | 302 | tx39_blast_dcache(); |
348 | } else { | 303 | } else { |
349 | unsigned long dc_lsize = current_cpu_data.dcache.linesz; | 304 | blast_inv_dcache_range(addr, addr + size); |
350 | a = addr & ~(dc_lsize - 1); | ||
351 | end = (addr + size - 1) & ~(dc_lsize - 1); | ||
352 | while (1) { | ||
353 | invalidate_dcache_line(a); /* Hit_Invalidate_D */ | ||
354 | if (a == end) break; | ||
355 | a += dc_lsize; | ||
356 | } | ||
357 | } | 305 | } |
358 | } | 306 | } |
359 | 307 | ||
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h index cc53196efa40..9632c27dad15 100644 --- a/include/asm-mips/r4kcache.h +++ b/include/asm-mips/r4kcache.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <asm/asm.h> | 15 | #include <asm/asm.h> |
16 | #include <asm/cacheops.h> | 16 | #include <asm/cacheops.h> |
17 | #include <asm/cpu-features.h> | ||
17 | 18 | ||
18 | /* | 19 | /* |
19 | * This macro return a properly sign-extended address suitable as base address | 20 | * This macro return a properly sign-extended address suitable as base address |
@@ -78,22 +79,25 @@ static inline void flush_scache_line(unsigned long addr) | |||
78 | cache_op(Hit_Writeback_Inv_SD, addr); | 79 | cache_op(Hit_Writeback_Inv_SD, addr); |
79 | } | 80 | } |
80 | 81 | ||
82 | #define protected_cache_op(op,addr) \ | ||
83 | __asm__ __volatile__( \ | ||
84 | " .set push \n" \ | ||
85 | " .set noreorder \n" \ | ||
86 | " .set mips3 \n" \ | ||
87 | "1: cache %0, (%1) \n" \ | ||
88 | "2: .set pop \n" \ | ||
89 | " .section __ex_table,\"a\" \n" \ | ||
90 | " "STR(PTR)" 1b, 2b \n" \ | ||
91 | " .previous" \ | ||
92 | : \ | ||
93 | : "i" (op), "r" (addr)) | ||
94 | |||
81 | /* | 95 | /* |
82 | * The next two are for badland addresses like signal trampolines. | 96 | * The next two are for badland addresses like signal trampolines. |
83 | */ | 97 | */ |
84 | static inline void protected_flush_icache_line(unsigned long addr) | 98 | static inline void protected_flush_icache_line(unsigned long addr) |
85 | { | 99 | { |
86 | __asm__ __volatile__( | 100 | protected_cache_op(Hit_Invalidate_I, addr); |
87 | " .set push \n" | ||
88 | " .set noreorder \n" | ||
89 | " .set mips3 \n" | ||
90 | "1: cache %0, (%1) \n" | ||
91 | "2: .set pop \n" | ||
92 | " .section __ex_table,\"a\" \n" | ||
93 | " "STR(PTR)" 1b, 2b \n" | ||
94 | " .previous" | ||
95 | : | ||
96 | : "i" (Hit_Invalidate_I), "r" (addr)); | ||
97 | } | 101 | } |
98 | 102 | ||
99 | /* | 103 | /* |
@@ -104,32 +108,12 @@ static inline void protected_flush_icache_line(unsigned long addr) | |||
104 | */ | 108 | */ |
105 | static inline void protected_writeback_dcache_line(unsigned long addr) | 109 | static inline void protected_writeback_dcache_line(unsigned long addr) |
106 | { | 110 | { |
107 | __asm__ __volatile__( | 111 | protected_cache_op(Hit_Writeback_Inv_D, addr); |
108 | " .set push \n" | ||
109 | " .set noreorder \n" | ||
110 | " .set mips3 \n" | ||
111 | "1: cache %0, (%1) \n" | ||
112 | "2: .set pop \n" | ||
113 | " .section __ex_table,\"a\" \n" | ||
114 | " "STR(PTR)" 1b, 2b \n" | ||
115 | " .previous" | ||
116 | : | ||
117 | : "i" (Hit_Writeback_Inv_D), "r" (addr)); | ||
118 | } | 112 | } |
119 | 113 | ||
120 | static inline void protected_writeback_scache_line(unsigned long addr) | 114 | static inline void protected_writeback_scache_line(unsigned long addr) |
121 | { | 115 | { |
122 | __asm__ __volatile__( | 116 | protected_cache_op(Hit_Writeback_Inv_SD, addr); |
123 | " .set push \n" | ||
124 | " .set noreorder \n" | ||
125 | " .set mips3 \n" | ||
126 | "1: cache %0, (%1) \n" | ||
127 | "2: .set pop \n" | ||
128 | " .section __ex_table,\"a\" \n" | ||
129 | " "STR(PTR)" 1b, 2b \n" | ||
130 | " .previous" | ||
131 | : | ||
132 | : "i" (Hit_Writeback_Inv_SD), "r" (addr)); | ||
133 | } | 117 | } |
134 | 118 | ||
135 | /* | 119 | /* |
@@ -295,4 +279,28 @@ __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) | |||
295 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) | 279 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) |
296 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) | 280 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) |
297 | 281 | ||
282 | /* build blast_xxx_range, protected_blast_xxx_range */ | ||
283 | #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \ | ||
284 | static inline void prot##blast_##pfx##cache##_range(unsigned long start, \ | ||
285 | unsigned long end) \ | ||
286 | { \ | ||
287 | unsigned long lsize = cpu_##desc##_line_size(); \ | ||
288 | unsigned long addr = start & ~(lsize - 1); \ | ||
289 | unsigned long aend = (end - 1) & ~(lsize - 1); \ | ||
290 | while (1) { \ | ||
291 | prot##cache_op(hitop, addr); \ | ||
292 | if (addr == aend) \ | ||
293 | break; \ | ||
294 | addr += lsize; \ | ||
295 | } \ | ||
296 | } | ||
297 | |||
298 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_) | ||
299 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_) | ||
300 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_) | ||
301 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, ) | ||
302 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, ) | ||
303 | /* blast_inv_dcache_range */ | ||
304 | __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, ) | ||
305 | |||
298 | #endif /* _ASM_R4KCACHE_H */ | 306 | #endif /* _ASM_R4KCACHE_H */ |