401 lines
12 KiB
C
401 lines
12 KiB
C
|
/*
|
||
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||
|
* Copyright 2016-2017 NXP
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||
|
* are permitted provided that the following conditions are met:
|
||
|
*
|
||
|
* o Redistributions of source code must retain the above copyright notice, this list
|
||
|
* of conditions and the following disclaimer.
|
||
|
*
|
||
|
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||
|
* other materials provided with the distribution.
|
||
|
*
|
||
|
* o Neither the name of the copyright holder nor the names of its
|
||
|
* contributors may be used to endorse or promote products derived from this
|
||
|
* software without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#include "fsl_smc.h"
|
||
|
#include "fsl_flash.h"
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM)
|
||
|
void SMC_GetParam(SMC_Type *base, smc_param_t *param)
|
||
|
{
|
||
|
uint32_t reg = base->PARAM;
|
||
|
param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK);
|
||
|
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||
|
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||
|
param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK);
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_PARAM */
|
||
|
|
||
|
void SMC_PreEnterStopModes(void)
|
||
|
{
|
||
|
flash_prefetch_speculation_status_t speculationStatus =
|
||
|
{
|
||
|
kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/
|
||
|
kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/
|
||
|
};
|
||
|
|
||
|
__disable_irq();
|
||
|
__ISB();
|
||
|
|
||
|
/*
|
||
|
* Before enter stop modes, the flash cache prefetch should be disabled.
|
||
|
* Otherwise the prefetch might be interrupted by stop, then the data and
|
||
|
* and instruction from flash are wrong.
|
||
|
*/
|
||
|
FLASH_PflashSetPrefetchSpeculation(&speculationStatus);
|
||
|
}
|
||
|
|
||
|
void SMC_PostExitStopModes(void)
|
||
|
{
|
||
|
flash_prefetch_speculation_status_t speculationStatus =
|
||
|
{
|
||
|
kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/
|
||
|
kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/
|
||
|
};
|
||
|
|
||
|
FLASH_PflashSetPrefetchSpeculation(&speculationStatus);
|
||
|
|
||
|
__enable_irq();
|
||
|
__ISB();
|
||
|
}
|
||
|
|
||
|
status_t SMC_SetPowerModeRun(SMC_Type *base)
|
||
|
{
|
||
|
uint8_t reg;
|
||
|
|
||
|
reg = base->PMCTRL;
|
||
|
/* configure Normal RUN mode */
|
||
|
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||
|
reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||
|
base->PMCTRL = reg;
|
||
|
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||
|
status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
||
|
{
|
||
|
uint8_t reg;
|
||
|
|
||
|
reg = base->PMCTRL;
|
||
|
/* configure High Speed RUN mode */
|
||
|
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||
|
reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||
|
base->PMCTRL = reg;
|
||
|
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||
|
|
||
|
status_t SMC_SetPowerModeWait(SMC_Type *base)
|
||
|
{
|
||
|
/* configure Normal Wait mode */
|
||
|
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||
|
__DSB();
|
||
|
__WFI();
|
||
|
__ISB();
|
||
|
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
|
||
|
status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
||
|
{
|
||
|
uint8_t reg;
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO)
|
||
|
/* configure the Partial Stop mode in Noraml Stop mode */
|
||
|
reg = base->STOPCTRL;
|
||
|
reg &= ~SMC_STOPCTRL_PSTOPO_MASK;
|
||
|
reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||
|
base->STOPCTRL = reg;
|
||
|
#endif
|
||
|
|
||
|
/* configure Normal Stop mode */
|
||
|
reg = base->PMCTRL;
|
||
|
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||
|
reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||
|
base->PMCTRL = reg;
|
||
|
|
||
|
/* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
|
||
|
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||
|
|
||
|
/* read back to make sure the configuration valid before enter stop mode */
|
||
|
(void)base->PMCTRL;
|
||
|
__DSB();
|
||
|
__WFI();
|
||
|
__ISB();
|
||
|
|
||
|
/* check whether the power mode enter Stop mode succeed */
|
||
|
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||
|
{
|
||
|
return kStatus_SMC_StopAbort;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
|
||
|
,
|
||
|
bool wakeupMode
|
||
|
#endif
|
||
|
)
|
||
|
{
|
||
|
uint8_t reg;
|
||
|
|
||
|
reg = base->PMCTRL;
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
|
||
|
/* configure whether the system remains in VLP mode on an interrupt */
|
||
|
if (wakeupMode)
|
||
|
{
|
||
|
/* exits to RUN mode on an interrupt */
|
||
|
reg |= SMC_PMCTRL_LPWUI_MASK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* remains in VLP mode on an interrupt */
|
||
|
reg &= ~SMC_PMCTRL_LPWUI_MASK;
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_LPWUI */
|
||
|
|
||
|
/* configure VLPR mode */
|
||
|
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||
|
reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||
|
base->PMCTRL = reg;
|
||
|
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
|
||
|
status_t SMC_SetPowerModeVlpw(SMC_Type *base)
|
||
|
{
|
||
|
/* configure VLPW mode */
|
||
|
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||
|
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||
|
__DSB();
|
||
|
__WFI();
|
||
|
__ISB();
|
||
|
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
|
||
|
status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
||
|
{
|
||
|
uint8_t reg;
|
||
|
|
||
|
/* configure VLPS mode */
|
||
|
reg = base->PMCTRL;
|
||
|
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||
|
reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||
|
base->PMCTRL = reg;
|
||
|
|
||
|
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||
|
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||
|
|
||
|
/* read back to make sure the configuration valid before enter stop mode */
|
||
|
(void)base->PMCTRL;
|
||
|
__DSB();
|
||
|
__WFI();
|
||
|
__ISB();
|
||
|
|
||
|
/* check whether the power mode enter VLPS mode succeed */
|
||
|
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||
|
{
|
||
|
return kStatus_SMC_StopAbort;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||
|
status_t SMC_SetPowerModeLls(SMC_Type *base
|
||
|
#if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||
|
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
|
||
|
,
|
||
|
const smc_power_mode_lls_config_t *config
|
||
|
#endif
|
||
|
)
|
||
|
{
|
||
|
uint8_t reg;
|
||
|
|
||
|
/* configure to LLS mode */
|
||
|
reg = base->PMCTRL;
|
||
|
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||
|
reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||
|
base->PMCTRL = reg;
|
||
|
|
||
|
/* configure LLS sub-mode*/
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||
|
reg = base->STOPCTRL;
|
||
|
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||
|
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||
|
base->STOPCTRL = reg;
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)
|
||
|
if (config->enableLpoClock)
|
||
|
{
|
||
|
base->STOPCTRL &= ~SMC_STOPCTRL_LPOPO_MASK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
base->STOPCTRL |= SMC_STOPCTRL_LPOPO_MASK;
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_LPOPO */
|
||
|
|
||
|
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||
|
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||
|
|
||
|
/* read back to make sure the configuration valid before enter stop mode */
|
||
|
(void)base->PMCTRL;
|
||
|
__DSB();
|
||
|
__WFI();
|
||
|
__ISB();
|
||
|
|
||
|
/* check whether the power mode enter LLS mode succeed */
|
||
|
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||
|
{
|
||
|
return kStatus_SMC_StopAbort;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||
|
status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config)
|
||
|
{
|
||
|
uint8_t reg;
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_PORPO) && FSL_FEATURE_SMC_HAS_PORPO)
|
||
|
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) || \
|
||
|
(defined(FSL_FEATURE_SMC_USE_STOPCTRL_VLLSM) && FSL_FEATURE_SMC_USE_STOPCTRL_VLLSM) || \
|
||
|
(defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||
|
if (config->subMode == kSMC_StopSub0)
|
||
|
#endif
|
||
|
{
|
||
|
/* configure whether the Por Detect work in Vlls0 mode */
|
||
|
if (config->enablePorDetectInVlls0)
|
||
|
{
|
||
|
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||
|
base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK;
|
||
|
#else
|
||
|
base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK;
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||
|
base->VLLSCTRL |= SMC_VLLSCTRL_PORPO_MASK;
|
||
|
#else
|
||
|
base->STOPCTRL |= SMC_STOPCTRL_PORPO_MASK;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_PORPO */
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION) && FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION)
|
||
|
else if (config->subMode == kSMC_StopSub2)
|
||
|
{
|
||
|
/* configure whether the Por Detect work in Vlls0 mode */
|
||
|
if (config->enableRam2InVlls2)
|
||
|
{
|
||
|
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||
|
base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK;
|
||
|
#else
|
||
|
base->STOPCTRL |= SMC_STOPCTRL_RAM2PO_MASK;
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||
|
base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK;
|
||
|
#else
|
||
|
base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */
|
||
|
|
||
|
/* configure to VLLS mode */
|
||
|
reg = base->PMCTRL;
|
||
|
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||
|
reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||
|
base->PMCTRL = reg;
|
||
|
|
||
|
/* configure the VLLS sub-mode */
|
||
|
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||
|
reg = base->VLLSCTRL;
|
||
|
reg &= ~SMC_VLLSCTRL_VLLSM_MASK;
|
||
|
reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||
|
base->VLLSCTRL = reg;
|
||
|
#else
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||
|
reg = base->STOPCTRL;
|
||
|
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||
|
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||
|
base->STOPCTRL = reg;
|
||
|
#else
|
||
|
reg = base->STOPCTRL;
|
||
|
reg &= ~SMC_STOPCTRL_VLLSM_MASK;
|
||
|
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||
|
base->STOPCTRL = reg;
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||
|
#endif
|
||
|
|
||
|
#if (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)
|
||
|
if (config->enableLpoClock)
|
||
|
{
|
||
|
base->STOPCTRL &= ~SMC_STOPCTRL_LPOPO_MASK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
base->STOPCTRL |= SMC_STOPCTRL_LPOPO_MASK;
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_LPOPO */
|
||
|
|
||
|
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||
|
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||
|
|
||
|
/* read back to make sure the configuration valid before enter stop mode */
|
||
|
(void)base->PMCTRL;
|
||
|
__DSB();
|
||
|
__WFI();
|
||
|
__ISB();
|
||
|
|
||
|
/* check whether the power mode enter LLS mode succeed */
|
||
|
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||
|
{
|
||
|
return kStatus_SMC_StopAbort;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return kStatus_Success;
|
||
|
}
|
||
|
}
|
||
|
#endif /* FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE */
|