diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/mm/cache-l2x0.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/mm/cache-l2x0.c')
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 123 |
1 files changed, 103 insertions, 20 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 9982eb385c0f..44c086710d2b 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -28,18 +28,34 @@ | |||
28 | static void __iomem *l2x0_base; | 28 | static void __iomem *l2x0_base; |
29 | static DEFINE_SPINLOCK(l2x0_lock); | 29 | static DEFINE_SPINLOCK(l2x0_lock); |
30 | static uint32_t l2x0_way_mask; /* Bitmask of active ways */ | 30 | static uint32_t l2x0_way_mask; /* Bitmask of active ways */ |
31 | static uint32_t l2x0_size; | ||
31 | 32 | ||
32 | static inline void cache_wait(void __iomem *reg, unsigned long mask) | 33 | static inline void cache_wait_way(void __iomem *reg, unsigned long mask) |
33 | { | 34 | { |
34 | /* wait for the operation to complete */ | 35 | /* wait for cache operation by line or way to complete */ |
35 | while (readl_relaxed(reg) & mask) | 36 | while (readl_relaxed(reg) & mask) |
36 | ; | 37 | ; |
37 | } | 38 | } |
38 | 39 | ||
40 | #ifdef CONFIG_CACHE_PL310 | ||
41 | static inline void cache_wait(void __iomem *reg, unsigned long mask) | ||
42 | { | ||
43 | /* cache operations by line are atomic on PL310 */ | ||
44 | } | ||
45 | #else | ||
46 | #define cache_wait cache_wait_way | ||
47 | #endif | ||
48 | |||
39 | static inline void cache_sync(void) | 49 | static inline void cache_sync(void) |
40 | { | 50 | { |
41 | void __iomem *base = l2x0_base; | 51 | void __iomem *base = l2x0_base; |
52 | |||
53 | #ifdef CONFIG_ARM_ERRATA_753970 | ||
54 | /* write to an unmmapped register */ | ||
55 | writel_relaxed(0, base + L2X0_DUMMY_REG); | ||
56 | #else | ||
42 | writel_relaxed(0, base + L2X0_CACHE_SYNC); | 57 | writel_relaxed(0, base + L2X0_CACHE_SYNC); |
58 | #endif | ||
43 | cache_wait(base + L2X0_CACHE_SYNC, 1); | 59 | cache_wait(base + L2X0_CACHE_SYNC, 1); |
44 | } | 60 | } |
45 | 61 | ||
@@ -57,18 +73,24 @@ static inline void l2x0_inv_line(unsigned long addr) | |||
57 | writel_relaxed(addr, base + L2X0_INV_LINE_PA); | 73 | writel_relaxed(addr, base + L2X0_INV_LINE_PA); |
58 | } | 74 | } |
59 | 75 | ||
60 | #ifdef CONFIG_PL310_ERRATA_588369 | 76 | #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) |
61 | static void debug_writel(unsigned long val) | ||
62 | { | ||
63 | extern void omap_smc1(u32 fn, u32 arg); | ||
64 | 77 | ||
65 | /* | 78 | #define debug_writel(val) outer_cache.set_debug(val) |
66 | * Texas Instrument secure monitor api to modify the | 79 | |
67 | * PL310 Debug Control Register. | 80 | static void l2x0_set_debug(unsigned long val) |
68 | */ | 81 | { |
69 | omap_smc1(0x100, val); | 82 | writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); |
70 | } | 83 | } |
84 | #else | ||
85 | /* Optimised out for non-errata case */ | ||
86 | static inline void debug_writel(unsigned long val) | ||
87 | { | ||
88 | } | ||
89 | |||
90 | #define l2x0_set_debug NULL | ||
91 | #endif | ||
71 | 92 | ||
93 | #ifdef CONFIG_PL310_ERRATA_588369 | ||
72 | static inline void l2x0_flush_line(unsigned long addr) | 94 | static inline void l2x0_flush_line(unsigned long addr) |
73 | { | 95 | { |
74 | void __iomem *base = l2x0_base; | 96 | void __iomem *base = l2x0_base; |
@@ -81,11 +103,6 @@ static inline void l2x0_flush_line(unsigned long addr) | |||
81 | } | 103 | } |
82 | #else | 104 | #else |
83 | 105 | ||
84 | /* Optimised out for non-errata case */ | ||
85 | static inline void debug_writel(unsigned long val) | ||
86 | { | ||
87 | } | ||
88 | |||
89 | static inline void l2x0_flush_line(unsigned long addr) | 106 | static inline void l2x0_flush_line(unsigned long addr) |
90 | { | 107 | { |
91 | void __iomem *base = l2x0_base; | 108 | void __iomem *base = l2x0_base; |
@@ -103,14 +120,47 @@ static void l2x0_cache_sync(void) | |||
103 | spin_unlock_irqrestore(&l2x0_lock, flags); | 120 | spin_unlock_irqrestore(&l2x0_lock, flags); |
104 | } | 121 | } |
105 | 122 | ||
106 | static inline void l2x0_inv_all(void) | 123 | static void __l2x0_flush_all(void) |
124 | { | ||
125 | debug_writel(0x03); | ||
126 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); | ||
127 | cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); | ||
128 | cache_sync(); | ||
129 | debug_writel(0x00); | ||
130 | } | ||
131 | |||
132 | static void l2x0_flush_all(void) | ||
133 | { | ||
134 | unsigned long flags; | ||
135 | |||
136 | /* clean all ways */ | ||
137 | spin_lock_irqsave(&l2x0_lock, flags); | ||
138 | __l2x0_flush_all(); | ||
139 | spin_unlock_irqrestore(&l2x0_lock, flags); | ||
140 | } | ||
141 | |||
142 | static void l2x0_clean_all(void) | ||
143 | { | ||
144 | unsigned long flags; | ||
145 | |||
146 | /* clean all ways */ | ||
147 | spin_lock_irqsave(&l2x0_lock, flags); | ||
148 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY); | ||
149 | cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask); | ||
150 | cache_sync(); | ||
151 | spin_unlock_irqrestore(&l2x0_lock, flags); | ||
152 | } | ||
153 | |||
154 | static void l2x0_inv_all(void) | ||
107 | { | 155 | { |
108 | unsigned long flags; | 156 | unsigned long flags; |
109 | 157 | ||
110 | /* invalidate all ways */ | 158 | /* invalidate all ways */ |
111 | spin_lock_irqsave(&l2x0_lock, flags); | 159 | spin_lock_irqsave(&l2x0_lock, flags); |
160 | /* Invalidating when L2 is enabled is a nono */ | ||
161 | BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1); | ||
112 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); | 162 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); |
113 | cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); | 163 | cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); |
114 | cache_sync(); | 164 | cache_sync(); |
115 | spin_unlock_irqrestore(&l2x0_lock, flags); | 165 | spin_unlock_irqrestore(&l2x0_lock, flags); |
116 | } | 166 | } |
@@ -159,6 +209,11 @@ static void l2x0_clean_range(unsigned long start, unsigned long end) | |||
159 | void __iomem *base = l2x0_base; | 209 | void __iomem *base = l2x0_base; |
160 | unsigned long flags; | 210 | unsigned long flags; |
161 | 211 | ||
212 | if ((end - start) >= l2x0_size) { | ||
213 | l2x0_clean_all(); | ||
214 | return; | ||
215 | } | ||
216 | |||
162 | spin_lock_irqsave(&l2x0_lock, flags); | 217 | spin_lock_irqsave(&l2x0_lock, flags); |
163 | start &= ~(CACHE_LINE_SIZE - 1); | 218 | start &= ~(CACHE_LINE_SIZE - 1); |
164 | while (start < end) { | 219 | while (start < end) { |
@@ -184,6 +239,11 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) | |||
184 | void __iomem *base = l2x0_base; | 239 | void __iomem *base = l2x0_base; |
185 | unsigned long flags; | 240 | unsigned long flags; |
186 | 241 | ||
242 | if ((end - start) >= l2x0_size) { | ||
243 | l2x0_flush_all(); | ||
244 | return; | ||
245 | } | ||
246 | |||
187 | spin_lock_irqsave(&l2x0_lock, flags); | 247 | spin_lock_irqsave(&l2x0_lock, flags); |
188 | start &= ~(CACHE_LINE_SIZE - 1); | 248 | start &= ~(CACHE_LINE_SIZE - 1); |
189 | while (start < end) { | 249 | while (start < end) { |
@@ -206,10 +266,22 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) | |||
206 | spin_unlock_irqrestore(&l2x0_lock, flags); | 266 | spin_unlock_irqrestore(&l2x0_lock, flags); |
207 | } | 267 | } |
208 | 268 | ||
269 | static void l2x0_disable(void) | ||
270 | { | ||
271 | unsigned long flags; | ||
272 | |||
273 | spin_lock_irqsave(&l2x0_lock, flags); | ||
274 | __l2x0_flush_all(); | ||
275 | writel_relaxed(0, l2x0_base + L2X0_CTRL); | ||
276 | dsb(); | ||
277 | spin_unlock_irqrestore(&l2x0_lock, flags); | ||
278 | } | ||
279 | |||
209 | void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | 280 | void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) |
210 | { | 281 | { |
211 | __u32 aux; | 282 | __u32 aux; |
212 | __u32 cache_id; | 283 | __u32 cache_id; |
284 | __u32 way_size = 0; | ||
213 | int ways; | 285 | int ways; |
214 | const char *type; | 286 | const char *type; |
215 | 287 | ||
@@ -244,6 +316,13 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | |||
244 | l2x0_way_mask = (1 << ways) - 1; | 316 | l2x0_way_mask = (1 << ways) - 1; |
245 | 317 | ||
246 | /* | 318 | /* |
319 | * L2 cache Size = Way size * Number of ways | ||
320 | */ | ||
321 | way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17; | ||
322 | way_size = 1 << (way_size + 3); | ||
323 | l2x0_size = ways * way_size * SZ_1K; | ||
324 | |||
325 | /* | ||
247 | * Check if l2x0 controller is already enabled. | 326 | * Check if l2x0 controller is already enabled. |
248 | * If you are booting from non-secure mode | 327 | * If you are booting from non-secure mode |
249 | * accessing the below registers will fault. | 328 | * accessing the below registers will fault. |
@@ -263,8 +342,12 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | |||
263 | outer_cache.clean_range = l2x0_clean_range; | 342 | outer_cache.clean_range = l2x0_clean_range; |
264 | outer_cache.flush_range = l2x0_flush_range; | 343 | outer_cache.flush_range = l2x0_flush_range; |
265 | outer_cache.sync = l2x0_cache_sync; | 344 | outer_cache.sync = l2x0_cache_sync; |
345 | outer_cache.flush_all = l2x0_flush_all; | ||
346 | outer_cache.inv_all = l2x0_inv_all; | ||
347 | outer_cache.disable = l2x0_disable; | ||
348 | outer_cache.set_debug = l2x0_set_debug; | ||
266 | 349 | ||
267 | printk(KERN_INFO "%s cache controller enabled\n", type); | 350 | printk(KERN_INFO "%s cache controller enabled\n", type); |
268 | printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", | 351 | printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", |
269 | ways, cache_id, aux); | 352 | ways, cache_id, aux, l2x0_size); |
270 | } | 353 | } |