cache-feroceon-l2.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * arch/arm/mm/cache-feroceon-l2.c - Feroceon L2 cache controller support
  3. *
  4. * Copyright (C) 2008 Marvell Semiconductor
  5. *
  6. * This file is licensed under the terms of the GNU General Public
  7. * License version 2. This program is licensed "as is" without any
  8. * warranty of any kind, whether express or implied.
  9. *
  10. * References:
  11. * - Unified Layer 2 Cache for Feroceon CPU Cores,
  12. * Document ID MV-S104858-00, Rev. A, October 23 2007.
  13. */
  14. #include <linux/init.h>
  15. #include <asm/cacheflush.h>
  16. #include <asm/plat-orion/cache-feroceon-l2.h>
  17. /*
  18. * Low-level cache maintenance operations.
  19. *
  20. * As well as the regular 'clean/invalidate/flush L2 cache line by
  21. * MVA' instructions, the Feroceon L2 cache controller also features
  22. * 'clean/invalidate L2 range by MVA' operations.
  23. *
  24. * Cache range operations are initiated by writing the start and
  25. * end addresses to successive cp15 registers, and process every
  26. * cache line whose first byte address lies in the inclusive range
  27. * [start:end].
  28. *
  29. * The cache range operations stall the CPU pipeline until completion.
  30. *
  31. * The range operations require two successive cp15 writes, in
  32. * between which we don't want to be preempted.
  33. */
  34. static inline void l2_clean_pa(unsigned long addr)
  35. {
  36. __asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
  37. }
  38. static inline void l2_clean_mva_range(unsigned long start, unsigned long end)
  39. {
  40. unsigned long flags;
  41. /*
  42. * Make sure 'start' and 'end' reference the same page, as
  43. * L2 is PIPT and range operations only do a TLB lookup on
  44. * the start address.
  45. */
  46. BUG_ON((start ^ end) & ~(PAGE_SIZE - 1));
  47. raw_local_irq_save(flags);
  48. __asm__("mcr p15, 1, %0, c15, c9, 4" : : "r" (start));
  49. __asm__("mcr p15, 1, %0, c15, c9, 5" : : "r" (end));
  50. raw_local_irq_restore(flags);
  51. }
  52. static inline void l2_clean_pa_range(unsigned long start, unsigned long end)
  53. {
  54. l2_clean_mva_range(__phys_to_virt(start), __phys_to_virt(end));
  55. }
  56. static inline void l2_clean_inv_pa(unsigned long addr)
  57. {
  58. __asm__("mcr p15, 1, %0, c15, c10, 3" : : "r" (addr));
  59. }
  60. static inline void l2_inv_pa(unsigned long addr)
  61. {
  62. __asm__("mcr p15, 1, %0, c15, c11, 3" : : "r" (addr));
  63. }
  64. static inline void l2_inv_mva_range(unsigned long start, unsigned long end)
  65. {
  66. unsigned long flags;
  67. /*
  68. * Make sure 'start' and 'end' reference the same page, as
  69. * L2 is PIPT and range operations only do a TLB lookup on
  70. * the start address.
  71. */
  72. BUG_ON((start ^ end) & ~(PAGE_SIZE - 1));
  73. raw_local_irq_save(flags);
  74. __asm__("mcr p15, 1, %0, c15, c11, 4" : : "r" (start));
  75. __asm__("mcr p15, 1, %0, c15, c11, 5" : : "r" (end));
  76. raw_local_irq_restore(flags);
  77. }
  78. static inline void l2_inv_pa_range(unsigned long start, unsigned long end)
  79. {
  80. l2_inv_mva_range(__phys_to_virt(start), __phys_to_virt(end));
  81. }
  82. /*
  83. * Linux primitives.
  84. *
  85. * Note that the end addresses passed to Linux primitives are
  86. * noninclusive, while the hardware cache range operations use
  87. * inclusive start and end addresses.
  88. */
  89. #define CACHE_LINE_SIZE 32
  90. #define MAX_RANGE_SIZE 1024
  91. static int l2_wt_override;
  92. static unsigned long calc_range_end(unsigned long start, unsigned long end)
  93. {
  94. unsigned long range_end;
  95. BUG_ON(start & (CACHE_LINE_SIZE - 1));
  96. BUG_ON(end & (CACHE_LINE_SIZE - 1));
  97. /*
  98. * Try to process all cache lines between 'start' and 'end'.
  99. */
  100. range_end = end;
  101. /*
  102. * Limit the number of cache lines processed at once,
  103. * since cache range operations stall the CPU pipeline
  104. * until completion.
  105. */
  106. if (range_end > start + MAX_RANGE_SIZE)
  107. range_end = start + MAX_RANGE_SIZE;
  108. /*
  109. * Cache range operations can't straddle a page boundary.
  110. */
  111. if (range_end > (start | (PAGE_SIZE - 1)) + 1)
  112. range_end = (start | (PAGE_SIZE - 1)) + 1;
  113. return range_end;
  114. }
  115. static void feroceon_l2_inv_range(unsigned long start, unsigned long end)
  116. {
  117. /*
  118. * Clean and invalidate partial first cache line.
  119. */
  120. if (start & (CACHE_LINE_SIZE - 1)) {
  121. l2_clean_inv_pa(start & ~(CACHE_LINE_SIZE - 1));
  122. start = (start | (CACHE_LINE_SIZE - 1)) + 1;
  123. }
  124. /*
  125. * Clean and invalidate partial last cache line.
  126. */
  127. if (end & (CACHE_LINE_SIZE - 1)) {
  128. l2_clean_inv_pa(end & ~(CACHE_LINE_SIZE - 1));
  129. end &= ~(CACHE_LINE_SIZE - 1);
  130. }
  131. /*
  132. * Invalidate all full cache lines between 'start' and 'end'.
  133. */
  134. while (start != end) {
  135. unsigned long range_end = calc_range_end(start, end);
  136. l2_inv_pa_range(start, range_end - CACHE_LINE_SIZE);
  137. start = range_end;
  138. }
  139. dsb();
  140. }
  141. static void feroceon_l2_clean_range(unsigned long start, unsigned long end)
  142. {
  143. /*
  144. * If L2 is forced to WT, the L2 will always be clean and we
  145. * don't need to do anything here.
  146. */
  147. if (!l2_wt_override) {
  148. start &= ~(CACHE_LINE_SIZE - 1);
  149. end = (end + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
  150. while (start != end) {
  151. unsigned long range_end = calc_range_end(start, end);
  152. l2_clean_pa_range(start, range_end - CACHE_LINE_SIZE);
  153. start = range_end;
  154. }
  155. }
  156. dsb();
  157. }
  158. static void feroceon_l2_flush_range(unsigned long start, unsigned long end)
  159. {
  160. start &= ~(CACHE_LINE_SIZE - 1);
  161. end = (end + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
  162. while (start != end) {
  163. unsigned long range_end = calc_range_end(start, end);
  164. if (!l2_wt_override)
  165. l2_clean_pa_range(start, range_end - CACHE_LINE_SIZE);
  166. l2_inv_pa_range(start, range_end - CACHE_LINE_SIZE);
  167. start = range_end;
  168. }
  169. dsb();
  170. }
  171. /*
  172. * Routines to disable and re-enable the D-cache and I-cache at run
  173. * time. These are necessary because the L2 cache can only be enabled
  174. * or disabled while the L1 Dcache and Icache are both disabled.
  175. */
  176. static void __init invalidate_and_disable_dcache(void)
  177. {
  178. u32 cr;
  179. cr = get_cr();
  180. if (cr & CR_C) {
  181. unsigned long flags;
  182. raw_local_irq_save(flags);
  183. flush_cache_all();
  184. set_cr(cr & ~CR_C);
  185. raw_local_irq_restore(flags);
  186. }
  187. }
  188. static void __init enable_dcache(void)
  189. {
  190. u32 cr;
  191. cr = get_cr();
  192. if (!(cr & CR_C))
  193. set_cr(cr | CR_C);
  194. }
  195. static void __init __invalidate_icache(void)
  196. {
  197. int dummy;
  198. __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0\n" : "=r" (dummy));
  199. }
  200. static void __init invalidate_and_disable_icache(void)
  201. {
  202. u32 cr;
  203. cr = get_cr();
  204. if (cr & CR_I) {
  205. set_cr(cr & ~CR_I);
  206. __invalidate_icache();
  207. }
  208. }
  209. static void __init enable_icache(void)
  210. {
  211. u32 cr;
  212. cr = get_cr();
  213. if (!(cr & CR_I))
  214. set_cr(cr | CR_I);
  215. }
  216. static inline u32 read_extra_features(void)
  217. {
  218. u32 u;
  219. __asm__("mrc p15, 1, %0, c15, c1, 0" : "=r" (u));
  220. return u;
  221. }
  222. static inline void write_extra_features(u32 u)
  223. {
  224. __asm__("mcr p15, 1, %0, c15, c1, 0" : : "r" (u));
  225. }
  226. static void __init disable_l2_prefetch(void)
  227. {
  228. u32 u;
  229. /*
  230. * Read the CPU Extra Features register and verify that the
  231. * Disable L2 Prefetch bit is set.
  232. */
  233. u = read_extra_features();
  234. if (!(u & 0x01000000)) {
  235. printk(KERN_INFO "Feroceon L2: Disabling L2 prefetch.\n");
  236. write_extra_features(u | 0x01000000);
  237. }
  238. }
  239. static void __init enable_l2(void)
  240. {
  241. u32 u;
  242. u = read_extra_features();
  243. if (!(u & 0x00400000)) {
  244. printk(KERN_INFO "Feroceon L2: Enabling L2\n");
  245. invalidate_and_disable_dcache();
  246. invalidate_and_disable_icache();
  247. write_extra_features(u | 0x00400000);
  248. enable_icache();
  249. enable_dcache();
  250. }
  251. }
  252. void __init feroceon_l2_init(int __l2_wt_override)
  253. {
  254. l2_wt_override = __l2_wt_override;
  255. disable_l2_prefetch();
  256. outer_cache.inv_range = feroceon_l2_inv_range;
  257. outer_cache.clean_range = feroceon_l2_clean_range;
  258. outer_cache.flush_range = feroceon_l2_flush_range;
  259. enable_l2();
  260. printk(KERN_INFO "Feroceon L2: Cache support initialised%s.\n",
  261. l2_wt_override ? ", in WT override mode" : "");
  262. }