/**************************************************************************//**
 * @file     clk.c
 * @version  V3.00
 * @brief    M460 series CLK driver source file
 *
 * @copyright SPDX-License-Identifier: Apache-2.0
 * @copyright Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
 *****************************************************************************/

#include "NuMicro.h"

/** @addtogroup Standard_Driver Standard Driver
  @{
*/

/** @addtogroup CLK_Driver CLK Driver
  @{
*/

/** @addtogroup CLK_EXPORTED_FUNCTIONS CLK Exported Functions
  @{
*/

/**
  * @brief      Disable clock divider output function
  * @param      None
  * @return     None
  * @details    This function disable clock divider output function.
  */
void CLK_DisableCKO(void)
{
    /* Disable CKO clock source */
    CLK->APBCLK0 &= (~CLK_APBCLK0_CLKOCKEN_Msk);
}

/**
  * @brief      This function enable clock divider output module clock,
  *             enable clock divider output function and set frequency selection.
  * @param[in]  u32ClkSrc is frequency divider function clock source. Including :
  *             - \ref CLK_CLKSEL1_CLKOSEL_HXT
  *             - \ref CLK_CLKSEL1_CLKOSEL_LXT
  *             - \ref CLK_CLKSEL1_CLKOSEL_HCLK
  *             - \ref CLK_CLKSEL1_CLKOSEL_HIRC
  *             - \ref CLK_CLKSEL1_CLKOSEL_LIRC
  *             - \ref CLK_CLKSEL1_CLKOSEL_PLLFN_DIV2
  *             - \ref CLK_CLKSEL1_CLKOSEL_PLL_DIV2
  * @param[in]  u32ClkDiv is divider output frequency selection. It could be 0~15.
  * @param[in]  u32ClkDivBy1En is clock divided by one enabled.
  * @return     None
  * @details    Output selected clock to CKO. The output clock frequency is divided by u32ClkDiv. \n
  *             The formula is: \n
  *                 CKO frequency = (Clock source frequency) / 2^(u32ClkDiv + 1) \n
  *             This function is just used to set CKO clock.
  *             User must enable I/O for CKO clock output pin by themselves. \n
  */
void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
{
    /* CKO = clock source / 2^(u32ClkDiv + 1) */
    CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | (u32ClkDiv) | (u32ClkDivBy1En << CLK_CLKOCTL_DIV1EN_Pos);

    /* Enable CKO clock source */
    CLK->APBCLK0 |= CLK_APBCLK0_CLKOCKEN_Msk;

    /* Select CKO clock source */
    CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_CLKOSEL_Msk)) | (u32ClkSrc);
}

/**
  * @brief      Enter to Power-down mode
  * @param      None
  * @return     None
  * @details    This function is used to let system enter to Power-down mode. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_PowerDown(void)
{
    volatile uint32_t u32SysTickTICKINT = 0, u32HIRCTCTL = 0, u32IRCTCTL = 0;

    /* Set the processor uses deep sleep as its low power mode */
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    /* Set system Power-down enabled */
    CLK->PWRCTL |= (CLK_PWRCTL_PDEN_Msk);

    /* Store SysTick interrupt and HIRC auto trim setting */
    u32SysTickTICKINT = SysTick->CTRL & SysTick_CTRL_TICKINT_Msk;
    u32HIRCTCTL = SYS->HIRCTCTL;
    u32IRCTCTL = SYS->IRCTCTL;

    /* Disable SysTick interrupt and HIRC auto trim */
    SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
    SYS->HIRCTCTL &= (~SYS_HIRCTCTL_FREQSEL_Msk);
    SYS->IRCTCTL &= (~SYS_IRCTCTL_FREQSEL_Msk);

    /* Chip enter Power-down mode after CPU run WFI instruction */
    __WFI();

    /* Restore SysTick interrupt and HIRC auto trim setting */
    if(u32SysTickTICKINT) SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
    SYS->HIRCTCTL = u32HIRCTCTL;
    SYS->IRCTCTL = u32IRCTCTL;
}

/**
  * @brief      Enter to Idle mode
  * @param      None
  * @return     None
  * @details    This function let system enter to Idle mode. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_Idle(void)
{
    /* Set the processor uses sleep as its low power mode */
    SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;

    /* Set chip in idle mode because of WFI command */
    CLK->PWRCTL &= ~CLK_PWRCTL_PDEN_Msk;

    /* Chip enter idle mode after CPU run WFI instruction */
    __WFI();
}

/**
  * @brief      Get external high speed crystal clock frequency
  * @param      None
  * @return     External high frequency crystal frequency
  * @details    This function get external high frequency crystal frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetHXTFreq(void)
{
    uint32_t u32Freq;

    if(CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk)
    {
        u32Freq = __HXT;
    }
    else
    {
        u32Freq = 0UL;
    }

    return u32Freq;
}


/**
  * @brief      Get external low speed crystal clock frequency
  * @param      None
  * @return     External low speed crystal clock frequency
  * @details    This function get external low frequency crystal frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetLXTFreq(void)
{
    uint32_t u32Freq;

    if(CLK->PWRCTL & CLK_PWRCTL_LXTEN_Msk)
    {
        u32Freq = __LXT;
    }
    else
    {
        u32Freq = 0UL;
    }

    return u32Freq;
}

/**
  * @brief      Get PCLK0 frequency
  * @param      None
  * @return     PCLK0 frequency
  * @details    This function get PCLK0 frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetPCLK0Freq(void)
{
    uint32_t u32Freq;
    SystemCoreClockUpdate();

    if((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) == CLK_PCLKDIV_APB0DIV_DIV1)
    {
        u32Freq = SystemCoreClock;
    }
    else if((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) == CLK_PCLKDIV_APB0DIV_DIV2)
    {
        u32Freq = SystemCoreClock >> 1;
    }
    else if((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) == CLK_PCLKDIV_APB0DIV_DIV4)
    {
        u32Freq = SystemCoreClock >> 2;
    }
    else if((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) == CLK_PCLKDIV_APB0DIV_DIV8)
    {
        u32Freq = SystemCoreClock >> 3;
    }
    else if((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) == CLK_PCLKDIV_APB0DIV_DIV16)
    {
        u32Freq = SystemCoreClock >> 4;
    }
    else
    {
        u32Freq = SystemCoreClock;
    }

    return u32Freq;
}


/**
  * @brief      Get PCLK1 frequency
  * @param      None
  * @return     PCLK1 frequency
  * @details    This function get PCLK1 frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetPCLK1Freq(void)
{
    uint32_t u32Freq;
    SystemCoreClockUpdate();

    if((CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) == CLK_PCLKDIV_APB1DIV_DIV1)
    {
        u32Freq = SystemCoreClock;
    }
    else if((CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) == CLK_PCLKDIV_APB1DIV_DIV2)
    {
        u32Freq = SystemCoreClock >> 1;
    }
    else if((CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) == CLK_PCLKDIV_APB1DIV_DIV4)
    {
        u32Freq = SystemCoreClock >> 2;
    }
    else if((CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) == CLK_PCLKDIV_APB1DIV_DIV8)
    {
        u32Freq = SystemCoreClock >> 3;
    }
    else if((CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) == CLK_PCLKDIV_APB1DIV_DIV16)
    {
        u32Freq = SystemCoreClock >> 4;
    }
    else
    {
        u32Freq = SystemCoreClock;
    }

    return u32Freq;
}


/**
  * @brief      Get HCLK frequency
  * @param      None
  * @return     HCLK frequency
  * @details    This function get HCLK frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetHCLKFreq(void)
{
    SystemCoreClockUpdate();
    return SystemCoreClock;
}


/**
  * @brief      Get CPU frequency
  * @param      None
  * @return     CPU frequency
  * @details    This function get CPU frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetCPUFreq(void)
{
    SystemCoreClockUpdate();
    return SystemCoreClock;
}


/**
  * @brief      Set HCLK frequency
  * @param[in]  u32Hclk is HCLK frequency. The range of u32Hclk is 50MHz ~ 200MHz.
  * @return     HCLK frequency
  * @details    This function is used to set HCLK frequency by using PLL. The frequency unit is Hz. \n
  *             Power level and flash access cycle are also set according to HCLK frequency. \n
  *             The register write-protection function should be disabled before using this function.
  */
uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
{
    uint32_t u32HIRCSTB;

    /* Read HIRC clock source stable flag */
    u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;

    /* Check HCLK frequency range is 50MHz ~ 200MHz */
    if(u32Hclk > FREQ_200MHZ)
    {
        u32Hclk = FREQ_200MHZ;
    }
    else if(u32Hclk < FREQ_50MHZ)
    {
        u32Hclk = FREQ_50MHZ;
    }

    /* Switch HCLK clock source to HIRC clock for safe */
    CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
    CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
    CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;
    CLK->CLKDIV0 &= (~CLK_CLKDIV0_HCLKDIV_Msk);

    /* Configure PLL setting if HXT clock is stable */
    if(CLK->STATUS & CLK_STATUS_HXTSTB_Msk)
    {
        u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, u32Hclk);
    }
    /* Configure PLL setting if HXT clock is not stable */
    else
    {
        u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC, u32Hclk);

        /* Read HIRC clock source stable flag */
        u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
    }

    /* Select HCLK clock source to PLL,
       select HCLK clock source divider as 1,
       adjust power level, flash access cycle and update system core clock
    */
    CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL, CLK_CLKDIV0_HCLK(1UL));

    /* Disable HIRC if HIRC is disabled before setting core clock */
    if(u32HIRCSTB == 0UL)
    {
        CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
    }

    /* Return actually HCLK frequency is PLL frequency divide 1 */
    return u32Hclk;
}

/**
  * @brief      Set HCLK clock source and HCLK clock divider
  * @param[in]  u32ClkSrc is HCLK clock source. Including :
  *             - \ref CLK_CLKSEL0_HCLKSEL_HXT
  *             - \ref CLK_CLKSEL0_HCLKSEL_LXT
  *             - \ref CLK_CLKSEL0_HCLKSEL_PLL
  *             - \ref CLK_CLKSEL0_HCLKSEL_LIRC
  *             - \ref CLK_CLKSEL0_HCLKSEL_HIRC
  * @param[in]  u32ClkDiv is HCLK clock divider. Including :
  *             - \ref CLK_CLKDIV0_HCLK(x)
  * @return     None
  * @details    This function set HCLK clock source and HCLK clock divider. \n
  *             Power level and flash access cycle are also set according to HCLK operation frequency. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
{
    uint32_t u32HIRCSTB, u32TimeOutCount;

    /* Read HIRC clock source stable flag */
    u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;

    /* Switch to HIRC for safe. Avoid HCLK too high when applying new divider. */
    CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
    CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
    CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;

    /* Switch to power level 0 for safe */
    SYS->PLCTL = (SYS->PLCTL & (~SYS_PLCTL_PLSEL_Msk)) | SYS_PLCTL_PLSEL_PL0;
    u32TimeOutCount = SystemCoreClock; /* 1 second time-out */
    while(SYS->PLSTS & SYS_PLSTS_PLCBUSY_Msk)
    {
        if(u32TimeOutCount-- == 0) break;
    }

    /* Set Flash Access Cycle to 8 for safe */
    FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (8);

    /* Apply new Divider */
    CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | u32ClkDiv;

    /* Switch HCLK to new HCLK source */
    CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | u32ClkSrc;

    /* Update System Core Clock */
    SystemCoreClockUpdate();

    /* Set power level according to new HCLK */
    if(SystemCoreClock <= FREQ_180MHZ)
    {
        SYS->PLCTL = (SYS->PLCTL & (~SYS_PLCTL_PLSEL_Msk)) | SYS_PLCTL_PLSEL_PL1;
    }
    u32TimeOutCount = SystemCoreClock; /* 1 second time-out */
    while(SYS->PLSTS & SYS_PLSTS_PLCBUSY_Msk)
    {
        if(u32TimeOutCount-- == 0) break;
    }

    /* Switch flash access cycle to suitable value base on HCLK */
    if(SystemCoreClock >= FREQ_175MHZ)
    {
        FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (8);
    }
    else if(SystemCoreClock >= FREQ_150MHZ)
    {
        FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (7);
    }
    else if(SystemCoreClock >= FREQ_125MHZ)
    {
        FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (6);
    }
    else if(SystemCoreClock >= FREQ_100MHZ)
    {
        FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (5);
    }
    else if(SystemCoreClock >= FREQ_75MHZ)
    {
        FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (4);
    }
    else if(SystemCoreClock >= FREQ_50MHZ)
    {
        FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (3);
    }
    else if(SystemCoreClock >= FREQ_25MHZ)
    {
        FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (2);
    }
    else /* SystemCoreClock < FREQ_25MHZ */
    {
        FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (1);
    }

    /* Disable HIRC if HIRC is disabled before switching HCLK source */
    if(u32HIRCSTB == 0UL)
    {
        CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
    }
}

