/**
 *******************************************************************************
 * @file    tmpm311_cg.c
 * @brief   This file provides API functions for CG driver 
 * @version V2.0.2.2
 * @date    2014/10/14
 * 
 * DO NOT USE THIS SOFTWARE WITHOUT THE SOFTWARE LICENSE AGREEMENT.
 * 
 * (C)Copyright TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2017 All rights reserved
 *******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "tmpm311_cg.h"

#if defined(__TMPM311_CG_H)
/** @addtogroup TX03_Periph_Driver
  * @{
  */

/** @defgroup CG
  * @brief CG driver modules
  * @{
  */

/** @defgroup CG_Private_Defines
  * @{
  */

#define CG_CLKCR_GEAR_CLEAR                  ((uint32_t)0xFFFFFFF8)
#define CG_CLKCR_GEAR_SET                    ((uint32_t)0x00000007)
#define CG_CLKCR_FPSEL_CLEAR                 ((uint32_t)0xFFFFFFBF)
#define CG_CLKCR_FPSEL_SET                   ((uint32_t)0x00000040)
#define CG_CLKCR_STICK_CLEAR                 ((uint32_t)0xFFFFFF7F)
#define CG_CLKCR_STICK_SET                   ((uint32_t)0x00000080)
#define CG_CLKCR_PRCK_CLEAR                  ((uint32_t)0x000000C7)
#define CG_CLKCR_PRCK_SET                    ((uint32_t)0x00000038)

#define CG_PROTECT_SET                       ((uint32_t)0x000000C1)
#define CG_PROTECT_CLEAR                     ((uint32_t)0x0000003E)

#define CG_CR_ST_SET                         ((uint32_t)0x00000030)
#define CG_CR_ST_RISING                      ((uint32_t)0x00000010)
#define CG_CR_ST_FALLING                     ((uint32_t)0x00000020)
#define CG_CR_ST_BOTH_EDGES                  ((uint32_t)0x00000030)

#define FC_GEAR_1_1                          ((uint32_t)0x00000000)
#define FC_GEAR_1_2                          ((uint32_t)0x00000001)
#define FC_GEAR_1_4                          ((uint32_t)0x00000002)
#define FC_GEAR_1_8                          ((uint32_t)0x00000003)
#define FC_GEAR_1_16                         ((uint32_t)0x00000004)

#define CG_OSCSEL_IHOSC                      ((uint32_t)0x00000000)
#define CG_OSCSEL_FOSC                       ((uint32_t)0x00000001)

#define CG_OSCSTF_IHOSC                      ((uint32_t)0x00000000)
#define CG_OSCSTF_FOSC                       ((uint32_t)0x00000001)

#define INT_RESETF_RSTF_CLEAR                ((uint32_t)0x00000000)

#define CG_WUHCR_WUPT_WUCLK_CLEAR            ((uint32_t)0xF000FEFF)
#define CG_WUHCR_WUCLK_SET                   ((uint32_t)0x00000100)
#define CG_WUHCR_WUON_SET                    ((uint32_t)0x00000001)
#define CG_WUHCR_WUEF_SET                    ((uint32_t)0x00000002)

#define CG_OSCEN_EHOSCEN_CLEAR               ((uint32_t)0xFFFFFFF9)
#define CG_OSCEN_EHOSCEN_SET                 ((uint32_t)0x00000006)
#define CG_OSCEN_EHOSC_SET                   ((uint32_t)0x00000002)
#define CG_OSCEN_EHCLKIN_SET                 ((uint32_t)0x00000004)
#define CG_OSCEN_IHOSCEN_SET                 ((uint32_t)0x00000001)
#define CG_OSCEN_IHOSCEN_CLEAR               ((uint32_t)0xFFFFFFFE)

