MCUXpresso_MCXA153/devices/MCXA153/drivers/fsl_cmc.c
Yilin Sun 35e678394a
Initial commit v2.14.2
Signed-off-by: Yilin Sun <imi415@imi.moe>
2024-02-11 19:33:06 +08:00

294 lines
9.7 KiB
C

/*
* Copyright 2022 ~ 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_cmc.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.mcx_cmc"
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
#if (defined(FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG) && FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG)
#define CMC_SRAMDIS_RESERVED_MASK \
(~(kCMC_RAMX0 | kCMC_RAMX1 | kCMC_RAMX2 | kCMC_RAMB | kCMC_RAMC0 | kCMC_RAMC1 | kCMC_RAMD0 | kCMC_RAMD1 | \
kCMC_RAME0 | kCMC_RAME1 | kCMC_RAMF0 | kCMC_RAMF1 | kCMC_RAMG0_RAMG1 | kCMC_RAMG2_RAMG3 | kCMC_RAMH0_RAMH1 | \
kCMC_LPCAC | kCMC_DMA0_DMA1_PKC | kCMC_USB0 | kCMC_PQ | kCMC_CAN0_CAN1_ENET_USB1 | kCMC_FlexSPI))
#define CMC_SRAMRET_RESERVED_MASK (CMC_SRAMDIS_RESERVED_MASK)
#endif /* FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG */
/*******************************************************************************
* Variables
******************************************************************************/
static uint32_t g_savedPrimask;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* brief Sets clock mode.
*
* This function configs the amount of clock gating when the core asserts
* Sleeping due to WFI, WFE or SLEEPONEXIT.
*
* param base CMC peripheral base address.
* param mode System clock mode.
*/
void CMC_SetClockMode(CMC_Type *base, cmc_clock_mode_t mode)
{
uint32_t reg;
reg = base->CKCTRL;
reg &= ~CMC_CKCTRL_CKMODE_MASK;
reg |= CMC_CKCTRL_CKMODE((mode));
base->CKCTRL = reg;
}
/*!
* brief Configures all power mode protection settings.
*
* This function configures the power mode protection settings for
* supported power modes. This should be done before setting the lowPower mode
* for each power doamin.
*
* The allowed lowpower modes are passed as bit map. For example, to allow
* Sleep and DeepSleep, use CMC_SetPowerModeProtection(CMC_base, kCMC_AllowSleepMode|kCMC_AllowDeepSleepMode).
* To allow all low power modes, use CMC_SetPowerModeProtection(CMC_base, kCMC_AllowAllLowPowerModes).
*
* param base CMC peripheral base address.
* param allowedModes Bitmaps of the allowed power modes.
*/
void CMC_SetPowerModeProtection(CMC_Type *base, uint32_t allowedModes)
{
uint32_t reg;
reg = base->PMPROT;
reg &= ~0xFUL;
reg |= allowedModes;
base->PMPROT = reg;
}
/*!
* brief Configure reset pin.
*
* This function configures reset pin. When enabled, the low power filter is enabled in both
* Active and Low power modes, the reset filter is only enabled in Active mode. When both filers
* are enabled, they operate in series.
*
* param base CMC peripheral base address.
* param config Pointer to the reset pin config structure.
*/
void CMC_ConfigResetPin(CMC_Type *base, const cmc_reset_pin_config_t *config)
{
assert(config != NULL);
uint32_t reg = base->RPC;
if (config->lowpowerFilterEnable)
{
reg |= CMC_RPC_LPFEN_MASK;
}
else
{
reg &= ~CMC_RPC_LPFEN_MASK;
}
if (config->resetFilterEnable)
{
reg |= (CMC_RPC_FILTEN_MASK | CMC_RPC_FILTCFG(config->resetFilterWidth));
}
else
{
reg &= ~(CMC_RPC_FILTEN_MASK | CMC_RPC_FILTCFG_MASK);
}
base->RPC = reg;
}
#if (defined(FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG) && FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG)
/*!
* brief Power off the selected system SRAM always.
*
* This function powers off the selected system SRAM always. The SRAM arrays should
* not be accessed while they are shut down. SRAM array contents are not retained
* if they are powered off.
*
* param base CMC peripheral base address.
* param mask Bitmap of the SRAM arrays to be powered off all modes.
*/
void CMC_PowerOffSRAMAllMode(CMC_Type *base, uint32_t mask)
{
uint32_t reg = base->SRAMDIS[0];
reg &= ~(CMC_SRAMDIS_DIS_MASK | CMC_SRAMDIS_RESERVED_MASK);
reg |= CMC_SRAMDIS_DIS(mask);
base->SRAMDIS[0] = reg;
}
/*!
* brief Power off the selected system SRAm during low power mode only.
*
* This function powers off the selected system SRAM only during low power mode.
* SRAM array contents are not retained if they are power off.
*
* param base CMC peripheral base address.
* param mask Bitmap of the SRAM arrays to be power off during low power mode only.
*/
void CMC_PowerOffSRAMLowPowerOnly(CMC_Type *base, uint32_t mask)
{
uint32_t reg = base->SRAMRET[0];
reg &= ~(CMC_SRAMRET_RET_MASK | CMC_SRAMRET_RESERVED_MASK);
reg |= CMC_SRAMRET_RET(mask);
base->SRAMRET[0] = reg;
}
#endif /* FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG */
/*!
* brief Configs the low power mode of the on-chip flash memory.
*
* This function config the low power mode of the on-chip flash memory.
*
* param base CMC peripheral base address.
* param wake
* true - Flash will exit low power state during the flash memory accesses.
* false - No effect.
* param doze
* true - Flash is disabled while core is sleeping
* false - No effect.
* param disable
* true - Flash memory is placed in low power state.
* false - No effect.
*/
void CMC_ConfigFlashMode(CMC_Type *base, bool wake, bool doze, bool disable)
{
uint32_t reg = 0UL;
reg |= (disable ? CMC_FLASHCR_FLASHDIS(1U) : CMC_FLASHCR_FLASHDIS(0U)) |
(doze ? CMC_FLASHCR_FLASHDOZE(1U) : CMC_FLASHCR_FLASHDOZE(0U)) |
(wake ? CMC_FLASHCR_FLASHWAKE(1U) : CMC_FLASHCR_FLASHWAKE(0U));
base->FLASHCR = reg;
}
/*!
* brief Prepares to enter stop modes.
*
* This function should be called before entering low power modes.
*
*/
void CMC_PreEnterLowPowerMode(void)
{
g_savedPrimask = DisableGlobalIRQ();
__ISB();
}
/*!
* brief Recovers after wake up from stop modes.
*
* This function should be called after waking up from low power modes.
* This function should be used with CMC_PreEnterLowPowerMode()
*
*/
void CMC_PostExitLowPowerMode(void)
{
EnableGlobalIRQ(g_savedPrimask);
__ISB();
}
/*!
* brief Configs the entry into the same low power mode for each power domains.
*
* This function provides the feature to entry into the same low power mode for each power
* domains. Before invoking this function, please ensure the selected power mode have been allowed.
*
* param base CMC peripheral base address.
* param lowPowerMode The low power mode to be entered. See @ref cmc_low_power_mode_t for the details.
*
*/
void CMC_GlobalEnterLowPowerMode(CMC_Type *base, cmc_low_power_mode_t lowPowerMode)
{
/* Note: unlock the CKCTRL register if this API will be reinvoked later. */
CMC_SetClockMode(base, kCMC_GateAllSystemClocksEnterLowPowerMode);
CMC_SetGlobalPowerMode(base, lowPowerMode);
/* Before executing WFI instruction read back the last register to
* ensure all registers writes have completed. */
(void)base->GPMCTRL;
/* Set the core into DeepSleep mode. */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
__ISB();
}
/*!
* brief Configs the entry into different low power modes for each of the power domains.
*
* This function provides the feature to entry into different low power modes for
* each power domains. Before invoking this function please ensure the selected
* modes are allowed.
*
* param base CMC peripheral base address.
* param base config Pointer to the cmc_power_domain_config_t structure.
*/
void CMC_EnterLowPowerMode(CMC_Type *base, const cmc_power_domain_config_t *config)
{
assert(config != NULL);
#if (CMC_PMCTRL_COUNT > 1U)
/* The WAKE domain must never be configured to a lower power mode compared with main power mode. */
assert(config->wake_domain <= config->main_domain);
#endif /* (CMC_PMCTRL_COUNT > 1U) */
if (config->clock_mode < kCMC_GateAllSystemClocksEnterLowPowerMode)
{
/* In This case the power domain doesn't need to be placed in low power state. */
/* Note: unlock the register if this API will be reinvoked later. */
CMC_SetClockMode(base, config->clock_mode);
CMC_SetMAINPowerMode(base, kCMC_ActiveOrSleepMode);
#if (CMC_PMCTRL_COUNT > 1U)
CMC_SetWAKEPowerMode(base, kCMC_ActiveOrSleepMode);
#endif /* (CMC_PMCTRL_COUNT > 1U) */
/* Before executing WFI instruction read back the last register to
* ensure all registers writes have completed. */
(void)base->CKCTRL;
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
__ISB();
}
else
{
/* Note: unlock the register if this API will be reinvoked later. */
CMC_SetClockMode(base, kCMC_GateAllSystemClocksEnterLowPowerMode);
CMC_SetMAINPowerMode(base, config->main_domain);
#if (CMC_PMCTRL_COUNT > 1U)
CMC_SetWAKEPowerMode(base, config->wake_domain);
#endif /* (CMC_PMCTRL_COUNT > 1U) */
/* Before execute WFI instruction read back the last register to
* ensure all registers writes have completed. */
#if (CMC_PMCTRL_COUNT > 1U)
if ((CMC_GetWAKEPowerMode(base) == config->wake_domain) && (CMC_GetMAINPowerMode(base) == config->main_domain))
{
#endif /* (CMC_PMCTRL_COUNT > 1U) */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
__ISB();
#if (CMC_PMCTRL_COUNT > 1U)
}
#endif /* (CMC_PMCTRL_COUNT > 1U) */
}
}