/**
  * @brief      This function set selected module clock source and module clock divider
  * @param[in]  u32ModuleIdx is module index.
  * @param[in]  u32ClkSrc is module clock source.
  * @param[in]  u32ClkDiv is module clock divider.
  * @return     None
  * @details    Valid parameter combinations listed in following table:
  *
  * |Module index        |Clock source                           |Divider                        |
  * | :----------------  | :-----------------------------------  | :--------------------------   |
  * |\ref USBH_MODULE    |\ref CLK_CLKSEL0_USBSEL_HIRC48M        |\ref CLK_CLKDIV0_USB(x)        |
  * |\ref USBH_MODULE    |\ref CLK_CLKSEL0_USBSEL_PLL_DIV2       |\ref CLK_CLKDIV0_USB(x)        |
  * |\ref OTG_MODULE     |\ref CLK_CLKSEL0_USBSEL_HIRC48M        |\ref CLK_CLKDIV0_USB(x)        |
  * |\ref OTG_MODULE     |\ref CLK_CLKSEL0_USBSEL_PLL_DIV2       |\ref CLK_CLKDIV0_USB(x)        |
  * |\ref USBD_MODULE    |\ref CLK_CLKSEL0_USBSEL_HIRC48M        |\ref CLK_CLKDIV0_USB(x)        |
  * |\ref USBD_MODULE    |\ref CLK_CLKSEL0_USBSEL_PLL_DIV2       |\ref CLK_CLKDIV0_USB(x)        |
  * |\ref EADC0_MODULE   |\ref CLK_CLKSEL0_EADC0SEL_PLLFN_DIV2   |\ref CLK_CLKDIV0_EADC0(x)      |
  * |\ref EADC0_MODULE   |\ref CLK_CLKSEL0_EADC0SEL_PLL_DIV2     |\ref CLK_CLKDIV0_EADC0(x)      |
  * |\ref EADC0_MODULE   |\ref CLK_CLKSEL0_EADC0SEL_HCLK         |\ref CLK_CLKDIV0_EADC0(x)      |
  * |\ref EADC1_MODULE   |\ref CLK_CLKSEL0_EADC1SEL_PLLFN_DIV2   |\ref CLK_CLKDIV2_EADC1(x)      |
  * |\ref EADC1_MODULE   |\ref CLK_CLKSEL0_EADC1SEL_PLL_DIV2     |\ref CLK_CLKDIV2_EADC1(x)      |
  * |\ref EADC1_MODULE   |\ref CLK_CLKSEL0_EADC1SEL_HCLK         |\ref CLK_CLKDIV2_EADC1(x)      |
  * |\ref EADC2_MODULE   |\ref CLK_CLKSEL0_EADC2SEL_PLLFN_DIV2   |\ref CLK_CLKDIV5_EADC2(x)      |
  * |\ref EADC2_MODULE   |\ref CLK_CLKSEL0_EADC2SEL_PLL_DIV2     |\ref CLK_CLKDIV5_EADC2(x)      |
  * |\ref EADC2_MODULE   |\ref CLK_CLKSEL0_EADC2SEL_HCLK         |\ref CLK_CLKDIV5_EADC2(x)      |
  * |\ref CCAP_MODULE    | x                                     | x                             |
  * |\ref CCAP_MODULE    | x                                     | x                             |
  * |\ref CCAP_MODULE    | x                                     | x                             |
  * |\ref CCAP_MODULE    | x                                     | x                             |
  * |\ref SEN_MODULE     |\ref CLK_CLKSEL0_CCAPSEL_HXT           |\ref CLK_CLKDIV3_VSENSE(x)     |
  * |\ref SEN_MODULE     |\ref CLK_CLKSEL0_CCAPSEL_PLL_DIV2      |\ref CLK_CLKDIV3_VSENSE(x)     |
  * |\ref SEN_MODULE     |\ref CLK_CLKSEL0_CCAPSEL_HCLK          |\ref CLK_CLKDIV3_VSENSE(x)     |
  * |\ref SEN_MODULE     |\ref CLK_CLKSEL0_CCAPSEL_HIRC          |\ref CLK_CLKDIV3_VSENSE(x)     |
  * |\ref SDH0_MODULE    |\ref CLK_CLKSEL0_SDH0SEL_HXT           |\ref CLK_CLKDIV0_SDH0(x)       |
  * |\ref SDH0_MODULE    |\ref CLK_CLKSEL0_SDH0SEL_PLL_DIV2      |\ref CLK_CLKDIV0_SDH0(x)       |
  * |\ref SDH0_MODULE    |\ref CLK_CLKSEL0_SDH0SEL_HIRC          |\ref CLK_CLKDIV0_SDH0(x)       |
  * |\ref SDH0_MODULE    |\ref CLK_CLKSEL0_SDH0SEL_HCLK          |\ref CLK_CLKDIV0_SDH0(x)       |
  * |\ref SDH1_MODULE    |\ref CLK_CLKSEL0_SDH1SEL_HXT           |\ref CLK_CLKDIV3_SDH1(x)       |
  * |\ref SDH1_MODULE    |\ref CLK_CLKSEL0_SDH1SEL_PLL_DIV2      |\ref CLK_CLKDIV3_SDH1(x)       |
  * |\ref SDH1_MODULE    |\ref CLK_CLKSEL0_SDH1SEL_HIRC          |\ref CLK_CLKDIV3_SDH1(x)       |
  * |\ref SDH1_MODULE    |\ref CLK_CLKSEL0_SDH1SEL_HCLK          |\ref CLK_CLKDIV3_SDH1(x)       |
  * |\ref CANFD0_MODULE  |\ref CLK_CLKSEL0_CANFD0SEL_HXT         |\ref CLK_CLKDIV5_CANFD0(x)     |
  * |\ref CANFD0_MODULE  |\ref CLK_CLKSEL0_CANFD0SEL_PLL_DIV2    |\ref CLK_CLKDIV5_CANFD0(x)     |
  * |\ref CANFD0_MODULE  |\ref CLK_CLKSEL0_CANFD0SEL_HCLK        |\ref CLK_CLKDIV5_CANFD0(x)     |
  * |\ref CANFD0_MODULE  |\ref CLK_CLKSEL0_CANFD0SEL_HIRC        |\ref CLK_CLKDIV5_CANFD0(x)     |
  * |\ref CANFD1_MODULE  |\ref CLK_CLKSEL0_CANFD1SEL_HXT         |\ref CLK_CLKDIV5_CANFD1(x)     |
  * |\ref CANFD1_MODULE  |\ref CLK_CLKSEL0_CANFD1SEL_PLL_DIV2    |\ref CLK_CLKDIV5_CANFD1(x)     |
  * |\ref CANFD1_MODULE  |\ref CLK_CLKSEL0_CANFD1SEL_HCLK        |\ref CLK_CLKDIV5_CANFD1(x)     |
  * |\ref CANFD1_MODULE  |\ref CLK_CLKSEL0_CANFD1SEL_HIRC        |\ref CLK_CLKDIV5_CANFD1(x)     |
  * |\ref CANFD2_MODULE  |\ref CLK_CLKSEL0_CANFD2SEL_HXT         |\ref CLK_CLKDIV5_CANFD2(x)     |
  * |\ref CANFD2_MODULE  |\ref CLK_CLKSEL0_CANFD2SEL_PLL_DIV2    |\ref CLK_CLKDIV5_CANFD2(x)     |
  * |\ref CANFD2_MODULE  |\ref CLK_CLKSEL0_CANFD2SEL_HCLK        |\ref CLK_CLKDIV5_CANFD2(x)     |
  * |\ref CANFD2_MODULE  |\ref CLK_CLKSEL0_CANFD2SEL_HIRC        |\ref CLK_CLKDIV5_CANFD2(x)     |
  * |\ref CANFD3_MODULE  |\ref CLK_CLKSEL0_CANFD3SEL_HXT         |\ref CLK_CLKDIV5_CANFD3(x)     |
  * |\ref CANFD3_MODULE  |\ref CLK_CLKSEL0_CANFD3SEL_PLL_DIV2    |\ref CLK_CLKDIV5_CANFD3(x)     |
  * |\ref CANFD3_MODULE  |\ref CLK_CLKSEL0_CANFD3SEL_HCLK        |\ref CLK_CLKDIV5_CANFD3(x)     |
  * |\ref CANFD3_MODULE  |\ref CLK_CLKSEL0_CANFD3SEL_HIRC        |\ref CLK_CLKDIV5_CANFD3(x)     |
  * |\ref EMAC0_MODULE   | x                                     | x                             |
  * |\ref WDT_MODULE     |\ref CLK_CLKSEL1_WDTSEL_LXT            | x                             |
  * |\ref WDT_MODULE     |\ref CLK_CLKSEL1_WDTSEL_HCLK_DIV2048   | x                             |
  * |\ref WDT_MODULE     |\ref CLK_CLKSEL1_WDTSEL_LIRC           | x                             |
  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_HXT           | x                             |
  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_LXT           | x                             |
  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_HCLK          | x                             |
  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_HIRC          | x                             |
  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_LIRC          | x                             |
  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_PLLFN_DIV2    | x                             |
  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_PLL_DIV2      | x                             |
  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_HXT           | x                             |
  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_LXT           | x                             |
  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_PCLK0         | x                             |
  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_EXT           | x                             |
  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_LIRC          | x                             |
  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_HIRC          | x                             |
  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_HXT           | x                             |
  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_LXT           | x                             |
  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_PCLK0         | x                             |
  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_EXT           | x                             |
  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_LIRC          | x                             |
  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_HIRC          | x                             |
  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_HXT           | x                             |
  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_LXT           | x                             |
  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_PCLK1         | x                             |
  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_EXT           | x                             |
  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_LIRC          | x                             |
  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_HIRC          | x                             |
  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_HXT           | x                             |
  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_LXT           | x                             |
  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_PCLK1         | x                             |
  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_EXT           | x                             |
  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_LIRC          | x                             |
  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_HIRC          | x                             |
  * |\ref UART0_MODULE   |\ref CLK_CLKSEL1_UART0SEL_HXT          |\ref CLK_CLKDIV0_UART0(x)      |
  * |\ref UART0_MODULE   |\ref CLK_CLKSEL1_UART0SEL_PLL_DIV2     |\ref CLK_CLKDIV0_UART0(x)      |
  * |\ref UART0_MODULE   |\ref CLK_CLKSEL1_UART0SEL_LXT          |\ref CLK_CLKDIV0_UART0(x)      |
  * |\ref UART0_MODULE   |\ref CLK_CLKSEL1_UART0SEL_HIRC         |\ref CLK_CLKDIV0_UART0(x)      |
  * |\ref UART1_MODULE   |\ref CLK_CLKSEL1_UART1SEL_HXT          |\ref CLK_CLKDIV0_UART1(x)      |
  * |\ref UART1_MODULE   |\ref CLK_CLKSEL1_UART1SEL_PLL_DIV2     |\ref CLK_CLKDIV0_UART1(x)      |
  * |\ref UART1_MODULE   |\ref CLK_CLKSEL1_UART1SEL_LXT          |\ref CLK_CLKDIV0_UART1(x)      |
  * |\ref UART1_MODULE   |\ref CLK_CLKSEL1_UART1SEL_HIRC         |\ref CLK_CLKDIV0_UART1(x)      |
  * |\ref WWDT_MODULE    |\ref CLK_CLKSEL1_WWDTSEL_HCLK_DIV2048  | x                             |
  * |\ref WWDT_MODULE    |\ref CLK_CLKSEL1_WWDTSEL_LIRC          | x                             |
  * |\ref EPWM0_MODULE   |\ref CLK_CLKSEL2_EPWM0SEL_HCLK         | x                             |
  * |\ref EPWM0_MODULE   |\ref CLK_CLKSEL2_EPWM0SEL_PCLK0        | x                             |
  * |\ref EPWM1_MODULE   |\ref CLK_CLKSEL2_EPWM1SEL_HCLK         | x                             |
  * |\ref EPWM1_MODULE   |\ref CLK_CLKSEL2_EPWM1SEL_PCLK1        | x                             |
  * |\ref QSPI0_MODULE   |\ref CLK_CLKSEL2_QSPI0SEL_HXT          | x                             |
  * |\ref QSPI0_MODULE   |\ref CLK_CLKSEL2_QSPI0SEL_PLL_DIV2     | x                             |
  * |\ref QSPI0_MODULE   |\ref CLK_CLKSEL2_QSPI0SEL_PCLK0        | x                             |
  * |\ref QSPI0_MODULE   |\ref CLK_CLKSEL2_QSPI0SEL_HIRC         | x                             |
  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_HXT           | x                             |
  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_PLL_DIV2      | x                             |
  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_PCLK1         | x                             |
  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_HIRC          | x                             |
  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_HIRC48M       | x                             |
  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_PLLFN_DIV2    | x                             |
  * |\ref BPWM0_MODULE   |\ref CLK_CLKSEL2_BPWM0SEL_HCLK         | x                             |
  * |\ref BPWM0_MODULE   |\ref CLK_CLKSEL2_BPWM0SEL_PCLK0        | x                             |
  * |\ref BPWM1_MODULE   |\ref CLK_CLKSEL2_BPWM1SEL_HCLK         | x                             |
  * |\ref BPWM1_MODULE   |\ref CLK_CLKSEL2_BPWM1SEL_PCLK1        | x                             |
  * |\ref QSPI1_MODULE   |\ref CLK_CLKSEL3_QSPI1SEL_HXT          | x                             |
  * |\ref QSPI1_MODULE   |\ref CLK_CLKSEL3_QSPI1SEL_PLL_DIV2     | x                             |
  * |\ref QSPI1_MODULE   |\ref CLK_CLKSEL3_QSPI1SEL_PCLK1        | x                             |
  * |\ref QSPI1_MODULE   |\ref CLK_CLKSEL3_QSPI1SEL_HIRC         | x                             |
  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_HXT           | x                             |
  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_PLL_DIV2      | x                             |
  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_PCLK0         | x                             |
  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_HIRC          | x                             |
  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_HIRC48M       | x                             |
  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_PLLFN_DIV2    | x                             |
  * |\ref I2S1_MODULE    |\ref CLK_CLKSEL2_I2S1SEL_HXT           |\ref CLK_CLKDIV2_I2S1(x)       |
  * |\ref I2S1_MODULE    |\ref CLK_CLKSEL2_I2S1SEL_PLL_DIV2      |\ref CLK_CLKDIV2_I2S1(x)       |
  * |\ref I2S1_MODULE    |\ref CLK_CLKSEL2_I2S1SEL_PCLK1         |\ref CLK_CLKDIV2_I2S1(x)       |
  * |\ref I2S1_MODULE    |\ref CLK_CLKSEL2_I2S1SEL_HIRC          |\ref CLK_CLKDIV2_I2S1(x)       |
  * |\ref I2S1_MODULE    |\ref CLK_CLKSEL2_I2S1SEL_HIRC48M       |\ref CLK_CLKDIV2_I2S1(x)       |
  * |\ref I2S1_MODULE    |\ref CLK_CLKSEL2_I2S1SEL_PLLFN_DIV2    |\ref CLK_CLKDIV2_I2S1(x)       |
  * |\ref UART8_MODULE   |\ref CLK_CLKSEL2_UART8SEL_HXT          |\ref CLK_CLKDIV5_UART8(x)      |
  * |\ref UART8_MODULE   |\ref CLK_CLKSEL2_UART8SEL_PLL_DIV2     |\ref CLK_CLKDIV5_UART8(x)      |
  * |\ref UART8_MODULE   |\ref CLK_CLKSEL2_UART8SEL_LXT          |\ref CLK_CLKDIV5_UART8(x)      |
  * |\ref UART8_MODULE   |\ref CLK_CLKSEL2_UART8SEL_HIRC         |\ref CLK_CLKDIV5_UART8(x)      |
  * |\ref UART9_MODULE   |\ref CLK_CLKSEL2_UART9SEL_HXT          |\ref CLK_CLKDIV5_UART9(x)      |
  * |\ref UART9_MODULE   |\ref CLK_CLKSEL2_UART9SEL_PLL_DIV2     |\ref CLK_CLKDIV5_UART9(x)      |
  * |\ref UART9_MODULE   |\ref CLK_CLKSEL2_UART9SEL_LXT          |\ref CLK_CLKDIV5_UART9(x)      |
  * |\ref UART9_MODULE   |\ref CLK_CLKSEL2_UART9SEL_HIRC         |\ref CLK_CLKDIV5_UART9(x)      |
  * |\ref TRNG_MODULE    |\ref CLK_CLKSEL2_TRNGSEL_LXT           | x                             |
  * |\ref TRNG_MODULE    |\ref CLK_CLKSEL2_TRNGSEL_LIRC          | x                             |
  * |\ref PSIO_MODULE    |\ref CLK_CLKSEL2_PSIOSEL_HXT           |\ref CLK_CLKDIV1_PSIO(x)       |
  * |\ref PSIO_MODULE    |\ref CLK_CLKSEL2_PSIOSEL_LXT           |\ref CLK_CLKDIV1_PSIO(x)       |
  * |\ref PSIO_MODULE    |\ref CLK_CLKSEL2_PSIOSEL_PCLK1         |\ref CLK_CLKDIV1_PSIO(x)       |
  * |\ref PSIO_MODULE    |\ref CLK_CLKSEL2_PSIOSEL_PLL_DIV2      |\ref CLK_CLKDIV1_PSIO(x)       |
  * |\ref PSIO_MODULE    |\ref CLK_CLKSEL2_PSIOSEL_LIRC          |\ref CLK_CLKDIV1_PSIO(x)       |
  * |\ref PSIO_MODULE    |\ref CLK_CLKSEL2_PSIOSEL_HIRC          |\ref CLK_CLKDIV1_PSIO(x)       |
  * |\ref SC0_MODULE     |\ref CLK_CLKSEL3_SC0SEL_HXT            |\ref CLK_CLKDIV1_SC0(x)        |
  * |\ref SC0_MODULE     |\ref CLK_CLKSEL3_SC0SEL_PLL_DIV2       |\ref CLK_CLKDIV1_SC0(x)        |
  * |\ref SC0_MODULE     |\ref CLK_CLKSEL3_SC0SEL_PCLK0          |\ref CLK_CLKDIV1_SC0(x)        |
  * |\ref SC0_MODULE     |\ref CLK_CLKSEL3_SC0SEL_HIRC           |\ref CLK_CLKDIV1_SC0(x)        |
  * |\ref SC1_MODULE     |\ref CLK_CLKSEL3_SC1SEL_HXT            |\ref CLK_CLKDIV1_SC1(x)        |
  * |\ref SC1_MODULE     |\ref CLK_CLKSEL3_SC1SEL_PLL_DIV2       |\ref CLK_CLKDIV1_SC1(x)        |
  * |\ref SC1_MODULE     |\ref CLK_CLKSEL3_SC1SEL_PCLK1          |\ref CLK_CLKDIV1_SC1(x)        |
  * |\ref SC1_MODULE     |\ref CLK_CLKSEL3_SC1SEL_HIRC           |\ref CLK_CLKDIV1_SC1(x)        |
  * |\ref SC2_MODULE     |\ref CLK_CLKSEL3_SC2SEL_HXT            |\ref CLK_CLKDIV1_SC2(x)        |
  * |\ref SC2_MODULE     |\ref CLK_CLKSEL3_SC2SEL_PLL_DIV2       |\ref CLK_CLKDIV1_SC2(x)        |
  * |\ref SC2_MODULE     |\ref CLK_CLKSEL3_SC2SEL_PCLK0          |\ref CLK_CLKDIV1_SC2(x)        |
  * |\ref SC2_MODULE     |\ref CLK_CLKSEL3_SC2SEL_HIRC           |\ref CLK_CLKDIV1_SC2(x)        |
  * |\ref KPI_MODULE     |\ref CLK_CLKSEL3_KPISEL_HXT            |\ref CLK_CLKDIV2_KPI(x)        |
  * |\ref KPI_MODULE     |\ref CLK_CLKSEL3_KPISEL_LIRC           |\ref CLK_CLKDIV2_KPI(x)        |
  * |\ref KPI_MODULE     |\ref CLK_CLKSEL3_KPISEL_HIRC           |\ref CLK_CLKDIV2_KPI(x)        |
  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL3_SPI2SEL_HXT           | x                             |
  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL3_SPI2SEL_PLL_DIV2      | x                             |
  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL3_SPI2SEL_PCLK1         | x                             |
  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL3_SPI2SEL_HIRC          | x                             |
  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL3_SPI2SEL_HIRC48M       | x                             |
  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL3_SPI2SEL_PLLFN_DIV2    | x                             |
  * |\ref SPI3_MODULE    |\ref CLK_CLKSEL3_SPI3SEL_HXT           | x                             |
  * |\ref SPI3_MODULE    |\ref CLK_CLKSEL3_SPI3SEL_PLL_DIV2      | x                             |
  * |\ref SPI3_MODULE    |\ref CLK_CLKSEL3_SPI3SEL_PCLK0         | x                             |
  * |\ref SPI3_MODULE    |\ref CLK_CLKSEL3_SPI3SEL_HIRC          | x                             |
  * |\ref SPI3_MODULE    |\ref CLK_CLKSEL3_SPI3SEL_HIRC48M       | x                             |
  * |\ref SPI3_MODULE    |\ref CLK_CLKSEL3_SPI3SEL_PLLFN_DIV2    | x                             |
  * |\ref I2S0_MODULE    |\ref CLK_CLKSEL3_I2S0SEL_HXT           |\ref CLK_CLKDIV2_I2S0(x)       |
  * |\ref I2S0_MODULE    |\ref CLK_CLKSEL3_I2S0SEL_PLL_DIV2      |\ref CLK_CLKDIV2_I2S0(x)       |
  * |\ref I2S0_MODULE    |\ref CLK_CLKSEL3_I2S0SEL_PCLK0         |\ref CLK_CLKDIV2_I2S0(x)       |
  * |\ref I2S0_MODULE    |\ref CLK_CLKSEL3_I2S0SEL_HIRC          |\ref CLK_CLKDIV2_I2S0(x)       |
  * |\ref I2S0_MODULE    |\ref CLK_CLKSEL3_I2S0SEL_HIRC48M       |\ref CLK_CLKDIV2_I2S0(x)       |
  * |\ref I2S0_MODULE    |\ref CLK_CLKSEL3_I2S0SEL_PLLFN_DIV2    |\ref CLK_CLKDIV2_I2S0(x)       |
  * |\ref UART6_MODULE   |\ref CLK_CLKSEL3_UART6SEL_HXT          |\ref CLK_CLKDIV4_UART6(x)      |
  * |\ref UART6_MODULE   |\ref CLK_CLKSEL3_UART6SEL_PLL_DIV2     |\ref CLK_CLKDIV4_UART6(x)      |
  * |\ref UART6_MODULE   |\ref CLK_CLKSEL3_UART6SEL_LXT          |\ref CLK_CLKDIV4_UART6(x)      |
  * |\ref UART6_MODULE   |\ref CLK_CLKSEL3_UART6SEL_HIRC         |\ref CLK_CLKDIV4_UART6(x)      |
  * |\ref UART7_MODULE   |\ref CLK_CLKSEL3_UART7SEL_HXT          |\ref CLK_CLKDIV4_UART7(x)      |
  * |\ref UART7_MODULE   |\ref CLK_CLKSEL3_UART7SEL_PLL_DIV2     |\ref CLK_CLKDIV4_UART7(x)      |
  * |\ref UART7_MODULE   |\ref CLK_CLKSEL3_UART7SEL_LXT          |\ref CLK_CLKDIV4_UART7(x)      |
  * |\ref UART7_MODULE   |\ref CLK_CLKSEL3_UART7SEL_HIRC         |\ref CLK_CLKDIV4_UART7(x)      |
  * |\ref UART2_MODULE   |\ref CLK_CLKSEL3_UART2SEL_HXT          |\ref CLK_CLKDIV4_UART2(x)      |
  * |\ref UART2_MODULE   |\ref CLK_CLKSEL3_UART2SEL_PLL_DIV2     |\ref CLK_CLKDIV4_UART2(x)      |
  * |\ref UART2_MODULE   |\ref CLK_CLKSEL3_UART2SEL_LXT          |\ref CLK_CLKDIV4_UART2(x)      |
  * |\ref UART2_MODULE   |\ref CLK_CLKSEL3_UART2SEL_HIRC         |\ref CLK_CLKDIV4_UART2(x)      |
  * |\ref UART3_MODULE   |\ref CLK_CLKSEL3_UART3SEL_HXT          |\ref CLK_CLKDIV4_UART3(x)      |
  * |\ref UART3_MODULE   |\ref CLK_CLKSEL3_UART3SEL_PLL_DIV2     |\ref CLK_CLKDIV4_UART3(x)      |
  * |\ref UART3_MODULE   |\ref CLK_CLKSEL3_UART3SEL_LXT          |\ref CLK_CLKDIV4_UART3(x)      |
  * |\ref UART3_MODULE   |\ref CLK_CLKSEL3_UART3SEL_HIRC         |\ref CLK_CLKDIV4_UART3(x)      |
  * |\ref UART4_MODULE   |\ref CLK_CLKSEL3_UART4SEL_HXT          |\ref CLK_CLKDIV4_UART4(x)      |
  * |\ref UART4_MODULE   |\ref CLK_CLKSEL3_UART4SEL_PLL_DIV2     |\ref CLK_CLKDIV4_UART4(x)      |
  * |\ref UART4_MODULE   |\ref CLK_CLKSEL3_UART4SEL_LXT          |\ref CLK_CLKDIV4_UART4(x)      |
  * |\ref UART4_MODULE   |\ref CLK_CLKSEL3_UART4SEL_HIRC         |\ref CLK_CLKDIV4_UART4(x)      |
  * |\ref UART5_MODULE   |\ref CLK_CLKSEL3_UART5SEL_HXT          |\ref CLK_CLKDIV4_UART5(x)      |
  * |\ref UART5_MODULE   |\ref CLK_CLKSEL3_UART5SEL_PLL_DIV2     |\ref CLK_CLKDIV4_UART5(x)      |
  * |\ref UART5_MODULE   |\ref CLK_CLKSEL3_UART5SEL_LXT          |\ref CLK_CLKDIV4_UART5(x)      |
  * |\ref UART5_MODULE   |\ref CLK_CLKSEL3_UART5SEL_HIRC         |\ref CLK_CLKDIV4_UART5(x)      |
  * |\ref RTC_MODULE     |\ref RTC_LXTCTL_RTCCKSEL_LXT           | x                             |
  * |\ref RTC_MODULE     |\ref RTC_LXTCTL_RTCCKSEL_LIRC          | x                             |
  * |\ref SPI4_MODULE    |\ref CLK_CLKSEL4_SPI4SEL_HXT           | x                             |
  * |\ref SPI4_MODULE    |\ref CLK_CLKSEL4_SPI4SEL_PLL_DIV2      | x                             |
  * |\ref SPI4_MODULE    |\ref CLK_CLKSEL4_SPI4SEL_PCLK1         | x                             |
  * |\ref SPI4_MODULE    |\ref CLK_CLKSEL4_SPI4SEL_HIRC          | x                             |
  * |\ref SPI5_MODULE    |\ref CLK_CLKSEL4_SPI5SEL_HXT           | x                             |
  * |\ref SPI5_MODULE    |\ref CLK_CLKSEL4_SPI5SEL_PLL_DIV2      | x                             |
  * |\ref SPI5_MODULE    |\ref CLK_CLKSEL4_SPI5SEL_PCLK0         | x                             |
  * |\ref SPI5_MODULE    |\ref CLK_CLKSEL4_SPI5SEL_HIRC          | x                             |
  * |\ref SPI6_MODULE    |\ref CLK_CLKSEL4_SPI6SEL_HXT           | x                             |
  * |\ref SPI6_MODULE    |\ref CLK_CLKSEL4_SPI6SEL_PLL_DIV2      | x                             |
  * |\ref SPI6_MODULE    |\ref CLK_CLKSEL4_SPI6SEL_PCLK1         | x                             |
  * |\ref SPI6_MODULE    |\ref CLK_CLKSEL4_SPI6SEL_HIRC          | x                             |
  * |\ref SPI7_MODULE    |\ref CLK_CLKSEL4_SPI7SEL_HXT           | x                             |
  * |\ref SPI7_MODULE    |\ref CLK_CLKSEL4_SPI7SEL_PLL_DIV2      | x                             |
  * |\ref SPI7_MODULE    |\ref CLK_CLKSEL4_SPI7SEL_PCLK0         | x                             |
  * |\ref SPI7_MODULE    |\ref CLK_CLKSEL4_SPI7SEL_HIRC          | x                             |
  * |\ref SPI8_MODULE    |\ref CLK_CLKSEL4_SPI8SEL_HXT           | x                             |
  * |\ref SPI8_MODULE    |\ref CLK_CLKSEL4_SPI8SEL_PLL_DIV2      | x                             |
  * |\ref SPI8_MODULE    |\ref CLK_CLKSEL4_SPI8SEL_PCLK1         | x                             |
  * |\ref SPI8_MODULE    |\ref CLK_CLKSEL4_SPI8SEL_HIRC          | x                             |
  * |\ref SPI9_MODULE    |\ref CLK_CLKSEL4_SPI9SEL_HXT           | x                             |
  * |\ref SPI9_MODULE    |\ref CLK_CLKSEL4_SPI9SEL_PLL_DIV2      | x                             |
  * |\ref SPI9_MODULE    |\ref CLK_CLKSEL4_SPI9SEL_PCLK0         | x                             |
  * |\ref SPI9_MODULE    |\ref CLK_CLKSEL4_SPI9SEL_HIRC          | x                             |
  * |\ref SPI10_MODULE   |\ref CLK_CLKSEL4_SPI10SEL_HXT          | x                             |
  * |\ref SPI10_MODULE   |\ref CLK_CLKSEL4_SPI10SEL_PLL_DIV2     | x                             |
  * |\ref SPI10_MODULE   |\ref CLK_CLKSEL4_SPI10SEL_PCLK1        | x                             |
  * |\ref SPI10_MODULE   |\ref CLK_CLKSEL4_SPI10SEL_HIRC         | x                             |
  *
  */
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
{
    uint32_t u32Sel = 0UL, u32Div = 0UL;
    uint32_t au32SelTbl[5] = {0x0UL, 0x4UL, 0x8UL, 0xCUL, 0x4CUL};       /* CLK_CLKSEL0~4 */
    uint32_t au32DivTbl[6] = {0x0UL, 0x4UL, 0x8UL, 0xCUL, 0x10UL, 0x1C}; /* CLK_CLKDIV0~5 */
    uint32_t u32RTCCKEN = CLK->APBCLK0 & CLK_APBCLK0_RTCCKEN_Msk;

    if(u32ModuleIdx == RTC_MODULE)      /* RTC clock source configuration */
    {
        if(u32RTCCKEN == 0UL)
        {
            CLK->APBCLK0 |= CLK_APBCLK0_RTCCKEN_Msk; /* Enable RTC clock to get LXT clock source */
        }

        /* Select RTC clock source */
        RTC->LXTCTL = (RTC->LXTCTL & (~RTC_LXTCTL_RTCCKSEL_Msk)) | (u32ClkSrc);

        if(u32RTCCKEN == 0UL)
        {
            CLK->APBCLK0 &= (~CLK_APBCLK0_RTCCKEN_Msk); /* Disable RTC clock if it is disabled before */
        }
    }
    else /* Others clock source configuration */
    {
        /* Configure clock source divider */
        switch(u32ModuleIdx)
        {
            /* For 8 bits divider */
            case EADC0_MODULE:
                CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_EADC0DIV_Msk)) | (u32ClkDiv);
                break;
            case SDH0_MODULE:
                CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_SDH0DIV_Msk)) | (u32ClkDiv);
                break;
            case SC0_MODULE:
                CLK->CLKDIV1 = (CLK->CLKDIV1 & (~CLK_CLKDIV1_SC0DIV_Msk)) | (u32ClkDiv);
                break;
            case SC1_MODULE:
                CLK->CLKDIV1 = (CLK->CLKDIV1 & (~CLK_CLKDIV1_SC1DIV_Msk)) | (u32ClkDiv);
                break;
            case SC2_MODULE:
                CLK->CLKDIV1 = (CLK->CLKDIV1 & (~CLK_CLKDIV1_SC2DIV_Msk)) | (u32ClkDiv);
                break;
            case PSIO_MODULE:
                CLK->CLKDIV1 = (CLK->CLKDIV1 & (~CLK_CLKDIV1_PSIODIV_Msk)) | (u32ClkDiv);
                break;
            case KPI_MODULE:
                CLK->CLKDIV2 = (CLK->CLKDIV2 & (~CLK_CLKDIV2_KPIDIV_Msk)) | (u32ClkDiv);
                break;
            case EADC1_MODULE:
                CLK->CLKDIV2 = (CLK->CLKDIV2 & (~CLK_CLKDIV2_EADC1DIV_Msk)) | (u32ClkDiv);
                break;
            case SEN_MODULE:
                CLK->CLKDIV3 = (CLK->CLKDIV3 & (~CLK_CLKDIV3_VSENSEDIV_Msk)) | (u32ClkDiv);
                break;
            case SDH1_MODULE:
                CLK->CLKDIV3 = (CLK->CLKDIV3 & (~CLK_CLKDIV3_SDH1DIV_Msk)) | (u32ClkDiv);
                break;
            case EADC2_MODULE:
                CLK->CLKDIV5 = (CLK->CLKDIV5 & (~CLK_CLKDIV5_EADC2DIV_Msk)) | (u32ClkDiv);
                break;

            /* Others */
            default:
            {
                if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk)
                {
                    /* Get clock divider control register address */
                    u32Div = (uint32_t)&CLK->CLKDIV0 + (au32DivTbl[MODULE_CLKDIV(u32ModuleIdx)]);
                    /* Apply new divider */
                    M32(u32Div) = (M32(u32Div) & (~(MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx)))) | u32ClkDiv;
                }
            }
            break;
        }

        /* Configure clock source */
        if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
        {
            /* Get clock select control register address */
            u32Sel = (uint32_t)&CLK->CLKSEL0 + (au32SelTbl[MODULE_CLKSEL(u32ModuleIdx)]);
            /* Set new clock selection setting */
            M32(u32Sel) = (M32(u32Sel) & (~(MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx)))) | u32ClkSrc;
        }
    }

}

