cache.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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 <linux/log2.h>
  11. #include <asm/arcregs.h>
  12. #include <asm/arc-bcr.h>
  13. #include <asm/cache.h>
  14. /*
  15. * [ NOTE 1 ]:
  16. * Data cache (L1 D$ or SL$) entire invalidate operation or data cache disable
  17. * operation may result in unexpected behavior and data loss even if we flush
  18. * data cache right before invalidation. That may happens if we store any context
  19. * on stack (like we store BLINK register on stack before function call).
  20. * BLINK register is the register where return address is automatically saved
  21. * when we do function call with instructions like 'bl'.
  22. *
  23. * There is the real example:
  24. * We may hang in the next code as we store any BLINK register on stack in
  25. * invalidate_dcache_all() function.
  26. *
  27. * void flush_dcache_all() {
  28. * __dc_entire_op(OP_FLUSH);
  29. * // Other code //
  30. * }
  31. *
  32. * void invalidate_dcache_all() {
  33. * __dc_entire_op(OP_INV);
  34. * // Other code //
  35. * }
  36. *
  37. * void foo(void) {
  38. * flush_dcache_all();
  39. * invalidate_dcache_all();
  40. * }
  41. *
  42. * Now let's see what really happens during that code execution:
  43. *
  44. * foo()
  45. * |->> call flush_dcache_all
  46. * [return address is saved to BLINK register]
  47. * [push BLINK] (save to stack) ![point 1]
  48. * |->> call __dc_entire_op(OP_FLUSH)
  49. * [return address is saved to BLINK register]
  50. * [flush L1 D$]
  51. * return [jump to BLINK]
  52. * <<------
  53. * [other flush_dcache_all code]
  54. * [pop BLINK] (get from stack)
  55. * return [jump to BLINK]
  56. * <<------
  57. * |->> call invalidate_dcache_all
  58. * [return address is saved to BLINK register]
  59. * [push BLINK] (save to stack) ![point 2]
  60. * |->> call __dc_entire_op(OP_FLUSH)
  61. * [return address is saved to BLINK register]
  62. * [invalidate L1 D$] ![point 3]
  63. * // Oops!!!
  64. * // We lose return address from invalidate_dcache_all function:
  65. * // we save it to stack and invalidate L1 D$ after that!
  66. * return [jump to BLINK]
  67. * <<------
  68. * [other invalidate_dcache_all code]
  69. * [pop BLINK] (get from stack)
  70. * // we don't have this data in L1 dcache as we invalidated it in [point 3]
  71. * // so we get it from next memory level (for example DDR memory)
  72. * // but in the memory we have value which we save in [point 1], which
  73. * // is return address from flush_dcache_all function (instead of
  74. * // address from current invalidate_dcache_all function which we
  75. * // saved in [point 2] !)
  76. * return [jump to BLINK]
  77. * <<------
  78. * // As BLINK points to invalidate_dcache_all, we call it again and
  79. * // loop forever.
  80. *
  81. * Fortunately we may fix that by using flush & invalidation of D$ with a single
  82. * one instruction (instead of flush and invalidation instructions pair) and
  83. * enabling force function inline with '__attribute__((always_inline))' gcc
  84. * attribute to avoid any function call (and BLINK store) between cache flush
  85. * and disable.
  86. */
  87. DECLARE_GLOBAL_DATA_PTR;
  88. /* Bit values in IC_CTRL */
  89. #define IC_CTRL_CACHE_DISABLE BIT(0)
  90. /* Bit values in DC_CTRL */
  91. #define DC_CTRL_CACHE_DISABLE BIT(0)
  92. #define DC_CTRL_INV_MODE_FLUSH BIT(6)
  93. #define DC_CTRL_FLUSH_STATUS BIT(8)
  94. #define OP_INV BIT(0)
  95. #define OP_FLUSH BIT(1)
  96. #define OP_FLUSH_N_INV (OP_FLUSH | OP_INV)
  97. /* Bit val in SLC_CONTROL */
  98. #define SLC_CTRL_DIS 0x001
  99. #define SLC_CTRL_IM 0x040
  100. #define SLC_CTRL_BUSY 0x100
  101. #define SLC_CTRL_RGN_OP_INV 0x200
  102. /*
  103. * By default that variable will fall into .bss section.
  104. * But .bss section is not relocated and so it will be initilized before
  105. * relocation but will be used after being zeroed.
  106. */
  107. #define CACHE_LINE_MASK (~(gd->arch.l1_line_sz - 1))
  108. bool ioc_exists __section(".data") = false;
  109. /* To force enable IOC set ioc_enable to 'true' */
  110. bool ioc_enable __section(".data") = false;
  111. static inline bool pae_exists(void)
  112. {
  113. /* TODO: should we compare mmu version from BCR and from CONFIG? */
  114. #if (CONFIG_ARC_MMU_VER >= 4)
  115. union bcr_mmu_4 mmu4;
  116. mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR);
  117. if (mmu4.fields.pae)
  118. return true;
  119. #endif /* (CONFIG_ARC_MMU_VER >= 4) */
  120. return false;
  121. }
  122. static inline bool icache_exists(void)
  123. {
  124. union bcr_di_cache ibcr;
  125. ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
  126. return !!ibcr.fields.ver;
  127. }
  128. static inline bool dcache_exists(void)
  129. {
  130. union bcr_di_cache dbcr;
  131. dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
  132. return !!dbcr.fields.ver;
  133. }
  134. static inline bool slc_exists(void)
  135. {
  136. if (is_isa_arcv2()) {
  137. union bcr_generic sbcr;
  138. sbcr.word = read_aux_reg(ARC_BCR_SLC);
  139. return !!sbcr.fields.ver;
  140. }
  141. return false;
  142. }
  143. static void __slc_entire_op(const int op)
  144. {
  145. unsigned int ctrl;
  146. if (!slc_exists())
  147. return;
  148. ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
  149. if (!(op & OP_FLUSH)) /* i.e. OP_INV */
  150. ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */
  151. else
  152. ctrl |= SLC_CTRL_IM;
  153. write_aux_reg(ARC_AUX_SLC_CTRL, ctrl);
  154. if (op & OP_INV) /* Inv or flush-n-inv use same cmd reg */
  155. write_aux_reg(ARC_AUX_SLC_INVALIDATE, 0x1);
  156. else
  157. write_aux_reg(ARC_AUX_SLC_FLUSH, 0x1);
  158. /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */
  159. read_aux_reg(ARC_AUX_SLC_CTRL);
  160. /* Important to wait for flush to complete */
  161. while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY);
  162. }
  163. static void slc_upper_region_init(void)
  164. {
  165. /*
  166. * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist
  167. * only if PAE exists in current HW. So we had to check pae_exist
  168. * before using them.
  169. */
  170. if (!pae_exists())
  171. return;
  172. /*
  173. * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0
  174. * as we don't use PAE40.
  175. */
  176. write_aux_reg(ARC_AUX_SLC_RGN_END1, 0);
  177. write_aux_reg(ARC_AUX_SLC_RGN_START1, 0);
  178. }
  179. static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op)
  180. {
  181. #ifdef CONFIG_ISA_ARCV2
  182. unsigned int ctrl;
  183. unsigned long end;
  184. if (!slc_exists())
  185. return;
  186. /*
  187. * The Region Flush operation is specified by CTRL.RGN_OP[11..9]
  188. * - b'000 (default) is Flush,
  189. * - b'001 is Invalidate if CTRL.IM == 0
  190. * - b'001 is Flush-n-Invalidate if CTRL.IM == 1
  191. */
  192. ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
  193. /* Don't rely on default value of IM bit */
  194. if (!(op & OP_FLUSH)) /* i.e. OP_INV */
  195. ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */
  196. else
  197. ctrl |= SLC_CTRL_IM;
  198. if (op & OP_INV)
  199. ctrl |= SLC_CTRL_RGN_OP_INV; /* Inv or flush-n-inv */
  200. else
  201. ctrl &= ~SLC_CTRL_RGN_OP_INV;
  202. write_aux_reg(ARC_AUX_SLC_CTRL, ctrl);
  203. /*
  204. * Lower bits are ignored, no need to clip
  205. * END needs to be setup before START (latter triggers the operation)
  206. * END can't be same as START, so add (l2_line_sz - 1) to sz
  207. */
  208. end = paddr + sz + gd->arch.slc_line_sz - 1;
  209. /*
  210. * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1)
  211. * are always == 0 as we don't use PAE40, so we only setup lower ones
  212. * (ARC_AUX_SLC_RGN_END and ARC_AUX_SLC_RGN_START)
  213. */
  214. write_aux_reg(ARC_AUX_SLC_RGN_END, end);
  215. write_aux_reg(ARC_AUX_SLC_RGN_START, paddr);
  216. /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */
  217. read_aux_reg(ARC_AUX_SLC_CTRL);
  218. while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY);
  219. #endif /* CONFIG_ISA_ARCV2 */
  220. }
  221. static void arc_ioc_setup(void)
  222. {
  223. /* IOC Aperture start is equal to DDR start */
  224. unsigned int ap_base = CONFIG_SYS_SDRAM_BASE;
  225. /* IOC Aperture size is equal to DDR size */
  226. long ap_size = CONFIG_SYS_SDRAM_SIZE;
  227. flush_n_invalidate_dcache_all();
  228. if (!is_power_of_2(ap_size) || ap_size < 4096)
  229. panic("IOC Aperture size must be power of 2 and bigger 4Kib");
  230. /*
  231. * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB,
  232. * so setting 0x11 implies 512M, 0x12 implies 1G...
  233. */
  234. write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE,
  235. order_base_2(ap_size / 1024) - 2);
  236. /* IOC Aperture start must be aligned to the size of the aperture */
  237. if (ap_base % ap_size != 0)
  238. panic("IOC Aperture start must be aligned to the size of the aperture");
  239. write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12);
  240. write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1);
  241. write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1);
  242. }
  243. static void read_decode_cache_bcr_arcv2(void)
  244. {
  245. #ifdef CONFIG_ISA_ARCV2
  246. union bcr_slc_cfg slc_cfg;
  247. union bcr_clust_cfg cbcr;
  248. if (slc_exists()) {
  249. slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG);
  250. gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64;
  251. }
  252. cbcr.word = read_aux_reg(ARC_BCR_CLUSTER);
  253. if (cbcr.fields.c && ioc_enable)
  254. ioc_exists = true;
  255. #endif /* CONFIG_ISA_ARCV2 */
  256. }
  257. void read_decode_cache_bcr(void)
  258. {
  259. int dc_line_sz = 0, ic_line_sz = 0;
  260. union bcr_di_cache ibcr, dbcr;
  261. ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
  262. if (ibcr.fields.ver) {
  263. gd->arch.l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len;
  264. if (!ic_line_sz)
  265. panic("Instruction exists but line length is 0\n");
  266. }
  267. dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
  268. if (dbcr.fields.ver) {
  269. gd->arch.l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len;
  270. if (!dc_line_sz)
  271. panic("Data cache exists but line length is 0\n");
  272. }
  273. if (ic_line_sz && dc_line_sz && (ic_line_sz != dc_line_sz))
  274. panic("Instruction and data cache line lengths differ\n");
  275. }
  276. void cache_init(void)
  277. {
  278. read_decode_cache_bcr();
  279. if (is_isa_arcv2())
  280. read_decode_cache_bcr_arcv2();
  281. if (is_isa_arcv2() && ioc_exists)
  282. arc_ioc_setup();
  283. if (is_isa_arcv2() && slc_exists())
  284. slc_upper_region_init();
  285. }
  286. int icache_status(void)
  287. {
  288. if (!icache_exists())
  289. return 0;
  290. if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE)
  291. return 0;
  292. else
  293. return 1;
  294. }
  295. void icache_enable(void)
  296. {
  297. if (icache_exists())
  298. write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
  299. ~IC_CTRL_CACHE_DISABLE);
  300. }
  301. void icache_disable(void)
  302. {
  303. if (icache_exists())
  304. write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
  305. IC_CTRL_CACHE_DISABLE);
  306. }
  307. /* IC supports only invalidation */
  308. static inline void __ic_entire_invalidate(void)
  309. {
  310. if (!icache_status())
  311. return;
  312. /* Any write to IC_IVIC register triggers invalidation of entire I$ */
  313. write_aux_reg(ARC_AUX_IC_IVIC, 1);
  314. /*
  315. * As per ARC HS databook (see chapter 5.3.3.2)
  316. * it is required to add 3 NOPs after each write to IC_IVIC.
  317. */
  318. __builtin_arc_nop();
  319. __builtin_arc_nop();
  320. __builtin_arc_nop();
  321. read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */
  322. }
  323. void invalidate_icache_all(void)
  324. {
  325. __ic_entire_invalidate();
  326. if (is_isa_arcv2())
  327. __slc_entire_op(OP_INV);
  328. }
  329. int dcache_status(void)
  330. {
  331. if (!dcache_exists())
  332. return 0;
  333. if (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE)
  334. return 0;
  335. else
  336. return 1;
  337. }
  338. void dcache_enable(void)
  339. {
  340. if (!dcache_exists())
  341. return;
  342. write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
  343. ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
  344. }
  345. void dcache_disable(void)
  346. {
  347. if (!dcache_exists())
  348. return;
  349. write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
  350. DC_CTRL_CACHE_DISABLE);
  351. }
  352. /* Common Helper for Line Operations on D-cache */
  353. static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz,
  354. const int cacheop)
  355. {
  356. unsigned int aux_cmd;
  357. int num_lines;
  358. /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
  359. aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL;
  360. sz += paddr & ~CACHE_LINE_MASK;
  361. paddr &= CACHE_LINE_MASK;
  362. num_lines = DIV_ROUND_UP(sz, gd->arch.l1_line_sz);
  363. while (num_lines-- > 0) {
  364. #if (CONFIG_ARC_MMU_VER == 3)
  365. write_aux_reg(ARC_AUX_DC_PTAG, paddr);
  366. #endif
  367. write_aux_reg(aux_cmd, paddr);
  368. paddr += gd->arch.l1_line_sz;
  369. }
  370. }
  371. static void __before_dc_op(const int op)
  372. {
  373. unsigned int ctrl;
  374. ctrl = read_aux_reg(ARC_AUX_DC_CTRL);
  375. /* IM bit implies flush-n-inv, instead of vanilla inv */
  376. if (op == OP_INV)
  377. ctrl &= ~DC_CTRL_INV_MODE_FLUSH;
  378. else
  379. ctrl |= DC_CTRL_INV_MODE_FLUSH;
  380. write_aux_reg(ARC_AUX_DC_CTRL, ctrl);
  381. }
  382. static void __after_dc_op(const int op)
  383. {
  384. if (op & OP_FLUSH) /* flush / flush-n-inv both wait */
  385. while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
  386. }
  387. static inline void __dc_entire_op(const int cacheop)
  388. {
  389. int aux;
  390. if (!dcache_status())
  391. return;
  392. __before_dc_op(cacheop);
  393. if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */
  394. aux = ARC_AUX_DC_IVDC;
  395. else
  396. aux = ARC_AUX_DC_FLSH;
  397. write_aux_reg(aux, 0x1);
  398. __after_dc_op(cacheop);
  399. }
  400. static inline void __dc_line_op(unsigned long paddr, unsigned long sz,
  401. const int cacheop)
  402. {
  403. if (!dcache_status())
  404. return;
  405. __before_dc_op(cacheop);
  406. __dcache_line_loop(paddr, sz, cacheop);
  407. __after_dc_op(cacheop);
  408. }
  409. void invalidate_dcache_range(unsigned long start, unsigned long end)
  410. {
  411. if (start >= end)
  412. return;
  413. /*
  414. * ARCv1 -> call __dc_line_op
  415. * ARCv2 && no IOC -> call __dc_line_op; call __slc_rgn_op
  416. * ARCv2 && IOC enabled -> nothing
  417. */
  418. if (!is_isa_arcv2() || !ioc_exists)
  419. __dc_line_op(start, end - start, OP_INV);
  420. if (is_isa_arcv2() && !ioc_exists)
  421. __slc_rgn_op(start, end - start, OP_INV);
  422. }
  423. void flush_dcache_range(unsigned long start, unsigned long end)
  424. {
  425. if (start >= end)
  426. return;
  427. /*
  428. * ARCv1 -> call __dc_line_op
  429. * ARCv2 && no IOC -> call __dc_line_op; call __slc_rgn_op
  430. * ARCv2 && IOC enabled -> nothing
  431. */
  432. if (!is_isa_arcv2() || !ioc_exists)
  433. __dc_line_op(start, end - start, OP_FLUSH);
  434. if (is_isa_arcv2() && !ioc_exists)
  435. __slc_rgn_op(start, end - start, OP_FLUSH);
  436. }
  437. void flush_cache(unsigned long start, unsigned long size)
  438. {
  439. flush_dcache_range(start, start + size);
  440. }
  441. /*
  442. * As invalidate_dcache_all() is not used in generic U-Boot code and as we
  443. * don't need it in arch/arc code alone (invalidate without flush) we implement
  444. * flush_n_invalidate_dcache_all (flush and invalidate in 1 operation) because
  445. * it's much safer. See [ NOTE 1 ] for more details.
  446. */
  447. void flush_n_invalidate_dcache_all(void)
  448. {
  449. __dc_entire_op(OP_FLUSH_N_INV);
  450. if (is_isa_arcv2())
  451. __slc_entire_op(OP_FLUSH_N_INV);
  452. }
  453. void flush_dcache_all(void)
  454. {
  455. __dc_entire_op(OP_FLUSH);
  456. if (is_isa_arcv2())
  457. __slc_entire_op(OP_FLUSH);
  458. }