static CG_DivideLevel numToDivideLevel_table[CG_DIVIDE_MAX] = {
    CG_DIVIDE_1,
    CG_DIVIDE_2,
    CG_DIVIDE_4,
    CG_DIVIDE_8,
    CG_DIVIDE_16,
    CG_DIVIDE_32,
    CG_DIVIDE_64,
    CG_DIVIDE_128,
    CG_DIVIDE_256,
    CG_DIVIDE_512,
    CG_DIVIDE_UNKNOWN
};

static CG_PhiT0Src numPhiT0Src_table[CG_PHIT0_SRC_MAX] = {
    CG_PHIT0_SRC_FGEAR,
    CG_PHIT0_SRC_FC
};

static CG_SysTickSrc numSysTickSrc_table[CG_STICK_SRC_MAX] = {
    CG_STICK_SRC_IHOSC,
    CG_STICK_SRC_FOSC
};

static volatile uint32_t *const CG_CRn[2U] = {
    &TSB_INT0->CR0, &TSB_INT0->CR1
};

/** @} */
/* End of group CG_Private_Defines */

/** @defgroup CG_Private_FunctionPrototypes
  * @{
  */

/** @} */
/* End of group CG_Private_FunctionPrototypes */

/** @defgroup CG_Private_Functions
  * @{
  */

/** @} */
/* End of group CG_Private_Functions */

/** @defgroup CG_Exported_Functions
  * @{
  */

/**
  * @brief  Set dividing level between clock fgear and fc.
  * @param  DivideFgearFromFc: Dividing level between fgear and fc.
  *   This parameter can be one of the following values:
  *   CG_DIVIDE_1, CG_DIVIDE_2, CG_DIVIDE_4, CG_DIVIDE_8, CG_DIVIDE_16
  * @retval None
  * @register The used register:
  *   CG0CLKCR<GEAR[2:0]>
  */
void CG_SetFgearLevel(CG_DivideLevel DivideFgearFromFc)
{
    /* Check the parameters */
    assert_param(IS_CG_GEAR_DIVIDE_LEVEL(DivideFgearFromFc));

    TSB_CG0->CLKCR &= CG_CLKCR_GEAR_CLEAR;

    /* Set the value of fgear */
    switch (DivideFgearFromFc) {
    case CG_DIVIDE_1:
        TSB_CG0->CLKCR |= FC_GEAR_1_1;
        break;
    case CG_DIVIDE_2:
        TSB_CG0->CLKCR |= FC_GEAR_1_2;
        break;
    case CG_DIVIDE_4:
        TSB_CG0->CLKCR |= FC_GEAR_1_4;
        break;
    case CG_DIVIDE_8:
        TSB_CG0->CLKCR |= FC_GEAR_1_8;
        break;
    case CG_DIVIDE_16:
        TSB_CG0->CLKCR |= FC_GEAR_1_16;
        break;
    default:
        /* Do nothing */
        break;
    }
}

/**
  * @brief  Get dividing level between clock fgear and fc.
  * @param  None
  * @retval The dividing level between clock fgear and fc
  *   The value returned can be one of the following values:
  *   CG_DIVIDE_1, CG_DIVIDE_2, CG_DIVIDE_4,
  *   CG_DIVIDE_8, CG_DIVIDE_16 or CG_DIVIDE_UNKNOWN
  * @register The used register:
  *   CG0CLKCR<GEAR[2:0]>
  */
CG_DivideLevel CG_GetFgearLevel(void)
{
    CG_DivideLevel DivideFgearFromFc = CG_DIVIDE_UNKNOWN;
    uint32_t syscr = TSB_CG0->CLKCR;
    syscr &= CG_CLKCR_GEAR_SET;

    switch (syscr) {
    case FC_GEAR_1_1:
        DivideFgearFromFc = CG_DIVIDE_1;
        break;
    case FC_GEAR_1_2:
        DivideFgearFromFc = CG_DIVIDE_2;
        break;
    case FC_GEAR_1_4:
        DivideFgearFromFc = CG_DIVIDE_4;
        break;
    case FC_GEAR_1_8:
        DivideFgearFromFc = CG_DIVIDE_8;
        break;
    case FC_GEAR_1_16:
        DivideFgearFromFc = CG_DIVIDE_16;
        break;
    default:
        /* Do nothing */
        break;
    }

    return DivideFgearFromFc;
}

