cache-mn10300.S 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. #define mn10300_dcache_inv_range_intr_interval \
  17. +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
  18. #if mn10300_dcache_inv_range_intr_interval > 0xff
  19. #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
  20. #endif
  21. .am33_2
  22. .globl mn10300_icache_inv
  23. .globl mn10300_dcache_inv
  24. .globl mn10300_dcache_inv_range
  25. .globl mn10300_dcache_inv_range2
  26. .globl mn10300_dcache_inv_page
  27. ###############################################################################
  28. #
  29. # void mn10300_icache_inv(void)
  30. # Invalidate the entire icache
  31. #
  32. ###############################################################################
  33. ALIGN
  34. mn10300_icache_inv:
  35. mov CHCTR,a0
  36. movhu (a0),d0
  37. btst CHCTR_ICEN,d0
  38. beq mn10300_icache_inv_end
  39. mov epsw,d1
  40. and ~EPSW_IE,epsw
  41. nop
  42. nop
  43. # disable the icache
  44. and ~CHCTR_ICEN,d0
  45. movhu d0,(a0)
  46. # and wait for it to calm down
  47. setlb
  48. movhu (a0),d0
  49. btst CHCTR_ICBUSY,d0
  50. lne
  51. # invalidate
  52. or CHCTR_ICINV,d0
  53. movhu d0,(a0)
  54. # wait for the cache to finish
  55. mov CHCTR,a0
  56. setlb
  57. movhu (a0),d0
  58. btst CHCTR_ICBUSY,d0
  59. lne
  60. # and reenable it
  61. and ~CHCTR_ICINV,d0
  62. or CHCTR_ICEN,d0
  63. movhu d0,(a0)
  64. movhu (a0),d0
  65. mov d1,epsw
  66. mn10300_icache_inv_end:
  67. ret [],0
  68. ###############################################################################
  69. #
  70. # void mn10300_dcache_inv(void)
  71. # Invalidate the entire dcache
  72. #
  73. ###############################################################################
  74. ALIGN
  75. mn10300_dcache_inv:
  76. mov CHCTR,a0
  77. movhu (a0),d0
  78. btst CHCTR_DCEN,d0
  79. beq mn10300_dcache_inv_end
  80. mov epsw,d1
  81. and ~EPSW_IE,epsw
  82. nop
  83. nop
  84. # disable the dcache
  85. and ~CHCTR_DCEN,d0
  86. movhu d0,(a0)
  87. # and wait for it to calm down
  88. setlb
  89. movhu (a0),d0
  90. btst CHCTR_DCBUSY,d0
  91. lne
  92. # invalidate
  93. or CHCTR_DCINV,d0
  94. movhu d0,(a0)
  95. # wait for the cache to finish
  96. mov CHCTR,a0
  97. setlb
  98. movhu (a0),d0
  99. btst CHCTR_DCBUSY,d0
  100. lne
  101. # and reenable it
  102. and ~CHCTR_DCINV,d0
  103. or CHCTR_DCEN,d0
  104. movhu d0,(a0)
  105. movhu (a0),d0
  106. mov d1,epsw
  107. mn10300_dcache_inv_end:
  108. ret [],0
  109. ###############################################################################
  110. #
  111. # void mn10300_dcache_inv_range(unsigned start, unsigned end)
  112. # void mn10300_dcache_inv_range2(unsigned start, unsigned size)
  113. # void mn10300_dcache_inv_page(unsigned start)
  114. # Invalidate a range of addresses on a page in the dcache
  115. #
  116. ###############################################################################
  117. ALIGN
  118. mn10300_dcache_inv_page:
  119. mov PAGE_SIZE,d1
  120. mn10300_dcache_inv_range2:
  121. add d0,d1
  122. mn10300_dcache_inv_range:
  123. movm [d2,d3,a2],(sp)
  124. mov CHCTR,a2
  125. movhu (a2),d2
  126. btst CHCTR_DCEN,d2
  127. beq mn10300_dcache_inv_range_end
  128. and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
  129. # addr down
  130. mov d0,a1
  131. add L1_CACHE_BYTES,d1 # round end addr up
  132. and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
  133. clr d2 # we're going to clear tag ram
  134. # entries
  135. # read the tags from the tag RAM, and if they indicate a valid dirty
  136. # cache line then invalidate that line
  137. mov DCACHE_TAG(0,0),a0
  138. mov a1,d0
  139. and L1_CACHE_TAG_ENTRY,d0
  140. add d0,a0 # starting dcache tag RAM
  141. # access address
  142. sub a1,d1
  143. lsr L1_CACHE_SHIFT,d1 # total number of entries to
  144. # examine
  145. and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
  146. mn10300_dcache_inv_range_outer_loop:
  147. # disable interrupts
  148. mov epsw,d3
  149. and ~EPSW_IE,epsw
  150. nop # note that reading CHCTR and
  151. # AND'ing D0 occupy two delay
  152. # slots after disabling
  153. # interrupts
  154. # disable the dcache
  155. movhu (a2),d0
  156. and ~CHCTR_DCEN,d0
  157. movhu d0,(a2)
  158. # and wait for it to calm down
  159. setlb
  160. movhu (a2),d0
  161. btst CHCTR_DCBUSY,d0
  162. lne
  163. mn10300_dcache_inv_range_loop:
  164. # process the way 0 slot
  165. mov (L1_CACHE_WAYDISP*0,a0),d0 # read the tag in the way 0 slot
  166. btst L1_CACHE_TAG_VALID,d0
  167. beq mn10300_dcache_inv_range_skip_0 # jump if this cacheline is not
  168. # valid
  169. xor a1,d0
  170. lsr 12,d0
  171. bne mn10300_dcache_inv_range_skip_0 # jump if not this cacheline
  172. mov d2,(a0) # kill the tag
  173. mn10300_dcache_inv_range_skip_0:
  174. # process the way 1 slot
  175. mov (L1_CACHE_WAYDISP*1,a0),d0 # read the tag in the way 1 slot
  176. btst L1_CACHE_TAG_VALID,d0
  177. beq mn10300_dcache_inv_range_skip_1 # jump if this cacheline is not
  178. # valid
  179. xor a1,d0
  180. lsr 12,d0
  181. bne mn10300_dcache_inv_range_skip_1 # jump if not this cacheline
  182. mov d2,(a0) # kill the tag
  183. mn10300_dcache_inv_range_skip_1:
  184. # process the way 2 slot
  185. mov (L1_CACHE_WAYDISP*2,a0),d0 # read the tag in the way 2 slot
  186. btst L1_CACHE_TAG_VALID,d0
  187. beq mn10300_dcache_inv_range_skip_2 # jump if this cacheline is not
  188. # valid
  189. xor a1,d0
  190. lsr 12,d0
  191. bne mn10300_dcache_inv_range_skip_2 # jump if not this cacheline
  192. mov d2,(a0) # kill the tag
  193. mn10300_dcache_inv_range_skip_2:
  194. # process the way 3 slot
  195. mov (L1_CACHE_WAYDISP*3,a0),d0 # read the tag in the way 3 slot
  196. btst L1_CACHE_TAG_VALID,d0
  197. beq mn10300_dcache_inv_range_skip_3 # jump if this cacheline is not
  198. # valid
  199. xor a1,d0
  200. lsr 12,d0
  201. bne mn10300_dcache_inv_range_skip_3 # jump if not this cacheline
  202. mov d2,(a0) # kill the tag
  203. mn10300_dcache_inv_range_skip_3:
  204. # approx every N steps we re-enable the cache and see if there are any
  205. # interrupts to be processed
  206. # we also break out if we've reached the end of the loop
  207. # (the bottom nibble of the count is zero in both cases)
  208. add L1_CACHE_BYTES,a0
  209. add L1_CACHE_BYTES,a1
  210. add -1,d1
  211. btst mn10300_dcache_inv_range_intr_interval,d1
  212. bne mn10300_dcache_inv_range_loop
  213. # wait for the cache to finish what it's doing
  214. setlb
  215. movhu (a2),d0
  216. btst CHCTR_DCBUSY,d0
  217. lne
  218. # and reenable it
  219. or CHCTR_DCEN,d0
  220. movhu d0,(a2)
  221. movhu (a2),d0
  222. # re-enable interrupts
  223. # - we don't bother with delay NOPs as we'll have enough instructions
  224. # before we disable interrupts again to give the interrupts a chance
  225. # to happen
  226. mov d3,epsw
  227. # go around again if the counter hasn't yet reached zero
  228. add 0,d1
  229. bne mn10300_dcache_inv_range_outer_loop
  230. mn10300_dcache_inv_range_end:
  231. ret [d2,d3,a2],12