tangled
alpha
login
or
join now
tjh.dev
/
kernel
1
fork
atom
Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1
fork
atom
overview
issues
pulls
pipelines
Merge branch 'pending-l2x0' into cache
Russell King
16 years ago
bf32eb85
f74f7e57
+72
-21
1 changed file
expand all
collapse all
unified
split
arch
arm
mm
cache-l2x0.c
+72
-21
arch/arm/mm/cache-l2x0.c
reviewed
···
28
28
static void __iomem *l2x0_base;
29
29
static DEFINE_SPINLOCK(l2x0_lock);
30
30
31
31
-
static inline void sync_writel(unsigned long val, unsigned long reg,
32
32
-
unsigned long complete_mask)
31
31
+
static inline void cache_wait(void __iomem *reg, unsigned long mask)
33
32
{
34
34
-
unsigned long flags;
35
35
-
36
36
-
spin_lock_irqsave(&l2x0_lock, flags);
37
37
-
writel(val, l2x0_base + reg);
38
33
/* wait for the operation to complete */
39
39
-
while (readl(l2x0_base + reg) & complete_mask)
34
34
+
while (readl(reg) & mask)
40
35
;
41
41
-
spin_unlock_irqrestore(&l2x0_lock, flags);
42
36
}
43
37
44
38
static inline void cache_sync(void)
45
39
{
46
46
-
sync_writel(0, L2X0_CACHE_SYNC, 1);
40
40
+
void __iomem *base = l2x0_base;
41
41
+
writel(0, base + L2X0_CACHE_SYNC);
42
42
+
cache_wait(base + L2X0_CACHE_SYNC, 1);
47
43
}
48
44
49
45
static inline void l2x0_inv_all(void)
50
46
{
47
47
+
unsigned long flags;
48
48
+
51
49
/* invalidate all ways */
52
52
-
sync_writel(0xff, L2X0_INV_WAY, 0xff);
50
50
+
spin_lock_irqsave(&l2x0_lock, flags);
51
51
+
writel(0xff, l2x0_base + L2X0_INV_WAY);
52
52
+
cache_wait(l2x0_base + L2X0_INV_WAY, 0xff);
53
53
cache_sync();
54
54
+
spin_unlock_irqrestore(&l2x0_lock, flags);
54
55
}
55
56
56
57
static void l2x0_inv_range(unsigned long start, unsigned long end)
57
58
{
58
58
-
unsigned long addr;
59
59
+
void __iomem *base = l2x0_base;
60
60
+
unsigned long flags;
59
61
62
62
+
spin_lock_irqsave(&l2x0_lock, flags);
60
63
if (start & (CACHE_LINE_SIZE - 1)) {
61
64
start &= ~(CACHE_LINE_SIZE - 1);
62
62
-
sync_writel(start, L2X0_CLEAN_INV_LINE_PA, 1);
65
65
+
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
66
66
+
writel(start, base + L2X0_CLEAN_INV_LINE_PA);
63
67
start += CACHE_LINE_SIZE;
64
68
}
65
69
66
70
if (end & (CACHE_LINE_SIZE - 1)) {
67
71
end &= ~(CACHE_LINE_SIZE - 1);
68
68
-
sync_writel(end, L2X0_CLEAN_INV_LINE_PA, 1);
72
72
+
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
73
73
+
writel(end, base + L2X0_CLEAN_INV_LINE_PA);
69
74
}
70
75
71
71
-
for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
72
72
-
sync_writel(addr, L2X0_INV_LINE_PA, 1);
76
76
+
while (start < end) {
77
77
+
unsigned long blk_end = start + min(end - start, 4096UL);
78
78
+
79
79
+
while (start < blk_end) {
80
80
+
cache_wait(base + L2X0_INV_LINE_PA, 1);
81
81
+
writel(start, base + L2X0_INV_LINE_PA);
82
82
+
start += CACHE_LINE_SIZE;
83
83
+
}
84
84
+
85
85
+
if (blk_end < end) {
86
86
+
spin_unlock_irqrestore(&l2x0_lock, flags);
87
87
+
spin_lock_irqsave(&l2x0_lock, flags);
88
88
+
}
89
89
+
}
90
90
+
cache_wait(base + L2X0_INV_LINE_PA, 1);
73
91
cache_sync();
92
92
+
spin_unlock_irqrestore(&l2x0_lock, flags);
74
93
}
75
94
76
95
static void l2x0_clean_range(unsigned long start, unsigned long end)
77
96
{
78
78
-
unsigned long addr;
97
97
+
void __iomem *base = l2x0_base;
98
98
+
unsigned long flags;
79
99
100
100
+
spin_lock_irqsave(&l2x0_lock, flags);
80
101
start &= ~(CACHE_LINE_SIZE - 1);
81
81
-
for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
82
82
-
sync_writel(addr, L2X0_CLEAN_LINE_PA, 1);
102
102
+
while (start < end) {
103
103
+
unsigned long blk_end = start + min(end - start, 4096UL);
104
104
+
105
105
+
while (start < blk_end) {
106
106
+
cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
107
107
+
writel(start, base + L2X0_CLEAN_LINE_PA);
108
108
+
start += CACHE_LINE_SIZE;
109
109
+
}
110
110
+
111
111
+
if (blk_end < end) {
112
112
+
spin_unlock_irqrestore(&l2x0_lock, flags);
113
113
+
spin_lock_irqsave(&l2x0_lock, flags);
114
114
+
}
115
115
+
}
116
116
+
cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
83
117
cache_sync();
118
118
+
spin_unlock_irqrestore(&l2x0_lock, flags);
84
119
}
85
120
86
121
static void l2x0_flush_range(unsigned long start, unsigned long end)
87
122
{
88
88
-
unsigned long addr;
123
123
+
void __iomem *base = l2x0_base;
124
124
+
unsigned long flags;
89
125
126
126
+
spin_lock_irqsave(&l2x0_lock, flags);
90
127
start &= ~(CACHE_LINE_SIZE - 1);
91
91
-
for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
92
92
-
sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1);
128
128
+
while (start < end) {
129
129
+
unsigned long blk_end = start + min(end - start, 4096UL);
130
130
+
131
131
+
while (start < blk_end) {
132
132
+
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
133
133
+
writel(start, base + L2X0_CLEAN_INV_LINE_PA);
134
134
+
start += CACHE_LINE_SIZE;
135
135
+
}
136
136
+
137
137
+
if (blk_end < end) {
138
138
+
spin_unlock_irqrestore(&l2x0_lock, flags);
139
139
+
spin_lock_irqsave(&l2x0_lock, flags);
140
140
+
}
141
141
+
}
142
142
+
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
93
143
cache_sync();
144
144
+
spin_unlock_irqrestore(&l2x0_lock, flags);
94
145
}
95
146
96
147
void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)