123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- /*
- * 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 */
|