/* * Copyright (c) 2016, Freescale Semiconductor, Inc. * Copyright 2016-2022 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_clock.h" #include "fsl_common.h" /******************************************************************************* * Definitions ******************************************************************************/ /* Component ID definition, used by tools. */ #ifndef FSL_COMPONENT_ID #define FSL_COMPONENT_ID "platform.drivers.clock" #endif #define OTP_INIT_API ((void (*)(uint32_t src_clk_freq))0x13007FFF) #define OTP_DEINIT_API ((void (*)(void))0x1300804D) #define OTP_FUSE_READ_API ((void (*)(uint32_t addr, uint32_t * data))0x1300805D) /* OTP fuse index. */ #define FRO_192MHZ_SC_TRIM 0x2C #define FRO_192MHZ_RD_TRIM 0x2B #define FRO_96MHZ_SC_TRIM 0x2E #define FRO_96MHZ_RD_TRIM 0x2D /******************************************************************************* * Variables ******************************************************************************/ /* External XTAL (OSC) clock frequency. */ volatile uint32_t g_xtalFreq = 0U; /* External CLK_IN pin clock frequency. */ volatile uint32_t g_clkinFreq = 0U; /* External MCLK IN clock frequency. */ volatile uint32_t g_mclkFreq = 0U; /******************************************************************************* * Code ******************************************************************************/ /* Clock Selection for IP */ /** * brief Configure the clock selection muxes. * param connection : Clock to be configured. * return Nothing */ void CLOCK_AttachClk(clock_attach_id_t connection) { bool final_descriptor = false; uint32_t i; uint32_t tuple; volatile uint32_t *pClkSel; for (i = 0U; (i < 2U) && (!final_descriptor); i++) { tuple = ((uint32_t)connection) >> (i * 14U); /*!< pick up next descriptor */ if ((((uint32_t)connection) & 0x80000000U) != 0UL) { pClkSel = CLKCTL_TUPLE_REG(CLKCTL1, tuple); } else { pClkSel = CLKCTL_TUPLE_REG(CLKCTL0, tuple); } if ((tuple & 0x7FFU) != 0U) { *pClkSel = CLKCTL_TUPLE_SEL(tuple); } else { final_descriptor = true; } } if ((((uint32_t)connection) & 0x40000000U) != 0U) { CLKCTL0->FRODIVSEL = (((uint32_t)connection) >> 28U) & 0x3U; } } /* Set IP Clock divider */ /** * brief Setup peripheral clock dividers. * param div_name : Clock divider name * param divider : Value to be divided. Divided clock frequency = Undivided clock frequency / divider. * return Nothing */ void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divider) { volatile uint32_t *pClkDiv; if ((((uint32_t)div_name) & 0x80000000U) != 0U) { pClkDiv = CLKCTL_TUPLE_REG(CLKCTL1, div_name); } else { pClkDiv = CLKCTL_TUPLE_REG(CLKCTL0, div_name); } /* Reset the divider counter */ *pClkDiv |= 1UL << 29U; if (divider == 0U) /*!< halt */ { *pClkDiv |= 1UL << 30U; } else { *pClkDiv = divider - 1U; while (((*pClkDiv) & 0x80000000U) != 0U) { } } } /* Get SYSTEM PLL Clk */ /*! brief Return Frequency of SYSPLL * return Frequency of SYSPLL */ uint32_t CLOCK_GetSysPllFreq(void) { uint32_t freq = 0U; uint64_t freqTmp; switch ((CLKCTL0->SYSPLL0CLKSEL) & CLKCTL0_SYSPLL0CLKSEL_SEL_MASK) { case CLKCTL0_SYSPLL0CLKSEL_SEL(0): freq = CLK_FRO_DIV8_CLK; break; case CLKCTL0_SYSPLL0CLKSEL_SEL(1): freq = CLOCK_GetXtalInClkFreq(); break; default: assert(false); break; } if (((CLKCTL0->SYSPLL0CTL0) & CLKCTL0_SYSPLL0CTL0_BYPASS_MASK) == 0U) { /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */ freqTmp = ((uint64_t)freq * ((uint64_t)(CLKCTL0->SYSPLL0NUM))) / ((uint64_t)(CLKCTL0->SYSPLL0DENOM)); freq *= ((CLKCTL0->SYSPLL0CTL0) & CLKCTL0_SYSPLL0CTL0_MULT_MASK) >> CLKCTL0_SYSPLL0CTL0_MULT_SHIFT; freq += (uint32_t)freqTmp; } return freq; } /* Get SYSTEM PLL PFDn Clk */ /*! brief Get current output frequency of specific System PLL PFD. * param pfd : pfd name to get frequency. * return Frequency of SYSPLL PFD. */ uint32_t CLOCK_GetSysPfdFreq(clock_pfd_t pfd) { uint32_t freq = CLOCK_GetSysPllFreq(); if (((CLKCTL0->SYSPLL0CTL0) & CLKCTL0_SYSPLL0CTL0_BYPASS_MASK) == 0U) { switch (pfd) { case kCLOCK_Pfd0: freq = (uint32_t)((uint64_t)freq * 18U / ((CLKCTL0->SYSPLL0PFD & CLKCTL0_SYSPLL0PFD_PFD0_MASK) >> CLKCTL0_SYSPLL0PFD_PFD0_SHIFT)); break; case kCLOCK_Pfd1: freq = (uint32_t)((uint64_t)freq * 18U / ((CLKCTL0->SYSPLL0PFD & CLKCTL0_SYSPLL0PFD_PFD1_MASK) >> CLKCTL0_SYSPLL0PFD_PFD1_SHIFT)); break; case kCLOCK_Pfd2: freq = (uint32_t)((uint64_t)freq * 18U / ((CLKCTL0->SYSPLL0PFD & CLKCTL0_SYSPLL0PFD_PFD2_MASK) >> CLKCTL0_SYSPLL0PFD_PFD2_SHIFT)); break; case kCLOCK_Pfd3: freq = (uint32_t)((uint64_t)freq * 18U / ((CLKCTL0->SYSPLL0PFD & CLKCTL0_SYSPLL0PFD_PFD3_MASK) >> CLKCTL0_SYSPLL0PFD_PFD3_SHIFT)); break; default: freq = 0U; break; } } return freq; } static uint32_t CLOCK_GetMainPllClkFreq(void) { return CLOCK_GetSysPfdFreq(kCLOCK_Pfd0) / ((CLKCTL0->MAINPLLCLKDIV & CLKCTL0_MAINPLLCLKDIV_DIV_MASK) + 1U); } static uint32_t CLOCK_GetDspPllClkFreq(void) { return CLOCK_GetSysPfdFreq(kCLOCK_Pfd1) / ((CLKCTL0->DSPPLLCLKDIV & CLKCTL0_DSPPLLCLKDIV_DIV_MASK) + 1U); } static uint32_t CLOCK_GetAux0PllClkFreq(void) { return CLOCK_GetSysPfdFreq(kCLOCK_Pfd2) / ((CLKCTL0->AUX0PLLCLKDIV & CLKCTL0_AUX0PLLCLKDIV_DIV_MASK) + 1U); } static uint32_t CLOCK_GetAux1PllClkFreq(void) { return CLOCK_GetSysPfdFreq(kCLOCK_Pfd3) / ((CLKCTL0->AUX1PLLCLKDIV & CLKCTL0_AUX1PLLCLKDIV_DIV_MASK) + 1U); } /* Get AUDIO PLL Clk */ /*! brief Return Frequency of AUDIO PLL * return Frequency of AUDIO PLL */ uint32_t CLOCK_GetAudioPllFreq(void) { uint32_t freq = 0U; uint64_t freqTmp; switch ((CLKCTL1->AUDIOPLL0CLKSEL) & CLKCTL1_AUDIOPLL0CLKSEL_SEL_MASK) { case CLKCTL1_AUDIOPLL0CLKSEL_SEL(0): freq = CLK_FRO_DIV8_CLK; break; case CLKCTL1_AUDIOPLL0CLKSEL_SEL(1): freq = CLOCK_GetXtalInClkFreq(); break; default: freq = 0U; break; } if (((CLKCTL1->AUDIOPLL0CTL0) & CLKCTL1_AUDIOPLL0CTL0_BYPASS_MASK) == 0U) { /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */ freqTmp = ((uint64_t)freq * ((uint64_t)(CLKCTL1->AUDIOPLL0NUM))) / ((uint64_t)(CLKCTL1->AUDIOPLL0DENOM)); freq *= ((CLKCTL1->AUDIOPLL0CTL0) & CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) >> CLKCTL1_AUDIOPLL0CTL0_MULT_SHIFT; freq += (uint32_t)freqTmp; } return freq; } /* Get AUDIO PLL PFDn Clk */ /*! brief Get current output frequency of specific Audio PLL PFD. * param pfd : pfd name to get frequency. * return Frequency of AUDIO PLL PFD. */ uint32_t CLOCK_GetAudioPfdFreq(clock_pfd_t pfd) { uint32_t freq = CLOCK_GetAudioPllFreq(); if (((CLKCTL1->AUDIOPLL0CTL0) & CLKCTL1_AUDIOPLL0CTL0_BYPASS_MASK) == 0U) { switch (pfd) { case kCLOCK_Pfd0: freq = (uint32_t)( (uint64_t)freq * 18U / ((CLKCTL1->AUDIOPLL0PFD & CLKCTL1_AUDIOPLL0PFD_PFD0_MASK) >> CLKCTL1_AUDIOPLL0PFD_PFD0_SHIFT)); break; case kCLOCK_Pfd1: freq = (uint32_t)( (uint64_t)freq * 18U / ((CLKCTL1->AUDIOPLL0PFD & CLKCTL1_AUDIOPLL0PFD_PFD1_MASK) >> CLKCTL1_AUDIOPLL0PFD_PFD1_SHIFT)); break; case kCLOCK_Pfd2: freq = (uint32_t)( (uint64_t)freq * 18U / ((CLKCTL1->AUDIOPLL0PFD & CLKCTL1_AUDIOPLL0PFD_PFD2_MASK) >> CLKCTL1_AUDIOPLL0PFD_PFD2_SHIFT)); break; case kCLOCK_Pfd3: freq = (uint32_t)( (uint64_t)freq * 18U / ((CLKCTL1->AUDIOPLL0PFD & CLKCTL1_AUDIOPLL0PFD_PFD3_MASK) >> CLKCTL1_AUDIOPLL0PFD_PFD3_SHIFT)); break; default: freq = 0U; break; } } return freq; } static uint32_t CLOCK_GetAudioPllClkFreq(void) { return CLOCK_GetAudioPfdFreq(kCLOCK_Pfd0) / ((CLKCTL1->AUDIOPLLCLKDIV & CLKCTL1_AUDIOPLLCLKDIV_DIV_MASK) + 1U); } static uint32_t CLOCK_GetFroDivFreq(void) { uint32_t freq = 0U; switch ((CLKCTL0->FRODIVSEL) & CLKCTL0_FRODIVSEL_SEL_MASK) { case CLKCTL0_FRODIVSEL_SEL(0): freq = CLK_FRO_DIV2_CLK; break; case CLKCTL0_FRODIVSEL_SEL(1): freq = CLK_FRO_DIV4_CLK; break; case CLKCTL0_FRODIVSEL_SEL(2): freq = CLK_FRO_DIV8_CLK; break; case CLKCTL0_FRODIVSEL_SEL(3): freq = CLK_FRO_DIV16_CLK; break; default: freq = 0U; break; } return freq; } /* Get MAIN Clk */ /*! brief Return Frequency of main clk * return Frequency of main clk */ uint32_t CLOCK_GetMainClkFreq(void) { uint32_t freq = 0U; switch ((CLKCTL0->MAINCLKSELB) & CLKCTL0_MAINCLKSELB_SEL_MASK) { case CLKCTL0_MAINCLKSELB_SEL(0): switch ((CLKCTL0->MAINCLKSELA) & CLKCTL0_MAINCLKSELA_SEL_MASK) { case CLKCTL0_MAINCLKSELA_SEL(0): freq = CLOCK_GetLpOscFreq(); break; case CLKCTL0_MAINCLKSELA_SEL(1): freq = CLOCK_GetFroDivFreq(); break; case CLKCTL0_MAINCLKSELA_SEL(2): freq = CLOCK_GetXtalInClkFreq(); break; case CLKCTL0_MAINCLKSELA_SEL(3): freq = CLK_FRO_CLK; break; default: freq = 0U; break; } break; case CLKCTL0_MAINCLKSELB_SEL(1): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL0_MAINCLKSELB_SEL(2): freq = CLOCK_GetOsc32KFreq(); break; default: freq = 0U; break; } return freq; } /* Get DSP MAIN Clk */ /*! brief Return Frequency of DSP main clk * return Frequency of DSP main clk */ uint32_t CLOCK_GetDspMainClkFreq(void) { uint32_t freq = 0U; switch ((CLKCTL1->DSPCPUCLKSELB) & CLKCTL1_DSPCPUCLKSELB_SEL_MASK) { case CLKCTL1_DSPCPUCLKSELB_SEL(0): switch ((CLKCTL1->DSPCPUCLKSELA) & CLKCTL1_DSPCPUCLKSELA_SEL_MASK) { case CLKCTL1_DSPCPUCLKSELA_SEL(0): freq = CLK_FRO_CLK; break; case CLKCTL1_DSPCPUCLKSELA_SEL(1): freq = CLOCK_GetXtalInClkFreq(); break; case CLKCTL1_DSPCPUCLKSELA_SEL(2): freq = CLOCK_GetLpOscFreq(); break; default: freq = 0U; break; } break; case CLKCTL1_DSPCPUCLKSELB_SEL(1): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL1_DSPCPUCLKSELB_SEL(2): freq = CLOCK_GetDspPllClkFreq(); break; case CLKCTL1_DSPCPUCLKSELB_SEL(3): freq = CLOCK_GetOsc32KFreq(); break; default: freq = 0U; break; } return freq; } /* Get ADC Clk */ /*! brief Return Frequency of Adc Clock * return Frequency of Adc Clock. */ uint32_t CLOCK_GetAdcClkFreq(void) { uint32_t freq = 0U; switch ((CLKCTL0->ADC0FCLKSEL1) & CLKCTL0_ADC0FCLKSEL1_SEL_MASK) { case CLKCTL0_ADC0FCLKSEL1_SEL(0): switch ((CLKCTL0->ADC0FCLKSEL0) & CLKCTL0_ADC0FCLKSEL0_SEL_MASK) { case CLKCTL0_ADC0FCLKSEL0_SEL(0): freq = CLOCK_GetXtalInClkFreq(); break; case CLKCTL0_ADC0FCLKSEL0_SEL(1): freq = CLOCK_GetLpOscFreq(); break; case CLKCTL0_ADC0FCLKSEL0_SEL(2): freq = CLK_FRO_DIV4_CLK; break; default: freq = 0U; break; } break; case CLKCTL0_ADC0FCLKSEL1_SEL(1): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL0_ADC0FCLKSEL1_SEL(2): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL0_ADC0FCLKSEL1_SEL(3): freq = CLOCK_GetAux1PllClkFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL0->ADC0FCLKDIV & CLKCTL0_ADC0FCLKDIV_DIV_MASK) + 1U); } /* Get CLOCK OUT Clk */ /*! brief Return Frequency of ClockOut * return Frequency of ClockOut */ uint32_t CLOCK_GetClockOutClkFreq(void) { uint32_t freq = 0U; switch ((CLKCTL1->CLKOUTSEL1) & CLKCTL1_CLKOUTSEL1_SEL_MASK) { case CLKCTL1_CLKOUTSEL1_SEL(0): switch ((CLKCTL1->CLKOUTSEL0) & CLKCTL1_CLKOUTSEL0_SEL_MASK) { case CLKCTL1_CLKOUTSEL0_SEL(0): freq = CLOCK_GetXtalInClkFreq(); break; case CLKCTL1_CLKOUTSEL0_SEL(1): freq = CLOCK_GetLpOscFreq(); break; case CLKCTL1_CLKOUTSEL0_SEL(2): freq = CLK_FRO_DIV2_CLK; break; case CLKCTL1_CLKOUTSEL0_SEL(3): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL1_CLKOUTSEL0_SEL(4): freq = CLOCK_GetDspMainClkFreq(); break; default: freq = 0U; break; } break; case CLKCTL1_CLKOUTSEL1_SEL(1): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL1_CLKOUTSEL1_SEL(2): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL1_CLKOUTSEL1_SEL(3): freq = CLOCK_GetDspPllClkFreq(); break; case CLKCTL1_CLKOUTSEL1_SEL(4): freq = CLOCK_GetAux1PllClkFreq(); break; case CLKCTL1_CLKOUTSEL1_SEL(5): freq = CLOCK_GetAudioPllClkFreq(); break; case CLKCTL1_CLKOUTSEL1_SEL(6): freq = CLOCK_GetOsc32KFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL1->CLKOUTFCLKDIV & CLKCTL1_CLKOUTFCLKDIV_DIV_MASK) + 1U); } /* Get FRG Clk */ /*! brief Return Input frequency for the Fractional baud rate generator * return Input Frequency for FRG */ uint32_t CLOCK_GetFRGClock(uint32_t id) { uint32_t freq = 0U; uint32_t frgPllDiv = 1U; uint32_t clkSel = 0U; uint32_t frgDiv = 0U; uint32_t frgMul = 0U; assert(id <= 17U); if (id == 17U) { clkSel = CLKCTL1->FRG17CLKSEL & CLKCTL1_FRG17CLKSEL_SEL_MASK; frgMul = (CLKCTL1->FRG17CTL & CLKCTL1_FRG17CTL_MULT_MASK) >> CLKCTL1_FRG17CTL_MULT_SHIFT; frgDiv = (CLKCTL1->FRG17CTL & CLKCTL1_FRG17CTL_DIV_MASK) >> CLKCTL1_FRG17CTL_DIV_SHIFT; } else { clkSel = CLKCTL1->FLEXCOMM[id].FRGCLKSEL & CLKCTL1_FRGCLKSEL_SEL_MASK; frgMul = (CLKCTL1->FLEXCOMM[id].FRGCTL & CLKCTL1_FRGCTL_MULT_MASK) >> CLKCTL1_FRGCTL_MULT_SHIFT; frgDiv = (CLKCTL1->FLEXCOMM[id].FRGCTL & CLKCTL1_FRGCTL_DIV_MASK) >> CLKCTL1_FRGCTL_DIV_SHIFT; } switch (clkSel) { case CLKCTL1_FRGCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL1_FRGCLKSEL_SEL(1): frgPllDiv = (CLKCTL1->FRGPLLCLKDIV & CLKCTL1_FRGPLLCLKDIV_DIV_MASK) + 1U; freq = CLOCK_GetMainPllClkFreq() / frgPllDiv; break; case CLKCTL1_FRGCLKSEL_SEL(2): freq = CLK_FRO_DIV4_CLK; break; default: freq = 0U; break; } return (uint32_t)(((uint64_t)freq * ((uint64_t)frgDiv + 1ULL)) / (frgMul + frgDiv + 1UL)); } /* Get FLEXCOMM Clk */ /*! brief Return Frequency of Flexcomm functional Clock * param id : flexcomm index to get frequency. * return Frequency of Flexcomm functional Clock */ uint32_t CLOCK_GetFlexcommClkFreq(uint32_t id) { uint32_t freq = 0U; uint32_t clkSel = 0U; assert(id <= 16U); clkSel = CLKCTL1->FLEXCOMM[id].FCFCLKSEL; switch (clkSel & CLKCTL1_FCFCLKSEL_SEL_MASK) { case CLKCTL1_FCFCLKSEL_SEL(0): freq = CLK_FRO_DIV4_CLK; break; case CLKCTL1_FCFCLKSEL_SEL(1): freq = CLOCK_GetAudioPllClkFreq(); break; case CLKCTL1_FCFCLKSEL_SEL(2): freq = g_mclkFreq; break; case CLKCTL1_FCFCLKSEL_SEL(3): freq = CLOCK_GetFRGClock(id); break; default: freq = 0U; break; } return freq; } /*! @brief Return Frequency of Flexio functional Clock * @return Frequency of Flexcomm functional Clock */ uint32_t CLOCK_GetFlexioClkFreq(void) { uint32_t freq = 0U; switch (CLKCTL1->FLEXIOCLKSEL & CLKCTL1_FLEXIOCLKSEL_SEL_MASK) { case CLKCTL1_FLEXIOCLKSEL_SEL(0): freq = CLK_FRO_DIV2_CLK; break; case CLKCTL1_FLEXIOCLKSEL_SEL(1): freq = CLOCK_GetAudioPllClkFreq(); break; case CLKCTL1_FLEXIOCLKSEL_SEL(2): freq = CLOCK_GetMclkInClkFreq(); break; case CLKCTL1_FLEXIOCLKSEL_SEL(3): freq = CLOCK_GetFRGClock(17); break; default: freq = 0U; break; } return freq / ((CLKCTL1->FLEXIOCLKDIV & CLKCTL1_FLEXIOCLKDIV_DIV_MASK) + 1U); } /* Get CTIMER Clk */ /*! brief Return Frequency of Ctimer Clock * param id : ctimer index to get frequency. * return Frequency of Ctimer Clock */ uint32_t CLOCK_GetCtimerClkFreq(uint32_t id) { uint32_t freq = 0U; switch ((CLKCTL1->CT32BITFCLKSEL[id]) & CLKCTL1_CT32BITFCLKSEL_SEL_MASK) { case CLKCTL1_CT32BITFCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL1_CT32BITFCLKSEL_SEL(1): freq = CLK_FRO_CLK; break; case CLKCTL1_CT32BITFCLKSEL_SEL(2): freq = CLOCK_GetAudioPllClkFreq(); break; case CLKCTL1_CT32BITFCLKSEL_SEL(3): freq = CLOCK_GetMclkInClkFreq(); break; case CLKCTL1_CT32BITFCLKSEL_SEL(4): freq = CLOCK_GetWakeClk32KFreq(); break; default: freq = 0U; break; } return freq; } /*! @brief Return Frequency of FLEXSPI Clock * @param id : flexspi index to get frequency. * @return Frequency of Flexspi. */ uint32_t CLOCK_GetFlexspiClkFreq(uint32_t id) { uint32_t freq = 0U; uint32_t clkSel; uint32_t clkDiv; assert(id <= 1U); if (id == 0U) { clkSel = CLKCTL0->FLEXSPI0FCLKSEL & CLKCTL0_FLEXSPI0FCLKSEL_SEL_MASK; clkDiv = CLKCTL0->FLEXSPI0FCLKDIV & CLKCTL0_FLEXSPI0FCLKDIV_DIV_MASK; } else { clkSel = CLKCTL0->FLEXSPI1FCLKSEL & CLKCTL0_FLEXSPI1FCLKSEL_SEL_MASK; clkDiv = CLKCTL0->FLEXSPI1FCLKDIV & CLKCTL0_FLEXSPI1FCLKDIV_DIV_MASK; } switch (clkSel) { case CLKCTL0_FLEXSPI0FCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL0_FLEXSPI0FCLKSEL_SEL(1): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL0_FLEXSPI0FCLKSEL_SEL(2): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL0_FLEXSPI0FCLKSEL_SEL(3): freq = CLK_FRO_CLK; break; case CLKCTL0_FLEXSPI0FCLKSEL_SEL(4): freq = CLOCK_GetAux1PllClkFreq(); break; default: freq = 0U; break; } return freq / (clkDiv + 1U); } /* Get SCT Clk */ /*! brief Return Frequency of sct * return Frequency of sct clk */ uint32_t CLOCK_GetSctClkFreq(void) { uint32_t freq = 0U; switch ((CLKCTL0->SCTFCLKSEL) & CLKCTL0_SCTFCLKSEL_SEL_MASK) { case CLKCTL0_SCTFCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL0_SCTFCLKSEL_SEL(1): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL0_SCTFCLKSEL_SEL(2): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL0_SCTFCLKSEL_SEL(3): freq = CLK_FRO_CLK; break; case CLKCTL0_SCTFCLKSEL_SEL(4): freq = CLOCK_GetAux1PllClkFreq(); break; case CLKCTL0_SCTFCLKSEL_SEL(5): freq = CLOCK_GetAudioPllClkFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL0->SCTIN7CLKDIV & CLKCTL0_SCTIN7CLKDIV_DIV_MASK) + 1U); } /*! brief Return Frequency of mclk * return Frequency of mclk clk */ uint32_t CLOCK_GetMclkClkFreq(void) { uint32_t freq = 0U; if ((CLKCTL1->AUDIOMCLKSEL & CLKCTL1_AUDIOMCLKSEL_SEL_MASK) == CLKCTL1_AUDIOMCLKSEL_SEL(0)) { freq = CLK_FRO_DIV8_CLK; } else if ((CLKCTL1->AUDIOMCLKSEL & CLKCTL1_AUDIOMCLKSEL_SEL_MASK) == CLKCTL1_AUDIOMCLKSEL_SEL(1)) { freq = CLOCK_GetAudioPllClkFreq(); } else { freq = 0U; } return freq / ((CLKCTL1->AUDIOMCLKDIV & CLKCTL1_AUDIOMCLKDIV_DIV_MASK) + 1U); } /*! @brief Return Frequency of WDT clk * @param id : WDT index to get frequency. * @return Frequency of WDT clk */ uint32_t CLOCK_GetWdtClkFreq(uint32_t id) { uint32_t freq = 0U; assert(id <= 1U); if (id == 0U) { if ((CLKCTL0->WDT0FCLKSEL & CLKCTL0_WDT0FCLKSEL_SEL_MASK) == CLKCTL0_WDT0FCLKSEL_SEL(0)) { freq = CLOCK_GetLpOscFreq(); } else { freq = 0U; } } else { if ((CLKCTL1->WDT1FCLKSEL & CLKCTL1_WDT1FCLKSEL_SEL_MASK) == CLKCTL1_WDT1FCLKSEL_SEL(0)) { freq = CLOCK_GetLpOscFreq(); } else { freq = 0U; } } return freq; } /*! brief Return Frequency of systick clk * return Frequency of systick clk */ uint32_t CLOCK_GetSystickClkFreq(void) { uint32_t freq = 0U; switch (CLKCTL0->SYSTICKFCLKSEL & CLKCTL0_SYSTICKFCLKSEL_SEL_MASK) { case CLKCTL0_SYSTICKFCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq() / ((CLKCTL0->SYSTICKFCLKDIV & CLKCTL0_SYSTICKFCLKDIV_DIV_MASK) + 1U); break; case CLKCTL0_SYSTICKFCLKSEL_SEL(1): freq = CLOCK_GetLpOscFreq(); break; case CLKCTL0_SYSTICKFCLKSEL_SEL(2): freq = CLOCK_GetOsc32KFreq(); break; default: freq = 0U; break; } return freq; } /*! brief Return Frequency of SDIO clk * param id : SDIO index to get frequency. * return Frequency of SDIO clk */ uint32_t CLOCK_GetSdioClkFreq(uint32_t id) { uint32_t freq = 0U; volatile uint32_t *pClkSel; volatile uint32_t *pClkDiv; assert(id <= 1U); if (id == 0U) { pClkSel = &CLKCTL0->SDIO0FCLKSEL; pClkDiv = &CLKCTL0->SDIO0FCLKDIV; } else { pClkSel = &CLKCTL0->SDIO1FCLKSEL; pClkDiv = &CLKCTL0->SDIO1FCLKDIV; } switch ((*pClkSel) & CLKCTL0_SDIO0FCLKSEL_SEL_MASK) { case CLKCTL0_SDIO0FCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL0_SDIO0FCLKSEL_SEL(1): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL0_SDIO0FCLKSEL_SEL(2): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL0_SDIO0FCLKSEL_SEL(3): freq = CLK_FRO_DIV2_CLK; break; case CLKCTL0_SDIO0FCLKSEL_SEL(4): freq = CLOCK_GetAux1PllClkFreq(); break; default: freq = 0U; break; } return freq / (((*pClkDiv) & CLKCTL0_SDIO0FCLKDIV_DIV_MASK) + 1U); } /*! @brief Return Frequency of I3C clk * @return Frequency of I3C clk */ uint32_t CLOCK_GetI3cClkFreq(void) { uint32_t freq = 0U; switch (CLKCTL1->I3C01FCLKSEL & CLKCTL1_I3C01FCLKSEL_SEL_MASK) { case CLKCTL1_I3C01FCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL1_I3C01FCLKSEL_SEL(1): freq = CLK_FRO_DIV8_CLK; break; default: freq = 0U; break; } return freq / ((CLKCTL1->I3C01FCLKDIV & CLKCTL1_I3C01FCLKDIV_DIV_MASK) + 1U); } /*! brief Return Frequency of USB clk * return Frequency of USB clk */ uint32_t CLOCK_GetUsbClkFreq(void) { uint32_t freq = 0U; switch (CLKCTL0->USBHSFCLKSEL & CLKCTL0_USBHSFCLKSEL_SEL_MASK) { case CLKCTL0_USBHSFCLKSEL_SEL(0): freq = CLOCK_GetXtalInClkFreq(); break; case CLKCTL0_USBHSFCLKSEL_SEL(1): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL0_USBHSFCLKSEL_SEL(3): freq = CLOCK_GetAux0PllClkFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL0->USBHSFCLKDIV & CLKCTL0_USBHSFCLKDIV_DIV_MASK) + 1U); } /*! brief Return Frequency of DMIC clk * return Frequency of DMIC clk */ uint32_t CLOCK_GetDmicClkFreq(void) { uint32_t freq = 0U; switch ((CLKCTL1->DMIC0FCLKSEL) & CLKCTL1_DMIC0FCLKSEL_SEL_MASK) { case CLKCTL1_DMIC0FCLKSEL_SEL(0): freq = CLK_FRO_DIV4_CLK; break; case CLKCTL1_DMIC0FCLKSEL_SEL(1): freq = CLOCK_GetAudioPllClkFreq(); break; case CLKCTL1_DMIC0FCLKSEL_SEL(2): freq = CLOCK_GetMclkInClkFreq(); break; case CLKCTL1_DMIC0FCLKSEL_SEL(3): freq = CLOCK_GetLpOscFreq(); break; case CLKCTL1_DMIC0FCLKSEL_SEL(4): freq = CLOCK_GetWakeClk32KFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL1->DMIC0FCLKDIV & CLKCTL1_DMIC0FCLKDIV_DIV_MASK) + 1U); } /*! brief Return Frequency of ACMP clk * return Frequency of ACMP clk */ uint32_t CLOCK_GetAcmpClkFreq(void) { uint32_t freq = 0U; switch ((CLKCTL1->ACMP0FCLKSEL) & CLKCTL1_ACMP0FCLKSEL_SEL_MASK) { case CLKCTL1_ACMP0FCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL1_ACMP0FCLKSEL_SEL(1): freq = CLK_FRO_DIV4_CLK; break; case CLKCTL1_ACMP0FCLKSEL_SEL(2): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL1_ACMP0FCLKSEL_SEL(3): freq = CLOCK_GetAux1PllClkFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL1->ACMP0FCLKDIV & CLKCTL1_ACMP0FCLKDIV_DIV_MASK) + 1U); } /*! @brief Return Frequency of GPU functional Clock * @return Frequency of GPU functional Clock */ uint32_t CLOCK_GetGpuClkFreq(void) { uint32_t freq = 0U; switch (CLKCTL0->GPUCLKSEL & CLKCTL0_GPUCLKSEL_SEL_MASK) { case CLKCTL0_GPUCLKSEL_SEL(0): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL0_GPUCLKSEL_SEL(1): freq = CLK_FRO_CLK; break; case CLKCTL0_GPUCLKSEL_SEL(2): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL0_GPUCLKSEL_SEL(3): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL0_GPUCLKSEL_SEL(4): freq = CLOCK_GetAux1PllClkFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL0->GPUCLKDIV & CLKCTL0_GPUCLKDIV_DIV_MASK) + 1U); } /*! @brief Return Frequency of DCNano Pixel functional Clock * @return Frequency of DCNano pixel functional Clock */ uint32_t CLOCK_GetDcPixelClkFreq(void) { uint32_t freq = 0U; switch (CLKCTL0->DCPIXELCLKSEL & CLKCTL0_DCPIXELCLKSEL_SEL_MASK) { case CLKCTL0_DCPIXELCLKSEL_SEL(0): freq = CLOCK_GetMipiDphyClkFreq(); break; case CLKCTL0_DCPIXELCLKSEL_SEL(1): freq = CLOCK_GetMainClkFreq(); break; case CLKCTL0_DCPIXELCLKSEL_SEL(2): freq = CLK_FRO_CLK; break; case CLKCTL0_DCPIXELCLKSEL_SEL(3): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL0_DCPIXELCLKSEL_SEL(4): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL0_DCPIXELCLKSEL_SEL(5): freq = CLOCK_GetAux1PllClkFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL0->DCPIXELCLKDIV & CLKCTL0_DCPIXELCLKDIV_DIV_MASK) + 1U); } /*! @brief Return Frequency of MIPI DPHY functional Clock * @return Frequency of MIPI DPHY functional Clock */ uint32_t CLOCK_GetMipiDphyClkFreq(void) { uint32_t freq = 0U; switch (CLKCTL0->DPHYCLKSEL & CLKCTL0_DPHYCLKSEL_SEL_MASK) { case CLKCTL0_DPHYCLKSEL_SEL(0): freq = CLK_FRO_CLK; break; case CLKCTL0_DPHYCLKSEL_SEL(1): freq = CLOCK_GetMainPllClkFreq(); break; case CLKCTL0_DPHYCLKSEL_SEL(2): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL0_DPHYCLKSEL_SEL(3): freq = CLOCK_GetAux1PllClkFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL0->DPHYCLKDIV & CLKCTL0_DPHYCLKDIV_DIV_MASK) + 1U); } /*! @brief Return Frequency of MIPI DPHY Esc RX functional Clock * @return Frequency of MIPI DPHY Esc RX functional Clock */ uint32_t CLOCK_GetMipiDphyEscRxClkFreq(void) { uint32_t freq = 0U; switch (CLKCTL0->DPHYESCCLKSEL & CLKCTL0_DPHYESCCLKSEL_SEL_MASK) { case CLKCTL0_DPHYESCCLKSEL_SEL(0): freq = CLK_FRO_CLK; break; case CLKCTL0_DPHYESCCLKSEL_SEL(1): freq = CLK_FRO_DIV16_CLK; break; case CLKCTL0_DPHYESCCLKSEL_SEL(2): freq = CLOCK_GetAux0PllClkFreq(); break; case CLKCTL0_DPHYESCCLKSEL_SEL(3): freq = CLOCK_GetAux1PllClkFreq(); break; default: freq = 0U; break; } return freq / ((CLKCTL0->DPHYESCRXCLKDIV & CLKCTL0_DPHYESCRXCLKDIV_DIV_MASK) + 1U); } /*! @brief Return Frequency of MIPI DPHY Esc Tx functional Clock * @return Frequency of MIPI DPHY Esc Tx functional Clock */ uint32_t CLOCK_GetMipiDphyEscTxClkFreq(void) { return CLOCK_GetMipiDphyEscRxClkFreq() / ((CLKCTL0->DPHYESCTXCLKDIV & CLKCTL0_DPHYESCTXCLKDIV_DIV_MASK) + 1U); } /* Get IP Clk */ /*! brief Return Frequency of selected clock * return Frequency of selected clock */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq = 0U; switch (clockName) { case kCLOCK_CoreSysClk: case kCLOCK_BusClk: freq = CLOCK_GetMainClkFreq() / ((CLKCTL0->SYSCPUAHBCLKDIV & CLKCTL0_SYSCPUAHBCLKDIV_DIV_MASK) + 1U); break; case kCLOCK_MclkClk: freq = CLOCK_GetMclkClkFreq(); break; case kCLOCK_ClockOutClk: freq = CLOCK_GetClockOutClkFreq(); break; case kCLOCK_AdcClk: freq = CLOCK_GetAdcClkFreq(); break; case kCLOCK_Flexspi0Clk: freq = CLOCK_GetFlexspiClkFreq(0U); break; case kCLOCK_Flexspi1Clk: freq = CLOCK_GetFlexspiClkFreq(1U); break; case kCLOCK_SctClk: freq = CLOCK_GetSctClkFreq(); break; case kCLOCK_Wdt0Clk: freq = CLOCK_GetWdtClkFreq(0U); break; case kCLOCK_Wdt1Clk: freq = CLOCK_GetWdtClkFreq(1U); break; case kCLOCK_SystickClk: freq = CLOCK_GetSystickClkFreq(); break; case kCLOCK_Sdio0Clk: freq = CLOCK_GetSdioClkFreq(0U); break; case kCLOCK_Sdio1Clk: freq = CLOCK_GetSdioClkFreq(1U); break; case kCLOCK_I3cClk: freq = CLOCK_GetI3cClkFreq(); break; case kCLOCK_UsbClk: freq = CLOCK_GetUsbClkFreq(); break; case kCLOCK_DmicClk: freq = CLOCK_GetDmicClkFreq(); break; case kCLOCK_DspCpuClk: freq = CLOCK_GetDspMainClkFreq() / ((CLKCTL1->DSPCPUCLKDIV & CLKCTL1_DSPCPUCLKDIV_DIV_MASK) + 1U); break; case kCLOCK_AcmpClk: freq = CLOCK_GetAcmpClkFreq(); break; case kCLOCK_Flexcomm0Clk: freq = CLOCK_GetFlexcommClkFreq(0U); break; case kCLOCK_Flexcomm1Clk: freq = CLOCK_GetFlexcommClkFreq(1U); break; case kCLOCK_Flexcomm2Clk: freq = CLOCK_GetFlexcommClkFreq(2U); break; case kCLOCK_Flexcomm3Clk: freq = CLOCK_GetFlexcommClkFreq(3U); break; case kCLOCK_Flexcomm4Clk: freq = CLOCK_GetFlexcommClkFreq(4U); break; case kCLOCK_Flexcomm5Clk: freq = CLOCK_GetFlexcommClkFreq(5U); break; case kCLOCK_Flexcomm6Clk: freq = CLOCK_GetFlexcommClkFreq(6U); break; case kCLOCK_Flexcomm7Clk: freq = CLOCK_GetFlexcommClkFreq(7U); break; case kCLOCK_Flexcomm8Clk: freq = CLOCK_GetFlexcommClkFreq(8U); break; case kCLOCK_Flexcomm9Clk: freq = CLOCK_GetFlexcommClkFreq(9U); break; case kCLOCK_Flexcomm10Clk: freq = CLOCK_GetFlexcommClkFreq(10U); break; case kCLOCK_Flexcomm11Clk: freq = CLOCK_GetFlexcommClkFreq(11U); break; case kCLOCK_Flexcomm12Clk: freq = CLOCK_GetFlexcommClkFreq(12U); break; case kCLOCK_Flexcomm13Clk: freq = CLOCK_GetFlexcommClkFreq(13U); break; case kCLOCK_Flexcomm14Clk: freq = CLOCK_GetFlexcommClkFreq(14U); break; case kCLOCK_Flexcomm15Clk: freq = CLOCK_GetFlexcommClkFreq(15U); break; case kCLOCK_Flexcomm16Clk: freq = CLOCK_GetFlexcommClkFreq(16U); break; case kCLOCK_FlexioClk: freq = CLOCK_GetFlexioClkFreq(); break; case kCLOCK_GpuClk: freq = CLOCK_GetGpuClkFreq(); break; case kCLOCK_DcPixelClk: freq = CLOCK_GetDcPixelClkFreq(); break; case kCLOCK_MipiDphyClk: freq = CLOCK_GetMipiDphyClkFreq(); break; case kCLOCK_MipiDphyEscRxClk: freq = CLOCK_GetMipiDphyEscRxClkFreq(); break; case kCLOCK_MipiDphyEscTxClk: freq = CLOCK_GetMipiDphyEscTxClkFreq(); break; default: freq = 0U; break; } return freq; } /* Set FRG Clk */ /*! brief Set output of the Fractional baud rate generator * param config : Configuration to set to FRGn clock. */ void CLOCK_SetFRGClock(const clock_frg_clk_config_t *config) { uint32_t i = config->num; assert(i <= 17U); assert(config->divider == 255U); /* Always set to 0xFF to use with the fractional baudrate generator.*/ if (i == 17U) { CLKCTL1->FRG17CLKSEL = (uint32_t)config->sfg_clock_src; CLKCTL1->FRG17CTL = (CLKCTL1_FRG17CTL_MULT(config->mult) | CLKCTL1_FRG17CTL_DIV(config->divider)); } else { CLKCTL1->FLEXCOMM[i].FRGCLKSEL = (uint32_t)config->sfg_clock_src; CLKCTL1->FLEXCOMM[i].FRGCTL = (CLKCTL1_FRGCTL_MULT(config->mult) | CLKCTL1_FRGCTL_DIV(config->divider)); } } /* Initialize the SYSTEM PLL Clk */ /*! brief Initialize the System PLL. * param config : Configuration to set to PLL. */ void CLOCK_InitSysPll(const clock_sys_pll_config_t *config) { /* Power down SYSPLL before change fractional settings */ SYSCTL0->PDRUNCFG0_SET = SYSCTL0_PDRUNCFG0_SYSPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_SYSPLLANA_PD_MASK; CLKCTL0->SYSPLL0CLKSEL = (uint32_t)config->sys_pll_src; CLKCTL0->SYSPLL0NUM = config->numerator; CLKCTL0->SYSPLL0DENOM = config->denominator; switch (config->sys_pll_mult) { case kCLOCK_SysPllMult16: CLKCTL0->SYSPLL0CTL0 = (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(16); break; case kCLOCK_SysPllMult17: CLKCTL0->SYSPLL0CTL0 = (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(17); break; case kCLOCK_SysPllMult18: CLKCTL0->SYSPLL0CTL0 = (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(18); break; case kCLOCK_SysPllMult19: CLKCTL0->SYSPLL0CTL0 = (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(19); break; case kCLOCK_SysPllMult20: CLKCTL0->SYSPLL0CTL0 = (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(20); break; case kCLOCK_SysPllMult21: CLKCTL0->SYSPLL0CTL0 = (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(21); break; case kCLOCK_SysPllMult22: CLKCTL0->SYSPLL0CTL0 = (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(22); break; default: assert(false); break; } /* Clear System PLL reset*/ CLKCTL0->SYSPLL0CTL0 &= ~CLKCTL0_SYSPLL0CTL0_RESET_MASK; /* Power up SYSPLL*/ SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_SYSPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_SYSPLLANA_PD_MASK; SDK_DelayAtLeastUs((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 2U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* Set System PLL HOLDRINGOFF_ENA */ CLKCTL0->SYSPLL0CTL0 |= CLKCTL0_SYSPLL0CTL0_HOLDRINGOFF_ENA_MASK; SDK_DelayAtLeastUs((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 6U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* Clear System PLL HOLDRINGOFF_ENA*/ CLKCTL0->SYSPLL0CTL0 &= ~CLKCTL0_SYSPLL0CTL0_HOLDRINGOFF_ENA_MASK; SDK_DelayAtLeastUs((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 3U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); } /* Initialize the System PLL PFD */ /*! brief Initialize the System PLL PFD. * param pfd : Which PFD clock to enable. * param divider : The PFD divider value. * note It is recommended that PFD settings are kept between 12-35. */ void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t divider) { uint32_t pfdIndex = (uint32_t)pfd; uint32_t syspfd; syspfd = CLKCTL0->SYSPLL0PFD & ~(((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_CLKGATE_MASK | (uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_MASK) << (8UL * pfdIndex)); /* Disable the clock output first. */ CLKCTL0->SYSPLL0PFD = syspfd | ((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); /* Set the new value and enable output. */ CLKCTL0->SYSPLL0PFD = syspfd | ((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0(divider) << (8UL * pfdIndex)); /* Wait for output becomes stable. */ while ((CLKCTL0->SYSPLL0PFD & ((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_CLKRDY_MASK << (8UL * pfdIndex))) == 0UL) { } /* Clear ready status flag. */ CLKCTL0->SYSPLL0PFD |= ((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_CLKRDY_MASK << (8UL * pfdIndex)); } /* Initialize the Audio PLL Clk */ /*! brief Initialize the audio PLL. * param config : Configuration to set to PLL. */ void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config) { /* Power down Audio PLL before change fractional settings */ SYSCTL0->PDRUNCFG0_SET = SYSCTL0_PDRUNCFG0_AUDPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_AUDPLLANA_PD_MASK; CLKCTL1->AUDIOPLL0CLKSEL = (uint32_t)config->audio_pll_src; CLKCTL1->AUDIOPLL0NUM = config->numerator; CLKCTL1->AUDIOPLL0DENOM = config->denominator; switch (config->audio_pll_mult) { case kCLOCK_AudioPllMult16: CLKCTL1->AUDIOPLL0CTL0 = (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(16); break; case kCLOCK_AudioPllMult17: CLKCTL1->AUDIOPLL0CTL0 = (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(17); break; case kCLOCK_AudioPllMult18: CLKCTL1->AUDIOPLL0CTL0 = (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(18); break; case kCLOCK_AudioPllMult19: CLKCTL1->AUDIOPLL0CTL0 = (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(19); break; case kCLOCK_AudioPllMult20: CLKCTL1->AUDIOPLL0CTL0 = (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(20); break; case kCLOCK_AudioPllMult21: CLKCTL1->AUDIOPLL0CTL0 = (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(21); break; case kCLOCK_AudioPllMult22: CLKCTL1->AUDIOPLL0CTL0 = (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(22); break; default: assert(false); break; } /* Clear Audio PLL reset*/ CLKCTL1->AUDIOPLL0CTL0 &= ~CLKCTL1_AUDIOPLL0CTL0_RESET_MASK; /* Power up Audio PLL*/ SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_AUDPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_AUDPLLANA_PD_MASK; SDK_DelayAtLeastUs((CLKCTL1->AUDIOPLL0LOCKTIMEDIV2 & CLKCTL1_AUDIOPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 2U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* Set Audio PLL HOLDRINGOFF_ENA */ CLKCTL1->AUDIOPLL0CTL0 |= CLKCTL1_AUDIOPLL0CTL0_HOLDRINGOFF_ENA_MASK; SDK_DelayAtLeastUs((CLKCTL1->AUDIOPLL0LOCKTIMEDIV2 & CLKCTL1_AUDIOPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 6U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* Clear Audio PLL HOLDRINGOFF_ENA*/ CLKCTL1->AUDIOPLL0CTL0 &= ~CLKCTL1_AUDIOPLL0CTL0_HOLDRINGOFF_ENA_MASK; SDK_DelayAtLeastUs((CLKCTL1->AUDIOPLL0LOCKTIMEDIV2 & CLKCTL1_AUDIOPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 3U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); } /* Initialize the Audio PLL PFD */ /*! brief Initialize the audio PLL PFD. * param pfd : Which PFD clock to enable. * param divider : The PFD divider value. * note It is recommended that PFD settings are kept between 12-35. */ void CLOCK_InitAudioPfd(clock_pfd_t pfd, uint8_t divider) { uint32_t pfdIndex = (uint32_t)pfd; uint32_t syspfd; syspfd = CLKCTL1->AUDIOPLL0PFD & ~(((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_CLKGATE_MASK | (uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_MASK) << (8UL * pfdIndex)); /* Disable the clock output first. */ CLKCTL1->AUDIOPLL0PFD = syspfd | ((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); /* Set the new value and enable output. */ CLKCTL1->AUDIOPLL0PFD = syspfd | ((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0(divider) << (8UL * pfdIndex)); /* Wait for output becomes stable. */ while ((CLKCTL1->AUDIOPLL0PFD & ((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_CLKRDY_MASK << (8UL * pfdIndex))) == 0UL) { } /* Clear ready status flag. */ CLKCTL1->AUDIOPLL0PFD |= ((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_CLKRDY_MASK << (8UL * pfdIndex)); } /*! @brief Enable/Disable sys osc clock from external crystal clock. * @param enable : true to enable system osc clock, false to bypass system osc. * @param enableLowPower : true to enable low power mode, false to enable high gain mode. * @param delay_us : Delay time after OSC power up. */ void CLOCK_EnableSysOscClk(bool enable, bool enableLowPower, uint32_t delay_us) { uint32_t ctrl = enableLowPower ? CLKCTL0_SYSOSCCTL0_LP_ENABLE_MASK : 0U; if (enable) { CLKCTL0->SYSOSCCTL0 = ctrl; CLKCTL0->SYSOSCBYPASS = 0U; SDK_DelayAtLeastUs(delay_us, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); } else { CLKCTL0->SYSOSCCTL0 = ctrl | CLKCTL0_SYSOSCCTL0_BYPASS_ENABLE_MASK; } } /*! @brief Enable/Disable FRO clock output. * @param divOutEnable : Or'ed value of clock_fro_output_en_t to enable certain clock freq output. */ void CLOCK_EnableFroClk(uint32_t divOutEnable) { if (divOutEnable != 0U) { /* Some FRO frequency need to be outputed. Wait FRO stable first in case FRO just get powered on. */ while ((CLKCTL0->FROCLKSTATUS & CLKCTL0_FROCLKSTATUS_CLK_OK_MASK) == 0U) { } } else { /* Do nothing */ } CLKCTL0->FRODIVOEN = divOutEnable & (uint32_t)kCLOCK_FroAllOutEn; } void CLOCK_EnableFroClkFreq(uint32_t targetFreq, uint32_t divOutEnable) { (void)CLOCK_FroTuneToFreq(targetFreq); CLOCK_EnableFroClk(divOutEnable); } #ifndef __XTENSA__ /*! @brief Enable/Disable FRO192M or FRO96M clock output. * @param froFreq : target fro frequency. * @param divOutEnable : Or'ed value of clock_fro_output_en_t to enable certain clock freq output. */ void CLOCK_EnableFroClkRange(clock_fro_freq_t froFreq, uint32_t divOutEnable) { uint32_t scTrim, rdTrim; OTP_INIT_API(CLOCK_GetFreq(kCLOCK_BusClk)); if (froFreq == kCLOCK_Fro192M) { /* Read 192M FRO clock Trim settings from fuse. */ OTP_FUSE_READ_API(FRO_192MHZ_SC_TRIM, &scTrim); OTP_FUSE_READ_API(FRO_192MHZ_RD_TRIM, &rdTrim); } else { /* Read 96M FRO clock Trim settings from fuse. */ OTP_FUSE_READ_API(FRO_96MHZ_SC_TRIM, &scTrim); OTP_FUSE_READ_API(FRO_96MHZ_RD_TRIM, &rdTrim); } OTP_DEINIT_API(); CLKCTL0->FRO_SCTRIM = CLKCTL0_FRO_SCTRIM_TRIM(scTrim); CLKCTL0->FRO_RDTRIM = CLKCTL0_FRO_RDTRIM_TRIM(rdTrim); CLKCTL0->FRO_CONTROL &= ~CLKCTL0_FRO_CONTROL_EXP_COUNT_MASK; /* Reset the EXP_COUNT. */ CLOCK_EnableFroClk(divOutEnable); } #endif /* __XTENSA__ */ /*! @brief Enable LPOSC 1MHz clock. */ void CLOCK_EnableLpOscClk(void) { /* No LPOSC enable/disable control in CLKCTL. Just wait LPOSC stable in case LPOSC just get powered on. */ while ((CLKCTL0->LPOSCCTL0 & CLKCTL0_LPOSCCTL0_CLKRDY_MASK) == 0U) { } } status_t CLOCK_FroTuneToFreq(uint32_t targetFreq) { uint32_t xtalFreq = CLOCK_GetXtalInClkFreq(); uint32_t expected, up, low; uint32_t captured, trim; assert(xtalFreq); assert(targetFreq >= CLK_FRO_LOW_FREQ); assert(targetFreq <= CLK_FRO_HIGH_FREQ); if (xtalFreq == 0U) { /* The reference clock for the tuner is unavailable. */ return kStatus_Fail; } targetFreq = (targetFreq / 4U); /* Avoid the need for 64-bit calculation. */ targetFreq = targetFreq / 100U; xtalFreq = xtalFreq / 100U; expected = ((targetFreq * 4095U) / xtalFreq + 6U) / 2U; up = ((((targetFreq * 2047U) / xtalFreq) * 100085U) / 100000U) + 2U; low = ((((targetFreq * 2048U) / xtalFreq) * 99915U + 100000U) / 100000U) + 3U; /* Start tuning */ CLKCTL0->FRO_CONTROL = CLKCTL0_FRO_CONTROL_EXP_COUNT(expected) | CLKCTL0_FRO_CONTROL_THRESH_RANGE_UP(up - expected) | CLKCTL0_FRO_CONTROL_THRESH_RANGE_LOW(expected - low) | CLKCTL0_FRO_CONTROL_ENA_TUNE_MASK; while (true) { while ((CLKCTL0->FRO_CAPVAL & CLKCTL0_FRO_CAPVAL_DATA_VALID_MASK) == 0U) { } captured = CLKCTL0->FRO_CAPVAL & CLKCTL0_FRO_CAPVAL_CAPVAL_MASK; trim = CLKCTL0->FRO_RDTRIM; /* Clear FRO_CAPVAL VALID flag */ CLKCTL0->FRO_RDTRIM = trim; /* Reach the frequency range, then return. */ if ((captured <= up) && (captured >= low)) { break; } } CLKCTL0->FRO_CONTROL &= ~CLKCTL0_FRO_CONTROL_ENA_TUNE_MASK; return kStatus_Success; } void CLOCK_EnableFroTuning(bool enable) { uint32_t xtalFreq = CLOCK_GetXtalInClkFreq(); uint32_t targetFreq = CLK_FRO_DIV4_CLK; uint32_t expected, up, low; uint32_t captured, trim; assert(xtalFreq); assert(targetFreq > xtalFreq); if (enable) { /* Avoid the need for 64-bit calculation. */ xtalFreq = xtalFreq / 100U; targetFreq = targetFreq / 100U; expected = ((targetFreq * 4095U) / xtalFreq + 6U) / 2U; up = (((targetFreq * 2047U) / xtalFreq) * 100085U) / 100000U + 2U; low = (((targetFreq * 2048U) / xtalFreq) * 99915U + 100000U) / 100000U + 3U; /* Start tuning */ CLKCTL0->FRO_CONTROL = CLKCTL0_FRO_CONTROL_EXP_COUNT(expected) | CLKCTL0_FRO_CONTROL_THRESH_RANGE_UP(up - expected) | CLKCTL0_FRO_CONTROL_THRESH_RANGE_LOW(expected - low) | CLKCTL0_FRO_CONTROL_ENA_TUNE_MASK; while (true) { while ((CLKCTL0->FRO_CAPVAL & CLKCTL0_FRO_CAPVAL_DATA_VALID_MASK) == 0U) { } captured = CLKCTL0->FRO_CAPVAL & CLKCTL0_FRO_CAPVAL_CAPVAL_MASK; trim = CLKCTL0->FRO_RDTRIM; /* Clear FRO_CAPVAL VALID flag */ CLKCTL0->FRO_RDTRIM = trim; /* Reach the frequency range, then return. */ if ((captured <= up) && (captured >= low)) { break; } } } else { CLKCTL0->FRO_CONTROL &= ~CLKCTL0_FRO_CONTROL_ENA_TUNE_MASK; } } /*! @brief Enable USB HS device clock. * * This function enables USB HS device clock. */ void CLOCK_EnableUsbHs0DeviceClock(clock_attach_id_t src, uint8_t divider) { CLOCK_AttachClk(src); /* frequency division for usb ip clock */ CLOCK_SetClkDiv(kCLOCK_DivUsbHsFclk, divider); /* Enable usbhs device clock */ CLOCK_EnableClock(kCLOCK_UsbhsDevice); } /*! @brief Disable USB HS device clock. * * This function disables USB HS device clock. */ void CLOCK_DisableUsbHs0DeviceClock(void) { /* Disable usbhs device clock */ CLOCK_DisableClock(kCLOCK_UsbhsDevice); } /*! @brief Enable USB HS host clock. * * This function enables USB HS host clock. */ void CLOCK_EnableUsbHs0HostClock(clock_attach_id_t src, uint8_t divider) { CLOCK_AttachClk(src); /* frequency division for usb ip clock */ CLOCK_SetClkDiv(kCLOCK_DivUsbHsFclk, divider); /* Enable usbhs host clock */ CLOCK_EnableClock(kCLOCK_UsbhsHost); } /*! @brief Disable USB HS host clock. * * This function disables USB HS host clock. */ void CLOCK_DisableUsbHs0HostClock(void) { /* Disable usbhs host clock */ CLOCK_DisableClock(kCLOCK_UsbhsHost); } /*! brief Enable USB hs0PhyPll clock. * * param src USB HS clock source. * param freq The frequency specified by src. * retval true The clock is set successfully. * retval false The clock source is invalid to get proper USB HS clock. */ bool CLOCK_EnableUsbHs0PhyPllClock(clock_attach_id_t src, uint32_t freq) { uint32_t phyPllDiv = 0U; uint16_t multiplier = 0U; bool retVal = true; if (((uint32_t)(CLKCTL0->USBHSFCLKSEL & CLKCTL0_USBHSFCLKSEL_SEL_MASK)) != CLKCTL0_USBHSFCLKSEL_SEL(src)) { retVal = false; } if ((480000000U % freq) != 0U) { retVal = false; } multiplier = (uint16_t)(480000000U / freq); switch (multiplier) { case 13U: { phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U); break; } case 15U: { phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U); break; } case 16U: { phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U); break; } case 20U: { phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(3U); break; } case 22U: { phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U); break; } case 25U: { phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U); break; } case 30U: { phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U); break; } case 240U: { phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(7U); break; } default: { retVal = false; break; } } if (retVal) { /* enable usb phy clock */ CLOCK_EnableClock(kCLOCK_UsbhsPhy); USBPHY->CTRL_CLR = USBPHY_CTRL_SFTRST_MASK; USBPHY->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK; /* This field controls the USB PLL regulator, set to enable the regulator. SW must set this bit 15 us before setting PLL_POWER to avoid glitches on PLL output clock. */ USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_PLL_REG_ENABLE_MASK; uint32_t i = 5000U; while ((i--) != 0U) { __NOP(); } USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_PLL_POWER(1); while ((USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_POWER_MASK) == 0U) { USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_PLL_POWER(1); } while ((USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK) == 0U) { } USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~(USBPHY_PLL_SIC_PLL_DIV_SEL_MASK)) | phyPllDiv; USBPHY->PLL_SIC_CLR = USBPHY_PLL_SIC_PLL_BYPASS_MASK; while ((USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_BYPASS_MASK) != 0U) { USBPHY->PLL_SIC_CLR = USBPHY_PLL_SIC_PLL_BYPASS_MASK; } USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_PLL_ENABLE(1); USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_EN_USB_CLKS(1); while ((USBPHY->PLL_SIC & (USBPHY_PLL_SIC_PLL_ENABLE(1) | USBPHY_PLL_SIC_SET_PLL_EN_USB_CLKS(1))) != (USBPHY_PLL_SIC_PLL_ENABLE(1) | USBPHY_PLL_SIC_SET_PLL_EN_USB_CLKS(1))) { USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_PLL_ENABLE(1) | USBPHY_PLL_SIC_SET_PLL_EN_USB_CLKS(1); } USBPHY->PWD = 0x0; } return retVal; } /*! @brief Disable USB hs0PhyPll clock. * * This function disables USB hs0PhyPll clock. */ void CLOCK_DisableUsbHs0PhyPllClock(void) { USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */ USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK; /* Power down PLL */ }