cache-ops.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*
  2. * Copyright (c) 2008 Travis Geiselbrecht
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files
  6. * (the "Software"), to deal in the Software without restriction,
  7. * including without limitation the rights to use, copy, modify, merge,
  8. * publish, distribute, sublicense, and/or sell copies of the Software,
  9. * and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <asm.h>
  24. #include <arch/ops.h>
  25. #include <arch/defines.h>
  26. .text
  27. #if ARM_WITH_CACHE
  28. /* low level cache routines for various cpu families */
  29. #if ARM_CPU_ARM1136 || ARM_CPU_ARM926
  30. /* void arch_disable_cache(uint flags) */
  31. FUNCTION(arch_disable_cache)
  32. mov r12, #0 // zero register
  33. mrs r3, cpsr // save the old interrupt state
  34. #if ARM_ISA_ARMv6
  35. .word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
  36. #else
  37. orr r3, r3, #(1<<7)
  38. msr cpsr, r3
  39. #endif
  40. .Ldcache_disable:
  41. tst r0, #DCACHE
  42. beq .Licache_disable
  43. mrc p15, 0, r1, c1, c0, 0 // cr1
  44. tst r1, #(1<<2) // is the dcache already disabled?
  45. beq .Licache_disable
  46. bic r1, #(1<<2)
  47. mcr p15, 0, r1, c1, c0, 0 // disable dcache
  48. #if ARM_CPU_ARM1136
  49. mcr p15, 0, r12, c7, c14, 0 // clean & invalidate dcache
  50. #elif ARM_CPU_ARM926
  51. 0:
  52. mrc p15, 0, r15, c7, c14, 3 // clean & invalidate dcache
  53. bne 0b
  54. #else
  55. #error whut?
  56. #endif
  57. mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
  58. .Licache_disable:
  59. tst r0, #ICACHE
  60. beq .Ldone_disable
  61. mrc p15, 0, r1, c1, c0, 0 // cr1
  62. bic r1, #(1<<12)
  63. mcr p15, 0, r1, c1, c0, 0 // disable icache
  64. mcr p15, 0, r12, c7, c5, 0 // invalidate icache
  65. .Ldone_disable:
  66. msr cpsr, r3
  67. bx lr
  68. /* void arch_enable_cache(uint flags) */
  69. FUNCTION(arch_enable_cache)
  70. mov r12, #0 // zero register
  71. mrs r3, cpsr // save the old interrupt state
  72. #if ARM_ISA_ARMv6
  73. .word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
  74. #else
  75. orr r3, r3, #(1<<7)
  76. msr cpsr, r3
  77. #endif
  78. .Ldcache_enable:
  79. tst r0, #DCACHE
  80. beq .Licache_enable
  81. mrc p15, 0, r1, c1, c0, 0 // cr1
  82. tst r1, #(1<<2) // is the dcache already enabled?
  83. bne .Licache_enable
  84. mcr p15, 0, r12, c7, c6, 0 // invalidate dcache
  85. orr r1, #(1<<2)
  86. mcr p15, 0, r1, c1, c0, 0 // enable dcache
  87. .Licache_enable:
  88. tst r0, #ICACHE
  89. beq .Ldone_enable
  90. mcr p15, 0, r12, c7, c5, 0 // invalidate icache
  91. mrc p15, 0, r1, c1, c0, 0 // cr1
  92. orr r1, #(1<<12)
  93. mcr p15, 0, r1, c1, c0, 0 // enable icache
  94. .Ldone_enable:
  95. msr cpsr, r3
  96. bx lr
  97. #elif ARM_ISA_ARMV7
  98. /* void arch_disable_cache(uint flags) */
  99. FUNCTION(arch_disable_cache)
  100. stmfd sp!, {r4-r11, lr}
  101. mov r7, r0 // save flags
  102. mrs r12, cpsr // save the old interrupt state
  103. .word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
  104. .Ldcache_disable:
  105. tst r7, #DCACHE
  106. beq .Licache_disable
  107. mrc p15, 0, r0, c1, c0, 0 // cr1
  108. tst r0, #(1<<2) // is the dcache already disabled?
  109. beq .Ldcache_already_disabled
  110. bic r0, #(1<<2)
  111. mcr p15, 0, r0, c1, c0, 0 // disable dcache
  112. // flush and invalidate the dcache
  113. // NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
  114. bl flush_invalidate_cache_v7
  115. b .Ldcache_disable_L2
  116. .Ldcache_already_disabled:
  117. // make sure all of the caches are invalidated
  118. // NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
  119. bl invalidate_cache_v7
  120. .Ldcache_disable_L2:
  121. #if ARM_CPU_CORTEX_A9
  122. // disable the L2, if present
  123. mrc p15, 0, r0, c1, c0, 1 // aux cr1
  124. bic r0, #(1<<1)
  125. mcr p15, 0, r0, c1, c0, 1 // disable L2 dcache
  126. #endif
  127. .Licache_disable:
  128. tst r7, #ICACHE
  129. beq .Ldone_disable
  130. mrc p15, 0, r0, c1, c0, 0 // cr1
  131. bic r0, #(1<<12)
  132. mcr p15, 0, r0, c1, c0, 0 // disable icache
  133. .Ldone_disable:
  134. // make sure the icache is always invalidated
  135. mov r0, #0
  136. mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
  137. msr cpsr, r12
  138. ldmfd sp!, {r4-r11, pc}
  139. /* void arch_enable_cache(uint flags) */
  140. FUNCTION(arch_enable_cache)
  141. stmfd sp!, {r4-r11, lr}
  142. mov r7, r0 // save flags
  143. mrs r12, cpsr // save the old interrupt state
  144. .word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
  145. .Ldcache_enable:
  146. tst r7, #DCACHE
  147. beq .Licache_enable
  148. mrc p15, 0, r0, c1, c0, 0 // cr1
  149. tst r0, #(1<<2) // is the dcache already enabled?
  150. bne .Licache_enable
  151. // invalidate L1 and L2
  152. // NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
  153. bl invalidate_cache_v7
  154. #if ARM_CPU_CORTEX_A9
  155. // enable the L2, if present
  156. mrc p15, 0, r0, c1, c0, 1 // aux cr1
  157. orr r0, #(1<<1)
  158. mcr p15, 0, r0, c1, c0, 1 // enable L2 dcache
  159. #endif
  160. mrc p15, 0, r0, c1, c0, 0 // cr1
  161. orr r0, #(1<<2)
  162. mcr p15, 0, r0, c1, c0, 0 // enable dcache
  163. .Licache_enable:
  164. tst r7, #ICACHE
  165. beq .Ldone_enable
  166. mov r0, #0
  167. mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
  168. mrc p15, 0, r0, c1, c0, 0 // cr1
  169. orr r0, #(1<<12)
  170. mcr p15, 0, r0, c1, c0, 0 // enable icache
  171. .Ldone_enable:
  172. msr cpsr, r12
  173. ldmfd sp!, {r4-r11, pc}
  174. // flush & invalidate cache routine, trashes r0-r6, r9-r11
  175. flush_invalidate_cache_v7:
  176. /* from ARMv7 manual, B2-17 */
  177. MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
  178. ANDS R3, R0, #0x7000000
  179. MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
  180. BEQ .Lfinished
  181. MOV R10, #0
  182. .Loop1:
  183. ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
  184. MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
  185. AND R1, R1, #7 // get those 3 bits alone
  186. CMP R1, #2
  187. BLT .Lskip // no cache or only instruction cache at this level
  188. MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
  189. .word 0xf57ff06f // ISB // ISB to sync the change to the CacheSizeID reg
  190. MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
  191. AND R2, R1, #0x7 // extract the line length field
  192. ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
  193. LDR R4, =0x3FF
  194. ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
  195. CLZ R5, R4 // R5 is the bit position of the way size increment
  196. LDR R6, =0x00007FFF
  197. ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
  198. .Loop2:
  199. MOV R9, R4 // R9 working copy of the max way size (right aligned)
  200. .Loop3:
  201. ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
  202. ORR R11, R11, R6, LSL R2 // factor in the index number
  203. MCR p15, 0, R11, c7, c14, 2 // clean & invalidate by set/way
  204. SUBS R9, R9, #1 // decrement the way number
  205. BGE .Loop3
  206. SUBS R6, R6, #1 // decrement the index
  207. BGE .Loop2
  208. .Lskip:
  209. ADD R10, R10, #2 // increment the cache number
  210. CMP R3, R10
  211. BGT .Loop1
  212. .Lfinished:
  213. mov r10, #0
  214. mcr p15, 2, r10, c0, c0, 0 // select cache level 0
  215. .word 0xf57ff06f // isb
  216. bx lr
  217. // invalidate cache routine, trashes r0-r6, r9-r11
  218. invalidate_cache_v7:
  219. /* from ARMv7 manual, B2-17 */
  220. MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
  221. ANDS R3, R0, #0x7000000
  222. MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
  223. BEQ .Lfinished_invalidate
  224. MOV R10, #0
  225. .Loop1_invalidate:
  226. ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
  227. MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
  228. AND R1, R1, #7 // get those 3 bits alone
  229. CMP R1, #2
  230. BLT .Lskip_invalidate // no cache or only instruction cache at this level
  231. MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
  232. .word 0xf57ff06f // ISB // ISB to sync the change to the CacheSizeID reg
  233. MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
  234. AND R2, R1, #0x7 // extract the line length field
  235. ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
  236. LDR R4, =0x3FF
  237. ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
  238. CLZ R5, R4 // R5 is the bit position of the way size increment
  239. LDR R6, =0x00007FFF
  240. ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
  241. .Loop2_invalidate:
  242. MOV R9, R4 // R9 working copy of the max way size (right aligned)
  243. .Loop3_invalidate:
  244. ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
  245. ORR R11, R11, R6, LSL R2 // factor in the index number
  246. MCR p15, 0, R11, c7, c6, 2 // invalidate by set/way
  247. SUBS R9, R9, #1 // decrement the way number
  248. BGE .Loop3_invalidate
  249. SUBS R6, R6, #1 // decrement the index
  250. BGE .Loop2_invalidate
  251. .Lskip_invalidate:
  252. ADD R10, R10, #2 // increment the cache number
  253. CMP R3, R10
  254. BGT .Loop1_invalidate
  255. .Lfinished_invalidate:
  256. mov r10, #0
  257. mcr p15, 2, r10, c0, c0, 0 // select cache level 0
  258. .word 0xf57ff06f // isb
  259. bx lr
  260. #else
  261. #error unhandled cpu
  262. #endif
  263. #if ARM_CPU_ARM926 || ARM_CPU_ARM1136 || ARM_CPU_CORTEX_A8 || ARM_CPU_CORTEX_A9 || ARM_CPU_CORTEX_A7 || ARM_CPU_CORTEX_A53
  264. /* shared cache flush routines */
  265. /* void arch_flush_cache_range(addr_t start, size_t len); */
  266. FUNCTION(arch_clean_cache_range)
  267. #ifdef HAVE_CACHE_PL310
  268. stmfd sp!, {r4, r5, lr}
  269. mov r4, r0
  270. mov r5, r1
  271. #endif
  272. add r2, r0, r1 // get the end address
  273. bic r0, #(CACHE_LINE - 1) // align the start address
  274. 0:
  275. #ifdef CONFIG_ARM_ERRATA_855873
  276. mcr p15, 0, r0, c7, c14, 1 // clean cache to PoC by MVA (DCCIMVAC )
  277. #else
  278. mcr p15, 0, r0, c7, c10, 1 // clean cache to PoC by MVA
  279. #endif
  280. add r0, r0, #CACHE_LINE
  281. cmp r0, r2
  282. blo 0b
  283. mov r0, #0
  284. mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
  285. mov r0, r4
  286. mov r1, r5
  287. #ifdef HAVE_CACHE_PL310
  288. bl l2_clean_range
  289. ldmfd sp!, {r4, r5, pc}
  290. #else
  291. bx lr
  292. #endif
  293. /* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
  294. FUNCTION(arch_clean_invalidate_cache_range)
  295. #ifdef HAVE_CACHE_PL310
  296. stmfd sp!, {r4, r5, lr}
  297. mov r4, r0
  298. mov r5, r1
  299. #endif
  300. add r2, r0, r1 // get the end address
  301. bic r0, #(CACHE_LINE - 1) // align the start address
  302. 0:
  303. mcr p15, 0, r0, c7, c14, 1 // clean & invalidate cache to PoC by MVA
  304. add r0, r0, #CACHE_LINE
  305. cmp r0, r2
  306. blo 0b
  307. mov r0, #0
  308. mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
  309. mov r0, r4
  310. mov r1, r5
  311. #ifdef HAVE_CACHE_PL310
  312. bl l2_flush_range
  313. ldmfd sp!, {r4, r5, pc}
  314. #else
  315. bx lr
  316. #endif
  317. /* void arch_sync_cache_range(addr_t start, size_t len); */
  318. FUNCTION(arch_sync_cache_range)
  319. push { r14 }
  320. bl arch_clean_cache_range
  321. mov r0, #0
  322. mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
  323. pop { pc }
  324. #else
  325. #error unhandled cpu
  326. #endif
  327. #else
  328. /* no cache */
  329. FUNCTION(arch_disable_cache)
  330. bx lr
  331. FUNCTION(arch_enable_cache)
  332. bx lr
  333. FUNCTION(arch_clean_cache_range)
  334. bx lr
  335. FUNCTION(arch_clean_invalidate_cache_range)
  336. bx lr
  337. FUNCTION(arch_sync_cache_range)
  338. bx lr
  339. #endif // ARM_WITH_CACHE