fsl_flexcomm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2016, Freescale Semiconductor, Inc.
  4. * Copyright 2016-2017 NXP
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include "fsl_common.h"
  35. #include "fsl_flexcomm.h"
  36. /*******************************************************************************
  37. * Definitions
  38. ******************************************************************************/
  39. /* Component ID definition, used by tools. */
  40. #ifndef FSL_COMPONENT_ID
  41. #define FSL_COMPONENT_ID "platform.drivers.flexcomm"
  42. #endif
  43. /*******************************************************************************
  44. * Prototypes
  45. ******************************************************************************/
  46. /*! @brief Set the FLEXCOMM mode . */
  47. static status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock);
  48. /*! @brief check whether flexcomm supports peripheral type */
  49. static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph);
  50. /*******************************************************************************
  51. * Variables
  52. ******************************************************************************/
  53. /*! @brief Pointers to real IRQ handlers installed by drivers for each instance. */
  54. static flexcomm_irq_handler_t s_flexcommIrqHandler[FSL_FEATURE_SOC_FLEXCOMM_COUNT];
  55. /*! @brief Pointers to handles for each instance to provide context to interrupt routines */
  56. static void *s_flexcommHandle[FSL_FEATURE_SOC_FLEXCOMM_COUNT];
  57. /*! @brief Array to map FLEXCOMM instance number to IRQ number. */
  58. IRQn_Type const kFlexcommIrqs[] = FLEXCOMM_IRQS;
  59. /*! @brief Array to map FLEXCOMM instance number to base address. */
  60. static const uint32_t s_flexcommBaseAddrs[FSL_FEATURE_SOC_FLEXCOMM_COUNT] = FLEXCOMM_BASE_ADDRS;
  61. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  62. /*! @brief IDs of clock for each FLEXCOMM module */
  63. static const clock_ip_name_t s_flexcommClocks[] = FLEXCOMM_CLOCKS;
  64. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  65. /*******************************************************************************
  66. * Code
  67. ******************************************************************************/
  68. /* check whether flexcomm supports peripheral type */
  69. static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph)
  70. {
  71. if (periph == FLEXCOMM_PERIPH_NONE)
  72. {
  73. return true;
  74. }
  75. else if (periph <= FLEXCOMM_PERIPH_I2S_TX)
  76. {
  77. return (base->PSELID & (uint32_t)(1 << ((uint32_t)periph + 3))) > (uint32_t)0 ? true : false;
  78. }
  79. else if (periph == FLEXCOMM_PERIPH_I2S_RX)
  80. {
  81. return (base->PSELID & (1 << 7)) > (uint32_t)0 ? true : false;
  82. }
  83. else
  84. {
  85. return false;
  86. }
  87. }
  88. /* Get the index corresponding to the FLEXCOMM */
  89. uint32_t FLEXCOMM_GetInstance(void *base)
  90. {
  91. int i;
  92. for (i = 0; i < FSL_FEATURE_SOC_FLEXCOMM_COUNT; i++)
  93. {
  94. if ((uint32_t)base == s_flexcommBaseAddrs[i])
  95. {
  96. return i;
  97. }
  98. }
  99. assert(false);
  100. return 0;
  101. }
  102. /* Changes FLEXCOMM mode */
  103. static status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock)
  104. {
  105. /* Check whether peripheral type is present */
  106. if (!FLEXCOMM_PeripheralIsPresent(base, periph))
  107. {
  108. return kStatus_OutOfRange;
  109. }
  110. /* Flexcomm is locked to different peripheral type than expected */
  111. if ((base->PSELID & FLEXCOMM_PSELID_LOCK_MASK) && ((base->PSELID & FLEXCOMM_PSELID_PERSEL_MASK) != periph))
  112. {
  113. return kStatus_Fail;
  114. }
  115. /* Check if we are asked to lock */
  116. if (lock)
  117. {
  118. base->PSELID = (uint32_t)periph | FLEXCOMM_PSELID_LOCK_MASK;
  119. }
  120. else
  121. {
  122. base->PSELID = (uint32_t)periph;
  123. }
  124. return kStatus_Success;
  125. }
  126. status_t FLEXCOMM_Init(void *base, FLEXCOMM_PERIPH_T periph)
  127. {
  128. int idx = FLEXCOMM_GetInstance(base);
  129. if (idx < 0)
  130. {
  131. return kStatus_InvalidArgument;
  132. }
  133. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  134. /* Enable the peripheral clock */
  135. CLOCK_EnableClock(s_flexcommClocks[idx]);
  136. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  137. /* Set the FLEXCOMM to given peripheral */
  138. return FLEXCOMM_SetPeriph((FLEXCOMM_Type *)base, periph, 0);
  139. }
  140. void FLEXCOMM_SetIRQHandler(void *base, flexcomm_irq_handler_t handler, void *handle)
  141. {
  142. uint32_t instance;
  143. /* Look up instance number */
  144. instance = FLEXCOMM_GetInstance(base);
  145. /* Clear handler first to avoid execution of the handler with wrong handle */
  146. s_flexcommIrqHandler[instance] = NULL;
  147. s_flexcommHandle[instance] = handle;
  148. s_flexcommIrqHandler[instance] = handler;
  149. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  150. exception return operation might vector to incorrect interrupt */
  151. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  152. __DSB();
  153. #endif
  154. }
  155. /* IRQ handler functions overloading weak symbols in the startup */
  156. #if defined(FLEXCOMM0)
  157. void FLEXCOMM0_DriverIRQHandler(void)
  158. {
  159. assert(s_flexcommIrqHandler[0]);
  160. s_flexcommIrqHandler[0]((void *)s_flexcommBaseAddrs[0], s_flexcommHandle[0]);
  161. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  162. exception return operation might vector to incorrect interrupt */
  163. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  164. __DSB();
  165. #endif
  166. }
  167. #endif
  168. #if defined(FLEXCOMM1)
  169. void FLEXCOMM1_DriverIRQHandler(void)
  170. {
  171. assert(s_flexcommIrqHandler[1]);
  172. s_flexcommIrqHandler[1]((void *)s_flexcommBaseAddrs[1], s_flexcommHandle[1]);
  173. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  174. exception return operation might vector to incorrect interrupt */
  175. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  176. __DSB();
  177. #endif
  178. }
  179. #endif
  180. #if defined(FLEXCOMM2)
  181. void FLEXCOMM2_DriverIRQHandler(void)
  182. {
  183. assert(s_flexcommIrqHandler[2]);
  184. s_flexcommIrqHandler[2]((void *)s_flexcommBaseAddrs[2], s_flexcommHandle[2]);
  185. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  186. exception return operation might vector to incorrect interrupt */
  187. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  188. __DSB();
  189. #endif
  190. }
  191. #endif
  192. #if defined(FLEXCOMM3)
  193. void FLEXCOMM3_DriverIRQHandler(void)
  194. {
  195. assert(s_flexcommIrqHandler[3]);
  196. s_flexcommIrqHandler[3]((void *)s_flexcommBaseAddrs[3], s_flexcommHandle[3]);
  197. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  198. exception return operation might vector to incorrect interrupt */
  199. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  200. __DSB();
  201. #endif
  202. }
  203. #endif
  204. #if defined(FLEXCOMM4)
  205. void FLEXCOMM4_DriverIRQHandler(void)
  206. {
  207. assert(s_flexcommIrqHandler[4]);
  208. s_flexcommIrqHandler[4]((void *)s_flexcommBaseAddrs[4], s_flexcommHandle[4]);
  209. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  210. exception return operation might vector to incorrect interrupt */
  211. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  212. __DSB();
  213. #endif
  214. }
  215. #endif
  216. #if defined(FLEXCOMM5)
  217. void FLEXCOMM5_DriverIRQHandler(void)
  218. {
  219. assert(s_flexcommIrqHandler[5]);
  220. s_flexcommIrqHandler[5]((void *)s_flexcommBaseAddrs[5], s_flexcommHandle[5]);
  221. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  222. exception return operation might vector to incorrect interrupt */
  223. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  224. __DSB();
  225. #endif
  226. }
  227. #endif
  228. #if defined(FLEXCOMM6)
  229. void FLEXCOMM6_DriverIRQHandler(void)
  230. {
  231. assert(s_flexcommIrqHandler[6]);
  232. s_flexcommIrqHandler[6]((void *)s_flexcommBaseAddrs[6], s_flexcommHandle[6]);
  233. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  234. exception return operation might vector to incorrect interrupt */
  235. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  236. __DSB();
  237. #endif
  238. }
  239. #endif
  240. #if defined(FLEXCOMM7)
  241. void FLEXCOMM7_DriverIRQHandler(void)
  242. {
  243. assert(s_flexcommIrqHandler[7]);
  244. s_flexcommIrqHandler[7]((void *)s_flexcommBaseAddrs[7], s_flexcommHandle[7]);
  245. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  246. exception return operation might vector to incorrect interrupt */
  247. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  248. __DSB();
  249. #endif
  250. }
  251. #endif
  252. #if defined(FLEXCOMM8)
  253. void FLEXCOMM8_DriverIRQHandler(void)
  254. {
  255. assert(s_flexcommIrqHandler[8]);
  256. s_flexcommIrqHandler[8]((void *)s_flexcommBaseAddrs[8], s_flexcommHandle[8]);
  257. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  258. exception return operation might vector to incorrect interrupt */
  259. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  260. __DSB();
  261. #endif
  262. }
  263. #endif
  264. #if defined(FLEXCOMM9)
  265. void FLEXCOMM9_DriverIRQHandler(void)
  266. {
  267. assert(s_flexcommIrqHandler[9]);
  268. s_flexcommIrqHandler[9]((void *)s_flexcommBaseAddrs[9], s_flexcommHandle[9]);
  269. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  270. exception return operation might vector to incorrect interrupt */
  271. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  272. __DSB();
  273. #endif
  274. }
  275. #endif