Files
mongoose/tutorials/nxp/frdm-rw612-xpresso-freertos-lwip/drivers/fsl_clock.c
T

1702 lines
50 KiB
C

/*
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_clock.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.clock"
#endif
/* Each loop costs 3 cpu cycles */
#define CLOCK_DELAY_LOOPS(cpuFreq, delayFreq, delayCycles) \
((((cpuFreq) + (delayFreq)-1U) / (delayFreq)) * (delayCycles) / 3U)
#define CLOCK_KHZ(freq) ((freq)*1000UL)
#define CLOCK_MHZ(freq) (CLOCK_KHZ(freq) * 1000UL)
/*******************************************************************************
* Variables
******************************************************************************/
/* External CLK_IN pin clock frequency. */
volatile uint32_t g_clkinFreq = 0U;
/* External MCLK in (mclk_in) clock frequency. If not used,
set this to 0. Otherwise, set it to the exact rate in Hz this pin is
being driven at.*/
volatile uint32_t g_mclkinFreq = 0U;
static const uint32_t s_avpllFreq[] = {
0U,
CLOCK_KHZ(2048UL), /*!< AVPLL channel frequency 2.048MHz */
CLOCK_KHZ(4096UL), /*!< AVPLL channel frequency 4.096MHz */
CLOCK_KHZ(6144UL), /*!< AVPLL channel frequency 6.144MHz */
CLOCK_KHZ(8192UL), /*!< AVPLL channel frequency 8.192MHz */
11289600UL, /*!< AVPLL channel frequency 11.2896MHz */
CLOCK_MHZ(12UL), /*!< AVPLL channel frequency 12MHz */
CLOCK_KHZ(12288UL), /*!< AVPLL channel frequency 12.288MHz */
CLOCK_KHZ(24576UL), /*!< AVPLL channel frequency 24.576MHz */
CLOCK_MHZ(64UL), /*!< AVPLL channel frequency 64MHz */
CLOCK_KHZ(98304UL), /*!< AVPLL channel frequency 98.304MHz */
};
static const uint32_t s_avpllFreqOff[] = {
0U, /*!< AVPLL channel unchanged */
0x53U, /*!< AVPLL channel frequency 2.048MHz */
0x1050U, /*!< AVPLL channel frequency 4.096MHz */
0x4145DU, /*!< AVPLL channel frequency 6.144MHz */
0x4145DU, /*!< AVPLL channel frequency 8.192MHz */
0x38B3U, /*!< AVPLL channel frequency 11.2896MHz */
0U, /*!< AVPLL channel frequency 12MHz */
0x4145DU, /*!< AVPLL channel frequency 12.288MHz */
0x4145DU, /*!< AVPLL channel frequency 24.576MHz */
0xCCCDU, /*!< AVPLL channel frequency 64MHz */
0x4145DU, /*!< AVPLL channel frequency 98.304MHz */
};
static const uint32_t s_avpllPostDiv[] = {
0U, /*!< AVPLL channel unchanged */
791U, /*!< AVPLL channel frequency 2.048MHz */
395U, /*!< AVPLL channel frequency 4.096MHz */
264U, /*!< AVPLL channel frequency 6.144MHz */
198U, /*!< AVPLL channel frequency 8.192MHz */
143U, /*!< AVPLL channel frequency 11.2896MHz */
135U, /*!< AVPLL channel frequency 12MHz */
132U, /*!< AVPLL channel frequency 12.288MHz */
66U, /*!< AVPLL channel frequency 24.576MHz */
25U, /*!< AVPLL channel frequency 64MHz */
16U, /*!< AVPLL channel frequency 98.304MHz */
};
static const uint32_t s_avpllPostDiv0p5[] = {
0U, /*!< AVPLL channel unchanged */
0U, /*!< AVPLL channel frequency 2.048MHz */
0U, /*!< AVPLL channel frequency 4.096MHz */
0U, /*!< AVPLL channel frequency 6.144MHz */
0U, /*!< AVPLL channel frequency 8.192MHz */
0U, /*!< AVPLL channel frequency 11.2896MHz */
0U, /*!< AVPLL channel frequency 12MHz */
0U, /*!< AVPLL channel frequency 12.288MHz */
0U, /*!< AVPLL channel frequency 24.576MHz */
0U, /*!< AVPLL channel frequency 64MHz */
1U, /*!< AVPLL channel frequency 98.304MHz */
};
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
/* Workaround iar/armgcc optimization issue */
__attribute__((__noinline__))
static void CLOCK_Delay(uint32_t loop)
{
if (loop > 0U)
{
__ASM volatile(
"1: \n"
" SUBS %0, %0, #1 \n"
" CMP %0, #0 \n"
" BNE 1b \n"
:
: "r"(loop));
}
}
static void CLOCK_DelayUs(uint32_t us)
{
uint32_t instNum;
instNum = ((SystemCoreClock + 999999UL) / 1000000UL) * us;
CLOCK_Delay((instNum + 2U) / 3U);
}
/*! @brief Return Frequency of t3pll_mci_48_60m_irc
* @return Frequency of t3pll_mci_48_60m_irc
*/
uint32_t CLOCK_GetT3PllMciIrcClkFreq(void)
{
uint32_t freq = 0U;
if ((SYSPLL_T3->CLKTREE_CTRL_SIX_REG & 0xFU) == 0x5U)
{
freq = CLOCK_MHZ(2560UL) / 43UL;
}
else if ((SYSPLL_T3->CLKTREE_CTRL_SIX_REG & 0xFU) == 0xAU)
{
freq = CLOCK_MHZ(2560UL) / 53UL;
}
else
{
/* Only 48MHz and 60MHz is allowed */
assert(false);
}
return freq;
}
/*! @brief Return Frequency of t3pll_mci_213p3m
* @return Frequency of t3pll_mci_213p3m
*/
uint32_t CLOCK_GetT3PllMci213mClkFreq(void)
{
uint32_t freq = CLOCK_KHZ(213300UL);
return freq;
}
/*! @brief Return Frequency of t3pll_mci_256m
* @return Frequency of t3pll_mci_256m
*/
uint32_t CLOCK_GetT3PllMci256mClkFreq(void)
{
uint32_t freq = CLOCK_MHZ(256UL);
return freq;
}
/*! @brief Return Frequency of t3pll_mci_flexspi_clk
* @return Frequency of t3pll_mci_flexspi_clk
*/
uint32_t CLOCK_GetT3PllMciFlexspiClkFreq(void)
{
uint32_t freq = CLOCK_MHZ(365UL);
;
return freq;
}
static uint32_t CLOCK_GetTcpuFvcoFreq(void)
{
uint32_t freq = 0UL;
uint32_t steps;
steps = (SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_TCPU_FBDIV_MASK) >> SYSCTL2_PLL_CTRL_TCPU_FBDIV_SHIFT;
if ((CLK_XTAL_OSC_CLK == CLK_XTAL_OSC_CLK_40000KHZ) && (steps >= 75UL) && (steps <= 96UL))
{
/* Fbdiv from 75 to 96, step 40MHz */
steps -= 75UL;
freq = CLOCK_MHZ(3000UL) + steps * CLOCK_MHZ(40UL);
}
else if ((CLK_XTAL_OSC_CLK == CLK_XTAL_OSC_CLK_38400KHZ) && (steps >= 78UL) && (steps <= 100UL))
{
/* Fbdiv from 78 to 100, step 38.4MHz */
steps -= 78UL;
freq = CLOCK_KHZ(2995200UL) + steps * CLOCK_KHZ(38400UL);
}
else
{
assert(false);
}
return freq;
}
/*! @brief Return Frequency of tcpu_mci_clk
* return Frequency of tcpu_mci_clk
*/
uint32_t CLOCK_GetTcpuMciClkFreq(void)
{
uint32_t freq = CLOCK_GetTcpuFvcoFreq() / 12UL;
return freq;
}
/*! @brief Return Frequency of tcpu_mci_flexspi_clk
* @return Frequency of tcpu_mci_flexspi_clk
*/
uint32_t CLOCK_GetTcpuMciFlexspiClkFreq(void)
{
uint32_t div =
(SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_TCPU_FLEXSPI_CLK_SEL_MASK) >> SYSCTL2_PLL_CTRL_TCPU_FLEXSPI_CLK_SEL_SHIFT;
return CLOCK_GetTcpuFvcoFreq() / (12UL - div);
}
/*! @brief Return Frequency of tddr_mci_flexspi_clk
* @return Frequency of tddr_mci_flexspi_clk
*/
uint32_t CLOCK_GetTddrMciFlexspiClkFreq(void)
{
uint32_t div =
(SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_TDDR_FLEXSPI_CLK_SEL_MASK) >> SYSCTL2_PLL_CTRL_TDDR_FLEXSPI_CLK_SEL_SHIFT;
/* TDDR FVCO fixed to 3.2GHz */
return CLOCK_MHZ(3200UL) / (11UL - div);
}
/*! @brief Return Frequency of tddr_mci_enet_clk
* @return Frequency of tddr_mci_enet_clk
*/
uint32_t CLOCK_GetTddrMciEnetClkFreq(void)
{
uint32_t freq = CLOCK_MHZ(50UL);
return freq;
}
/*!
* @brief Enable the clock for specific IP.
*
* @param clk Which clock to enable, see @ref clock_ip_name_t.
*/
void CLOCK_EnableClock(clock_ip_name_t clk)
{
uint32_t index;
if (clk == kCLOCK_RefClkCauSlp)
{
PMU->CAU_SLP_CTRL &= ~PMU_CAU_SLP_CTRL_CAU_SOC_SLP_CG_MASK;
while ((PMU->CAU_SLP_CTRL & PMU_CAU_SLP_CTRL_SOC_SLP_RDY_MASK) == 0U)
{
}
}
else if (((uint32_t)clk & SYS_CLK_GATE_FLAG_MASK) != 0U)
{
SYSCTL2->SOURCE_CLK_GATE &= ~SYS_CLK_GATE_BIT_MASK(clk);
/* Delay 2 40MHz cycles to make it ready. */
CLOCK_Delay(CLOCK_DELAY_LOOPS(SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY, 40000000UL, 2U));
}
else
{
index = CLK_GATE_ABSTRACT_REG_OFFSET(clk);
switch (index)
{
case CLK_CTL0_PSCCTL0:
CLKCTL0->PSCCTL0_SET = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL0_PSCCTL1:
CLKCTL0->PSCCTL1_SET = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL0_PSCCTL2:
CLKCTL0->PSCCTL2_SET = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL1_PSCCTL0:
CLKCTL1->PSCCTL0_SET = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL1_PSCCTL1:
CLKCTL1->PSCCTL1_SET = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL1_PSCCTL2:
CLKCTL1->PSCCTL2_SET = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
default:
assert(false);
break;
}
if (clk == kCLOCK_Gau)
{
SYSCTL2->GAU_CTRL = SYSCTL2_GAU_CTRL_GAU_GPDAC_MCLK_EN_MASK | SYSCTL2_GAU_CTRL_GAU_BG_MCLK_EN_MASK |
SYSCTL2_GAU_CTRL_GAU_GPADC1_MCLK_EN_MASK | SYSCTL2_GAU_CTRL_GAU_GPADC0_MCLK_EN_MASK |
SYSCTL2_GAU_CTRL_GAU_ACOMP_MCLK_EN_MASK;
}
}
}
/*!
* @brief Disable the clock for specific IP.
*
* @param clk Which clock to disable, see @ref clock_ip_name_t.
*/
void CLOCK_DisableClock(clock_ip_name_t clk)
{
uint32_t index;
if (clk == kCLOCK_RefClkCauSlp)
{
PMU->CAU_SLP_CTRL |= PMU_CAU_SLP_CTRL_CAU_SOC_SLP_CG_MASK;
}
else if (((uint32_t)clk & SYS_CLK_GATE_FLAG_MASK) != 0U)
{
SYSCTL2->SOURCE_CLK_GATE |= SYS_CLK_GATE_BIT_MASK(clk);
}
else
{
index = CLK_GATE_ABSTRACT_REG_OFFSET(clk);
switch (index)
{
case CLK_CTL0_PSCCTL0:
CLKCTL0->PSCCTL0_CLR = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL0_PSCCTL1:
CLKCTL0->PSCCTL1_CLR = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL0_PSCCTL2:
CLKCTL0->PSCCTL2_CLR = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL1_PSCCTL0:
CLKCTL1->PSCCTL0_CLR = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL1_PSCCTL1:
CLKCTL1->PSCCTL1_CLR = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
case CLK_CTL1_PSCCTL2:
CLKCTL1->PSCCTL2_CLR = (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
break;
default:
assert(false);
break;
}
if (clk == kCLOCK_Gau)
{
SYSCTL2->GAU_CTRL = 0U;
}
}
}
/**
* @brief Configure the clock selection muxes.
* @param connection : Clock to be configured.
*/
void CLOCK_AttachClk(clock_attach_id_t connection)
{
bool final_descriptor = false;
uint32_t i;
volatile uint32_t *pClkSel;
if (((uint32_t)connection & PMU_TUPLE_MUX_AVAIL) != 0U)
{
*PMU_TUPLE_REG(PMU, connection) = PMU_TUPLE_SEL(connection);
}
else if (((uint32_t)connection & CLKOUT_TUPLE_MUX_AVAIL) != 0U)
{
CLKCTL1->CLKOUTSEL0 = CLKCTL1_CLKOUTSEL0_SEL(((uint32_t)connection >> 4U) & 0x7U);
CLKCTL1->CLKOUTSEL1 = CLKCTL1_CLKOUTSEL1_SEL(((uint32_t)connection >> 8U) & 0x7U);
CLKCTL1->CLKOUTSEL2 = CLKCTL1_CLKOUTSEL2_SEL(((uint32_t)connection >> 12U) & 0x7U);
}
else
{
for (i = 0U; (i < 2U) && (!final_descriptor); i++)
{
connection =
(clock_attach_id_t)(uint32_t)(((uint32_t)connection) >> (i * 16U)); /*!< pick up next descriptor */
if ((((uint32_t)connection) & CLKCTL1_TUPLE_FLAG_MASK) != 0UL)
{
pClkSel = CLKCTL_TUPLE_REG(CLKCTL1, connection);
}
else
{
pClkSel = CLKCTL_TUPLE_REG(CLKCTL0, connection);
}
if ((((uint32_t)connection) & 0xFFCU) != 0UL)
{
*pClkSel = CLKCTL_TUPLE_SEL(connection);
}
else
{
final_descriptor = true;
}
}
}
}
/**
* @brief Setup clock dividers.
* @param name : Clock divider name
* @param divider : Value to be divided.
*/
void CLOCK_SetClkDiv(clock_div_name_t name, uint32_t divider)
{
volatile uint32_t *pClkDiv;
if ((((uint32_t)name) & CLKCTL1_TUPLE_FLAG_MASK) != 0UL)
{
pClkDiv = CLKCTL_TUPLE_REG(CLKCTL1, name);
}
else
{
pClkDiv = CLKCTL_TUPLE_REG(CLKCTL0, name);
}
/* Reset the divider counter */
*pClkDiv |= 1UL << 29U;
if (divider == 0U) /*!< halt */
{
*pClkDiv |= 1UL << 30U;
}
else
{
*pClkDiv = divider - 1U;
while (((*pClkDiv) & 0x80000000U) != 0UL)
{
}
}
}
/*! brief Return Frequency of selected clock
* return Frequency of selected clock
*/
uint32_t CLOCK_GetFreq(clock_name_t clockName)
{
uint32_t freq;
switch (clockName)
{
case kCLOCK_CoreSysClk:
case kCLOCK_BusClk:
freq = CLOCK_GetCoreSysClkFreq();
break;
case kCLOCK_MclkClk:
freq = CLOCK_GetMclkClkFreq();
break;
default:
freq = 0U;
break;
}
return freq;
}
/*! @brief Return Frequency of High-Freq output of FRO
* @return Frequency of High-Freq output of FRO
*/
uint32_t CLOCK_GetFFroFreq(void)
{
return CLOCK_GetT3PllMciIrcClkFreq();
}
/*! @brief Return Frequency of SFRO
* @return Frequency of SFRO
*/
uint32_t CLOCK_GetSFroFreq(void)
{
return CLOCK_GetT3PllMci256mClkFreq() / 16U;
}
/*! @brief Return Frequency of AUDIO PLL (AVPLL CH1)
* @return Frequency of AUDIO PLL
*/
uint32_t CLOCK_GetAvPllCh1Freq(void)
{
uint32_t postdiv =
(SYSCTL2->AVPLL_CTRL5 & SYSCTL2_AVPLL_CTRL5_POSTDIV_C1_MASK) >> SYSCTL2_AVPLL_CTRL5_POSTDIV_C1_SHIFT;
uint32_t i;
uint32_t freq = 0U;
for (i = 1U; i < ARRAY_SIZE(s_avpllPostDiv); i++)
{
if (s_avpllPostDiv[i] == postdiv)
{
freq = s_avpllFreq[i];
break;
}
}
return freq;
}
/*! @brief Return Frequency of AVPLL CH2
* @return Frequency of AVPLL CH2
*/
uint32_t CLOCK_GetAvPllCh2Freq(void)
{
uint32_t postdiv =
(SYSCTL2->AVPLL_CTRL11 & SYSCTL2_AVPLL_CTRL11_POSTDIV_C2_MASK) >> SYSCTL2_AVPLL_CTRL11_POSTDIV_C2_SHIFT;
uint32_t i;
uint32_t freq = 0U;
for (i = 1U; i < ARRAY_SIZE(s_avpllPostDiv); i++)
{
if (s_avpllPostDiv[i] == postdiv)
{
freq = s_avpllFreq[i];
break;
}
}
return freq;
}
static uint32_t CLOCK_GetMainPllClkFreq(void)
{
return CLOCK_GetTcpuMciClkFreq() / ((CLKCTL0->MAINPLLCLKDIV & CLKCTL0_MAINPLLCLKDIV_DIV_MASK) + 1U);
}
static uint32_t CLOCK_GetAux0PllClkFreq(void)
{
return CLOCK_GetTcpuMciClkFreq() / ((CLKCTL0->AUX0PLLCLKDIV & CLKCTL0_AUX0PLLCLKDIV_DIV_MASK) + 1U);
}
static uint32_t CLOCK_GetAux1PllClkFreq(void)
{
return CLOCK_GetT3PllMci213mClkFreq() / ((CLKCTL0->AUX1PLLCLKDIV & CLKCTL0_AUX1PLLCLKDIV_DIV_MASK) + 1U);
}
static uint32_t CLOCK_GetAudioPllClkFreq(void)
{
return CLOCK_GetAvPllCh1Freq() / ((CLKCTL1->AUDIOPLLCLKDIV & CLKCTL1_AUDIOPLLCLKDIV_DIV_MASK) + 1U);
}
/* 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_GetSysOscFreq();
break;
case CLKCTL0_MAINCLKSELA_SEL(1):
freq = CLOCK_GetFFroFreq() / 4U;
break;
case CLKCTL0_MAINCLKSELA_SEL(2):
freq = CLOCK_GetLpOscFreq();
break;
case CLKCTL0_MAINCLKSELA_SEL(3):
freq = CLOCK_GetFFroFreq();
break;
default:
freq = 0U;
break;
}
break;
case CLKCTL0_MAINCLKSELB_SEL(1):
freq = CLOCK_GetSFroFreq();
break;
case CLKCTL0_MAINCLKSELB_SEL(2):
freq = CLOCK_GetMainPllClkFreq();
break;
case CLKCTL0_MAINCLKSELB_SEL(3):
freq = CLOCK_GetClk32KFreq();
break;
default:
freq = 0U;
break;
}
return freq;
}
/* Get Core/Bus Clk */
/*! @brief Return Frequency of core/bus clk
* @return Frequency of core/bus clk
*/
uint32_t CLOCK_GetCoreSysClkFreq(void)
{
return CLOCK_GetMainClkFreq() / ((CLKCTL0->SYSCPUAHBCLKDIV & CLKCTL0_SYSCPUAHBCLKDIV_DIV_MASK) + 1U);
}
/*! @brief Return Frequency of systick clk
* @return Frequency of systick clk
*/
uint32_t CLOCK_GetSystickClkFreq(void)
{
uint32_t freq = 0U;
switch (CLKCTL0->SYSTICKFCLKSEL)
{
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_GetClk32KFreq();
break;
case CLKCTL0_SYSTICKFCLKSEL_SEL(3):
freq = CLOCK_GetSFroFreq();
break;
default:
freq = 0U;
break;
}
return freq;
}
/* 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;
if (id <= 3UL)
{
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;
}
else if (id == 14UL)
{
clkSel = CLKCTL1->FRG14CLKSEL & CLKCTL1_FRG14CLKSEL_SEL_MASK;
frgMul = ((CLKCTL1->FRG14CTL) & CLKCTL1_FRGCTL_MULT_MASK) >> CLKCTL1_FRGCTL_MULT_SHIFT;
frgDiv = ((CLKCTL1->FRG14CTL) & CLKCTL1_FRGCTL_DIV_MASK) >> CLKCTL1_FRGCTL_DIV_SHIFT;
}
else
{
assert(false);
}
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 = CLOCK_GetSFroFreq();
break;
case CLKCTL1_FRGCLKSEL_SEL(3):
freq = CLOCK_GetFFroFreq();
break;
default:
freq = 0U;
break;
}
return (uint32_t)(((uint64_t)freq * ((uint64_t)frgDiv + 1ULL)) / (frgMul + frgDiv + 1UL));
}
/* 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 <= 14U);
assert(config->divider == 255U); /* Always set to 0xFF to use with the fractional baudrate generator.*/
if (i <= 3UL)
{
CLKCTL1->FLEXCOMM[i].FRGCLKSEL = (uint32_t)config->sfg_clock_src;
CLKCTL1->FLEXCOMM[i].FRGCTL = (CLKCTL1_FRGCTL_MULT(config->mult) | CLKCTL1_FRGCTL_DIV(config->divider));
}
else if (i == 14UL)
{
CLKCTL1->FRG14CLKSEL = (uint32_t)config->sfg_clock_src;
CLKCTL1->FRG14CTL = (CLKCTL1_FRGCTL_MULT(config->mult) | CLKCTL1_FRGCTL_DIV(config->divider));
}
else
{
assert(false);
}
}
/*! @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 = CLOCK_GetSFroFreq();
break;
case CLKCTL1_DMIC0FCLKSEL_SEL(1):
freq = CLOCK_GetFFroFreq();
break;
case CLKCTL1_DMIC0FCLKSEL_SEL(2):
freq = CLOCK_GetAudioPllClkFreq();
break;
case CLKCTL1_DMIC0FCLKSEL_SEL(3):
freq = CLOCK_GetMclkInClkFreq();
break;
case CLKCTL1_DMIC0FCLKSEL_SEL(4):
freq = CLOCK_GetLpOscFreq();
break;
case CLKCTL1_DMIC0FCLKSEL_SEL(5):
freq = CLOCK_GetClk32KFreq();
break;
case CLKCTL1_DMIC0FCLKSEL_SEL(6):
freq = CLOCK_GetMainClkFreq();
break;
default:
freq = 0U;
break;
}
return freq / ((CLKCTL1->DMIC0CLKDIV & CLKCTL1_DMIC0CLKDIV_DIV_MASK) + 1U);
}
/*! @brief Return Frequency of LCD clk
* @return Frequency of LCD clk
*/
uint32_t CLOCK_GetLcdClkFreq(void)
{
uint32_t freq = 0U;
switch ((CLKCTL0->LCDFCLKSEL) & CLKCTL0_LCDFCLKSEL_SEL_MASK)
{
case CLKCTL0_LCDFCLKSEL_SEL(0):
freq = CLOCK_GetMainClkFreq();
break;
case CLKCTL0_LCDFCLKSEL_SEL(1):
freq = CLOCK_GetT3PllMciFlexspiClkFreq();
break;
case CLKCTL0_LCDFCLKSEL_SEL(2):
freq = CLOCK_GetTcpuMciFlexspiClkFreq();
break;
case CLKCTL0_LCDFCLKSEL_SEL(3):
freq = CLOCK_GetTddrMciFlexspiClkFreq();
break;
default:
freq = 0U;
break;
}
return freq / ((CLKCTL0->LCDFCLKDIV & CLKCTL0_LCDFCLKDIV_DIV_MASK) + 1U);
}
/*! @brief Return Frequency of WDT clk
* @return Frequency of WDT clk
*/
uint32_t CLOCK_GetWdtClkFreq(void)
{
uint32_t freq = 0U;
switch ((CLKCTL0->WDT0FCLKSEL) & CLKCTL0_WDT0FCLKSEL_SEL_MASK)
{
case CLKCTL0_WDT0FCLKSEL_SEL(0):
freq = CLOCK_GetLpOscFreq();
break;
case CLKCTL0_WDT0FCLKSEL_SEL(1):
freq = CLOCK_GetMainClkFreq();
break;
default:
freq = 0U;
break;
}
return freq;
}
/*! @brief Return Frequency of mclk
* @return Frequency of mclk clk
*/
uint32_t CLOCK_GetMclkClkFreq(void)
{
uint32_t freq = 0U;
switch ((CLKCTL1->AUDIOMCLKSEL) & CLKCTL1_AUDIOMCLKSEL_SEL_MASK)
{
case CLKCTL1_AUDIOMCLKSEL_SEL(0):
freq = CLOCK_GetFFroFreq();
break;
case CLKCTL1_AUDIOMCLKSEL_SEL(1):
freq = CLOCK_GetAudioPllClkFreq();
break;
case CLKCTL1_AUDIOMCLKSEL_SEL(2):
freq = CLOCK_GetMainClkFreq();
break;
default:
freq = 0U;
break;
}
return freq / ((CLKCTL1->AUDIOMCLKDIV & CLKCTL1_AUDIOMCLKDIV_DIV_MASK) + 1U);
}
/*! @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 = CLOCK_GetFFroFreq();
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->SCTFCLKDIV & CLKCTL0_SCTFCLKDIV_DIV_MASK) + 1U);
}
/*! @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;
if (id <= 3UL)
{
clkSel = CLKCTL1->FLEXCOMM[id].FCFCLKSEL;
}
else if (id == 14UL)
{
clkSel = CLKCTL1->FC14FCLKSEL;
}
else
{
assert(false);
}
switch (clkSel)
{
case CLKCTL1_FCFCLKSEL_SEL(0):
freq = CLOCK_GetSFroFreq();
break;
case CLKCTL1_FCFCLKSEL_SEL(1):
freq = CLOCK_GetFFroFreq();
break;
case CLKCTL1_FCFCLKSEL_SEL(2):
freq = CLOCK_GetAudioPllClkFreq();
break;
case CLKCTL1_FCFCLKSEL_SEL(3):
freq = CLOCK_GetMclkInClkFreq();
break;
case CLKCTL1_FCFCLKSEL_SEL(4):
freq = CLOCK_GetFRGClock(id);
break;
default:
freq = 0U;
break;
}
return freq;
}
/*! @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;
assert(id < 4U);
switch ((CLKCTL1->CT32BITFCLKSEL[id]) & CLKCTL1_CT32BITFCLKSEL_SEL_MASK)
{
case CLKCTL1_CT32BITFCLKSEL_SEL(0):
freq = CLOCK_GetMainClkFreq();
break;
case CLKCTL1_CT32BITFCLKSEL_SEL(1):
freq = CLOCK_GetSFroFreq();
break;
case CLKCTL1_CT32BITFCLKSEL_SEL(2):
freq = CLOCK_GetFFroFreq();
break;
case CLKCTL1_CT32BITFCLKSEL_SEL(3):
freq = CLOCK_GetAudioPllClkFreq();
break;
case CLKCTL1_CT32BITFCLKSEL_SEL(4):
freq = CLOCK_GetMclkInClkFreq();
break;
case CLKCTL1_CT32BITFCLKSEL_SEL(5):
freq = CLOCK_GetLpOscFreq();
break;
default:
freq = 0U;
break;
}
return freq;
}
/*! @brief Return Frequency of Utick Clock
* @return Frequency of Utick Clock
*/
uint32_t CLOCK_GetUtickClkFreq(void)
{
uint32_t freq = 0U;
switch ((CLKCTL0->UTICKFCLKSEL) & CLKCTL0_UTICKFCLKSEL_SEL_MASK)
{
case CLKCTL0_UTICKFCLKSEL_SEL(0):
freq = CLOCK_GetLpOscFreq();
break;
case CLKCTL1_CT32BITFCLKSEL_SEL(1):
freq = CLOCK_GetMainClkFreq();
break;
default:
freq = 0U;
break;
}
return freq;
}
/*! @brief Return Frequency of FLEXSPI Clock
* @return Frequency of FLEXSPI.
*/
uint32_t CLOCK_GetFlexspiClkFreq(void)
{
uint32_t freq = 0U;
switch ((CLKCTL0->FLEXSPIFCLKSEL) & CLKCTL0_FLEXSPIFCLKSEL_SEL_MASK)
{
case CLKCTL0_FLEXSPIFCLKSEL_SEL(0):
freq = CLOCK_GetMainClkFreq();
break;
case CLKCTL0_FLEXSPIFCLKSEL_SEL(1):
freq = CLOCK_GetT3PllMciFlexspiClkFreq();
break;
case CLKCTL0_FLEXSPIFCLKSEL_SEL(2):
freq = CLOCK_GetAux0PllClkFreq();
break;
case CLKCTL0_FLEXSPIFCLKSEL_SEL(3):
freq = CLOCK_GetFFroFreq();
break;
case CLKCTL0_FLEXSPIFCLKSEL_SEL(4):
freq = CLOCK_GetAux1PllClkFreq();
break;
case CLKCTL0_FLEXSPIFCLKSEL_SEL(5):
freq = CLOCK_GetTddrMciFlexspiClkFreq();
break;
case CLKCTL0_FLEXSPIFCLKSEL_SEL(6):
freq = CLOCK_GetT3PllMci256mClkFreq();
break;
default:
freq = 0U;
break;
}
return freq / ((CLKCTL0->FLEXSPIFCLKDIV & CLKCTL0_FLEXSPIFCLKDIV_DIV_MASK) + 1U);
}
/*! @brief Return Frequency of USIM Clock
* @return Frequency of USIM.
*/
uint32_t CLOCK_GetUsimClkFreq(void)
{
uint32_t freq = 0U;
switch ((CLKCTL0->USIMFCLKSEL) & CLKCTL0_USIMFCLKSEL_SEL_MASK)
{
case CLKCTL0_USIMFCLKSEL_SEL(0):
freq = CLOCK_GetMainClkFreq();
break;
case CLKCTL0_USIMFCLKSEL_SEL(1):
freq = CLOCK_GetAudioPllClkFreq();
break;
case CLKCTL0_USIMFCLKSEL_SEL(2):
freq = CLOCK_GetFFroFreq();
break;
default:
freq = 0U;
break;
}
return freq / ((CLKCTL0->USIMFCLKDIV & CLKCTL0_USIMFCLKDIV_DIV_MASK) + 1U);
}
/*! @brief Return Frequency of GAU Clock
* @return Frequency of GAU.
*/
uint32_t CLOCK_GetGauClkFreq(void)
{
uint32_t freq = 0U;
switch ((CLKCTL0->GAUFCLKSEL) & CLKCTL0_GAUFCLKSEL_SEL_MASK)
{
case CLKCTL0_GAUFCLKSEL_SEL(0):
freq = CLOCK_GetMainClkFreq();
break;
case CLKCTL0_GAUFCLKSEL_SEL(1):
freq = CLOCK_GetT3PllMci256mClkFreq();
break;
case CLKCTL0_GAUFCLKSEL_SEL(2):
freq = CLOCK_GetAvPllCh2Freq();
break;
default:
freq = 0U;
break;
}
return freq / ((CLKCTL0->GAUFCLKDIV & CLKCTL0_GAUFCLKDIV_DIV_MASK) + 1U);
}
/*! @brief Return Frequency of OSTimer Clock
* @return Frequency of OSTimer.
*/
uint32_t CLOCK_GetOSTimerClkFreq(void)
{
uint32_t freq = 0U;
switch ((CLKCTL1->OSEVENTFCLKSEL) & CLKCTL1_OSEVENTFCLKSEL_SEL_MASK)
{
case CLKCTL1_OSEVENTFCLKSEL_SEL(0):
freq = CLOCK_GetLpOscFreq();
break;
case CLKCTL1_OSEVENTFCLKSEL_SEL(1):
freq = CLOCK_GetClk32KFreq();
break;
case CLKCTL1_OSEVENTFCLKSEL_SEL(2):
freq = CLOCK_GetCoreSysClkFreq();
break;
case CLKCTL1_OSEVENTFCLKSEL_SEL(3):
freq = CLOCK_GetMainClkFreq();
break;
default:
freq = 0U;
break;
}
return freq;
}
/*! @brief Enables and disables 32kHz XTAL
* @param enable : true to enable 32k XTAL clock, false to disable clock
*/
void CLOCK_EnableXtal32K(bool enable)
{
if (enable)
{
AON_SOC_CIU->PAD_PU_PD_EN1 &=
~(AON_SOC_CIU_PAD_PU_PD_EN1_GPIO22_PU_PD_EN_MASK | AON_SOC_CIU_PAD_PU_PD_EN1_GPIO23_PU_PD_EN_MASK);
AON_SOC_CIU->MCI_IOMUX_EN0 |= (3UL << 22);
PMU->XTAL32K_CTRL |= PMU_XTAL32K_CTRL_X32K_EN_MASK;
while ((PMU->XTAL32K_CTRL & PMU_XTAL32K_CTRL_X32K_RDY_MASK) == 0U)
{
}
}
else
{
PMU->XTAL32K_CTRL &= ~PMU_XTAL32K_CTRL_X32K_EN_MASK;
}
}
/*! @brief Enables and disables RTC 32KHz
* @param enable : true to enable 32k RTC clock, false to disable clock
*/
void CLOCK_EnableRtc32K(bool enable)
{
if (enable)
{
CLKCTL0->CLK32KHZCTL0 |= CLKCTL0_CLK32KHZCTL0_ENA_32KHZ_MASK;
}
else
{
CLKCTL0->CLK32KHZCTL0 &= ~CLKCTL0_CLK32KHZCTL0_ENA_32KHZ_MASK;
}
}
static uint32_t CLOCK_CfgTcpuRefClk(uint32_t targetHz, clock_tcpu_flexspi_div_t div)
{
uint32_t freq = 0UL;
uint32_t steps = 0UL;
if (CLK_XTAL_OSC_CLK == CLK_XTAL_OSC_CLK_40000KHZ)
{
/* Fbdiv from 75 to 96, step 40MHz */
freq = MAX(targetHz, CLOCK_MHZ(3000UL));
freq = MIN(freq, CLOCK_MHZ(3840UL));
/* Find the closest freq to target */
steps = (freq + CLOCK_MHZ(20UL) - CLOCK_MHZ(3000UL)) / CLOCK_MHZ(40UL);
freq = CLOCK_MHZ(3000UL) + steps * CLOCK_MHZ(40UL);
/* Get step register value */
steps += 75UL;
}
else if (CLK_XTAL_OSC_CLK == CLK_XTAL_OSC_CLK_38400KHZ)
{
/* Fbdiv from 78 to 100, step 38.4MHz */
freq = MAX(targetHz, CLOCK_KHZ(2995200UL));
freq = MIN(freq, CLOCK_MHZ(3840UL));
/* Find the closest freq to target */
steps = (freq + CLOCK_KHZ(19200UL) - CLOCK_KHZ(2995200UL)) / CLOCK_KHZ(38400UL);
freq = CLOCK_KHZ(2995200UL) + steps * CLOCK_KHZ(38400UL);
/* Get step register value */
steps += 78UL;
}
else
{
assert(false);
}
SYSCTL2->PLL_CTRL =
(SYSCTL2->PLL_CTRL & ~(SYSCTL2_PLL_CTRL_TCPU_FBDIV_MASK | SYSCTL2_PLL_CTRL_TCPU_FLEXSPI_CLK_SEL_MASK)) |
SYSCTL2_PLL_CTRL_TCPU_FBDIV(steps) | SYSCTL2_PLL_CTRL_TCPU_FLEXSPI_CLK_SEL(div);
return freq;
}
/*! @brief Initialize TCPU FVCO to target frequency.
* For 40MHz XTAL, FVCO ranges from 3000MHz to 3840MHz.
For 38.4MHz XTAL, FVCO ranges from 2995.2MHz to 3840MHz
* @param targetHz : Target FVCO frequency in Hz.
* @param div : Divider for tcpu_mci_flexspi_clk.
* @return Actual FVCO frequency in Hz.
*/
uint32_t CLOCK_InitTcpuRefClk(uint32_t targetHz, clock_tcpu_flexspi_div_t div)
{
uint32_t freq;
if ((SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_TCPU_PDB_MASK) != 0U)
{
CLOCK_DeinitTcpuRefClk();
}
SYSPLL_TCPU->TCPU_CTRL_ONE_REG = 0x74U;
freq = CLOCK_CfgTcpuRefClk(targetHz, div);
/* Set PDB */
SYSCTL2->PLL_CTRL |= SYSCTL2_PLL_CTRL_TCPU_PDB_MASK;
/* Wait PLL lock */
while ((SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_TCPU_LOCK_MASK) == 0U)
{
}
return freq;
}
/*! brief Deinit the TCPU reference clock.
* param none.
*/
void CLOCK_DeinitTcpuRefClk(void)
{
/* Gate all TCPU output clocks */
SYSCTL2->SOURCE_CLK_GATE |=
SYSCTL2_SOURCE_CLK_GATE_TCPU_MCI_CLK_CG_MASK | SYSCTL2_SOURCE_CLK_GATE_TCPU_MCI_FLEXSPI_CLK_CG_MASK;
/* Clear PDB */
SYSCTL2->PLL_CTRL &= ~SYSCTL2_PLL_CTRL_TCPU_PDB_MASK;
/* Wait PLL lock */
/* Ensure SystemCoreClock is up to date for accurate CLOCK_DelayUs() */
SystemCoreClockUpdate();
CLOCK_DelayUs(1U);
CLOCK_DisableClock(kCLOCK_RefClkTcpu);
}
/*! @brief Initialize the TDDR reference clock.
* @param div : Divider for tddr_mci_flexspi_clk.
*/
void CLOCK_InitTddrRefClk(clock_tddr_flexspi_div_t div)
{
if ((SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_TDDR_PDB_MASK) != 0U)
{
CLOCK_DeinitTddrRefClk();
}
REG_SYSPLL_TDDR->TDDR_CTRL_ONE_REG = 0x74U;
SYSCTL2->PLL_CTRL =
(SYSCTL2->PLL_CTRL & ~SYSCTL2_PLL_CTRL_TDDR_FLEXSPI_CLK_SEL_MASK) | SYSCTL2_PLL_CTRL_TDDR_FLEXSPI_CLK_SEL(div);
/* Set PDB */
SYSCTL2->PLL_CTRL |= SYSCTL2_PLL_CTRL_TDDR_PDB_MASK;
/* Wait PLL lock */
while ((SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_TDDR_LOCK_MASK) == 0U)
{
}
}
/*! brief Deinit the TDDR reference clock.
* param none.
*/
void CLOCK_DeinitTddrRefClk(void)
{
/* Gate all TDDR output clocks */
SYSCTL2->SOURCE_CLK_GATE |=
SYSCTL2_SOURCE_CLK_GATE_TDDR_MCI_ENET_CLK_CG_MASK | SYSCTL2_SOURCE_CLK_GATE_TDDR_MCI_FLEXSPI_CLK_CG_MASK;
/* Clear PDB */
SYSCTL2->PLL_CTRL &= ~SYSCTL2_PLL_CTRL_TDDR_PDB_MASK;
/* Wait PLL lock */
/* Ensure SystemCoreClock is up to date for accurate CLOCK_DelayUs() */
SystemCoreClockUpdate();
CLOCK_DelayUs(1U);
CLOCK_DisableClock(kCLOCK_RefClkTddr);
}
/*! @brief Initialize the T3 reference clock.
* @param cnfg : t3pll_mci_48_60m_irc clock configuration
*/
void CLOCK_InitT3RefClk(clock_t3_mci_irc_config_t cnfg)
{
if ((SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_T3_PDB_MASK) != 0U)
{
CLOCK_DeinitT3RefClk();
}
if (cnfg == kCLOCK_T3MciIrc60m)
{
SYSPLL_T3->CLKTREE_CTRL_SIX_REG = 0x5U;
}
else
{
SYSPLL_T3->CLKTREE_CTRL_SIX_REG = 0xAU;
}
/* Set PDB */
SYSCTL2->PLL_CTRL |= SYSCTL2_PLL_CTRL_T3_PDB_MASK;
/* Wait PLL lock */
while ((SYSCTL2->PLL_CTRL & SYSCTL2_PLL_CTRL_T3_LOCK_MASK) == 0U)
{
}
}
/*! brief Deinit the T3 reference clock.
* param none.
*/
void CLOCK_DeinitT3RefClk(void)
{
/* Ensure SystemCoreClock is up to date for accurate CLOCK_DelayUs() */
SystemCoreClockUpdate();
/* Gate all T3 output clocks */
SYSCTL2->SOURCE_CLK_GATE |=
SYSCTL2_SOURCE_CLK_GATE_T3PLL_MCI_48_60M_IRC_CG_MASK | SYSCTL2_SOURCE_CLK_GATE_T3PLL_MCI_256M_CG_MASK |
SYSCTL2_SOURCE_CLK_GATE_T3PLL_MCI_213P3M_CG_MASK | SYSCTL2_SOURCE_CLK_GATE_T3PLL_MCI_FLEXSPI_CLK_CG_MASK;
/* Clear PDB */
SYSCTL2->PLL_CTRL &= ~SYSCTL2_PLL_CTRL_T3_PDB_MASK;
/* Wait PLL lock */
CLOCK_DelayUs(1U);
}
static void CLOCK_ConfigAvPll(void)
{
uint32_t fbdiv = 0x51U;
uint32_t freq_offset_c8 = 0x0U;
uint32_t pll_calclk_div = 0x14U;
uint32_t refdiv = 0x2U;
uint32_t ext_speed = 0x2U;
uint32_t intpi = 0x3U;
uint32_t intpr = 0x4U;
uint32_t icp = 0x5U;
if (CLK_XTAL_OSC_CLK == CLK_XTAL_OSC_CLK_38400KHZ)
{
fbdiv = 0x54U;
freq_offset_c8 = 0x4924U;
pll_calclk_div = 0x13U;
}
SYSCTL2->AVPLL_CTRL2 =
(SYSCTL2->AVPLL_CTRL2 & ~(SYSCTL2_AVPLL_CTRL2_ICP_MASK | SYSCTL2_AVPLL_CTRL2_INTPI_MASK |
SYSCTL2_AVPLL_CTRL2_INTPR_MASK | SYSCTL2_AVPLL_CTRL2_PLL_CALCLK_DIV_MASK)) |
SYSCTL2_AVPLL_CTRL2_ICP(icp) | SYSCTL2_AVPLL_CTRL2_INTPI(intpi) | SYSCTL2_AVPLL_CTRL2_INTPR(intpr) |
SYSCTL2_AVPLL_CTRL2_PLL_CALCLK_DIV(pll_calclk_div);
SYSCTL2->AVPLL_CTRL3 =
(SYSCTL2->AVPLL_CTRL3 & ~SYSCTL2_AVPLL_CTRL3_REFDIV_MASK) | SYSCTL2_AVPLL_CTRL3_REFDIV(refdiv);
SYSCTL2->AVPLL_CTRL0 =
(SYSCTL2->AVPLL_CTRL0 & ~SYSCTL2_AVPLL_CTRL0_EXT_SPEED_MASK) | SYSCTL2_AVPLL_CTRL0_EXT_SPEED(ext_speed);
SYSCTL2->AVPLL_CTRL1 = (SYSCTL2->AVPLL_CTRL1 & ~SYSCTL2_AVPLL_CTRL1_FBDIV_MASK) | SYSCTL2_AVPLL_CTRL1_FBDIV(fbdiv);
SYSCTL2->AVPLL_CTRL8 =
(SYSCTL2->AVPLL_CTRL8 & ~(SYSCTL2_AVPLL_CTRL8_EN_LP_C8_MASK | SYSCTL2_AVPLL_CTRL8_FREQ_OFFSET_C8_MASK)) |
SYSCTL2_AVPLL_CTRL8_FREQ_OFFSET_C8(freq_offset_c8);
}
static void CLOCK_ConfigAvPllCh1(clock_avpll_ch_freq_t ch1Freq)
{
if (ch1Freq != kCLOCK_AvPllChUnchanged)
{
SYSCTL2->AVPLL_CTRL2 = (SYSCTL2->AVPLL_CTRL2 & ~SYSCTL2_AVPLL_CTRL2_POSTDIV_0P5_C1_MASK) |
SYSCTL2_AVPLL_CTRL2_POSTDIV_0P5_C1(s_avpllPostDiv0p5[(uint32_t)ch1Freq]);
SYSCTL2->AVPLL_CTRL1 = (SYSCTL2->AVPLL_CTRL1 & ~SYSCTL2_AVPLL_CTRL1_FREQ_OFFSET_C1_MASK) |
SYSCTL2_AVPLL_CTRL1_FREQ_OFFSET_C1(s_avpllFreqOff[(uint32_t)ch1Freq]);
SYSCTL2->AVPLL_CTRL5 = (SYSCTL2->AVPLL_CTRL5 & ~SYSCTL2_AVPLL_CTRL5_POSTDIV_C1_MASK) |
SYSCTL2_AVPLL_CTRL5_POSTDIV_C1(s_avpllPostDiv[(uint32_t)ch1Freq]);
}
}
static void CLOCK_ConfigAvPllCh2(clock_avpll_ch_freq_t ch2Freq)
{
if (ch2Freq != kCLOCK_AvPllChUnchanged)
{
SYSCTL2->AVPLL_CTRL12 = (SYSCTL2->AVPLL_CTRL12 & ~SYSCTL2_AVPLL_CTRL12_POSTDIV_0P5_C2_MASK) |
SYSCTL2_AVPLL_CTRL12_POSTDIV_0P5_C2(s_avpllPostDiv0p5[(uint32_t)ch2Freq]);
SYSCTL2->AVPLL_CTRL11 = SYSCTL2_AVPLL_CTRL11_FREQ_OFFSET_C2(s_avpllFreqOff[(uint32_t)ch2Freq]) |
SYSCTL2_AVPLL_CTRL11_POSTDIV_C2(s_avpllPostDiv[(uint32_t)ch2Freq]);
}
}
static void CLOCK_PowerUpAnaGrp(void)
{
uint32_t anaGrpPu = SYSCTL2->ANA_GRP_CTRL;
if ((anaGrpPu & SYSCTL2_ANA_GRP_CTRL_PU_AG_MASK) == 0U)
{
SYSCTL2->ANA_GRP_CTRL = anaGrpPu | SYSCTL2_ANA_GRP_CTRL_PU_AG_MASK;
CLOCK_DelayUs(50U); /* Delay 50us */
}
}
static void CLOCK_PowerDownAnaGrp(void)
{
uint32_t anaGrpPu = SYSCTL2->ANA_GRP_CTRL;
if ((anaGrpPu & SYSCTL2_ANA_GRP_CTRL_PU_AG_MASK) != 0U)
{
SYSCTL2->ANA_GRP_CTRL = anaGrpPu & ~SYSCTL2_ANA_GRP_CTRL_PU_AG_MASK;
}
}
/*! @brief Initialize the AVPLL.
* @param enableCh1 : Enable AVPLL channel1
* @param enableCh2 : Enable AVPLL channel2
* @param enableCali : Enable AVPLL calibration
*/
void CLOCK_EnableAvPllCh(bool enableCh1, bool enableCh2, bool enableCali)
{
uint32_t calDoneDelay;
/* Step 3: Pull up PU_C1 PU_C2 */
if (enableCh1)
{
SYSCTL2->AVPLL_CTRL2 |= SYSCTL2_AVPLL_CTRL2_PU_C1_MASK;
}
if (enableCh2)
{
SYSCTL2->AVPLL_CTRL12 |= SYSCTL2_AVPLL_CTRL12_PU_C2_MASK;
}
/* Pull up freq_offset_c8_ready */
SYSCTL2->AVPLL_CTRL8 |= SYSCTL2_AVPLL_CTRL8_FREQ_OFFSET_READY_C8_MASK;
CLOCK_DelayUs(3U); /* Delay 516*FVCO*4, about 3us */
/* Step 4: Pull low freq_offset_c8_ready */
SYSCTL2->AVPLL_CTRL8 &= ~SYSCTL2_AVPLL_CTRL8_FREQ_OFFSET_READY_C8_MASK;
CLOCK_DelayUs(2U); /* Delay more than 1us, recommended to delay 2us */
/* Step 5: Pull low RESET_C8 */
SYSCTL2->AVPLL_CTRL8 &= ~SYSCTL2_AVPLL_CTRL8_AVPLL_RESET_C8_MASK;
CLOCK_DelayUs(5U); /* Delay 5us. */
if (enableCali)
{
/* Step 6: Cali start */
SYSCTL2->AVPLL_CTRL2 |= SYSCTL2_AVPLL_CTRL2_PLL_CAL_START_MASK;
}
CLOCK_DelayUs(5U); /* Delay 5us */
/* Step 7: Pull low RESET_C1 RESET_C2 */
if (enableCh1)
{
SYSCTL2->AVPLL_CTRL8 &= ~SYSCTL2_AVPLL_CTRL8_AVPLL_RESET_C1_MASK;
}
if (enableCh2)
{
SYSCTL2->AVPLL_CTRL13 &= ~SYSCTL2_AVPLL_CTRL13_AVPLL_RESET_C2_MASK;
}
CLOCK_DelayUs(2U); /* Delay 516*FVCO , about 2us */
/* Step 8: Pull high freq_offset_ready_c1/c2 */
if (enableCh1)
{
SYSCTL2->AVPLL_CTRL1 |= SYSCTL2_AVPLL_CTRL1_FREQ_OFFSET_READY_C1_MASK;
}
if (enableCh2)
{
SYSCTL2->AVPLL_CTRL12 |= SYSCTL2_AVPLL_CTRL12_FREQ_OFFSET_READY_C2_MASK;
}
CLOCK_DelayUs(2U); /* Delay 516*FVCO , about 2us */
/* Step 9: pull low freq_offset_ready_c1/2 */
if (enableCh1)
{
SYSCTL2->AVPLL_CTRL1 &= ~SYSCTL2_AVPLL_CTRL1_FREQ_OFFSET_READY_C1_MASK;
}
if (enableCh2)
{
SYSCTL2->AVPLL_CTRL12 &= ~SYSCTL2_AVPLL_CTRL12_FREQ_OFFSET_READY_C2_MASK;
}
CLOCK_DelayUs(12U); /* Delay more than 10us, recommended 12 us */
if (enableCali)
{
/* Step 10: wait cali done */
calDoneDelay = 0U;
while (
((SYSCTL2->AVPLL_CTRL7 & SYSCTL2_AVPLL_CTRL7_PLL_CAL_DONE_MASK) != SYSCTL2_AVPLL_CTRL7_PLL_CAL_DONE_MASK) &&
(calDoneDelay < 600U)) /* Wait cali done or 600us */
{
calDoneDelay += 10U;
CLOCK_DelayUs(10U);
}
CLOCK_DelayUs(10U);
/* Step 11: clear cali start */
SYSCTL2->AVPLL_CTRL2 &= ~SYSCTL2_AVPLL_CTRL2_PLL_CAL_START_MASK;
}
}
/*! @brief Disable the AVPLL.
* @param disableCh1 : Disable AVPLL channel1, channel unchanged on false.
* @param disableCh2 : Disable AVPLL channel2, channel unchanged on false.
*/
void CLOCK_DisableAvPllCh(bool disableCh1, bool disableCh2)
{
if (disableCh1)
{
/* Pull up RESET_C1 */
SYSCTL2->AVPLL_CTRL8 |= SYSCTL2_AVPLL_CTRL8_AVPLL_RESET_C1_MASK;
/* Pull low PU_C1 */
SYSCTL2->AVPLL_CTRL2 &= ~SYSCTL2_AVPLL_CTRL2_PU_C1_MASK;
}
if (disableCh2)
{
/* Pull up RESET_C2 */
SYSCTL2->AVPLL_CTRL13 |= SYSCTL2_AVPLL_CTRL13_AVPLL_RESET_C2_MASK;
/* Pull low PU_C2 */
SYSCTL2->AVPLL_CTRL12 &= ~SYSCTL2_AVPLL_CTRL12_PU_C2_MASK;
}
}
/*! @brief Initialize the AVPLL.
* @param cnfg : AVPLL clock configuration
*/
void CLOCK_InitAvPll(const clock_avpll_config_t *cnfg)
{
assert(cnfg);
if ((SYSCTL2->AVPLL_CTRL2 & SYSCTL2_AVPLL_CTRL2_PU_MASK) != 0U)
{
/* Pull down AVPLL power for initialization. */
CLOCK_DeinitAvPll();
}
/* Ensure SystemCoreClock is up to date for accurate CLOCK_DelayUs() */
SystemCoreClockUpdate();
/* Ensure ANA_GRP is powered up */
CLOCK_PowerUpAnaGrp();
/* Configure CH1/CH2 frequency */
CLOCK_ConfigAvPll();
CLOCK_ConfigAvPllCh1(cnfg->ch1Freq);
CLOCK_ConfigAvPllCh2(cnfg->ch2Freq);
/* Step 1: Pull up PU */
SYSCTL2->AVPLL_CTRL2 |= SYSCTL2_AVPLL_CTRL2_PU_MASK;
CLOCK_DelayUs(15U); /* Wait more than 10us, recommended to delay 15us */
/* Step 2: Pull low RESET */
SYSCTL2->AVPLL_CTRL8 &= ~SYSCTL2_AVPLL_CTRL8_AVPLL_RESET_MASK;
CLOCK_DelayUs(15U); /* Wait more than 10us, recommended to delay 15us */
/* Enable channels */
CLOCK_EnableAvPllCh(true, true, cnfg->enableCali);
}
/*! @brief Deinit the AVPLL.
*/
void CLOCK_DeinitAvPll(void)
{
CLOCK_DisableAvPllCh(true, true);
/* Pull up RESET */
SYSCTL2->AVPLL_CTRL8 |= SYSCTL2_AVPLL_CTRL8_AVPLL_RESET_MASK;
/* Pull up RESET_C8 */
SYSCTL2->AVPLL_CTRL8 |= SYSCTL2_AVPLL_CTRL8_AVPLL_RESET_C8_MASK;
/* Pull low PU */
SYSCTL2->AVPLL_CTRL2 &= ~SYSCTL2_AVPLL_CTRL2_PU_MASK;
/* Disable REFCLK AUD. */
CLOCK_DisableClock(kCLOCK_RefClkAud);
if ((SYSCTL2->USB_CTRL & SYSCTL2_USB_CTRL_USB_PU_MASK) == 0U)
{
/* USB also not used, ANA_GRP can be powered down. */
CLOCK_PowerDownAnaGrp();
}
}
/*! @brief Update the AVPLL channel configuration. Enable/Disable state keeps unchanged.
* @param ch1Freq : Channel 1 frequency to set.
* @param ch2Freq : Channel 2 frequency to set.
* @param enableCali : Enable AVPLL calibration.
*/
void CLOCK_ConfigAvPllCh(clock_avpll_ch_freq_t ch1Freq, clock_avpll_ch_freq_t ch2Freq, bool enableCali)
{
bool needRenableCh1, needRenableCh2;
if ((ch1Freq == kCLOCK_AvPllChUnchanged) && (ch2Freq == kCLOCK_AvPllChUnchanged))
{
/* Nothing to change. */
return;
}
/* If channel enabled and need to update configuration, need to reenable. */
needRenableCh1 =
((SYSCTL2->AVPLL_CTRL2 & SYSCTL2_AVPLL_CTRL2_PU_C1_MASK) != 0U) && (ch1Freq != kCLOCK_AvPllChUnchanged);
needRenableCh2 =
((SYSCTL2->AVPLL_CTRL12 & SYSCTL2_AVPLL_CTRL12_PU_C2_MASK) != 0U) && (ch2Freq != kCLOCK_AvPllChUnchanged);
/* Disable channel before update configuration. */
CLOCK_DisableAvPllCh(needRenableCh1, needRenableCh2);
CLOCK_ConfigAvPll();
if (ch1Freq != kCLOCK_AvPllChUnchanged)
{
CLOCK_ConfigAvPllCh1(ch1Freq);
}
if (ch2Freq != kCLOCK_AvPllChUnchanged)
{
CLOCK_ConfigAvPllCh2(ch2Freq);
}
/* Reenable channel if needed. */
CLOCK_EnableAvPllCh(needRenableCh1, needRenableCh2, enableCali);
}
/*! @brief Enable USB HS PHY PLL clock.
*
* This function enables USB HS PHY PLL clock.
*/
void CLOCK_EnableUsbhsPhyClock(void)
{
uint32_t value;
value = SYSCTL2->USB_CTRL;
uint32_t delay = 100000;
/* Ensure SystemCoreClock is up to date for accurate CLOCK_DelayUs() */
SystemCoreClockUpdate();
/* Ensure ANA_GRP is powered on */
SYSCTL2->ANA_GRP_CTRL |= SYSCTL2_ANA_GRP_CTRL_PU_XTL_MASK;
CLOCK_PowerUpAnaGrp();
/* Reset USB PHY */
value |=
SYSCTL2_USB_CTRL_SOFT_PHY_RESET_MASK | SYSCTL2_USB_CTRL_PHY_RESET_SEL_MASK; /* Use soft reset to reset PHY */
SYSCTL2->USB_CTRL =
value & ~(SYSCTL2_USB_CTRL_USB_PU_PLL_MASK | SYSCTL2_USB_CTRL_USB_PU_MASK | SYSCTL2_USB_CTRL_USB_PU_OTG_MASK);
__NOP();
value &= ~(SYSCTL2_USB_CTRL_SOFT_PHY_RESET_MASK |
SYSCTL2_USB_CTRL_PHY_RESET_SEL_MASK); /* It is an active high reset; this bit is inverted */
SYSCTL2->USB_CTRL = value;
/* Power up PHY OTG detection circuit */
USBOTG->PHY_REG_OTG_CONTROL |= USBC_PHY_REG_CHGDTC_CONTRL_1_PD_EN_MASK;
/* Analog power up through pin */
value |= SYSCTL2_USB_CTRL_USB_PU_MASK | SYSCTL2_USB_CTRL_USB_PU_OTG_MASK;
SYSCTL2->USB_CTRL = value;
/* Power up PLL via pin; raising edge will auto trigger calibration */
value |= SYSCTL2_USB_CTRL_USB_PU_PLL_MASK;
SYSCTL2->USB_CTRL = value;
while ((delay-- > 0U) && ((USBOTG->PLL_CONTROL_0 & USBC_PLL_CONTROL_0_PLL_READY_MASK) == 0U))
{
}
}
/*! @brief Disable USB HS PHY PLL clock.
*
* This function disables USB HS PHY PLL clock.
*/
void CLOCK_DisableUsbhsPhyClock(void)
{
uint32_t value;
value = SYSCTL2->USB_CTRL;
/* Power down PHY OTG detection circuit */
USBOTG->PHY_REG_OTG_CONTROL |= USBC_PHY_REG_CHGDTC_CONTRL_1_PD_EN_MASK;
/* Analog power down through pin */
value &= ~SYSCTL2_USB_CTRL_USB_PU_MASK & ~SYSCTL2_USB_CTRL_USB_PU_OTG_MASK;
SYSCTL2->USB_CTRL = value;
/* Power down PLL via pin */
value &= ~SYSCTL2_USB_CTRL_USB_PU_PLL_MASK;
SYSCTL2->USB_CTRL = value;
if ((SYSCTL2->AVPLL_CTRL2 & SYSCTL2_AVPLL_CTRL2_PU_MASK) == 0U)
{
/* AVPLL also not used, ANA_GRP can be powered down. */
CLOCK_PowerDownAnaGrp();
}
SYSCTL2->ANA_GRP_CTRL &= ~SYSCTL2_ANA_GRP_CTRL_PU_XTL_MASK;
}