/**
  * @brief      Set SysTick clock source
  * @param[in]  u32ClkSrc is module clock source. Including:
  *             - \ref CLK_CLKSEL0_STCLKSEL_HXT
  *             - \ref CLK_CLKSEL0_STCLKSEL_LXT
  *             - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2
  *             - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
  *             - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
  * @return     None
  * @details    This function set SysTick clock source. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
{
    CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
}

/**
  * @brief      Enable clock source
  * @param[in]  u32ClkMask is clock source mask. Including :
  *             - \ref CLK_PWRCTL_HXTEN_Msk
  *             - \ref CLK_PWRCTL_LXTEN_Msk
  *             - \ref CLK_PWRCTL_HIRCEN_Msk
  *             - \ref CLK_PWRCTL_LIRCEN_Msk
  *             - \ref CLK_PWRCTL_HIRC48MEN_Msk
  * @return     None
  * @details    This function enable clock source. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_EnableXtalRC(uint32_t u32ClkMask)
{
    CLK->PWRCTL |= u32ClkMask;
}

/**
  * @brief      Disable clock source
  * @param[in]  u32ClkMask is clock source mask. Including :
  *             - \ref CLK_PWRCTL_HXTEN_Msk
  *             - \ref CLK_PWRCTL_LXTEN_Msk
  *             - \ref CLK_PWRCTL_HIRCEN_Msk
  *             - \ref CLK_PWRCTL_LIRCEN_Msk
  *             - \ref CLK_PWRCTL_HIRC48MEN_Msk
  * @return     None
  * @details    This function disable clock source. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_DisableXtalRC(uint32_t u32ClkMask)
{
    CLK->PWRCTL &= ~u32ClkMask;
}

/**
  * @brief      Enable module clock
  * @param[in]  u32ModuleIdx is module index. Including :
  *             - \ref PDMA0_MODULE
  *             - \ref PDMA1_MODULE
  *             - \ref ISP_MODULE
  *             - \ref EBI_MODULE
  *             - \ref ST_MODULE
  *             - \ref EMAC0_MODULE
  *             - \ref SDH0_MODULE
  *             - \ref SDH1_MODULE
  *             - \ref CRC_MODULE
  *             - \ref CCAP_MODULE
  *             - \ref SEN_MODULE
  *             - \ref HSUSBD_MODULE
  *             - \ref HSOTG_MODULE
  *             - \ref HBI_MODULE
  *             - \ref CRPT_MODULE
  *             - \ref KS_MODULE
  *             - \ref SPIM_MODULE
  *             - \ref FMCIDLE_MODULE
  *             - \ref USBH_MODULE
  *             - \ref OTG_MODULE
  *             - \ref USBD_MODULE
  *             - \ref TRACE_MODULE
  *             - \ref GPA_MODULE
  *             - \ref GPB_MODULE
  *             - \ref GPC_MODULE
  *             - \ref GPD_MODULE
  *             - \ref GPE_MODULE
  *             - \ref GPF_MODULE
  *             - \ref GPG_MODULE
  *             - \ref GPH_MODULE
  *             - \ref GPI_MODULE
  *             - \ref GPJ_MODULE
  *             - \ref CANFD0_MODULE
  *             - \ref CANFD1_MODULE
  *             - \ref CANFD2_MODULE
  *             - \ref CANFD3_MODULE
  *             - \ref WDT_MODULE
  *             - \ref WWDT_MODULE
  *             - \ref RTC_MODULE
  *             - \ref TMR0_MODULE
  *             - \ref TMR1_MODULE
  *             - \ref TMR2_MODULE
  *             - \ref TMR3_MODULE
  *             - \ref CLKO_MODULE
  *             - \ref ACMP01_MODULE
  *             - \ref ACMP23_MODULE
  *             - \ref I2C0_MODULE
  *             - \ref I2C1_MODULE
  *             - \ref I2C2_MODULE
  *             - \ref I2C3_MODULE
  *             - \ref I2C4_MODULE
  *             - \ref QSPI0_MODULE
  *             - \ref QSPI1_MODULE
  *             - \ref SPI0_MODULE
  *             - \ref SPI1_MODULE
  *             - \ref SPI2_MODULE
  *             - \ref SPI3_MODULE
  *             - \ref SPI4_MODULE
  *             - \ref SPI5_MODULE
  *             - \ref SPI6_MODULE
  *             - \ref SPI7_MODULE
  *             - \ref SPI8_MODULE
  *             - \ref SPI9_MODULE
  *             - \ref SPI10_MODULE
  *             - \ref UART0_MODULE
  *             - \ref UART1_MODULE
  *             - \ref UART2_MODULE
  *             - \ref UART3_MODULE
  *             - \ref UART4_MODULE
  *             - \ref UART5_MODULE
  *             - \ref UART6_MODULE
  *             - \ref UART7_MODULE
  *             - \ref UART8_MODULE
  *             - \ref UART9_MODULE
  *             - \ref EADC0_MODULE
  *             - \ref EADC1_MODULE
  *             - \ref EADC2_MODULE
  *             - \ref I2S0_MODULE
  *             - \ref I2S1_MODULE
  *             - \ref SC0_MODULE
  *             - \ref SC1_MODULE
  *             - \ref SC2_MODULE
  *             - \ref USCI0_MODULE
  *             - \ref PSIO_MODULE
  *             - \ref DAC_MODULE
  *             - \ref EPWM0_MODULE
  *             - \ref EPWM1_MODULE
  *             - \ref BPWM0_MODULE
  *             - \ref BPWM1_MODULE
  *             - \ref EQEI0_MODULE
  *             - \ref EQEI1_MODULE
  *             - \ref EQEI2_MODULE
  *             - \ref EQEI3_MODULE
  *             - \ref TRNG_MODULE
  *             - \ref ECAP0_MODULE
  *             - \ref ECAP1_MODULE
  *             - \ref ECAP2_MODULE
  *             - \ref ECAP3_MODULE
  *             - \ref TRNG_MODULE
  *             - \ref KPI_MODULE
  * @return     None
  * @details    This function is used to enable module clock.
  */
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
{
    uint32_t u32TmpVal = 0UL, u32TmpAddr = 0UL;

    /* Index, 0x0:AHBCLK0, 0x1:APBCLK0, 0x2:APBCLK1, 0x3:APBCLK2, 0x4:AHBCLK1 */
    uint32_t au32ClkEnTbl[5] = {0x0UL, 0x4UL, 0x8UL, 0x34UL, 0x54UL};

    u32TmpVal = (1UL << MODULE_IP_EN_Pos(u32ModuleIdx));
    u32TmpAddr = (uint32_t)&CLK->AHBCLK0 + au32ClkEnTbl[MODULE_APBCLK(u32ModuleIdx)];

    *(volatile uint32_t *)u32TmpAddr |= u32TmpVal;
}

