xref: /linux/arch/sh/mm/flush-sh4.c (revision 6ac1ef482d7ae0c690f1640bf6eb818ff9a2d91e)
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