1 /* 2 * arch/arm/mm/cache-l2x0.c - L210/L220 cache controller support 3 * 4 * Copyright (C) 2007 ARM Limited 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 #include <linux/init.h> 20 #include <linux/spinlock.h> 21 #include <linux/io.h> 22 23 #include <asm/cacheflush.h> 24 #include <asm/hardware/cache-l2x0.h> 25 26 #define CACHE_LINE_SIZE 32 27 28 static void __iomem *l2x0_base; 29 static DEFINE_SPINLOCK(l2x0_lock); 30 static uint32_t l2x0_way_mask; /* Bitmask of active ways */ 31 static uint32_t l2x0_size; 32 33 static inline void cache_wait_way(void __iomem *reg, unsigned long mask) 34 { 35 /* wait for cache operation by line or way to complete */ 36 while (readl_relaxed(reg) & mask) 37 ; 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 49 static inline void cache_sync(void) 50 { 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 57 writel_relaxed(0, base + L2X0_CACHE_SYNC); 58 #endif 59 cache_wait(base + L2X0_CACHE_SYNC, 1); 60 } 61 62 static inline void l2x0_clean_line(unsigned long addr) 63 { 64 void __iomem *base = l2x0_base; 65 cache_wait(base + L2X0_CLEAN_LINE_PA, 1); 66 writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA); 67 } 68 69 static inline void l2x0_inv_line(unsigned long addr) 70 { 71 void __iomem *base = l2x0_base; 72 cache_wait(base + L2X0_INV_LINE_PA, 1); 73 writel_relaxed(addr, base + L2X0_INV_LINE_PA); 74 } 75 76 #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) 77 78 #define debug_writel(val) outer_cache.set_debug(val) 79 80 static void l2x0_set_debug(unsigned long val) 81 { 82 writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); 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 92 93 #ifdef CONFIG_PL310_ERRATA_588369 94 static inline void l2x0_flush_line(unsigned long addr) 95 { 96 void __iomem *base = l2x0_base; 97 98 /* Clean by PA followed by Invalidate by PA */ 99 cache_wait(base + L2X0_CLEAN_LINE_PA, 1); 100 writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA); 101 cache_wait(base + L2X0_INV_LINE_PA, 1); 102 writel_relaxed(addr, base + L2X0_INV_LINE_PA); 103 } 104 #else 105 106 static inline void l2x0_flush_line(unsigned long addr) 107 { 108 void __iomem *base = l2x0_base; 109 cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); 110 writel_relaxed(addr, base + L2X0_CLEAN_INV_LINE_PA); 111 } 112 #endif 113 114 static void l2x0_cache_sync(void) 115 { 116 unsigned long flags; 117 118 spin_lock_irqsave(&l2x0_lock, flags); 119 cache_sync(); 120 spin_unlock_irqrestore(&l2x0_lock, flags); 121 } 122 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) 155 { 156 unsigned long flags; 157 158 /* invalidate all ways */ 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); 162 writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); 163 cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); 164 cache_sync(); 165 spin_unlock_irqrestore(&l2x0_lock, flags); 166 } 167 168 static void l2x0_inv_range(unsigned long start, unsigned long end) 169 { 170 void __iomem *base = l2x0_base; 171 unsigned long flags; 172 173 spin_lock_irqsave(&l2x0_lock, flags); 174 if (start & (CACHE_LINE_SIZE - 1)) { 175 start &= ~(CACHE_LINE_SIZE - 1); 176 debug_writel(0x03); 177 l2x0_flush_line(start); 178 debug_writel(0x00); 179 start += CACHE_LINE_SIZE; 180 } 181 182 if (end & (CACHE_LINE_SIZE - 1)) { 183 end &= ~(CACHE_LINE_SIZE - 1); 184 debug_writel(0x03); 185 l2x0_flush_line(end); 186 debug_writel(0x00); 187 } 188 189 while (start < end) { 190 unsigned long blk_end = start + min(end - start, 4096UL); 191 192 while (start < blk_end) { 193 l2x0_inv_line(start); 194 start += CACHE_LINE_SIZE; 195 } 196 197 if (blk_end < end) { 198 spin_unlock_irqrestore(&l2x0_lock, flags); 199 spin_lock_irqsave(&l2x0_lock, flags); 200 } 201 } 202 cache_wait(base + L2X0_INV_LINE_PA, 1); 203 cache_sync(); 204 spin_unlock_irqrestore(&l2x0_lock, flags); 205 } 206 207 static void l2x0_clean_range(unsigned long start, unsigned long end) 208 { 209 void __iomem *base = l2x0_base; 210 unsigned long flags; 211 212 if ((end - start) >= l2x0_size) { 213 l2x0_clean_all(); 214 return; 215 } 216 217 spin_lock_irqsave(&l2x0_lock, flags); 218 start &= ~(CACHE_LINE_SIZE - 1); 219 while (start < end) { 220 unsigned long blk_end = start + min(end - start, 4096UL); 221 222 while (start < blk_end) { 223 l2x0_clean_line(start); 224 start += CACHE_LINE_SIZE; 225 } 226 227 if (blk_end < end) { 228 spin_unlock_irqrestore(&l2x0_lock, flags); 229 spin_lock_irqsave(&l2x0_lock, flags); 230 } 231 } 232 cache_wait(base + L2X0_CLEAN_LINE_PA, 1); 233 cache_sync(); 234 spin_unlock_irqrestore(&l2x0_lock, flags); 235 } 236 237 static void l2x0_flush_range(unsigned long start, unsigned long end) 238 { 239 void __iomem *base = l2x0_base; 240 unsigned long flags; 241 242 if ((end - start) >= l2x0_size) { 243 l2x0_flush_all(); 244 return; 245 } 246 247 spin_lock_irqsave(&l2x0_lock, flags); 248 start &= ~(CACHE_LINE_SIZE - 1); 249 while (start < end) { 250 unsigned long blk_end = start + min(end - start, 4096UL); 251 252 debug_writel(0x03); 253 while (start < blk_end) { 254 l2x0_flush_line(start); 255 start += CACHE_LINE_SIZE; 256 } 257 debug_writel(0x00); 258 259 if (blk_end < end) { 260 spin_unlock_irqrestore(&l2x0_lock, flags); 261 spin_lock_irqsave(&l2x0_lock, flags); 262 } 263 } 264 cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); 265 cache_sync(); 266 spin_unlock_irqrestore(&l2x0_lock, flags); 267 } 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 280 void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) 281 { 282 __u32 aux; 283 __u32 cache_id; 284 __u32 way_size = 0; 285 int ways; 286 const char *type; 287 288 l2x0_base = base; 289 290 cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); 291 aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); 292 293 aux &= aux_mask; 294 aux |= aux_val; 295 296 /* Determine the number of ways */ 297 switch (cache_id & L2X0_CACHE_ID_PART_MASK) { 298 case L2X0_CACHE_ID_PART_L310: 299 if (aux & (1 << 16)) 300 ways = 16; 301 else 302 ways = 8; 303 type = "L310"; 304 break; 305 case L2X0_CACHE_ID_PART_L210: 306 ways = (aux >> 13) & 0xf; 307 type = "L210"; 308 break; 309 default: 310 /* Assume unknown chips have 8 ways */ 311 ways = 8; 312 type = "L2x0 series"; 313 break; 314 } 315 316 l2x0_way_mask = (1 << ways) - 1; 317 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 /* 326 * Check if l2x0 controller is already enabled. 327 * If you are booting from non-secure mode 328 * accessing the below registers will fault. 329 */ 330 if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { 331 332 /* l2x0 controller is disabled */ 333 writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); 334 335 l2x0_inv_all(); 336 337 /* enable L2X0 */ 338 writel_relaxed(1, l2x0_base + L2X0_CTRL); 339 } 340 341 outer_cache.inv_range = l2x0_inv_range; 342 outer_cache.clean_range = l2x0_clean_range; 343 outer_cache.flush_range = l2x0_flush_range; 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; 349 350 printk(KERN_INFO "%s cache controller enabled\n", type); 351 printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", 352 ways, cache_id, aux, l2x0_size); 353 } 354