PeripheralDriver_Flagchip_F.../Src/module_driver_smc.c

998 lines
30 KiB
C

/**
* @file module_driver_smc.c
* @author Flagchip
* @brief SMC driver type definition and API
* @version 2.0.0
* @date 2024-08-20
*
* SDK Version: 2.6.0
*
* @copyright Copyright (c) 2020-2024 Flagchip Semiconductors Co., Ltd.
*
* @details
*/
/********************************************************************************
* Revision History:
*
* Version Date Initials CR# Descriptions
* --------- ---------- ------------ ---------- ---------------
* 0.1.0 2022-11-21 Flagchip032 N/A FC7300 First version
* 0.2.0 2023-02-13 Flagchip032 N/A optimize SMC driver code
* 2.0.0 2024-09-30 Flagchip055 N/A Update file structures
********************************************************************************/
#include "module_driver_smc.h"
#include "module_driver_scg.h"
#if SCG_PLLX_CLK1_SUPPORT
#include "module_driver_cpm.h"
#endif
#if SMC_INSTANCE_COUNT > 0U
#if SCG_PLLX_CLK1_SUPPORT
SMC_PllStatusType tSmc_PllStatusBeforeStopMode =
{
.bPll0Clk1GateOff = false,
#if SCG_PLL0_CLK2_SUPPORT
.bPll0Clk2GateOff = false,
#endif /* SCG_PLL0_CLK2_SUPPORT */
#if SCG_PLL1_SUPPORT
.bPll1Clk1GateOff = false,
#endif /* SCG_PLL1_SUPPORT */
};
static void SMC_EntryStopMode_PllxClk1_Clk2Status(void);
static void SMC_EntryStopMode_PLLClkOperation(void);
static void SMC_EntryStandbyMode_PllxClk1_Clk2Operation(void);
static void SMC_ExitStopMode_PllxOperation(void);
/**
* @brief Check PLLx_CLK1 enable status
*
* @param void
*
* @ note
* INdex PLL0/1_CLK1_CLK2 PLL0/1 Operation
* 0 Enable STEN N/A
* 1 Disable STEN N/A
* 2 Enable No STEN ShutOff
* 3 Disable No STEN N/A
*/
static void SMC_EntryStopMode_PllxClk1_Clk2Status(void)
{
uint32_t u32CoreId;
uint32_t u32Pll0CsrRegVal;
#if SCG_PLL1_SUPPORT
uint32_t u32Pll1CsrRegVal;
#endif /* SCG_PLL1_SUPPORT */
u32CoreId = Cpm_HWA_GetCoreId();
if(0U == u32CoreId)
{
u32Pll0CsrRegVal = SCG_HWA_GetPll0Csr();
#if SCG_PLL1_SUPPORT
u32Pll1CsrRegVal = SCG_HWA_GetPll1Csr();
#endif /* SCG_PLL1_SUPPORT */
if(SCG_PLL0CSR_CK1EN_MASK == (u32Pll0CsrRegVal & SCG_PLL0CSR_CK1EN_MASK))
{
if(SCG_PLL0CSR_STEN_MASK == (u32Pll0CsrRegVal & SCG_PLL0CSR_STEN_MASK))
{
/* PLL0_CLK1 enable and PLL0 STEN */
tSmc_PllStatusBeforeStopMode.bPll0Clk1GateOff = false;
}
else
{
/* PLL0_CLK1 enable and PLL0 no STEN */
tSmc_PllStatusBeforeStopMode.bPll0Clk1GateOff = true;
}
}
else
{
/* PLL0_CLK1 disable */
tSmc_PllStatusBeforeStopMode.bPll0Clk1GateOff = false;
}
#if SCG_PLL0_CLK2_SUPPORT
if(SCG_PLL0CSR_CK2EN_MASK == (u32Pll0CsrRegVal & SCG_PLL0CSR_CK2EN_MASK))
{
if(SCG_PLL0CSR_STEN_MASK == (u32Pll0CsrRegVal & SCG_PLL0CSR_STEN_MASK))
{
/* PLL0_CLK2 enable and PLL0 STEN */
tSmc_PllStatusBeforeStopMode.bPll0Clk2GateOff = false;
}
else
{
/* PLL0_CLK2 enable and PLL0 no STEN */
tSmc_PllStatusBeforeStopMode.bPll0Clk2GateOff = true;
}
}
else
{
/* PLL0_CLK2 disable */
tSmc_PllStatusBeforeStopMode.bPll0Clk2GateOff = false;
}
#endif /* SCG_PLL0_CLK2_SUPPORT */
#if SCG_PLL1_SUPPORT
if(SCG_PLL1CSR_CK1EN_MASK == (u32Pll1CsrRegVal & SCG_PLL1CSR_CK1EN_MASK))
{
if(SCG_PLL1CSR_STEN_MASK == (u32Pll1CsrRegVal & SCG_PLL1CSR_STEN_MASK))
{
/* PLL1_CLK1 enable and PLL1 STEN */
tSmc_PllStatusBeforeStopMode.bPll1Clk1GateOff = false;
}
else
{
/* PLL1_CLK1 enable and PLL1 no STEN */
tSmc_PllStatusBeforeStopMode.bPll1Clk1GateOff = true;
}
}
else
{
/* PLL1_CLK1 disable*/
tSmc_PllStatusBeforeStopMode.bPll1Clk1GateOff = false;
}
#endif /* SCG_PLL1_SUPPORT */
}
else
{
/* Not Core 0, do nothing */
}
}
/**
* @brief Set Pll Operation before stop mode
*
* @note Core 0 operate
*
*/
static void SMC_EntryStopMode_PLLClkOperation(void)
{
uint32_t u32CoreId;
u32CoreId = Cpm_HWA_GetCoreId();
if(0U == u32CoreId)
{
/* PLL0_CLK1 operation before entry stop mode */
if(true == tSmc_PllStatusBeforeStopMode.bPll0Clk1GateOff)
{
/* PLL0_CLK1 need to be gated off */
SCG_HWA_UnlockPllCsr(SCG_PLL0_CLOCK_SYMBOL);
SCG_HWA_DisablePLL0CLK1Output();
}
else
{
/* PLL0_CLK1 no need operation */
}
#if SCG_PLL0_CLK2_SUPPORT
/* PLL0_CLK2 operation before entry stop mode */
if(true == tSmc_PllStatusBeforeStopMode.bPll0Clk2GateOff)
{
/* PLL0_CLK1 need to be gated off */
SCG_HWA_UnlockPllCsr(SCG_PLL0_CLOCK_SYMBOL);
SCG_HWA_DisablePLL0CLK2Output();
}
else
{
/* PLL0_CLK2 no need operation */
}
#endif /* SCG_PLL0_CLK2_SUPPORT */
#if SCG_PLL1_SUPPORT
/* PLL1_CLK1 operation before entry stop mode */
if(true == tSmc_PllStatusBeforeStopMode.bPll1Clk1GateOff)
{
/* PLL1_CLK1 need to be gated off */
SCG_HWA_UnlockPllCsr(SCG_PLL1_CLOCK_SYMBOL);
SCG_HWA_DisablePLL1CLK1Output();
}
else
{
/* PLL1_CLK1 no need operation */
}
#endif /* SCG_PLL1_SUPPORT */
}
else
{
/* Not Core 0, do nothing */
}
}
/**
* @brief Restore PLL0_CLK1, PLL0_CLK2 and PLL1_CLK1 configuration when exit stop mode
*
* @note Core 0 operate
*
*/
static void SMC_ExitStopMode_PllxOperation(void)
{
uint32_t u32CoreId;
uint32_t u32TempVal;
uint32_t u32ScgCsrRegVal;
uint32_t u32Pll0CsrRegVal;
#if SCG_PLL1_SUPPORT
uint32_t u32Pll1CsrRegVal;
#endif /* SCG_PLL1_SUPPORT */
SCG_ClockCtrlType tSysClkCfg;
SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS;
SCG_FircType tFircCfg =
{
.bLock = false,
.bCm = false,
.bTrEn = false,
.bSten = false,
.u8TrimSrc = 0U,
.eDivL = SCG_ASYNCCLOCKDIV_BY4,
.eDivM = SCG_ASYNCCLOCKDIV_BY2,
.eDivH = SCG_ASYNCCLOCKDIV_BY1
};
u32CoreId = Cpm_HWA_GetCoreId();
if(0U == u32CoreId)
{
/* PLL0 Operation */
if( (true == tSmc_PllStatusBeforeStopMode.bPll0Clk1GateOff)
#if SCG_PLL0_CLK2_SUPPORT
|| (true == tSmc_PllStatusBeforeStopMode.bPll0Clk2GateOff)
#endif /* SCG_PLL0_CLK2_SUPPORT */
)
{
/* Record SCG CSR register value. */
u32ScgCsrRegVal = SCG_HWA_GetCSR();
if( (uint8_t)SCG_CLOCK_SRC_PLL0 == SCG_HWA_GetSysClkSrc())
{
/* System clock is PLL0, change to FIRC first. */
eStatusVal = SCG_SwitchSystemClock(SCG_CLOCK_SRC_FIRC);
if (SCG_STATUS_SEQUENCE_ERROR == eStatusVal)
{
eStatusVal = SCG_EnableFIRC(&tFircCfg);
if (SCG_STATUS_TIMEOUT != eStatusVal)
{
eStatusVal = SCG_SwitchSystemClock(SCG_CLOCK_SRC_FIRC);
}
}
else
{
/* do nothing */
}
}
else
{
/* System clock is not PLL0, no change. */
}
if (SCG_STATUS_SUCCESS == eStatusVal)
{
u32Pll0CsrRegVal = SCG_HWA_GetPll0Csr();
/* Turn off PLL0, because re-enable PLL0_CLK1 and PLL0_CLK2 need keep PLL0 EN is 0 */
/* PLL0_CLK1 and PLL0_CLK2 has been turn off before entry stop mode */
SCG_HWA_UnlockPllCsr(SCG_PLL0_CLOCK_SYMBOL);
SCG_HWA_SetPllCsr(SCG_PLL0_CLOCK_SYMBOL, SCG_PLL0CSR_ERR_MASK);
SCG_HWA_EnablePll0ForceOff();
u32TempVal = CLOCK_OFF_STABILIZATION_TIMEOUT;
while ((true == SCG_HWA_GetClockValid(SCG_PLL0_CLOCK_SYMBOL)) && (u32TempVal > 0U))
{
u32TempVal--;
}
if (0U == u32TempVal)
{
eStatusVal = SCG_STATUS_TIMEOUT;
}
else
{
/* Re-enable PLL0_CLK1 or PLL0_CLK2 */
u32TempVal = SCG_PLL0CSR_EN_MASK |
#if SCG_PLL0_CLK2_SUPPORT
SCG_PLL0CSR_CK2EN(tSmc_PllStatusBeforeStopMode.bPll0Clk2GateOff)|
#endif /* SCG_PLL0_CLK2_SUPPORT */
SCG_PLL0CSR_CK1EN(tSmc_PllStatusBeforeStopMode.bPll0Clk1GateOff);
SCG_HWA_SetPllCsr(SCG_PLL0_CLOCK_SYMBOL, u32TempVal);
/* Wait PLL0 locked */
u32TempVal = PLL_STABILIZATION_TIMEOUT;
while ((false == SCG_HWA_GetPllLocked(SCG_PLL0_CLOCK_SYMBOL)) && (u32TempVal > 0U))
{
u32TempVal--;
}
if(0U == u32TempVal)
{
eStatusVal = SCG_STATUS_TIMEOUT;
}
else
{
if (SCG_PLL0CSR_CM_MASK == (u32Pll0CsrRegVal & SCG_PLL0CSR_CM_MASK))
{
SCG_HWA_EnablePllClockMonitor(SCG_PLL0_CLOCK_SYMBOL);
}
else
{
/* Do nothing */
}
if (SCG_PLL0CSR_CMRE_MASK == (u32Pll0CsrRegVal & SCG_PLL0CSR_CMRE_MASK))
{
SCG_HWA_EnablePllClockMonitorReset(SCG_PLL0_CLOCK_SYMBOL);
}
else
{
/* Do nothing */
}
if(SCG_PLL0CSR_LK_MASK == (u32Pll0CsrRegVal & SCG_PLL0CSR_LK_MASK))
{
SCG_HWA_LockPllCsr(SCG_PLL0_CLOCK_SYMBOL);
}
else
{
/* Keep unlock */
}
if((uint8_t)SCG_CLOCK_SRC_PLL0 == (uint8_t)((u32ScgCsrRegVal & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT))
{
/* SCG CSR has been changed, means system clock is PLL0 and has changed to FIRC
* restore system clock configuration
*/
tSysClkCfg.bSysClkMonitor = true;
tSysClkCfg.eDivCore = (SCG_ClockDivType)(uint8_t)((u32ScgCsrRegVal & SCG_CCR_DIVCORE_MASK)>>SCG_CCR_DIVCORE_SHIFT);
tSysClkCfg.eDivBus = (SCG_ClockDivType)(uint8_t)((u32ScgCsrRegVal & SCG_CCR_DIVBUS_MASK)>>SCG_CCR_DIVBUS_SHIFT);
tSysClkCfg.eDivSlow = (SCG_ClockDivType)(uint8_t)((u32ScgCsrRegVal & SCG_CCR_DIVSLOW_MASK)>>SCG_CCR_DIVSLOW_SHIFT);
tSysClkCfg.eSrc = (SCG_ClockSrcType)(uint8_t)((u32ScgCsrRegVal & SCG_CCR_SCS_MASK)>>SCG_CCR_SCS_SHIFT);
(void)SCG_SetClkCtrl(&tSysClkCfg);
}
else
{
/* SCG CSR has not been changed */
}
}
}
}
else
{
/* System clock switch failed. */
}
}
else
{
/* do nothing */
}
#if SCG_PLL1_SUPPORT
/* PLL1 Operation */
if(true == tSmc_PllStatusBeforeStopMode.bPll1Clk1GateOff)
{
u32Pll1CsrRegVal = SCG_HWA_GetPll1Csr();
/* Must turn Off PLL1, before Restore PLL1_CLK1 */
SCG_HWA_UnlockPllCsr(SCG_PLL1_CLOCK_SYMBOL);
SCG_HWA_SetPllCsr(SCG_PLL1_CLOCK_SYMBOL, SCG_PLL1CSR_ERR_MASK);
SCG_HWA_EnablePll1ForceOff();
u32TempVal = CLOCK_OFF_STABILIZATION_TIMEOUT;
while ((true == SCG_HWA_GetClockValid(SCG_PLL1_CLOCK_SYMBOL)) && (u32TempVal > 0U))
{
u32TempVal--;
}
if (0U == u32TempVal)
{
eStatusVal = SCG_STATUS_TIMEOUT;
}
else
{
/* Restore PLL1_CLK1 */
u32TempVal = SCG_PLL1CSR_EN_MASK | SCG_PLL1CSR_CK1EN_MASK;
SCG_HWA_SetPllCsr(SCG_PLL1_CLOCK_SYMBOL, u32TempVal);
/* Wait PLL1 locked */
u32TempVal = PLL_STABILIZATION_TIMEOUT;
while ((false == SCG_HWA_GetPllLocked(SCG_PLL1_CLOCK_SYMBOL)) && (u32TempVal > 0U))
{
u32TempVal--;
}
if(0U == u32TempVal)
{
/* disable PLL0 failed */
eStatusVal = SCG_STATUS_TIMEOUT;
}
else
{
if (SCG_PLL1CSR_CM_MASK == (u32Pll1CsrRegVal & SCG_PLL1CSR_CM_MASK))
{
SCG_HWA_EnablePllClockMonitor(SCG_PLL1_CLOCK_SYMBOL);
}
else
{
/* Do nothing */
}
if (SCG_PLL1CSR_CMRE_MASK == (u32Pll1CsrRegVal & SCG_PLL1CSR_CMRE_MASK))
{
SCG_HWA_EnablePllClockMonitorReset(SCG_PLL1_CLOCK_SYMBOL);
}
else
{
/* Do nothing */
}
if(SCG_PLL1CSR_LK_MASK == (u32Pll1CsrRegVal & SCG_PLL1CSR_LK_MASK))
{
SCG_HWA_LockPllCsr(SCG_PLL1_CLOCK_SYMBOL);
}
else
{
/* Keep unlock */
}
}
}
}
else
{
/* do nothing */
}
#endif /* SCG_PLL1_SUPPORT */
}
else
{
/* Not Core 0, do nothing */
}
}
/**
* @brief Set PllxClk1Operation before standby mode
*
*/
static void SMC_EntryStandbyMode_PllxClk1_Clk2Operation(void)
{
uint32_t u32CoreId;
u32CoreId = Cpm_HWA_GetCoreId();
if(0U == u32CoreId)
{
/* Disable PLL0_CLK1 */
SCG_HWA_UnlockPllCsr(SCG_PLL0_CLOCK_SYMBOL);
SCG_HWA_DisablePLL0CLK1Output();
#if SCG_PLL0_CLK2_SUPPORT
SCG_HWA_DisablePLL0CLK2Output();
#endif /* SCG_PLL0_CLK2_SUPPORT */
#if SCG_PLL1_SUPPORT
/* Disable PLL1_CLK1 */
SCG_HWA_UnlockPllCsr(SCG_PLL1_CLOCK_SYMBOL);
SCG_HWA_DisablePLL1CLK1Output();
#endif /* SCG_PLL1_SUPPORT */
}
else
{
/* Core 0 gate off */
}
}
#endif /* SCG_PLLX_CLK1_SUPPORT */
/**
* @brief Set system mode
*
* @param eMode MCU low power mode
*
*/
void SMC_SetSystemMode(const SMC_ModeType eMode)
{
switch (eMode)
{
case SMC_MODE_RUN:
/* Clear the SLEEPDEEP bit to disable deep sleep mode */
CM7_HWA_DisableDeepSleep();
break;
case SMC_MODE_STOP:
/* switch smc mode to stop mode */
SMC_HWA_SetStopModeCtrl(SMC_STOP_MODE);
/* Set the SLEEPDEEP bit to enable deep sleep mode (STOP)*/
CM7_HWA_EnableDeepSleep();
#if SCG_PLLX_CLK1_SUPPORT
SMC_EntryStopMode_PllxClk1_Clk2Status();
SMC_EntryStopMode_PLLClkOperation();
#endif
/* Cpu is going into deep sleep state */
STANDBY();
#if SCG_PLLX_CLK1_SUPPORT
SMC_ExitStopMode_PllxOperation();
#endif
break;
case SMC_MODE_WAIT:
/* Clear the SLEEPDEEP bit to disable deep sleep mode */
CM7_HWA_DisableDeepSleep();
/* Cpu is going into sleep state */
STANDBY();
break;
case SMC_MODE_STANBY_0:
/* select standby mode*/
SMC_HWA_SetStandbyMode(SMC_CFG_STANDBY_0);
/* switch smc mode to standby mode */
SMC_HWA_SetStopModeCtrl(SMC_STANDBY_MODE);
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CM7_HWA_EnableDeepSleep();
#if SCG_PLLX_CLK1_SUPPORT
SMC_EntryStandbyMode_PllxClk1_Clk2Operation();
#endif
/* Cpu is going into deep sleep state */
STANDBY();
break;
case SMC_MODE_STANBY_1:
/* select standby mode*/
SMC_HWA_SetStandbyMode(SMC_CFG_STANDBY_1);
/* switch smc mode to standby mode */
SMC_HWA_SetStopModeCtrl(SMC_STANDBY_MODE);
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CM7_HWA_EnableDeepSleep();
#if SCG_PLLX_CLK1_SUPPORT
SMC_EntryStandbyMode_PllxClk1_Clk2Operation();
#endif
/* Cpu is going into deep sleep state */
STANDBY();
break;
case SMC_MODE_STANBY_2:
/* select standby mode*/
SMC_HWA_SetStandbyMode(SMC_CFG_STANDBY_2);
/* switch smc mode to standby mode */
SMC_HWA_SetStopModeCtrl(SMC_STANDBY_MODE);
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CM7_HWA_EnableDeepSleep();
#if SCG_PLLX_CLK1_SUPPORT
SMC_EntryStandbyMode_PllxClk1_Clk2Operation();
#endif
/* Cpu is going into deep sleep state */
STANDBY();
break;
case SMC_MODE_STANBY_3:
/* select standby mode*/
SMC_HWA_SetStandbyMode(SMC_CFG_STANDBY_3);
/* switch smc mode to standby mode */
SMC_HWA_SetStopModeCtrl(SMC_STANDBY_MODE);
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CM7_HWA_EnableDeepSleep();
#if SCG_PLLX_CLK1_SUPPORT
SMC_EntryStandbyMode_PllxClk1_Clk2Operation();
#endif
/* Cpu is going into deep sleep state */
STANDBY();
break;
default:
/* do nothing */
break;
}
}
#if SMC_CLOCKCONFIG_SUPPORT
/**
* @brief set always on clock source configuration include AON32K, RTC, AONCLK clock.
*
* @param pAonclkSrcType pointer to AONCLKSR instance for AON clock source configuration
* @param bLockStatus to lock current register
*
* @return Set clock out operation success/failed
*/
SMC_StatusType SMC_SetAonClkSrc(const SMC_AONCLKSRType *const pAonclkSrcType, bool bLockStatus)
{
SMC_StatusType eRetVal = SMC_STATUS_PARAM_INVALID;
#if SMC_DEV_ERROR_REPORT == STD_ON
if (pAonclkSrcType == NULL)
{
SMC_ReportDevError(SMC_SET_AONCLKSRC_ID, SMC_E_PARAM_POINTER);
}
else
{
#endif
/* Check SMC_AONCLKSR register lock status */
if (0U == SMC_HWA_GetAONCLKSRLOCK())
{
/* Gating SIRC_32K clock*/
if ((SMC_AON32K_SIRCDIV_32K_CLK == pAonclkSrcType->eAon32KSel) ||
(SMC_AON_SIRCDIV_32K_CLK == pAonclkSrcType->eAonSel) ||
(SMC_RTC_SIRCDIV_32K_CLK == pAonclkSrcType->eRtcSel))
{
SMC_HWA_SetSIRCDIV32KEN(1U);
}
else
{
/* No deal with */
}
/* Gating SIRC32_1K clock*/
if (SMC_AON_SIRC32_1K_CLK == pAonclkSrcType->eAonSel)
{
SMC_HWA_SetAON1KCLKEN(1U);
}
else
{
/* No deal with */
}
/* Set AONCLOCK configuration */
SMC_HWA_SetAON32kClkSrc(pAonclkSrcType->eAon32KSel);
SMC_HWA_SetRTCClkSrc(pAonclkSrcType->eRtcSel);
SMC_HWA_SetAONClkSrc(pAonclkSrcType->eAonSel);
if (true == bLockStatus)
{
/* Lock SMC_AONCLKSR register */
SMC_HWA_SetAONCLKSRLOCK(1U);
}
eRetVal = SMC_STATUS_SUCCESS;
}
else
{
/* No deal with */
}
#if SMC_DEV_ERROR_REPORT == STD_ON
}
#endif
return eRetVal;
}
/**
* @brief Report the clock source status and frequency configured in MCU run time.
* The clock frequency and status would change by clock set function.
*
* @param eClkkName: the SMC clock source to query
* @param pFreq: frequency variable point to get the frequency value
* @return true or false. This indicate the clock source status invalid or request clock source out of
* range.
*/
SMC_StatusType SMC_GetSMCClockFreq(const SMC_ClkSrcType eClkkName, uint32_t *const pFreq)
{
SMC_StatusType eRetVal = SMC_STATUS_PARAM_INVALID;
uint32_t u32TempVal;
#if SMC_DEV_ERROR_REPORT == STD_ON
if (pFreq == NULL)
{
SMC_ReportDevError(SMC_GET_CLOCK_FREQ_ID, SMC_E_PARAM_POINTER);
}
else if (eClkkName > SMC_END_OF_CLOCKS)
{
SMC_ReportDevError(SMC_GET_CLOCK_FREQ_ID, SMC_E_PARAM_OUT_RANGE);
}
else
{
#endif
u32TempVal = SMC_HWA_Get_AONCLKSR();
if (SMC_AON_CLK == eClkkName)
{
SMC_AONClkSrcType eClockkRet = (SMC_AONClkSrcType)(uint8_t)((u32TempVal & SMC_AONCLKSR_AONCLKSEL_MASK) >> SMC_AONCLKSR_AONCLKSEL_SHIFT);
if (SMC_AON_SIRCDIV_128K_CLK == eClockkRet)
{
*pFreq = SMC_AONCLK_128K;
}
else if (SMC_AON_SIRC32_1K_CLK == eClockkRet)
{
*pFreq = SMC_AONCLK_1K;
}
else
{
*pFreq = SMC_AONCLK_32K;
}
eRetVal = SMC_STATUS_SUCCESS;
}
else if (SMC_AON32K_CLK == eClkkName)
{
SMC_AON32KClkSrcType eClockkRet = (SMC_AON32KClkSrcType)(uint8_t)((u32TempVal & SMC_AONCLKSR_AON32KCLKSEL_MASK) >> SMC_AONCLKSR_AON32KCLKSEL_SHIFT);
if (SMC_AON32K_SOSC32K_CLK == eClockkRet)
{
*pFreq = SMC_AONCLK_SOSC_32K;
}
else
{
*pFreq = SMC_AONCLK_32K;
}
eRetVal = SMC_STATUS_SUCCESS;
}
else if (SMC_RTC_CLK == eClkkName)
{
SMC_RTCClkSrcType eClockkRet = (SMC_RTCClkSrcType)(uint8_t)((u32TempVal & SMC_AONCLKSR_RTCCLKSEL_MASK) >> SMC_AONCLKSR_RTCCLKSEL_SHIFT);
if (SMC_RTC_FOSCDIVL_CLK == eClockkRet)
{
*pFreq = SCG_GetScgClockFreq(SCG_FOSCDIVL_CLK);
}
else if (SMC_RTC_SOSC_CLK == eClockkRet)
{
*pFreq = SMC_AONCLK_SOSC_32K;
}
else
{
*pFreq = SMC_AONCLK_32K;
}
eRetVal = SMC_STATUS_SUCCESS;
}
else
{
/* Clock out or error parameter do not get frequency */
*pFreq = 0U;
}
#if SMC_DEV_ERROR_REPORT == STD_ON
}
#endif
return eRetVal;
}
/**
* @brief Configure the low power wakeup PAD output in SMC_LP_WAKEUP register
*
* @param SMC_LPWakeUpPadType the low power wakeup PAD source and polarity configuration
*/
void SMC_SetLPWakeUpPad(const SMC_LPWakeUpPadType* pLPWakeUpPad)
{
uint8_t u8Index;
uint32_t u32RegVal;
/* Unlock SMC important registers */
SMC_HWA_SetPmportReg(0U);
/* Get IO lock status */
u32RegVal = SMC_HWA_GetIolockReg();
for(u8Index=0U; u8Index < LP_WAKEUP_PAD_NUM; u8Index++)
{
SMC_HWA_SetLPWakeUpPadSrc(pLPWakeUpPad[u8Index].u8LPWakeUpPadNum, (uint8_t)(pLPWakeUpPad[u8Index].eLpWakeUpPadSel));
SMC_HWA_SetLPWakeUpPadPol(pLPWakeUpPad[u8Index].u8LPWakeUpPadNum, (uint8_t)(pLPWakeUpPad[u8Index].eLpWakeUpPadPolSel));
if (SMC_LPWAKEUP_PAD_DISABLE != (pLPWakeUpPad[u8Index].eLpWakeUpPadSel) )
{
/* Default enable iolock when wakeup pad is enabled */
u32RegVal |= ( 1U <<(SMC_IOLOCK_IOLOCK_CTRL0_SHIFT - (pLPWakeUpPad[u8Index].u8LPWakeUpPadNum)) );
}
else
{
/* Disable iolock when wakeuppad is disabled */
u32RegVal &= ~( 1U <<(SMC_IOLOCK_IOLOCK_CTRL0_SHIFT - (pLPWakeUpPad[u8Index].u8LPWakeUpPadNum)) );
}
}
/* Set IO lock status */
SMC_HWA_SetIolockReg(u32RegVal);
}
/**
* @brief Configure SMC mixed used control
*
* @param SMC_MixedUsedType SMC mixed used control
*/
void SMC_SetMixedUsedConfiguration(const SMC_MixedUsedType* pMixedUsedConfig)
{
#if SMC_LP_GOOD_SUPPORT
uint32_t u32Temp = 0U;
/* Unlock SMC important registers */
SMC_HWA_SetPmportReg(0U);
/* Set SRAM2 block retention control */
SMC_HWA_SetRETEN((uint16_t)(pMixedUsedConfig->eRamRetenSel));
/* PG Contrl */
if ((boolean)TRUE == pMixedUsedConfig->tPGCtrlConifg.bEnable)
{
u32Temp |= (uint32_t)( SMC_PGCTRL_PG_EN_MASK | SMC_PGCTRL_PG_LOCK_EN_MASK |
SMC_PGCTRL_PG_LOCK_SEL(pMixedUsedConfig->tPGCtrlConifg.ePGLockSel) |
SMC_PGCTRL_PG_POL(pMixedUsedConfig->tPGCtrlConifg.ePGActivePol)
);
}
else
{
/* Disable PG control */
u32Temp = 0U;
/* Set standby exit postpone count through PCUCtrl when LP_GOOD is not used. */
SMC_HWA_SetRPM_EXIT_CNT(pMixedUsedConfig->tPGCtrlConifg.u16RpmExitCnt);
}
SMC_HWA_SetPgctrlReg(u32Temp);
#else
/* Unlock SMC important registers */
SMC_HWA_SetPmportReg(0U);
/* Set standby exit postpone count through PCUCtrl when LP_GOOD is not used. */
SMC_HWA_SetRPM_EXIT_CNT(pMixedUsedConfig->tPGCtrlConifg.u16RpmExitCnt);
#endif
}
/**
* @brief set clock out. with clock out pin configure, the clock would be monitored.
* This Function may combined with SCG_ClkOut setting
* need to call SCG_SetClkOut,if clock out source set to SCG_CLKOUT. *
* @param pSmcClkOut to SmcClkOut instance for clock out configuration
* @param bLockStatus to lock current register
*
* @return Set clock out operation success/failed
* @note configuration sequence:
* 1. Disable CLKOUTEN
* 2. Set CLKOUTSEL
* 3. Enable CLKOUTEN
*/
SMC_StatusType SMC_SetClockOut(const SMC_ClkoutType *const pSmcClkOut, bool bLockStatus)
{
SMC_StatusType eRetVal = SMC_STATUS_PARAM_INVALID;
#if SMC_DEV_ERROR_REPORT == STD_ON
if (pSmcClkOut == NULL)
{
SMC_ReportDevError(SMC_SET_CLOCK_OUT_ID, SMC_E_PARAM_POINTER);
}
else
{
#endif
/* Check SMC_CLKOUT_CTRL register lock status */
if (0U == SMC_HWA_CLKOUT_CTRL_GetLockStatus())
{
/* Disable CLKOUTEN */
SMC_HWA_DisableClockOut();
/* Set CLKOUTDIV */
SMC_HWA_SetClkOutDiv(pSmcClkOut->eDivider);
/* Set CLKOUTSEL */
SMC_HWA_SetClkOutSel(pSmcClkOut->eClkOutSrc);
/* Enable CLKOUTEN */
SMC_HWA_EnableClockOut();
if (true == bLockStatus)
{
/* Lock SMC_CLKOUT_CTRL register */
SMC_HWA_LockCLKOUT_CTRL();
}
else
{
/* No deal with */
}
eRetVal = SMC_STATUS_SUCCESS;
}
else
{
/* No deal with */
}
#if SMC_DEV_ERROR_REPORT == STD_ON
}
#endif
return eRetVal;
}
#if SMC_SCG_WAKEUP_CONFIG_SUPPORT
/**
* @brief Set scg wakup configuration.
*
* @param SMC_SCGWakeUpConfigType SCG wakeup configuration
*
*/
void SMC_SetSCGWakeUpConfiguration(const SMC_SCGWakeUpConfigType *const pSCGWakeUpConfig)
{
uint32_t u32RegVal = 0U;
u32RegVal = SMC_SCG_WAKEUP_SCG_WAKEUP_CFG(pSCGWakeUpConfig->eWakeUpSource) |
SMC_SCG_WAKEUP_SCG_POL(pSCGWakeUpConfig->eWakeUpPolarity) |
SMC_SCG_WAKEUP_SCG_TRGSEL(pSCGWakeUpConfig->eSircTriggerToAdc) |
SMC_SCG_WAKEUP_LOCK(pSCGWakeUpConfig->eRegLockSel);
SMC_HWA_SetSCG_WAKEUP_REG(u32RegVal);
}
#endif
#if SMC_TSTMP0CLOCK_CONFIG_SUPPORT
/**
* @brief Set tstmp0 clock configuration.
*
* @param SMC_Tmtmp0ClkConfigType Tstmp0 clock configuration
*
* @note configuration sequence:
* 1. Disable EN and wait for 4 clock cycles
* 2. Set div and sel
* 3. Enable EN and wait for 4 clock cycles
* if set lock bit, this register can be restored by POR
*/
void SMC_SetTstmp0ClockConfiguration(const SMC_Tmtmp0ClkConfigType *const pTstmp0ClkConfig)
{
uint32_t u32RegVal = 0U;
uint32_t u32WaitCycles;
uint32_t i;
/* Get clock source to determine wait cycle */
u32RegVal = (SMC_HWA_GetTstmp0_CLk_CfgReg() & SMC_TSTMP0_CLK_CFG_SEL_MASK)>>SMC_TSTMP0_CLK_CFG_SEL_SHIFT;
if( (uint32)SMC_TSTMP0_CLK_SRC_SIRCDIV_1M == u32RegVal )
{
u32WaitCycles = SMC_TSTMP0_DUMMY_CYCLES_1M;
}
else if ( (uint32)SMC_TSTMP0_CLK_SRC_FOSC_DIVL == u32RegVal )
{
u32WaitCycles = SMC_TSTMP0_DUMMY_CYCLES_250K;
}
else
{
u32WaitCycles = SMC_TSTMP0_DUMMY_CYCLES_32K;
}
SMC_HWA_DisableTstmp0Clk();
for(i=0U; i<u32WaitCycles; i++)
{
__asm volatile("nop");
}
u32RegVal = (uint32_t)( SMC_TSTMP0_CLK_CFG_DIV(pTstmp0ClkConfig->eClkDiv) |
SMC_TSTMP0_CLK_CFG_SEL(pTstmp0ClkConfig->eClkSrc) );
SMC_HWA_SetTstmp0_CLk_CfgReg(u32RegVal);
SMC_HWA_EnableTstmp0Clk();
/* Recalculate u32WaitCycles because clock source may be changed */
if( SMC_TSTMP0_CLK_SRC_SIRCDIV_1M == pTstmp0ClkConfig->eClkSrc )
{
u32WaitCycles = SMC_TSTMP0_DUMMY_CYCLES_1M;
}
else if ( SMC_TSTMP0_CLK_SRC_FOSC_DIVL == pTstmp0ClkConfig->eClkSrc )
{
u32WaitCycles = SMC_TSTMP0_DUMMY_CYCLES_250K;
}
else
{
u32WaitCycles = SMC_TSTMP0_DUMMY_CYCLES_32K;
}
for(i=0U; i<u32WaitCycles; i++)
{
__asm volatile("nop");
}
}
#endif /* #if SMC_TSTMP0CLOCK_CONFIG_SUPPORT */
#endif /* #if SMC_CLOCKCONFIG_SUPPORT */
#endif /* #if SMC_INSTANCE_COUNT > 0U */