/**
  * @brief  Set fperiph for PhiT0
  * @param  PhiT0Src: Set PhiT0 Source
  *   This parameter can be one of the following values:
  *   CG_PHIT0_SRC_FGEAR or CG_PHIT0_SRC_FC
  * @retval None
  * @register The used register:
  *   CG0CLKCR<FPSEL>
  */
void CG_SetPhiT0Src(CG_PhiT0Src PhiT0Src)
{
    uint32_t regval = TSB_CG0->CLKCR;
    uint32_t tmp = 0U;

    /* Check the parameters */
    assert_param(IS_CG_PHIT0_SRC(PhiT0Src));

    regval &= CG_CLKCR_FPSEL_CLEAR;
    tmp = (uint32_t) PhiT0Src;
    regval |= (tmp << 6U);

    TSB_CG0->CLKCR = regval;
}

/**
  * @brief  Get PhiT0 Source
  * @param  None
  * @retval The source of PhiT0
  *   The value returned can be one of the following values:
  *   CG_PHIT0_SRC_FGEAR or CG_PHIT0_SRC_FC
  * @register The used register:
  *   CG0CLKCR<FPSEL>
  */
CG_PhiT0Src CG_GetPhiT0Src(void)
{
    uint32_t regval = TSB_CG0->CLKCR;
    CG_PhiT0Src source = CG_PHIT0_SRC_FGEAR;

    regval &= CG_CLKCR_FPSEL_SET;
    regval = (regval >> 6U);
    source = numPhiT0Src_table[regval];

    return source;
}

/**
  * @brief  Set source clock for the SysTick reference clock.
  * @param  SysTickSrc: Select SysTick source.
  *   This parameter can be one of the following values:
  *   CG_STICK_SRC_IHOSC or CG_STICK_SRC_FOSC
  * @retval None
  * @register The used register:
  *   CG0CLKCR<STICK>
  */
void CG_SetSysTickSrc(CG_SysTickSrc SysTickSrc)
{
    uint32_t regval = TSB_CG0->CLKCR;
    uint32_t tmp = 0U;

    /* Check the parameters */
    assert_param(IS_CG_STICK_SRC(SysTickSrc));

    regval &= CG_CLKCR_STICK_CLEAR;
    tmp = (uint32_t) SysTickSrc;
    regval |= (tmp << 7U);

    TSB_CG0->CLKCR = regval;
}

/**
  * @brief  Get the SysTick reference clock source
  * @param  None
  * @retval The source of SysTick
  *   The value returned can be one of the following values:
  *   CG_STICK_SRC_IHOSC or CG_STICK_SRC_FOSC
  * @register The used register:
  *   CG0CLKCR<STICK>
  */
CG_SysTickSrc CG_GetSysTickSrc(void)
{
    uint32_t regval = TSB_CG0->CLKCR;
    CG_SysTickSrc source = CG_STICK_SRC_IHOSC;

    regval &= CG_CLKCR_STICK_SET;
    regval = (regval >> 7U);
    source = numSysTickSrc_table[regval];

    return source;
}

/**
  * @brief  Set dividing level between clock PhiT0 and fc.
  * @param  DividePhiT0FromFc: Dividing level between PhiT0 and fc.
  *   This parameter can be one of the following values:
  *   CG_DIVIDE_1, CG_DIVIDE_2, CG_DIVIDE_4, CG_DIVIDE_8,
  *   CG_DIVIDE_16, CG_DIVIDE_32, CG_DIVIDE_64, CG_DIVIDE_128,
  *   CG_DIVIDE_256 or CG_DIVIDE_512
  * @retval  Success or not
  *   The value returned can be one of the following values:
  *   SUCCESS or ERROR
  * @register The used register:
  *   CG0CLKCR<PRCK[2:0]>
  */
