sh: Fix up more 64-bit pgprot truncation on SH-X2 TLB.
[linux-2.6.git] / arch / sh / mm / flush-sh4.c
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 }