cache.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <config.h>
  7. #include <common.h>
  8. #include <linux/compiler.h>
  9. #include <linux/kernel.h>
  10. #include <asm/arcregs.h>
  11. #include <asm/cache.h>
  12. /* Bit values in IC_CTRL */
  13. #define IC_CTRL_CACHE_DISABLE (1 << 0)
  14. /* Bit values in DC_CTRL */
  15. #define DC_CTRL_CACHE_DISABLE (1 << 0)
  16. #define DC_CTRL_INV_MODE_FLUSH (1 << 6)
  17. #define DC_CTRL_FLUSH_STATUS (1 << 8)
  18. #define CACHE_VER_NUM_MASK 0xF
  19. #define SLC_CTRL_SB (1 << 2)
  20. #define OP_INV 0x1
  21. #define OP_FLUSH 0x2
  22. #define OP_INV_IC 0x3
  23. /*
  24. * By default that variable will fall into .bss section.
  25. * But .bss section is not relocated and so it will be initilized before
  26. * relocation but will be used after being zeroed.
  27. */
  28. int l1_line_sz __section(".data");
  29. int dcache_exists __section(".data");
  30. int icache_exists __section(".data");
  31. #define CACHE_LINE_MASK (~(l1_line_sz - 1))
  32. #ifdef CONFIG_ISA_ARCV2
  33. int slc_line_sz __section(".data");
  34. int slc_exists __section(".data");
  35. int ioc_exists __section(".data");
  36. static unsigned int __before_slc_op(const int op)
  37. {
  38. unsigned int reg = reg;
  39. if (op == OP_INV) {
  40. /*
  41. * IM is set by default and implies Flush-n-inv
  42. * Clear it here for vanilla inv
  43. */
  44. reg = read_aux_reg(ARC_AUX_SLC_CTRL);
  45. write_aux_reg(ARC_AUX_SLC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH);
  46. }
  47. return reg;
  48. }
  49. static void __after_slc_op(const int op, unsigned int reg)
  50. {
  51. if (op & OP_FLUSH) { /* flush / flush-n-inv both wait */
  52. /*
  53. * Make sure "busy" bit reports correct status,
  54. * see STAR 9001165532
  55. */
  56. read_aux_reg(ARC_AUX_SLC_CTRL);
  57. while (read_aux_reg(ARC_AUX_SLC_CTRL) &
  58. DC_CTRL_FLUSH_STATUS)
  59. ;
  60. }
  61. /* Switch back to default Invalidate mode */
  62. if (op == OP_INV)
  63. write_aux_reg(ARC_AUX_SLC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH);
  64. }
  65. static inline void __slc_line_loop(unsigned long paddr, unsigned long sz,
  66. const int op)
  67. {
  68. unsigned int aux_cmd;
  69. int num_lines;
  70. #define SLC_LINE_MASK (~(slc_line_sz - 1))
  71. aux_cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL;
  72. sz += paddr & ~SLC_LINE_MASK;
  73. paddr &= SLC_LINE_MASK;
  74. num_lines = DIV_ROUND_UP(sz, slc_line_sz);
  75. while (num_lines-- > 0) {
  76. write_aux_reg(aux_cmd, paddr);
  77. paddr += slc_line_sz;
  78. }
  79. }
  80. static inline void __slc_entire_op(const int cacheop)
  81. {
  82. int aux;
  83. unsigned int ctrl_reg = __before_slc_op(cacheop);
  84. if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */
  85. aux = ARC_AUX_SLC_INVALIDATE;
  86. else
  87. aux = ARC_AUX_SLC_FLUSH;
  88. write_aux_reg(aux, 0x1);
  89. __after_slc_op(cacheop, ctrl_reg);
  90. }
  91. static inline void __slc_line_op(unsigned long paddr, unsigned long sz,
  92. const int cacheop)
  93. {
  94. unsigned int ctrl_reg = __before_slc_op(cacheop);
  95. __slc_line_loop(paddr, sz, cacheop);
  96. __after_slc_op(cacheop, ctrl_reg);
  97. }
  98. #else
  99. #define __slc_entire_op(cacheop)
  100. #define __slc_line_op(paddr, sz, cacheop)
  101. #endif
  102. #ifdef CONFIG_ISA_ARCV2
  103. static void read_decode_cache_bcr_arcv2(void)
  104. {
  105. union {
  106. struct {
  107. #ifdef CONFIG_CPU_BIG_ENDIAN
  108. unsigned int pad:24, way:2, lsz:2, sz:4;
  109. #else
  110. unsigned int sz:4, lsz:2, way:2, pad:24;
  111. #endif
  112. } fields;
  113. unsigned int word;
  114. } slc_cfg;
  115. union {
  116. struct {
  117. #ifdef CONFIG_CPU_BIG_ENDIAN
  118. unsigned int pad:24, ver:8;
  119. #else
  120. unsigned int ver:8, pad:24;
  121. #endif
  122. } fields;
  123. unsigned int word;
  124. } sbcr;
  125. sbcr.word = read_aux_reg(ARC_BCR_SLC);
  126. if (sbcr.fields.ver) {
  127. slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG);
  128. slc_exists = 1;
  129. slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64;
  130. }
  131. union {
  132. struct bcr_clust_cfg {
  133. #ifdef CONFIG_CPU_BIG_ENDIAN
  134. unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8;
  135. #else
  136. unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7;
  137. #endif
  138. } fields;
  139. unsigned int word;
  140. } cbcr;
  141. cbcr.word = read_aux_reg(ARC_BCR_CLUSTER);
  142. if (cbcr.fields.c)
  143. ioc_exists = 1;
  144. }
  145. #endif
  146. void read_decode_cache_bcr(void)
  147. {
  148. int dc_line_sz = 0, ic_line_sz = 0;
  149. union {
  150. struct {
  151. #ifdef CONFIG_CPU_BIG_ENDIAN
  152. unsigned int pad:12, line_len:4, sz:4, config:4, ver:8;
  153. #else
  154. unsigned int ver:8, config:4, sz:4, line_len:4, pad:12;
  155. #endif
  156. } fields;
  157. unsigned int word;
  158. } ibcr, dbcr;
  159. ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
  160. if (ibcr.fields.ver) {
  161. icache_exists = 1;
  162. l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len;
  163. if (!ic_line_sz)
  164. panic("Instruction exists but line length is 0\n");
  165. }
  166. dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
  167. if (dbcr.fields.ver){
  168. dcache_exists = 1;
  169. l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len;
  170. if (!dc_line_sz)
  171. panic("Data cache exists but line length is 0\n");
  172. }
  173. if (ic_line_sz && dc_line_sz && (ic_line_sz != dc_line_sz))
  174. panic("Instruction and data cache line lengths differ\n");
  175. }
  176. void cache_init(void)
  177. {
  178. read_decode_cache_bcr();
  179. #ifdef CONFIG_ISA_ARCV2
  180. read_decode_cache_bcr_arcv2();
  181. if (ioc_exists) {
  182. flush_dcache_all();
  183. invalidate_dcache_all();
  184. /* IO coherency base - 0x8z */
  185. write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, 0x80000);
  186. /* IO coherency aperture size - 512Mb: 0x8z-0xAz */
  187. write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, 0x11);
  188. /* Enable partial writes */
  189. write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1);
  190. /* Enable IO coherency */
  191. write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1);
  192. }
  193. #endif
  194. }
  195. int icache_status(void)
  196. {
  197. if (!icache_exists)
  198. return 0;
  199. if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE)
  200. return 0;
  201. else
  202. return 1;
  203. }
  204. void icache_enable(void)
  205. {
  206. if (icache_exists)
  207. write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
  208. ~IC_CTRL_CACHE_DISABLE);
  209. }
  210. void icache_disable(void)
  211. {
  212. if (icache_exists)
  213. write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
  214. IC_CTRL_CACHE_DISABLE);
  215. }
  216. #ifndef CONFIG_SYS_DCACHE_OFF
  217. void invalidate_icache_all(void)
  218. {
  219. /* Any write to IC_IVIC register triggers invalidation of entire I$ */
  220. if (icache_status()) {
  221. write_aux_reg(ARC_AUX_IC_IVIC, 1);
  222. read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */
  223. }
  224. }
  225. #else
  226. void invalidate_icache_all(void)
  227. {
  228. }
  229. #endif
  230. int dcache_status(void)
  231. {
  232. if (!dcache_exists)
  233. return 0;
  234. if (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE)
  235. return 0;
  236. else
  237. return 1;
  238. }
  239. void dcache_enable(void)
  240. {
  241. if (!dcache_exists)
  242. return;
  243. write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
  244. ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
  245. }
  246. void dcache_disable(void)
  247. {
  248. if (!dcache_exists)
  249. return;
  250. write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
  251. DC_CTRL_CACHE_DISABLE);
  252. }
  253. #ifndef CONFIG_SYS_DCACHE_OFF
  254. /*
  255. * Common Helper for Line Operations on {I,D}-Cache
  256. */
  257. static inline void __cache_line_loop(unsigned long paddr, unsigned long sz,
  258. const int cacheop)
  259. {
  260. unsigned int aux_cmd;
  261. #if (CONFIG_ARC_MMU_VER == 3)
  262. unsigned int aux_tag;
  263. #endif
  264. int num_lines;
  265. if (cacheop == OP_INV_IC) {
  266. aux_cmd = ARC_AUX_IC_IVIL;
  267. #if (CONFIG_ARC_MMU_VER == 3)
  268. aux_tag = ARC_AUX_IC_PTAG;
  269. #endif
  270. } else {
  271. /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
  272. aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL;
  273. #if (CONFIG_ARC_MMU_VER == 3)
  274. aux_tag = ARC_AUX_DC_PTAG;
  275. #endif
  276. }
  277. sz += paddr & ~CACHE_LINE_MASK;
  278. paddr &= CACHE_LINE_MASK;
  279. num_lines = DIV_ROUND_UP(sz, l1_line_sz);
  280. while (num_lines-- > 0) {
  281. #if (CONFIG_ARC_MMU_VER == 3)
  282. write_aux_reg(aux_tag, paddr);
  283. #endif
  284. write_aux_reg(aux_cmd, paddr);
  285. paddr += l1_line_sz;
  286. }
  287. }
  288. static unsigned int __before_dc_op(const int op)
  289. {
  290. unsigned int reg;
  291. if (op == OP_INV) {
  292. /*
  293. * IM is set by default and implies Flush-n-inv
  294. * Clear it here for vanilla inv
  295. */
  296. reg = read_aux_reg(ARC_AUX_DC_CTRL);
  297. write_aux_reg(ARC_AUX_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH);
  298. }
  299. return reg;
  300. }
  301. static void __after_dc_op(const int op, unsigned int reg)
  302. {
  303. if (op & OP_FLUSH) /* flush / flush-n-inv both wait */
  304. while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
  305. ;
  306. /* Switch back to default Invalidate mode */
  307. if (op == OP_INV)
  308. write_aux_reg(ARC_AUX_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH);
  309. }
  310. static inline void __dc_entire_op(const int cacheop)
  311. {
  312. int aux;
  313. unsigned int ctrl_reg = __before_dc_op(cacheop);
  314. if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */
  315. aux = ARC_AUX_DC_IVDC;
  316. else
  317. aux = ARC_AUX_DC_FLSH;
  318. write_aux_reg(aux, 0x1);
  319. __after_dc_op(cacheop, ctrl_reg);
  320. }
  321. static inline void __dc_line_op(unsigned long paddr, unsigned long sz,
  322. const int cacheop)
  323. {
  324. unsigned int ctrl_reg = __before_dc_op(cacheop);
  325. __cache_line_loop(paddr, sz, cacheop);
  326. __after_dc_op(cacheop, ctrl_reg);
  327. }
  328. #else
  329. #define __dc_entire_op(cacheop)
  330. #define __dc_line_op(paddr, sz, cacheop)
  331. #endif /* !CONFIG_SYS_DCACHE_OFF */
  332. void invalidate_dcache_range(unsigned long start, unsigned long end)
  333. {
  334. #ifdef CONFIG_ISA_ARCV2
  335. if (!ioc_exists)
  336. #endif
  337. __dc_line_op(start, end - start, OP_INV);
  338. #ifdef CONFIG_ISA_ARCV2
  339. if (slc_exists && !ioc_exists)
  340. __slc_line_op(start, end - start, OP_INV);
  341. #endif
  342. }
  343. void flush_dcache_range(unsigned long start, unsigned long end)
  344. {
  345. #ifdef CONFIG_ISA_ARCV2
  346. if (!ioc_exists)
  347. #endif
  348. __dc_line_op(start, end - start, OP_FLUSH);
  349. #ifdef CONFIG_ISA_ARCV2
  350. if (slc_exists && !ioc_exists)
  351. __slc_line_op(start, end - start, OP_FLUSH);
  352. #endif
  353. }
  354. void flush_cache(unsigned long start, unsigned long size)
  355. {
  356. flush_dcache_range(start, start + size);
  357. }
  358. void invalidate_dcache_all(void)
  359. {
  360. __dc_entire_op(OP_INV);
  361. #ifdef CONFIG_ISA_ARCV2
  362. if (slc_exists)
  363. __slc_entire_op(OP_INV);
  364. #endif
  365. }
  366. void flush_dcache_all(void)
  367. {
  368. __dc_entire_op(OP_FLUSH);
  369. #ifdef CONFIG_ISA_ARCV2
  370. if (slc_exists)
  371. __slc_entire_op(OP_FLUSH);
  372. #endif
  373. }