cache-inv-by-tag.S 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /* MN10300 CPU core caching routines
  2. *
  3. * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public Licence
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the Licence, or (at your option) any later version.
  10. */
  11. #include <linux/sys.h>
  12. #include <linux/linkage.h>
  13. #include <asm/smp.h>
  14. #include <asm/page.h>
  15. #include <asm/cache.h>
  16. #include <asm/irqflags.h>
  17. #include <asm/cacheflush.h>
  18. #include "cache.inc"
  19. #define mn10300_local_dcache_inv_range_intr_interval \
  20. +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
  21. #if mn10300_local_dcache_inv_range_intr_interval > 0xff
  22. #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
  23. #endif
  24. .am33_2
  25. .globl mn10300_local_icache_inv_page
  26. .globl mn10300_local_icache_inv_range
  27. .globl mn10300_local_icache_inv_range2
  28. mn10300_local_icache_inv_page = mn10300_local_icache_inv
  29. mn10300_local_icache_inv_range = mn10300_local_icache_inv
  30. mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
  31. #ifndef CONFIG_SMP
  32. .globl mn10300_icache_inv
  33. .globl mn10300_icache_inv_page
  34. .globl mn10300_icache_inv_range
  35. .globl mn10300_icache_inv_range2
  36. .globl mn10300_dcache_inv
  37. .globl mn10300_dcache_inv_page
  38. .globl mn10300_dcache_inv_range
  39. .globl mn10300_dcache_inv_range2
  40. mn10300_icache_inv = mn10300_local_icache_inv
  41. mn10300_icache_inv_page = mn10300_local_icache_inv_page
  42. mn10300_icache_inv_range = mn10300_local_icache_inv_range
  43. mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
  44. mn10300_dcache_inv = mn10300_local_dcache_inv
  45. mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
  46. mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
  47. mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
  48. #endif /* !CONFIG_SMP */
  49. ###############################################################################
  50. #
  51. # void mn10300_local_icache_inv(void)
  52. # Invalidate the entire icache
  53. #
  54. ###############################################################################
  55. ALIGN
  56. .globl mn10300_local_icache_inv
  57. .type mn10300_local_icache_inv,@function
  58. mn10300_local_icache_inv:
  59. mov CHCTR,a0
  60. movhu (a0),d0
  61. btst CHCTR_ICEN,d0
  62. beq mn10300_local_icache_inv_end
  63. invalidate_icache 1
  64. mn10300_local_icache_inv_end:
  65. ret [],0
  66. .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
  67. ###############################################################################
  68. #
  69. # void mn10300_local_dcache_inv(void)
  70. # Invalidate the entire dcache
  71. #
  72. ###############################################################################
  73. ALIGN
  74. .globl mn10300_local_dcache_inv
  75. .type mn10300_local_dcache_inv,@function
  76. mn10300_local_dcache_inv:
  77. mov CHCTR,a0
  78. movhu (a0),d0
  79. btst CHCTR_DCEN,d0
  80. beq mn10300_local_dcache_inv_end
  81. invalidate_dcache 1
  82. mn10300_local_dcache_inv_end:
  83. ret [],0
  84. .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
  85. ###############################################################################
  86. #
  87. # void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
  88. # void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
  89. # void mn10300_local_dcache_inv_page(unsigned long start)
  90. # Invalidate a range of addresses on a page in the dcache
  91. #
  92. ###############################################################################
  93. ALIGN
  94. .globl mn10300_local_dcache_inv_page
  95. .globl mn10300_local_dcache_inv_range
  96. .globl mn10300_local_dcache_inv_range2
  97. .type mn10300_local_dcache_inv_page,@function
  98. .type mn10300_local_dcache_inv_range,@function
  99. .type mn10300_local_dcache_inv_range2,@function
  100. mn10300_local_dcache_inv_page:
  101. and ~(PAGE_SIZE-1),d0
  102. mov PAGE_SIZE,d1
  103. mn10300_local_dcache_inv_range2:
  104. add d0,d1
  105. mn10300_local_dcache_inv_range:
  106. # If we are in writeback mode we check the start and end alignments,
  107. # and if they're not cacheline-aligned, we must flush any bits outside
  108. # the range that share cachelines with stuff inside the range
  109. #ifdef CONFIG_MN10300_CACHE_WBACK
  110. btst ~L1_CACHE_TAG_MASK,d0
  111. bne 1f
  112. btst ~L1_CACHE_TAG_MASK,d1
  113. beq 2f
  114. 1:
  115. bra mn10300_local_dcache_flush_inv_range
  116. 2:
  117. #endif /* CONFIG_MN10300_CACHE_WBACK */
  118. movm [d2,d3,a2],(sp)
  119. mov CHCTR,a2
  120. movhu (a2),d2
  121. btst CHCTR_DCEN,d2
  122. beq mn10300_local_dcache_inv_range_end
  123. #ifndef CONFIG_MN10300_CACHE_WBACK
  124. and L1_CACHE_TAG_MASK,d0 # round start addr down
  125. add L1_CACHE_BYTES,d1 # round end addr up
  126. and L1_CACHE_TAG_MASK,d1
  127. #endif /* !CONFIG_MN10300_CACHE_WBACK */
  128. mov d0,a1
  129. clr d2 # we're going to clear tag RAM
  130. # entries
  131. # read the tags from the tag RAM, and if they indicate a valid dirty
  132. # cache line then invalidate that line
  133. mov DCACHE_TAG(0,0),a0
  134. mov a1,d0
  135. and L1_CACHE_TAG_ENTRY,d0
  136. add d0,a0 # starting dcache tag RAM
  137. # access address
  138. sub a1,d1
  139. lsr L1_CACHE_SHIFT,d1 # total number of entries to
  140. # examine
  141. and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
  142. mn10300_local_dcache_inv_range_outer_loop:
  143. LOCAL_CLI_SAVE(d3)
  144. # disable the dcache
  145. movhu (a2),d0
  146. and ~CHCTR_DCEN,d0
  147. movhu d0,(a2)
  148. # and wait for it to calm down
  149. setlb
  150. movhu (a2),d0
  151. btst CHCTR_DCBUSY,d0
  152. lne
  153. mn10300_local_dcache_inv_range_loop:
  154. # process the way 0 slot
  155. mov (L1_CACHE_WAYDISP*0,a0),d0 # read the tag in the way 0 slot
  156. btst L1_CACHE_TAG_VALID,d0
  157. beq mn10300_local_dcache_inv_range_skip_0 # jump if this cacheline
  158. # is not valid
  159. xor a1,d0
  160. lsr 12,d0
  161. bne mn10300_local_dcache_inv_range_skip_0 # jump if not this cacheline
  162. mov d2,(L1_CACHE_WAYDISP*0,a0) # kill the tag
  163. mn10300_local_dcache_inv_range_skip_0:
  164. # process the way 1 slot
  165. mov (L1_CACHE_WAYDISP*1,a0),d0 # read the tag in the way 1 slot
  166. btst L1_CACHE_TAG_VALID,d0
  167. beq mn10300_local_dcache_inv_range_skip_1 # jump if this cacheline
  168. # is not valid
  169. xor a1,d0
  170. lsr 12,d0
  171. bne mn10300_local_dcache_inv_range_skip_1 # jump if not this cacheline
  172. mov d2,(L1_CACHE_WAYDISP*1,a0) # kill the tag
  173. mn10300_local_dcache_inv_range_skip_1:
  174. # process the way 2 slot
  175. mov (L1_CACHE_WAYDISP*2,a0),d0 # read the tag in the way 2 slot
  176. btst L1_CACHE_TAG_VALID,d0
  177. beq mn10300_local_dcache_inv_range_skip_2 # jump if this cacheline
  178. # is not valid
  179. xor a1,d0
  180. lsr 12,d0
  181. bne mn10300_local_dcache_inv_range_skip_2 # jump if not this cacheline
  182. mov d2,(L1_CACHE_WAYDISP*2,a0) # kill the tag
  183. mn10300_local_dcache_inv_range_skip_2:
  184. # process the way 3 slot
  185. mov (L1_CACHE_WAYDISP*3,a0),d0 # read the tag in the way 3 slot
  186. btst L1_CACHE_TAG_VALID,d0
  187. beq mn10300_local_dcache_inv_range_skip_3 # jump if this cacheline
  188. # is not valid
  189. xor a1,d0
  190. lsr 12,d0
  191. bne mn10300_local_dcache_inv_range_skip_3 # jump if not this cacheline
  192. mov d2,(L1_CACHE_WAYDISP*3,a0) # kill the tag
  193. mn10300_local_dcache_inv_range_skip_3:
  194. # approx every N steps we re-enable the cache and see if there are any
  195. # interrupts to be processed
  196. # we also break out if we've reached the end of the loop
  197. # (the bottom nibble of the count is zero in both cases)
  198. add L1_CACHE_BYTES,a0
  199. add L1_CACHE_BYTES,a1
  200. and ~L1_CACHE_WAYDISP,a0
  201. add -1,d1
  202. btst mn10300_local_dcache_inv_range_intr_interval,d1
  203. bne mn10300_local_dcache_inv_range_loop
  204. # wait for the cache to finish what it's doing
  205. setlb
  206. movhu (a2),d0
  207. btst CHCTR_DCBUSY,d0
  208. lne
  209. # and reenable it
  210. or CHCTR_DCEN,d0
  211. movhu d0,(a2)
  212. movhu (a2),d0
  213. # re-enable interrupts
  214. # - we don't bother with delay NOPs as we'll have enough instructions
  215. # before we disable interrupts again to give the interrupts a chance
  216. # to happen
  217. LOCAL_IRQ_RESTORE(d3)
  218. # go around again if the counter hasn't yet reached zero
  219. add 0,d1
  220. bne mn10300_local_dcache_inv_range_outer_loop
  221. mn10300_local_dcache_inv_range_end:
  222. ret [d2,d3,a2],12
  223. .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
  224. .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
  225. .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2