1 #include <linux/mm.h> 2 #include <asm/mmu_context.h> 3 #include <asm/cache_insns.h> 4 #include <asm/cacheflush.h> 5 #include <asm/traps.h> 6 7 /* 8 * Write back the dirty D-caches, but not invalidate them. 9 * 10 * START: Virtual Address (U0, P1, or P3) 11 * SIZE: Size of the region. 12 */ 13 static void sh4__flush_wback_region(void *start, int size) 14 { 15 reg_size_t aligned_start, v, cnt, end; 16 17 aligned_start = register_align(start); 18 v = aligned_start & ~(L1_CACHE_BYTES-1); 19 end = (aligned_start + size + L1_CACHE_BYTES-1) 20 & ~(L1_CACHE_BYTES-1); 21 cnt = (end - v) / L1_CACHE_BYTES; 22 23 while (cnt >= 8) { 24 __ocbwb(v); v += L1_CACHE_BYTES; 25 __ocbwb(v); v += L1_CACHE_BYTES; 26 __ocbwb(v); v += L1_CACHE_BYTES; 27 __ocbwb(v); v += L1_CACHE_BYTES; 28 __ocbwb(v); v += L1_CACHE_BYTES; 29 __ocbwb(v); v += L1_CACHE_BYTES; 30 __ocbwb(v); v += L1_CACHE_BYTES; 31 __ocbwb(v); v += L1_CACHE_BYTES; 32 cnt -= 8; 33 } 34 35 while (cnt) { 36 __ocbwb(v); v += L1_CACHE_BYTES; 37 cnt--; 38 } 39 } 40 41 /* 42 * Write back the dirty D-caches and invalidate them. 43 * 44 * START: Virtual Address (U0, P1, or P3) 45 * SIZE: Size of the region. 46 */ 47 static void sh4__flush_purge_region(void *start, int size) 48 { 49 reg_size_t aligned_start, v, cnt, end; 50 51 aligned_start = register_align(start); 52 v = aligned_start & ~(L1_CACHE_BYTES-1); 53 end = (aligned_start + size + L1_CACHE_BYTES-1) 54 & ~(L1_CACHE_BYTES-1); 55 cnt = (end - v) / L1_CACHE_BYTES; 56 57 while (cnt >= 8) { 58 __ocbp(v); v += L1_CACHE_BYTES; 59 __ocbp(v); v += L1_CACHE_BYTES; 60 __ocbp(v); v += L1_CACHE_BYTES; 61 __ocbp(v); v += L1_CACHE_BYTES; 62 __ocbp(v); v += L1_CACHE_BYTES; 63 __ocbp(v); v += L1_CACHE_BYTES; 64 __ocbp(v); v += L1_CACHE_BYTES; 65 __ocbp(v); v += L1_CACHE_BYTES; 66 cnt -= 8; 67 } 68 while (cnt) { 69 __ocbp(v); v += L1_CACHE_BYTES; 70 cnt--; 71 } 72 } 73 74 /* 75 * No write back please 76 */ 77 static void sh4__flush_invalidate_region(void *start, int size) 78 { 79 reg_size_t aligned_start, v, cnt, end; 80 81 aligned_start = register_align(start); 82 v = aligned_start & ~(L1_CACHE_BYTES-1); 83 end = (aligned_start + size + L1_CACHE_BYTES-1) 84 & ~(L1_CACHE_BYTES-1); 85 cnt = (end - v) / L1_CACHE_BYTES; 86 87 while (cnt >= 8) { 88 __ocbi(v); v += L1_CACHE_BYTES; 89 __ocbi(v); v += L1_CACHE_BYTES; 90 __ocbi(v); v += L1_CACHE_BYTES; 91 __ocbi(v); v += L1_CACHE_BYTES; 92 __ocbi(v); v += L1_CACHE_BYTES; 93 __ocbi(v); v += L1_CACHE_BYTES; 94 __ocbi(v); v += L1_CACHE_BYTES; 95 __ocbi(v); v += L1_CACHE_BYTES; 96 cnt -= 8; 97 } 98 99 while (cnt) { 100 __ocbi(v); v += L1_CACHE_BYTES; 101 cnt--; 102 } 103 } 104 105 void __init sh4__flush_region_init(void) 106 { 107 __flush_wback_region = sh4__flush_wback_region; 108 __flush_invalidate_region = sh4__flush_invalidate_region; 109 __flush_purge_region = sh4__flush_purge_region; 110 } 111