--- /dev/null
+/*\r
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.\r
+ * Copyright 2016 - 2019 , NXP\r
+ * All rights reserved.\r
+ *\r
+ *\r
+ * SPDX-License-Identifier: BSD-3-Clause\r
+ */\r
+\r
+#include "fsl_clock.h"\r
+#include "fsl_power.h"\r
+/*******************************************************************************\r
+ * Definitions\r
+ ******************************************************************************/\r
+/* Component ID definition, used by tools. */\r
+#ifndef FSL_COMPONENT_ID\r
+#define FSL_COMPONENT_ID "platform.drivers.clock"\r
+#endif\r
+#define NVALMAX (0x100U)\r
+#define PVALMAX (0x20U)\r
+#define MVALMAX (0x8000U)\r
+\r
+#define USB_NVALMAX (0x4U)\r
+#define USB_PVALMAX (0x8U)\r
+#define USB_MVALMAX (0x100U)\r
+\r
+#define PLL_MAX_N_DIV 0x100U\r
+#define USB_PLL_MAX_N_DIV 0x100U\r
+\r
+#define PLL_MDEC_VAL_P (0U) /*!< MDEC is in bits 16 downto 0 */\r
+#define PLL_MDEC_VAL_M (0x1FFFFUL << PLL_MDEC_VAL_P) /*!< NDEC is in bits 9 downto 0 */\r
+#define PLL_NDEC_VAL_P (0U) /*!< NDEC is in bits 9:0 */\r
+#define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P)\r
+#define PLL_PDEC_VAL_P (0U) /*!< PDEC is in bits 6:0 */\r
+#define PLL_PDEC_VAL_M (0x7FUL << PLL_PDEC_VAL_P)\r
+\r
+#define PLL_MIN_CCO_FREQ_MHZ (275000000U)\r
+#define PLL_MAX_CCO_FREQ_MHZ (550000000U)\r
+#define PLL_LOWER_IN_LIMIT (4000U) /*!< Minimum PLL input rate */\r
+#define PLL_MIN_IN_SSMODE (2000000U)\r
+#define PLL_MAX_IN_SSMODE (4000000U)\r
+\r
+/*!< Middle of the range values for spread-spectrum */\r
+#define PLL_SSCG_MF_FREQ_VALUE 4U\r
+#define PLL_SSCG_MC_COMP_VALUE 2U\r
+#define PLL_SSCG_MR_DEPTH_VALUE 4U\r
+#define PLL_SSCG_DITHER_VALUE 0U\r
+\r
+/*!< USB PLL CCO MAX AND MIN FREQ */\r
+#define USB_PLL_MIN_CCO_FREQ_MHZ (156000000U)\r
+#define USB_PLL_MAX_CCO_FREQ_MHZ (320000000U)\r
+#define USB_PLL_LOWER_IN_LIMIT (1000000U) /*!< Minimum PLL input rate */\r
+\r
+#define USB_PLL_MSEL_VAL_P (0U) /*!< MSEL is in bits 7 downto 0 */\r
+#define USB_PLL_MSEL_VAL_M (0xFFU)\r
+#define USB_PLL_PSEL_VAL_P (8U) /*!< PDEC is in bits 9:8 */\r
+#define USB_PLL_PSEL_VAL_M (0x3U)\r
+#define USB_PLL_NSEL_VAL_P (10U) /*!< NDEC is in bits 11:10 */\r
+#define USB_PLL_NSEL_VAL_M (0x3U)\r
+\r
+/*!< SWITCH USB POSTDIVIDER FOR REGITSER WRITING */\r
+#define SWITCH_USB_PSEL(x) \\r
+ (((x) == 0x0U) ? 0x1U : ((x) == 0x1U) ? 0x02U : ((x) == 0x2U) ? 0x4U : ((x) == 3U) ? 0x8U : 0U)\r
+\r
+/*!< SYS PLL NDEC reg */\r
+#define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)\r
+/*!< SYS PLL PDEC reg */\r
+#define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)\r
+/*!< SYS PLL MDEC reg */\r
+#define PLL_MDEC_VAL_SET(value) (((unsigned long)(value) << PLL_MDEC_VAL_P) & PLL_MDEC_VAL_M)\r
+\r
+/*!< SYS PLL NSEL reg */\r
+#define USB_PLL_NSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_NSEL_VAL_M) << USB_PLL_NSEL_VAL_P)\r
+/*!< SYS PLL PSEL reg */\r
+#define USB_PLL_PSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_PSEL_VAL_M) << USB_PLL_PSEL_VAL_P)\r
+/*!< SYS PLL MSEL reg */\r
+#define USB_PLL_MSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_MSEL_VAL_M) << USB_PLL_MSEL_VAL_P)\r
+\r
+/*!< FRAC control */\r
+#define AUDIO_PLL_FRACT_MD_P (0U)\r
+#define AUDIO_PLL_FRACT_MD_INT_P (15U)\r
+#define AUDIO_PLL_FRACT_MD_M (0x7FFFUL << AUDIO_PLL_FRACT_MD_P)\r
+#define AUDIO_PLL_FRACT_MD_INT_M (0x7FUL << AUDIO_PLL_FRACT_MD_INT_P)\r
+\r
+#define AUDIO_PLL_MD_FRACT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_P) & PLL_FRAC_MD_FRACT_M)\r
+#define AUDIO_PLL_MD_INT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_INT_P) & AUDIO_PLL_FRACT_MD_INT_M)\r
+\r
+/* Saved value of PLL output rate, computed whenever needed to save run-time\r
+ computation on each call to retrive the PLL rate. */\r
+static uint32_t s_Pll_Freq;\r
+static uint32_t s_Usb_Pll_Freq;\r
+static uint32_t s_Audio_Pll_Freq;\r
+\r
+/** External clock rate on the CLKIN pin in Hz. If not used,\r
+ set this to 0. Otherwise, set it to the exact rate in Hz this pin is\r
+ being driven at. */\r
+static const uint32_t g_I2S_Mclk_Freq = 0U;\r
+static const uint32_t g_Ext_Clk_Freq = 12000000U;\r
+static const uint32_t g_Lcd_Clk_In_Freq = 0U;\r
+\r
+/*******************************************************************************\r
+ * Variables\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ * Prototypes\r
+ ******************************************************************************/\r
+/* Find encoded NDEC value for raw N value, max N = NVALMAX */\r
+static uint32_t pllEncodeN(uint32_t N);\r
+/* Find decoded N value for raw NDEC value */\r
+static uint32_t pllDecodeN(uint32_t NDEC);\r
+/* Find encoded PDEC value for raw P value, max P = PVALMAX */\r
+static uint32_t pllEncodeP(uint32_t P);\r
+/* Find decoded P value for raw PDEC value */\r
+static uint32_t pllDecodeP(uint32_t PDEC);\r
+/* Find encoded MDEC value for raw M value, max M = MVALMAX */\r
+static uint32_t pllEncodeM(uint32_t M);\r
+/* Find decoded M value for raw MDEC value */\r
+static uint32_t pllDecodeM(uint32_t MDEC);\r
+/* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */\r
+static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);\r
+/* Get predivider (N) from PLL NDEC setting */\r
+static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg);\r
+/* Get postdivider (P) from PLL PDEC setting */\r
+static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg);\r
+/* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */\r
+static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg);\r
+/* Convert the binary to fractional part */\r
+static double Binary2Fractional(uint32_t binaryPart);\r
+/* Calculate the powerTimes' power of 2 */\r
+static uint32_t power2Cal(uint32_t powerTimes);\r
+/* Get the greatest common divisor */\r
+static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);\r
+/* Set PLL output based on desired output rate */\r
+static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup);\r
+\r
+/* Update local PLL rate variable */\r
+static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup);\r
+static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup);\r
+\r
+/*!\r
+ * @brief Set fro clock frequency.\r
+ * Due to LPC540xx 0A silicon and LPC540xx 1B silicon have different ROM addresses for set fro\r
+ * frequency api, so add this api to get rom version.\r
+ * @param base romVersion pointer to recieve rom version.\r
+ */\r
+#if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \\r
+ (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION)\r
+static uint32_t CLOCK_GetRomVersion(uint8_t *romVersion);\r
+#endif\r
+\r
+static const uint8_t wdtFreqLookup[32] = {0, 8, 12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41,\r
+ 42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61};\r
+/*******************************************************************************\r
+ * Code\r
+ ******************************************************************************/\r
+#if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \\r
+ (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION)\r
+static uint32_t CLOCK_GetRomVersion(uint8_t *romVersion)\r
+{\r
+ uint32_t command[5] = {0U}, result[4] = {0U};\r
+\r
+ command[0] = 55U;\r
+ result[0] = 0;\r
+ result[1] = 0;\r
+ ((void (*)(uint32_t cmd[5], uint32_t stat[4]))FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION)(command, result);\r
+\r
+ *romVersion = (uint8_t)(result[1]);\r
+\r
+ return result[0];\r
+}\r
+#endif\r
+\r
+/**\r
+ * brief\r
+ * Initialize the Core clock to given frequency (12, 48 or 96 MHz), this API is implememnt in ROM code.\r
+ * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed\r
+ * output is enabled.\r
+ * Usage: CLOCK_SetupFROClocking(frequency), (frequency must be one of 12, 48 or 96 MHz)\r
+ * Note: Need to make sure ROM and OTP has power(PDRUNCFG0[17,29]= 0U) before calling this API since this API is\r
+ * implemented in ROM code and the FROHF TRIM value is stored in OTP\r
+ *\r
+ * param froFreq target fro frequency.\r
+ * return Nothing\r
+ */\r
+\r
+void CLOCK_SetupFROClocking(uint32_t froFreq)\r
+{\r
+ uint32_t froRomAddr = 0U;\r
+#if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \\r
+ (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION)\r
+ uint8_t romVersion = 0U;\r
+\r
+ if (CLOCK_GetRomVersion(&romVersion) == (uint32_t)kStatus_Success)\r
+ {\r
+ if (romVersion == FSL_ROM_VERSION_1B)\r
+ {\r
+ froRomAddr = FSL_ROM_VERSION_1B_FRO_SETTING_ADDR;\r
+ }\r
+ else\r
+ {\r
+ froRomAddr = FSL_ROM_VERSION_0A_FRO_SETTING_ADDR;\r
+ }\r
+\r
+ (*((void (*)(uint32_t funcname))(froRomAddr)))(froFreq);\r
+ }\r
+#else\r
+ froRomAddr = FSL_ROM_VERSION_0A_FRO_SETTING_ADDR;\r
+\r
+ (*((void (*)(uint32_t))(froRomAddr)))(froFreq);\r
+#endif\r
+}\r
+\r
+/* Clock Selection for IP */\r
+/**\r
+ * brief Configure the clock selection muxes.\r
+ * param connection : Clock to be configured.\r
+ * return Nothing\r
+ */\r
+void CLOCK_AttachClk(clock_attach_id_t connection)\r
+{\r
+ uint8_t mux;\r
+ uint8_t sel;\r
+ uint16_t item;\r
+ uint32_t tmp32 = (uint32_t)connection;\r
+ uint32_t i;\r
+ volatile uint32_t *pClkSel;\r
+\r
+ pClkSel = &(SYSCON->STICKCLKSEL);\r
+\r
+ if (kNONE_to_NONE != connection)\r
+ {\r
+ for (i = 0U; i < 2U; i++)\r
+ {\r
+ if (tmp32 == 0U)\r
+ {\r
+ break;\r
+ }\r
+ item = (uint16_t)GET_ID_ITEM(tmp32);\r
+ if (item != 0UL)\r
+ {\r
+ mux = GET_ID_ITEM_MUX(item);\r
+ sel = GET_ID_ITEM_SEL(item);\r
+ if (mux == CM_ASYNCAPB)\r
+ {\r
+ SYSCON->ASYNCAPBCTRL = SYSCON_ASYNCAPBCTRL_ENABLE(1);\r
+ ASYNC_SYSCON->ASYNCAPBCLKSELA = sel;\r
+ }\r
+ else\r
+ {\r
+ ((volatile uint32_t *)pClkSel)[mux] = sel;\r
+ }\r
+ }\r
+ tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */\r
+ }\r
+ }\r
+}\r
+\r
+/* Return the actual clock attach id */\r
+/**\r
+ * brief Get the actual clock attach id.\r
+ * This fuction uses the offset in input attach id, then it reads the actual source value in\r
+ * the register and combine the offset to obtain an actual attach id.\r
+ * param attachId : Clock attach id to get.\r
+ * return Clock source value.\r
+ */\r
+clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)\r
+{\r
+ uint8_t mux;\r
+ uint8_t actualSel;\r
+ uint32_t tmp32 = (uint32_t)attachId;\r
+ uint32_t i;\r
+ uint32_t actualAttachId = 0U;\r
+ uint32_t selector = GET_ID_SELECTOR(tmp32);\r
+ volatile uint32_t *pClkSel;\r
+\r
+ pClkSel = &(SYSCON->STICKCLKSEL);\r
+\r
+ if (kNONE_to_NONE == attachId)\r
+ {\r
+ return kNONE_to_NONE;\r
+ }\r
+\r
+ for (i = 0U; i < 2U; i++)\r
+ {\r
+ mux = GET_ID_ITEM_MUX(tmp32);\r
+ if (tmp32 != 0UL)\r
+ {\r
+ if (mux == CM_ASYNCAPB)\r
+ {\r
+ actualSel = (uint8_t)(ASYNC_SYSCON->ASYNCAPBCLKSELA);\r
+ }\r
+ else\r
+ {\r
+ actualSel = (uint8_t)(((volatile uint32_t *)pClkSel)[mux]);\r
+ }\r
+\r
+ /* Consider the combination of two registers */\r
+ actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);\r
+ }\r
+ tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */\r
+ }\r
+\r
+ actualAttachId |= selector;\r
+\r
+ return (clock_attach_id_t)actualAttachId;\r
+}\r
+\r
+/* Set IP Clock Divider */\r
+/**\r
+ * brief Setup peripheral clock dividers.\r
+ * param div_name : Clock divider name\r
+ * param divided_by_value: Value to be divided\r
+ * param reset : Whether to reset the divider counter.\r
+ * return Nothing\r
+ */\r
+void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)\r
+{\r
+ volatile uint32_t *pClkDiv;\r
+\r
+ pClkDiv = &(SYSCON->SYSTICKCLKDIV);\r
+ if (reset)\r
+ {\r
+ ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 29U;\r
+ }\r
+ if (divided_by_value == 0U) /*!< halt */\r
+ {\r
+ ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 30U;\r
+ }\r
+ else\r
+ {\r
+ ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = (divided_by_value - 1U);\r
+ }\r
+}\r
+\r
+/* Get CLOCK OUT Clk */\r
+/*! brief Return Frequency of ClockOut\r
+ * return Frequency of ClockOut\r
+ */\r
+uint32_t CLOCK_GetClockOutClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->CLKOUTSELA)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+\r
+ case 1U:\r
+ freq = CLOCK_GetExtClkFreq();\r
+ break;\r
+\r
+ case 2U:\r
+ freq = CLOCK_GetWdtOscFreq();\r
+ break;\r
+\r
+ case 3U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+\r
+ case 4U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+\r
+ case 5U:\r
+ freq = CLOCK_GetUsbPllOutFreq();\r
+ break;\r
+\r
+ case 6U:\r
+ freq = CLOCK_GetAudioPllOutFreq();\r
+ break;\r
+\r
+ case 7U:\r
+ freq = CLOCK_GetOsc32KFreq();\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+ return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get SPIFI Clk */\r
+/*! brief Return Frequency of Spifi Clock\r
+ * return Frequency of Spifi.\r
+ */\r
+uint32_t CLOCK_GetSpifiClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->SPIFICLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetUsbPllOutFreq();\r
+ break;\r
+ case 3U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case 4U:\r
+ freq = CLOCK_GetAudioPllOutFreq();\r
+ break;\r
+ case 7U:\r
+ freq = 0U;\r
+ break;\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->SPIFICLKDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get ADC Clk */\r
+/*! brief Return Frequency of Adc Clock\r
+ * return Frequency of Adc Clock.\r
+ */\r
+uint32_t CLOCK_GetAdcClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->ADCCLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetUsbPllOutFreq();\r
+ break;\r
+ case 3U:\r
+ freq = CLOCK_GetAudioPllOutFreq();\r
+ break;\r
+ case 7U:\r
+ freq = 0U;\r
+ break;\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->ADCCLKDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get USB0 Clk */\r
+/*! brief Return Frequency of Usb0 Clock\r
+ * return Frequency of Usb0 Clock.\r
+ */\r
+uint32_t CLOCK_GetUsb0ClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->USB0CLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetUsbPllOutFreq();\r
+ break;\r
+ case 7U:\r
+ freq = 0U;\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get USB1 Clk */\r
+/*! brief Return Frequency of Usb1 Clock\r
+ * return Frequency of Usb1 Clock.\r
+ */\r
+uint32_t CLOCK_GetUsb1ClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->USB1CLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetUsbPllOutFreq();\r
+ break;\r
+ case 7U:\r
+ freq = 0U;\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->USB1CLKDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get MCLK Clk */\r
+/*! brief Return Frequency of MClk Clock\r
+ * return Frequency of MClk Clock.\r
+ */\r
+uint32_t CLOCK_GetMclkClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->MCLKCLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffu) + 1U);\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetAudioPllOutFreq();\r
+ break;\r
+ case 7U:\r
+ freq = 0U;\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get SCTIMER Clk */\r
+/*! brief Return Frequency of SCTimer Clock\r
+ * return Frequency of SCTimer Clock.\r
+ */\r
+uint32_t CLOCK_GetSctClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->SCTCLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case 3U:\r
+ freq = CLOCK_GetAudioPllOutFreq();\r
+ break;\r
+ case 7U:\r
+ freq = 0U;\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get SDIO Clk */\r
+/*! brief Return Frequency of SDIO Clock\r
+ * return Frequency of SDIO Clock.\r
+ */\r
+uint32_t CLOCK_GetSdioClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->SDIOCLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetUsbPllOutFreq();\r
+ break;\r
+ case 3U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case 4U:\r
+ freq = CLOCK_GetAudioPllOutFreq();\r
+ break;\r
+ case 7U:\r
+ freq = 0U;\r
+ break;\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->SDIOCLKDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get LCD Clk */\r
+/*! brief Return Frequency of LCD Clock\r
+ * return Frequency of LCD Clock.\r
+ */\r
+uint32_t CLOCK_GetLcdClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->LCDCLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetLcdClkIn();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case 3U:\r
+ freq = 0U;\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->LCDCLKDIV & 0xffU) + 1U);\r
+}\r
+\r
+/* Get LCD CLK IN Clk */\r
+/*! brief Return Frequency of LCD CLKIN Clock\r
+ * return Frequency of LCD CLKIN Clock.\r
+ */\r
+uint32_t CLOCK_GetLcdClkIn(void)\r
+{\r
+ return g_Lcd_Clk_In_Freq;\r
+}\r
+\r
+/* Get FRO 12M Clk */\r
+/*! brief Return Frequency of FRO 12MHz\r
+ * return Frequency of FRO 12MHz\r
+ */\r
+uint32_t CLOCK_GetFro12MFreq(void)\r
+{\r
+ return ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ? 0U : 12000000U;\r
+}\r
+\r
+/* Get EXT OSC Clk */\r
+/*! brief Return Frequency of External Clock\r
+ * return Frequency of External Clock. If no external clock is used returns 0.\r
+ */\r
+uint32_t CLOCK_GetExtClkFreq(void)\r
+{\r
+ return g_Ext_Clk_Freq;\r
+}\r
+\r
+/* Get WATCH DOG Clk */\r
+/*! brief Return Frequency of Watchdog Oscillator\r
+ * return Frequency of Watchdog Oscillator\r
+ */\r
+uint32_t CLOCK_GetWdtOscFreq(void)\r
+{\r
+ uint8_t freq_sel, div_sel;\r
+ if ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_WDT_OSC_MASK) != 0UL)\r
+ {\r
+ return 0U;\r
+ }\r
+ else\r
+ {\r
+ div_sel = (uint8_t)(((SYSCON->WDTOSCCTRL & 0x1fU) + 1U) << 1U);\r
+ freq_sel =\r
+ wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)];\r
+ return ((uint32_t)freq_sel * 50000U) / ((uint32_t)div_sel);\r
+ }\r
+}\r
+\r
+/* Get HF FRO Clk */\r
+/*! brief Return Frequency of High-Freq output of FRO\r
+ * return Frequency of High-Freq output of FRO\r
+ */\r
+uint32_t CLOCK_GetFroHfFreq(void)\r
+{\r
+ if (((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ||\r
+ (0UL == (SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK)))\r
+ {\r
+ return 0U;\r
+ }\r
+\r
+ if ((SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK) != 0UL)\r
+ {\r
+ return 96000000U;\r
+ }\r
+ else\r
+ {\r
+ return 48000000U;\r
+ }\r
+}\r
+\r
+/* Get SYSTEM PLL Clk */\r
+/*! brief Return Frequency of PLL\r
+ * return Frequency of PLL\r
+ */\r
+uint32_t CLOCK_GetPllOutFreq(void)\r
+{\r
+ return s_Pll_Freq;\r
+}\r
+\r
+/* Get AUDIO PLL Clk */\r
+/*! brief Return Frequency of AUDIO PLL\r
+ * return Frequency of PLL\r
+ */\r
+uint32_t CLOCK_GetAudioPllOutFreq(void)\r
+{\r
+ return s_Audio_Pll_Freq;\r
+}\r
+\r
+/* Get USB PLL Clk */\r
+/*! brief Return Frequency of USB PLL\r
+ * return Frequency of PLL\r
+ */\r
+uint32_t CLOCK_GetUsbPllOutFreq(void)\r
+{\r
+ return s_Usb_Pll_Freq;\r
+}\r
+\r
+/* Get RTC OSC Clk */\r
+/*! brief Return Frequency of 32kHz osc\r
+ * return Frequency of 32kHz osc\r
+ */\r
+uint32_t CLOCK_GetOsc32KFreq(void)\r
+{\r
+ return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */\r
+}\r
+\r
+/* Get MAIN Clk */\r
+/*! brief Return Frequency of Core System\r
+ * return Frequency of Core System\r
+ */\r
+uint32_t CLOCK_GetCoreSysClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->MAINCLKSELB)\r
+ {\r
+ case 0U:\r
+ if (SYSCON->MAINCLKSELA == 0U)\r
+ {\r
+ freq = CLOCK_GetFro12MFreq();\r
+ }\r
+ else if (SYSCON->MAINCLKSELA == 1U)\r
+ {\r
+ freq = CLOCK_GetExtClkFreq();\r
+ }\r
+ else if (SYSCON->MAINCLKSELA == 2U)\r
+ {\r
+ freq = CLOCK_GetWdtOscFreq();\r
+ }\r
+ else if (SYSCON->MAINCLKSELA == 3U)\r
+ {\r
+ freq = CLOCK_GetFroHfFreq();\r
+ }\r
+ else\r
+ {\r
+ /* Add comment to prevent the case of rule 15.7. */\r
+ }\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+\r
+ case 3U:\r
+ freq = CLOCK_GetOsc32KFreq();\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq;\r
+}\r
+\r
+/* Get I2S MCLK Clk */\r
+/*! brief Return Frequency of I2S MCLK Clock\r
+ * return Frequency of I2S MCLK Clock\r
+ */\r
+uint32_t CLOCK_GetI2SMClkFreq(void)\r
+{\r
+ return g_I2S_Mclk_Freq;\r
+}\r
+\r
+/* Get ASYNC APB Clk */\r
+/*! brief Return Frequency of Asynchronous APB Clock\r
+ * return Frequency of Asynchronous APB Clock Clock\r
+ */\r
+uint32_t CLOCK_GetAsyncApbClkFreq(void)\r
+{\r
+ async_clock_src_t clkSrc;\r
+ uint32_t clkRate;\r
+\r
+ clkSrc = CLOCK_GetAsyncApbClkSrc();\r
+\r
+ switch (clkSrc)\r
+ {\r
+ case kCLOCK_AsyncMainClk:\r
+ clkRate = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case kCLOCK_AsyncFro12Mhz:\r
+ clkRate = CLK_FRO_12MHZ;\r
+ break;\r
+ default:\r
+ clkRate = 0U;\r
+ break;\r
+ }\r
+\r
+ return clkRate;\r
+}\r
+\r
+/* Get MCAN Clk */\r
+/*! brief Return Frequency of MCAN Clock\r
+ * param MCanSel : 0U: MCAN0; 1U: MCAN1\r
+ * return Frequency of MCAN Clock\r
+ */\r
+uint32_t CLOCK_GetMCanClkFreq(uint32_t MCanSel)\r
+{\r
+ uint32_t freq = 0U;\r
+ switch (MCanSel)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN0CLKDIV & 0xffU) + 1U);\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN1CLKDIV & 0xffU) + 1U);\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq;\r
+}\r
+\r
+/* Get FLEXCOMM Clk */\r
+/*! brief Return Frequency of Flexcomm functional Clock\r
+ * return Frequency of Flexcomm functional Clock\r
+ */\r
+uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ if (id != 10U)\r
+ {\r
+ switch (SYSCON->FCLKSEL[id])\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetFro12MFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffu) + 1U);\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetAudioPllOutFreq();\r
+ break;\r
+ case 3U:\r
+ freq = CLOCK_GetI2SMClkFreq();\r
+ break;\r
+ case 4U:\r
+ freq = CLOCK_GetFrgClkFreq();\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ switch (SYSCON->FCLKSEL10)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetUsbPllOutFreq();\r
+ break;\r
+ case 3U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case 4U:\r
+ freq = CLOCK_GetAudioPllOutFreq();\r
+ break;\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return freq;\r
+}\r
+\r
+/* Get FRG Clk */\r
+uint32_t CLOCK_GetFRGInputClock(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->FRGCLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetFro12MFreq();\r
+ break;\r
+ case 3U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq;\r
+}\r
+\r
+/* Get FRG Clk */\r
+/*! brief Return Frequency of frg\r
+ * return Frequency of FRG\r
+ */\r
+uint32_t CLOCK_GetFrgClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK)\r
+ {\r
+ freq = (uint32_t)(((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /\r
+ ((SYSCON_FRGCTRL_DIV_MASK + 1U) +\r
+ ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));\r
+ }\r
+ else\r
+ {\r
+ freq = 0U;\r
+ }\r
+\r
+ return freq;\r
+}\r
+\r
+/* Get FRG Clk */\r
+/*! brief Return Frequency of dmic\r
+ * return Frequency of DMIC\r
+ */\r
+uint32_t CLOCK_GetDmicClkFreq(void)\r
+{\r
+ uint32_t freq = 0U;\r
+\r
+ switch (SYSCON->DMICCLKSEL)\r
+ {\r
+ case 0U:\r
+ freq = CLOCK_GetFro12MFreq();\r
+ break;\r
+ case 1U:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case 2U:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case 3U:\r
+ freq = CLOCK_GetI2SMClkFreq();\r
+ break;\r
+ case 4U:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case 5U:\r
+ freq = CLOCK_GetWdtOscFreq();\r
+ break;\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U);\r
+ ;\r
+}\r
+\r
+/* Set FRG Clk */\r
+uint32_t CLOCK_SetFRGClock(uint32_t freq)\r
+{\r
+ assert(0UL != freq);\r
+\r
+ uint32_t input = CLOCK_GetFRGInputClock();\r
+ uint32_t mul;\r
+\r
+ if ((freq > 48000000U) || (freq > input) || (input / freq >= 2U))\r
+ {\r
+ /* FRG output frequency should be less than equal to 48MHz */\r
+ return 0U;\r
+ }\r
+ else\r
+ {\r
+ mul = (uint32_t)((((uint64_t)input - freq) * 256U) / ((uint64_t)freq));\r
+ SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK;\r
+ return 1U;\r
+ }\r
+}\r
+\r
+/* Set IP Clk */\r
+/*! brief Return Frequency of selected clock\r
+ * return Frequency of selected clock\r
+ */\r
+uint32_t CLOCK_GetFreq(clock_name_t clockName)\r
+{\r
+ uint32_t freq;\r
+ switch (clockName)\r
+ {\r
+ case kCLOCK_CoreSysClk:\r
+ freq = CLOCK_GetCoreSysClkFreq();\r
+ break;\r
+ case kCLOCK_BusClk:\r
+ freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);\r
+ break;\r
+ case kCLOCK_ClockOut:\r
+ freq = CLOCK_GetClockOutClkFreq();\r
+ break;\r
+ case kCLOCK_Mclk:\r
+ freq = CLOCK_GetMclkClkFreq();\r
+ break;\r
+ case kCLOCK_FroHf:\r
+ freq = CLOCK_GetFroHfFreq();\r
+ break;\r
+ case kCLOCK_Fro12M:\r
+ freq = CLOCK_GetFro12MFreq();\r
+ break;\r
+ case kCLOCK_ExtClk:\r
+ freq = CLOCK_GetExtClkFreq();\r
+ break;\r
+ case kCLOCK_PllOut:\r
+ freq = CLOCK_GetPllOutFreq();\r
+ break;\r
+ case kCLOCK_WdtOsc:\r
+ freq = CLOCK_GetWdtOscFreq();\r
+ break;\r
+ case kCLOCK_Frg:\r
+ freq = CLOCK_GetFrgClkFreq();\r
+ break;\r
+\r
+ case kCLOCK_AsyncApbClk:\r
+ freq = CLOCK_GetAsyncApbClkFreq();\r
+ break;\r
+ default:\r
+ freq = 0U;\r
+ break;\r
+ }\r
+\r
+ return freq;\r
+}\r
+\r
+/* Find encoded NDEC value for raw N value, max N = NVALMAX */\r
+static uint32_t pllEncodeN(uint32_t N)\r
+{\r
+ uint32_t x, i;\r
+\r
+ /* Find NDec */\r
+ switch (N)\r
+ {\r
+ case 0U:\r
+ x = 0x3FFU;\r
+ break;\r
+\r
+ case 1U:\r
+ x = 0x302U;\r
+ break;\r
+\r
+ case 2U:\r
+ x = 0x202U;\r
+ break;\r
+\r
+ default:\r
+ x = 0x080U;\r
+ for (i = N; i <= NVALMAX; i++)\r
+ {\r
+ x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);\r
+ }\r
+ break;\r
+ }\r
+\r
+ return x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P);\r
+}\r
+\r
+/* Find decoded N value for raw NDEC value */\r
+static uint32_t pllDecodeN(uint32_t NDEC)\r
+{\r
+ uint32_t n, x, i;\r
+\r
+ /* Find NDec */\r
+ switch (NDEC)\r
+ {\r
+ case 0x3FFU:\r
+ n = 0U;\r
+ break;\r
+\r
+ case 0x302U:\r
+ n = 1U;\r
+ break;\r
+\r
+ case 0x202U:\r
+ n = 2U;\r
+ break;\r
+\r
+ default:\r
+ x = 0x080U;\r
+ n = 0xFFFFFFFFU;\r
+ for (i = NVALMAX; i >= 3U; i--)\r
+ {\r
+ x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);\r
+ if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)\r
+ {\r
+ /* Decoded value of NDEC */\r
+ n = i;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+\r
+ return n;\r
+}\r
+\r
+/* Find encoded PDEC value for raw P value, max P = PVALMAX */\r
+static uint32_t pllEncodeP(uint32_t P)\r
+{\r
+ uint32_t x, i;\r
+\r
+ /* Find PDec */\r
+ switch (P)\r
+ {\r
+ case 0U:\r
+ x = 0x7FU;\r
+ break;\r
+\r
+ case 1U:\r
+ x = 0x62U;\r
+ break;\r
+\r
+ case 2U:\r
+ x = 0x42U;\r
+ break;\r
+\r
+ default:\r
+ x = 0x10U;\r
+ for (i = P; i <= PVALMAX; i++)\r
+ {\r
+ x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);\r
+ }\r
+ break;\r
+ }\r
+\r
+ return x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P);\r
+}\r
+\r
+/* Find decoded P value for raw PDEC value */\r
+static uint32_t pllDecodeP(uint32_t PDEC)\r
+{\r
+ uint32_t p, x, i;\r
+\r
+ /* Find PDec */\r
+ switch (PDEC)\r
+ {\r
+ case 0x7FU:\r
+ p = 0U;\r
+ break;\r
+\r
+ case 0x62U:\r
+ p = 1U;\r
+ break;\r
+\r
+ case 0x42U:\r
+ p = 2U;\r
+ break;\r
+\r
+ default:\r
+ x = 0x10U;\r
+ p = 0xFFFFFFFFU;\r
+ for (i = PVALMAX; i >= 3U; i--)\r
+ {\r
+ x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);\r
+ if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC)\r
+ {\r
+ /* Decoded value of PDEC */\r
+ p = i;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+\r
+ return p;\r
+}\r
+\r
+/* Find encoded MDEC value for raw M value, max M = MVALMAX */\r
+static uint32_t pllEncodeM(uint32_t M)\r
+{\r
+ uint32_t i, x;\r
+\r
+ /* Find MDec */\r
+ switch (M)\r
+ {\r
+ case 0U:\r
+ x = 0x1FFFFU;\r
+ break;\r
+\r
+ case 1U:\r
+ x = 0x18003U;\r
+ break;\r
+\r
+ case 2U:\r
+ x = 0x10003U;\r
+ break;\r
+\r
+ default:\r
+ x = 0x04000U;\r
+ for (i = M; i <= MVALMAX; i++)\r
+ {\r
+ x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);\r
+ }\r
+ break;\r
+ }\r
+\r
+ return x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P);\r
+}\r
+\r
+/* Find decoded M value for raw MDEC value */\r
+static uint32_t pllDecodeM(uint32_t MDEC)\r
+{\r
+ uint32_t m, i, x;\r
+\r
+ /* Find MDec */\r
+ switch (MDEC)\r
+ {\r
+ case 0x1FFFFU:\r
+ m = 0U;\r
+ break;\r
+\r
+ case 0x18003U:\r
+ m = 1U;\r
+ break;\r
+\r
+ case 0x10003U:\r
+ m = 2U;\r
+ break;\r
+\r
+ default:\r
+ x = 0x04000U;\r
+ m = 0xFFFFFFFFU;\r
+ for (i = MVALMAX; i >= 3U; i--)\r
+ {\r
+ x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);\r
+ if ((x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P)) == MDEC)\r
+ {\r
+ /* Decoded value of MDEC */\r
+ m = i;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+\r
+ return m;\r
+}\r
+\r
+/* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */\r
+static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)\r
+{\r
+ /* bandwidth: compute selP from Multiplier */\r
+ if (M < 60U)\r
+ {\r
+ *pSelP = (M >> 1U) + 1U;\r
+ }\r
+ else\r
+ {\r
+ *pSelP = PVALMAX - 1U;\r
+ }\r
+\r
+ /* bandwidth: compute selI from Multiplier */\r
+ if (M > 16384U)\r
+ {\r
+ *pSelI = 1U;\r
+ }\r
+ else if (M > 8192U)\r
+ {\r
+ *pSelI = 2U;\r
+ }\r
+ else if (M > 2048U)\r
+ {\r
+ *pSelI = 4U;\r
+ }\r
+ else if (M >= 501U)\r
+ {\r
+ *pSelI = 8U;\r
+ }\r
+ else if (M >= 60U)\r
+ {\r
+ *pSelI = 4U * (1024U / (M + 9U));\r
+ }\r
+ else\r
+ {\r
+ *pSelI = (M & 0x3CU) + 4U;\r
+ }\r
+\r
+ if (*pSelI > ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT))\r
+ {\r
+ *pSelI = ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT);\r
+ }\r
+\r
+ *pSelR = 0U;\r
+}\r
+\r
+/* Get predivider (N) from PLL NDEC setting */\r
+static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)\r
+{\r
+ uint32_t preDiv = 1;\r
+\r
+ /* Direct input is not used? */\r
+ if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT)) == 0U)\r
+ {\r
+ /* Decode NDEC value to get (N) pre divider */\r
+ preDiv = pllDecodeN(nDecReg & 0x3FFU);\r
+ if (preDiv == 0U)\r
+ {\r
+ preDiv = 1U;\r
+ }\r
+ }\r
+\r
+ /* Adjusted by 1, directi is used to bypass */\r
+ return preDiv;\r
+}\r
+\r
+/* Get postdivider (P) from PLL PDEC setting */\r
+static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)\r
+{\r
+ uint32_t postDiv = 1U;\r
+\r
+ /* Direct input is not used? */\r
+ if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U)\r
+ {\r
+ /* Decode PDEC value to get (P) post divider */\r
+ postDiv = 2U * pllDecodeP(pDecReg & 0x7FU);\r
+ if (postDiv == 0U)\r
+ {\r
+ postDiv = 2U;\r
+ }\r
+ }\r
+\r
+ /* Adjusted by 1, directo is used to bypass */\r
+ return postDiv;\r
+}\r
+\r
+/* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */\r
+static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)\r
+{\r
+ uint32_t mMult = 1U;\r
+\r
+ /* Decode MDEC value to get (M) multiplier */\r
+ mMult = pllDecodeM(mDecReg & 0x1FFFFU);\r
+\r
+ if (mMult == 0U)\r
+ {\r
+ mMult = 1U;\r
+ }\r
+\r
+ return mMult;\r
+}\r
+\r
+/* Calculate the powerTimes' power of 2 */\r
+static uint32_t power2Cal(uint32_t powerTimes)\r
+{\r
+ uint32_t ret = 1U;\r
+ uint32_t i;\r
+ for (i = 0; i < powerTimes; i++)\r
+ {\r
+ ret *= 2U;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+/* Convert the binary to fractional part */\r
+static double Binary2Fractional(uint32_t binaryPart)\r
+{\r
+ double fractional = 0.0;\r
+ for (uint32_t i = 0U; i <= 14U; i++)\r
+ {\r
+ fractional += (double)(uint32_t)((binaryPart >> i) & 0x1U) / (double)(uint32_t)power2Cal(15U - i);\r
+ }\r
+ return fractional;\r
+}\r
+\r
+/* Find greatest common divisor between m and n */\r
+static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)\r
+{\r
+ uint32_t tmp;\r
+\r
+ while (n != 0U)\r
+ {\r
+ tmp = n;\r
+ n = m % n;\r
+ m = tmp;\r
+ }\r
+\r
+ return m;\r
+}\r
+\r
+/*\r
+ * Set PLL output based on desired output rate.\r
+ * In this function, the it calculates the PLL setting for output frequency from input clock\r
+ * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.\r
+ * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.\r
+ */\r
+static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)\r
+{\r
+ uint32_t nDivOutHz, fccoHz, multFccoDiv;\r
+ uint32_t pllPreDivider, pllMultiplier, pllPostDivider;\r
+ uint32_t pllDirectInput, pllDirectOutput;\r
+ uint32_t pllSelP, pllSelI, pllSelR, uplimoff;\r
+\r
+ /* Baseline parameters (no input or output dividers) */\r
+ pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */\r
+ pllPostDivider = 0U; /* 0 implies post-divider will be disabled */\r
+ pllDirectOutput = 1U;\r
+ multFccoDiv = 2U;\r
+\r
+ /* Verify output rate parameter */\r
+ if (foutHz > PLL_MAX_CCO_FREQ_MHZ)\r
+ {\r
+ /* Maximum PLL output with post divider=1 cannot go above this frequency */\r
+ return kStatus_PLL_OutputTooHigh;\r
+ }\r
+ if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))\r
+ {\r
+ /* Minmum PLL output with maximum post divider cannot go below this frequency */\r
+ return kStatus_PLL_OutputTooLow;\r
+ }\r
+\r
+ /* Verify input rate parameter */\r
+ if (finHz < PLL_LOWER_IN_LIMIT)\r
+ {\r
+ /* Input clock into the PLL cannot be lower than this */\r
+ return kStatus_PLL_InputTooLow;\r
+ }\r
+\r
+ /* Find the optimal CCO frequency for the output and input that\r
+ will keep it inside the PLL CCO range. This may require\r
+ tweaking the post-divider for the PLL. */\r
+ fccoHz = foutHz;\r
+ while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)\r
+ {\r
+ /* CCO output is less than minimum CCO range, so the CCO output\r
+ needs to be bumped up and the post-divider is used to bring\r
+ the PLL output back down. */\r
+ pllPostDivider++;\r
+ if (pllPostDivider > PVALMAX)\r
+ {\r
+ return kStatus_PLL_OutsideIntLimit;\r
+ }\r
+\r
+ /* Target CCO goes up, PLL output goes down */\r
+ fccoHz = foutHz * (pllPostDivider * 2U);\r
+ pllDirectOutput = 0U;\r
+ }\r
+\r
+ /* Determine if a pre-divider is needed to get the best frequency */\r
+ if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz))\r
+ {\r
+ uint32_t a = FindGreatestCommonDivisor(fccoHz, (multFccoDiv * finHz));\r
+\r
+ if (a > 20000U)\r
+ {\r
+ a = (multFccoDiv * finHz) / a;\r
+ if ((a != 0U) && (a < PLL_MAX_N_DIV))\r
+ {\r
+ pllPreDivider = a;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Bypass pre-divider hardware if pre-divider is 1 */\r
+ if (pllPreDivider > 1U)\r
+ {\r
+ pllDirectInput = 0U;\r
+ }\r
+ else\r
+ {\r
+ pllDirectInput = 1U;\r
+ }\r
+\r
+ /* Determine PLL multipler */\r
+ nDivOutHz = (finHz / pllPreDivider);\r
+ pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv;\r
+\r
+ /* Find optimal values for filter */\r
+ /* Will bumping up M by 1 get us closer to the desired CCO frequency? */\r
+ if ((nDivOutHz * ((multFccoDiv * pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))\r
+ {\r
+ pllMultiplier++;\r
+ }\r
+\r
+ /* Setup filtering */\r
+ pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);\r
+ uplimoff = 0U;\r
+\r
+ /* Get encoded value for M (mult) and use manual filter, disable SS mode */\r
+ pSetup->pllmdec = PLL_MDEC_VAL_SET(pllEncodeM(pllMultiplier));\r
+\r
+ /* Get encoded values for N (prediv) and P (postdiv) */\r
+ pSetup->pllndec = PLL_NDEC_VAL_SET(pllEncodeN(pllPreDivider));\r
+ pSetup->pllpdec = PLL_PDEC_VAL_SET(pllEncodeP(pllPostDivider));\r
+\r
+ /* PLL control */\r
+ pSetup->pllctrl = (pllSelR << SYSCON_SYSPLLCTRL_SELR_SHIFT) | /* Filter coefficient */\r
+ (pllSelI << SYSCON_SYSPLLCTRL_SELI_SHIFT) | /* Filter coefficient */\r
+ (pllSelP << SYSCON_SYSPLLCTRL_SELP_SHIFT) | /* Filter coefficient */\r
+ (0UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT) | /* PLL bypass mode disabled */\r
+ (uplimoff << SYSCON_SYSPLLCTRL_UPLIMOFF_SHIFT) | /* SS/fractional mode disabled */\r
+ (pllDirectInput << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT) | /* Bypass pre-divider? */\r
+ (pllDirectOutput << SYSCON_SYSPLLCTRL_DIRECTO_SHIFT); /* Bypass post-divider? */\r
+\r
+ return kStatus_PLL_Success;\r
+}\r
+\r
+#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)\r
+/* Alloct the static buffer for cache. */\r
+static pll_setup_t gPllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];\r
+static uint32_t gFinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};\r
+static uint32_t gFoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};\r
+static uint32_t gPllSetupCacheIdx = 0U;\r
+#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */\r
+\r
+/*\r
+ * Calculate the PLL setting values from input clock freq to output freq.\r
+ */\r
+static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)\r
+{\r
+ pll_error_t retErr;\r
+#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)\r
+ uint32_t i;\r
+\r
+ for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)\r
+ {\r
+ if ((finHz == gFinHzCache[i]) && (foutHz == gFoutHzCache[i]))\r
+ {\r
+ /* Hit the target in cache buffer. */\r
+ pSetup->pllctrl = gPllSetupCacheStruct[i].pllctrl;\r
+ pSetup->pllndec = gPllSetupCacheStruct[i].pllndec;\r
+ pSetup->pllpdec = gPllSetupCacheStruct[i].pllpdec;\r
+ pSetup->pllmdec = gPllSetupCacheStruct[i].pllmdec;\r
+ retErr = kStatus_PLL_Success;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)\r
+ {\r
+ return retErr;\r
+ }\r
+#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */\r
+\r
+ /* No cache or did not hit the cache. */\r
+ retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup);\r
+\r
+#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)\r
+ if (kStatus_PLL_Success == retErr)\r
+ {\r
+ /* Cache the most recent calulation result into buffer. */\r
+ gFinHzCache[gPllSetupCacheIdx] = finHz;\r
+ gFoutHzCache[gPllSetupCacheIdx] = foutHz;\r
+\r
+ gPllSetupCacheStruct[gPllSetupCacheIdx].pllctrl = pSetup->pllctrl;\r
+ gPllSetupCacheStruct[gPllSetupCacheIdx].pllndec = pSetup->pllndec;\r
+ gPllSetupCacheStruct[gPllSetupCacheIdx].pllpdec = pSetup->pllpdec;\r
+ gPllSetupCacheStruct[gPllSetupCacheIdx].pllmdec = pSetup->pllmdec;\r
+ /* Update the index for next available buffer. */\r
+ gPllSetupCacheIdx = (gPllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;\r
+ }\r
+#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */\r
+\r
+ return retErr;\r
+}\r
+\r
+/* Update SYSTEM PLL rate variable */\r
+static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup)\r
+{\r
+ s_Pll_Freq = CLOCK_GetSystemPLLOutFromSetup(pSetup);\r
+}\r
+\r
+/* Update AUDIO PLL rate variable */\r
+static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup)\r
+{\r
+ s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromSetup(pSetup);\r
+}\r
+\r
+/* Update AUDIO Fractional PLL rate variable */\r
+static void CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t *pSetup)\r
+{\r
+ s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromFractSetup(pSetup);\r
+}\r
+\r
+/* Update USB PLL rate variable */\r
+static void CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t *pSetup)\r
+{\r
+ s_Usb_Pll_Freq = CLOCK_GetUsbPLLOutFromSetup(pSetup);\r
+}\r
+\r
+/* Return System PLL input clock rate */\r
+/*! brief Return System PLL input clock rate\r
+ * return System PLL input clock rate\r
+ */\r
+uint32_t CLOCK_GetSystemPLLInClockRate(void)\r
+{\r
+ uint32_t clkRate = 0U;\r
+\r
+ switch ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK))\r
+ {\r
+ case 0x00U:\r
+ clkRate = CLK_FRO_12MHZ;\r
+ break;\r
+\r
+ case 0x01U:\r
+ clkRate = CLOCK_GetExtClkFreq();\r
+ break;\r
+\r
+ case 0x02U:\r
+ clkRate = CLOCK_GetWdtOscFreq();\r
+ break;\r
+\r
+ case 0x03U:\r
+ clkRate = CLOCK_GetOsc32KFreq();\r
+ break;\r
+\r
+ default:\r
+ clkRate = 0U;\r
+ break;\r
+ }\r
+\r
+ return clkRate;\r
+}\r
+\r
+/* Return Audio PLL input clock rate */\r
+/*! brief Return Audio PLL input clock rate\r
+ * return Audio PLL input clock rate\r
+ */\r
+uint32_t CLOCK_GetAudioPLLInClockRate(void)\r
+{\r
+ uint32_t clkRate = 0U;\r
+\r
+ switch ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK))\r
+ {\r
+ case 0x00U:\r
+ clkRate = CLK_FRO_12MHZ;\r
+ break;\r
+\r
+ case 0x01U:\r
+ clkRate = CLOCK_GetExtClkFreq();\r
+ break;\r
+\r
+ default:\r
+ clkRate = 0U;\r
+ break;\r
+ }\r
+\r
+ return clkRate;\r
+}\r
+\r
+/* Return System PLL output clock rate from setup structure */\r
+/*! brief Return System PLL output clock rate from setup structure\r
+ * param pSetup : Pointer to a PLL setup structure\r
+ * return System PLL output clock rate the setup structure will generate\r
+ */\r
+uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup)\r
+{\r
+ uint32_t prediv, postdiv, mMult, inPllRate;\r
+ uint64_t workRate;\r
+\r
+ inPllRate = CLOCK_GetSystemPLLInClockRate();\r
+ /* If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock*/\r
+ if ((pSetup->pllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U)\r
+ {\r
+ /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */\r
+ /*\r
+ * 1. Pre-divider\r
+ * Pre-divider is only available when the DIRECTI is disabled.\r
+ */\r
+ if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK))\r
+ {\r
+ prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);\r
+ }\r
+ else\r
+ {\r
+ prediv = 1U; /* The pre-divider is bypassed. */\r
+ }\r
+ /*\r
+ * 2. Post-divider\r
+ * Post-divider is only available when the DIRECTO is disabled.\r
+ */\r
+ if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK))\r
+ {\r
+ postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);\r
+ }\r
+ else\r
+ {\r
+ postdiv = 1U; /* The post-divider is bypassed. */\r
+ }\r
+ /* Adjust input clock */\r
+ inPllRate = inPllRate / prediv;\r
+\r
+ /* MDEC used for rate */\r
+ mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);\r
+ workRate = (uint64_t)inPllRate * (uint64_t)mMult;\r
+\r
+ workRate = workRate / ((uint64_t)postdiv);\r
+ workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/\r
+ }\r
+ else\r
+ {\r
+ /* In bypass mode */\r
+ workRate = (uint64_t)inPllRate;\r
+ }\r
+\r
+ return (uint32_t)workRate;\r
+}\r
+\r
+/* Return Usb PLL output clock rate from setup structure */\r
+/*! brief Return System USB PLL output clock rate from setup structure\r
+ * param pSetup : Pointer to a PLL setup structure\r
+ * return System PLL output clock rate the setup structure will generate\r
+ */\r
+uint32_t CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t *pSetup)\r
+{\r
+ uint32_t nsel, psel, msel, inPllRate;\r
+ uint64_t workRate;\r
+ inPllRate = CLOCK_GetExtClkFreq();\r
+ msel = pSetup->msel;\r
+ psel = pSetup->psel;\r
+ nsel = pSetup->nsel;\r
+\r
+ /* Make sure the PSEL is correct. */\r
+ if (0U == SWITCH_USB_PSEL(psel))\r
+ {\r
+ return 0UL;\r
+ }\r
+\r
+ if (pSetup->fbsel)\r
+ {\r
+ /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */\r
+ workRate = ((uint64_t)inPllRate) * ((uint64_t)msel + 1U) / ((uint64_t)nsel + 1U);\r
+ }\r
+ else\r
+ {\r
+ /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */\r
+ workRate = ((uint64_t)inPllRate / ((uint64_t)nsel + 1U)) * (msel + 1U) / (2U * SWITCH_USB_PSEL(psel));\r
+ }\r
+\r
+ return (uint32_t)workRate;\r
+}\r
+\r
+/* Return Audio PLL output clock rate from setup structure */\r
+/*! brief Return System AUDIO PLL output clock rate from setup structure\r
+ * param pSetup : Pointer to a PLL setup structure\r
+ * return System PLL output clock rate the setup structure will generate\r
+ */\r
+uint32_t CLOCK_GetAudioPLLOutFromSetup(pll_setup_t *pSetup)\r
+{\r
+ uint32_t prediv, postdiv, mMult, inPllRate;\r
+ uint64_t workRate;\r
+\r
+ inPllRate = CLOCK_GetAudioPLLInClockRate();\r
+ if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)\r
+ {\r
+ /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */\r
+ /*\r
+ * 1. Pre-divider\r
+ * Pre-divider is only available when the DIRECTI is disabled.\r
+ */\r
+ if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))\r
+ {\r
+ prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);\r
+ }\r
+ else\r
+ {\r
+ prediv = 1U; /* The pre-divider is bypassed. */\r
+ }\r
+ /*\r
+ * 2. Post-divider\r
+ * Post-divider is only available when the DIRECTO is disabled.\r
+ */\r
+ if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))\r
+ {\r
+ postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);\r
+ }\r
+ else\r
+ {\r
+ postdiv = 1U; /* The post-divider is bypassed. */\r
+ }\r
+ /* Adjust input clock */\r
+ inPllRate = inPllRate / prediv;\r
+\r
+ /* MDEC used for rate */\r
+ mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);\r
+ workRate = (uint64_t)inPllRate * (uint64_t)mMult;\r
+\r
+ workRate = workRate / ((uint64_t)postdiv);\r
+ workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/\r
+ }\r
+ else\r
+ {\r
+ /* In bypass mode */\r
+ workRate = (uint64_t)inPllRate;\r
+ }\r
+\r
+ return (uint32_t)workRate;\r
+}\r
+\r
+/* Return Audio PLL output clock rate from audio fractioanl setup structure */\r
+/*! brief Return System AUDIO PLL output clock rate from audio fractioanl setup structure\r
+ * param pSetup : Pointer to a PLL setup structure\r
+ * return System PLL output clock rate the setup structure will generate\r
+ */\r
+uint32_t CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t *pSetup)\r
+{\r
+ uint32_t prediv, postdiv, inPllRate;\r
+ double workRate, mMultFactional;\r
+\r
+ inPllRate = CLOCK_GetAudioPLLInClockRate();\r
+ if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)\r
+ {\r
+ /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */\r
+ /*\r
+ * 1. Pre-divider\r
+ * Pre-divider is only available when the DIRECTI is disabled.\r
+ */\r
+ if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))\r
+ {\r
+ prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);\r
+ }\r
+ else\r
+ {\r
+ prediv = 1U; /* The pre-divider is bypassed. */\r
+ }\r
+ /*\r
+ * 2. Post-divider\r
+ * Post-divider is only available when the DIRECTO is disabled.\r
+ */\r
+ if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))\r
+ {\r
+ postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);\r
+ }\r
+ else\r
+ {\r
+ postdiv = 1U; /* The post-divider is bypassed. */\r
+ }\r
+ /* Adjust input clock */\r
+ inPllRate = inPllRate / prediv;\r
+\r
+ mMultFactional = (double)(uint32_t)(pSetup->audpllfrac >> 15) +\r
+ (double)(uint32_t)Binary2Fractional(pSetup->audpllfrac & 0x7FFFU);\r
+ workRate = (double)inPllRate * (double)mMultFactional;\r
+\r
+ workRate = workRate / ((double)postdiv);\r
+ workRate = workRate * 2.0; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/\r
+ }\r
+ else\r
+ {\r
+ /* In bypass mode */\r
+ workRate = (double)(uint64_t)inPllRate;\r
+ }\r
+\r
+ return (uint32_t)workRate;\r
+}\r
+\r
+/* Set the current PLL Rate */\r
+/*! brief Store the current PLL rate\r
+ * param rate: Current rate of the PLL\r
+ * return Nothing\r
+ **/\r
+void CLOCK_SetStoredPLLClockRate(uint32_t rate)\r
+{\r
+ s_Pll_Freq = rate;\r
+}\r
+\r
+/* Set the current Audio PLL Rate */\r
+/*! brief Store the current AUDIO PLL rate\r
+ * param rate: Current rate of the PLL\r
+ * return Nothing\r
+ **/\r
+void CLOCK_SetStoredAudioPLLClockRate(uint32_t rate)\r
+{\r
+ s_Audio_Pll_Freq = rate;\r
+}\r
+\r
+/* Set the current Usb PLL Rate */\r
+void CLOCK_SetStoredUsbPLLClockRate(uint32_t rate)\r
+{\r
+ s_Usb_Pll_Freq = rate;\r
+}\r
+\r
+/* Return System PLL output clock rate */\r
+/*! brief Return System PLL output clock rate\r
+ * param recompute : Forces a PLL rate recomputation if true\r
+ * return System PLL output clock rate\r
+ * note The PLL rate is cached in the driver in a variable as\r
+ * the rate computation function can take some time to perform. It\r
+ * is recommended to use 'false' with the 'recompute' parameter.\r
+ */\r
+uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute)\r
+{\r
+ pll_setup_t Setup;\r
+ uint32_t rate;\r
+\r
+ if ((recompute) || (s_Pll_Freq == 0U))\r
+ {\r
+ Setup.pllctrl = SYSCON->SYSPLLCTRL;\r
+ Setup.pllndec = SYSCON->SYSPLLNDEC;\r
+ Setup.pllpdec = SYSCON->SYSPLLPDEC;\r
+ Setup.pllmdec = SYSCON->SYSPLLMDEC;\r
+\r
+ CLOCK_GetSystemPLLOutFromSetupUpdate(&Setup);\r
+ }\r
+\r
+ rate = s_Pll_Freq;\r
+\r
+ return rate;\r
+}\r
+\r
+/* Return AUDIO PLL output clock rate */\r
+/*! brief Return System AUDIO PLL output clock rate\r
+ * param recompute : Forces a AUDIO PLL rate recomputation if true\r
+ * return System AUDIO PLL output clock rate\r
+ * note The AUDIO PLL rate is cached in the driver in a variable as\r
+ * the rate computation function can take some time to perform. It\r
+ * is recommended to use 'false' with the 'recompute' parameter.\r
+ */\r
+uint32_t CLOCK_GetAudioPLLOutClockRate(bool recompute)\r
+{\r
+ pll_setup_t Setup;\r
+ uint32_t rate;\r
+\r
+ if ((recompute) || (s_Audio_Pll_Freq == 0U))\r
+ {\r
+ Setup.pllctrl = SYSCON->AUDPLLCTRL;\r
+ Setup.pllndec = SYSCON->AUDPLLNDEC;\r
+ Setup.pllpdec = SYSCON->AUDPLLPDEC;\r
+ Setup.pllmdec = SYSCON->AUDPLLMDEC;\r
+\r
+ CLOCK_GetAudioPLLOutFromSetupUpdate(&Setup);\r
+ }\r
+\r
+ rate = s_Audio_Pll_Freq;\r
+ return rate;\r
+}\r
+\r
+/* Return USB PLL output clock rate */\r
+uint32_t CLOCK_GetUsbPLLOutClockRate(bool recompute)\r
+{\r
+ usb_pll_setup_t Setup;\r
+ uint32_t rate;\r
+\r
+ if ((recompute) || (s_Usb_Pll_Freq == 0U))\r
+ {\r
+ Setup.msel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_MSEL_SHIFT) & SYSCON_USBPLLCTRL_MSEL_MASK);\r
+ Setup.psel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_PSEL_SHIFT) & SYSCON_USBPLLCTRL_PSEL_MASK);\r
+ Setup.nsel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_NSEL_SHIFT) & SYSCON_USBPLLCTRL_NSEL_MASK);\r
+ Setup.fbsel = (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_FBSEL_SHIFT) & SYSCON_USBPLLCTRL_FBSEL_MASK) != 0UL);\r
+ Setup.bypass =\r
+ (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_BYPASS_SHIFT) & SYSCON_USBPLLCTRL_BYPASS_MASK) != 0UL);\r
+ Setup.direct =\r
+ (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_DIRECT_SHIFT) & SYSCON_USBPLLCTRL_DIRECT_MASK) != 0UL);\r
+ CLOCK_GetUsbPLLOutFromSetupUpdate(&Setup);\r
+ }\r
+\r
+ rate = s_Usb_Pll_Freq;\r
+ return rate;\r
+}\r
+\r
+/* Set PLL output based on the passed PLL setup data */\r
+/*! brief Set PLL output based on the passed PLL setup data\r
+ * param pControl : Pointer to populated PLL control structure to generate setup with\r
+ * param pSetup : Pointer to PLL setup structure to be filled\r
+ * return PLL_ERROR_SUCCESS on success, or PLL setup error code\r
+ * note Actual frequency for setup may vary from the desired frequency based on the\r
+ * accuracy of input clocks, rounding, non-fractional PLL mode, etc.\r
+ */\r
+pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup)\r
+{\r
+ uint32_t inRate;\r
+ pll_error_t pllError;\r
+\r
+ /* Determine input rate for the PLL */\r
+ if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)\r
+ {\r
+ inRate = pControl->inputRate;\r
+ }\r
+ else\r
+ {\r
+ inRate = CLOCK_GetSystemPLLInClockRate();\r
+ }\r
+\r
+ /* PLL flag options */\r
+ pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup);\r
+ pSetup->pllRate = pControl->desiredRate;\r
+ return pllError;\r
+}\r
+\r
+/* Set PLL output from PLL setup structure */\r
+/*! brief Set PLL output from PLL setup structure (precise frequency)\r
+ * param pSetup : Pointer to populated PLL setup structure\r
+ * param flagcfg : Flag configuration for PLL config structure\r
+ * return PLL_ERROR_SUCCESS on success, or PLL setup error code\r
+ * note This function will power off the PLL, setup the PLL with the\r
+ * new setup data, and then optionally powerup the PLL, wait for PLL lock,\r
+ * and adjust system voltages to the new PLL rate. The function will not\r
+ * alter any source clocks (ie, main systen clock) that may use the PLL,\r
+ * so these should be setup prior to and after exiting the function.\r
+ */\r
+pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)\r
+{\r
+ if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U)\r
+ {\r
+ /* Turn on the ext clock if system pll input select clk_in */\r
+ CLOCK_Enable_SysOsc(true);\r
+ }\r
+ /* Enable power for PLLs */\r
+ POWER_SetPLL();\r
+ /* Power off PLL during setup changes */\r
+ POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);\r
+\r
+ pSetup->flags = flagcfg;\r
+\r
+ /* Write PLL setup data */\r
+ SYSCON->SYSPLLCTRL = pSetup->pllctrl;\r
+ SYSCON->SYSPLLNDEC = pSetup->pllndec;\r
+ SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */\r
+ SYSCON->SYSPLLPDEC = pSetup->pllpdec;\r
+ SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */\r
+ SYSCON->SYSPLLMDEC = pSetup->pllmdec;\r
+ SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */\r
+\r
+ /* Flags for lock or power on */\r
+ if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)\r
+ {\r
+ /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */\r
+ uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/\r
+ uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);\r
+\r
+ /* Initialize and power up PLL */\r
+ SYSCON->SYSPLLMDEC = maxCCO;\r
+ POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);\r
+\r
+ /* Set mreq to activate */\r
+ SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);\r
+\r
+ /* Delay for 72 uSec @ 12Mhz */\r
+ SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+\r
+ /* clear mreq to prepare for restoring mreq */\r
+ SYSCON->SYSPLLMDEC = curSSCTRL;\r
+\r
+ /* set original value back and activate */\r
+ SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);\r
+\r
+ /* Enable peripheral states by setting low */\r
+ POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);\r
+ }\r
+ if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
+ {\r
+ while (CLOCK_IsSystemPLLLocked() == false)\r
+ {\r
+ }\r
+ }\r
+\r
+ /* Update current programmed PLL rate var */\r
+ CLOCK_GetSystemPLLOutFromSetupUpdate(pSetup);\r
+\r
+ /* System voltage adjustment, occurs prior to setting main system clock */\r
+ if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0U)\r
+ {\r
+ POWER_SetVoltageForFreq(s_Pll_Freq);\r
+ }\r
+\r
+ return kStatus_PLL_Success;\r
+}\r
+\r
+/* Set AUDIO PLL output from AUDIO PLL setup structure */\r
+/*! brief Set AUDIO PLL output from AUDIOPLL setup structure (precise frequency)\r
+ * param pSetup : Pointer to populated PLL setup structure\r
+ * param flagcfg : Flag configuration for PLL config structure\r
+ * return PLL_ERROR_SUCCESS on success, or PLL setup error code\r
+ * note This function will power off the PLL, setup the PLL with the\r
+ * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock,\r
+ * and adjust system voltages to the new AUDIOPLL rate. The function will not\r
+ * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL,\r
+ * so these should be setup prior to and after exiting the function.\r
+ */\r
+pll_error_t CLOCK_SetupAudioPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)\r
+{\r
+ if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)\r
+ {\r
+ /* Turn on the ext clock if system pll input select clk_in */\r
+ CLOCK_Enable_SysOsc(true);\r
+ }\r
+ /* Enable power VD3 for PLLs */\r
+ POWER_SetPLL();\r
+ /* Power off PLL during setup changes */\r
+ POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
+\r
+ pSetup->flags = flagcfg;\r
+\r
+ /* Write PLL setup data */\r
+ SYSCON->AUDPLLCTRL = pSetup->pllctrl;\r
+ SYSCON->AUDPLLNDEC = pSetup->pllndec;\r
+ SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLPDEC = pSetup->pllpdec;\r
+ SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLMDEC = pSetup->pllmdec;\r
+ SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1); /* disable fractional function */\r
+\r
+ /* Flags for lock or power on */\r
+ if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)\r
+ {\r
+ /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */\r
+ uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/\r
+ uint32_t curSSCTRL = SYSCON->AUDPLLMDEC & ~(1UL << 17U);\r
+\r
+ /* Initialize and power up PLL */\r
+ SYSCON->AUDPLLMDEC = maxCCO;\r
+ POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
+\r
+ /* Set mreq to activate */\r
+ SYSCON->AUDPLLMDEC = maxCCO | (1UL << 17U);\r
+\r
+ /* Delay for 72 uSec @ 12Mhz */\r
+ SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+\r
+ /* clear mreq to prepare for restoring mreq */\r
+ SYSCON->AUDPLLMDEC = curSSCTRL;\r
+\r
+ /* set original value back and activate */\r
+ SYSCON->AUDPLLMDEC = curSSCTRL | (1UL << 17U);\r
+\r
+ /* Enable peripheral states by setting low */\r
+ POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
+ }\r
+ if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
+ {\r
+ while (CLOCK_IsAudioPLLLocked() == false)\r
+ {\r
+ }\r
+ }\r
+\r
+ /* Update current programmed PLL rate var */\r
+ CLOCK_GetAudioPLLOutFromSetupUpdate(pSetup);\r
+\r
+ return kStatus_PLL_Success;\r
+}\r
+\r
+/* Set AUDIO PLL output from AUDIO PLL fractional setup structure */\r
+/*! brief Set AUDIO PLL output from AUDIOPLL setup structure using the Audio Fractional divider register(precise\r
+ * frequency)\r
+ * param pSetup : Pointer to populated PLL setup structure\r
+ * param flagcfg : Flag configuration for PLL config structure\r
+ * return PLL_ERROR_SUCCESS on success, or PLL setup error code\r
+ * note This function will power off the PLL, setup the PLL with the\r
+ * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock,\r
+ * and adjust system voltages to the new AUDIOPLL rate. The function will not\r
+ * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL,\r
+ * so these should be setup prior to and after exiting the function.\r
+ */\r
+pll_error_t CLOCK_SetupAudioPLLPrecFract(pll_setup_t *pSetup, uint32_t flagcfg)\r
+{\r
+ if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)\r
+ {\r
+ /* Turn on the ext clock if system pll input select clk_in */\r
+ CLOCK_Enable_SysOsc(true);\r
+ }\r
+ /* Enable power VD3 for PLLs */\r
+ POWER_SetPLL();\r
+ /* Power off PLL during setup changes */\r
+ POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
+\r
+ pSetup->flags = flagcfg;\r
+\r
+ /* Write PLL setup data */\r
+ SYSCON->AUDPLLCTRL = pSetup->pllctrl;\r
+ SYSCON->AUDPLLNDEC = pSetup->pllndec;\r
+ SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLPDEC = pSetup->pllpdec;\r
+ SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLMDEC = pSetup->pllmdec;\r
+ SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(0); /* enable fractional function */\r
+ SYSCON->AUDPLLFRAC = pSetup->audpllfrac;\r
+ SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT);\r
+\r
+ /* Enable peripheral states by setting low */\r
+ POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
+\r
+ if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
+ {\r
+ while (CLOCK_IsAudioPLLLocked() == false)\r
+ {\r
+ }\r
+ }\r
+\r
+ /* Update current programmed PLL rate var */\r
+ CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pSetup);\r
+\r
+ return kStatus_PLL_Success;\r
+}\r
+\r
+/* Set Audio PLL output based on the passed Audio PLL setup data */\r
+/*! brief Set AUDIO PLL output based on the passed AUDIO PLL setup data\r
+ * param pControl : Pointer to populated PLL control structure to generate setup with\r
+ * param pSetup : Pointer to PLL setup structure to be filled\r
+ * return PLL_ERROR_SUCCESS on success, or PLL setup error code\r
+ * note Actual frequency for setup may vary from the desired frequency based on the\r
+ * accuracy of input clocks, rounding, non-fractional PLL mode, etc.\r
+ */\r
+pll_error_t CLOCK_SetupAudioPLLData(pll_config_t *pControl, pll_setup_t *pSetup)\r
+{\r
+ uint32_t inRate;\r
+ pll_error_t pllError;\r
+\r
+ /* Determine input rate for the PLL */\r
+ if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)\r
+ {\r
+ inRate = pControl->inputRate;\r
+ }\r
+ else\r
+ {\r
+ inRate = CLOCK_GetAudioPLLInClockRate();\r
+ }\r
+\r
+ /* PLL flag options */\r
+ pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup);\r
+ pSetup->pllRate = pControl->desiredRate;\r
+ return pllError;\r
+}\r
+\r
+/* Setup PLL Frequency from pre-calculated value */\r
+/**\r
+ * brief Set PLL output from PLL setup structure (precise frequency)\r
+ * param pSetup : Pointer to populated PLL setup structure\r
+ * return kStatus_PLL_Success on success, or PLL setup error code\r
+ * note This function will power off the PLL, setup the PLL with the\r
+ * new setup data, and then optionally powerup the PLL, wait for PLL lock,\r
+ * and adjust system voltages to the new PLL rate. The function will not\r
+ * alter any source clocks (ie, main systen clock) that may use the PLL,\r
+ * so these should be setup prior to and after exiting the function.\r
+ */\r
+pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup)\r
+{\r
+ if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U)\r
+ {\r
+ /* Turn on the ext clock if system pll input select clk_in */\r
+ CLOCK_Enable_SysOsc(true);\r
+ }\r
+ /* Enable power VD3 for PLLs */\r
+ POWER_SetPLL();\r
+ /* Power off PLL during setup changes */\r
+ POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);\r
+\r
+ /* Write PLL setup data */\r
+ SYSCON->SYSPLLCTRL = pSetup->pllctrl;\r
+ SYSCON->SYSPLLNDEC = pSetup->pllndec;\r
+ SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */\r
+ SYSCON->SYSPLLPDEC = pSetup->pllpdec;\r
+ SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */\r
+ SYSCON->SYSPLLMDEC = pSetup->pllmdec;\r
+ SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */\r
+\r
+ /* Flags for lock or power on */\r
+ if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)\r
+ {\r
+ /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */\r
+ uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/\r
+ uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);\r
+\r
+ /* Initialize and power up PLL */\r
+ SYSCON->SYSPLLMDEC = maxCCO;\r
+ POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);\r
+\r
+ /* Set mreq to activate */\r
+ SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);\r
+\r
+ /* Delay for 72 uSec @ 12Mhz */\r
+ SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+\r
+ /* clear mreq to prepare for restoring mreq */\r
+ SYSCON->SYSPLLMDEC = curSSCTRL;\r
+\r
+ /* set original value back and activate */\r
+ SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);\r
+\r
+ /* Enable peripheral states by setting low */\r
+ POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);\r
+ }\r
+ if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
+ {\r
+ while (CLOCK_IsSystemPLLLocked() == false)\r
+ {\r
+ }\r
+ }\r
+\r
+ /* Update current programmed PLL rate var */\r
+ s_Pll_Freq = pSetup->pllRate;\r
+\r
+ return kStatus_PLL_Success;\r
+}\r
+\r
+/* Setup Audio PLL Frequency from pre-calculated value */\r
+/**\r
+ * brief Set Audio PLL output from Audio PLL setup structure (precise frequency)\r
+ * param pSetup : Pointer to populated PLL setup structure\r
+ * return kStatus_PLL_Success on success, or Audio PLL setup error code\r
+ * note This function will power off the PLL, setup the Audio PLL with the\r
+ * new setup data, and then optionally powerup the PLL, wait for Audio PLL lock,\r
+ * and adjust system voltages to the new PLL rate. The function will not\r
+ * alter any source clocks (ie, main systen clock) that may use the Audio PLL,\r
+ * so these should be setup prior to and after exiting the function.\r
+ */\r
+pll_error_t CLOCK_SetAudioPLLFreq(const pll_setup_t *pSetup)\r
+{\r
+ if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)\r
+ {\r
+ /* Turn on the ext clock if system pll input select clk_in */\r
+ CLOCK_Enable_SysOsc(true);\r
+ }\r
+ /* Enable power VD3 for PLLs */\r
+ POWER_SetPLL();\r
+ /* Power off Audio PLL during setup changes */\r
+ POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
+\r
+ /* Write Audio PLL setup data */\r
+ SYSCON->AUDPLLCTRL = pSetup->pllctrl;\r
+ SYSCON->AUDPLLFRAC = pSetup->audpllfrac;\r
+ SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLNDEC = pSetup->pllndec;\r
+ SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_AUDPLLNDEC_NREQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLPDEC = pSetup->pllpdec;\r
+ SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_AUDPLLPDEC_PREQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLMDEC = pSetup->pllmdec;\r
+ SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_AUDPLLMDEC_MREQ_SHIFT); /* latch */\r
+ SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1); /* disable fractional function */\r
+\r
+ /* Flags for lock or power on */\r
+ if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)\r
+ {\r
+ /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */\r
+ uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/\r
+ uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);\r
+\r
+ /* Initialize and power up PLL */\r
+ SYSCON->SYSPLLMDEC = maxCCO;\r
+ POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
+\r
+ /* Set mreq to activate */\r
+ SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);\r
+\r
+ /* Delay for 72 uSec @ 12Mhz */\r
+ SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+\r
+ /* clear mreq to prepare for restoring mreq */\r
+ SYSCON->SYSPLLMDEC = curSSCTRL;\r
+\r
+ /* set original value back and activate */\r
+ SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);\r
+\r
+ /* Enable peripheral states by setting low */\r
+ POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
+ }\r
+ if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
+ {\r
+ while (CLOCK_IsAudioPLLLocked() == false)\r
+ {\r
+ }\r
+ }\r
+\r
+ /* Update current programmed PLL rate var */\r
+ s_Audio_Pll_Freq = pSetup->pllRate;\r
+\r
+ return kStatus_PLL_Success;\r
+}\r
+\r
+/* Setup USB PLL Frequency from pre-calculated value */\r
+/**\r
+ * brief Set USB PLL output from USB PLL setup structure (precise frequency)\r
+ * param pSetup : Pointer to populated USB PLL setup structure\r
+ * return kStatus_PLL_Success on success, or USB PLL setup error code\r
+ * note This function will power off the USB PLL, setup the PLL with the\r
+ * new setup data, and then optionally powerup the USB PLL, wait for USB PLL lock,\r
+ * and adjust system voltages to the new USB PLL rate. The function will not\r
+ * alter any source clocks (ie, usb pll clock) that may use the USB PLL,\r
+ * so these should be setup prior to and after exiting the function.\r
+ */\r
+pll_error_t CLOCK_SetUsbPLLFreq(const usb_pll_setup_t *pSetup)\r
+{\r
+ uint32_t usbpllctrl, fccoHz;\r
+ uint8_t msel, psel, nsel;\r
+ bool pllDirectInput, pllDirectOutput, pllfbsel;\r
+\r
+ msel = pSetup->msel;\r
+ psel = pSetup->psel;\r
+ nsel = pSetup->nsel;\r
+ pllDirectOutput = pSetup->direct;\r
+ pllDirectInput = pSetup->bypass;\r
+ pllfbsel = pSetup->fbsel;\r
+\r
+ /* Input clock into the PLL cannot be lower than this */\r
+ if (pSetup->inputRate < USB_PLL_LOWER_IN_LIMIT)\r
+ {\r
+ return kStatus_PLL_InputTooLow;\r
+ }\r
+\r
+ if (pllfbsel)\r
+ {\r
+ /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */\r
+ fccoHz = (pSetup->inputRate / ((uint32_t)nsel + 1U)) * 2U * (msel + 1U) * SWITCH_USB_PSEL(psel);\r
+\r
+ /* USB PLL CCO out rate cannot be lower than this */\r
+ if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ)\r
+ {\r
+ return kStatus_PLL_CCOTooLow;\r
+ }\r
+ /* USB PLL CCO out rate cannot be Higher than this */\r
+ if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ)\r
+ {\r
+ return kStatus_PLL_CCOTooHigh;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */\r
+ fccoHz = pSetup->inputRate / ((uint32_t)nsel + 1U) * (msel + 1U);\r
+\r
+ /* USB PLL CCO out rate cannot be lower than this */\r
+ if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ)\r
+ {\r
+ return kStatus_PLL_CCOTooLow;\r
+ }\r
+ /* USB PLL CCO out rate cannot be Higher than this */\r
+ if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ)\r
+ {\r
+ return kStatus_PLL_CCOTooHigh;\r
+ }\r
+ }\r
+\r
+ /* If configure the USB HOST clock, VD5 power for USB PHY should be enable\r
+ before the PLL is working */\r
+ /* Turn on the ext clock for usb pll input */\r
+ CLOCK_Enable_SysOsc(true);\r
+\r
+ /* Enable power VD3 for PLLs */\r
+ POWER_SetPLL();\r
+\r
+ /* Power on the VD5 for USB PHY */\r
+ POWER_SetUsbPhy();\r
+\r
+ /* Power off USB PLL during setup changes */\r
+ POWER_EnablePD(kPDRUNCFG_PD_USB_PLL);\r
+\r
+ /* Write USB PLL setup data */\r
+ usbpllctrl = USB_PLL_NSEL_VAL_SET(nsel) | /* NSEL VALUE */\r
+ USB_PLL_PSEL_VAL_SET(psel) | /* PSEL VALUE */\r
+ USB_PLL_MSEL_VAL_SET(msel) | /* MSEL VALUE */\r
+ (uint32_t)pllDirectInput << SYSCON_USBPLLCTRL_BYPASS_SHIFT | /* BYPASS DISABLE */\r
+ (uint32_t)pllDirectOutput << SYSCON_USBPLLCTRL_DIRECT_SHIFT | /* DIRECTO DISABLE */\r
+ (uint32_t)pllfbsel << SYSCON_USBPLLCTRL_FBSEL_SHIFT; /* FBSEL SELECT */\r
+\r
+ SYSCON->USBPLLCTRL = usbpllctrl;\r
+\r
+ POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);\r
+\r
+ /* Delay for 72 uSec @ 12Mhz for the usb pll to lock */\r
+ SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+ if (false == pllDirectInput)\r
+ {\r
+ while (CLOCK_IsUsbPLLLocked() == false)\r
+ {\r
+ }\r
+ }\r
+ CLOCK_GetUsbPLLOutFromSetupUpdate(pSetup);\r
+ return kStatus_PLL_Success;\r
+}\r
+\r
+/* Set System PLL clock based on the input frequency and multiplier */\r
+/*! brief Set PLL output based on the multiplier and input frequency\r
+ * param multiply_by : multiplier\r
+ * param input_freq : Clock input frequency of the PLL\r
+ * return Nothing\r
+ * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this\r
+ * function does not disable or enable PLL power, wait for PLL lock,\r
+ * or adjust system voltages. These must be done in the application.\r
+ * The function will not alter any source clocks (ie, main systen clock)\r
+ * that may use the PLL, so these should be setup prior to and after\r
+ * exiting the function.\r
+ */\r
+void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq)\r
+{\r
+ uint32_t cco_freq = input_freq * multiply_by;\r
+ uint32_t pdec = 1U;\r
+ uint32_t selr;\r
+ uint32_t seli;\r
+ uint32_t selp;\r
+ uint32_t mdec, ndec;\r
+\r
+ uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO(1);\r
+\r
+ while (cco_freq < 275000000U)\r
+ {\r
+ multiply_by <<= 1U; /* double value in each iteration */\r
+ pdec <<= 1U; /* correspondingly double pdec to cancel effect of double msel */\r
+ cco_freq = input_freq * multiply_by;\r
+ }\r
+ selr = 0U;\r
+ if (multiply_by < 60U)\r
+ {\r
+ seli = (multiply_by & 0x3cU) + 4U;\r
+ selp = (multiply_by >> 1U) + 1U;\r
+ }\r
+ else\r
+ {\r
+ selp = 31U;\r
+ if (multiply_by > 16384U)\r
+ {\r
+ seli = 1U;\r
+ }\r
+ else if (multiply_by > 8192U)\r
+ {\r
+ seli = 2U;\r
+ }\r
+ else if (multiply_by > 2048U)\r
+ {\r
+ seli = 4U;\r
+ }\r
+ else if (multiply_by >= 501U)\r
+ {\r
+ seli = 8U;\r
+ }\r
+ else\r
+ {\r
+ seli = 4U * (1024U / (multiply_by + 9U));\r
+ }\r
+ }\r
+\r
+ if (pdec > 1U)\r
+ {\r
+ directo = 0U; /* use post divider */\r
+ pdec = pdec / 2U; /* Account for minus 1 encoding */\r
+ /* Translate P value */\r
+ switch (pdec)\r
+ {\r
+ case 1U:\r
+ pdec = 0x62U; /* 1 * 2 */\r
+ break;\r
+ case 2U:\r
+ pdec = 0x42U; /* 2 * 2 */\r
+ break;\r
+ case 4U:\r
+ pdec = 0x02U; /* 4 * 2 */\r
+ break;\r
+ case 8U:\r
+ pdec = 0x0bU; /* 8 * 2 */\r
+ break;\r
+ case 16U:\r
+ pdec = 0x11U; /* 16 * 2 */\r
+ break;\r
+ case 32U:\r
+ pdec = 0x08U; /* 32 * 2 */\r
+ break;\r
+ default:\r
+ pdec = 0x08U;\r
+ break;\r
+ }\r
+ }\r
+\r
+ mdec = PLL_MDEC_VAL_SET(pllEncodeM(multiply_by));\r
+ ndec = 0x302U; /* pre divide by 1 (hardcoded) */\r
+\r
+ SYSCON->SYSPLLCTRL = directo | (selr << SYSCON_SYSPLLCTRL_SELR_SHIFT) | (seli << SYSCON_SYSPLLCTRL_SELI_SHIFT) |\r
+ (selp << SYSCON_SYSPLLCTRL_SELP_SHIFT);\r
+ SYSCON->SYSPLLPDEC = pdec | (1U << 7U); /* set Pdec value and assert preq */\r
+ SYSCON->SYSPLLNDEC = ndec | (1UL << 10U); /* set Pdec value and assert preq */\r
+ SYSCON->SYSPLLMDEC = (1UL << 17U) | mdec; /* select non sscg MDEC value, assert mreq and select mdec value */\r
+}\r
+\r
+/* Enable USB DEVICE FULL SPEED clock */\r
+/*! brief Enable USB Device FS clock.\r
+ * param src : clock source\r
+ * param freq: clock frequency\r
+ * Enable USB Device Full Speed clock.\r
+ */\r
+bool CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src, uint32_t freq)\r
+{\r
+ bool ret = true;\r
+\r
+ CLOCK_DisableClock(kCLOCK_Usbd0);\r
+\r
+ if (kCLOCK_UsbSrcFro == src)\r
+ {\r
+ switch (freq)\r
+ {\r
+ case 96000000U:\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */\r
+ break;\r
+\r
+ case 48000000U:\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */\r
+ break;\r
+\r
+ default:\r
+ ret = false;\r
+ break;\r
+ }\r
+ /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */\r
+ SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |\r
+ SYSCON_FROCTRL_USBCLKADJ_MASK;\r
+ /* Select FRO 96 or 48 MHz */\r
+ CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);\r
+ }\r
+ else\r
+ {\r
+ /*Set the USB PLL as the Usb0 CLK*/\r
+ POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);\r
+\r
+ usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};\r
+\r
+ (void)CLOCK_SetUsbPLLFreq(&pll_setup);\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);\r
+ CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK);\r
+ SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+ }\r
+ CLOCK_EnableClock(kCLOCK_Usbd0);\r
+ CLOCK_EnableClock(kCLOCK_UsbRam1);\r
+\r
+ return ret;\r
+}\r
+\r
+/* Enable USB HOST FULL SPEED clock */\r
+/*! brief Enable USB HOST FS clock.\r
+ * param src : clock source\r
+ * param freq: clock frequency\r
+ * Enable USB HOST Full Speed clock.\r
+ */\r
+bool CLOCK_EnableUsbfs0HostClock(clock_usb_src_t src, uint32_t freq)\r
+{\r
+ bool ret = true;\r
+\r
+ CLOCK_DisableClock(kCLOCK_Usbhmr0);\r
+ CLOCK_DisableClock(kCLOCK_Usbhsl0);\r
+\r
+ if (kCLOCK_UsbSrcFro == src)\r
+ {\r
+ switch (freq)\r
+ {\r
+ case 96000000U:\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */\r
+ break;\r
+\r
+ case 48000000U:\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */\r
+ break;\r
+\r
+ default:\r
+ ret = false;\r
+ break;\r
+ }\r
+ /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */\r
+ SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |\r
+ SYSCON_FROCTRL_USBCLKADJ_MASK;\r
+ /* Select FRO 96 or 48 MHz */\r
+ CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);\r
+ }\r
+ else\r
+ {\r
+ /*Set the USB PLL as the Usb0 CLK*/\r
+ POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);\r
+\r
+ usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};\r
+\r
+ (void)CLOCK_SetUsbPLLFreq(&pll_setup);\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);\r
+ CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK);\r
+ SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+ }\r
+ CLOCK_EnableClock(kCLOCK_Usbhmr0);\r
+ CLOCK_EnableClock(kCLOCK_Usbhsl0);\r
+ CLOCK_EnableClock(kCLOCK_UsbRam1);\r
+\r
+ return ret;\r
+}\r
+\r
+/* Enable USB DEVICE HIGH SPEED clock */\r
+/*! brief Enable USB Device HS clock.\r
+ * param src : clock source\r
+ * param freq: clock frequency\r
+ * Enable USB Device High Speed clock.\r
+ */\r
+bool CLOCK_EnableUsbhs0DeviceClock(clock_usb_src_t src, uint32_t freq)\r
+{\r
+ bool ret = true;\r
+ CLOCK_DisableClock(kCLOCK_Usbd1);\r
+ /* Power on the VD5 for USB PHY */\r
+ POWER_SetUsbPhy();\r
+ if (kCLOCK_UsbSrcFro == src)\r
+ {\r
+ switch (freq)\r
+ {\r
+ case 96000000U:\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */\r
+ break;\r
+\r
+ case 48000000U:\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */\r
+ break;\r
+\r
+ default:\r
+ ret = false;\r
+ break;\r
+ }\r
+ /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */\r
+ SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |\r
+ SYSCON_FROCTRL_USBCLKADJ_MASK;\r
+ /* Select FRO 96 or 48 MHz */\r
+ CLOCK_AttachClk(kFRO_HF_to_USB1_CLK);\r
+ }\r
+ else\r
+ {\r
+ SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+ usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};\r
+\r
+ (void)CLOCK_SetUsbPLLFreq(&pll_setup);\r
+\r
+ /* Select USB PLL output as USB clock src */\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false);\r
+ CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK);\r
+ }\r
+\r
+ SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+ /* Enable USB1D and USB1RAM */\r
+ CLOCK_EnableClock(kCLOCK_Usbd1);\r
+ CLOCK_EnableClock(kCLOCK_UsbRam1);\r
+ POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */\r
+ return ret;\r
+}\r
+\r
+/* Enable USB HOST HIGH SPEED clock */\r
+/*! brief Enable USB HOST HS clock.\r
+ * param src : clock source\r
+ * param freq: clock frequency\r
+ * Enable USB HOST High Speed clock.\r
+ */\r
+bool CLOCK_EnableUsbhs0HostClock(clock_usb_src_t src, uint32_t freq)\r
+{\r
+ bool ret = true;\r
+ CLOCK_DisableClock(kCLOCK_Usbh1);\r
+ /* Power on the VD5 for USB PHY */\r
+ POWER_SetUsbPhy();\r
+ if (kCLOCK_UsbSrcFro == src)\r
+ {\r
+ switch (freq)\r
+ {\r
+ case 96000000U:\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */\r
+ break;\r
+\r
+ case 48000000U:\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */\r
+ break;\r
+\r
+ default:\r
+ ret = false;\r
+ break;\r
+ }\r
+ /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */\r
+ SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |\r
+ SYSCON_FROCTRL_USBCLKADJ_MASK;\r
+ /* Select FRO 96 or 48 MHz */\r
+ CLOCK_AttachClk(kFRO_HF_to_USB1_CLK);\r
+ }\r
+ else\r
+ {\r
+ SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+ usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};\r
+\r
+ (void)CLOCK_SetUsbPLLFreq(&pll_setup);\r
+\r
+ /* Select USB PLL output as USB clock src */\r
+ CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false);\r
+ CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK);\r
+ }\r
+\r
+ SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
+ /* Enable USBh1 and USB1RAM */\r
+ CLOCK_EnableClock(kCLOCK_Usbh1);\r
+ CLOCK_EnableClock(kCLOCK_UsbRam1);\r
+ POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */\r
+ return ret;\r
+}\r