Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:00

0001 /*
0002  * Copyright (c) 2015, Freescale Semiconductor, Inc.
0003  * Copyright 2016-2020 NXP
0004  * All rights reserved.
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_mu.h"
0010 
0011 /* Component ID definition, used by tools. */
0012 #ifndef FSL_COMPONENT_ID
0013 #define FSL_COMPONENT_ID "platform.drivers.mu"
0014 #endif
0015 
0016 /*******************************************************************************
0017  * Variables
0018  ******************************************************************************/
0019 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0020 /*! @brief Pointers to mu clocks for each instance. */
0021 static const clock_ip_name_t s_muClocks[] = MU_CLOCKS;
0022 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0023 /*! @brief Pointers to mu bases for each instance. */
0024 static MU_Type *const s_muBases[] = MU_BASE_PTRS;
0025 
0026 /******************************************************************************
0027  * Code
0028  *****************************************************************************/
0029 static uint32_t MU_GetInstance(MU_Type *base)
0030 {
0031     uint32_t instance;
0032 
0033     /* Find the instance index from base address mappings. */
0034     for (instance = 0U; instance < (sizeof(s_muBases) / sizeof(s_muBases[0])); instance++)
0035     {
0036         if (s_muBases[instance] == base)
0037         {
0038             break;
0039         }
0040     }
0041 
0042     assert(instance < (sizeof(s_muBases) / sizeof(s_muBases[0])));
0043 
0044     return instance;
0045 }
0046 
0047 /*!
0048  * brief Initializes the MU module.
0049  *
0050  * This function enables the MU clock only.
0051  *
0052  * param base MU peripheral base address.
0053  */
0054 void MU_Init(MU_Type *base)
0055 {
0056 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0057     (void)CLOCK_EnableClock(s_muClocks[MU_GetInstance(base)]);
0058 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0059 }
0060 
0061 /*!
0062  * brief De-initializes the MU module.
0063  *
0064  * This function disables the MU clock only.
0065  *
0066  * param base MU peripheral base address.
0067  */
0068 void MU_Deinit(MU_Type *base)
0069 {
0070 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0071     (void)CLOCK_DisableClock(s_muClocks[MU_GetInstance(base)]);
0072 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0073 }
0074 
0075 /*!
0076  * brief Blocks to send a message.
0077  *
0078  * This function waits until the TX register is empty and sends the message.
0079  *
0080  * param base MU peripheral base address.
0081  * param regIndex  TX register index.
0082  * param msg      Message to send.
0083  */
0084 void MU_SendMsg(MU_Type *base, uint32_t regIndex, uint32_t msg)
0085 {
0086     assert(regIndex < MU_TR_COUNT);
0087 
0088     /* Wait TX register to be empty. */
0089     while (0U == (base->SR & (((uint32_t)kMU_Tx0EmptyFlag) >> regIndex)))
0090     {
0091         ; /* Intentional empty while*/
0092     }
0093 
0094     base->TR[regIndex] = msg;
0095 }
0096 
0097 /*!
0098  * brief Blocks to receive a message.
0099  *
0100  * This function waits until the RX register is full and receives the message.
0101  *
0102  * param base MU peripheral base address.
0103  * param regIndex  RX register index.
0104  * return The received message.
0105  */
0106 uint32_t MU_ReceiveMsg(MU_Type *base, uint32_t regIndex)
0107 {
0108     assert(regIndex < MU_TR_COUNT);
0109 
0110     /* Wait RX register to be full. */
0111     while (0U == (base->SR & (((uint32_t)kMU_Rx0FullFlag) >> regIndex)))
0112     {
0113         ; /* Intentional empty while*/
0114     }
0115 
0116     return base->RR[regIndex];
0117 }
0118 
0119 /*!
0120  * brief Blocks setting the 3-bit MU flags reflect on the other MU side.
0121  *
0122  * This function blocks setting the 3-bit MU flags. Every time the 3-bit MU flags are changed,
0123  * the status flag \c kMU_FlagsUpdatingFlag asserts indicating the 3-bit MU flags are
0124  * updating to the other side. After the 3-bit MU flags are updated, the status flag
0125  * \c kMU_FlagsUpdatingFlag is cleared by hardware. During the flags updating period,
0126  * the flags cannot be changed. This function waits for the MU status flag
0127  * \c kMU_FlagsUpdatingFlag cleared and sets the 3-bit MU flags.
0128  *
0129  * param base MU peripheral base address.
0130  * param flags The 3-bit MU flags to set.
0131  */
0132 void MU_SetFlags(MU_Type *base, uint32_t flags)
0133 {
0134     /* Wait for update finished. */
0135     while (0U != (base->SR & ((uint32_t)MU_SR_FUP_MASK)))
0136     {
0137         ; /* Intentional empty while*/
0138     }
0139 
0140     MU_SetFlagsNonBlocking(base, flags);
0141 }
0142 
0143 /*!
0144  * brief Triggers interrupts to the other core.
0145  *
0146  * This function triggers the specific interrupts to the other core. The interrupts
0147  * to trigger are passed in as bit mask. See \ref _mu_interrupt_trigger.
0148  * The MU should not trigger an interrupt to the other core when the previous interrupt
0149  * has not been processed by the other core. This function checks whether the
0150  * previous interrupts have been processed. If not, it returns an error.
0151  *
0152  * code
0153  * if (kStatus_Success != MU_TriggerInterrupts(base, kMU_GenInt0InterruptTrigger | kMU_GenInt2InterruptTrigger))
0154  * {
0155  *     Previous general purpose interrupt 0 or general purpose interrupt 2
0156  *     has not been processed by the other core.
0157  * }
0158  * endcode
0159  *
0160  * param base MU peripheral base address.
0161  * param mask Bit mask of the interrupts to trigger. See _mu_interrupt_trigger.
0162  * retval kStatus_Success    Interrupts have been triggered successfully.
0163  * retval kStatus_Fail       Previous interrupts have not been accepted.
0164  */
0165 status_t MU_TriggerInterrupts(MU_Type *base, uint32_t mask)
0166 {
0167     status_t status = kStatus_Success;
0168     uint32_t reg    = base->CR;
0169 
0170     /* Previous interrupt has been accepted. */
0171     if (0U == (reg & mask))
0172     {
0173         /* All interrupts have been accepted, trigger now. */
0174         reg      = (reg & ~(MU_CR_GIRn_MASK | MU_CR_NMI_MASK)) | mask;
0175         base->CR = reg;
0176         status   = kStatus_Success;
0177     }
0178     else
0179     {
0180         status = kStatus_Fail;
0181     }
0182 
0183     return status;
0184 }
0185 
0186 #if !(defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
0187 /*!
0188  * brief Boots the core at B side.
0189  *
0190  * This function sets the B side core's boot configuration and releases the
0191  * core from reset.
0192  *
0193  * param base MU peripheral base address.
0194  * param mode Core B boot mode.
0195  * note Only MU side A can use this function.
0196  */
0197 void MU_BootCoreB(MU_Type *base, mu_core_boot_mode_t mode)
0198 {
0199 #if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
0200     /* Clean the reset de-assert pending flag. */
0201     base->SR = MU_SR_RDIP_MASK;
0202 #endif
0203 
0204 #if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
0205     uint32_t reg = base->CCR;
0206 
0207     reg = (reg & ~(MU_CCR_HR_MASK | MU_CCR_RSTH_MASK | MU_CCR_BOOT_MASK)) | MU_CCR_BOOT(mode);
0208 
0209     base->CCR = reg;
0210 #else
0211     uint32_t reg = base->CR;
0212 
0213     reg = (reg & ~((MU_CR_GIRn_MASK | MU_CR_NMI_MASK) | MU_CR_HR_MASK | MU_CR_RSTH_MASK | MU_CR_BBOOT_MASK)) |
0214           MU_CR_BBOOT(mode);
0215 
0216     base->CR = reg;
0217 #endif
0218 }
0219 
0220 /*!
0221  * brief Boots the other core.
0222  *
0223  * This function boots the other core with a boot configuration.
0224  *
0225  * param base MU peripheral base address.
0226  * param mode The other core boot mode.
0227  */
0228 void MU_BootOtherCore(MU_Type *base, mu_core_boot_mode_t mode)
0229 {
0230     /*
0231      * MU_BootOtherCore and MU_BootCoreB are the same, MU_BootCoreB is kept
0232      * for compatible with older platforms.
0233      */
0234     MU_BootCoreB(base, mode);
0235 }
0236 #endif /* FSL_FEATURE_MU_NO_RSTH */
0237 
0238 #if !(defined(FSL_FEATURE_MU_NO_HR) && FSL_FEATURE_MU_NO_HR)
0239 #if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
0240 /*!
0241  * brief Hardware reset the other core.
0242  *
0243  * This function resets the other core, the other core could mask the
0244  * hardware reset by calling ref MU_MaskHardwareReset. The hardware reset
0245  * mask feature is only available for some platforms.
0246  * This function could be used together with MU_BootOtherCore to control the
0247  * other core reset workflow.
0248  *
0249  * Example 1: Reset the other core, and no hold reset
0250  * code
0251  * MU_HardwareResetOtherCore(MU_A, true, false, bootMode);
0252  * endcode
0253  * In this example, the core at MU side B will reset with the specified boot mode.
0254  *
0255  * Example 2: Reset the other core and hold it, then boot the other core later.
0256  * code
0257  *    Here the other core enters reset, and the reset is hold
0258  * MU_HardwareResetOtherCore(MU_A, true, true, modeDontCare);
0259  *    Current core boot the other core when necessary.
0260  * MU_BootOtherCore(MU_A, bootMode);
0261  * endcode
0262  *
0263  * param base MU peripheral base address.
0264  * param waitReset Wait the other core enters reset.
0265  *                    - true: Wait until the other core enters reset, if the other
0266  *                      core has masked the hardware reset, then this function will
0267  *                      be blocked.
0268  *                    - false: Don't wait the reset.
0269  * param holdReset Hold the other core reset or not.
0270  *                    - true: Hold the other core in reset, this function returns
0271  *                      directly when the other core enters reset.
0272  *                    - false: Don't hold the other core in reset, this function
0273  *                      waits until the other core out of reset.
0274  * param bootMode Boot mode of the other core, if p holdReset is true, this
0275  *                 parameter is useless.
0276  */
0277 void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode)
0278 {
0279 #if (defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
0280     /* If MU does not support hold reset, then the parameter must be false. */
0281     assert(false == holdReset);
0282 #endif
0283     uint32_t ccr = base->CCR & ~(MU_CCR_HR_MASK | MU_CCR_RSTH_MASK | MU_CCR_BOOT_MASK);
0284 
0285     ccr |= MU_CCR_BOOT(bootMode);
0286 
0287     if (holdReset)
0288     {
0289         ccr |= MU_CCR_RSTH_MASK;
0290     }
0291 
0292     /* Clean the reset assert pending flag. */
0293     base->SR = (MU_SR_RAIP_MASK | MU_SR_RDIP_MASK);
0294 
0295     /* Set CCR[HR] to trigger hardware reset. */
0296     base->CCR = ccr | MU_CCR_HR_MASK;
0297 
0298     /* If wait the other core enters reset. */
0299     if (waitReset)
0300     {
0301         /* Wait for the other core go to reset. */
0302         while (0U == (base->SR & MU_SR_RAIP_MASK))
0303         {
0304             ; /* Intentional empty while*/
0305         }
0306 
0307         if (!holdReset)
0308         {
0309             /* Clear CCR[HR]. */
0310             base->CCR = ccr;
0311 
0312             /* Wait for the other core out of reset. */
0313             while (0U == (base->SR & MU_SR_RDIP_MASK))
0314             {
0315                 ; /* Intentional empty while*/
0316             }
0317         }
0318     }
0319 }
0320 #else /* FSL_FEATURE_MU_HAS_CCR */
0321 /*!
0322  * brief Hardware reset the other core.
0323  *
0324  * This function resets the other core, the other core could mask the
0325  * hardware reset by calling ref MU_MaskHardwareReset. The hardware reset
0326  * mask feature is only available for some platforms.
0327  * This function could be used together with MU_BootOtherCore to control the
0328  * other core reset workflow.
0329  *
0330  * Example 1: Reset the other core, and no hold reset
0331  * code
0332  * MU_HardwareResetOtherCore(MU_A, true, false, bootMode);
0333  * endcode
0334  * In this example, the core at MU side B will reset with the specified boot mode.
0335  *
0336  * Example 2: Reset the other core and hold it, then boot the other core later.
0337  * code
0338  *    Here the other core enters reset, and the reset is hold
0339  * MU_HardwareResetOtherCore(MU_A, true, true, modeDontCare);
0340  *    Current core boot the other core when necessary.
0341  * MU_BootOtherCore(MU_A, bootMode);
0342  * endcode
0343  *
0344  * param base MU peripheral base address.
0345  * param waitReset Wait the other core enters reset.
0346  *                    - true: Wait until the other core enters reset, if the other
0347  *                      core has masked the hardware reset, then this function will
0348  *                      be blocked.
0349  *                    - false: Don't wait the reset.
0350  * param holdReset Hold the other core reset or not.
0351  *                    - true: Hold the other core in reset, this function returns
0352  *                      directly when the other core enters reset.
0353  *                    - false: Don't hold the other core in reset, this function
0354  *                      waits until the other core out of reset.
0355  * param bootMode Boot mode of the other core, if p holdReset is true, this
0356  *                 parameter is useless.
0357  */
0358 void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode)
0359 {
0360 #if (defined(FSL_FEATURE_MU_NO_RSTH) && FSL_FEATURE_MU_NO_RSTH)
0361     /* If MU does not support hold reset, then the parameter must be false. */
0362     assert(false == holdReset);
0363 #endif
0364     uint32_t resetFlag = 0;
0365 
0366     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);
0367 
0368     cr |= MU_CR_BOOT(bootMode);
0369 
0370     if (holdReset)
0371     {
0372         cr |= MU_CR_RSTH_MASK;
0373     }
0374 
0375 #if (defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
0376     resetFlag |= MU_SR_RAIP_MASK;
0377 #endif
0378 #if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
0379     resetFlag |= MU_SR_RDIP_MASK;
0380 #endif
0381     /* Clean the reset assert pending flag. */
0382     base->SR = resetFlag;
0383 
0384     /* Set CR[HR] to trigger hardware reset. */
0385     base->CR = cr | MU_CR_HR_MASK;
0386 
0387     /* If wait the other core enters reset. */
0388     if (waitReset)
0389     {
0390 #if (defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
0391         /* Wait for the other core go to reset. */
0392         while (0U == (base->SR & MU_SR_RAIP_MASK))
0393         {
0394             ; /* Intentional empty while*/
0395         }
0396 #endif
0397 
0398         if (!holdReset)
0399         {
0400             /* Clear CR[HR]. */
0401             base->CR = cr;
0402 
0403 #if (defined(FSL_FEATURE_MU_HAS_RESET_DEASSERT_INT) && FSL_FEATURE_MU_HAS_RESET_ASSERT_INT)
0404             /* Wait for the other core out of reset. */
0405             while (0U == (base->SR & MU_SR_RDIP_MASK))
0406             {
0407                 ; /* Intentional empty while*/
0408             }
0409 #endif
0410         }
0411     }
0412 }
0413 #endif /* FSL_FEATURE_MU_HAS_CCR  */
0414 #endif /* FSL_FEATURE_MU_NO_HR */