fsl_cache.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * The Clear BSD License
  3. * Copyright 2016-2017 NXP
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted (subject to the limitations in the disclaimer below) provided
  8. * that the following conditions are met:
  9. *
  10. * o Redistributions of source code must retain the above copyright notice, this list
  11. * of conditions and the following disclaimer.
  12. *
  13. * o Redistributions in binary form must reproduce the above copyright notice, this
  14. * list of conditions and the following disclaimer in the documentation and/or
  15. * other materials provided with the distribution.
  16. *
  17. * o Neither the name of the copyright holder nor the names of its
  18. * contributors may be used to endorse or promote products derived from this
  19. * software without specific prior written permission.
  20. *
  21. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  26. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  29. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include "fsl_cache.h"
  34. /*******************************************************************************
  35. * Definitions
  36. ******************************************************************************/
  37. /* Component ID definition, used by tools. */
  38. #ifndef FSL_COMPONENT_ID
  39. #define FSL_COMPONENT_ID "platform.drivers.cache_lmem"
  40. #endif
  41. #define L1CACHE_ONEWAYSIZE_BYTE (4096U) /*!< Cache size is 4K-bytes one way. */
  42. #define L1CACHE_CODEBUSADDR_BOUNDARY (0x1FFFFFFF) /*!< The processor code bus address boundary. */
  43. /*******************************************************************************
  44. * Code
  45. ******************************************************************************/
  46. #if (FSL_FEATURE_SOC_LMEM_COUNT == 1)
  47. void L1CACHE_EnableCodeCache(void)
  48. {
  49. /* First, invalidate the entire cache. */
  50. L1CACHE_InvalidateCodeCache();
  51. /* Now enable the cache. */
  52. LMEM->PCCCR |= LMEM_PCCCR_ENCACHE_MASK;
  53. }
  54. void L1CACHE_DisableCodeCache(void)
  55. {
  56. /* First, push any modified contents. */
  57. L1CACHE_CleanCodeCache();
  58. /* Now disable the cache. */
  59. LMEM->PCCCR &= ~LMEM_PCCCR_ENCACHE_MASK;
  60. }
  61. void L1CACHE_InvalidateCodeCache(void)
  62. {
  63. /* Enables the processor code bus to invalidate all lines in both ways.
  64. and Initiate the processor code bus code cache command. */
  65. LMEM->PCCCR |= LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_GO_MASK;
  66. /* Wait until the cache command completes. */
  67. while (LMEM->PCCCR & LMEM_PCCCR_GO_MASK)
  68. {
  69. }
  70. /* As a precaution clear the bits to avoid inadvertently re-running this command. */
  71. LMEM->PCCCR &= ~(LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_INVW1_MASK);
  72. }
  73. void L1CACHE_InvalidateCodeCacheByRange(uint32_t address, uint32_t size_byte)
  74. {
  75. uint32_t endAddr = address + size_byte;
  76. uint32_t pccReg = 0;
  77. /* Align address to cache line size. */
  78. uint32_t startAddr = address & ~(L1CODEBUSCACHE_LINESIZE_BYTE - 1U);
  79. while (startAddr < endAddr)
  80. {
  81. /* Set the invalidate by line command and use the physical address. */
  82. pccReg = (LMEM->PCCLCR & ~LMEM_PCCLCR_LCMD_MASK) | LMEM_PCCLCR_LCMD(1) | LMEM_PCCLCR_LADSEL_MASK;
  83. LMEM->PCCLCR = pccReg;
  84. /* Set the address and initiate the command. */
  85. LMEM->PCCSAR = (startAddr & LMEM_PCCSAR_PHYADDR_MASK) | LMEM_PCCSAR_LGO_MASK;
  86. /* Wait until the cache command completes. */
  87. while (LMEM->PCCSAR & LMEM_PCCSAR_LGO_MASK)
  88. {
  89. }
  90. startAddr += L1CODEBUSCACHE_LINESIZE_BYTE;
  91. }
  92. }
  93. void L1CACHE_CleanCodeCache(void)
  94. {
  95. /* Enable the processor code bus to push all modified lines. */
  96. LMEM->PCCCR |= LMEM_PCCCR_PUSHW0_MASK | LMEM_PCCCR_PUSHW1_MASK | LMEM_PCCCR_GO_MASK;
  97. /* Wait until the cache command completes. */
  98. while (LMEM->PCCCR & LMEM_PCCCR_GO_MASK)
  99. {
  100. }
  101. /* As a precaution clear the bits to avoid inadvertently re-running this command. */
  102. LMEM->PCCCR &= ~(LMEM_PCCCR_PUSHW0_MASK | LMEM_PCCCR_PUSHW1_MASK);
  103. }
  104. void L1CACHE_CleanCodeCacheByRange(uint32_t address, uint32_t size_byte)
  105. {
  106. uint32_t endAddr = address + size_byte;
  107. uint32_t pccReg = 0;
  108. /* Align address to cache line size. */
  109. uint32_t startAddr = address & ~(L1CODEBUSCACHE_LINESIZE_BYTE - 1U);
  110. while (startAddr < endAddr)
  111. {
  112. /* Set the push by line command. */
  113. pccReg = (LMEM->PCCLCR & ~LMEM_PCCLCR_LCMD_MASK) | LMEM_PCCLCR_LCMD(2) | LMEM_PCCLCR_LADSEL_MASK;
  114. LMEM->PCCLCR = pccReg;
  115. /* Set the address and initiate the command. */
  116. LMEM->PCCSAR = (startAddr & LMEM_PCCSAR_PHYADDR_MASK) | LMEM_PCCSAR_LGO_MASK;
  117. /* Wait until the cache command completes. */
  118. while (LMEM->PCCSAR & LMEM_PCCSAR_LGO_MASK)
  119. {
  120. }
  121. startAddr += L1CODEBUSCACHE_LINESIZE_BYTE;
  122. }
  123. }
  124. void L1CACHE_CleanInvalidateCodeCache(void)
  125. {
  126. /* Push and invalidate all. */
  127. LMEM->PCCCR |= LMEM_PCCCR_PUSHW0_MASK | LMEM_PCCCR_PUSHW1_MASK | LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_INVW1_MASK |
  128. LMEM_PCCCR_GO_MASK;
  129. /* Wait until the cache command completes. */
  130. while (LMEM->PCCCR & LMEM_PCCCR_GO_MASK)
  131. {
  132. }
  133. /* As a precaution clear the bits to avoid inadvertently re-running this command. */
  134. LMEM->PCCCR &= ~(LMEM_PCCCR_PUSHW0_MASK | LMEM_PCCCR_PUSHW1_MASK | LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_INVW1_MASK);
  135. }
  136. void L1CACHE_CleanInvalidateCodeCacheByRange(uint32_t address, uint32_t size_byte)
  137. {
  138. uint32_t endAddr = address + size_byte;
  139. uint32_t pccReg = 0;
  140. /* Align address to cache line size. */
  141. uint32_t startAddr = address & ~(L1CODEBUSCACHE_LINESIZE_BYTE - 1U);
  142. while (startAddr < endAddr)
  143. {
  144. /* Set the push by line command. */
  145. pccReg = (LMEM->PCCLCR & ~LMEM_PCCLCR_LCMD_MASK) | LMEM_PCCLCR_LCMD(3) | LMEM_PCCLCR_LADSEL_MASK;
  146. LMEM->PCCLCR = pccReg;
  147. /* Set the address and initiate the command. */
  148. LMEM->PCCSAR = (startAddr & LMEM_PCCSAR_PHYADDR_MASK) | LMEM_PCCSAR_LGO_MASK;
  149. /* Wait until the cache command completes. */
  150. while (LMEM->PCCSAR & LMEM_PCCSAR_LGO_MASK)
  151. {
  152. }
  153. startAddr += L1CODEBUSCACHE_LINESIZE_BYTE;
  154. }
  155. }
  156. #if defined(FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE) && FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE
  157. void L1CACHE_EnableSystemCache(void)
  158. {
  159. /* First, invalidate the entire cache. */
  160. L1CACHE_InvalidateSystemCache();
  161. /* Now enable the cache. */
  162. LMEM->PSCCR |= LMEM_PSCCR_ENCACHE_MASK;
  163. }
  164. void L1CACHE_DisableSystemCache(void)
  165. {
  166. /* First, push any modified contents. */
  167. L1CACHE_CleanSystemCache();
  168. /* Now disable the cache. */
  169. LMEM->PSCCR &= ~LMEM_PSCCR_ENCACHE_MASK;
  170. }
  171. void L1CACHE_InvalidateSystemCache(void)
  172. {
  173. /* Enables the processor system bus to invalidate all lines in both ways.
  174. and Initiate the processor system bus cache command. */
  175. LMEM->PSCCR |= LMEM_PSCCR_INVW0_MASK | LMEM_PSCCR_INVW1_MASK | LMEM_PSCCR_GO_MASK;
  176. /* Wait until the cache command completes */
  177. while (LMEM->PSCCR & LMEM_PSCCR_GO_MASK)
  178. {
  179. }
  180. /* As a precaution clear the bits to avoid inadvertently re-running this command. */
  181. LMEM->PSCCR &= ~(LMEM_PSCCR_INVW0_MASK | LMEM_PSCCR_INVW1_MASK);
  182. }
  183. void L1CACHE_InvalidateSystemCacheByRange(uint32_t address, uint32_t size_byte)
  184. {
  185. uint32_t endAddr = address + size_byte;
  186. uint32_t pscReg = 0;
  187. uint32_t startAddr = address & ~(L1SYSTEMBUSCACHE_LINESIZE_BYTE - 1U); /* Align address to cache line size */
  188. while (startAddr < endAddr)
  189. {
  190. /* Set the invalidate by line command and use the physical address. */
  191. pscReg = (LMEM->PSCLCR & ~LMEM_PSCLCR_LCMD_MASK) | LMEM_PSCLCR_LCMD(1) | LMEM_PSCLCR_LADSEL_MASK;
  192. LMEM->PSCLCR = pscReg;
  193. /* Set the address and initiate the command. */
  194. LMEM->PSCSAR = (startAddr & LMEM_PSCSAR_PHYADDR_MASK) | LMEM_PSCSAR_LGO_MASK;
  195. /* Wait until the cache command completes. */
  196. while (LMEM->PSCSAR & LMEM_PSCSAR_LGO_MASK)
  197. {
  198. }
  199. startAddr += L1SYSTEMBUSCACHE_LINESIZE_BYTE;
  200. }
  201. }
  202. void L1CACHE_CleanSystemCache(void)
  203. {
  204. /* Enable the processor system bus to push all modified lines. */
  205. LMEM->PSCCR |= LMEM_PSCCR_PUSHW0_MASK | LMEM_PSCCR_PUSHW1_MASK | LMEM_PSCCR_GO_MASK;
  206. /* Wait until the cache command completes. */
  207. while (LMEM->PSCCR & LMEM_PSCCR_GO_MASK)
  208. {
  209. }
  210. /* As a precaution clear the bits to avoid inadvertently re-running this command. */
  211. LMEM->PSCCR &= ~(LMEM_PSCCR_PUSHW0_MASK | LMEM_PSCCR_PUSHW1_MASK);
  212. }
  213. void L1CACHE_CleanSystemCacheByRange(uint32_t address, uint32_t size_byte)
  214. {
  215. uint32_t endAddr = address + size_byte;
  216. uint32_t pscReg = 0;
  217. uint32_t startAddr = address & ~(L1SYSTEMBUSCACHE_LINESIZE_BYTE - 1U); /* Align address to cache line size. */
  218. while (startAddr < endAddr)
  219. {
  220. /* Set the push by line command. */
  221. pscReg = (LMEM->PSCLCR & ~LMEM_PSCLCR_LCMD_MASK) | LMEM_PSCLCR_LCMD(2) | LMEM_PSCLCR_LADSEL_MASK;
  222. LMEM->PSCLCR = pscReg;
  223. /* Set the address and initiate the command. */
  224. LMEM->PSCSAR = (startAddr & LMEM_PSCSAR_PHYADDR_MASK) | LMEM_PSCSAR_LGO_MASK;
  225. /* Wait until the cache command completes. */
  226. while (LMEM->PSCSAR & LMEM_PSCSAR_LGO_MASK)
  227. {
  228. }
  229. startAddr += L1SYSTEMBUSCACHE_LINESIZE_BYTE;
  230. }
  231. }
  232. void L1CACHE_CleanInvalidateSystemCache(void)
  233. {
  234. /* Push and invalidate all. */
  235. LMEM->PSCCR |= LMEM_PSCCR_PUSHW0_MASK | LMEM_PSCCR_PUSHW1_MASK | LMEM_PSCCR_INVW0_MASK | LMEM_PSCCR_INVW1_MASK |
  236. LMEM_PSCCR_GO_MASK;
  237. /* Wait until the cache command completes. */
  238. while (LMEM->PSCCR & LMEM_PSCCR_GO_MASK)
  239. {
  240. }
  241. /* As a precaution clear the bits to avoid inadvertently re-running this command. */
  242. LMEM->PSCCR &= ~(LMEM_PSCCR_PUSHW0_MASK | LMEM_PSCCR_PUSHW1_MASK | LMEM_PSCCR_INVW0_MASK | LMEM_PSCCR_INVW1_MASK);
  243. }
  244. void L1CACHE_CleanInvalidateSystemCacheByRange(uint32_t address, uint32_t size_byte)
  245. {
  246. uint32_t endAddr = address + size_byte;
  247. uint32_t pscReg = 0;
  248. uint32_t startAddr = address & ~(L1SYSTEMBUSCACHE_LINESIZE_BYTE - 1U); /* Align address to cache line size. */
  249. while (startAddr < endAddr)
  250. {
  251. /* Set the push by line command. */
  252. pscReg = (LMEM->PSCLCR & ~LMEM_PSCLCR_LCMD_MASK) | LMEM_PSCLCR_LCMD(3) | LMEM_PSCLCR_LADSEL_MASK;
  253. LMEM->PSCLCR = pscReg;
  254. /* Set the address and initiate the command. */
  255. LMEM->PSCSAR = (startAddr & LMEM_PSCSAR_PHYADDR_MASK) | LMEM_PSCSAR_LGO_MASK;
  256. /* Wait until the cache command completes. */
  257. while (LMEM->PSCSAR & LMEM_PSCSAR_LGO_MASK)
  258. {
  259. }
  260. startAddr += L1SYSTEMBUSCACHE_LINESIZE_BYTE;
  261. }
  262. }
  263. #endif /* FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE */
  264. #endif /* FSL_FEATURE_SOC_LMEM_COUNT == 1 */
  265. void L1CACHE_InvalidateICacheByRange(uint32_t address, uint32_t size_byte)
  266. {
  267. #if (FSL_FEATURE_SOC_LMEM_COUNT == 1)
  268. uint32_t endAddr = address + size_byte;
  269. uint32_t size = size_byte;
  270. if (endAddr <= L1CACHE_CODEBUSADDR_BOUNDARY)
  271. {
  272. L1CACHE_InvalidateCodeCacheByRange(address, size);
  273. }
  274. else if (address <= L1CACHE_CODEBUSADDR_BOUNDARY)
  275. {
  276. size = L1CACHE_CODEBUSADDR_BOUNDARY - address;
  277. L1CACHE_InvalidateCodeCacheByRange(address, size);
  278. #if defined(FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE) && FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE
  279. size = size_byte - size;
  280. L1CACHE_InvalidateSystemCacheByRange((L1CACHE_CODEBUSADDR_BOUNDARY + 1), size);
  281. #endif /* FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE */
  282. }
  283. else
  284. {
  285. #if defined(FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE) && FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE
  286. L1CACHE_InvalidateSystemCacheByRange(address, size);
  287. #endif /* FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE */
  288. }
  289. #endif /* FSL_FEATURE_SOC_LMEM_COUNT == 1 */
  290. }
  291. void L1CACHE_CleanDCacheByRange(uint32_t address, uint32_t size_byte)
  292. {
  293. #if (FSL_FEATURE_SOC_LMEM_COUNT == 1)
  294. uint32_t endAddr = address + size_byte;
  295. uint32_t size = size_byte;
  296. if (endAddr <= L1CACHE_CODEBUSADDR_BOUNDARY)
  297. {
  298. L1CACHE_CleanCodeCacheByRange(address, size);
  299. }
  300. else if (address <= L1CACHE_CODEBUSADDR_BOUNDARY)
  301. {
  302. size = L1CACHE_CODEBUSADDR_BOUNDARY - address;
  303. L1CACHE_CleanCodeCacheByRange(address, size);
  304. #if defined(FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE) && FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE
  305. size = size_byte - size;
  306. L1CACHE_CleanSystemCacheByRange((L1CACHE_CODEBUSADDR_BOUNDARY + 1), size);
  307. #endif /* FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE */
  308. }
  309. else
  310. {
  311. #if defined(FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE) && FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE
  312. L1CACHE_CleanSystemCacheByRange(address, size);
  313. #endif /* FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE */
  314. }
  315. #endif /* FSL_FEATURE_SOC_LMEM_COUNT == 1 */
  316. }
  317. void L1CACHE_CleanInvalidateDCacheByRange(uint32_t address, uint32_t size_byte)
  318. {
  319. #if (FSL_FEATURE_SOC_LMEM_COUNT == 1)
  320. uint32_t endAddr = address + size_byte;
  321. uint32_t size = size_byte;
  322. if (endAddr <= L1CACHE_CODEBUSADDR_BOUNDARY)
  323. {
  324. L1CACHE_CleanInvalidateCodeCacheByRange(address, size);
  325. }
  326. else if (address <= L1CACHE_CODEBUSADDR_BOUNDARY)
  327. {
  328. size = L1CACHE_CODEBUSADDR_BOUNDARY - address;
  329. L1CACHE_CleanInvalidateCodeCacheByRange(address, size);
  330. #if defined(FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE) && FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE
  331. size = size_byte - size;
  332. L1CACHE_CleanInvalidateSystemCacheByRange((L1CACHE_CODEBUSADDR_BOUNDARY + 1), size);
  333. #endif /* FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE */
  334. }
  335. else
  336. {
  337. #if defined(FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE) && FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE
  338. L1CACHE_CleanInvalidateSystemCacheByRange(address, size);
  339. #endif /* FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE */
  340. }
  341. #endif /* FSL_FEATURE_SOC_LMEM_COUNT == 1 */
  342. }