Result CG_SetPhiT0Level(CG_DivideLevel DividePhiT0FromFc)
{
    uint32_t fprclk = 0U;
    CG_DivideLevel fgear = CG_DIVIDE_UNKNOWN;
    CG_PhiT0Src PhiT0_src = CG_PHIT0_SRC_FGEAR;
    Result retval = ERROR;
    uint32_t regval = TSB_CG0->CLKCR;

    PhiT0_src = CG_GetPhiT0Src();
    if (PhiT0_src == CG_PHIT0_SRC_FC) { /* phiT0 src == fc , max divider: 32 */
        /* Check the parameters */
        assert_param(IS_CG_FC_DIDIDE_LEVEL(DividePhiT0FromFc));

        fprclk = (uint32_t) DividePhiT0FromFc;
        regval &= CG_CLKCR_PRCK_CLEAR;
        fprclk <<= 3U;
        regval |= fprclk;
        TSB_CG0->CLKCR = regval;
        retval = SUCCESS;
    } else {                    /* phiT0 src == fgear, max divider: 512 */
        /* Check the parameters */
        assert_param(IS_CG_DIVIDE_FC_LEVEL(DividePhiT0FromFc));

        fgear = CG_GetFgearLevel();
        if (fgear != CG_DIVIDE_UNKNOWN) {
            if (DividePhiT0FromFc >= fgear) {
                fprclk = (uint32_t) DividePhiT0FromFc - (uint32_t) fgear;
                if (fprclk < CG_DIVIDE_64) {
                    regval &= CG_CLKCR_PRCK_CLEAR;
                    fprclk <<= 3U;
                    regval |= fprclk;
                    TSB_CG0->CLKCR = regval;
                    retval = SUCCESS;
                } else {
                    /* Do nothing */
                }
            } else {
                /* Do nothing */
            }
        } else {
            /* Do nothing */
        }
    }

    return retval;
}

/**
  * @brief  Get dividing level between clock phiT0 and fc.
  * @param  None
  * @retval The divide level between clock phiT0 and fc
  *   The value returned can be one of the following values:
  *   CG_DIVIDE_1, CG_DIVIDE_2, CG_DIVIDE_4, CG_DIVIDE_8,
  *   CG_DIVIDE_16, CG_DIVIDE_32, CG_DIVIDE_64, CG_DIVIDE_128,
  *   CG_DIVIDE_256, CG_DIVIDE_512 or CG_DIVIDE_UNKNOWN
  * @register The used register:
  *   CG0CLKCR<PRCK[2:0]><GEAR[2:0]><FPSEL>
  */
CG_DivideLevel CG_GetPhiT0Level(void)
{
    uint32_t fprclk = 0U;
    CG_DivideLevel fgear = CG_DIVIDE_UNKNOWN;
    CG_DivideLevel phiT0Level = CG_DIVIDE_UNKNOWN;
    CG_PhiT0Src PhiT0_src = CG_PHIT0_SRC_FGEAR;

    fprclk = TSB_CG0->CLKCR & CG_CLKCR_PRCK_SET;
    fprclk = (uint32_t) (fprclk >> 3U);
    PhiT0_src = CG_GetPhiT0Src();

    if (PhiT0_src == CG_PHIT0_SRC_FC) {
        phiT0Level = numToDivideLevel_table[fprclk];
    } else {
        fgear = CG_GetFgearLevel();
        if (fgear != CG_DIVIDE_UNKNOWN) {
            fprclk = fprclk + (uint32_t) fgear;
            if (fprclk < CG_DIVIDE_UNKNOWN) {
                phiT0Level = numToDivideLevel_table[fprclk];
            } else {
                /* Do nothing */
            }
        } else {
            /* Do nothing */
        }
    }

    return phiT0Level;
}

