fsl_mu.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2020 NXP
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_mu.h"
  9. /* Component ID definition, used by tools. */
  10. #ifndef FSL_COMPONENT_ID
  11. #define FSL_COMPONENT_ID "platform.drivers.mu"
  12. #endif
  13. /*******************************************************************************
  14. * Variables
  15. ******************************************************************************/
  16. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  17. /*! @brief Pointers to mu clocks for each instance. */
  18. static const clock_ip_name_t s_muClocks[] = MU_CLOCKS;
  19. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  20. /*! @brief Pointers to mu bases for each instance. */
  21. static MU_Type *const s_muBases[] = MU_BASE_PTRS;
  22. /******************************************************************************
  23. * Code
  24. *****************************************************************************/
  25. static uint32_t MU_GetInstance(MU_Type *base)
  26. {
  27. uint32_t instance;
  28. /* Find the instance index from base address mappings. */
  29. for (instance = 0U; instance < (sizeof(s_muBases) / sizeof(s_muBases[0])); instance++)
  30. {
  31. if (s_muBases[instance] == base)
  32. {
  33. break;
  34. }
  35. }
  36. assert(instance < (sizeof(s_muBases) / sizeof(s_muBases[0])));
  37. return instance;
  38. }
  39. /*!
  40. * brief Initializes the MU module.
  41. *
  42. * This function enables the MU clock only.
  43. *
  44. * param base MU peripheral base address.
  45. */
  46. void MU_Init(MU_Type *base)
  47. {
  48. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  49. (void)CLOCK_EnableClock(s_muClocks[MU_GetInstance(base)]);
  50. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  51. }
  52. /*!
  53. * brief De-initializes the MU module.
  54. *
  55. * This function disables the MU clock only.
  56. *
  57. * param base MU peripheral base address.
  58. */
  59. void MU_Deinit(MU_Type *base)
  60. {
  61. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  62. (void)CLOCK_DisableClock(s_muClocks[MU_GetInstance(base)]);
  63. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  64. }
  65. /*!
  66. * brief Blocks to send a message.
  67. *
  68. * This function waits until the TX register is empty and sends the message.
  69. *
  70. * param base MU peripheral base address.
  71. * param regIndex TX register index.
  72. * param msg Message to send.
  73. */
  74. void MU_SendMsg(MU_Type *base, uint32_t regIndex, uint32_t msg)
  75. {
  76. assert(regIndex < MU_TR_COUNT);
  77. /* Wait TX register to be empty. */
  78. while (0U == (base->SR & (((uint32_t)kMU_Tx0EmptyFlag) >> regIndex)))
  79. {
  80. ; /* Intentional empty while*/
  81. }
  82. base->TR[regIndex] = msg;
  83. }
  84. /*!
  85. * brief Blocks to receive a message.
  86. *
  87. * This function waits until the RX register is full and receives the message.
  88. *
  89. * param base MU peripheral base address.
  90. * param regIndex RX register index.
  91. * return The received message.
  92. */
  93. uint32_t MU_ReceiveMsg(MU_Type *base, uint32_t regIndex)
  94. {
  95. assert(regIndex < MU_TR_COUNT);
  96. /* Wait RX register to be full. */
  97. while (0U == (base->SR & (((uint32_t)kMU_Rx0FullFlag) >> regIndex)))
  98. {
  99. ; /* Intentional empty while*/
  100. }
  101. return base->RR[regIndex];
  102. }
  103. /*!
  104. * brief Blocks setting the 3-bit MU flags reflect on the other MU side.
  105. *
  106. * This function blocks setting the 3-bit MU flags. Every time the 3-bit MU flags are changed,
  107. * the status flag \c kMU_FlagsUpdatingFlag asserts indicating the 3-bit MU flags are
  108. * updating to the other side. After the 3-bit MU flags are updated, the status flag
  109. * \c kMU_FlagsUpdatingFlag is cleared by hardware. During the flags updating period,
  110. * the flags cannot be changed. This function waits for the MU status flag
  111. * \c kMU_FlagsUpdatingFlag cleared and sets the 3-bit MU flags.
  112. *
  113. * param base MU peripheral base address.
  114. * param flags The 3-bit MU flags to set.
  115. */
  116. void MU_SetFlags(MU_Type *base, uint32_t flags)
  117. {
  118. /* Wait for update finished. */
  119. while (0U != (base->SR & ((uint32_t)MU_SR_FUP_MASK)))
  120. {
  121. ; /* Intentional empty while*/
  122. }
  123. MU_SetFlagsNonBlocking(base, flags);
  124. }
  125. /*!
  126. * brief Triggers interrupts to the other core.
  127. *
  128. * This function triggers the specific interrupts to the other core. The interrupts
  129. * to trigger are passed in as bit mask. See \ref _mu_interrupt_trigger.
  130. * The MU should not trigger an interrupt to the other core when the previous interrupt
  131. * has not been processed by the other core. This function checks whether the
  132. * previous interrupts have been processed. If not, it returns an error.
  133. *
  134. * code
  135. * if (kStatus_Success != MU_TriggerInterrupts(base, kMU_GenInt0InterruptTrigger | kMU_GenInt2InterruptTrigger))
  136. * {
  137. * Previous general purpose interrupt 0 or general purpose interrupt 2
  138. * has not been processed by the other core.
  139. * }
  140. * endcode
  141. *
  142. * param base MU peripheral base address.
  143. * param mask Bit mask of the interrupts to trigger. See _mu_interrupt_trigger.
  144. * retval kStatus_Success Interrupts have been triggered successfully.
  145. * retval kStatus_Fail Previous interrupts have not been accepted.
  146. */
  147. status_t MU_TriggerInterrupts(MU_Type *base, uint32_t mask)
  148. {
  149. status_t status = kStatus_Success;
  150. uint32_t reg = base->CR;
  151. /* Previous interrupt has been accepted. */
  152. if (0U == (reg & mask))
  153. {
  154. /* All interrupts have been accepted, trigger now. */
  155. reg = (reg & ~(MU_CR_GIRn_MASK | MU_CR_NMI_MASK)) | mask;
  156. base->CR = reg;
  157. status = kStatus_Success;
  158. }
  159. else
  160. {
  161. status = kStatus_Fail;
  162. }
  163. return status;
  164. }
  165. #if !(defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
  166. /*!
  167. * brief Boots the core at B side.
  168. *
  169. * This function sets the B side core's boot configuration and releases the
  170. * core from reset.
  171. *
  172. * param base MU peripheral base address.
  173. * param mode Core B boot mode.
  174. * note Only MU side A can use this function.
  175. */
  176. void MU_BootCoreB(MU_Type *base, mu_core_boot_mode_t mode)
  177. {
  178. #if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
  179. /* Clean the reset de-assert pending flag. */
  180. base->SR = MU_SR_RDIP_MASK;
  181. #endif
  182. #if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
  183. uint32_t reg = base->CCR;
  184. reg = (reg & ~(MU_CCR_HR_MASK | MU_CCR_RSTH_MASK | MU_CCR_BOOT_MASK)) | MU_CCR_BOOT(mode);
  185. base->CCR = reg;
  186. #else
  187. uint32_t reg = base->CR;
  188. reg = (reg & ~((MU_CR_GIRn_MASK | MU_CR_NMI_MASK) | MU_CR_HR_MASK | MU_CR_RSTH_MASK | MU_CR_BBOOT_MASK)) |
  189. MU_CR_BBOOT(mode);
  190. base->CR = reg;
  191. #endif
  192. }
  193. /*!
  194. * brief Boots the other core.
  195. *
  196. * This function boots the other core with a boot configuration.
  197. *
  198. * param base MU peripheral base address.
  199. * param mode The other core boot mode.
  200. */
  201. void MU_BootOtherCore(MU_Type *base, mu_core_boot_mode_t mode)
  202. {
  203. /*
  204. * MU_BootOtherCore and MU_BootCoreB are the same, MU_BootCoreB is kept
  205. * for compatible with older platforms.
  206. */
  207. MU_BootCoreB(base, mode);
  208. }
  209. #endif /* FSL_FEATURE_MU_NO_RSTH */
  210. #if !(defined(FSL_FEATURE_MU_NO_HR) && FSL_FEATURE_MU_NO_HR)
  211. #if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
  212. /*!
  213. * brief Hardware reset the other core.
  214. *
  215. * This function resets the other core, the other core could mask the
  216. * hardware reset by calling ref MU_MaskHardwareReset. The hardware reset
  217. * mask feature is only available for some platforms.
  218. * This function could be used together with MU_BootOtherCore to control the
  219. * other core reset workflow.
  220. *
  221. * Example 1: Reset the other core, and no hold reset
  222. * code
  223. * MU_HardwareResetOtherCore(MU_A, true, false, bootMode);
  224. * endcode
  225. * In this example, the core at MU side B will reset with the specified boot mode.
  226. *
  227. * Example 2: Reset the other core and hold it, then boot the other core later.
  228. * code
  229. * Here the other core enters reset, and the reset is hold
  230. * MU_HardwareResetOtherCore(MU_A, true, true, modeDontCare);
  231. * Current core boot the other core when necessary.
  232. * MU_BootOtherCore(MU_A, bootMode);
  233. * endcode
  234. *
  235. * param base MU peripheral base address.
  236. * param waitReset Wait the other core enters reset.
  237. * - true: Wait until the other core enters reset, if the other
  238. * core has masked the hardware reset, then this function will
  239. * be blocked.
  240. * - false: Don't wait the reset.
  241. * param holdReset Hold the other core reset or not.
  242. * - true: Hold the other core in reset, this function returns
  243. * directly when the other core enters reset.
  244. * - false: Don't hold the other core in reset, this function
  245. * waits until the other core out of reset.
  246. * param bootMode Boot mode of the other core, if p holdReset is true, this
  247. * parameter is useless.
  248. */
  249. void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode)
  250. {
  251. #if (defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
  252. /* If MU does not support hold reset, then the parameter must be false. */
  253. assert(false == holdReset);
  254. #endif
  255. uint32_t ccr = base->CCR & ~(MU_CCR_HR_MASK | MU_CCR_RSTH_MASK | MU_CCR_BOOT_MASK);
  256. ccr |= MU_CCR_BOOT(bootMode);
  257. if (holdReset)
  258. {
  259. ccr |= MU_CCR_RSTH_MASK;
  260. }
  261. /* Clean the reset assert pending flag. */
  262. base->SR = (MU_SR_RAIP_MASK | MU_SR_RDIP_MASK);
  263. /* Set CCR[HR] to trigger hardware reset. */
  264. base->CCR = ccr | MU_CCR_HR_MASK;
  265. /* If wait the other core enters reset. */
  266. if (waitReset)
  267. {
  268. /* Wait for the other core go to reset. */
  269. while (0U == (base->SR & MU_SR_RAIP_MASK))
  270. {
  271. ; /* Intentional empty while*/
  272. }
  273. if (!holdReset)
  274. {
  275. /* Clear CCR[HR]. */
  276. base->CCR = ccr;
  277. /* Wait for the other core out of reset. */
  278. while (0U == (base->SR & MU_SR_RDIP_MASK))
  279. {
  280. ; /* Intentional empty while*/
  281. }
  282. }
  283. }
  284. }
  285. #else /* FSL_FEATURE_MU_HAS_CCR */
  286. /*!
  287. * brief Hardware reset the other core.
  288. *
  289. * This function resets the other core, the other core could mask the
  290. * hardware reset by calling ref MU_MaskHardwareReset. The hardware reset
  291. * mask feature is only available for some platforms.
  292. * This function could be used together with MU_BootOtherCore to control the
  293. * other core reset workflow.
  294. *
  295. * Example 1: Reset the other core, and no hold reset
  296. * code
  297. * MU_HardwareResetOtherCore(MU_A, true, false, bootMode);
  298. * endcode
  299. * In this example, the core at MU side B will reset with the specified boot mode.
  300. *
  301. * Example 2: Reset the other core and hold it, then boot the other core later.
  302. * code
  303. * Here the other core enters reset, and the reset is hold
  304. * MU_HardwareResetOtherCore(MU_A, true, true, modeDontCare);
  305. * Current core boot the other core when necessary.
  306. * MU_BootOtherCore(MU_A, bootMode);
  307. * endcode
  308. *
  309. * param base MU peripheral base address.
  310. * param waitReset Wait the other core enters reset.
  311. * - true: Wait until the other core enters reset, if the other
  312. * core has masked the hardware reset, then this function will
  313. * be blocked.
  314. * - false: Don't wait the reset.
  315. * param holdReset Hold the other core reset or not.
  316. * - true: Hold the other core in reset, this function returns
  317. * directly when the other core enters reset.
  318. * - false: Don't hold the other core in reset, this function
  319. * waits until the other core out of reset.
  320. * param bootMode Boot mode of the other core, if p holdReset is true, this
  321. * parameter is useless.
  322. */
  323. void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode)
  324. {
  325. #if (defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
  326. /* If MU does not support hold reset, then the parameter must be false. */
  327. assert(false == holdReset);
  328. #endif
  329. uint32_t resetFlag = 0;
  330. uint32_t cr = base->CR & ~(MU_CR_HR_MASK | MU_CR_RSTH_MASK | MU_CR_BOOT_MASK | MU_CR_GIRn_MASK | MU_CR_NMI_MASK);
  331. cr |= MU_CR_BOOT(bootMode);
  332. if (holdReset)
  333. {
  334. cr |= MU_CR_RSTH_MASK;
  335. }
  336. #if (defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
  337. resetFlag |= MU_SR_RAIP_MASK;
  338. #endif
  339. #if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
  340. resetFlag |= MU_SR_RDIP_MASK;
  341. #endif
  342. /* Clean the reset assert pending flag. */
  343. base->SR = resetFlag;
  344. /* Set CR[HR] to trigger hardware reset. */
  345. base->CR = cr | MU_CR_HR_MASK;
  346. /* If wait the other core enters reset. */
  347. if (waitReset)
  348. {
  349. #if (defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
  350. /* Wait for the other core go to reset. */
  351. while (0U == (base->SR & MU_SR_RAIP_MASK))
  352. {
  353. ; /* Intentional empty while*/
  354. }
  355. #endif
  356. if (!holdReset)
  357. {
  358. /* Clear CR[HR]. */
  359. base->CR = cr;
  360. #if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
  361. /* Wait for the other core out of reset. */
  362. while (0U == (base->SR & MU_SR_RDIP_MASK))
  363. {
  364. ; /* Intentional empty while*/
  365. }
  366. #endif
  367. }
  368. }
  369. }
  370. #endif /* FSL_FEATURE_MU_HAS_CCR */
  371. #endif /* FSL_FEATURE_MU_NO_HR */