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