summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imxrt/mcux-sdk/drivers/mu/fsl_mu.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/mu/fsl_mu.c414
1 files changed, 414 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/mu/fsl_mu.c b/bsps/arm/imxrt/mcux-sdk/drivers/mu/fsl_mu.c
new file mode 100644
index 0000000000..40b8dfd0f1
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/mu/fsl_mu.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_mu.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.mu"
+#endif
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+/*! @brief Pointers to mu clocks for each instance. */
+static const clock_ip_name_t s_muClocks[] = MU_CLOCKS;
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+/*! @brief Pointers to mu bases for each instance. */
+static MU_Type *const s_muBases[] = MU_BASE_PTRS;
+
+/******************************************************************************
+ * Code
+ *****************************************************************************/
+static uint32_t MU_GetInstance(MU_Type *base)
+{
+ uint32_t instance;
+
+ /* Find the instance index from base address mappings. */
+ for (instance = 0U; instance < (sizeof(s_muBases) / sizeof(s_muBases[0])); instance++)
+ {
+ if (s_muBases[instance] == base)
+ {
+ break;
+ }
+ }
+
+ assert(instance < (sizeof(s_muBases) / sizeof(s_muBases[0])));
+
+ return instance;
+}
+
+/*!
+ * brief Initializes the MU module.
+ *
+ * This function enables the MU clock only.
+ *
+ * param base MU peripheral base address.
+ */
+void MU_Init(MU_Type *base)
+{
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+ (void)CLOCK_EnableClock(s_muClocks[MU_GetInstance(base)]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+}
+
+/*!
+ * brief De-initializes the MU module.
+ *
+ * This function disables the MU clock only.
+ *
+ * param base MU peripheral base address.
+ */
+void MU_Deinit(MU_Type *base)
+{
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+ (void)CLOCK_DisableClock(s_muClocks[MU_GetInstance(base)]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+}
+
+/*!
+ * brief Blocks to send a message.
+ *
+ * This function waits until the TX register is empty and sends the message.
+ *
+ * param base MU peripheral base address.
+ * param regIndex TX register index.
+ * param msg Message to send.
+ */
+void MU_SendMsg(MU_Type *base, uint32_t regIndex, uint32_t msg)
+{
+ assert(regIndex < MU_TR_COUNT);
+
+ /* Wait TX register to be empty. */
+ while (0U == (base->SR & (((uint32_t)kMU_Tx0EmptyFlag) >> regIndex)))
+ {
+ ; /* Intentional empty while*/
+ }
+
+ base->TR[regIndex] = msg;
+}
+
+/*!
+ * brief Blocks to receive a message.
+ *
+ * This function waits until the RX register is full and receives the message.
+ *
+ * param base MU peripheral base address.
+ * param regIndex RX register index.
+ * return The received message.
+ */
+uint32_t MU_ReceiveMsg(MU_Type *base, uint32_t regIndex)
+{
+ assert(regIndex < MU_TR_COUNT);
+
+ /* Wait RX register to be full. */
+ while (0U == (base->SR & (((uint32_t)kMU_Rx0FullFlag) >> regIndex)))
+ {
+ ; /* Intentional empty while*/
+ }
+
+ return base->RR[regIndex];
+}
+
+/*!
+ * brief Blocks setting the 3-bit MU flags reflect on the other MU side.
+ *
+ * This function blocks setting the 3-bit MU flags. Every time the 3-bit MU flags are changed,
+ * the status flag \c kMU_FlagsUpdatingFlag asserts indicating the 3-bit MU flags are
+ * updating to the other side. After the 3-bit MU flags are updated, the status flag
+ * \c kMU_FlagsUpdatingFlag is cleared by hardware. During the flags updating period,
+ * the flags cannot be changed. This function waits for the MU status flag
+ * \c kMU_FlagsUpdatingFlag cleared and sets the 3-bit MU flags.
+ *
+ * param base MU peripheral base address.
+ * param flags The 3-bit MU flags to set.
+ */
+void MU_SetFlags(MU_Type *base, uint32_t flags)
+{
+ /* Wait for update finished. */
+ while (0U != (base->SR & ((uint32_t)MU_SR_FUP_MASK)))
+ {
+ ; /* Intentional empty while*/
+ }
+
+ MU_SetFlagsNonBlocking(base, flags);
+}
+
+/*!
+ * brief Triggers interrupts to the other core.
+ *
+ * This function triggers the specific interrupts to the other core. The interrupts
+ * to trigger are passed in as bit mask. See \ref _mu_interrupt_trigger.
+ * The MU should not trigger an interrupt to the other core when the previous interrupt
+ * has not been processed by the other core. This function checks whether the
+ * previous interrupts have been processed. If not, it returns an error.
+ *
+ * code
+ * if (kStatus_Success != MU_TriggerInterrupts(base, kMU_GenInt0InterruptTrigger | kMU_GenInt2InterruptTrigger))
+ * {
+ * Previous general purpose interrupt 0 or general purpose interrupt 2
+ * has not been processed by the other core.
+ * }
+ * endcode
+ *
+ * param base MU peripheral base address.
+ * param mask Bit mask of the interrupts to trigger. See _mu_interrupt_trigger.
+ * retval kStatus_Success Interrupts have been triggered successfully.
+ * retval kStatus_Fail Previous interrupts have not been accepted.
+ */
+status_t MU_TriggerInterrupts(MU_Type *base, uint32_t mask)
+{
+ status_t status = kStatus_Success;
+ uint32_t reg = base->CR;
+
+ /* Previous interrupt has been accepted. */
+ if (0U == (reg & mask))
+ {
+ /* All interrupts have been accepted, trigger now. */
+ reg = (reg & ~(MU_CR_GIRn_MASK | MU_CR_NMI_MASK)) | mask;
+ base->CR = reg;
+ status = kStatus_Success;
+ }
+ else
+ {
+ status = kStatus_Fail;
+ }
+
+ return status;
+}
+
+#if !(defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
+/*!
+ * brief Boots the core at B side.
+ *
+ * This function sets the B side core's boot configuration and releases the
+ * core from reset.
+ *
+ * param base MU peripheral base address.
+ * param mode Core B boot mode.
+ * note Only MU side A can use this function.
+ */
+void MU_BootCoreB(MU_Type *base, mu_core_boot_mode_t mode)
+{
+#if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
+ /* Clean the reset de-assert pending flag. */
+ base->SR = MU_SR_RDIP_MASK;
+#endif
+
+#if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
+ uint32_t reg = base->CCR;
+
+ reg = (reg & ~(MU_CCR_HR_MASK | MU_CCR_RSTH_MASK | MU_CCR_BOOT_MASK)) | MU_CCR_BOOT(mode);
+
+ base->CCR = reg;
+#else
+ uint32_t reg = base->CR;
+
+ reg = (reg & ~((MU_CR_GIRn_MASK | MU_CR_NMI_MASK) | MU_CR_HR_MASK | MU_CR_RSTH_MASK | MU_CR_BBOOT_MASK)) |
+ MU_CR_BBOOT(mode);
+
+ base->CR = reg;
+#endif
+}
+
+/*!
+ * brief Boots the other core.
+ *
+ * This function boots the other core with a boot configuration.
+ *
+ * param base MU peripheral base address.
+ * param mode The other core boot mode.
+ */
+void MU_BootOtherCore(MU_Type *base, mu_core_boot_mode_t mode)
+{
+ /*
+ * MU_BootOtherCore and MU_BootCoreB are the same, MU_BootCoreB is kept
+ * for compatible with older platforms.
+ */
+ MU_BootCoreB(base, mode);
+}
+#endif /* FSL_FEATURE_MU_NO_RSTH */
+
+#if !(defined(FSL_FEATURE_MU_NO_HR) && FSL_FEATURE_MU_NO_HR)
+#if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
+/*!
+ * brief Hardware reset the other core.
+ *
+ * This function resets the other core, the other core could mask the
+ * hardware reset by calling ref MU_MaskHardwareReset. The hardware reset
+ * mask feature is only available for some platforms.
+ * This function could be used together with MU_BootOtherCore to control the
+ * other core reset workflow.
+ *
+ * Example 1: Reset the other core, and no hold reset
+ * code
+ * MU_HardwareResetOtherCore(MU_A, true, false, bootMode);
+ * endcode
+ * In this example, the core at MU side B will reset with the specified boot mode.
+ *
+ * Example 2: Reset the other core and hold it, then boot the other core later.
+ * code
+ * Here the other core enters reset, and the reset is hold
+ * MU_HardwareResetOtherCore(MU_A, true, true, modeDontCare);
+ * Current core boot the other core when necessary.
+ * MU_BootOtherCore(MU_A, bootMode);
+ * endcode
+ *
+ * param base MU peripheral base address.
+ * param waitReset Wait the other core enters reset.
+ * - true: Wait until the other core enters reset, if the other
+ * core has masked the hardware reset, then this function will
+ * be blocked.
+ * - false: Don't wait the reset.
+ * param holdReset Hold the other core reset or not.
+ * - true: Hold the other core in reset, this function returns
+ * directly when the other core enters reset.
+ * - false: Don't hold the other core in reset, this function
+ * waits until the other core out of reset.
+ * param bootMode Boot mode of the other core, if p holdReset is true, this
+ * parameter is useless.
+ */
+void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode)
+{
+#if (defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
+ /* If MU does not support hold reset, then the parameter must be false. */
+ assert(false == holdReset);
+#endif
+ uint32_t ccr = base->CCR & ~(MU_CCR_HR_MASK | MU_CCR_RSTH_MASK | MU_CCR_BOOT_MASK);
+
+ ccr |= MU_CCR_BOOT(bootMode);
+
+ if (holdReset)
+ {
+ ccr |= MU_CCR_RSTH_MASK;
+ }
+
+ /* Clean the reset assert pending flag. */
+ base->SR = (MU_SR_RAIP_MASK | MU_SR_RDIP_MASK);
+
+ /* Set CCR[HR] to trigger hardware reset. */
+ base->CCR = ccr | MU_CCR_HR_MASK;
+
+ /* If wait the other core enters reset. */
+ if (waitReset)
+ {
+ /* Wait for the other core go to reset. */
+ while (0U == (base->SR & MU_SR_RAIP_MASK))
+ {
+ ; /* Intentional empty while*/
+ }
+
+ if (!holdReset)
+ {
+ /* Clear CCR[HR]. */
+ base->CCR = ccr;
+
+ /* Wait for the other core out of reset. */
+ while (0U == (base->SR & MU_SR_RDIP_MASK))
+ {
+ ; /* Intentional empty while*/
+ }
+ }
+ }
+}
+#else /* FSL_FEATURE_MU_HAS_CCR */
+/*!
+ * brief Hardware reset the other core.
+ *
+ * This function resets the other core, the other core could mask the
+ * hardware reset by calling ref MU_MaskHardwareReset. The hardware reset
+ * mask feature is only available for some platforms.
+ * This function could be used together with MU_BootOtherCore to control the
+ * other core reset workflow.
+ *
+ * Example 1: Reset the other core, and no hold reset
+ * code
+ * MU_HardwareResetOtherCore(MU_A, true, false, bootMode);
+ * endcode
+ * In this example, the core at MU side B will reset with the specified boot mode.
+ *
+ * Example 2: Reset the other core and hold it, then boot the other core later.
+ * code
+ * Here the other core enters reset, and the reset is hold
+ * MU_HardwareResetOtherCore(MU_A, true, true, modeDontCare);
+ * Current core boot the other core when necessary.
+ * MU_BootOtherCore(MU_A, bootMode);
+ * endcode
+ *
+ * param base MU peripheral base address.
+ * param waitReset Wait the other core enters reset.
+ * - true: Wait until the other core enters reset, if the other
+ * core has masked the hardware reset, then this function will
+ * be blocked.
+ * - false: Don't wait the reset.
+ * param holdReset Hold the other core reset or not.
+ * - true: Hold the other core in reset, this function returns
+ * directly when the other core enters reset.
+ * - false: Don't hold the other core in reset, this function
+ * waits until the other core out of reset.
+ * param bootMode Boot mode of the other core, if p holdReset is true, this
+ * parameter is useless.
+ */
+void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode)
+{
+#if (defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
+ /* If MU does not support hold reset, then the parameter must be false. */
+ assert(false == holdReset);
+#endif
+ uint32_t resetFlag = 0;
+
+ 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);
+
+ cr |= MU_CR_BOOT(bootMode);
+
+ if (holdReset)
+ {
+ cr |= MU_CR_RSTH_MASK;
+ }
+
+#if (defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
+ resetFlag |= MU_SR_RAIP_MASK;
+#endif
+#if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
+ resetFlag |= MU_SR_RDIP_MASK;
+#endif
+ /* Clean the reset assert pending flag. */
+ base->SR = resetFlag;
+
+ /* Set CR[HR] to trigger hardware reset. */
+ base->CR = cr | MU_CR_HR_MASK;
+
+ /* If wait the other core enters reset. */
+ if (waitReset)
+ {
+#if (defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
+ /* Wait for the other core go to reset. */
+ while (0U == (base->SR & MU_SR_RAIP_MASK))
+ {
+ ; /* Intentional empty while*/
+ }
+#endif
+
+ if (!holdReset)
+ {
+ /* Clear CR[HR]. */
+ base->CR = cr;
+
+#if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
+ /* Wait for the other core out of reset. */
+ while (0U == (base->SR & MU_SR_RDIP_MASK))
+ {
+ ; /* Intentional empty while*/
+ }
+#endif
+ }
+ }
+}
+#endif /* FSL_FEATURE_MU_HAS_CCR */
+#endif /* FSL_FEATURE_MU_NO_HR */