Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sh/mm/flush-sh4.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <linux/mm.h>
3
#include <asm/mmu_context.h>
4
#include <asm/cache_insns.h>
5
#include <asm/cacheflush.h>
6
#include <asm/traps.h>
7
8
/*
9
* Write back the dirty D-caches, but not invalidate them.
10
*
11
* START: Virtual Address (U0, P1, or P3)
12
* SIZE: Size of the region.
13
*/
14
static void sh4__flush_wback_region(void *start, int size)
15
{
16
reg_size_t aligned_start, v, cnt, end;
17
18
aligned_start = register_align(start);
19
v = aligned_start & ~(L1_CACHE_BYTES-1);
20
end = (aligned_start + size + L1_CACHE_BYTES-1)
21
& ~(L1_CACHE_BYTES-1);
22
cnt = (end - v) / L1_CACHE_BYTES;
23
24
while (cnt >= 8) {
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
__ocbwb(v); v += L1_CACHE_BYTES;
33
cnt -= 8;
34
}
35
36
while (cnt) {
37
__ocbwb(v); v += L1_CACHE_BYTES;
38
cnt--;
39
}
40
}
41
42
/*
43
* Write back the dirty D-caches and invalidate them.
44
*
45
* START: Virtual Address (U0, P1, or P3)
46
* SIZE: Size of the region.
47
*/
48
static void sh4__flush_purge_region(void *start, int size)
49
{
50
reg_size_t aligned_start, v, cnt, end;
51
52
aligned_start = register_align(start);
53
v = aligned_start & ~(L1_CACHE_BYTES-1);
54
end = (aligned_start + size + L1_CACHE_BYTES-1)
55
& ~(L1_CACHE_BYTES-1);
56
cnt = (end - v) / L1_CACHE_BYTES;
57
58
while (cnt >= 8) {
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
__ocbp(v); v += L1_CACHE_BYTES;
67
cnt -= 8;
68
}
69
while (cnt) {
70
__ocbp(v); v += L1_CACHE_BYTES;
71
cnt--;
72
}
73
}
74
75
/*
76
* No write back please
77
*/
78
static void sh4__flush_invalidate_region(void *start, int size)
79
{
80
reg_size_t aligned_start, v, cnt, end;
81
82
aligned_start = register_align(start);
83
v = aligned_start & ~(L1_CACHE_BYTES-1);
84
end = (aligned_start + size + L1_CACHE_BYTES-1)
85
& ~(L1_CACHE_BYTES-1);
86
cnt = (end - v) / L1_CACHE_BYTES;
87
88
while (cnt >= 8) {
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
__ocbi(v); v += L1_CACHE_BYTES;
97
cnt -= 8;
98
}
99
100
while (cnt) {
101
__ocbi(v); v += L1_CACHE_BYTES;
102
cnt--;
103
}
104
}
105
106
void __init sh4__flush_region_init(void)
107
{
108
__flush_wback_region = sh4__flush_wback_region;
109
__flush_invalidate_region = sh4__flush_invalidate_region;
110
__flush_purge_region = sh4__flush_purge_region;
111
}
112
113