1/* 2 * Copyright (C) 2011 Texas Instruments Incorporated 3 * Author: Mark Salter <msalter@redhat.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9#include <linux/of.h> 10#include <linux/of_address.h> 11#include <linux/io.h> 12 13#include <asm/cache.h> 14#include <asm/soc.h> 15 16/* 17 * Internal Memory Control Registers for caches 18 */ 19#define IMCR_CCFG 0x0000 20#define IMCR_L1PCFG 0x0020 21#define IMCR_L1PCC 0x0024 22#define IMCR_L1DCFG 0x0040 23#define IMCR_L1DCC 0x0044 24#define IMCR_L2ALLOC0 0x2000 25#define IMCR_L2ALLOC1 0x2004 26#define IMCR_L2ALLOC2 0x2008 27#define IMCR_L2ALLOC3 0x200c 28#define IMCR_L2WBAR 0x4000 29#define IMCR_L2WWC 0x4004 30#define IMCR_L2WIBAR 0x4010 31#define IMCR_L2WIWC 0x4014 32#define IMCR_L2IBAR 0x4018 33#define IMCR_L2IWC 0x401c 34#define IMCR_L1PIBAR 0x4020 35#define IMCR_L1PIWC 0x4024 36#define IMCR_L1DWIBAR 0x4030 37#define IMCR_L1DWIWC 0x4034 38#define IMCR_L1DWBAR 0x4040 39#define IMCR_L1DWWC 0x4044 40#define IMCR_L1DIBAR 0x4048 41#define IMCR_L1DIWC 0x404c 42#define IMCR_L2WB 0x5000 43#define IMCR_L2WBINV 0x5004 44#define IMCR_L2INV 0x5008 45#define IMCR_L1PINV 0x5028 46#define IMCR_L1DWB 0x5040 47#define IMCR_L1DWBINV 0x5044 48#define IMCR_L1DINV 0x5048 49#define IMCR_MAR_BASE 0x8000 50#define IMCR_MAR96_111 0x8180 51#define IMCR_MAR128_191 0x8200 52#define IMCR_MAR224_239 0x8380 53#define IMCR_L2MPFAR 0xa000 54#define IMCR_L2MPFSR 0xa004 55#define IMCR_L2MPFCR 0xa008 56#define IMCR_L2MPLK0 0xa100 57#define IMCR_L2MPLK1 0xa104 58#define IMCR_L2MPLK2 0xa108 59#define IMCR_L2MPLK3 0xa10c 60#define IMCR_L2MPLKCMD 0xa110 61#define IMCR_L2MPLKSTAT 0xa114 62#define IMCR_L2MPPA_BASE 0xa200 63#define IMCR_L1PMPFAR 0xa400 64#define IMCR_L1PMPFSR 0xa404 65#define IMCR_L1PMPFCR 0xa408 66#define IMCR_L1PMPLK0 0xa500 67#define IMCR_L1PMPLK1 0xa504 68#define IMCR_L1PMPLK2 0xa508 69#define IMCR_L1PMPLK3 0xa50c 70#define IMCR_L1PMPLKCMD 0xa510 71#define IMCR_L1PMPLKSTAT 0xa514 72#define IMCR_L1PMPPA_BASE 0xa600 73#define IMCR_L1DMPFAR 0xac00 74#define IMCR_L1DMPFSR 0xac04 75#define IMCR_L1DMPFCR 0xac08 76#define IMCR_L1DMPLK0 0xad00 77#define IMCR_L1DMPLK1 0xad04 78#define IMCR_L1DMPLK2 0xad08 79#define IMCR_L1DMPLK3 0xad0c 80#define IMCR_L1DMPLKCMD 0xad10 81#define IMCR_L1DMPLKSTAT 0xad14 82#define IMCR_L1DMPPA_BASE 0xae00 83#define IMCR_L2PDWAKE0 0xc040 84#define IMCR_L2PDWAKE1 0xc044 85#define IMCR_L2PDSLEEP0 0xc050 86#define IMCR_L2PDSLEEP1 0xc054 87#define IMCR_L2PDSTAT0 0xc060 88#define IMCR_L2PDSTAT1 0xc064 89 90/* 91 * CCFG register values and bits 92 */ 93#define L2MODE_0K_CACHE 0x0 94#define L2MODE_32K_CACHE 0x1 95#define L2MODE_64K_CACHE 0x2 96#define L2MODE_128K_CACHE 0x3 97#define L2MODE_256K_CACHE 0x7 98 99#define L2PRIO_URGENT 0x0 100#define L2PRIO_HIGH 0x1 101#define L2PRIO_MEDIUM 0x2 102#define L2PRIO_LOW 0x3 103 104#define CCFG_ID 0x100 /* Invalidate L1P bit */ 105#define CCFG_IP 0x200 /* Invalidate L1D bit */ 106 107static void __iomem *cache_base; 108 109/* 110 * L1 & L2 caches generic functions 111 */ 112#define imcr_get(reg) soc_readl(cache_base + (reg)) 113#define imcr_set(reg, value) \ 114do { \ 115 soc_writel((value), cache_base + (reg)); \ 116 soc_readl(cache_base + (reg)); \ 117} while (0) 118 119static void cache_block_operation_wait(unsigned int wc_reg) 120{ 121 /* Wait for completion */ 122 while (imcr_get(wc_reg)) 123 cpu_relax(); 124} 125 126static DEFINE_SPINLOCK(cache_lock); 127 128/* 129 * Generic function to perform a block cache operation as 130 * invalidate or writeback/invalidate 131 */ 132static void cache_block_operation(unsigned int *start, 133 unsigned int *end, 134 unsigned int bar_reg, 135 unsigned int wc_reg) 136{ 137 unsigned long flags; 138 unsigned int wcnt = 139 (L2_CACHE_ALIGN_CNT((unsigned int) end) 140 - L2_CACHE_ALIGN_LOW((unsigned int) start)) >> 2; 141 unsigned int wc = 0; 142 143 for (; wcnt; wcnt -= wc, start += wc) { 144loop: 145 spin_lock_irqsave(&cache_lock, flags); 146 147 /* 148 * If another cache operation is occuring 149 */ 150 if (unlikely(imcr_get(wc_reg))) { 151 spin_unlock_irqrestore(&cache_lock, flags); 152 153 /* Wait for previous operation completion */ 154 cache_block_operation_wait(wc_reg); 155 156 /* Try again */ 157 goto loop; 158 } 159 160 imcr_set(bar_reg, L2_CACHE_ALIGN_LOW((unsigned int) start)); 161 162 if (wcnt > 0xffff) 163 wc = 0xffff; 164 else 165 wc = wcnt; 166 167 /* Set word count value in the WC register */ 168 imcr_set(wc_reg, wc & 0xffff); 169 170 spin_unlock_irqrestore(&cache_lock, flags); 171 172 /* Wait for completion */ 173 cache_block_operation_wait(wc_reg); 174 } 175} 176 177static void cache_block_operation_nowait(unsigned int *start, 178 unsigned int *end, 179 unsigned int bar_reg, 180 unsigned int wc_reg) 181{ 182 unsigned long flags; 183 unsigned int wcnt = 184 (L2_CACHE_ALIGN_CNT((unsigned int) end) 185 - L2_CACHE_ALIGN_LOW((unsigned int) start)) >> 2; 186 unsigned int wc = 0; 187 188 for (; wcnt; wcnt -= wc, start += wc) { 189 190 spin_lock_irqsave(&cache_lock, flags); 191 192 imcr_set(bar_reg, L2_CACHE_ALIGN_LOW((unsigned int) start)); 193 194 if (wcnt > 0xffff) 195 wc = 0xffff; 196 else 197 wc = wcnt; 198 199 /* Set word count value in the WC register */ 200 imcr_set(wc_reg, wc & 0xffff); 201 202 spin_unlock_irqrestore(&cache_lock, flags); 203 204 /* Don't wait for completion on last cache operation */ 205 if (wcnt > 0xffff) 206 cache_block_operation_wait(wc_reg); 207 } 208} 209 210/* 211 * L1 caches management 212 */ 213 214/* 215 * Disable L1 caches 216 */ 217void L1_cache_off(void) 218{ 219 unsigned int dummy; 220 221 imcr_set(IMCR_L1PCFG, 0); 222 dummy = imcr_get(IMCR_L1PCFG); 223 224 imcr_set(IMCR_L1DCFG, 0); 225 dummy = imcr_get(IMCR_L1DCFG); 226} 227 228/* 229 * Enable L1 caches 230 */ 231void L1_cache_on(void) 232{ 233 unsigned int dummy; 234 235 imcr_set(IMCR_L1PCFG, 7); 236 dummy = imcr_get(IMCR_L1PCFG); 237 238 imcr_set(IMCR_L1DCFG, 7); 239 dummy = imcr_get(IMCR_L1DCFG); 240} 241 242/* 243 * L1P global-invalidate all 244 */ 245void L1P_cache_global_invalidate(void) 246{ 247 unsigned int set = 1; 248 imcr_set(IMCR_L1PINV, set); 249 while (imcr_get(IMCR_L1PINV) & 1) 250 cpu_relax(); 251} 252 253/* 254 * L1D global-invalidate all 255 * 256 * Warning: this operation causes all updated data in L1D to 257 * be discarded rather than written back to the lower levels of 258 * memory 259 */ 260void L1D_cache_global_invalidate(void) 261{ 262 unsigned int set = 1; 263 imcr_set(IMCR_L1DINV, set); 264 while (imcr_get(IMCR_L1DINV) & 1) 265 cpu_relax(); 266} 267 268void L1D_cache_global_writeback(void) 269{ 270 unsigned int set = 1; 271 imcr_set(IMCR_L1DWB, set); 272 while (imcr_get(IMCR_L1DWB) & 1) 273 cpu_relax(); 274} 275 276void L1D_cache_global_writeback_invalidate(void) 277{ 278 unsigned int set = 1; 279 imcr_set(IMCR_L1DWBINV, set); 280 while (imcr_get(IMCR_L1DWBINV) & 1) 281 cpu_relax(); 282} 283 284/* 285 * L2 caches management 286 */ 287 288/* 289 * Set L2 operation mode 290 */ 291void L2_cache_set_mode(unsigned int mode) 292{ 293 unsigned int ccfg = imcr_get(IMCR_CCFG); 294 295 /* Clear and set the L2MODE bits in CCFG */ 296 ccfg &= ~7; 297 ccfg |= (mode & 7); 298 imcr_set(IMCR_CCFG, ccfg); 299 ccfg = imcr_get(IMCR_CCFG); 300} 301 302/* 303 * L2 global-writeback and global-invalidate all 304 */ 305void L2_cache_global_writeback_invalidate(void) 306{ 307 imcr_set(IMCR_L2WBINV, 1); 308 while (imcr_get(IMCR_L2WBINV)) 309 cpu_relax(); 310} 311 312/* 313 * L2 global-writeback all 314 */ 315void L2_cache_global_writeback(void) 316{ 317 imcr_set(IMCR_L2WB, 1); 318 while (imcr_get(IMCR_L2WB)) 319 cpu_relax(); 320} 321 322/* 323 * Cacheability controls 324 */ 325void enable_caching(unsigned long start, unsigned long end) 326{ 327 unsigned int mar = IMCR_MAR_BASE + ((start >> 24) << 2); 328 unsigned int mar_e = IMCR_MAR_BASE + ((end >> 24) << 2); 329 330 for (; mar <= mar_e; mar += 4) 331 imcr_set(mar, imcr_get(mar) | 1); 332} 333 334void disable_caching(unsigned long start, unsigned long end) 335{ 336 unsigned int mar = IMCR_MAR_BASE + ((start >> 24) << 2); 337 unsigned int mar_e = IMCR_MAR_BASE + ((end >> 24) << 2); 338 339 for (; mar <= mar_e; mar += 4) 340 imcr_set(mar, imcr_get(mar) & ~1); 341} 342 343 344/* 345 * L1 block operations 346 */ 347void L1P_cache_block_invalidate(unsigned int start, unsigned int end) 348{ 349 cache_block_operation((unsigned int *) start, 350 (unsigned int *) end, 351 IMCR_L1PIBAR, IMCR_L1PIWC); 352} 353EXPORT_SYMBOL(L1P_cache_block_invalidate); 354 355void L1D_cache_block_invalidate(unsigned int start, unsigned int end) 356{ 357 cache_block_operation((unsigned int *) start, 358 (unsigned int *) end, 359 IMCR_L1DIBAR, IMCR_L1DIWC); 360} 361 362void L1D_cache_block_writeback_invalidate(unsigned int start, unsigned int end) 363{ 364 cache_block_operation((unsigned int *) start, 365 (unsigned int *) end, 366 IMCR_L1DWIBAR, IMCR_L1DWIWC); 367} 368 369void L1D_cache_block_writeback(unsigned int start, unsigned int end) 370{ 371 cache_block_operation((unsigned int *) start, 372 (unsigned int *) end, 373 IMCR_L1DWBAR, IMCR_L1DWWC); 374} 375EXPORT_SYMBOL(L1D_cache_block_writeback); 376 377/* 378 * L2 block operations 379 */ 380void L2_cache_block_invalidate(unsigned int start, unsigned int end) 381{ 382 cache_block_operation((unsigned int *) start, 383 (unsigned int *) end, 384 IMCR_L2IBAR, IMCR_L2IWC); 385} 386 387void L2_cache_block_writeback(unsigned int start, unsigned int end) 388{ 389 cache_block_operation((unsigned int *) start, 390 (unsigned int *) end, 391 IMCR_L2WBAR, IMCR_L2WWC); 392} 393 394void L2_cache_block_writeback_invalidate(unsigned int start, unsigned int end) 395{ 396 cache_block_operation((unsigned int *) start, 397 (unsigned int *) end, 398 IMCR_L2WIBAR, IMCR_L2WIWC); 399} 400 401void L2_cache_block_invalidate_nowait(unsigned int start, unsigned int end) 402{ 403 cache_block_operation_nowait((unsigned int *) start, 404 (unsigned int *) end, 405 IMCR_L2IBAR, IMCR_L2IWC); 406} 407 408void L2_cache_block_writeback_nowait(unsigned int start, unsigned int end) 409{ 410 cache_block_operation_nowait((unsigned int *) start, 411 (unsigned int *) end, 412 IMCR_L2WBAR, IMCR_L2WWC); 413} 414 415void L2_cache_block_writeback_invalidate_nowait(unsigned int start, 416 unsigned int end) 417{ 418 cache_block_operation_nowait((unsigned int *) start, 419 (unsigned int *) end, 420 IMCR_L2WIBAR, IMCR_L2WIWC); 421} 422 423 424/* 425 * L1 and L2 caches configuration 426 */ 427void __init c6x_cache_init(void) 428{ 429 struct device_node *node; 430 431 node = of_find_compatible_node(NULL, NULL, "ti,c64x+cache"); 432 if (!node) 433 return; 434 435 cache_base = of_iomap(node, 0); 436 437 of_node_put(node); 438 439 if (!cache_base) 440 return; 441 442 /* Set L2 caches on the the whole L2 SRAM memory */ 443 L2_cache_set_mode(L2MODE_SIZE); 444 445 /* Enable L1 */ 446 L1_cache_on(); 447} 448