mt_cache_v8.S 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #include <linux/linkage.h>
  2. #include <linux/init.h>
  3. #include <asm/assembler.h>
  4. .text
  5. .equ SCTLR_C_BIT, 0x00000004
  6. .equ SCTLR_I_BIT, 0x00001000
  7. .equ DCISW, 0x0
  8. .equ DCCISW, 0x1
  9. .equ DCCSW, 0x2
  10. .equ LOC_SHIFT, 24
  11. .equ CLIDR_FIELD_WIDTH, 3
  12. .equ LEVEL_SHIFT, 1
  13. ENTRY(__enable_icache)
  14. mrs x0, SCTLR_EL1
  15. orr x0, x0, #SCTLR_I_BIT
  16. msr SCTLR_EL1, x0
  17. ret
  18. ENDPROC(__enable_icache)
  19. ENTRY(__disable_icache)
  20. mrs x0, SCTLR_EL1
  21. bic x0, x0, #SCTLR_I_BIT
  22. msr SCTLR_EL1, x0
  23. ret
  24. ENDPROC(__disable_icache)
  25. /* might pollute x0 */
  26. .macro __dis_D
  27. mrs x0, SCTLR_EL1
  28. bic x0, x0, #SCTLR_C_BIT
  29. dsb sy
  30. msr SCTLR_EL1, x0
  31. dsb sy
  32. isb sy
  33. .endm
  34. ENTRY(__enable_dcache)
  35. mrs x0, SCTLR_EL1
  36. orr x0, x0, #SCTLR_C_BIT
  37. dsb sy
  38. msr SCTLR_EL1, x0
  39. dsb sy
  40. isb sy
  41. ret
  42. ENDPROC(__enable_dcache)
  43. ENTRY(__disable_dcache)
  44. mrs x0, SCTLR_EL1
  45. bic x0, x0, #SCTLR_C_BIT
  46. dsb sy
  47. msr SCTLR_EL1, x0
  48. dsb sy
  49. isb sy
  50. ret
  51. ENDPROC(__disable_dcache)
  52. ENTRY(__enable_cache)
  53. mrs x0, SCTLR_EL1
  54. orr x0, x0, #SCTLR_I_BIT
  55. orr x0, x0, #SCTLR_C_BIT
  56. dsb sy
  57. msr SCTLR_EL1, x0
  58. dsb sy
  59. isb sy
  60. ret
  61. ENDPROC(__enable_cache)
  62. ENTRY(__disable_cache)
  63. mrs x0, SCTLR_EL1
  64. bic x0, x0, #SCTLR_I_BIT
  65. bic x0, x0, #SCTLR_C_BIT
  66. dsb sy
  67. msr SCTLR_EL1, x0
  68. dsb sy
  69. isb sy
  70. ret
  71. ENDPROC(__disable_cache)
  72. /* ---------------------------------------------------------------
  73. * Data cache operations by set/way to the level specified
  74. *
  75. * The main function, do_dcsw_op requires:
  76. * x0: The operation type (0-2), as defined in arch.h
  77. * x1: The first cache level to operate on
  78. * x3: The last cache level to operate on
  79. * x9: clidr_el1
  80. * and will carry out the operation on each data cache from level 0
  81. * to the level in x3 in sequence
  82. *
  83. * The dcsw_op macro sets up the x3 and x9 parameters based on
  84. * clidr_el1 cache information before invoking the main function
  85. * ---------------------------------------------------------------
  86. */
  87. ENTRY(do_dcsw_op)
  88. lsl x3, x3, #1
  89. cbz x3, exit
  90. sub x1, x1, #1
  91. lsl x1, x1, #1
  92. mov x10, x1
  93. adr x14, dcsw_loop_table // compute inner loop address
  94. add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions
  95. mov x0, x9
  96. mov w8, #1
  97. loop:
  98. add x2, x10, x10, lsr #1 // work out 3x current cache level
  99. lsr x1, x0, x2 // extract cache type bits from clidr
  100. and x1, x1, #7 // mask the bits for current cache only
  101. cmp x1, #2 // see what cache we have at this level
  102. b.lt level_done // nothing to do if no cache or icache
  103. msr csselr_el1, x10 // select current cache level in csselr
  104. isb // isb to sych the new cssr&csidr
  105. mrs x1, ccsidr_el1 // read the new ccsidr
  106. and x2, x1, #7 // extract the length of the cache lines
  107. add x2, x2, #4 // add 4 (line length offset)
  108. ubfx x4, x1, #3, #10 // maximum way number
  109. clz w5, w4 // bit position of way size increment
  110. lsl w9, w4, w5 // w9 = aligned max way number
  111. lsl w16, w8, w5 // w16 = way number loop decrement
  112. orr w9, w10, w9 // w9 = combine way and cache number
  113. ubfx w6, w1, #13, #15 // w6 = max set number
  114. lsl w17, w8, w2 // w17 = set number loop decrement
  115. dsb sy // barrier before we start this level
  116. br x14 // jump to DC operation specific loop
  117. .macro dcsw_loop _op
  118. loop2_\_op:
  119. lsl w7, w6, w2 // w7 = aligned max set number
  120. loop3_\_op:
  121. orr w11, w9, w7 // combine cache, way and set number
  122. dc \_op, x11
  123. subs w7, w7, w17 // decrement set number
  124. b.ge loop3_\_op
  125. subs x9, x9, x16 // decrement way number
  126. b.ge loop2_\_op
  127. b level_done
  128. .endm
  129. level_done:
  130. add x10, x10, #2 // increment cache number
  131. cmp x3, x10
  132. b.gt loop
  133. msr csselr_el1, xzr // select cache level 0 in csselr
  134. dsb sy // barrier to complete final cache operation
  135. isb
  136. exit:
  137. ret
  138. ENDPROC(do_dcsw_op)
  139. dcsw_loop_table:
  140. dcsw_loop isw
  141. dcsw_loop cisw
  142. dcsw_loop csw
  143. .macro __inner_dcache_all mode
  144. mov x0, \mode
  145. mov x1, #1
  146. mrs x9, clidr_el1
  147. ubfx x3, x9, #24, #0x7 /* LOC as last cache level */
  148. b do_dcsw_op
  149. .endm
  150. .macro __inner_dcache_L1 mode
  151. mov x0, \mode
  152. mov x1, #1
  153. mov x3, #1
  154. mrs x9, clidr_el1
  155. b do_dcsw_op
  156. .endm
  157. .macro __inner_dcache_L2 mode
  158. mov x0, \mode
  159. mov x1, #2
  160. mov x3, #2
  161. mrs x9, clidr_el1
  162. b do_dcsw_op
  163. .endm
  164. .macro __inner_dcache_L1_L2 mode
  165. mov x0, \mode
  166. mov x1, #1
  167. mov x3, #2
  168. mrs x9, clidr_el1
  169. b do_dcsw_op
  170. .endm
  171. ENTRY(__inner_flush_dcache_all)
  172. __inner_dcache_all #DCCISW
  173. ENDPROC(__inner_flush_dcache_all)
  174. ENTRY(__inner_flush_dcache_L1)
  175. __inner_dcache_L1 #DCCISW
  176. ENDPROC(__inner_flush_dcache_L1)
  177. ENTRY(__inner_flush_dcache_L2)
  178. __inner_dcache_L2 #DCCISW
  179. ENDPROC(__inner_flush_dcache_L2)
  180. ENTRY(__inner_clean_dcache_all)
  181. __inner_dcache_all #DCCSW
  182. ENDPROC(__inner_clean_dcache_all)
  183. ENTRY(__inner_clean_dcache_L1)
  184. __inner_dcache_L1 #DCCSW
  185. ENDPROC(__inner_clean_dcache_L1)
  186. ENTRY(__inner_clean_dcache_L2)
  187. __inner_dcache_L2 #DCCSW
  188. ENDPROC(__inner_clean_dcache_L2)
  189. ENTRY(__inner_inv_dcache_all)
  190. __inner_dcache_all #DCISW
  191. ENDPROC(__inner_inv_dcache_all)
  192. ENTRY(__inner_inv_dcache_L1)
  193. __inner_dcache_L1 #DCISW
  194. ENDPROC(__inner_clean_dcache_L1)
  195. ENTRY(__inner_inv_dcache_L2)
  196. __inner_dcache_L2 #DCISW
  197. ENDPROC(__inner_clean_dcache_L2)
  198. ENTRY(__disable_dcache__inner_flush_dcache_L1)
  199. __dis_D
  200. __inner_dcache_L1 #DCCISW
  201. ENDPROC(__disable_dcache__inner_flush_dcache_L1)
  202. ENTRY(__disable_dcache__inner_flush_dcache_L1__inner_flush_dcache_L2)
  203. __dis_D
  204. __inner_dcache_L1_L2 #DCCISW
  205. ENDPROC(__disable_dcache__inner_flush_dcache_L1__inner_flush_dcache_L2)
  206. ENTRY(__disable_dcache__inner_clean_dcache_L1__inner_clean_dcache_L2)
  207. __dis_D
  208. __inner_dcache_L1_L2 #DCCSW
  209. ENDPROC(__disable_dcache__inner_clean_dcache_L1__inner_clean_dcache_L2)
  210. ENTRY(__disable_dcache__inner_flush_dcache_L1__inner_clean_dcache_L2)
  211. __dis_D
  212. /* since we need to do different operations for L1/L2,
  213. and our current implementation would jump from do_dcsw_op to caller(who invokes the last bl) directly,
  214. we need to construct stack frame by ourself here.
  215. We use two caller-saved registers, x12 & x13, to save lr & sp,
  216. to prevent any memory access during cache operation
  217. NOTICE: any macro or function MUST not corrupt x12 & x13 here
  218. */
  219. mov x12, x29
  220. mov x13, x30
  221. mov x29, sp
  222. bl __inner_flush_dcache_L1
  223. mov x29, x12
  224. mov x30, x13
  225. __inner_dcache_L2 #DCCSW
  226. ENDPROC(__disable_dcache__inner_flush_dcache_L1__inner_clean_dcache_L2)