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