/**
  * @brief  Set the warm up time. 
  * @param  Source: Select source of warm-up counter
  *   This parameter can be one of the following values:
  *   CG_WARM_UP_SRC_OSC_INT_HIGH, CG_WARM_UP_SRC_OSC_EXT_HIGH.
  *   Warm-up function is not necessary when using stable external clock.
  * @param  Time: Set count time for warm-up timer.
  * @retval None
  * @register The used register:
  *   CG0WUHCR<WUPT[11:0]><WUCLK>
  */
void CG_SetWarmUpTime(CG_WarmUpSrc Source, uint16_t Time)
{
    uint32_t tmp = 0U;

    /* Check the parameters */
    assert_param(IS_CG_WARM_UP_SRC(Source));

    switch (Source) {
    case CG_WARM_UP_SRC_OSC_INT_HIGH:
        /* Check the parameters */
        assert_param(IS_CG_WARM_UP_TIME_HIGH(Time));
        tmp = Time;
        tmp <<= 16U;
        TSB_CG0->WUHCR &= CG_WUHCR_WUPT_WUCLK_CLEAR;
        TSB_CG0->WUHCR |= tmp;
        break;
    case CG_WARM_UP_SRC_OSC_EXT_HIGH:
        /* Check the parameters */
        assert_param(IS_CG_WARM_UP_TIME_HIGH(Time));
        tmp = Time;
        tmp <<= 16U;
        TSB_CG0->WUHCR &= CG_WUHCR_WUPT_WUCLK_CLEAR;
        TSB_CG0->WUHCR |= CG_WUHCR_WUCLK_SET;
        TSB_CG0->WUHCR |= tmp;
        break;
    default:
        /* Do nothing */
        break;
    }
}

/**
  * @brief  Start operation of the specified timer for oscillator.
  * @param  None
  * @retval None
  * @register The used register:
  *   CG0WUHCR<WUON>
  */
void CG_StartWarmUp(void)
{
    TSB_CG0->WUHCR |= CG_WUHCR_WUON_SET;
}

/**
  * @brief Check whether the warm up is completed or not.
  * @param None
  * @retval The state of the specified warm-up
  *   The value returned can be one of the following values:
  *   DONE or BUSY
  * @register The used register:
  *   CG0WUHCR<WUEF>
  */
WorkState CG_GetWarmUpState(void)
{
    WorkState state = BUSY;
    uint32_t tmp = 0U;

    tmp = TSB_CG0->WUHCR & CG_WUHCR_WUEF_SET;
    if (tmp == 0U) {
        state = DONE;
    } else {
        /* Do nothing */
    }

    return state;
}

/**
  * @brief  Enable or disable high-speed oscillator (fosc)
  * @param  Source: Select clock source for fosc
  *   This parameter can be one of the following values:
  *   CG_FOSC_OSC_EXT or CG_FOSC_OSC_INT
  * @param  NewState: oscillator is enabled or disabled
  *   This parameter can be one of the following values:
  *   DISABLE or ENABLE
  * @retval Success or failure
  *   The value returned can be one of the following values:
  *   SUCCESS or ERROR
  * @register The used register:
  *   CG0OSCEN<EHOSCEN><IHOSCEN>
  */