/**
  * @brief      Disable module clock
  * @param[in]  u32ModuleIdx is module index. Including :
  *             - \ref PDMA0_MODULE
  *             - \ref PDMA1_MODULE
  *             - \ref ISP_MODULE
  *             - \ref EBI_MODULE
  *             - \ref ST_MODULE
  *             - \ref EMAC0_MODULE
  *             - \ref SDH0_MODULE
  *             - \ref SDH1_MODULE
  *             - \ref CRC_MODULE
  *             - \ref CCAP_MODULE
  *             - \ref SEN_MODULE
  *             - \ref HSUSBD_MODULE
  *             - \ref HSOTG_MODULE
  *             - \ref HBI_MODULE
  *             - \ref CRPT_MODULE
  *             - \ref KS_MODULE
  *             - \ref SPIM_MODULE
  *             - \ref FMCIDLE_MODULE
  *             - \ref USBH_MODULE
  *             - \ref OTG_MODULE
  *             - \ref USBD_MODULE
  *             - \ref TRACE_MODULE
  *             - \ref GPA_MODULE
  *             - \ref GPB_MODULE
  *             - \ref GPC_MODULE
  *             - \ref GPD_MODULE
  *             - \ref GPE_MODULE
  *             - \ref GPF_MODULE
  *             - \ref GPG_MODULE
  *             - \ref GPH_MODULE
  *             - \ref GPI_MODULE
  *             - \ref GPJ_MODULE
  *             - \ref CANFD0_MODULE
  *             - \ref CANFD1_MODULE
  *             - \ref CANFD2_MODULE
  *             - \ref CANFD3_MODULE
  *             - \ref WDT_MODULE
  *             - \ref WWDT_MODULE
  *             - \ref RTC_MODULE
  *             - \ref TMR0_MODULE
  *             - \ref TMR1_MODULE
  *             - \ref TMR2_MODULE
  *             - \ref TMR3_MODULE
  *             - \ref CLKO_MODULE
  *             - \ref ACMP01_MODULE
  *             - \ref ACMP23_MODULE
  *             - \ref I2C0_MODULE
  *             - \ref I2C1_MODULE
  *             - \ref I2C2_MODULE
  *             - \ref I2C3_MODULE
  *             - \ref I2C4_MODULE
  *             - \ref QSPI0_MODULE
  *             - \ref QSPI1_MODULE
  *             - \ref SPI0_MODULE
  *             - \ref SPI1_MODULE
  *             - \ref SPI2_MODULE
  *             - \ref SPI3_MODULE
  *             - \ref SPI4_MODULE
  *             - \ref SPI5_MODULE
  *             - \ref SPI6_MODULE
  *             - \ref SPI7_MODULE
  *             - \ref SPI8_MODULE
  *             - \ref SPI9_MODULE
  *             - \ref SPI10_MODULE
  *             - \ref UART0_MODULE
  *             - \ref UART1_MODULE
  *             - \ref UART2_MODULE
  *             - \ref UART3_MODULE
  *             - \ref UART4_MODULE
  *             - \ref UART5_MODULE
  *             - \ref UART6_MODULE
  *             - \ref UART7_MODULE
  *             - \ref UART8_MODULE
  *             - \ref UART9_MODULE
  *             - \ref EADC0_MODULE
  *             - \ref EADC1_MODULE
  *             - \ref EADC2_MODULE
  *             - \ref I2S0_MODULE
  *             - \ref I2S1_MODULE
  *             - \ref SC0_MODULE
  *             - \ref SC1_MODULE
  *             - \ref SC2_MODULE
  *             - \ref USCI0_MODULE
  *             - \ref PSIO_MODULE
  *             - \ref DAC_MODULE
  *             - \ref EPWM0_MODULE
  *             - \ref EPWM1_MODULE
  *             - \ref BPWM0_MODULE
  *             - \ref BPWM1_MODULE
  *             - \ref EQEI0_MODULE
  *             - \ref EQEI1_MODULE
  *             - \ref EQEI2_MODULE
  *             - \ref EQEI3_MODULE
  *             - \ref TRNG_MODULE
  *             - \ref ECAP0_MODULE
  *             - \ref ECAP1_MODULE
  *             - \ref ECAP2_MODULE
  *             - \ref ECAP3_MODULE
  *             - \ref TRNG_MODULE
  *             - \ref KPI_MODULE
  * @return     None
  * @details    This function is used to disable module clock.
  */
