cache-flush-by-reg.S 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* MN10300 CPU core caching routines, using indirect regs on cache controller
  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. .am33_2
  18. #ifndef CONFIG_SMP
  19. .globl mn10300_dcache_flush
  20. .globl mn10300_dcache_flush_page
  21. .globl mn10300_dcache_flush_range
  22. .globl mn10300_dcache_flush_range2
  23. .globl mn10300_dcache_flush_inv
  24. .globl mn10300_dcache_flush_inv_page
  25. .globl mn10300_dcache_flush_inv_range
  26. .globl mn10300_dcache_flush_inv_range2
  27. mn10300_dcache_flush = mn10300_local_dcache_flush
  28. mn10300_dcache_flush_page = mn10300_local_dcache_flush_page
  29. mn10300_dcache_flush_range = mn10300_local_dcache_flush_range
  30. mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2
  31. mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv
  32. mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page
  33. mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range
  34. mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range2
  35. #endif /* !CONFIG_SMP */
  36. ###############################################################################
  37. #
  38. # void mn10300_local_dcache_flush(void)
  39. # Flush the entire data cache back to RAM
  40. #
  41. ###############################################################################
  42. ALIGN
  43. .globl mn10300_local_dcache_flush
  44. .type mn10300_local_dcache_flush,@function
  45. mn10300_local_dcache_flush:
  46. movhu (CHCTR),d0
  47. btst CHCTR_DCEN,d0
  48. beq mn10300_local_dcache_flush_end
  49. mov DCPGCR,a0
  50. LOCAL_CLI_SAVE(d1)
  51. # wait for busy bit of area purge
  52. setlb
  53. mov (a0),d0
  54. btst DCPGCR_DCPGBSY,d0
  55. lne
  56. # set mask
  57. clr d0
  58. mov d0,(DCPGMR)
  59. # area purge
  60. #
  61. # DCPGCR = DCPGCR_DCP
  62. #
  63. mov DCPGCR_DCP,d0
  64. mov d0,(a0)
  65. # wait for busy bit of area purge
  66. setlb
  67. mov (a0),d0
  68. btst DCPGCR_DCPGBSY,d0
  69. lne
  70. LOCAL_IRQ_RESTORE(d1)
  71. mn10300_local_dcache_flush_end:
  72. ret [],0
  73. .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
  74. ###############################################################################
  75. #
  76. # void mn10300_local_dcache_flush_page(unsigned long start)
  77. # void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
  78. # void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
  79. # Flush a range of addresses on a page in the dcache
  80. #
  81. ###############################################################################
  82. ALIGN
  83. .globl mn10300_local_dcache_flush_page
  84. .globl mn10300_local_dcache_flush_range
  85. .globl mn10300_local_dcache_flush_range2
  86. .type mn10300_local_dcache_flush_page,@function
  87. .type mn10300_local_dcache_flush_range,@function
  88. .type mn10300_local_dcache_flush_range2,@function
  89. mn10300_local_dcache_flush_page:
  90. and ~(PAGE_SIZE-1),d0
  91. mov PAGE_SIZE,d1
  92. mn10300_local_dcache_flush_range2:
  93. add d0,d1
  94. mn10300_local_dcache_flush_range:
  95. movm [d2,d3,a2],(sp)
  96. movhu (CHCTR),d2
  97. btst CHCTR_DCEN,d2
  98. beq mn10300_local_dcache_flush_range_end
  99. # calculate alignsize
  100. #
  101. # alignsize = L1_CACHE_BYTES;
  102. # for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1)
  103. # alignsize <<= 1;
  104. # d2 = alignsize;
  105. #
  106. mov L1_CACHE_BYTES,d2
  107. sub d0,d1,d3
  108. add -1,d3
  109. lsr L1_CACHE_SHIFT,d3
  110. beq 2f
  111. 1:
  112. add d2,d2
  113. lsr 1,d3
  114. bne 1b
  115. 2:
  116. mov d1,a1 # a1 = end
  117. LOCAL_CLI_SAVE(d3)
  118. mov DCPGCR,a0
  119. # wait for busy bit of area purge
  120. setlb
  121. mov (a0),d1
  122. btst DCPGCR_DCPGBSY,d1
  123. lne
  124. # determine the mask
  125. mov d2,d1
  126. add -1,d1
  127. not d1 # d1 = mask = ~(alignsize-1)
  128. mov d1,(DCPGMR)
  129. and d1,d0,a2 # a2 = mask & start
  130. dcpgloop:
  131. # area purge
  132. mov a2,d0
  133. or DCPGCR_DCP,d0
  134. mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCP
  135. # wait for busy bit of area purge
  136. setlb
  137. mov (a0),d1
  138. btst DCPGCR_DCPGBSY,d1
  139. lne
  140. # check purge of end address
  141. add d2,a2 # a2 += alignsize
  142. cmp a1,a2 # if (a2 < end) goto dcpgloop
  143. bns dcpgloop
  144. LOCAL_IRQ_RESTORE(d3)
  145. mn10300_local_dcache_flush_range_end:
  146. ret [d2,d3,a2],12
  147. .size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
  148. .size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
  149. .size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
  150. ###############################################################################
  151. #
  152. # void mn10300_local_dcache_flush_inv(void)
  153. # Flush the entire data cache and invalidate all entries
  154. #
  155. ###############################################################################
  156. ALIGN
  157. .globl mn10300_local_dcache_flush_inv
  158. .type mn10300_local_dcache_flush_inv,@function
  159. mn10300_local_dcache_flush_inv:
  160. movhu (CHCTR),d0
  161. btst CHCTR_DCEN,d0
  162. beq mn10300_local_dcache_flush_inv_end
  163. mov DCPGCR,a0
  164. LOCAL_CLI_SAVE(d1)
  165. # wait for busy bit of area purge & invalidate
  166. setlb
  167. mov (a0),d0
  168. btst DCPGCR_DCPGBSY,d0
  169. lne
  170. # set the mask to cover everything
  171. clr d0
  172. mov d0,(DCPGMR)
  173. # area purge & invalidate
  174. mov DCPGCR_DCP|DCPGCR_DCI,d0
  175. mov d0,(a0)
  176. # wait for busy bit of area purge & invalidate
  177. setlb
  178. mov (a0),d0
  179. btst DCPGCR_DCPGBSY,d0
  180. lne
  181. LOCAL_IRQ_RESTORE(d1)
  182. mn10300_local_dcache_flush_inv_end:
  183. ret [],0
  184. .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
  185. ###############################################################################
  186. #
  187. # void mn10300_local_dcache_flush_inv_page(unsigned long start)
  188. # void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
  189. # void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
  190. # Flush and invalidate a range of addresses on a page in the dcache
  191. #
  192. ###############################################################################
  193. ALIGN
  194. .globl mn10300_local_dcache_flush_inv_page
  195. .globl mn10300_local_dcache_flush_inv_range
  196. .globl mn10300_local_dcache_flush_inv_range2
  197. .type mn10300_local_dcache_flush_inv_page,@function
  198. .type mn10300_local_dcache_flush_inv_range,@function
  199. .type mn10300_local_dcache_flush_inv_range2,@function
  200. mn10300_local_dcache_flush_inv_page:
  201. and ~(PAGE_SIZE-1),d0
  202. mov PAGE_SIZE,d1
  203. mn10300_local_dcache_flush_inv_range2:
  204. add d0,d1
  205. mn10300_local_dcache_flush_inv_range:
  206. movm [d2,d3,a2],(sp)
  207. movhu (CHCTR),d2
  208. btst CHCTR_DCEN,d2
  209. beq mn10300_local_dcache_flush_inv_range_end
  210. # calculate alignsize
  211. #
  212. # alignsize = L1_CACHE_BYTES;
  213. # for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1)
  214. # alignsize <<= 1;
  215. # d2 = alignsize
  216. #
  217. mov L1_CACHE_BYTES,d2
  218. sub d0,d1,d3
  219. add -1,d3
  220. lsr L1_CACHE_SHIFT,d3
  221. beq 2f
  222. 1:
  223. add d2,d2
  224. lsr 1,d3
  225. bne 1b
  226. 2:
  227. mov d1,a1 # a1 = end
  228. LOCAL_CLI_SAVE(d3)
  229. mov DCPGCR,a0
  230. # wait for busy bit of area purge & invalidate
  231. setlb
  232. mov (a0),d1
  233. btst DCPGCR_DCPGBSY,d1
  234. lne
  235. # set the mask
  236. mov d2,d1
  237. add -1,d1
  238. not d1 # d1 = mask = ~(alignsize-1)
  239. mov d1,(DCPGMR)
  240. and d1,d0,a2 # a2 = mask & start
  241. dcpgivloop:
  242. # area purge & invalidate
  243. mov a2,d0
  244. or DCPGCR_DCP|DCPGCR_DCI,d0
  245. mov d0,(a0) # DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI
  246. # wait for busy bit of area purge & invalidate
  247. setlb
  248. mov (a0),d1
  249. btst DCPGCR_DCPGBSY,d1
  250. lne
  251. # check purge & invalidate of end address
  252. add d2,a2 # a2 += alignsize
  253. cmp a1,a2 # if (a2 < end) goto dcpgivloop
  254. bns dcpgivloop
  255. LOCAL_IRQ_RESTORE(d3)
  256. mn10300_local_dcache_flush_inv_range_end:
  257. ret [d2,d3,a2],12
  258. .size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
  259. .size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
  260. .size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2