cache.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. * arch/metag/mm/cache.c
  3. *
  4. * Copyright (C) 2001, 2002, 2005, 2007, 2012 Imagination Technologies.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU General Public License version 2 as published by the
  8. * Free Software Foundation.
  9. *
  10. * Cache control code
  11. */
  12. #include <linux/export.h>
  13. #include <linux/io.h>
  14. #include <asm/cacheflush.h>
  15. #include <asm/core_reg.h>
  16. #include <asm/global_lock.h>
  17. #include <asm/metag_isa.h>
  18. #include <asm/metag_mem.h>
  19. #include <asm/metag_regs.h>
  20. #define DEFAULT_CACHE_WAYS_LOG2 2
  21. /*
  22. * Size of a set in the caches. Initialised for default 16K stride, adjusted
  23. * according to values passed through TBI global heap segment via LDLK (on ATP)
  24. * or config registers (on HTP/MTP)
  25. */
  26. static int dcache_set_shift = METAG_TBI_CACHE_SIZE_BASE_LOG2
  27. - DEFAULT_CACHE_WAYS_LOG2;
  28. static int icache_set_shift = METAG_TBI_CACHE_SIZE_BASE_LOG2
  29. - DEFAULT_CACHE_WAYS_LOG2;
  30. /*
  31. * The number of sets in the caches. Initialised for HTP/ATP, adjusted
  32. * according to NOMMU setting in config registers
  33. */
  34. static unsigned char dcache_sets_log2 = DEFAULT_CACHE_WAYS_LOG2;
  35. static unsigned char icache_sets_log2 = DEFAULT_CACHE_WAYS_LOG2;
  36. #ifndef CONFIG_METAG_META12
  37. /**
  38. * metag_lnkget_probe() - Probe whether lnkget/lnkset go around the cache
  39. */
  40. static volatile u32 lnkget_testdata[16] __initdata __aligned(64);
  41. #define LNKGET_CONSTANT 0xdeadbeef
  42. static void __init metag_lnkget_probe(void)
  43. {
  44. int temp;
  45. long flags;
  46. /*
  47. * It's conceivable the user has configured a globally coherent cache
  48. * shared with non-Linux hardware threads, so use LOCK2 to prevent them
  49. * from executing and causing cache eviction during the test.
  50. */
  51. __global_lock2(flags);
  52. /* read a value to bring it into the cache */
  53. (void)lnkget_testdata[0];
  54. lnkget_testdata[0] = 0;
  55. /* lnkget/lnkset it to modify it */
  56. asm volatile(
  57. "1: LNKGETD %0, [%1]\n"
  58. " LNKSETD [%1], %2\n"
  59. " DEFR %0, TXSTAT\n"
  60. " ANDT %0, %0, #HI(0x3f000000)\n"
  61. " CMPT %0, #HI(0x02000000)\n"
  62. " BNZ 1b\n"
  63. : "=&d" (temp)
  64. : "da" (&lnkget_testdata[0]), "bd" (LNKGET_CONSTANT)
  65. : "cc");
  66. /* re-read it to see if the cached value changed */
  67. temp = lnkget_testdata[0];
  68. __global_unlock2(flags);
  69. /* flush the cache line to fix any incoherency */
  70. __builtin_dcache_flush((void *)&lnkget_testdata[0]);
  71. #if defined(CONFIG_METAG_LNKGET_AROUND_CACHE)
  72. /* if the cache is right, LNKGET_AROUND_CACHE is unnecessary */
  73. if (temp == LNKGET_CONSTANT)
  74. pr_info("LNKGET/SET go through cache but CONFIG_METAG_LNKGET_AROUND_CACHE=y\n");
  75. #elif defined(CONFIG_METAG_ATOMICITY_LNKGET)
  76. /*
  77. * if the cache is wrong, LNKGET_AROUND_CACHE is really necessary
  78. * because the kernel is configured to use LNKGET/SET for atomicity
  79. */
  80. WARN(temp != LNKGET_CONSTANT,
  81. "LNKGET/SET go around cache but CONFIG_METAG_LNKGET_AROUND_CACHE=n\n"
  82. "Expect kernel failure as it's used for atomicity primitives\n");
  83. #elif defined(CONFIG_SMP)
  84. /*
  85. * if the cache is wrong, LNKGET_AROUND_CACHE should be used or the
  86. * gateway page won't flush and userland could break.
  87. */
  88. WARN(temp != LNKGET_CONSTANT,
  89. "LNKGET/SET go around cache but CONFIG_METAG_LNKGET_AROUND_CACHE=n\n"
  90. "Expect userland failure as it's used for user gateway page\n");
  91. #else
  92. /*
  93. * if the cache is wrong, LNKGET_AROUND_CACHE is set wrong, but it
  94. * doesn't actually matter as it doesn't have any effect on !SMP &&
  95. * !ATOMICITY_LNKGET.
  96. */
  97. if (temp != LNKGET_CONSTANT)
  98. pr_warn("LNKGET/SET go around cache but CONFIG_METAG_LNKGET_AROUND_CACHE=n\n");
  99. #endif
  100. }
  101. #endif /* !CONFIG_METAG_META12 */
  102. /**
  103. * metag_cache_probe() - Probe L1 cache configuration.
  104. *
  105. * Probe the L1 cache configuration to aid the L1 physical cache flushing
  106. * functions.
  107. */
  108. void __init metag_cache_probe(void)
  109. {
  110. #ifndef CONFIG_METAG_META12
  111. int coreid = metag_in32(METAC_CORE_ID);
  112. int config = metag_in32(METAC_CORE_CONFIG2);
  113. int cfgcache = coreid & METAC_COREID_CFGCACHE_BITS;
  114. if (cfgcache == METAC_COREID_CFGCACHE_TYPE0 ||
  115. cfgcache == METAC_COREID_CFGCACHE_PRIVNOMMU) {
  116. icache_sets_log2 = 1;
  117. dcache_sets_log2 = 1;
  118. }
  119. /* For normal size caches, the smallest size is 4Kb.
  120. For small caches, the smallest size is 64b */
  121. icache_set_shift = (config & METAC_CORECFG2_ICSMALL_BIT)
  122. ? 6 : 12;
  123. icache_set_shift += (config & METAC_CORE_C2ICSZ_BITS)
  124. >> METAC_CORE_C2ICSZ_S;
  125. icache_set_shift -= icache_sets_log2;
  126. dcache_set_shift = (config & METAC_CORECFG2_DCSMALL_BIT)
  127. ? 6 : 12;
  128. dcache_set_shift += (config & METAC_CORECFG2_DCSZ_BITS)
  129. >> METAC_CORECFG2_DCSZ_S;
  130. dcache_set_shift -= dcache_sets_log2;
  131. metag_lnkget_probe();
  132. #else
  133. /* Extract cache sizes from global heap segment */
  134. unsigned long val, u;
  135. int width, shift, addend;
  136. PTBISEG seg;
  137. seg = __TBIFindSeg(NULL, TBID_SEG(TBID_THREAD_GLOBAL,
  138. TBID_SEGSCOPE_GLOBAL,
  139. TBID_SEGTYPE_HEAP));
  140. if (seg != NULL) {
  141. val = seg->Data[1];
  142. /* Work out width of I-cache size bit-field */
  143. u = ((unsigned long) METAG_TBI_ICACHE_SIZE_BITS)
  144. >> METAG_TBI_ICACHE_SIZE_S;
  145. width = 0;
  146. while (u & 1) {
  147. width++;
  148. u >>= 1;
  149. }
  150. /* Extract sign-extended size addend value */
  151. shift = 32 - (METAG_TBI_ICACHE_SIZE_S + width);
  152. addend = (long) ((val & METAG_TBI_ICACHE_SIZE_BITS)
  153. << shift)
  154. >> (shift + METAG_TBI_ICACHE_SIZE_S);
  155. /* Now calculate I-cache set size */
  156. icache_set_shift = (METAG_TBI_CACHE_SIZE_BASE_LOG2
  157. - DEFAULT_CACHE_WAYS_LOG2)
  158. + addend;
  159. /* Similarly for D-cache */
  160. u = ((unsigned long) METAG_TBI_DCACHE_SIZE_BITS)
  161. >> METAG_TBI_DCACHE_SIZE_S;
  162. width = 0;
  163. while (u & 1) {
  164. width++;
  165. u >>= 1;
  166. }
  167. shift = 32 - (METAG_TBI_DCACHE_SIZE_S + width);
  168. addend = (long) ((val & METAG_TBI_DCACHE_SIZE_BITS)
  169. << shift)
  170. >> (shift + METAG_TBI_DCACHE_SIZE_S);
  171. dcache_set_shift = (METAG_TBI_CACHE_SIZE_BASE_LOG2
  172. - DEFAULT_CACHE_WAYS_LOG2)
  173. + addend;
  174. }
  175. #endif
  176. }
  177. static void metag_phys_data_cache_flush(const void *start)
  178. {
  179. unsigned long flush0, flush1, flush2, flush3;
  180. int loops, step;
  181. int thread;
  182. int part, offset;
  183. int set_shift;
  184. /* Use a sequence of writes to flush the cache region requested */
  185. thread = (__core_reg_get(TXENABLE) & TXENABLE_THREAD_BITS)
  186. >> TXENABLE_THREAD_S;
  187. /* Cache is broken into sets which lie in contiguous RAMs */
  188. set_shift = dcache_set_shift;
  189. /* Move to the base of the physical cache flush region */
  190. flush0 = LINSYSCFLUSH_DCACHE_LINE;
  191. step = 64;
  192. /* Get partition data for this thread */
  193. part = metag_in32(SYSC_DCPART0 +
  194. (SYSC_xCPARTn_STRIDE * thread));
  195. if ((int)start < 0)
  196. /* Access Global vs Local partition */
  197. part >>= SYSC_xCPARTG_AND_S
  198. - SYSC_xCPARTL_AND_S;
  199. /* Extract offset and move SetOff */
  200. offset = (part & SYSC_xCPARTL_OR_BITS)
  201. >> SYSC_xCPARTL_OR_S;
  202. flush0 += (offset << (set_shift - 4));
  203. /* Shrink size */
  204. part = (part & SYSC_xCPARTL_AND_BITS)
  205. >> SYSC_xCPARTL_AND_S;
  206. loops = ((part + 1) << (set_shift - 4));
  207. /* Reduce loops by step of cache line size */
  208. loops /= step;
  209. flush1 = flush0 + (1 << set_shift);
  210. flush2 = flush0 + (2 << set_shift);
  211. flush3 = flush0 + (3 << set_shift);
  212. if (dcache_sets_log2 == 1) {
  213. flush2 = flush1;
  214. flush3 = flush1 + step;
  215. flush1 = flush0 + step;
  216. step <<= 1;
  217. loops >>= 1;
  218. }
  219. /* Clear loops ways in cache */
  220. while (loops-- != 0) {
  221. /* Clear the ways. */
  222. #if 0
  223. /*
  224. * GCC doesn't generate very good code for this so we
  225. * provide inline assembly instead.
  226. */
  227. metag_out8(0, flush0);
  228. metag_out8(0, flush1);
  229. metag_out8(0, flush2);
  230. metag_out8(0, flush3);
  231. flush0 += step;
  232. flush1 += step;
  233. flush2 += step;
  234. flush3 += step;
  235. #else
  236. asm volatile (
  237. "SETB\t[%0+%4++],%5\n"
  238. "SETB\t[%1+%4++],%5\n"
  239. "SETB\t[%2+%4++],%5\n"
  240. "SETB\t[%3+%4++],%5\n"
  241. : "+e" (flush0),
  242. "+e" (flush1),
  243. "+e" (flush2),
  244. "+e" (flush3)
  245. : "e" (step), "a" (0));
  246. #endif
  247. }
  248. }
  249. void metag_data_cache_flush_all(const void *start)
  250. {
  251. if ((metag_in32(SYSC_CACHE_MMU_CONFIG) & SYSC_CMMUCFG_DC_ON_BIT) == 0)
  252. /* No need to flush the data cache it's not actually enabled */
  253. return;
  254. metag_phys_data_cache_flush(start);
  255. }
  256. void metag_data_cache_flush(const void *start, int bytes)
  257. {
  258. unsigned long flush0;
  259. int loops, step;
  260. if ((metag_in32(SYSC_CACHE_MMU_CONFIG) & SYSC_CMMUCFG_DC_ON_BIT) == 0)
  261. /* No need to flush the data cache it's not actually enabled */
  262. return;
  263. if (bytes >= 4096) {
  264. metag_phys_data_cache_flush(start);
  265. return;
  266. }
  267. /* Use linear cache flush mechanism on META IP */
  268. flush0 = (int)start;
  269. loops = ((int)start & (DCACHE_LINE_BYTES - 1)) + bytes +
  270. (DCACHE_LINE_BYTES - 1);
  271. loops >>= DCACHE_LINE_S;
  272. #define PRIM_FLUSH(addr, offset) do { \
  273. int __addr = ((int) (addr)) + ((offset) * 64); \
  274. __builtin_dcache_flush((void *)(__addr)); \
  275. } while (0)
  276. #define LOOP_INC (4*64)
  277. do {
  278. /* By default stop */
  279. step = 0;
  280. switch (loops) {
  281. /* Drop Thru Cases! */
  282. default:
  283. PRIM_FLUSH(flush0, 3);
  284. loops -= 4;
  285. step = 1;
  286. case 3:
  287. PRIM_FLUSH(flush0, 2);
  288. case 2:
  289. PRIM_FLUSH(flush0, 1);
  290. case 1:
  291. PRIM_FLUSH(flush0, 0);
  292. flush0 += LOOP_INC;
  293. case 0:
  294. break;
  295. }
  296. } while (step);
  297. }
  298. EXPORT_SYMBOL(metag_data_cache_flush);
  299. static void metag_phys_code_cache_flush(const void *start, int bytes)
  300. {
  301. unsigned long flush0, flush1, flush2, flush3, end_set;
  302. int loops, step;
  303. int thread;
  304. int set_shift, set_size;
  305. int part, offset;
  306. /* Use a sequence of writes to flush the cache region requested */
  307. thread = (__core_reg_get(TXENABLE) & TXENABLE_THREAD_BITS)
  308. >> TXENABLE_THREAD_S;
  309. set_shift = icache_set_shift;
  310. /* Move to the base of the physical cache flush region */
  311. flush0 = LINSYSCFLUSH_ICACHE_LINE;
  312. step = 64;
  313. /* Get partition code for this thread */
  314. part = metag_in32(SYSC_ICPART0 +
  315. (SYSC_xCPARTn_STRIDE * thread));
  316. if ((int)start < 0)
  317. /* Access Global vs Local partition */
  318. part >>= SYSC_xCPARTG_AND_S-SYSC_xCPARTL_AND_S;
  319. /* Extract offset and move SetOff */
  320. offset = (part & SYSC_xCPARTL_OR_BITS)
  321. >> SYSC_xCPARTL_OR_S;
  322. flush0 += (offset << (set_shift - 4));
  323. /* Shrink size */
  324. part = (part & SYSC_xCPARTL_AND_BITS)
  325. >> SYSC_xCPARTL_AND_S;
  326. loops = ((part + 1) << (set_shift - 4));
  327. /* Where does the Set end? */
  328. end_set = flush0 + loops;
  329. set_size = loops;
  330. #ifdef CONFIG_METAG_META12
  331. if ((bytes < 4096) && (bytes < loops)) {
  332. /* Unreachable on HTP/MTP */
  333. /* Only target the sets that could be relavent */
  334. flush0 += (loops - step) & ((int) start);
  335. loops = (((int) start) & (step-1)) + bytes + step - 1;
  336. }
  337. #endif
  338. /* Reduce loops by step of cache line size */
  339. loops /= step;
  340. flush1 = flush0 + (1<<set_shift);
  341. flush2 = flush0 + (2<<set_shift);
  342. flush3 = flush0 + (3<<set_shift);
  343. if (icache_sets_log2 == 1) {
  344. flush2 = flush1;
  345. flush3 = flush1 + step;
  346. flush1 = flush0 + step;
  347. #if 0
  348. /* flush0 will stop one line early in this case
  349. * (flush1 will do the final line).
  350. * However we don't correct end_set here at the moment
  351. * because it will never wrap on HTP/MTP
  352. */
  353. end_set -= step;
  354. #endif
  355. step <<= 1;
  356. loops >>= 1;
  357. }
  358. /* Clear loops ways in cache */
  359. while (loops-- != 0) {
  360. #if 0
  361. /*
  362. * GCC doesn't generate very good code for this so we
  363. * provide inline assembly instead.
  364. */
  365. /* Clear the ways */
  366. metag_out8(0, flush0);
  367. metag_out8(0, flush1);
  368. metag_out8(0, flush2);
  369. metag_out8(0, flush3);
  370. flush0 += step;
  371. flush1 += step;
  372. flush2 += step;
  373. flush3 += step;
  374. #else
  375. asm volatile (
  376. "SETB\t[%0+%4++],%5\n"
  377. "SETB\t[%1+%4++],%5\n"
  378. "SETB\t[%2+%4++],%5\n"
  379. "SETB\t[%3+%4++],%5\n"
  380. : "+e" (flush0),
  381. "+e" (flush1),
  382. "+e" (flush2),
  383. "+e" (flush3)
  384. : "e" (step), "a" (0));
  385. #endif
  386. if (flush0 == end_set) {
  387. /* Wrap within Set 0 */
  388. flush0 -= set_size;
  389. flush1 -= set_size;
  390. flush2 -= set_size;
  391. flush3 -= set_size;
  392. }
  393. }
  394. }
  395. void metag_code_cache_flush_all(const void *start)
  396. {
  397. if ((metag_in32(SYSC_CACHE_MMU_CONFIG) & SYSC_CMMUCFG_IC_ON_BIT) == 0)
  398. /* No need to flush the code cache it's not actually enabled */
  399. return;
  400. metag_phys_code_cache_flush(start, 4096);
  401. }
  402. EXPORT_SYMBOL(metag_code_cache_flush_all);
  403. void metag_code_cache_flush(const void *start, int bytes)
  404. {
  405. #ifndef CONFIG_METAG_META12
  406. void *flush;
  407. int loops, step;
  408. #endif /* !CONFIG_METAG_META12 */
  409. if ((metag_in32(SYSC_CACHE_MMU_CONFIG) & SYSC_CMMUCFG_IC_ON_BIT) == 0)
  410. /* No need to flush the code cache it's not actually enabled */
  411. return;
  412. #ifdef CONFIG_METAG_META12
  413. /* CACHEWD isn't available on Meta1, so always do full cache flush */
  414. metag_phys_code_cache_flush(start, bytes);
  415. #else /* CONFIG_METAG_META12 */
  416. /* If large size do full physical cache flush */
  417. if (bytes >= 4096) {
  418. metag_phys_code_cache_flush(start, bytes);
  419. return;
  420. }
  421. /* Use linear cache flush mechanism on META IP */
  422. flush = (void *)((int)start & ~(ICACHE_LINE_BYTES-1));
  423. loops = ((int)start & (ICACHE_LINE_BYTES-1)) + bytes +
  424. (ICACHE_LINE_BYTES-1);
  425. loops >>= ICACHE_LINE_S;
  426. #define PRIM_IFLUSH(addr, offset) \
  427. __builtin_meta2_cachewd(((addr) + ((offset) * 64)), CACHEW_ICACHE_BIT)
  428. #define LOOP_INC (4*64)
  429. do {
  430. /* By default stop */
  431. step = 0;
  432. switch (loops) {
  433. /* Drop Thru Cases! */
  434. default:
  435. PRIM_IFLUSH(flush, 3);
  436. loops -= 4;
  437. step = 1;
  438. case 3:
  439. PRIM_IFLUSH(flush, 2);
  440. case 2:
  441. PRIM_IFLUSH(flush, 1);
  442. case 1:
  443. PRIM_IFLUSH(flush, 0);
  444. flush += LOOP_INC;
  445. case 0:
  446. break;
  447. }
  448. } while (step);
  449. #endif /* !CONFIG_METAG_META12 */
  450. }
  451. EXPORT_SYMBOL(metag_code_cache_flush);