void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
{
    uint32_t u32TmpVal = 0UL, u32TmpAddr = 0UL;

    /* Index, 0x0:AHBCLK0, 0x1:APBCLK0, 0x2:APBCLK1, 0x3:APBCLK2, 0x4:AHBCLK1 */
    uint32_t au32ClkEnTbl[5] = {0x0UL, 0x4UL, 0x8UL, 0x34UL, 0x54UL};

    u32TmpVal = ~(1UL << MODULE_IP_EN_Pos(u32ModuleIdx));
    u32TmpAddr = (uint32_t)&CLK->AHBCLK0 + au32ClkEnTbl[MODULE_APBCLK(u32ModuleIdx)];

    *(uint32_t *)u32TmpAddr &= u32TmpVal;
}


/**
  * @brief      Set PLL frequency
  * @param[in]  u32PllClkSrc is PLL clock source. Including :
  *             - \ref CLK_PLLCTL_PLLSRC_HXT
  *             - \ref CLK_PLLCTL_PLLSRC_HIRC
  * @param[in]  u32PllFreq is PLL frequency. The range of u32PllFreq is 50 MHz ~ 500 MHz.
  * @return     PLL frequency
  * @details    This function is used to configure CLK_PLLCTL register to set specified PLL frequency. \n
  *             The register write-protection function should be disabled before using this function.
  */
uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
{
    uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32PllClk;
    uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR;

    /* Check if HCLK is PLL before configure PLL */
    if((CLK->CLKSEL0 & CLK_CLKSEL0_HCLKSEL_Msk) == CLK_CLKSEL0_HCLKSEL_PLL)
    {
        /* Return PLL frequency directly if HCLK is PLL */
        return CLK_GetPLLClockFreq();
    }
    else
    {
        /* Disable PLL first to avoid unstable when setting PLL */
        CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
    }

    /* PLL source clock is from HXT */
    if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
    {
        /* Enable HXT clock */
        CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;

        /* Wait for HXT clock ready */
        CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);

        /* Select PLL source clock from HXT */
        u32PllSrcClk = __HXT;
    }

    /* PLL source clock is from HIRC */
    else
    {
        /* Enable HIRC clock */
        CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;

        /* Wait for HIRC clock ready */
        CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

        /* Select PLL source clock from HIRC */
        u32PllSrcClk = __HIRC;
    }

    /* Check PLL frequency range */
    /* Constraint 1: 50MHz < FOUT < 500MHz */
    if((u32PllFreq <= FREQ_500MHZ) && (u32PllFreq >= FREQ_50MHZ))
    {
        /* Select "NO" according to request frequency */
        if((u32PllFreq < FREQ_100MHZ) && (u32PllFreq >= FREQ_50MHZ))
        {
            u32NO = 3UL;
            u32PllFreq = u32PllFreq << 2;
        }
        else if((u32PllFreq < FREQ_200MHZ) && (u32PllFreq >= FREQ_100MHZ))
        {
            u32NO = 1UL;
            u32PllFreq = u32PllFreq << 1;
        }
        else
        {
            u32NO = 0UL;
        }

        /* Find best solution */
        u32Min = (uint32_t) - 1;    /* initial u32Min to max value of uint32_t (0xFFFFFFFF) */
        u32MinNR = 0UL;
        u32MinNF = 0UL;

        for(u32NR = 1UL; u32NR <= 32UL; u32NR++)   /* NR = 1~32 since NR = INDIV+1 and INDIV = 0~31 */
        {
            u32Tmp = u32PllSrcClk / u32NR;                      /* FREF = FIN/NR */
            if((u32Tmp >= FREQ_4MHZ) && (u32Tmp <= FREQ_8MHZ))  /* Constraint 2: 4MHz < FREF < 8MHz. */
            {
                for(u32NF = 2UL; u32NF <= 100UL; u32NF++)       /* NF = 2~513 since NF = FBDIV+2 and FBDIV = 0~511 */
                                                                /* max NF = 100 to avoid calculation overflow */
                {
                    u32Tmp2 = (u32Tmp * u32NF) << 1;                            /* FVCO = FREF*2*NF */
                    if((u32Tmp2 >= FREQ_200MHZ) && (u32Tmp2 <= FREQ_500MHZ))    /* Constraint 3: 200MHz < FVCO < 500MHz */
                    {
                        u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
                        if(u32Tmp3 < u32Min)
                        {
                            u32Min = u32Tmp3;
                            u32MinNR = u32NR;
                            u32MinNF = u32NF;

                            /* Break when get good results */
                            if(u32Min == 0UL)
                            {
                                break;
                            }
                        }
                    }
                }
            }
        }

        /* Enable and apply new PLL setting. */
        CLK->PLLCTL = u32PllClkSrc |
                      (u32NO << CLK_PLLCTL_OUTDIV_Pos) |
                      ((u32MinNR - 1UL) << CLK_PLLCTL_INDIV_Pos) |
                      ((u32MinNF - 2UL) << CLK_PLLCTL_FBDIV_Pos);

        /* Actual PLL output clock frequency. FOUT = (FIN/NR)*2*NF*(1/NO) */
        u32PllClk = u32PllSrcClk / ((u32NO + 1UL) * u32MinNR) * (u32MinNF << 1);
    }
    else
    {
        if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
        {

            /* Apply default PLL setting and return */
            CLK->PLLCTL = CLK_PLLCTL_192MHz_HXT;

            /* Actual PLL output clock frequency */
            u32PllClk = FREQ_192MHZ;
        }
        else
        {
            /* Apply default PLL setting and return */
            CLK->PLLCTL = CLK_PLLCTL_192MHz_HIRC;

            /* Actual PLL output clock frequency */
            u32PllClk = FREQ_192MHZ;
        }
    }

    if(u32PllClk != 0)
    {
        /* Wait for PLL clock stable */
        CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
    }

    /* Return actual PLL output clock frequency */
    return u32PllClk;
}


/**
  * @brief      Disable PLL
  * @param      None
  * @return     None
  * @details    This function set PLL in Power-down mode. It is skipped if HCLK is selected as PLL. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_DisablePLL(void)
{
    if((CLK->CLKSEL0 & CLK_CLKSEL0_HCLKSEL_Msk) != CLK_CLKSEL0_HCLKSEL_PLL)
        CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
}


/**
  * @brief      This function check selected clock source status
  * @param[in]  u32ClkMask is selected clock source. Including :
  *             - \ref CLK_STATUS_HXTSTB_Msk
  *             - \ref CLK_STATUS_LXTSTB_Msk
  *             - \ref CLK_STATUS_HIRCSTB_Msk
  *             - \ref CLK_STATUS_LIRCSTB_Msk
  *             - \ref CLK_STATUS_PLLSTB_Msk
  *             - \ref CLK_STATUS_PLLFNSTB_Msk
  *             - \ref CLK_STATUS_HIRC48MSTB_Msk
  * @retval     0  clock is not stable
  * @retval     1  clock is stable
  * @details    To wait for clock ready by specified clock source stable flag or timeout (>500ms)
  */
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
{
    uint32_t u32TimeOutCnt = SystemCoreClock >> 1; /* 500ms time-out */
    uint32_t u32Ret = 1U;

    while((CLK->STATUS & u32ClkMask) != u32ClkMask)
    {
        if(--u32TimeOutCnt == 0)
        {
            u32Ret = 0U;
            break;
        }
    }

    return u32Ret;
}

/**
  * @brief      Enable System Tick counter
  * @param[in]  u32ClkSrc is System Tick clock source. Including:
  *             - \ref CLK_CLKSEL0_STCLKSEL_HXT
  *             - \ref CLK_CLKSEL0_STCLKSEL_LXT
  *             - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2
  *             - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
  *             - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
  *             - \ref CLK_CLKSEL0_STCLKSEL_HCLK
  * @param[in]  u32Count is System Tick reload value. It could be 0~0xFFFFFF.
  * @return     None
  * @details    This function set System Tick clock source, reload value, enable System Tick counter and interrupt. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
{
    /* Set System Tick counter disabled */
    SysTick->CTRL = 0UL;

    /* Set System Tick clock source */
    if(u32ClkSrc == CLK_CLKSEL0_STCLKSEL_HCLK)
    {
        /* Disable System Tick clock source from external reference clock */
        CLK->AHBCLK0 &= ~CLK_AHBCLK0_STCKEN_Msk;

        /* Select System Tick clock source from core clock */
        SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
    }
    else
    {
        /* Enable System Tick clock source from external reference clock */
        CLK->AHBCLK0 |= CLK_AHBCLK0_STCKEN_Msk;

        /* Select System Tick external reference clock source */
        CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;

        /* Select System Tick clock source from external reference clock */
        SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;
    }

    /* Set System Tick reload value */
    SysTick->LOAD = u32Count;

    /* Clear System Tick current value and counter flag */
    SysTick->VAL = 0UL;

    /* Set System Tick interrupt enabled and counter enabled */
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}

/**
  * @brief      Disable System Tick counter
  * @param      None
  * @return     None
  * @details    This function disable System Tick counter.
  */
void CLK_DisableSysTick(void)
{
    /* Set System Tick counter disabled */
    SysTick->CTRL = 0UL;
}


/**
  * @brief      Power-down mode selected
  * @param[in]  u32PDMode is power down mode index. Including :
  *             - \ref CLK_PMUCTL_PDMSEL_PD
  *             - \ref CLK_PMUCTL_PDMSEL_LLPD
  *             - \ref CLK_PMUCTL_PDMSEL_FWPD
  *             - \ref CLK_PMUCTL_PDMSEL_SPD
  *             - \ref CLK_PMUCTL_PDMSEL_DPD
  * @return     None
  * @details    This function is used to set power-down mode.
  *             The register write-protection function should be disabled before using this function.
  */

void CLK_SetPowerDownMode(uint32_t u32PDMode)
{
    CLK->PMUCTL = (CLK->PMUCTL & ~(CLK_PMUCTL_PDMSEL_Msk)) | u32PDMode;
}


/**
 * @brief       Set Wake-up pin trigger type at Deep Power down mode
 *
 * @param[in]   u32TriggerType Wake-up pin trigger type
 *              - \ref CLK_DPDWKPIN_RISING
 *              - \ref CLK_DPDWKPIN_FALLING
 *              - \ref CLK_DPDWKPIN_BOTHEDGE
 *              - \ref CLK_DPDWKPIN1_RISING
 *              - \ref CLK_DPDWKPIN1_FALLING
 *              - \ref CLK_DPDWKPIN1_BOTHEDGE
 *              - \ref CLK_DPDWKPIN2_RISING
 *              - \ref CLK_DPDWKPIN2_FALLING
 *              - \ref CLK_DPDWKPIN2_BOTHEDGE
 *              - \ref CLK_DPDWKPIN3_RISING
 *              - \ref CLK_DPDWKPIN3_FALLING
 *              - \ref CLK_DPDWKPIN3_BOTHEDGE
 *              - \ref CLK_DPDWKPIN4_RISING
 *              - \ref CLK_DPDWKPIN4_FALLING
 *              - \ref CLK_DPDWKPIN4_BOTHEDGE
 * @return      None
 *
 * @details     This function is used to enable Wake-up pin trigger type.
 *              The register write-protection function should be disabled before using this function.
 */

void CLK_EnableDPDWKPin(uint32_t u32TriggerType)
{
    uint32_t u32Pin1, u32Pin2, u32Pin3, u32Pin4;

    /* Get DPD wake-up pin configuration */
    u32Pin1 = ((u32TriggerType) & CLK_PMUCTL_WKPINEN1_Msk);
    u32Pin2 = ((u32TriggerType) & CLK_PMUCTL_WKPINEN2_Msk);
    u32Pin3 = ((u32TriggerType) & CLK_PMUCTL_WKPINEN3_Msk);
    u32Pin4 = ((u32TriggerType) & CLK_PMUCTL_WKPINEN4_Msk);

    /* Set DPD wake-up pin configuration */
    if(u32Pin1)
    {
        CLK->PMUCTL = (CLK->PMUCTL & ~(CLK_PMUCTL_WKPINEN1_Msk)) | u32TriggerType;
    }
    else if(u32Pin2)
    {
        CLK->PMUCTL = (CLK->PMUCTL & ~(CLK_PMUCTL_WKPINEN2_Msk)) | u32TriggerType;
    }
    else if(u32Pin3)
    {
        CLK->PMUCTL = (CLK->PMUCTL & ~(CLK_PMUCTL_WKPINEN3_Msk)) | u32TriggerType;
    }
    else if(u32Pin4)
    {
        CLK->PMUCTL = (CLK->PMUCTL & ~(CLK_PMUCTL_WKPINEN4_Msk)) | u32TriggerType;
    }
    else
    {
        CLK->PMUCTL = (CLK->PMUCTL & ~(CLK_PMUCTL_WKPINEN0_Msk)) | u32TriggerType;
    }

}

