diff options
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/mm/cache-sh4.c | 63 |
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) = | |||
46 | static void sh4_flush_icache_range(void *args) | 46 | static 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 | ||
89 | static inline void flush_cache_4096(unsigned long start, | 92 | static inline void flush_cache_4096(unsigned long start, |