aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/cache-l2x0.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/mm/cache-l2x0.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (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.c123
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 @@
28static void __iomem *l2x0_base; 28static void __iomem *l2x0_base;
29static DEFINE_SPINLOCK(l2x0_lock); 29static DEFINE_SPINLOCK(l2x0_lock);
30static uint32_t l2x0_way_mask; /* Bitmask of active ways */ 30static uint32_t l2x0_way_mask; /* Bitmask of active ways */
31static uint32_t l2x0_size;
31 32
32static inline void cache_wait(void __iomem *reg, unsigned long mask) 33static 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
41static 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
39static inline void cache_sync(void) 49static 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)
61static 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. 80static 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 */
86static 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
72static inline void l2x0_flush_line(unsigned long addr) 94static 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 */
85static inline void debug_writel(unsigned long val)
86{
87}
88
89static inline void l2x0_flush_line(unsigned long addr) 106static 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
106static inline void l2x0_inv_all(void) 123static 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
132static 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
142static 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
154static 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
269static 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
209void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) 280void __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}