/**
 * @brief      Get power manager wake up source
 *
 * @param[in]   None
 * @return      None
 *
 * @details     This function get power manager wake up source.
 */

uint32_t CLK_GetPMUWKSrc(void)
{
    return (CLK->PMUSTS);
}

/**
 * @brief       Set specified GPIO as wake up source at Stand-by Power down mode
 *
 * @param[in]   u32Port GPIO port. It could be 0~3.
 * @param[in]   u32Pin  The pin of specified GPIO port. It could be 0 ~ 15.
 * @param[in]   u32TriggerType Wake-up pin trigger type
 *              - \ref CLK_SPDWKPIN_RISING
 *              - \ref CLK_SPDWKPIN_FALLING
 * @param[in]   u32DebounceEn Standby Power-down mode wake-up pin de-bounce function
 *              - \ref CLK_SPDWKPIN_DEBOUNCEEN
 *              - \ref CLK_SPDWKPIN_DEBOUNCEDIS
 * @return      None
 *
 * @details     This function is used to set specified GPIO as wake up source at Stand-by Power down mode.
 */
void CLK_EnableSPDWKPin(uint32_t u32Port, uint32_t u32Pin, uint32_t u32TriggerType, uint32_t u32DebounceEn)
{
    uint32_t u32tmpAddr = 0UL;
    uint32_t u32tmpVal = 0UL;

    /* GPx Stand-by Power-down Wake-up Pin Select */
    u32tmpAddr = (uint32_t)&CLK->PASWKCTL;
    u32tmpAddr += (0x4UL * u32Port);

    u32tmpVal = inpw((uint32_t *)u32tmpAddr);
    u32tmpVal = (u32tmpVal & ~(CLK_PASWKCTL_WKPSEL_Msk | CLK_PASWKCTL_PRWKEN_Msk | CLK_PASWKCTL_PFWKEN_Msk | CLK_PASWKCTL_DBEN_Msk | CLK_PASWKCTL_WKEN_Msk)) |
                (u32Pin << CLK_PASWKCTL_WKPSEL_Pos) | u32TriggerType | u32DebounceEn | CLK_SPDWKPIN_ENABLE;
    outpw((uint32_t *)u32tmpAddr, u32tmpVal);
}

/**
  * @brief      Get PLL clock frequency
  * @param      None
  * @return     PLL frequency
  * @details    This function get PLL frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetPLLClockFreq(void)
{
    uint32_t u32PllFreq = 0UL, u32PllReg;
    uint32_t u32FIN, u32NF, u32NR, u32NO;
    uint8_t au8NoTbl[4] = {1U, 2U, 2U, 4U};

    u32PllReg = CLK->PLLCTL;

    if(u32PllReg & (CLK_PLLCTL_PD_Msk | CLK_PLLCTL_OE_Msk))
    {
        u32PllFreq = 0UL;       /* PLL is in power down mode or fix low */
    }
    else                        /* PLL is in normal mode */
    {
        /* PLL source clock */
        if(u32PllReg & CLK_PLLCTL_PLLSRC_Msk)
        {
            u32FIN = __HIRC;    /* PLL source clock from HIRC */
        }
        else
        {
            u32FIN = __HXT;     /* PLL source clock from HXT */
        }

        /* Calculate PLL frequency */
        if(u32PllReg & CLK_PLLCTL_BP_Msk)
        {
            u32PllFreq = u32FIN;  /* PLL is in bypass mode */
        }
        else
        {
            /* PLL is output enabled in normal work mode */
            u32NO = au8NoTbl[((u32PllReg & CLK_PLLCTL_OUTDIV_Msk) >> CLK_PLLCTL_OUTDIV_Pos)];
            u32NF = ((u32PllReg & CLK_PLLCTL_FBDIV_Msk) >> CLK_PLLCTL_FBDIV_Pos) + 2UL;
            u32NR = ((u32PllReg & CLK_PLLCTL_INDIV_Msk) >> CLK_PLLCTL_INDIV_Pos) + 1UL;

            /* u32FIN is shifted 2 bits to avoid overflow */
            u32PllFreq = (((u32FIN >> 2) * (u32NF << 1)) / (u32NR * u32NO) << 2);
        }
    }

    return u32PllFreq;
}

/**
  * @brief      Get selected module clock source
  * @param[in]  u32ModuleIdx is module index.
  *             - \ref SDH0_MODULE
  *             - \ref SDH1_MODULE
  *             - \ref SEN_MODULE
  *             - \ref USBH_MODULE
  *             - \ref OTG_MODULE
  *             - \ref USBD_MODULE
  *             - \ref CANFD0_MODULE
  *             - \ref CANFD1_MODULE
  *             - \ref CANFD2_MODULE
  *             - \ref CANFD3_MODULE
  *             - \ref WDT_MODULE
  *             - \ref WWDT_MODULE
  *             - \ref RTC_MODULE
  *             - \ref TMR0_MODULE
  *             - \ref TMR1_MODULE
  *             - \ref TMR2_MODULE
  *             - \ref TMR3_MODULE
  *             - \ref CLKO_MODULE
  *             - \ref QSPI0_MODULE
  *             - \ref QSPI1_MODULE
  *             - \ref SPI0_MODULE
  *             - \ref SPI1_MODULE
  *             - \ref SPI2_MODULE
  *             - \ref SPI3_MODULE
  *             - \ref SPI4_MODULE
  *             - \ref SPI5_MODULE
  *             - \ref SPI6_MODULE
  *             - \ref SPI7_MODULE
  *             - \ref SPI8_MODULE
  *             - \ref SPI9_MODULE
  *             - \ref SPI10_MODULE
  *             - \ref UART0_MODULE
  *             - \ref UART1_MODULE
  *             - \ref UART2_MODULE
  *             - \ref UART3_MODULE
  *             - \ref UART4_MODULE
  *             - \ref UART5_MODULE
  *             - \ref UART6_MODULE
  *             - \ref UART7_MODULE
  *             - \ref UART8_MODULE
  *             - \ref UART9_MODULE
  *             - \ref EPWM0_MODULE
  *             - \ref EPWM1_MODULE
  *             - \ref BPWM0_MODULE
  *             - \ref BPWM1_MODULE
  *             - \ref EADC0_MODULE
  *             - \ref EADC1_MODULE
  *             - \ref EADC2_MODULE
  *             - \ref I2S0_MODULE
  *             - \ref I2S1_MODULE
  *             - \ref SC0_MODULE
  *             - \ref SC1_MODULE
  *             - \ref SC2_MODULE
  *             - \ref PSIO_MODULE
  *             - \ref TRNG_MODULE
  *             - \ref KPI_MODULE
  * @return     Selected module clock source setting
  * @details    This function get selected module clock source.
  */
uint32_t CLK_GetModuleClockSource(uint32_t u32ModuleIdx)
{
    uint32_t u32TmpVal = 0UL, u32TmpAddr = 0UL;
    uint32_t au32SelTbl[5] = {0x0UL, 0x4UL, 0x8UL, 0xCUL, 0x4CUL}; /* CLK_CLKSEL0~4 */
    uint32_t u32RTCCKEN = CLK->APBCLK0 & CLK_APBCLK0_RTCCKEN_Msk;

    /* Get clock source selection setting */
    if(u32ModuleIdx == RTC_MODULE)
    {
        if(u32RTCCKEN == 0UL)
        {
            /* Enable RTC clock to get LXT clock source */
            CLK->APBCLK0 |= CLK_APBCLK0_RTCCKEN_Msk;
        }

        u32TmpVal = ((RTC->LXTCTL & RTC_LXTCTL_RTCCKSEL_Msk) >> RTC_LXTCTL_RTCCKSEL_Pos);

        if(u32RTCCKEN == 0UL)
        {
            /* Disable RTC clock if it is disabled before */
            CLK->APBCLK0 &= (~CLK_APBCLK0_RTCCKEN_Msk);
        }

    }
    else if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
    {
        /* Get clock select control register address */
        u32TmpAddr = (uint32_t)&CLK->CLKSEL0 + (au32SelTbl[MODULE_CLKSEL(u32ModuleIdx)]);

        /* Get clock source selection setting */
        u32TmpVal = ((inpw((uint32_t *)u32TmpAddr) & (MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx))) >> MODULE_CLKSEL_Pos(u32ModuleIdx));
    }

    return u32TmpVal;

}

/**
  * @brief      Get selected module clock divider number
  * @param[in]  u32ModuleIdx is module index.
  *             - \ref SDH0_MODULE
  *             - \ref SDH1_MODULE
  *             - \ref SEN_MODULE
  *             - \ref USBH_MODULE
  *             - \ref OTG_MODULE
  *             - \ref USBD_MODULE
  *             - \ref CANFD0_MODULE
  *             - \ref CANFD1_MODULE
  *             - \ref CANFD2_MODULE
  *             - \ref CANFD3_MODULE
  *             - \ref UART0_MODULE
  *             - \ref UART1_MODULE
  *             - \ref UART2_MODULE
  *             - \ref UART3_MODULE
  *             - \ref UART4_MODULE
  *             - \ref UART5_MODULE
  *             - \ref UART6_MODULE
  *             - \ref UART7_MODULE
  *             - \ref UART8_MODULE
  *             - \ref UART9_MODULE
  *             - \ref EADC0_MODULE
  *             - \ref EADC1_MODULE
  *             - \ref EADC2_MODULE
  *             - \ref I2S0_MODULE
  *             - \ref I2S1_MODULE
  *             - \ref SC0_MODULE
  *             - \ref SC1_MODULE
  *             - \ref SC2_MODULE
  *             - \ref PSIO_MODULE
  *             - \ref KPI_MODULE
  * @return     Selected module clock divider number setting
  * @details    This function get selected module clock divider number.
  */
