/* * Copyright (c) 2016, Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_msmc.h" #if defined(__riscv) #define CONFIG_NORMAL_SLEEP EVENT_UNIT->SLPCTRL = (EVENT_UNIT->SLPCTRL & ~0x03) | (1 << 0) #define CONFIG_DEEP_SLEEP EVENT_UNIT->SLPCTRL |= 0x03; #else #define CONFIG_NORMAL_SLEEP SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk #define CONFIG_DEEP_SLEEP SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk #endif status_t SMC_SetPowerModeRun(SMC_Type *base) { uint32_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; } status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint32_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; } status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ CONFIG_NORMAL_SLEEP; __DSB(); __WFI(); __ISB(); return kStatus_Success; } status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint32_t reg; /* configure the Partial Stop mode in Noraml Stop mode */ reg = base->PMCTRL; reg &= ~(SMC_PMCTRL_PSTOPO_MASK | SMC_PMCTRL_STOPM_MASK); reg |= ((uint32_t)option << SMC_PMCTRL_PSTOPO_SHIFT) | (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ CONFIG_DEEP_SLEEP; /* read back to make sure the configuration valid before entering stop mode */ (void)base->PMCTRL; __DSB(); __WFI(); __ISB(); #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) /* check whether the power mode enter Stop mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) { return kStatus_SMC_StopAbort; } else { return kStatus_Success; } #else return kStatus_Success; #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */ } status_t SMC_SetPowerModeVlpr(SMC_Type *base) { uint32_t reg; reg = base->PMCTRL; /* 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 */ /* Clear the SLEEPDEEP bit to disable deep sleep mode */ CONFIG_NORMAL_SLEEP; __DSB(); __WFI(); __ISB(); return kStatus_Success; } status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint32_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 */ CONFIG_DEEP_SLEEP; /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; __DSB(); __WFI(); __ISB(); #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) /* check whether the power mode enter Stop mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) { return kStatus_SMC_StopAbort; } else { return kStatus_Success; } #else return kStatus_Success; #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */ } status_t SMC_SetPowerModeLls(SMC_Type *base) { uint32_t reg; /* configure to LLS mode */ reg = base->PMCTRL; reg &= ~SMC_PMCTRL_STOPM_MASK; reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ CONFIG_DEEP_SLEEP; /* read back to make sure the configuration valid before entering stop mode */ (void)base->PMCTRL; __DSB(); __WFI(); __ISB(); #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) /* check whether the power mode enter Stop mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) { return kStatus_SMC_StopAbort; } else { return kStatus_Success; } #else return kStatus_Success; #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */ } #if (defined(FSL_FEATURE_SMC_HAS_SUB_STOP_MODE) && FSL_FEATURE_SMC_HAS_SUB_STOP_MODE) #if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE0) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE0) status_t SMC_SetPowerModeVlls0(SMC_Type *base) { uint32_t reg; /* configure to VLLS mode */ reg = base->PMCTRL; reg &= ~SMC_PMCTRL_STOPM_MASK; reg |= (kSMC_StopVlls0 << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ CONFIG_DEEP_SLEEP; /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; __DSB(); __WFI(); __ISB(); return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */ #if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE2) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE2) status_t SMC_SetPowerModeVlls2(SMC_Type *base) { uint32_t reg; /* configure to VLLS mode */ reg = base->PMCTRL; reg &= ~SMC_PMCTRL_STOPM_MASK; reg |= (kSMC_StopVlls2 << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ CONFIG_DEEP_SLEEP; /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; __DSB(); __WFI(); __ISB(); return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */ #else /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */ status_t SMC_SetPowerModeVlls(SMC_Type *base) { uint32_t reg; /* configure to VLLS mode */ reg = base->PMCTRL; reg &= ~SMC_PMCTRL_STOPM_MASK; reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; #if defined(__riscv) EVENT->SCR = (EVENT->SCR & ~0x03) | (1 << 1); #else /* Set the SLEEPDEEP bit to enable deep sleep mode */ CONFIG_DEEP_SLEEP; #endif /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; __DSB(); __WFI(); __ISB(); #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) /* check whether the power mode enter Stop mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) { return kStatus_SMC_StopAbort; } else { return kStatus_Success; } #else return kStatus_Success; #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */ } #endif /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */ void SMC_ConfigureResetPinFilter(SMC_Type *base, const smc_reset_pin_filter_config_t *config) { assert(config); uint32_t reg; reg = SMC_RPC_FILTCFG(config->slowClockFilterCount) | SMC_RPC_FILTEN(config->enableFilter); #if (defined(FSL_FEATURE_SMC_HAS_RPC_LPOFEN) && FSL_FEATURE_SMC_HAS_RPC_LPOFEN) if (config->enableLpoFilter) { reg |= SMC_RPC_LPOFEN_MASK; } #endif /* FSL_FEATURE_SMC_HAS_RPC_LPOFEN */ base->RPC = reg; }