cache-sh2a.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * arch/sh/mm/cache-sh2a.c
  4. *
  5. * Copyright (C) 2008 Yoshinori Sato
  6. */
  7. #include <linux/init.h>
  8. #include <linux/mm.h>
  9. #include <asm/cache.h>
  10. #include <asm/addrspace.h>
  11. #include <asm/processor.h>
  12. #include <asm/cacheflush.h>
  13. #include <asm/io.h>
  14. /*
  15. * The maximum number of pages we support up to when doing ranged dcache
  16. * flushing. Anything exceeding this will simply flush the dcache in its
  17. * entirety.
  18. */
  19. #define MAX_OCACHE_PAGES 32
  20. #define MAX_ICACHE_PAGES 32
  21. #ifdef CONFIG_CACHE_WRITEBACK
  22. static void sh2a_flush_oc_line(unsigned long v, int way)
  23. {
  24. unsigned long addr = (v & 0x000007f0) | (way << 11);
  25. unsigned long data;
  26. data = __raw_readl(CACHE_OC_ADDRESS_ARRAY | addr);
  27. if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
  28. data &= ~SH_CACHE_UPDATED;
  29. __raw_writel(data, CACHE_OC_ADDRESS_ARRAY | addr);
  30. }
  31. }
  32. #endif
  33. static void sh2a_invalidate_line(unsigned long cache_addr, unsigned long v)
  34. {
  35. /* Set associative bit to hit all ways */
  36. unsigned long addr = (v & 0x000007f0) | SH_CACHE_ASSOC;
  37. __raw_writel((addr & CACHE_PHYSADDR_MASK), cache_addr | addr);
  38. }
  39. /*
  40. * Write back the dirty D-caches, but not invalidate them.
  41. */
  42. static void sh2a__flush_wback_region(void *start, int size)
  43. {
  44. #ifdef CONFIG_CACHE_WRITEBACK
  45. unsigned long v;
  46. unsigned long begin, end;
  47. unsigned long flags;
  48. int nr_ways;
  49. begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
  50. end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
  51. & ~(L1_CACHE_BYTES-1);
  52. nr_ways = current_cpu_data.dcache.ways;
  53. local_irq_save(flags);
  54. jump_to_uncached();
  55. /* If there are too many pages then flush the entire cache */
  56. if (((end - begin) >> PAGE_SHIFT) >= MAX_OCACHE_PAGES) {
  57. begin = CACHE_OC_ADDRESS_ARRAY;
  58. end = begin + (nr_ways * current_cpu_data.dcache.way_size);
  59. for (v = begin; v < end; v += L1_CACHE_BYTES) {
  60. unsigned long data = __raw_readl(v);
  61. if (data & SH_CACHE_UPDATED)
  62. __raw_writel(data & ~SH_CACHE_UPDATED, v);
  63. }
  64. } else {
  65. int way;
  66. for (way = 0; way < nr_ways; way++) {
  67. for (v = begin; v < end; v += L1_CACHE_BYTES)
  68. sh2a_flush_oc_line(v, way);
  69. }
  70. }
  71. back_to_cached();
  72. local_irq_restore(flags);
  73. #endif
  74. }
  75. /*
  76. * Write back the dirty D-caches and invalidate them.
  77. */
  78. static void sh2a__flush_purge_region(void *start, int size)
  79. {
  80. unsigned long v;
  81. unsigned long begin, end;
  82. unsigned long flags;
  83. begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
  84. end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
  85. & ~(L1_CACHE_BYTES-1);
  86. local_irq_save(flags);
  87. jump_to_uncached();
  88. for (v = begin; v < end; v+=L1_CACHE_BYTES) {
  89. #ifdef CONFIG_CACHE_WRITEBACK
  90. int way;
  91. int nr_ways = current_cpu_data.dcache.ways;
  92. for (way = 0; way < nr_ways; way++)
  93. sh2a_flush_oc_line(v, way);
  94. #endif
  95. sh2a_invalidate_line(CACHE_OC_ADDRESS_ARRAY, v);
  96. }
  97. back_to_cached();
  98. local_irq_restore(flags);
  99. }
  100. /*
  101. * Invalidate the D-caches, but no write back please
  102. */
  103. static void sh2a__flush_invalidate_region(void *start, int size)
  104. {
  105. unsigned long v;
  106. unsigned long begin, end;
  107. unsigned long flags;
  108. begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
  109. end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
  110. & ~(L1_CACHE_BYTES-1);
  111. local_irq_save(flags);
  112. jump_to_uncached();
  113. /* If there are too many pages then just blow the cache */
  114. if (((end - begin) >> PAGE_SHIFT) >= MAX_OCACHE_PAGES) {
  115. __raw_writel(__raw_readl(SH_CCR) | CCR_OCACHE_INVALIDATE,
  116. SH_CCR);
  117. } else {
  118. for (v = begin; v < end; v += L1_CACHE_BYTES)
  119. sh2a_invalidate_line(CACHE_OC_ADDRESS_ARRAY, v);
  120. }
  121. back_to_cached();
  122. local_irq_restore(flags);
  123. }
  124. /*
  125. * Write back the range of D-cache, and purge the I-cache.
  126. */
  127. static void sh2a_flush_icache_range(void *args)
  128. {
  129. struct flusher_data *data = args;
  130. unsigned long start, end;
  131. unsigned long v;
  132. unsigned long flags;
  133. start = data->addr1 & ~(L1_CACHE_BYTES-1);
  134. end = (data->addr2 + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);
  135. #ifdef CONFIG_CACHE_WRITEBACK
  136. sh2a__flush_wback_region((void *)start, end-start);
  137. #endif
  138. local_irq_save(flags);
  139. jump_to_uncached();
  140. /* I-Cache invalidate */
  141. /* If there are too many pages then just blow the cache */
  142. if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
  143. __raw_writel(__raw_readl(SH_CCR) | CCR_ICACHE_INVALIDATE,
  144. SH_CCR);
  145. } else {
  146. for (v = start; v < end; v += L1_CACHE_BYTES)
  147. sh2a_invalidate_line(CACHE_IC_ADDRESS_ARRAY, v);
  148. }
  149. back_to_cached();
  150. local_irq_restore(flags);
  151. }
  152. void __init sh2a_cache_init(void)
  153. {
  154. local_flush_icache_range = sh2a_flush_icache_range;
  155. __flush_wback_region = sh2a__flush_wback_region;
  156. __flush_purge_region = sh2a__flush_purge_region;
  157. __flush_invalidate_region = sh2a__flush_invalidate_region;
  158. }