uint32_t CLK_GetModuleClockDivider(uint32_t u32ModuleIdx)
{
    uint32_t u32DivVal = 0UL, u32DivAddr = 0UL;
    uint32_t au32DivTbl[6] = {0x0UL, 0x4UL, 0x8UL, 0xCUL, 0x10UL, 0x1C}; /* CLK_CLKDIV0~5 */

    switch(u32ModuleIdx)
    {
        /* For 8 bits divider */
        case EADC0_MODULE:
            u32DivVal = (CLK->CLKDIV0 & CLK_CLKDIV0_EADC0DIV_Msk) >> CLK_CLKDIV0_EADC0DIV_Pos;
            break;
        case SDH0_MODULE:
            u32DivVal = (CLK->CLKDIV0 & CLK_CLKDIV0_SDH0DIV_Msk) >> CLK_CLKDIV0_SDH0DIV_Pos;
            break;
        case SC0_MODULE:
            u32DivVal = (CLK->CLKDIV1 & CLK_CLKDIV1_SC0DIV_Msk) >> CLK_CLKDIV1_SC0DIV_Pos;
            break;
        case SC1_MODULE:
            u32DivVal = (CLK->CLKDIV1 & CLK_CLKDIV1_SC1DIV_Msk) >> CLK_CLKDIV1_SC1DIV_Pos;
            break;
        case SC2_MODULE:
            u32DivVal = (CLK->CLKDIV1 & CLK_CLKDIV1_SC2DIV_Msk) >> CLK_CLKDIV1_SC2DIV_Pos;
            break;
        case PSIO_MODULE:
            u32DivVal = (CLK->CLKDIV1 & CLK_CLKDIV1_PSIODIV_Msk) >> CLK_CLKDIV1_PSIODIV_Pos;
            break;
        case KPI_MODULE:
            u32DivVal = (CLK->CLKDIV2 & CLK_CLKDIV2_KPIDIV_Msk) >> CLK_CLKDIV2_KPIDIV_Pos;
            break;
        case EADC1_MODULE:
            u32DivVal = (CLK->CLKDIV2 & CLK_CLKDIV2_EADC1DIV_Msk) >> CLK_CLKDIV2_EADC1DIV_Pos;
            break;
        case SEN_MODULE:
            u32DivVal = (CLK->CLKDIV3 & CLK_CLKDIV3_VSENSEDIV_Msk) >> CLK_CLKDIV3_VSENSEDIV_Pos;
            break;
        case SDH1_MODULE:
            u32DivVal = (CLK->CLKDIV3 & CLK_CLKDIV3_SDH1DIV_Msk) >> CLK_CLKDIV3_SDH1DIV_Pos;
            break;
        case EADC2_MODULE:
            u32DivVal = (CLK->CLKDIV5 & CLK_CLKDIV5_EADC2DIV_Msk) >> CLK_CLKDIV5_EADC2DIV_Pos;
            break;

        /* Others */
        default:
        {
            /* Get clock divider control register address */
            u32DivAddr = (uint32_t)&CLK->CLKDIV0 + (au32DivTbl[MODULE_CLKDIV(u32ModuleIdx)]);
            /* Get clock divider number setting */
            u32DivVal = ((inpw((uint32_t *)u32DivAddr) & (MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx))) >> MODULE_CLKDIV_Pos(u32ModuleIdx));
        }
        break;
    }

    return u32DivVal;
}

/**
  * @brief      Disable PLLFN
  * @param      None
  * @return     None
  * @details    This function set PLLFN in Power-down mode. \n
  *             The register write-protection function should be disabled before using this function.
  */
void CLK_DisablePLLFN(void)
{
    CLK->PLLFNCTL1 |= CLK_PLLFNCTL1_PD_Msk;
}

/**
  * @brief      Set PLLFN frequency
  * @param[in]  u32PllClkSrc is PLLFN clock source. Including :
  *             - \ref CLK_PLLFNCTL1_PLLSRC_HXT
  *             - \ref CLK_PLLFNCTL1_PLLSRC_HIRC
  * @param[in]  u32PllFreq is PLLFN frequency. The range of u32PllFreq is 50 MHz ~ 500 MHz.
  * @return     PLL frequency
  * @details    This function is used to configure CLK_PLLFNCTL0 and CLK_PLLFNCTL1 register to set specified PLLFN frequency. \n
  *             The register write-protection function should be disabled before using this function.
  */
uint32_t CLK_EnablePLLFN(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
{
    uint32_t u32FIN, u32FVCO, u32FREF, u32PllClk = 0;
    uint32_t u32NR = 0UL, u32NF = 0UL, u32NO;
    uint32_t u32FVCO_NF, u32FVCO_X, u32FRDIV;
    uint32_t u32Tmp3, u32Min, u32MinNF, u32MinNR, u32MinFRDIV, u32PllFreq_temp;

    /* Disable PLLFN first to avoid unstable when setting PLLFN */
    CLK->PLLFNCTL1 |= CLK_PLLFNCTL1_PD_Msk;

    /* PLLFN source clock is from HXT */
    if(u32PllClkSrc == CLK_PLLFNCTL1_PLLSRC_HXT)
    {
        /* Enable HXT clock */
        CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;

        /* Wait for HXT clock ready */
        CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);

        /* Select PLLFN source clock from HXT */
        u32FIN = __HXT;
    }

    /* PLL source clock is from HIRC */
    else
    {
        /* Enable HIRC clock */
        CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;

        /* Wait for HIRC clock ready */
        CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

        /* Select PLLFN source clock from HIRC */
        u32FIN = __HIRC;
    }

    /* Check PLLFN frequency range */
    /* Constraint 1: 50MHz < FOUT < 500MHz */
    if((u32PllFreq <= FREQ_500MHZ) && (u32PllFreq >= FREQ_50MHZ))
    {
        /* Select "NO" according to request frequency */
        if((u32PllFreq < FREQ_100MHZ) && (u32PllFreq >= FREQ_50MHZ))
        {
            u32NO = 3UL;
            u32FVCO = u32PllFreq << 2;
        }
        else if((u32PllFreq < FREQ_200MHZ) && (u32PllFreq >= FREQ_100MHZ))
        {
            u32NO = 1UL;
            u32FVCO = u32PllFreq << 1;
        }
        else
        {
            u32NO = 0UL;
            u32FVCO = u32PllFreq;
        }

        /* Find best solution */
        u32Min = (uint32_t) - 1;    /* initial u32Min to max value of uint32_t (0xFFFFFFFF) */
        u32MinNR = 0UL;
        u32MinNF = 0UL;
        u32MinFRDIV = 0UL;

        for(u32NR = 1UL; u32NR <= 32UL; u32NR++)   /* NR = 1~32 since NR = INDIV+1 and INDIV = 0~31 */
        {
            u32FREF = u32FIN / u32NR;                               /* FREF = FIN/NR */

            if((u32FREF >= FREQ_1MHZ) && (u32FREF <= FREQ_8MHZ))    /* Constraint 2: 1MHz <= FREF <= 8MHz. */
            {                                                       /* FVCO = FREF * 2 * (NF.x) */
                u32NF = (u32FVCO>>1) / u32FREF;                     /* NF.x = FVCO * (1/FREF) * (1/2) */
                if( (u32NF >= 12) && (u32NF <=255) )                /* NF = 12~255 */
                {
                    u32FVCO_NF = (u32FREF*u32NF)<<1;                /* FVCO_NF = FREF * 2 * (NF) */
                    u32FVCO_X = u32FVCO - u32FVCO_NF;               /* FVCO_X = FVCO - FVCO_NF */

                                                                    /* FVCO_X = FREF * 2 * (x) */
                                                                    /* x = FVCO_X * (1/FREF) * (1/2) */
                    u32FRDIV = (u32FVCO_X<<9) / (u32FREF>>2);       /* FRDIV = 4096 * x */

                    u32PllFreq_temp = ((((u32FIN/u32NR)<<1)*u32NF ) / (u32NO+1)) + ((((u32FIN/u32NR)*u32FRDIV )>>11) / (u32NO+1));

                    u32Tmp3 = (u32PllFreq_temp > u32PllFreq) ? u32PllFreq_temp - u32PllFreq : u32PllFreq - u32PllFreq_temp;

                    if(u32Tmp3 < u32Min)
                    {
                        u32Min = u32Tmp3;
                        u32MinNR = u32NR;
                        u32MinNF = u32NF;
                        u32MinFRDIV = u32FRDIV;
                        u32PllClk = u32PllFreq_temp;

                        /* Break when get good results */
                        if(u32Min == 0UL)
                        {
                            break;
                        }
                    }
                }
            }
        }
    }

    if((u32PllFreq > FREQ_500MHZ) || (u32PllFreq < FREQ_50MHZ) || (u32Min == (uint32_t) - 1))
    {
        if(u32PllClkSrc == CLK_PLLFNCTL1_PLLSRC_HXT)
        {
#if (__HXT == 12000000)
            /* Apply default PLLFN setting and return */
            CLK->PLLFNCTL0 = CLK_PLLCTL_192MHz_HXT;
            CLK->PLLFNCTL1 = CLK_PLLFNCTL1_PLLSRC_HXT;

            /* Actual PLLFN output clock frequency */
            u32PllClk = FREQ_192MHZ;
#else
            /* No default PLL setting */
            u32PllClk = 0;
#endif
        }
        else
        {
            /* Apply default PLLFN setting and return */
            CLK->PLLFNCTL0 = CLK_PLLFNCTL0_192MHz_HIRC;
            CLK->PLLFNCTL1 = CLK_PLLFNCTL1_PLLSRC_HIRC;

            /* Actual PLL output clock frequency */
            u32PllClk = FREQ_192MHZ;
        }
    }
    else
    {
        /* Enable and apply new PLLFN setting. */
        CLK->PLLFNCTL0 = (u32MinFRDIV << CLK_PLLFNCTL0_FRDIV_Pos) |
                         (u32NO << CLK_PLLFNCTL0_OUTDIV_Pos) |
                         ((u32MinNR - 1UL) << CLK_PLLFNCTL0_INDIV_Pos) |
                         ((u32MinNF - 2UL) << CLK_PLLFNCTL0_FBDIV_Pos);
        CLK->PLLFNCTL1 = u32PllClkSrc;
    }

    if(u32PllClk != 0)
    {
        /* Wait for PLLFN clock stable */
        CLK_WaitClockReady(CLK_STATUS_PLLFNSTB_Msk);
    }

    /* Return actual PLLFN output clock frequency */
    return u32PllClk;
}


/**
  * @brief      Get PLLFN clock frequency
  * @param      None
  * @return     PLLFN frequency
  * @details    This function get PLLFN frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetPLLFNClockFreq(void)
{
    uint32_t u32PllFreq = 0UL, u32PllReg0, u32PllReg1;
    uint32_t u32FIN, u32NF, u32NR, u32NO, u32FRDIV;
    uint8_t au8NoTbl[4] = {1U, 2U, 2U, 4U};

    /* Get PLLFN configuration */
    u32PllReg0 = CLK->PLLFNCTL0;
    u32PllReg1 = CLK->PLLFNCTL1;

    if(u32PllReg1 & (CLK_PLLFNCTL1_PD_Msk | CLK_PLLFNCTL1_OE_Msk))
    {
        u32PllFreq = 0UL;       /* PLLFN is in power down mode or fix low */
    }
    else                        /* PLLFN is in normal mode */
    {
        /* PLLFN source clock */
        if(u32PllReg1 & CLK_PLLFNCTL1_PLLSRC_Msk)
        {
            u32FIN = __HIRC;    /* PLLFN source clock from HIRC */
        }
        else
        {
            u32FIN = __HXT;     /* PLLFN source clock from HXT */
        }

        /* Calculate PLLFN frequency */
        if(u32PllReg1 & CLK_PLLFNCTL1_BP_Msk)
        {
            u32PllFreq = u32FIN;  /* PLLFN is in bypass mode */
        }
        else
        {
            /* PLLFN is output enabled in normal work mode */
            u32NO = au8NoTbl[((u32PllReg0 & CLK_PLLFNCTL0_OUTDIV_Msk) >> CLK_PLLFNCTL0_OUTDIV_Pos)];
            u32NF = ((u32PllReg0 & CLK_PLLFNCTL0_FBDIV_Msk) >> CLK_PLLFNCTL0_FBDIV_Pos) + 2UL;
            u32NR = ((u32PllReg0 & CLK_PLLFNCTL0_INDIV_Msk) >> CLK_PLLFNCTL0_INDIV_Pos) + 1UL;
            u32FRDIV = ((u32PllReg0 & CLK_PLLFNCTL0_FRDIV_Msk) >> CLK_PLLFNCTL0_FRDIV_Pos);

            u32PllFreq = ((((u32FIN/u32NR)<<1)*u32NF ) / (u32NO)) + ((((u32FIN/u32NR)*u32FRDIV )>>11) / (u32NO));
        }
    }

    return u32PllFreq;
}


/*@}*/ /* end of group CLK_EXPORTED_FUNCTIONS */

/*@}*/ /* end of group CLK_Driver */

/*@}*/ /* end of group Standard_Driver */