Result CG_SetFosc(CG_FoscSrc Source, FunctionalState NewState)
{
    CG_FoscSrc fosc_src = CG_FOSC_OSC_EXT;
    CG_FcSrc fc_src = CG_FC_SRC_IHOSC;
    Result retval = ERROR;
    uint32_t regval = TSB_CG0->OSCEN;

    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    assert_param(IS_CG_FOSC_STATE(Source));

    switch (Source) {
    case CG_FOSC_OSC_EXT:
        if (NewState == ENABLE) {
            /* Enable and select external high-speed oscillator */
            regval &= CG_OSCEN_EHOSCEN_CLEAR;
            regval |= CG_OSCEN_EHOSC_SET;
            retval = SUCCESS;
        } else {
            fosc_src = CG_GetFoscSrc();
            if (fosc_src == CG_FOSC_OSC_EXT) {
                /* external oscillator is in use, so it can't be disabled */
                retval = ERROR;
            } else {
                /* Disable external high-speed oscillator */
                regval &= CG_OSCEN_EHOSCEN_CLEAR;
                retval = SUCCESS;
            }
        }
        break;
    case CG_FOSC_OSC_INT:
        if (NewState == ENABLE) {
            /* Enable internal high-speed oscillator */
            regval |= CG_OSCEN_IHOSCEN_SET;
            retval = SUCCESS;
        } else {
            fc_src = CG_GetFcSrc();
            if (fc_src == CG_FC_SRC_IHOSC) {
                /* internal high-speed oscillator is in  use, so it can't be disabled */
                retval = ERROR;
            } else {
                /* Disable internal high-speed oscillator */
                regval &= CG_OSCEN_IHOSCEN_CLEAR;
                retval = SUCCESS;
            }
        }
        break;
    default:
        /* Do nothing */
        break;
    }
    TSB_CG0->OSCEN = regval;
    return retval;
}

/**
  * @brief  Set the source of high-speed oscillator (fosc)
  * @param  Source: Select clock source for fosc
  *   This parameter can be one of the following values:
  *   CG_FOSC_OSC_EXT, CG_FOSC_CLKIN_EXT.
  * @retval None
  * @register The used register:
  *   CG0OSCEN<EHOSCEN>
  */
void CG_SetFoscSrc(CG_FoscSrc Source)
{
    uint32_t regval = TSB_CG0->OSCEN;

    /* Check the parameters */
    assert_param(IS_CG_FOSC_SRC(Source));

    regval &= CG_OSCEN_EHOSCEN_CLEAR;

    if (Source == CG_FOSC_OSC_EXT) {
        /* Selects external high-speed oscillator */
        regval |= CG_OSCEN_EHOSC_SET;
    } else {
        /* Selects an external clock input */
        regval |= CG_OSCEN_EHCLKIN_SET;
    }
    TSB_CG0->OSCEN = regval;
}

/**
  * @brief  Get the source of high-speed oscillator (fosc)
  * @param  None
  * @retval Source of fosc
  *   The value returned can be one of the following values:
  *   CG_FOSC_OSC_EXT, CG_FOSC_CLKIN_EXT, CG_FOSC_UNKNOWN.
  * @register The used register:
  *   CG0OSCEN<EHOSCEN>
  */
CG_FoscSrc CG_GetFoscSrc(void)
{
    uint32_t ehoscen = TSB_CG0->OSCEN & CG_OSCEN_EHOSCEN_SET;
    CG_FoscSrc fosc_src = CG_FOSC_UNKNOWN;

    switch (ehoscen) {
    case CG_OSCEN_EHOSC_SET:
        fosc_src = CG_FOSC_OSC_EXT;
        break;
    case CG_OSCEN_EHCLKIN_SET:
        fosc_src = CG_FOSC_CLKIN_EXT;
        break;
    default:
        /* Do nothing */
        break;
    }

    return fosc_src;
}

/**
  * @brief  Get the state of high-speed oscillator (fosc)
  * @param  Source: Select fosc source
  *   This parameter can be one of the following values:
  *   CG_FOSC_OSC_EXT or CG_FOSC_OSC_INT
  * @retval State of fosc
  *   The value returned can be one of the following values:
  *   ENABLE or DISABLE
  * @register The used register:
  *   CG0OSCEN<EHOSCEN><IHOSCEN>
  */
