cache.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2012 Andes Technology Corporation
  4. * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
  5. * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
  6. */
  7. #include <common.h>
  8. #if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF))
  9. static inline unsigned long CACHE_SET(unsigned char cache)
  10. {
  11. if (cache == ICACHE)
  12. return 64 << ((GET_ICM_CFG() & ICM_CFG_MSK_ISET) \
  13. >> ICM_CFG_OFF_ISET);
  14. else
  15. return 64 << ((GET_DCM_CFG() & DCM_CFG_MSK_DSET) \
  16. >> DCM_CFG_OFF_DSET);
  17. }
  18. static inline unsigned long CACHE_WAY(unsigned char cache)
  19. {
  20. if (cache == ICACHE)
  21. return 1 + ((GET_ICM_CFG() & ICM_CFG_MSK_IWAY) \
  22. >> ICM_CFG_OFF_IWAY);
  23. else
  24. return 1 + ((GET_DCM_CFG() & DCM_CFG_MSK_DWAY) \
  25. >> DCM_CFG_OFF_DWAY);
  26. }
  27. static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
  28. {
  29. if (cache == ICACHE)
  30. return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
  31. >> ICM_CFG_OFF_ISZ) - 1);
  32. else
  33. return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
  34. >> DCM_CFG_OFF_DSZ) - 1);
  35. }
  36. #endif
  37. #ifndef CONFIG_SYS_ICACHE_OFF
  38. void invalidate_icache_all(void)
  39. {
  40. unsigned long end, line_size;
  41. line_size = CACHE_LINE_SIZE(ICACHE);
  42. end = line_size * CACHE_WAY(ICACHE) * CACHE_SET(ICACHE);
  43. do {
  44. end -= line_size;
  45. __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
  46. end -= line_size;
  47. __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
  48. end -= line_size;
  49. __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
  50. end -= line_size;
  51. __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
  52. } while (end > 0);
  53. }
  54. void invalidate_icache_range(unsigned long start, unsigned long end)
  55. {
  56. unsigned long line_size;
  57. line_size = CACHE_LINE_SIZE(ICACHE);
  58. while (end > start) {
  59. asm volatile (
  60. "\n\tcctl %0, L1I_VA_INVAL"
  61. :
  62. : "r"(start)
  63. );
  64. start += line_size;
  65. }
  66. }
  67. void icache_enable(void)
  68. {
  69. asm volatile (
  70. "mfsr $p0, $mr8\n\t"
  71. "ori $p0, $p0, 0x01\n\t"
  72. "mtsr $p0, $mr8\n\t"
  73. "isb\n\t"
  74. );
  75. }
  76. void icache_disable(void)
  77. {
  78. asm volatile (
  79. "mfsr $p0, $mr8\n\t"
  80. "li $p1, ~0x01\n\t"
  81. "and $p0, $p0, $p1\n\t"
  82. "mtsr $p0, $mr8\n\t"
  83. "isb\n\t"
  84. );
  85. }
  86. int icache_status(void)
  87. {
  88. int ret;
  89. asm volatile (
  90. "mfsr $p0, $mr8\n\t"
  91. "andi %0, $p0, 0x01\n\t"
  92. : "=r" (ret)
  93. :
  94. : "memory"
  95. );
  96. return ret;
  97. }
  98. #else
  99. void invalidate_icache_all(void)
  100. {
  101. }
  102. void invalidate_icache_range(unsigned long start, unsigned long end)
  103. {
  104. }
  105. void icache_enable(void)
  106. {
  107. }
  108. void icache_disable(void)
  109. {
  110. }
  111. int icache_status(void)
  112. {
  113. return 0;
  114. }
  115. #endif
  116. #ifndef CONFIG_SYS_DCACHE_OFF
  117. void dcache_wbinval_all(void)
  118. {
  119. unsigned long end, line_size;
  120. line_size = CACHE_LINE_SIZE(DCACHE);
  121. end = line_size * CACHE_WAY(DCACHE) * CACHE_SET(DCACHE);
  122. do {
  123. end -= line_size;
  124. __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
  125. __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
  126. end -= line_size;
  127. __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
  128. __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
  129. end -= line_size;
  130. __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
  131. __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
  132. end -= line_size;
  133. __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
  134. __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
  135. } while (end > 0);
  136. }
  137. void flush_dcache_range(unsigned long start, unsigned long end)
  138. {
  139. unsigned long line_size;
  140. line_size = CACHE_LINE_SIZE(DCACHE);
  141. while (end > start) {
  142. asm volatile (
  143. "\n\tcctl %0, L1D_VA_WB"
  144. "\n\tcctl %0, L1D_VA_INVAL" : : "r" (start)
  145. );
  146. start += line_size;
  147. }
  148. }
  149. void invalidate_dcache_range(unsigned long start, unsigned long end)
  150. {
  151. unsigned long line_size;
  152. line_size = CACHE_LINE_SIZE(DCACHE);
  153. while (end > start) {
  154. asm volatile (
  155. "\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)
  156. );
  157. start += line_size;
  158. }
  159. }
  160. void dcache_enable(void)
  161. {
  162. asm volatile (
  163. "mfsr $p0, $mr8\n\t"
  164. "ori $p0, $p0, 0x02\n\t"
  165. "mtsr $p0, $mr8\n\t"
  166. "isb\n\t"
  167. );
  168. }
  169. void dcache_disable(void)
  170. {
  171. asm volatile (
  172. "mfsr $p0, $mr8\n\t"
  173. "li $p1, ~0x02\n\t"
  174. "and $p0, $p0, $p1\n\t"
  175. "mtsr $p0, $mr8\n\t"
  176. "isb\n\t"
  177. );
  178. }
  179. int dcache_status(void)
  180. {
  181. int ret;
  182. asm volatile (
  183. "mfsr $p0, $mr8\n\t"
  184. "andi %0, $p0, 0x02\n\t"
  185. : "=r" (ret)
  186. :
  187. : "memory"
  188. );
  189. return ret;
  190. }
  191. #else
  192. void dcache_wbinval_all(void)
  193. {
  194. }
  195. void flush_dcache_range(unsigned long start, unsigned long end)
  196. {
  197. }
  198. void invalidate_dcache_range(unsigned long start, unsigned long end)
  199. {
  200. }
  201. void dcache_enable(void)
  202. {
  203. }
  204. void dcache_disable(void)
  205. {
  206. }
  207. int dcache_status(void)
  208. {
  209. return 0;
  210. }
  211. #endif
  212. void flush_dcache_all(void)
  213. {
  214. dcache_wbinval_all();
  215. }
  216. void cache_flush(void)
  217. {
  218. flush_dcache_all();
  219. invalidate_icache_all();
  220. }
  221. void flush_cache(unsigned long addr, unsigned long size)
  222. {
  223. flush_dcache_range(addr, addr + size);
  224. invalidate_icache_range(addr, addr + size);
  225. }