aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/mm/cache-sh4.c63
1 files changed, 33 insertions, 30 deletions
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 3ac4945cb493..b2453bbef4cd 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -46,7 +46,6 @@ static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
46static void sh4_flush_icache_range(void *args) 46static void sh4_flush_icache_range(void *args)
47{ 47{
48 struct flusher_data *data = args; 48 struct flusher_data *data = args;
49 int icacheaddr;
50 unsigned long start, end; 49 unsigned long start, end;
51 unsigned long flags, v; 50 unsigned long flags, v;
52 int i; 51 int i;
@@ -54,36 +53,40 @@ static void sh4_flush_icache_range(void *args)
54 start = data->addr1; 53 start = data->addr1;
55 end = data->addr2; 54 end = data->addr2;
56 55
57 /* If there are too many pages then just blow the caches */ 56 /* If there are too many pages then just blow away the caches */
58 if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) { 57 if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
59 local_flush_cache_all(args); 58 local_flush_cache_all(NULL);
60 } else { 59 return;
61 /* selectively flush d-cache then invalidate the i-cache */ 60 }
62 /* this is inefficient, so only use for small ranges */ 61
63 start &= ~(L1_CACHE_BYTES-1); 62 /*
64 end += L1_CACHE_BYTES-1; 63 * Selectively flush d-cache then invalidate the i-cache.
65 end &= ~(L1_CACHE_BYTES-1); 64 * This is inefficient, so only use this for small ranges.
66 65 */
67 local_irq_save(flags); 66 start &= ~(L1_CACHE_BYTES-1);
68 jump_to_uncached(); 67 end += L1_CACHE_BYTES-1;
69 68 end &= ~(L1_CACHE_BYTES-1);
70 for (v = start; v < end; v+=L1_CACHE_BYTES) { 69
71 asm volatile("ocbwb %0" 70 local_irq_save(flags);
72 : /* no output */ 71 jump_to_uncached();
73 : "m" (__m(v))); 72
74 73 for (v = start; v < end; v += L1_CACHE_BYTES) {
75 icacheaddr = CACHE_IC_ADDRESS_ARRAY | ( 74 unsigned long icacheaddr;
76 v & cpu_data->icache.entry_mask); 75
77 76 __ocbwb(v);
78 for (i = 0; i < cpu_data->icache.ways; 77
79 i++, icacheaddr += cpu_data->icache.way_incr) 78 icacheaddr = CACHE_IC_ADDRESS_ARRAY | (v &
80 /* Clear i-cache line valid-bit */ 79 cpu_data->icache.entry_mask);
81 ctrl_outl(0, icacheaddr); 80
82 } 81 /* Clear i-cache line valid-bit */
83 82 for (i = 0; i < cpu_data->icache.ways; i++) {
84 back_to_cached(); 83 __raw_writel(0, icacheaddr);
85 local_irq_restore(flags); 84 icacheaddr += cpu_data->icache.way_incr;
85 }
86 } 86 }
87
88 back_to_cached();
89 local_irq_restore(flags);
87} 90}
88 91
89static inline void flush_cache_4096(unsigned long start, 92static inline void flush_cache_4096(unsigned long start,