cache.S 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * File: arch/blackfin/mach-common/cache.S
  3. * Based on:
  4. * Author: LG Soft India
  5. *
  6. * Created:
  7. * Description: cache control support
  8. *
  9. * Modified:
  10. * Copyright 2004-2006 Analog Devices Inc.
  11. *
  12. * Bugs: Enter bugs at http://blackfin.uclinux.org/
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 2 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, see the file COPYING, or write
  26. * to the Free Software Foundation, Inc.,
  27. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  28. */
  29. #include <linux/linkage.h>
  30. #include <asm/cplb.h>
  31. #include <asm/entry.h>
  32. #include <asm/blackfin.h>
  33. #include <asm/cache.h>
  34. .text
  35. .align 2
  36. ENTRY(_cache_invalidate)
  37. /*
  38. * Icache or DcacheA or DcacheB Invalidation
  39. * or any combination thereof
  40. * R0 has bits
  41. * CPLB_ENABLE_ICACHE_P,CPLB_ENABLE_DCACHE_P,CPLB_ENABLE_DCACHE2_P
  42. * set as required
  43. */
  44. [--SP] = R7;
  45. R7 = R0;
  46. CC = BITTST(R7,CPLB_ENABLE_ICACHE_P);
  47. IF !CC JUMP .Lno_icache;
  48. [--SP] = RETS;
  49. CALL _icache_invalidate;
  50. RETS = [SP++];
  51. .Lno_icache:
  52. CC = BITTST(R7,CPLB_ENABLE_DCACHE_P);
  53. IF !CC JUMP .Lno_dcache_a;
  54. R0 = 0; /* specifies bank A */
  55. [--SP] = RETS;
  56. CALL _dcache_invalidate;
  57. RETS = [SP++];
  58. .Lno_dcache_a:
  59. CC = BITTST(R7,CPLB_ENABLE_DCACHE2_P);
  60. IF !CC JUMP .Lno_dcache_b;
  61. R0 = 0;
  62. BITSET(R0, 23); /* specifies bank B */
  63. [--SP] = RETS;
  64. CALL _dcache_invalidate;
  65. RETS = [SP++];
  66. .Lno_dcache_b:
  67. R7 = [SP++];
  68. RTS;
  69. ENDPROC(_cache_invalidate)
  70. /* Invalidate the Entire Instruction cache by
  71. * disabling IMC bit
  72. */
  73. ENTRY(_icache_invalidate)
  74. ENTRY(_invalidate_entire_icache)
  75. [--SP] = ( R7:5);
  76. P0.L = LO(IMEM_CONTROL);
  77. P0.H = HI(IMEM_CONTROL);
  78. R7 = [P0];
  79. /* Clear the IMC bit , All valid bits in the instruction
  80. * cache are set to the invalid state
  81. */
  82. BITCLR(R7,IMC_P);
  83. CLI R6;
  84. SSYNC; /* SSYNC required before invalidating cache. */
  85. .align 8;
  86. [P0] = R7;
  87. SSYNC;
  88. STI R6;
  89. /* Configures the instruction cache agian */
  90. R6 = (IMC | ENICPLB);
  91. R7 = R7 | R6;
  92. CLI R6;
  93. SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
  94. .align 8;
  95. [P0] = R7;
  96. SSYNC;
  97. STI R6;
  98. ( R7:5) = [SP++];
  99. RTS;
  100. ENDPROC(_invalidate_entire_icache)
  101. ENDPROC(_icache_invalidate)
  102. /*
  103. * blackfin_cache_flush_range(start, end)
  104. * Invalidate all cache lines assocoiated with this
  105. * area of memory.
  106. *
  107. * start: Start address
  108. * end: End address
  109. */
  110. ENTRY(_blackfin_icache_flush_range)
  111. R2 = -L1_CACHE_BYTES;
  112. R2 = R0 & R2;
  113. P0 = R2;
  114. P1 = R1;
  115. CSYNC(R3);
  116. IFLUSH [P0];
  117. 1:
  118. IFLUSH [P0++];
  119. CC = P0 < P1 (iu);
  120. IF CC JUMP 1b (bp);
  121. IFLUSH [P0];
  122. SSYNC(R3);
  123. RTS;
  124. ENDPROC(_blackfin_icache_flush_range)
  125. /*
  126. * blackfin_icache_dcache_flush_range(start, end)
  127. * FLUSH all cache lines assocoiated with this
  128. * area of memory.
  129. *
  130. * start: Start address
  131. * end: End address
  132. */
  133. ENTRY(_blackfin_icache_dcache_flush_range)
  134. R2 = -L1_CACHE_BYTES;
  135. R2 = R0 & R2;
  136. P0 = R2;
  137. P1 = R1;
  138. CSYNC(R3);
  139. IFLUSH [P0];
  140. 1:
  141. FLUSH [P0];
  142. IFLUSH [P0++];
  143. CC = P0 < P1 (iu);
  144. IF CC JUMP 1b (bp);
  145. IFLUSH [P0];
  146. FLUSH [P0];
  147. SSYNC(R3);
  148. RTS;
  149. ENDPROC(_blackfin_icache_dcache_flush_range)
  150. /* Throw away all D-cached data in specified region without any obligation to
  151. * write them back. However, we must clean the D-cached entries around the
  152. * boundaries of the start and/or end address is not cache aligned.
  153. *
  154. * Start: start address,
  155. * end : end address.
  156. */
  157. ENTRY(_blackfin_dcache_invalidate_range)
  158. R2 = -L1_CACHE_BYTES;
  159. R2 = R0 & R2;
  160. P0 = R2;
  161. P1 = R1;
  162. CSYNC(R3);
  163. FLUSHINV[P0];
  164. 1:
  165. FLUSHINV[P0++];
  166. CC = P0 < P1 (iu);
  167. IF CC JUMP 1b (bp);
  168. /* If the data crosses a cache line, then we'll be pointing to
  169. * the last cache line, but won't have flushed/invalidated it yet,
  170. * so do one more.
  171. */
  172. FLUSHINV[P0];
  173. SSYNC(R3);
  174. RTS;
  175. ENDPROC(_blackfin_dcache_invalidate_range)
  176. /* Invalidate the Entire Data cache by
  177. * clearing DMC[1:0] bits
  178. */
  179. ENTRY(_invalidate_entire_dcache)
  180. ENTRY(_dcache_invalidate)
  181. [--SP] = ( R7:6);
  182. P0.L = LO(DMEM_CONTROL);
  183. P0.H = HI(DMEM_CONTROL);
  184. R7 = [P0];
  185. /* Clear the DMC[1:0] bits, All valid bits in the data
  186. * cache are set to the invalid state
  187. */
  188. BITCLR(R7,DMC0_P);
  189. BITCLR(R7,DMC1_P);
  190. CLI R6;
  191. SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
  192. .align 8;
  193. [P0] = R7;
  194. SSYNC;
  195. STI R6;
  196. /* Configures the data cache again */
  197. R6 = DMEM_CNTR;
  198. R7 = R7 | R6;
  199. CLI R6;
  200. SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
  201. .align 8;
  202. [P0] = R7;
  203. SSYNC;
  204. STI R6;
  205. ( R7:6) = [SP++];
  206. RTS;
  207. ENDPROC(_dcache_invalidate)
  208. ENDPROC(_invalidate_entire_dcache)
  209. ENTRY(_blackfin_dcache_flush_range)
  210. R2 = -L1_CACHE_BYTES;
  211. R2 = R0 & R2;
  212. P0 = R2;
  213. P1 = R1;
  214. CSYNC(R3);
  215. FLUSH[P0];
  216. 1:
  217. FLUSH[P0++];
  218. CC = P0 < P1 (iu);
  219. IF CC JUMP 1b (bp);
  220. /* If the data crosses a cache line, then we'll be pointing to
  221. * the last cache line, but won't have flushed it yet, so do
  222. * one more.
  223. */
  224. FLUSH[P0];
  225. SSYNC(R3);
  226. RTS;
  227. ENDPROC(_blackfin_dcache_flush_range)
  228. ENTRY(_blackfin_dflush_page)
  229. P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT);
  230. P0 = R0;
  231. CSYNC(R3);
  232. FLUSH[P0];
  233. LSETUP (.Lfl1, .Lfl1) LC0 = P1;
  234. .Lfl1: FLUSH [P0++];
  235. SSYNC(R3);
  236. RTS;
  237. ENDPROC(_blackfin_dflush_page)