FunctionalState CG_GetFoscState(CG_FoscSrc Source)
{
    uint32_t regval = TSB_CG0->OSCEN;
    FunctionalState state = DISABLE;

    /* Check the parameters */
    assert_param(IS_CG_FOSC_STATE(Source));

    switch (Source) {
    case CG_FOSC_OSC_EXT:
        regval &= CG_OSCEN_EHOSCEN_SET;
        if (regval == CG_OSCEN_EHOSC_SET) {
            state = ENABLE;
        } else {
            /* Do nothing */
        }
        break;
    case CG_FOSC_OSC_INT:
        regval &= CG_OSCEN_IHOSCEN_SET;
        if (regval == CG_OSCEN_IHOSCEN_SET) {
            state = ENABLE;
        } else {
            /* Do nothing */
        }
        break;
    default:
        /* Do nothing */
        break;
    }

    return state;
}

/**
  * @brief  Set the source of fc
  * @param  Source: The source of fc
  *   This parameter can be one of the following values:
  *   CG_FC_SRC_FOSC, CG_FC_SRC_IHOSC
  * @retval success or failure
  *   The value returned can be one of the following values:
  *   SUCCESS or ERROR
  * @register The used register:
  *   CG0OSCSEL<OSCSEL[1:0]>
  */
Result CG_SetFcSrc(CG_FcSrc Source)
{
    Result retval = ERROR;
    FunctionalState state = DISABLE;
    CG_FoscSrc fosc_src = CG_FOSC_OSC_EXT;

    /* Check the parameters */
    assert_param(IS_CG_FC_SRC(Source));

    switch (Source) {
    case CG_FC_SRC_FOSC:
        fosc_src = CG_GetFoscSrc();
        switch (fosc_src) {
        case CG_FOSC_OSC_EXT:
            state = CG_GetFoscState(CG_FOSC_OSC_EXT);
            if (state == ENABLE) {
                TSB_CG0->OSCSEL = CG_OSCSEL_FOSC;
                retval = SUCCESS;
            } else {
                /* Do nothing */
            }
            break;
        case CG_FOSC_CLKIN_EXT:
            TSB_CG0->OSCSEL = CG_OSCSEL_FOSC;
            retval = SUCCESS;
            break;
        default:
            /* Do nothing */
            break;
        }
        break;
    case CG_FC_SRC_IHOSC:
        state = CG_GetFoscState(CG_FOSC_OSC_INT);
        if (state == ENABLE) {
            TSB_CG0->OSCSEL = CG_OSCSEL_IHOSC;
            retval = SUCCESS;
        } else {
            /* Do nothing */
        }
        break;
    default:
        /* Do nothing */
        break;
    }
    return retval;
}

/**
  * @brief  Get the source of fc
  * @param  None
  * @retval The source of fc
  *   The value returned can be one of the following values:
  *   CG_FC_SRC_FOSC, CG_FC_SRC_IHOSC
  * @register The used register:
  *   CG0OSCSTF<OSCF[1:0]>
  */
CG_FcSrc CG_GetFcSrc(void)
{
    CG_FcSrc fcsrc = CG_FC_SRC_FOSC;

    switch (TSB_CG0->OSCSTF) {
    case CG_OSCSTF_IHOSC:
        fcsrc = CG_FC_SRC_IHOSC;
        break;
    case CG_OSCSTF_FOSC:
        fcsrc = CG_FC_SRC_FOSC;
        break;
    default:
        /* Do nothing */
        break;
    }

    return fcsrc;
}

/**
  * @brief  Enable or disable to protect CG registers
  * @param  NewState: New state of the CG protect register
  *   This parameter can be one of the following values:
  *   DISABLE or ENABLE
  * @retval None
  * @register The used register:
  *   CG0PROTECT<CGPROTECT[7:0]>
  */
void CG_SetProtectCtrl(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState == ENABLE) {
        TSB_CG0->PROTECT = CG_PROTECT_SET;
    } else {
        TSB_CG0->PROTECT = CG_PROTECT_CLEAR;
    }
}

