aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/cache-sh4.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm/cache-sh4.c')
-rw-r--r--arch/sh/mm/cache-sh4.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index b2453bbef4cd..b7f235c74d66 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -26,7 +26,7 @@
26#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */ 26#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */
27#define MAX_ICACHE_PAGES 32 27#define MAX_ICACHE_PAGES 32
28 28
29static void __flush_cache_4096(unsigned long addr, unsigned long phys, 29static void __flush_cache_one(unsigned long addr, unsigned long phys,
30 unsigned long exec_offset); 30 unsigned long exec_offset);
31 31
32/* 32/*
@@ -43,7 +43,7 @@ static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
43 * Called from kernel/module.c:sys_init_module and routine for a.out format, 43 * Called from kernel/module.c:sys_init_module and routine for a.out format,
44 * signal handler code and kprobes code 44 * signal handler code and kprobes code
45 */ 45 */
46static void sh4_flush_icache_range(void *args) 46static void __uses_jump_to_uncached sh4_flush_icache_range(void *args)
47{ 47{
48 struct flusher_data *data = args; 48 struct flusher_data *data = args;
49 unsigned long start, end; 49 unsigned long start, end;
@@ -72,6 +72,7 @@ static void sh4_flush_icache_range(void *args)
72 72
73 for (v = start; v < end; v += L1_CACHE_BYTES) { 73 for (v = start; v < end; v += L1_CACHE_BYTES) {
74 unsigned long icacheaddr; 74 unsigned long icacheaddr;
75 int j, n;
75 76
76 __ocbwb(v); 77 __ocbwb(v);
77 78
@@ -79,8 +80,10 @@ static void sh4_flush_icache_range(void *args)
79 cpu_data->icache.entry_mask); 80 cpu_data->icache.entry_mask);
80 81
81 /* Clear i-cache line valid-bit */ 82 /* Clear i-cache line valid-bit */
83 n = boot_cpu_data.icache.n_aliases;
82 for (i = 0; i < cpu_data->icache.ways; i++) { 84 for (i = 0; i < cpu_data->icache.ways; i++) {
83 __raw_writel(0, icacheaddr); 85 for (j = 0; j < n; j++)
86 __raw_writel(0, icacheaddr + (j * PAGE_SIZE));
84 icacheaddr += cpu_data->icache.way_incr; 87 icacheaddr += cpu_data->icache.way_incr;
85 } 88 }
86 } 89 }
@@ -89,8 +92,7 @@ static void sh4_flush_icache_range(void *args)
89 local_irq_restore(flags); 92 local_irq_restore(flags);
90} 93}
91 94
92static inline void flush_cache_4096(unsigned long start, 95static inline void flush_cache_one(unsigned long start, unsigned long phys)
93 unsigned long phys)
94{ 96{
95 unsigned long flags, exec_offset = 0; 97 unsigned long flags, exec_offset = 0;
96 98
@@ -103,8 +105,7 @@ static inline void flush_cache_4096(unsigned long start,
103 exec_offset = 0x20000000; 105 exec_offset = 0x20000000;
104 106
105 local_irq_save(flags); 107 local_irq_save(flags);
106 __flush_cache_4096(start | SH_CACHE_ASSOC, 108 __flush_cache_one(start | SH_CACHE_ASSOC, P1SEGADDR(phys), exec_offset);
107 P1SEGADDR(phys), exec_offset);
108 local_irq_restore(flags); 109 local_irq_restore(flags);
109} 110}
110 111
@@ -129,8 +130,8 @@ static void sh4_flush_dcache_page(void *arg)
129 130
130 /* Loop all the D-cache */ 131 /* Loop all the D-cache */
131 n = boot_cpu_data.dcache.n_aliases; 132 n = boot_cpu_data.dcache.n_aliases;
132 for (i = 0; i < n; i++, addr += 4096) 133 for (i = 0; i < n; i++, addr += PAGE_SIZE)
133 flush_cache_4096(addr, phys); 134 flush_cache_one(addr, phys);
134 } 135 }
135 136
136 wmb(); 137 wmb();
@@ -318,11 +319,11 @@ static void sh4_flush_cache_page(void *args)
318 /* We only need to flush D-cache when we have alias */ 319 /* We only need to flush D-cache when we have alias */
319 if ((address^phys) & alias_mask) { 320 if ((address^phys) & alias_mask) {
320 /* Loop 4K of the D-cache */ 321 /* Loop 4K of the D-cache */
321 flush_cache_4096( 322 flush_cache_one(
322 CACHE_OC_ADDRESS_ARRAY | (address & alias_mask), 323 CACHE_OC_ADDRESS_ARRAY | (address & alias_mask),
323 phys); 324 phys);
324 /* Loop another 4K of the D-cache */ 325 /* Loop another 4K of the D-cache */
325 flush_cache_4096( 326 flush_cache_one(
326 CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask), 327 CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask),
327 phys); 328 phys);
328 } 329 }
@@ -337,7 +338,7 @@ static void sh4_flush_cache_page(void *args)
337 * kernel has never executed the code through its identity 338 * kernel has never executed the code through its identity
338 * translation. 339 * translation.
339 */ 340 */
340 flush_cache_4096( 341 flush_cache_one(
341 CACHE_IC_ADDRESS_ARRAY | (address & alias_mask), 342 CACHE_IC_ADDRESS_ARRAY | (address & alias_mask),
342 phys); 343 phys);
343 } 344 }
@@ -393,7 +394,7 @@ static void sh4_flush_cache_range(void *args)
393} 394}
394 395
395/** 396/**
396 * __flush_cache_4096 397 * __flush_cache_one
397 * 398 *
398 * @addr: address in memory mapped cache array 399 * @addr: address in memory mapped cache array
399 * @phys: P1 address to flush (has to match tags if addr has 'A' bit 400 * @phys: P1 address to flush (has to match tags if addr has 'A' bit
@@ -406,7 +407,7 @@ static void sh4_flush_cache_range(void *args)
406 * operation (purge/write-back) is selected by the lower 2 bits of 407 * operation (purge/write-back) is selected by the lower 2 bits of
407 * 'phys'. 408 * 'phys'.
408 */ 409 */
409static void __flush_cache_4096(unsigned long addr, unsigned long phys, 410static void __flush_cache_one(unsigned long addr, unsigned long phys,
410 unsigned long exec_offset) 411 unsigned long exec_offset)
411{ 412{
412 int way_count; 413 int way_count;