cache_v7.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2010
  4. * Texas Instruments, <www.ti.com>
  5. * Aneesh V <aneesh@ti.com>
  6. */
  7. #include <cpu_func.h>
  8. #include <asm/cache.h>
  9. #include <linux/types.h>
  10. #include <common.h>
  11. #include <asm/armv7.h>
  12. #include <asm/utils.h>
  13. #define ARMV7_DCACHE_INVAL_RANGE 1
  14. #define ARMV7_DCACHE_CLEAN_INVAL_RANGE 2
  15. #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
  16. /* Asm functions from cache_v7_asm.S */
  17. void v7_flush_dcache_all(void);
  18. void v7_invalidate_dcache_all(void);
  19. static u32 get_ccsidr(void)
  20. {
  21. u32 ccsidr;
  22. /* Read current CP15 Cache Size ID Register */
  23. asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr));
  24. return ccsidr;
  25. }
  26. static void v7_dcache_clean_inval_range(u32 start, u32 stop, u32 line_len)
  27. {
  28. u32 mva;
  29. /* Align start to cache line boundary */
  30. start &= ~(line_len - 1);
  31. for (mva = start; mva < stop; mva = mva + line_len) {
  32. /* DCCIMVAC - Clean & Invalidate data cache by MVA to PoC */
  33. asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (mva));
  34. }
  35. }
  36. static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len)
  37. {
  38. u32 mva;
  39. if (!check_cache_range(start, stop))
  40. return;
  41. for (mva = start; mva < stop; mva = mva + line_len) {
  42. /* DCIMVAC - Invalidate data cache by MVA to PoC */
  43. asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (mva));
  44. }
  45. }
  46. static void v7_dcache_maint_range(u32 start, u32 stop, u32 range_op)
  47. {
  48. u32 line_len, ccsidr;
  49. ccsidr = get_ccsidr();
  50. line_len = ((ccsidr & CCSIDR_LINE_SIZE_MASK) >>
  51. CCSIDR_LINE_SIZE_OFFSET) + 2;
  52. /* Converting from words to bytes */
  53. line_len += 2;
  54. /* converting from log2(linelen) to linelen */
  55. line_len = 1 << line_len;
  56. switch (range_op) {
  57. case ARMV7_DCACHE_CLEAN_INVAL_RANGE:
  58. v7_dcache_clean_inval_range(start, stop, line_len);
  59. break;
  60. case ARMV7_DCACHE_INVAL_RANGE:
  61. v7_dcache_inval_range(start, stop, line_len);
  62. break;
  63. }
  64. /* DSB to make sure the operation is complete */
  65. dsb();
  66. }
  67. /* Invalidate TLB */
  68. static void v7_inval_tlb(void)
  69. {
  70. /* Invalidate entire unified TLB */
  71. asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0));
  72. /* Invalidate entire data TLB */
  73. asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0));
  74. /* Invalidate entire instruction TLB */
  75. asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0));
  76. /* Full system DSB - make sure that the invalidation is complete */
  77. dsb();
  78. /* Full system ISB - make sure the instruction stream sees it */
  79. isb();
  80. }
  81. void invalidate_dcache_all(void)
  82. {
  83. v7_invalidate_dcache_all();
  84. v7_outer_cache_inval_all();
  85. }
  86. /*
  87. * Performs a clean & invalidation of the entire data cache
  88. * at all levels
  89. */
  90. void flush_dcache_all(void)
  91. {
  92. v7_flush_dcache_all();
  93. v7_outer_cache_flush_all();
  94. }
  95. /*
  96. * Invalidates range in all levels of D-cache/unified cache used:
  97. * Affects the range [start, stop - 1]
  98. */
  99. void invalidate_dcache_range(unsigned long start, unsigned long stop)
  100. {
  101. check_cache_range(start, stop);
  102. v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE);
  103. v7_outer_cache_inval_range(start, stop);
  104. }
  105. /*
  106. * Flush range(clean & invalidate) from all levels of D-cache/unified
  107. * cache used:
  108. * Affects the range [start, stop - 1]
  109. */
  110. void flush_dcache_range(unsigned long start, unsigned long stop)
  111. {
  112. check_cache_range(start, stop);
  113. v7_dcache_maint_range(start, stop, ARMV7_DCACHE_CLEAN_INVAL_RANGE);
  114. v7_outer_cache_flush_range(start, stop);
  115. }
  116. void arm_init_before_mmu(void)
  117. {
  118. v7_outer_cache_enable();
  119. invalidate_dcache_all();
  120. v7_inval_tlb();
  121. }
  122. void mmu_page_table_flush(unsigned long start, unsigned long stop)
  123. {
  124. flush_dcache_range(start, stop);
  125. v7_inval_tlb();
  126. }
  127. #else /* #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */
  128. void invalidate_dcache_all(void)
  129. {
  130. }
  131. void flush_dcache_all(void)
  132. {
  133. }
  134. void invalidate_dcache_range(unsigned long start, unsigned long stop)
  135. {
  136. }
  137. void flush_dcache_range(unsigned long start, unsigned long stop)
  138. {
  139. }
  140. void arm_init_before_mmu(void)
  141. {
  142. }
  143. void mmu_page_table_flush(unsigned long start, unsigned long stop)
  144. {
  145. }
  146. void arm_init_domains(void)
  147. {
  148. }
  149. #endif /* #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */
  150. #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
  151. /* Invalidate entire I-cache and branch predictor array */
  152. void invalidate_icache_all(void)
  153. {
  154. /*
  155. * Invalidate all instruction caches to PoU.
  156. * Also flushes branch target cache.
  157. */
  158. asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
  159. /* Invalidate entire branch predictor array */
  160. asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0));
  161. /* Full system DSB - make sure that the invalidation is complete */
  162. dsb();
  163. /* ISB - make sure the instruction stream sees it */
  164. isb();
  165. }
  166. #else
  167. void invalidate_icache_all(void)
  168. {
  169. }
  170. #endif
  171. /* Stub implementations for outer cache operations */
  172. __weak void v7_outer_cache_enable(void) {}
  173. __weak void v7_outer_cache_disable(void) {}
  174. __weak void v7_outer_cache_flush_all(void) {}
  175. __weak void v7_outer_cache_inval_all(void) {}
  176. __weak void v7_outer_cache_flush_range(u32 start, u32 end) {}
  177. __weak void v7_outer_cache_inval_range(u32 start, u32 end) {}