/**
  * @brief  Setup the INT source for releasing low power mode.
  * @param  INTSource: Select the release INT source
  *   This parameter can be one of the following values:  
  *   CG_INT_SRC_0, CG_INT_SRC_1.
  * @param  ActiveState: select the active state for release trigger
  *   This parameter can be one of the following values:
  *   CG_INT_ACTIVE_STATE_L, 
  *   CG_INT_ACTIVE_STATE_H, 
  *   CG_INT_ACTIVE_STATE_FALLING, 
  *   CG_INT_ACTIVE_STATE_RISING or 
  *   CG_INT_ACTIVE_STATE_BOTH_EDGES.
  * @retval None
  * @register The used register:
  *   INT0CRn<ACT[2:0]> ('n' can be 0,1)
  */
void CG_SetSTBYReleaseINTSrc(CG_INTSrc INTSource, CG_INTActiveState ActiveState)
{
    uint32_t num = 0U;

    /* Check the parameters */
    assert_param(IS_CG_INT_SRC(INTSource));
    assert_param(IS_CG_INT_ACTIVE_STATE(ActiveState));

    num = (uint32_t) INTSource;
    *CG_CRn[num] = ActiveState;
}

/**
  * @brief  Get the active state of INT source standby clear request
  * @param  INTSource: Select the release INT source
  *   This parameter can be one of the following values:  
  *   CG_INT_SRC_0, CG_INT_SRC_1.
  * @retval Active state of the input INT
  *   The value returned can be one of the following values:
  *   CG_INT_ACTIVE_STATE_FALLING, CG_INT_ACTIVE_STATE_RISING,
  *   CG_INT_ACTIVE_STATE_BOTH_EDGES or CG_INT_ACTIVE_STATE_INVALID.
  * @register The used register:
  *   INT0CRn<ST[1:0]> ('n' can be 0,1)
  */
CG_INTActiveState CG_GetSTBYReleaseINTState(CG_INTSrc INTSource)
{
    CG_INTActiveState int_active_state = CG_INT_ACTIVE_STATE_INVALID;
    uint32_t num = 0U;
    uint32_t st = 0U;

    /* Check the parameters */
    assert_param(IS_CG_INT_SRC(INTSource));

    num = (uint32_t) INTSource;
    st = *CG_CRn[num] & CG_CR_ST_SET;

    switch (st) {
    case CG_CR_ST_RISING:
        int_active_state = CG_INT_ACTIVE_STATE_RISING;
        break;
    case CG_CR_ST_FALLING:
        int_active_state = CG_INT_ACTIVE_STATE_FALLING;
        break;
    case CG_CR_ST_BOTH_EDGES:
        int_active_state = CG_INT_ACTIVE_STATE_BOTH_EDGES;
        break;
    default:
        /* Do nothing */
        break;
    }

    return (int_active_state);
}

/**
  * @brief  Clears the input INT request.
  * @param  INTSource: Select the release INT source
  *   This parameter can be one of the following values:
  *   CG_INT_SRC_0, CG_INT_SRC_1.
  * @retval None
  * @register The used register:
  *   INT0CLR<CLR>
  */
void CG_ClearINTReq(CG_INTSrc INTSource)
{
    uint32_t regval = INTSource;

    /* Check the parameters */
    assert_param(IS_CG_INT_SRC(INTSource));

    TSB_INT0->CLR = regval;
}

/**
  * @brief  Get the type of reset reason and clear the reset flag.
  * @param  None
  * @retval Reset flag
  * @register The used register:
  *   INT0RESETF<RSTF0><RSTF3><RSTF4>
  */
CG_ResetFlag CG_GetResetFlag(void)
{
    CG_ResetFlag reset_flag = { 0U };

    reset_flag.All = TSB_INT0->RESETF;
    /* Clear flag */
    TSB_INT0->RESETF = INT_RESETF_RSTF_CLEAR;

    return reset_flag;
}

/** @} */
/* End of group CG_Exported_Functions */

/** @} */
/* End of group CG */

/** @} */
/* End of group TX03_Periph_Driver */

#endif                          /* defined(__TMPM311_CG_H) */
