]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_MPU_LPC54018_MCUXpresso/NXP_Code/drivers/fsl_clock.c
Add MPU demo project for LPC54018 board.
[freertos] / FreeRTOS / Demo / CORTEX_MPU_LPC54018_MCUXpresso / NXP_Code / drivers / fsl_clock.c
1 /*\r
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.\r
3  * Copyright 2016 - 2019 , NXP\r
4  * All rights reserved.\r
5  *\r
6  *\r
7  * SPDX-License-Identifier: BSD-3-Clause\r
8  */\r
9 \r
10 #include "fsl_clock.h"\r
11 #include "fsl_power.h"\r
12 /*******************************************************************************\r
13  * Definitions\r
14  ******************************************************************************/\r
15 /* Component ID definition, used by tools. */\r
16 #ifndef FSL_COMPONENT_ID\r
17 #define FSL_COMPONENT_ID "platform.drivers.clock"\r
18 #endif\r
19 #define NVALMAX (0x100U)\r
20 #define PVALMAX (0x20U)\r
21 #define MVALMAX (0x8000U)\r
22 \r
23 #define USB_NVALMAX (0x4U)\r
24 #define USB_PVALMAX (0x8U)\r
25 #define USB_MVALMAX (0x100U)\r
26 \r
27 #define PLL_MAX_N_DIV 0x100U\r
28 #define USB_PLL_MAX_N_DIV 0x100U\r
29 \r
30 #define PLL_MDEC_VAL_P (0U)                          /*!<  MDEC is in bits  16 downto 0 */\r
31 #define PLL_MDEC_VAL_M (0x1FFFFUL << PLL_MDEC_VAL_P) /*!<  NDEC is in bits  9 downto 0 */\r
32 #define PLL_NDEC_VAL_P (0U)                          /*!<  NDEC is in bits  9:0 */\r
33 #define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P)\r
34 #define PLL_PDEC_VAL_P (0U) /*!<  PDEC is in bits 6:0 */\r
35 #define PLL_PDEC_VAL_M (0x7FUL << PLL_PDEC_VAL_P)\r
36 \r
37 #define PLL_MIN_CCO_FREQ_MHZ (275000000U)\r
38 #define PLL_MAX_CCO_FREQ_MHZ (550000000U)\r
39 #define PLL_LOWER_IN_LIMIT (4000U) /*!<  Minimum PLL input rate */\r
40 #define PLL_MIN_IN_SSMODE (2000000U)\r
41 #define PLL_MAX_IN_SSMODE (4000000U)\r
42 \r
43 /*!<  Middle of the range values for spread-spectrum */\r
44 #define PLL_SSCG_MF_FREQ_VALUE 4U\r
45 #define PLL_SSCG_MC_COMP_VALUE 2U\r
46 #define PLL_SSCG_MR_DEPTH_VALUE 4U\r
47 #define PLL_SSCG_DITHER_VALUE 0U\r
48 \r
49 /*!<  USB PLL CCO MAX AND MIN FREQ */\r
50 #define USB_PLL_MIN_CCO_FREQ_MHZ (156000000U)\r
51 #define USB_PLL_MAX_CCO_FREQ_MHZ (320000000U)\r
52 #define USB_PLL_LOWER_IN_LIMIT (1000000U) /*!<  Minimum PLL input rate */\r
53 \r
54 #define USB_PLL_MSEL_VAL_P (0U) /*!<  MSEL is in bits  7 downto 0 */\r
55 #define USB_PLL_MSEL_VAL_M (0xFFU)\r
56 #define USB_PLL_PSEL_VAL_P (8U) /*!<  PDEC is in bits 9:8 */\r
57 #define USB_PLL_PSEL_VAL_M (0x3U)\r
58 #define USB_PLL_NSEL_VAL_P (10U) /*!<  NDEC is in bits  11:10 */\r
59 #define USB_PLL_NSEL_VAL_M (0x3U)\r
60 \r
61 /*!<  SWITCH USB POSTDIVIDER FOR REGITSER WRITING */\r
62 #define SWITCH_USB_PSEL(x) \\r
63     (((x) == 0x0U) ? 0x1U : ((x) == 0x1U) ? 0x02U : ((x) == 0x2U) ? 0x4U : ((x) == 3U) ? 0x8U : 0U)\r
64 \r
65 /*!<  SYS PLL NDEC reg */\r
66 #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)\r
67 /*!<  SYS PLL PDEC reg */\r
68 #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)\r
69 /*!<  SYS PLL MDEC reg */\r
70 #define PLL_MDEC_VAL_SET(value) (((unsigned long)(value) << PLL_MDEC_VAL_P) & PLL_MDEC_VAL_M)\r
71 \r
72 /*!<  SYS PLL NSEL reg */\r
73 #define USB_PLL_NSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_NSEL_VAL_M) << USB_PLL_NSEL_VAL_P)\r
74 /*!<  SYS PLL PSEL reg */\r
75 #define USB_PLL_PSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_PSEL_VAL_M) << USB_PLL_PSEL_VAL_P)\r
76 /*!<  SYS PLL MSEL reg */\r
77 #define USB_PLL_MSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_MSEL_VAL_M) << USB_PLL_MSEL_VAL_P)\r
78 \r
79 /*!<  FRAC control */\r
80 #define AUDIO_PLL_FRACT_MD_P (0U)\r
81 #define AUDIO_PLL_FRACT_MD_INT_P (15U)\r
82 #define AUDIO_PLL_FRACT_MD_M (0x7FFFUL << AUDIO_PLL_FRACT_MD_P)\r
83 #define AUDIO_PLL_FRACT_MD_INT_M (0x7FUL << AUDIO_PLL_FRACT_MD_INT_P)\r
84 \r
85 #define AUDIO_PLL_MD_FRACT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_P) & PLL_FRAC_MD_FRACT_M)\r
86 #define AUDIO_PLL_MD_INT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_INT_P) & AUDIO_PLL_FRACT_MD_INT_M)\r
87 \r
88 /* Saved value of PLL output rate, computed whenever needed to save run-time\r
89    computation on each call to retrive the PLL rate. */\r
90 static uint32_t s_Pll_Freq;\r
91 static uint32_t s_Usb_Pll_Freq;\r
92 static uint32_t s_Audio_Pll_Freq;\r
93 \r
94 /** External clock rate on the CLKIN pin in Hz. If not used,\r
95     set this to 0. Otherwise, set it to the exact rate in Hz this pin is\r
96     being driven at. */\r
97 static const uint32_t g_I2S_Mclk_Freq   = 0U;\r
98 static const uint32_t g_Ext_Clk_Freq    = 12000000U;\r
99 static const uint32_t g_Lcd_Clk_In_Freq = 0U;\r
100 \r
101 /*******************************************************************************\r
102  * Variables\r
103  ******************************************************************************/\r
104 \r
105 /*******************************************************************************\r
106  * Prototypes\r
107  ******************************************************************************/\r
108 /* Find encoded NDEC value for raw N value, max N = NVALMAX */\r
109 static uint32_t pllEncodeN(uint32_t N);\r
110 /* Find decoded N value for raw NDEC value */\r
111 static uint32_t pllDecodeN(uint32_t NDEC);\r
112 /* Find encoded PDEC value for raw P value, max P = PVALMAX */\r
113 static uint32_t pllEncodeP(uint32_t P);\r
114 /* Find decoded P value for raw PDEC value */\r
115 static uint32_t pllDecodeP(uint32_t PDEC);\r
116 /* Find encoded MDEC value for raw M value, max M = MVALMAX */\r
117 static uint32_t pllEncodeM(uint32_t M);\r
118 /* Find decoded M value for raw MDEC value */\r
119 static uint32_t pllDecodeM(uint32_t MDEC);\r
120 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */\r
121 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);\r
122 /* Get predivider (N) from PLL NDEC setting */\r
123 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg);\r
124 /* Get postdivider (P) from PLL PDEC setting */\r
125 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg);\r
126 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */\r
127 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg);\r
128 /* Convert the binary to fractional part */\r
129 static double Binary2Fractional(uint32_t binaryPart);\r
130 /* Calculate the powerTimes' power of 2 */\r
131 static uint32_t power2Cal(uint32_t powerTimes);\r
132 /* Get the greatest common divisor */\r
133 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);\r
134 /* Set PLL output based on desired output rate */\r
135 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup);\r
136 \r
137 /* Update local PLL rate variable */\r
138 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup);\r
139 static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup);\r
140 \r
141 /*!\r
142  * @brief Set fro clock frequency.\r
143  * Due to LPC540xx 0A silicon and LPC540xx 1B silicon have different ROM addresses for set fro\r
144  * frequency api, so add this api to get rom version.\r
145  * @param base romVersion pointer to recieve rom version.\r
146  */\r
147 #if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \\r
148     (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION)\r
149 static uint32_t CLOCK_GetRomVersion(uint8_t *romVersion);\r
150 #endif\r
151 \r
152 static const uint8_t wdtFreqLookup[32] = {0,  8,  12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41,\r
153                                           42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61};\r
154 /*******************************************************************************\r
155  * Code\r
156  ******************************************************************************/\r
157 #if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \\r
158     (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION)\r
159 static uint32_t CLOCK_GetRomVersion(uint8_t *romVersion)\r
160 {\r
161     uint32_t command[5] = {0U}, result[4] = {0U};\r
162 \r
163     command[0] = 55U;\r
164     result[0]  = 0;\r
165     result[1]  = 0;\r
166     ((void (*)(uint32_t cmd[5], uint32_t stat[4]))FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION)(command, result);\r
167 \r
168     *romVersion = (uint8_t)(result[1]);\r
169 \r
170     return result[0];\r
171 }\r
172 #endif\r
173 \r
174 /**\r
175  * brief\r
176  *  Initialize the Core clock to given frequency (12, 48 or 96 MHz), this API is implememnt in ROM code.\r
177  * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed\r
178  * output is enabled.\r
179  * Usage: CLOCK_SetupFROClocking(frequency), (frequency must be one of 12, 48 or 96 MHz)\r
180  *  Note: Need to make sure ROM and OTP has power(PDRUNCFG0[17,29]= 0U) before calling this API since this API is\r
181  * implemented in ROM code and the FROHF TRIM value is stored in OTP\r
182  *\r
183  * param froFreq target fro frequency.\r
184  * return   Nothing\r
185  */\r
186 \r
187 void CLOCK_SetupFROClocking(uint32_t froFreq)\r
188 {\r
189     uint32_t froRomAddr = 0U;\r
190 #if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \\r
191     (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION)\r
192     uint8_t romVersion = 0U;\r
193 \r
194     if (CLOCK_GetRomVersion(&romVersion) == (uint32_t)kStatus_Success)\r
195     {\r
196         if (romVersion == FSL_ROM_VERSION_1B)\r
197         {\r
198             froRomAddr = FSL_ROM_VERSION_1B_FRO_SETTING_ADDR;\r
199         }\r
200         else\r
201         {\r
202             froRomAddr = FSL_ROM_VERSION_0A_FRO_SETTING_ADDR;\r
203         }\r
204 \r
205         (*((void (*)(uint32_t funcname))(froRomAddr)))(froFreq);\r
206     }\r
207 #else\r
208     froRomAddr = FSL_ROM_VERSION_0A_FRO_SETTING_ADDR;\r
209 \r
210     (*((void (*)(uint32_t))(froRomAddr)))(froFreq);\r
211 #endif\r
212 }\r
213 \r
214 /* Clock Selection for IP */\r
215 /**\r
216  * brief        Configure the clock selection muxes.\r
217  * param        connection      : Clock to be configured.\r
218  * return       Nothing\r
219  */\r
220 void CLOCK_AttachClk(clock_attach_id_t connection)\r
221 {\r
222     uint8_t mux;\r
223     uint8_t sel;\r
224     uint16_t item;\r
225     uint32_t tmp32 = (uint32_t)connection;\r
226     uint32_t i;\r
227     volatile uint32_t *pClkSel;\r
228 \r
229     pClkSel = &(SYSCON->STICKCLKSEL);\r
230 \r
231     if (kNONE_to_NONE != connection)\r
232     {\r
233         for (i = 0U; i < 2U; i++)\r
234         {\r
235             if (tmp32 == 0U)\r
236             {\r
237                 break;\r
238             }\r
239             item = (uint16_t)GET_ID_ITEM(tmp32);\r
240             if (item != 0UL)\r
241             {\r
242                 mux = GET_ID_ITEM_MUX(item);\r
243                 sel = GET_ID_ITEM_SEL(item);\r
244                 if (mux == CM_ASYNCAPB)\r
245                 {\r
246                     SYSCON->ASYNCAPBCTRL          = SYSCON_ASYNCAPBCTRL_ENABLE(1);\r
247                     ASYNC_SYSCON->ASYNCAPBCLKSELA = sel;\r
248                 }\r
249                 else\r
250                 {\r
251                     ((volatile uint32_t *)pClkSel)[mux] = sel;\r
252                 }\r
253             }\r
254             tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */\r
255         }\r
256     }\r
257 }\r
258 \r
259 /* Return the actual clock attach id */\r
260 /**\r
261  * brief   Get the actual clock attach id.\r
262  * This fuction uses the offset in input attach id, then it reads the actual source value in\r
263  * the register and combine the offset to obtain an actual attach id.\r
264  * param   attachId  : Clock attach id to get.\r
265  * return  Clock source value.\r
266  */\r
267 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)\r
268 {\r
269     uint8_t mux;\r
270     uint8_t actualSel;\r
271     uint32_t tmp32 = (uint32_t)attachId;\r
272     uint32_t i;\r
273     uint32_t actualAttachId = 0U;\r
274     uint32_t selector       = GET_ID_SELECTOR(tmp32);\r
275     volatile uint32_t *pClkSel;\r
276 \r
277     pClkSel = &(SYSCON->STICKCLKSEL);\r
278 \r
279     if (kNONE_to_NONE == attachId)\r
280     {\r
281         return kNONE_to_NONE;\r
282     }\r
283 \r
284     for (i = 0U; i < 2U; i++)\r
285     {\r
286         mux = GET_ID_ITEM_MUX(tmp32);\r
287         if (tmp32 != 0UL)\r
288         {\r
289             if (mux == CM_ASYNCAPB)\r
290             {\r
291                 actualSel = (uint8_t)(ASYNC_SYSCON->ASYNCAPBCLKSELA);\r
292             }\r
293             else\r
294             {\r
295                 actualSel = (uint8_t)(((volatile uint32_t *)pClkSel)[mux]);\r
296             }\r
297 \r
298             /* Consider the combination of two registers */\r
299             actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);\r
300         }\r
301         tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!<  pick up next descriptor */\r
302     }\r
303 \r
304     actualAttachId |= selector;\r
305 \r
306     return (clock_attach_id_t)actualAttachId;\r
307 }\r
308 \r
309 /* Set IP Clock Divider */\r
310 /**\r
311  * brief        Setup peripheral clock dividers.\r
312  * param        div_name        : Clock divider name\r
313  * param divided_by_value: Value to be divided\r
314  * param reset :  Whether to reset the divider counter.\r
315  * return       Nothing\r
316  */\r
317 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)\r
318 {\r
319     volatile uint32_t *pClkDiv;\r
320 \r
321     pClkDiv = &(SYSCON->SYSTICKCLKDIV);\r
322     if (reset)\r
323     {\r
324         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 29U;\r
325     }\r
326     if (divided_by_value == 0U) /*!<  halt */\r
327     {\r
328         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 30U;\r
329     }\r
330     else\r
331     {\r
332         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = (divided_by_value - 1U);\r
333     }\r
334 }\r
335 \r
336 /* Get CLOCK OUT Clk */\r
337 /*! brief       Return Frequency of ClockOut\r
338  *  return      Frequency of ClockOut\r
339  */\r
340 uint32_t CLOCK_GetClockOutClkFreq(void)\r
341 {\r
342     uint32_t freq = 0U;\r
343 \r
344     switch (SYSCON->CLKOUTSELA)\r
345     {\r
346         case 0U:\r
347             freq = CLOCK_GetCoreSysClkFreq();\r
348             break;\r
349 \r
350         case 1U:\r
351             freq = CLOCK_GetExtClkFreq();\r
352             break;\r
353 \r
354         case 2U:\r
355             freq = CLOCK_GetWdtOscFreq();\r
356             break;\r
357 \r
358         case 3U:\r
359             freq = CLOCK_GetFroHfFreq();\r
360             break;\r
361 \r
362         case 4U:\r
363             freq = CLOCK_GetPllOutFreq();\r
364             break;\r
365 \r
366         case 5U:\r
367             freq = CLOCK_GetUsbPllOutFreq();\r
368             break;\r
369 \r
370         case 6U:\r
371             freq = CLOCK_GetAudioPllOutFreq();\r
372             break;\r
373 \r
374         case 7U:\r
375             freq = CLOCK_GetOsc32KFreq();\r
376             break;\r
377 \r
378         default:\r
379             freq = 0U;\r
380             break;\r
381     }\r
382     return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);\r
383 }\r
384 \r
385 /* Get SPIFI Clk */\r
386 /*! brief       Return Frequency of Spifi Clock\r
387  *  return      Frequency of Spifi.\r
388  */\r
389 uint32_t CLOCK_GetSpifiClkFreq(void)\r
390 {\r
391     uint32_t freq = 0U;\r
392 \r
393     switch (SYSCON->SPIFICLKSEL)\r
394     {\r
395         case 0U:\r
396             freq = CLOCK_GetCoreSysClkFreq();\r
397             break;\r
398         case 1U:\r
399             freq = CLOCK_GetPllOutFreq();\r
400             break;\r
401         case 2U:\r
402             freq = CLOCK_GetUsbPllOutFreq();\r
403             break;\r
404         case 3U:\r
405             freq = CLOCK_GetFroHfFreq();\r
406             break;\r
407         case 4U:\r
408             freq = CLOCK_GetAudioPllOutFreq();\r
409             break;\r
410         case 7U:\r
411             freq = 0U;\r
412             break;\r
413         default:\r
414             freq = 0U;\r
415             break;\r
416     }\r
417 \r
418     return freq / ((SYSCON->SPIFICLKDIV & 0xffU) + 1U);\r
419 }\r
420 \r
421 /* Get ADC Clk */\r
422 /*! brief       Return Frequency of Adc Clock\r
423  *  return      Frequency of Adc Clock.\r
424  */\r
425 uint32_t CLOCK_GetAdcClkFreq(void)\r
426 {\r
427     uint32_t freq = 0U;\r
428 \r
429     switch (SYSCON->ADCCLKSEL)\r
430     {\r
431         case 0U:\r
432             freq = CLOCK_GetFroHfFreq();\r
433             break;\r
434         case 1U:\r
435             freq = CLOCK_GetPllOutFreq();\r
436             break;\r
437         case 2U:\r
438             freq = CLOCK_GetUsbPllOutFreq();\r
439             break;\r
440         case 3U:\r
441             freq = CLOCK_GetAudioPllOutFreq();\r
442             break;\r
443         case 7U:\r
444             freq = 0U;\r
445             break;\r
446         default:\r
447             freq = 0U;\r
448             break;\r
449     }\r
450 \r
451     return freq / ((SYSCON->ADCCLKDIV & 0xffU) + 1U);\r
452 }\r
453 \r
454 /* Get USB0 Clk */\r
455 /*! brief       Return Frequency of Usb0 Clock\r
456  *  return      Frequency of Usb0 Clock.\r
457  */\r
458 uint32_t CLOCK_GetUsb0ClkFreq(void)\r
459 {\r
460     uint32_t freq = 0U;\r
461 \r
462     switch (SYSCON->USB0CLKSEL)\r
463     {\r
464         case 0U:\r
465             freq = CLOCK_GetFroHfFreq();\r
466             break;\r
467         case 1U:\r
468             freq = CLOCK_GetPllOutFreq();\r
469             break;\r
470         case 2U:\r
471             freq = CLOCK_GetUsbPllOutFreq();\r
472             break;\r
473         case 7U:\r
474             freq = 0U;\r
475             break;\r
476 \r
477         default:\r
478             freq = 0U;\r
479             break;\r
480     }\r
481 \r
482     return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);\r
483 }\r
484 \r
485 /* Get USB1 Clk */\r
486 /*! brief       Return Frequency of Usb1 Clock\r
487  *  return      Frequency of Usb1 Clock.\r
488  */\r
489 uint32_t CLOCK_GetUsb1ClkFreq(void)\r
490 {\r
491     uint32_t freq = 0U;\r
492 \r
493     switch (SYSCON->USB1CLKSEL)\r
494     {\r
495         case 0U:\r
496             freq = CLOCK_GetCoreSysClkFreq();\r
497             break;\r
498         case 1U:\r
499             freq = CLOCK_GetPllOutFreq();\r
500             break;\r
501         case 2U:\r
502             freq = CLOCK_GetUsbPllOutFreq();\r
503             break;\r
504         case 7U:\r
505             freq = 0U;\r
506             break;\r
507 \r
508         default:\r
509             freq = 0U;\r
510             break;\r
511     }\r
512 \r
513     return freq / ((SYSCON->USB1CLKDIV & 0xffU) + 1U);\r
514 }\r
515 \r
516 /* Get MCLK Clk */\r
517 /*! brief       Return Frequency of MClk Clock\r
518  *  return      Frequency of MClk Clock.\r
519  */\r
520 uint32_t CLOCK_GetMclkClkFreq(void)\r
521 {\r
522     uint32_t freq = 0U;\r
523 \r
524     switch (SYSCON->MCLKCLKSEL)\r
525     {\r
526         case 0U:\r
527             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffu) + 1U);\r
528             break;\r
529         case 1U:\r
530             freq = CLOCK_GetAudioPllOutFreq();\r
531             break;\r
532         case 7U:\r
533             freq = 0U;\r
534             break;\r
535 \r
536         default:\r
537             freq = 0U;\r
538             break;\r
539     }\r
540 \r
541     return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);\r
542 }\r
543 \r
544 /* Get SCTIMER Clk */\r
545 /*! brief       Return Frequency of SCTimer Clock\r
546  *  return      Frequency of SCTimer Clock.\r
547  */\r
548 uint32_t CLOCK_GetSctClkFreq(void)\r
549 {\r
550     uint32_t freq = 0U;\r
551 \r
552     switch (SYSCON->SCTCLKSEL)\r
553     {\r
554         case 0U:\r
555             freq = CLOCK_GetCoreSysClkFreq();\r
556             break;\r
557         case 1U:\r
558             freq = CLOCK_GetPllOutFreq();\r
559             break;\r
560         case 2U:\r
561             freq = CLOCK_GetFroHfFreq();\r
562             break;\r
563         case 3U:\r
564             freq = CLOCK_GetAudioPllOutFreq();\r
565             break;\r
566         case 7U:\r
567             freq = 0U;\r
568             break;\r
569 \r
570         default:\r
571             freq = 0U;\r
572             break;\r
573     }\r
574 \r
575     return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);\r
576 }\r
577 \r
578 /* Get SDIO Clk */\r
579 /*! brief       Return Frequency of SDIO Clock\r
580  *  return      Frequency of SDIO Clock.\r
581  */\r
582 uint32_t CLOCK_GetSdioClkFreq(void)\r
583 {\r
584     uint32_t freq = 0U;\r
585 \r
586     switch (SYSCON->SDIOCLKSEL)\r
587     {\r
588         case 0U:\r
589             freq = CLOCK_GetCoreSysClkFreq();\r
590             break;\r
591         case 1U:\r
592             freq = CLOCK_GetPllOutFreq();\r
593             break;\r
594         case 2U:\r
595             freq = CLOCK_GetUsbPllOutFreq();\r
596             break;\r
597         case 3U:\r
598             freq = CLOCK_GetFroHfFreq();\r
599             break;\r
600         case 4U:\r
601             freq = CLOCK_GetAudioPllOutFreq();\r
602             break;\r
603         case 7U:\r
604             freq = 0U;\r
605             break;\r
606         default:\r
607             freq = 0U;\r
608             break;\r
609     }\r
610 \r
611     return freq / ((SYSCON->SDIOCLKDIV & 0xffU) + 1U);\r
612 }\r
613 \r
614 /* Get LCD Clk */\r
615 /*! brief       Return Frequency of LCD Clock\r
616  *  return      Frequency of LCD Clock.\r
617  */\r
618 uint32_t CLOCK_GetLcdClkFreq(void)\r
619 {\r
620     uint32_t freq = 0U;\r
621 \r
622     switch (SYSCON->LCDCLKSEL)\r
623     {\r
624         case 0U:\r
625             freq = CLOCK_GetCoreSysClkFreq();\r
626             break;\r
627         case 1U:\r
628             freq = CLOCK_GetLcdClkIn();\r
629             break;\r
630         case 2U:\r
631             freq = CLOCK_GetFroHfFreq();\r
632             break;\r
633         case 3U:\r
634             freq = 0U;\r
635             break;\r
636 \r
637         default:\r
638             freq = 0U;\r
639             break;\r
640     }\r
641 \r
642     return freq / ((SYSCON->LCDCLKDIV & 0xffU) + 1U);\r
643 }\r
644 \r
645 /* Get LCD CLK IN Clk */\r
646 /*! brief       Return Frequency of LCD CLKIN Clock\r
647  *  return      Frequency of LCD CLKIN Clock.\r
648  */\r
649 uint32_t CLOCK_GetLcdClkIn(void)\r
650 {\r
651     return g_Lcd_Clk_In_Freq;\r
652 }\r
653 \r
654 /* Get FRO 12M Clk */\r
655 /*! brief       Return Frequency of FRO 12MHz\r
656  *  return      Frequency of FRO 12MHz\r
657  */\r
658 uint32_t CLOCK_GetFro12MFreq(void)\r
659 {\r
660     return ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ? 0U : 12000000U;\r
661 }\r
662 \r
663 /* Get EXT OSC Clk */\r
664 /*! brief       Return Frequency of External Clock\r
665  *  return      Frequency of External Clock. If no external clock is used returns 0.\r
666  */\r
667 uint32_t CLOCK_GetExtClkFreq(void)\r
668 {\r
669     return g_Ext_Clk_Freq;\r
670 }\r
671 \r
672 /* Get WATCH DOG Clk */\r
673 /*! brief       Return Frequency of Watchdog Oscillator\r
674  *  return      Frequency of Watchdog Oscillator\r
675  */\r
676 uint32_t CLOCK_GetWdtOscFreq(void)\r
677 {\r
678     uint8_t freq_sel, div_sel;\r
679     if ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_WDT_OSC_MASK) != 0UL)\r
680     {\r
681         return 0U;\r
682     }\r
683     else\r
684     {\r
685         div_sel = (uint8_t)(((SYSCON->WDTOSCCTRL & 0x1fU) + 1U) << 1U);\r
686         freq_sel =\r
687             wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)];\r
688         return ((uint32_t)freq_sel * 50000U) / ((uint32_t)div_sel);\r
689     }\r
690 }\r
691 \r
692 /* Get HF FRO Clk */\r
693 /*! brief       Return Frequency of High-Freq output of FRO\r
694  *  return      Frequency of High-Freq output of FRO\r
695  */\r
696 uint32_t CLOCK_GetFroHfFreq(void)\r
697 {\r
698     if (((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ||\r
699         (0UL == (SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK)))\r
700     {\r
701         return 0U;\r
702     }\r
703 \r
704     if ((SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK) != 0UL)\r
705     {\r
706         return 96000000U;\r
707     }\r
708     else\r
709     {\r
710         return 48000000U;\r
711     }\r
712 }\r
713 \r
714 /* Get SYSTEM PLL Clk */\r
715 /*! brief       Return Frequency of PLL\r
716  *  return      Frequency of PLL\r
717  */\r
718 uint32_t CLOCK_GetPllOutFreq(void)\r
719 {\r
720     return s_Pll_Freq;\r
721 }\r
722 \r
723 /* Get AUDIO PLL Clk */\r
724 /*! brief       Return Frequency of AUDIO PLL\r
725  *  return      Frequency of PLL\r
726  */\r
727 uint32_t CLOCK_GetAudioPllOutFreq(void)\r
728 {\r
729     return s_Audio_Pll_Freq;\r
730 }\r
731 \r
732 /* Get USB PLL Clk */\r
733 /*! brief       Return Frequency of USB PLL\r
734  *  return      Frequency of PLL\r
735  */\r
736 uint32_t CLOCK_GetUsbPllOutFreq(void)\r
737 {\r
738     return s_Usb_Pll_Freq;\r
739 }\r
740 \r
741 /* Get RTC OSC Clk */\r
742 /*! brief       Return Frequency of 32kHz osc\r
743  *  return      Frequency of 32kHz osc\r
744  */\r
745 uint32_t CLOCK_GetOsc32KFreq(void)\r
746 {\r
747     return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */\r
748 }\r
749 \r
750 /* Get MAIN Clk */\r
751 /*! brief       Return Frequency of Core System\r
752  *  return      Frequency of Core System\r
753  */\r
754 uint32_t CLOCK_GetCoreSysClkFreq(void)\r
755 {\r
756     uint32_t freq = 0U;\r
757 \r
758     switch (SYSCON->MAINCLKSELB)\r
759     {\r
760         case 0U:\r
761             if (SYSCON->MAINCLKSELA == 0U)\r
762             {\r
763                 freq = CLOCK_GetFro12MFreq();\r
764             }\r
765             else if (SYSCON->MAINCLKSELA == 1U)\r
766             {\r
767                 freq = CLOCK_GetExtClkFreq();\r
768             }\r
769             else if (SYSCON->MAINCLKSELA == 2U)\r
770             {\r
771                 freq = CLOCK_GetWdtOscFreq();\r
772             }\r
773             else if (SYSCON->MAINCLKSELA == 3U)\r
774             {\r
775                 freq = CLOCK_GetFroHfFreq();\r
776             }\r
777             else\r
778             {\r
779                 /* Add comment to prevent the case of rule 15.7. */\r
780             }\r
781             break;\r
782         case 2U:\r
783             freq = CLOCK_GetPllOutFreq();\r
784             break;\r
785 \r
786         case 3U:\r
787             freq = CLOCK_GetOsc32KFreq();\r
788             break;\r
789 \r
790         default:\r
791             freq = 0U;\r
792             break;\r
793     }\r
794 \r
795     return freq;\r
796 }\r
797 \r
798 /* Get I2S MCLK Clk */\r
799 /*! brief       Return Frequency of I2S MCLK Clock\r
800  *  return      Frequency of I2S MCLK Clock\r
801  */\r
802 uint32_t CLOCK_GetI2SMClkFreq(void)\r
803 {\r
804     return g_I2S_Mclk_Freq;\r
805 }\r
806 \r
807 /* Get ASYNC APB Clk */\r
808 /*! brief       Return Frequency of Asynchronous APB Clock\r
809  *  return      Frequency of Asynchronous APB Clock Clock\r
810  */\r
811 uint32_t CLOCK_GetAsyncApbClkFreq(void)\r
812 {\r
813     async_clock_src_t clkSrc;\r
814     uint32_t clkRate;\r
815 \r
816     clkSrc = CLOCK_GetAsyncApbClkSrc();\r
817 \r
818     switch (clkSrc)\r
819     {\r
820         case kCLOCK_AsyncMainClk:\r
821             clkRate = CLOCK_GetCoreSysClkFreq();\r
822             break;\r
823         case kCLOCK_AsyncFro12Mhz:\r
824             clkRate = CLK_FRO_12MHZ;\r
825             break;\r
826         default:\r
827             clkRate = 0U;\r
828             break;\r
829     }\r
830 \r
831     return clkRate;\r
832 }\r
833 \r
834 /* Get MCAN Clk */\r
835 /*! brief       Return Frequency of MCAN Clock\r
836  *  param       MCanSel : 0U: MCAN0; 1U: MCAN1\r
837  *  return      Frequency of MCAN Clock\r
838  */\r
839 uint32_t CLOCK_GetMCanClkFreq(uint32_t MCanSel)\r
840 {\r
841     uint32_t freq = 0U;\r
842     switch (MCanSel)\r
843     {\r
844         case 0U:\r
845             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN0CLKDIV & 0xffU) + 1U);\r
846             break;\r
847         case 1U:\r
848             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN1CLKDIV & 0xffU) + 1U);\r
849             break;\r
850 \r
851         default:\r
852             freq = 0U;\r
853             break;\r
854     }\r
855 \r
856     return freq;\r
857 }\r
858 \r
859 /* Get FLEXCOMM Clk */\r
860 /*! brief       Return Frequency of Flexcomm functional Clock\r
861  *  return      Frequency of Flexcomm functional Clock\r
862  */\r
863 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)\r
864 {\r
865     uint32_t freq = 0U;\r
866 \r
867     if (id != 10U)\r
868     {\r
869         switch (SYSCON->FCLKSEL[id])\r
870         {\r
871             case 0U:\r
872                 freq = CLOCK_GetFro12MFreq();\r
873                 break;\r
874             case 1U:\r
875                 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffu) + 1U);\r
876                 break;\r
877             case 2U:\r
878                 freq = CLOCK_GetAudioPllOutFreq();\r
879                 break;\r
880             case 3U:\r
881                 freq = CLOCK_GetI2SMClkFreq();\r
882                 break;\r
883             case 4U:\r
884                 freq = CLOCK_GetFrgClkFreq();\r
885                 break;\r
886 \r
887             default:\r
888                 freq = 0U;\r
889                 break;\r
890         }\r
891     }\r
892     else\r
893     {\r
894         switch (SYSCON->FCLKSEL10)\r
895         {\r
896             case 0U:\r
897                 freq = CLOCK_GetCoreSysClkFreq();\r
898                 break;\r
899             case 1U:\r
900                 freq = CLOCK_GetPllOutFreq();\r
901                 break;\r
902             case 2U:\r
903                 freq = CLOCK_GetUsbPllOutFreq();\r
904                 break;\r
905             case 3U:\r
906                 freq = CLOCK_GetFroHfFreq();\r
907                 break;\r
908             case 4U:\r
909                 freq = CLOCK_GetAudioPllOutFreq();\r
910                 break;\r
911             default:\r
912                 freq = 0U;\r
913                 break;\r
914         }\r
915     }\r
916 \r
917     return freq;\r
918 }\r
919 \r
920 /* Get FRG Clk */\r
921 uint32_t CLOCK_GetFRGInputClock(void)\r
922 {\r
923     uint32_t freq = 0U;\r
924 \r
925     switch (SYSCON->FRGCLKSEL)\r
926     {\r
927         case 0U:\r
928             freq = CLOCK_GetCoreSysClkFreq();\r
929             break;\r
930         case 1U:\r
931             freq = CLOCK_GetPllOutFreq();\r
932             break;\r
933         case 2U:\r
934             freq = CLOCK_GetFro12MFreq();\r
935             break;\r
936         case 3U:\r
937             freq = CLOCK_GetFroHfFreq();\r
938             break;\r
939 \r
940         default:\r
941             freq = 0U;\r
942             break;\r
943     }\r
944 \r
945     return freq;\r
946 }\r
947 \r
948 /* Get FRG Clk */\r
949 /*! brief  Return Frequency of frg\r
950  *  return Frequency of FRG\r
951  */\r
952 uint32_t CLOCK_GetFrgClkFreq(void)\r
953 {\r
954     uint32_t freq = 0U;\r
955 \r
956     if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK)\r
957     {\r
958         freq = (uint32_t)(((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /\r
959                           ((SYSCON_FRGCTRL_DIV_MASK + 1U) +\r
960                            ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));\r
961     }\r
962     else\r
963     {\r
964         freq = 0U;\r
965     }\r
966 \r
967     return freq;\r
968 }\r
969 \r
970 /* Get FRG Clk */\r
971 /*! brief  Return Frequency of dmic\r
972  *  return Frequency of DMIC\r
973  */\r
974 uint32_t CLOCK_GetDmicClkFreq(void)\r
975 {\r
976     uint32_t freq = 0U;\r
977 \r
978     switch (SYSCON->DMICCLKSEL)\r
979     {\r
980         case 0U:\r
981             freq = CLOCK_GetFro12MFreq();\r
982             break;\r
983         case 1U:\r
984             freq = CLOCK_GetFroHfFreq();\r
985             break;\r
986         case 2U:\r
987             freq = CLOCK_GetPllOutFreq();\r
988             break;\r
989         case 3U:\r
990             freq = CLOCK_GetI2SMClkFreq();\r
991             break;\r
992         case 4U:\r
993             freq = CLOCK_GetCoreSysClkFreq();\r
994             break;\r
995         case 5U:\r
996             freq = CLOCK_GetWdtOscFreq();\r
997             break;\r
998         default:\r
999             freq = 0U;\r
1000             break;\r
1001     }\r
1002 \r
1003     return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U);\r
1004     ;\r
1005 }\r
1006 \r
1007 /* Set FRG Clk */\r
1008 uint32_t CLOCK_SetFRGClock(uint32_t freq)\r
1009 {\r
1010     assert(0UL != freq);\r
1011 \r
1012     uint32_t input = CLOCK_GetFRGInputClock();\r
1013     uint32_t mul;\r
1014 \r
1015     if ((freq > 48000000U) || (freq > input) || (input / freq >= 2U))\r
1016     {\r
1017         /* FRG output frequency should be less than equal to 48MHz */\r
1018         return 0U;\r
1019     }\r
1020     else\r
1021     {\r
1022         mul             = (uint32_t)((((uint64_t)input - freq) * 256U) / ((uint64_t)freq));\r
1023         SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK;\r
1024         return 1U;\r
1025     }\r
1026 }\r
1027 \r
1028 /* Set IP Clk */\r
1029 /*! brief       Return Frequency of selected clock\r
1030  *  return      Frequency of selected clock\r
1031  */\r
1032 uint32_t CLOCK_GetFreq(clock_name_t clockName)\r
1033 {\r
1034     uint32_t freq;\r
1035     switch (clockName)\r
1036     {\r
1037         case kCLOCK_CoreSysClk:\r
1038             freq = CLOCK_GetCoreSysClkFreq();\r
1039             break;\r
1040         case kCLOCK_BusClk:\r
1041             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);\r
1042             break;\r
1043         case kCLOCK_ClockOut:\r
1044             freq = CLOCK_GetClockOutClkFreq();\r
1045             break;\r
1046         case kCLOCK_Mclk:\r
1047             freq = CLOCK_GetMclkClkFreq();\r
1048             break;\r
1049         case kCLOCK_FroHf:\r
1050             freq = CLOCK_GetFroHfFreq();\r
1051             break;\r
1052         case kCLOCK_Fro12M:\r
1053             freq = CLOCK_GetFro12MFreq();\r
1054             break;\r
1055         case kCLOCK_ExtClk:\r
1056             freq = CLOCK_GetExtClkFreq();\r
1057             break;\r
1058         case kCLOCK_PllOut:\r
1059             freq = CLOCK_GetPllOutFreq();\r
1060             break;\r
1061         case kCLOCK_WdtOsc:\r
1062             freq = CLOCK_GetWdtOscFreq();\r
1063             break;\r
1064         case kCLOCK_Frg:\r
1065             freq = CLOCK_GetFrgClkFreq();\r
1066             break;\r
1067 \r
1068         case kCLOCK_AsyncApbClk:\r
1069             freq = CLOCK_GetAsyncApbClkFreq();\r
1070             break;\r
1071         default:\r
1072             freq = 0U;\r
1073             break;\r
1074     }\r
1075 \r
1076     return freq;\r
1077 }\r
1078 \r
1079 /* Find encoded NDEC value for raw N value, max N = NVALMAX */\r
1080 static uint32_t pllEncodeN(uint32_t N)\r
1081 {\r
1082     uint32_t x, i;\r
1083 \r
1084     /* Find NDec */\r
1085     switch (N)\r
1086     {\r
1087         case 0U:\r
1088             x = 0x3FFU;\r
1089             break;\r
1090 \r
1091         case 1U:\r
1092             x = 0x302U;\r
1093             break;\r
1094 \r
1095         case 2U:\r
1096             x = 0x202U;\r
1097             break;\r
1098 \r
1099         default:\r
1100             x = 0x080U;\r
1101             for (i = N; i <= NVALMAX; i++)\r
1102             {\r
1103                 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);\r
1104             }\r
1105             break;\r
1106     }\r
1107 \r
1108     return x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P);\r
1109 }\r
1110 \r
1111 /* Find decoded N value for raw NDEC value */\r
1112 static uint32_t pllDecodeN(uint32_t NDEC)\r
1113 {\r
1114     uint32_t n, x, i;\r
1115 \r
1116     /* Find NDec */\r
1117     switch (NDEC)\r
1118     {\r
1119         case 0x3FFU:\r
1120             n = 0U;\r
1121             break;\r
1122 \r
1123         case 0x302U:\r
1124             n = 1U;\r
1125             break;\r
1126 \r
1127         case 0x202U:\r
1128             n = 2U;\r
1129             break;\r
1130 \r
1131         default:\r
1132             x = 0x080U;\r
1133             n = 0xFFFFFFFFU;\r
1134             for (i = NVALMAX; i >= 3U; i--)\r
1135             {\r
1136                 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);\r
1137                 if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)\r
1138                 {\r
1139                     /* Decoded value of NDEC */\r
1140                     n = i;\r
1141                     break;\r
1142                 }\r
1143             }\r
1144             break;\r
1145     }\r
1146 \r
1147     return n;\r
1148 }\r
1149 \r
1150 /* Find encoded PDEC value for raw P value, max P = PVALMAX */\r
1151 static uint32_t pllEncodeP(uint32_t P)\r
1152 {\r
1153     uint32_t x, i;\r
1154 \r
1155     /* Find PDec */\r
1156     switch (P)\r
1157     {\r
1158         case 0U:\r
1159             x = 0x7FU;\r
1160             break;\r
1161 \r
1162         case 1U:\r
1163             x = 0x62U;\r
1164             break;\r
1165 \r
1166         case 2U:\r
1167             x = 0x42U;\r
1168             break;\r
1169 \r
1170         default:\r
1171             x = 0x10U;\r
1172             for (i = P; i <= PVALMAX; i++)\r
1173             {\r
1174                 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);\r
1175             }\r
1176             break;\r
1177     }\r
1178 \r
1179     return x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P);\r
1180 }\r
1181 \r
1182 /* Find decoded P value for raw PDEC value */\r
1183 static uint32_t pllDecodeP(uint32_t PDEC)\r
1184 {\r
1185     uint32_t p, x, i;\r
1186 \r
1187     /* Find PDec */\r
1188     switch (PDEC)\r
1189     {\r
1190         case 0x7FU:\r
1191             p = 0U;\r
1192             break;\r
1193 \r
1194         case 0x62U:\r
1195             p = 1U;\r
1196             break;\r
1197 \r
1198         case 0x42U:\r
1199             p = 2U;\r
1200             break;\r
1201 \r
1202         default:\r
1203             x = 0x10U;\r
1204             p = 0xFFFFFFFFU;\r
1205             for (i = PVALMAX; i >= 3U; i--)\r
1206             {\r
1207                 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);\r
1208                 if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC)\r
1209                 {\r
1210                     /* Decoded value of PDEC */\r
1211                     p = i;\r
1212                     break;\r
1213                 }\r
1214             }\r
1215             break;\r
1216     }\r
1217 \r
1218     return p;\r
1219 }\r
1220 \r
1221 /* Find encoded MDEC value for raw M value, max M = MVALMAX */\r
1222 static uint32_t pllEncodeM(uint32_t M)\r
1223 {\r
1224     uint32_t i, x;\r
1225 \r
1226     /* Find MDec */\r
1227     switch (M)\r
1228     {\r
1229         case 0U:\r
1230             x = 0x1FFFFU;\r
1231             break;\r
1232 \r
1233         case 1U:\r
1234             x = 0x18003U;\r
1235             break;\r
1236 \r
1237         case 2U:\r
1238             x = 0x10003U;\r
1239             break;\r
1240 \r
1241         default:\r
1242             x = 0x04000U;\r
1243             for (i = M; i <= MVALMAX; i++)\r
1244             {\r
1245                 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);\r
1246             }\r
1247             break;\r
1248     }\r
1249 \r
1250     return x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P);\r
1251 }\r
1252 \r
1253 /* Find decoded M value for raw MDEC value */\r
1254 static uint32_t pllDecodeM(uint32_t MDEC)\r
1255 {\r
1256     uint32_t m, i, x;\r
1257 \r
1258     /* Find MDec */\r
1259     switch (MDEC)\r
1260     {\r
1261         case 0x1FFFFU:\r
1262             m = 0U;\r
1263             break;\r
1264 \r
1265         case 0x18003U:\r
1266             m = 1U;\r
1267             break;\r
1268 \r
1269         case 0x10003U:\r
1270             m = 2U;\r
1271             break;\r
1272 \r
1273         default:\r
1274             x = 0x04000U;\r
1275             m = 0xFFFFFFFFU;\r
1276             for (i = MVALMAX; i >= 3U; i--)\r
1277             {\r
1278                 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);\r
1279                 if ((x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P)) == MDEC)\r
1280                 {\r
1281                     /* Decoded value of MDEC */\r
1282                     m = i;\r
1283                     break;\r
1284                 }\r
1285             }\r
1286             break;\r
1287     }\r
1288 \r
1289     return m;\r
1290 }\r
1291 \r
1292 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */\r
1293 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)\r
1294 {\r
1295     /* bandwidth: compute selP from Multiplier */\r
1296     if (M < 60U)\r
1297     {\r
1298         *pSelP = (M >> 1U) + 1U;\r
1299     }\r
1300     else\r
1301     {\r
1302         *pSelP = PVALMAX - 1U;\r
1303     }\r
1304 \r
1305     /* bandwidth: compute selI from Multiplier */\r
1306     if (M > 16384U)\r
1307     {\r
1308         *pSelI = 1U;\r
1309     }\r
1310     else if (M > 8192U)\r
1311     {\r
1312         *pSelI = 2U;\r
1313     }\r
1314     else if (M > 2048U)\r
1315     {\r
1316         *pSelI = 4U;\r
1317     }\r
1318     else if (M >= 501U)\r
1319     {\r
1320         *pSelI = 8U;\r
1321     }\r
1322     else if (M >= 60U)\r
1323     {\r
1324         *pSelI = 4U * (1024U / (M + 9U));\r
1325     }\r
1326     else\r
1327     {\r
1328         *pSelI = (M & 0x3CU) + 4U;\r
1329     }\r
1330 \r
1331     if (*pSelI > ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT))\r
1332     {\r
1333         *pSelI = ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT);\r
1334     }\r
1335 \r
1336     *pSelR = 0U;\r
1337 }\r
1338 \r
1339 /* Get predivider (N) from PLL NDEC setting */\r
1340 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)\r
1341 {\r
1342     uint32_t preDiv = 1;\r
1343 \r
1344     /* Direct input is not used? */\r
1345     if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT)) == 0U)\r
1346     {\r
1347         /* Decode NDEC value to get (N) pre divider */\r
1348         preDiv = pllDecodeN(nDecReg & 0x3FFU);\r
1349         if (preDiv == 0U)\r
1350         {\r
1351             preDiv = 1U;\r
1352         }\r
1353     }\r
1354 \r
1355     /* Adjusted by 1, directi is used to bypass */\r
1356     return preDiv;\r
1357 }\r
1358 \r
1359 /* Get postdivider (P) from PLL PDEC setting */\r
1360 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)\r
1361 {\r
1362     uint32_t postDiv = 1U;\r
1363 \r
1364     /* Direct input is not used? */\r
1365     if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U)\r
1366     {\r
1367         /* Decode PDEC value to get (P) post divider */\r
1368         postDiv = 2U * pllDecodeP(pDecReg & 0x7FU);\r
1369         if (postDiv == 0U)\r
1370         {\r
1371             postDiv = 2U;\r
1372         }\r
1373     }\r
1374 \r
1375     /* Adjusted by 1, directo is used to bypass */\r
1376     return postDiv;\r
1377 }\r
1378 \r
1379 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */\r
1380 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)\r
1381 {\r
1382     uint32_t mMult = 1U;\r
1383 \r
1384     /* Decode MDEC value to get (M) multiplier */\r
1385     mMult = pllDecodeM(mDecReg & 0x1FFFFU);\r
1386 \r
1387     if (mMult == 0U)\r
1388     {\r
1389         mMult = 1U;\r
1390     }\r
1391 \r
1392     return mMult;\r
1393 }\r
1394 \r
1395 /* Calculate the powerTimes' power of 2 */\r
1396 static uint32_t power2Cal(uint32_t powerTimes)\r
1397 {\r
1398     uint32_t ret = 1U;\r
1399     uint32_t i;\r
1400     for (i = 0; i < powerTimes; i++)\r
1401     {\r
1402         ret *= 2U;\r
1403     }\r
1404 \r
1405     return ret;\r
1406 }\r
1407 \r
1408 /* Convert the binary to fractional part */\r
1409 static double Binary2Fractional(uint32_t binaryPart)\r
1410 {\r
1411     double fractional = 0.0;\r
1412     for (uint32_t i = 0U; i <= 14U; i++)\r
1413     {\r
1414         fractional += (double)(uint32_t)((binaryPart >> i) & 0x1U) / (double)(uint32_t)power2Cal(15U - i);\r
1415     }\r
1416     return fractional;\r
1417 }\r
1418 \r
1419 /* Find greatest common divisor between m and n */\r
1420 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)\r
1421 {\r
1422     uint32_t tmp;\r
1423 \r
1424     while (n != 0U)\r
1425     {\r
1426         tmp = n;\r
1427         n   = m % n;\r
1428         m   = tmp;\r
1429     }\r
1430 \r
1431     return m;\r
1432 }\r
1433 \r
1434 /*\r
1435  * Set PLL output based on desired output rate.\r
1436  * In this function, the it calculates the PLL setting for output frequency from input clock\r
1437  * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.\r
1438  * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.\r
1439  */\r
1440 static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)\r
1441 {\r
1442     uint32_t nDivOutHz, fccoHz, multFccoDiv;\r
1443     uint32_t pllPreDivider, pllMultiplier, pllPostDivider;\r
1444     uint32_t pllDirectInput, pllDirectOutput;\r
1445     uint32_t pllSelP, pllSelI, pllSelR, uplimoff;\r
1446 \r
1447     /* Baseline parameters (no input or output dividers) */\r
1448     pllPreDivider   = 1U; /* 1 implies pre-divider will be disabled */\r
1449     pllPostDivider  = 0U; /* 0 implies post-divider will be disabled */\r
1450     pllDirectOutput = 1U;\r
1451     multFccoDiv     = 2U;\r
1452 \r
1453     /* Verify output rate parameter */\r
1454     if (foutHz > PLL_MAX_CCO_FREQ_MHZ)\r
1455     {\r
1456         /* Maximum PLL output with post divider=1 cannot go above this frequency */\r
1457         return kStatus_PLL_OutputTooHigh;\r
1458     }\r
1459     if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))\r
1460     {\r
1461         /* Minmum PLL output with maximum post divider cannot go below this frequency */\r
1462         return kStatus_PLL_OutputTooLow;\r
1463     }\r
1464 \r
1465     /* Verify input rate parameter */\r
1466     if (finHz < PLL_LOWER_IN_LIMIT)\r
1467     {\r
1468         /* Input clock into the PLL cannot be lower than this */\r
1469         return kStatus_PLL_InputTooLow;\r
1470     }\r
1471 \r
1472     /* Find the optimal CCO frequency for the output and input that\r
1473        will keep it inside the PLL CCO range. This may require\r
1474        tweaking the post-divider for the PLL. */\r
1475     fccoHz = foutHz;\r
1476     while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)\r
1477     {\r
1478         /* CCO output is less than minimum CCO range, so the CCO output\r
1479            needs to be bumped up and the post-divider is used to bring\r
1480            the PLL output back down. */\r
1481         pllPostDivider++;\r
1482         if (pllPostDivider > PVALMAX)\r
1483         {\r
1484             return kStatus_PLL_OutsideIntLimit;\r
1485         }\r
1486 \r
1487         /* Target CCO goes up, PLL output goes down */\r
1488         fccoHz          = foutHz * (pllPostDivider * 2U);\r
1489         pllDirectOutput = 0U;\r
1490     }\r
1491 \r
1492     /* Determine if a pre-divider is needed to get the best frequency */\r
1493     if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz))\r
1494     {\r
1495         uint32_t a = FindGreatestCommonDivisor(fccoHz, (multFccoDiv * finHz));\r
1496 \r
1497         if (a > 20000U)\r
1498         {\r
1499             a = (multFccoDiv * finHz) / a;\r
1500             if ((a != 0U) && (a < PLL_MAX_N_DIV))\r
1501             {\r
1502                 pllPreDivider = a;\r
1503             }\r
1504         }\r
1505     }\r
1506 \r
1507     /* Bypass pre-divider hardware if pre-divider is 1 */\r
1508     if (pllPreDivider > 1U)\r
1509     {\r
1510         pllDirectInput = 0U;\r
1511     }\r
1512     else\r
1513     {\r
1514         pllDirectInput = 1U;\r
1515     }\r
1516 \r
1517     /* Determine PLL multipler */\r
1518     nDivOutHz     = (finHz / pllPreDivider);\r
1519     pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv;\r
1520 \r
1521     /* Find optimal values for filter */\r
1522     /* Will bumping up M by 1 get us closer to the desired CCO frequency? */\r
1523     if ((nDivOutHz * ((multFccoDiv * pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))\r
1524     {\r
1525         pllMultiplier++;\r
1526     }\r
1527 \r
1528     /* Setup filtering */\r
1529     pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);\r
1530     uplimoff = 0U;\r
1531 \r
1532     /* Get encoded value for M (mult) and use manual filter, disable SS mode */\r
1533     pSetup->pllmdec = PLL_MDEC_VAL_SET(pllEncodeM(pllMultiplier));\r
1534 \r
1535     /* Get encoded values for N (prediv) and P (postdiv) */\r
1536     pSetup->pllndec = PLL_NDEC_VAL_SET(pllEncodeN(pllPreDivider));\r
1537     pSetup->pllpdec = PLL_PDEC_VAL_SET(pllEncodeP(pllPostDivider));\r
1538 \r
1539     /* PLL control */\r
1540     pSetup->pllctrl = (pllSelR << SYSCON_SYSPLLCTRL_SELR_SHIFT) |           /* Filter coefficient */\r
1541                       (pllSelI << SYSCON_SYSPLLCTRL_SELI_SHIFT) |           /* Filter coefficient */\r
1542                       (pllSelP << SYSCON_SYSPLLCTRL_SELP_SHIFT) |           /* Filter coefficient */\r
1543                       (0UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT) |             /* PLL bypass mode disabled */\r
1544                       (uplimoff << SYSCON_SYSPLLCTRL_UPLIMOFF_SHIFT) |      /* SS/fractional mode disabled */\r
1545                       (pllDirectInput << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT) | /* Bypass pre-divider? */\r
1546                       (pllDirectOutput << SYSCON_SYSPLLCTRL_DIRECTO_SHIFT); /* Bypass post-divider? */\r
1547 \r
1548     return kStatus_PLL_Success;\r
1549 }\r
1550 \r
1551 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)\r
1552 /* Alloct the static buffer for cache. */\r
1553 static pll_setup_t gPllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];\r
1554 static uint32_t gFinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]  = {0};\r
1555 static uint32_t gFoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};\r
1556 static uint32_t gPllSetupCacheIdx                                  = 0U;\r
1557 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */\r
1558 \r
1559 /*\r
1560  * Calculate the PLL setting values from input clock freq to output freq.\r
1561  */\r
1562 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)\r
1563 {\r
1564     pll_error_t retErr;\r
1565 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)\r
1566     uint32_t i;\r
1567 \r
1568     for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)\r
1569     {\r
1570         if ((finHz == gFinHzCache[i]) && (foutHz == gFoutHzCache[i]))\r
1571         {\r
1572             /* Hit the target in cache buffer. */\r
1573             pSetup->pllctrl = gPllSetupCacheStruct[i].pllctrl;\r
1574             pSetup->pllndec = gPllSetupCacheStruct[i].pllndec;\r
1575             pSetup->pllpdec = gPllSetupCacheStruct[i].pllpdec;\r
1576             pSetup->pllmdec = gPllSetupCacheStruct[i].pllmdec;\r
1577             retErr          = kStatus_PLL_Success;\r
1578             break;\r
1579         }\r
1580     }\r
1581 \r
1582     if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)\r
1583     {\r
1584         return retErr;\r
1585     }\r
1586 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */\r
1587 \r
1588     /* No cache or did not hit the cache. */\r
1589     retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup);\r
1590 \r
1591 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)\r
1592     if (kStatus_PLL_Success == retErr)\r
1593     {\r
1594         /* Cache the most recent calulation result into buffer. */\r
1595         gFinHzCache[gPllSetupCacheIdx]  = finHz;\r
1596         gFoutHzCache[gPllSetupCacheIdx] = foutHz;\r
1597 \r
1598         gPllSetupCacheStruct[gPllSetupCacheIdx].pllctrl = pSetup->pllctrl;\r
1599         gPllSetupCacheStruct[gPllSetupCacheIdx].pllndec = pSetup->pllndec;\r
1600         gPllSetupCacheStruct[gPllSetupCacheIdx].pllpdec = pSetup->pllpdec;\r
1601         gPllSetupCacheStruct[gPllSetupCacheIdx].pllmdec = pSetup->pllmdec;\r
1602         /* Update the index for next available buffer. */\r
1603         gPllSetupCacheIdx = (gPllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;\r
1604     }\r
1605 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */\r
1606 \r
1607     return retErr;\r
1608 }\r
1609 \r
1610 /* Update SYSTEM PLL rate variable */\r
1611 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup)\r
1612 {\r
1613     s_Pll_Freq = CLOCK_GetSystemPLLOutFromSetup(pSetup);\r
1614 }\r
1615 \r
1616 /* Update AUDIO PLL rate variable */\r
1617 static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup)\r
1618 {\r
1619     s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromSetup(pSetup);\r
1620 }\r
1621 \r
1622 /* Update AUDIO Fractional PLL rate variable */\r
1623 static void CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t *pSetup)\r
1624 {\r
1625     s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromFractSetup(pSetup);\r
1626 }\r
1627 \r
1628 /* Update USB PLL rate variable */\r
1629 static void CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t *pSetup)\r
1630 {\r
1631     s_Usb_Pll_Freq = CLOCK_GetUsbPLLOutFromSetup(pSetup);\r
1632 }\r
1633 \r
1634 /* Return System PLL input clock rate */\r
1635 /*! brief       Return System PLL input clock rate\r
1636  *  return      System PLL input clock rate\r
1637  */\r
1638 uint32_t CLOCK_GetSystemPLLInClockRate(void)\r
1639 {\r
1640     uint32_t clkRate = 0U;\r
1641 \r
1642     switch ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK))\r
1643     {\r
1644         case 0x00U:\r
1645             clkRate = CLK_FRO_12MHZ;\r
1646             break;\r
1647 \r
1648         case 0x01U:\r
1649             clkRate = CLOCK_GetExtClkFreq();\r
1650             break;\r
1651 \r
1652         case 0x02U:\r
1653             clkRate = CLOCK_GetWdtOscFreq();\r
1654             break;\r
1655 \r
1656         case 0x03U:\r
1657             clkRate = CLOCK_GetOsc32KFreq();\r
1658             break;\r
1659 \r
1660         default:\r
1661             clkRate = 0U;\r
1662             break;\r
1663     }\r
1664 \r
1665     return clkRate;\r
1666 }\r
1667 \r
1668 /* Return Audio PLL input clock rate */\r
1669 /*! brief       Return Audio PLL input clock rate\r
1670  *  return      Audio PLL input clock rate\r
1671  */\r
1672 uint32_t CLOCK_GetAudioPLLInClockRate(void)\r
1673 {\r
1674     uint32_t clkRate = 0U;\r
1675 \r
1676     switch ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK))\r
1677     {\r
1678         case 0x00U:\r
1679             clkRate = CLK_FRO_12MHZ;\r
1680             break;\r
1681 \r
1682         case 0x01U:\r
1683             clkRate = CLOCK_GetExtClkFreq();\r
1684             break;\r
1685 \r
1686         default:\r
1687             clkRate = 0U;\r
1688             break;\r
1689     }\r
1690 \r
1691     return clkRate;\r
1692 }\r
1693 \r
1694 /* Return System PLL output clock rate from setup structure */\r
1695 /*! brief       Return System PLL output clock rate from setup structure\r
1696  *  param       pSetup  : Pointer to a PLL setup structure\r
1697  *  return      System PLL output clock rate the setup structure will generate\r
1698  */\r
1699 uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup)\r
1700 {\r
1701     uint32_t prediv, postdiv, mMult, inPllRate;\r
1702     uint64_t workRate;\r
1703 \r
1704     inPllRate = CLOCK_GetSystemPLLInClockRate();\r
1705     /* If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock*/\r
1706     if ((pSetup->pllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U)\r
1707     {\r
1708         /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */\r
1709         /*\r
1710          * 1. Pre-divider\r
1711          * Pre-divider is only available when the DIRECTI is disabled.\r
1712          */\r
1713         if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK))\r
1714         {\r
1715             prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);\r
1716         }\r
1717         else\r
1718         {\r
1719             prediv = 1U; /* The pre-divider is bypassed. */\r
1720         }\r
1721         /*\r
1722          * 2. Post-divider\r
1723          * Post-divider is only available when the DIRECTO is disabled.\r
1724          */\r
1725         if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK))\r
1726         {\r
1727             postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);\r
1728         }\r
1729         else\r
1730         {\r
1731             postdiv = 1U; /* The post-divider is bypassed. */\r
1732         }\r
1733         /* Adjust input clock */\r
1734         inPllRate = inPllRate / prediv;\r
1735 \r
1736         /* MDEC used for rate */\r
1737         mMult    = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);\r
1738         workRate = (uint64_t)inPllRate * (uint64_t)mMult;\r
1739 \r
1740         workRate = workRate / ((uint64_t)postdiv);\r
1741         workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/\r
1742     }\r
1743     else\r
1744     {\r
1745         /* In bypass mode */\r
1746         workRate = (uint64_t)inPllRate;\r
1747     }\r
1748 \r
1749     return (uint32_t)workRate;\r
1750 }\r
1751 \r
1752 /* Return Usb PLL output clock rate from setup structure */\r
1753 /*! brief       Return System USB PLL output clock rate from setup structure\r
1754  *  param       pSetup  : Pointer to a PLL setup structure\r
1755  *  return      System PLL output clock rate the setup structure will generate\r
1756  */\r
1757 uint32_t CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t *pSetup)\r
1758 {\r
1759     uint32_t nsel, psel, msel, inPllRate;\r
1760     uint64_t workRate;\r
1761     inPllRate = CLOCK_GetExtClkFreq();\r
1762     msel      = pSetup->msel;\r
1763     psel      = pSetup->psel;\r
1764     nsel      = pSetup->nsel;\r
1765 \r
1766     /* Make sure the PSEL is correct. */\r
1767     if (0U == SWITCH_USB_PSEL(psel))\r
1768     {\r
1769         return 0UL;\r
1770     }\r
1771 \r
1772     if (pSetup->fbsel)\r
1773     {\r
1774         /*integer_mode: Fout = M*(Fin/N),  Fcco = 2*P*M*(Fin/N) */\r
1775         workRate = ((uint64_t)inPllRate) * ((uint64_t)msel + 1U) / ((uint64_t)nsel + 1U);\r
1776     }\r
1777     else\r
1778     {\r
1779         /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */\r
1780         workRate = ((uint64_t)inPllRate / ((uint64_t)nsel + 1U)) * (msel + 1U) / (2U * SWITCH_USB_PSEL(psel));\r
1781     }\r
1782 \r
1783     return (uint32_t)workRate;\r
1784 }\r
1785 \r
1786 /* Return Audio PLL output clock rate from setup structure */\r
1787 /*! brief       Return System AUDIO PLL output clock rate from setup structure\r
1788  *  param       pSetup  : Pointer to a PLL setup structure\r
1789  *  return      System PLL output clock rate the setup structure will generate\r
1790  */\r
1791 uint32_t CLOCK_GetAudioPLLOutFromSetup(pll_setup_t *pSetup)\r
1792 {\r
1793     uint32_t prediv, postdiv, mMult, inPllRate;\r
1794     uint64_t workRate;\r
1795 \r
1796     inPllRate = CLOCK_GetAudioPLLInClockRate();\r
1797     if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)\r
1798     {\r
1799         /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */\r
1800         /*\r
1801          * 1. Pre-divider\r
1802          * Pre-divider is only available when the DIRECTI is disabled.\r
1803          */\r
1804         if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))\r
1805         {\r
1806             prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);\r
1807         }\r
1808         else\r
1809         {\r
1810             prediv = 1U; /* The pre-divider is bypassed. */\r
1811         }\r
1812         /*\r
1813          * 2. Post-divider\r
1814          * Post-divider is only available when the DIRECTO is disabled.\r
1815          */\r
1816         if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))\r
1817         {\r
1818             postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);\r
1819         }\r
1820         else\r
1821         {\r
1822             postdiv = 1U; /* The post-divider is bypassed. */\r
1823         }\r
1824         /* Adjust input clock */\r
1825         inPllRate = inPllRate / prediv;\r
1826 \r
1827         /* MDEC used for rate */\r
1828         mMult    = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);\r
1829         workRate = (uint64_t)inPllRate * (uint64_t)mMult;\r
1830 \r
1831         workRate = workRate / ((uint64_t)postdiv);\r
1832         workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/\r
1833     }\r
1834     else\r
1835     {\r
1836         /* In bypass mode */\r
1837         workRate = (uint64_t)inPllRate;\r
1838     }\r
1839 \r
1840     return (uint32_t)workRate;\r
1841 }\r
1842 \r
1843 /* Return Audio PLL output clock rate from audio fractioanl setup structure */\r
1844 /*! brief       Return System AUDIO PLL output clock rate from audio fractioanl setup structure\r
1845  *  param       pSetup  : Pointer to a PLL setup structure\r
1846  *  return      System PLL output clock rate the setup structure will generate\r
1847  */\r
1848 uint32_t CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t *pSetup)\r
1849 {\r
1850     uint32_t prediv, postdiv, inPllRate;\r
1851     double workRate, mMultFactional;\r
1852 \r
1853     inPllRate = CLOCK_GetAudioPLLInClockRate();\r
1854     if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)\r
1855     {\r
1856         /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */\r
1857         /*\r
1858          * 1. Pre-divider\r
1859          * Pre-divider is only available when the DIRECTI is disabled.\r
1860          */\r
1861         if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))\r
1862         {\r
1863             prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);\r
1864         }\r
1865         else\r
1866         {\r
1867             prediv = 1U; /* The pre-divider is bypassed. */\r
1868         }\r
1869         /*\r
1870          * 2. Post-divider\r
1871          * Post-divider is only available when the DIRECTO is disabled.\r
1872          */\r
1873         if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))\r
1874         {\r
1875             postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);\r
1876         }\r
1877         else\r
1878         {\r
1879             postdiv = 1U; /* The post-divider is bypassed. */\r
1880         }\r
1881         /* Adjust input clock */\r
1882         inPllRate = inPllRate / prediv;\r
1883 \r
1884         mMultFactional = (double)(uint32_t)(pSetup->audpllfrac >> 15) +\r
1885                          (double)(uint32_t)Binary2Fractional(pSetup->audpllfrac & 0x7FFFU);\r
1886         workRate = (double)inPllRate * (double)mMultFactional;\r
1887 \r
1888         workRate = workRate / ((double)postdiv);\r
1889         workRate = workRate * 2.0; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/\r
1890     }\r
1891     else\r
1892     {\r
1893         /* In bypass mode */\r
1894         workRate = (double)(uint64_t)inPllRate;\r
1895     }\r
1896 \r
1897     return (uint32_t)workRate;\r
1898 }\r
1899 \r
1900 /* Set the current PLL Rate */\r
1901 /*! brief Store the current PLL rate\r
1902  *  param       rate: Current rate of the PLL\r
1903  *  return      Nothing\r
1904  **/\r
1905 void CLOCK_SetStoredPLLClockRate(uint32_t rate)\r
1906 {\r
1907     s_Pll_Freq = rate;\r
1908 }\r
1909 \r
1910 /* Set the current Audio PLL Rate */\r
1911 /*! brief Store the current AUDIO PLL rate\r
1912  *  param       rate: Current rate of the PLL\r
1913  *  return      Nothing\r
1914  **/\r
1915 void CLOCK_SetStoredAudioPLLClockRate(uint32_t rate)\r
1916 {\r
1917     s_Audio_Pll_Freq = rate;\r
1918 }\r
1919 \r
1920 /* Set the current Usb PLL Rate */\r
1921 void CLOCK_SetStoredUsbPLLClockRate(uint32_t rate)\r
1922 {\r
1923     s_Usb_Pll_Freq = rate;\r
1924 }\r
1925 \r
1926 /* Return System PLL output clock rate */\r
1927 /*! brief       Return System PLL output clock rate\r
1928  *  param       recompute       : Forces a PLL rate recomputation if true\r
1929  *  return      System PLL output clock rate\r
1930  *  note        The PLL rate is cached in the driver in a variable as\r
1931  *  the rate computation function can take some time to perform. It\r
1932  *  is recommended to use 'false' with the 'recompute' parameter.\r
1933  */\r
1934 uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute)\r
1935 {\r
1936     pll_setup_t Setup;\r
1937     uint32_t rate;\r
1938 \r
1939     if ((recompute) || (s_Pll_Freq == 0U))\r
1940     {\r
1941         Setup.pllctrl = SYSCON->SYSPLLCTRL;\r
1942         Setup.pllndec = SYSCON->SYSPLLNDEC;\r
1943         Setup.pllpdec = SYSCON->SYSPLLPDEC;\r
1944         Setup.pllmdec = SYSCON->SYSPLLMDEC;\r
1945 \r
1946         CLOCK_GetSystemPLLOutFromSetupUpdate(&Setup);\r
1947     }\r
1948 \r
1949     rate = s_Pll_Freq;\r
1950 \r
1951     return rate;\r
1952 }\r
1953 \r
1954 /* Return AUDIO PLL output clock rate */\r
1955 /*! brief       Return System AUDIO PLL output clock rate\r
1956  *  param       recompute       : Forces a AUDIO PLL rate recomputation if true\r
1957  *  return      System AUDIO PLL output clock rate\r
1958  *  note        The AUDIO PLL rate is cached in the driver in a variable as\r
1959  *  the rate computation function can take some time to perform. It\r
1960  *  is recommended to use 'false' with the 'recompute' parameter.\r
1961  */\r
1962 uint32_t CLOCK_GetAudioPLLOutClockRate(bool recompute)\r
1963 {\r
1964     pll_setup_t Setup;\r
1965     uint32_t rate;\r
1966 \r
1967     if ((recompute) || (s_Audio_Pll_Freq == 0U))\r
1968     {\r
1969         Setup.pllctrl = SYSCON->AUDPLLCTRL;\r
1970         Setup.pllndec = SYSCON->AUDPLLNDEC;\r
1971         Setup.pllpdec = SYSCON->AUDPLLPDEC;\r
1972         Setup.pllmdec = SYSCON->AUDPLLMDEC;\r
1973 \r
1974         CLOCK_GetAudioPLLOutFromSetupUpdate(&Setup);\r
1975     }\r
1976 \r
1977     rate = s_Audio_Pll_Freq;\r
1978     return rate;\r
1979 }\r
1980 \r
1981 /* Return USB PLL output clock rate */\r
1982 uint32_t CLOCK_GetUsbPLLOutClockRate(bool recompute)\r
1983 {\r
1984     usb_pll_setup_t Setup;\r
1985     uint32_t rate;\r
1986 \r
1987     if ((recompute) || (s_Usb_Pll_Freq == 0U))\r
1988     {\r
1989         Setup.msel  = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_MSEL_SHIFT) & SYSCON_USBPLLCTRL_MSEL_MASK);\r
1990         Setup.psel  = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_PSEL_SHIFT) & SYSCON_USBPLLCTRL_PSEL_MASK);\r
1991         Setup.nsel  = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_NSEL_SHIFT) & SYSCON_USBPLLCTRL_NSEL_MASK);\r
1992         Setup.fbsel = (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_FBSEL_SHIFT) & SYSCON_USBPLLCTRL_FBSEL_MASK) != 0UL);\r
1993         Setup.bypass =\r
1994             (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_BYPASS_SHIFT) & SYSCON_USBPLLCTRL_BYPASS_MASK) != 0UL);\r
1995         Setup.direct =\r
1996             (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_DIRECT_SHIFT) & SYSCON_USBPLLCTRL_DIRECT_MASK) != 0UL);\r
1997         CLOCK_GetUsbPLLOutFromSetupUpdate(&Setup);\r
1998     }\r
1999 \r
2000     rate = s_Usb_Pll_Freq;\r
2001     return rate;\r
2002 }\r
2003 \r
2004 /* Set PLL output based on the passed PLL setup data */\r
2005 /*! brief       Set PLL output based on the passed PLL setup data\r
2006  *  param       pControl        : Pointer to populated PLL control structure to generate setup with\r
2007  *  param       pSetup          : Pointer to PLL setup structure to be filled\r
2008  *  return      PLL_ERROR_SUCCESS on success, or PLL setup error code\r
2009  *  note        Actual frequency for setup may vary from the desired frequency based on the\r
2010  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.\r
2011  */\r
2012 pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup)\r
2013 {\r
2014     uint32_t inRate;\r
2015     pll_error_t pllError;\r
2016 \r
2017     /* Determine input rate for the PLL */\r
2018     if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)\r
2019     {\r
2020         inRate = pControl->inputRate;\r
2021     }\r
2022     else\r
2023     {\r
2024         inRate = CLOCK_GetSystemPLLInClockRate();\r
2025     }\r
2026 \r
2027     /* PLL flag options */\r
2028     pllError        = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup);\r
2029     pSetup->pllRate = pControl->desiredRate;\r
2030     return pllError;\r
2031 }\r
2032 \r
2033 /* Set PLL output from PLL setup structure */\r
2034 /*! brief       Set PLL output from PLL setup structure (precise frequency)\r
2035  * param        pSetup  : Pointer to populated PLL setup structure\r
2036  * param flagcfg : Flag configuration for PLL config structure\r
2037  * return       PLL_ERROR_SUCCESS on success, or PLL setup error code\r
2038  * note This function will power off the PLL, setup the PLL with the\r
2039  * new setup data, and then optionally powerup the PLL, wait for PLL lock,\r
2040  * and adjust system voltages to the new PLL rate. The function will not\r
2041  * alter any source clocks (ie, main systen clock) that may use the PLL,\r
2042  * so these should be setup prior to and after exiting the function.\r
2043  */\r
2044 pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)\r
2045 {\r
2046     if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U)\r
2047     {\r
2048         /* Turn on the ext clock if system pll input select clk_in */\r
2049         CLOCK_Enable_SysOsc(true);\r
2050     }\r
2051     /* Enable power for PLLs */\r
2052     POWER_SetPLL();\r
2053     /* Power off PLL during setup changes */\r
2054     POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);\r
2055 \r
2056     pSetup->flags = flagcfg;\r
2057 \r
2058     /* Write PLL setup data */\r
2059     SYSCON->SYSPLLCTRL = pSetup->pllctrl;\r
2060     SYSCON->SYSPLLNDEC = pSetup->pllndec;\r
2061     SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */\r
2062     SYSCON->SYSPLLPDEC = pSetup->pllpdec;\r
2063     SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */\r
2064     SYSCON->SYSPLLMDEC = pSetup->pllmdec;\r
2065     SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */\r
2066 \r
2067     /* Flags for lock or power on */\r
2068     if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)\r
2069     {\r
2070         /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */\r
2071         uint32_t maxCCO    = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/\r
2072         uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);\r
2073 \r
2074         /* Initialize  and power up PLL */\r
2075         SYSCON->SYSPLLMDEC = maxCCO;\r
2076         POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);\r
2077 \r
2078         /* Set mreq to activate */\r
2079         SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);\r
2080 \r
2081         /* Delay for 72 uSec @ 12Mhz */\r
2082         SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2083 \r
2084         /* clear mreq to prepare for restoring mreq */\r
2085         SYSCON->SYSPLLMDEC = curSSCTRL;\r
2086 \r
2087         /* set original value back and activate */\r
2088         SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);\r
2089 \r
2090         /* Enable peripheral states by setting low */\r
2091         POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);\r
2092     }\r
2093     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
2094     {\r
2095         while (CLOCK_IsSystemPLLLocked() == false)\r
2096         {\r
2097         }\r
2098     }\r
2099 \r
2100     /* Update current programmed PLL rate var */\r
2101     CLOCK_GetSystemPLLOutFromSetupUpdate(pSetup);\r
2102 \r
2103     /* System voltage adjustment, occurs prior to setting main system clock */\r
2104     if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0U)\r
2105     {\r
2106         POWER_SetVoltageForFreq(s_Pll_Freq);\r
2107     }\r
2108 \r
2109     return kStatus_PLL_Success;\r
2110 }\r
2111 \r
2112 /* Set AUDIO PLL output from AUDIO PLL setup structure */\r
2113 /*! brief       Set AUDIO PLL output from AUDIOPLL setup structure (precise frequency)\r
2114  * param        pSetup  : Pointer to populated PLL setup structure\r
2115  * param flagcfg : Flag configuration for PLL config structure\r
2116  * return       PLL_ERROR_SUCCESS on success, or PLL setup error code\r
2117  * note This function will power off the PLL, setup the PLL with the\r
2118  * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock,\r
2119  * and adjust system voltages to the new AUDIOPLL rate. The function will not\r
2120  * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL,\r
2121  * so these should be setup prior to and after exiting the function.\r
2122  */\r
2123 pll_error_t CLOCK_SetupAudioPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)\r
2124 {\r
2125     if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)\r
2126     {\r
2127         /* Turn on the ext clock if system pll input select clk_in */\r
2128         CLOCK_Enable_SysOsc(true);\r
2129     }\r
2130     /* Enable power VD3 for PLLs */\r
2131     POWER_SetPLL();\r
2132     /* Power off PLL during setup changes */\r
2133     POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
2134 \r
2135     pSetup->flags = flagcfg;\r
2136 \r
2137     /* Write PLL setup data */\r
2138     SYSCON->AUDPLLCTRL = pSetup->pllctrl;\r
2139     SYSCON->AUDPLLNDEC = pSetup->pllndec;\r
2140     SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */\r
2141     SYSCON->AUDPLLPDEC = pSetup->pllpdec;\r
2142     SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */\r
2143     SYSCON->AUDPLLMDEC = pSetup->pllmdec;\r
2144     SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */\r
2145     SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1);                            /* disable fractional function */\r
2146 \r
2147     /* Flags for lock or power on */\r
2148     if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)\r
2149     {\r
2150         /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */\r
2151         uint32_t maxCCO    = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/\r
2152         uint32_t curSSCTRL = SYSCON->AUDPLLMDEC & ~(1UL << 17U);\r
2153 \r
2154         /* Initialize  and power up PLL */\r
2155         SYSCON->AUDPLLMDEC = maxCCO;\r
2156         POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
2157 \r
2158         /* Set mreq to activate */\r
2159         SYSCON->AUDPLLMDEC = maxCCO | (1UL << 17U);\r
2160 \r
2161         /* Delay for 72 uSec @ 12Mhz */\r
2162         SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2163 \r
2164         /* clear mreq to prepare for restoring mreq */\r
2165         SYSCON->AUDPLLMDEC = curSSCTRL;\r
2166 \r
2167         /* set original value back and activate */\r
2168         SYSCON->AUDPLLMDEC = curSSCTRL | (1UL << 17U);\r
2169 \r
2170         /* Enable peripheral states by setting low */\r
2171         POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
2172     }\r
2173     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
2174     {\r
2175         while (CLOCK_IsAudioPLLLocked() == false)\r
2176         {\r
2177         }\r
2178     }\r
2179 \r
2180     /* Update current programmed PLL rate var */\r
2181     CLOCK_GetAudioPLLOutFromSetupUpdate(pSetup);\r
2182 \r
2183     return kStatus_PLL_Success;\r
2184 }\r
2185 \r
2186 /* Set AUDIO PLL output from AUDIO PLL fractional setup structure */\r
2187 /*! brief       Set AUDIO PLL output from AUDIOPLL setup structure using the Audio Fractional divider register(precise\r
2188  * frequency)\r
2189  * param        pSetup  : Pointer to populated PLL setup structure\r
2190  * param flagcfg : Flag configuration for PLL config structure\r
2191  * return       PLL_ERROR_SUCCESS on success, or PLL setup error code\r
2192  * note This function will power off the PLL, setup the PLL with the\r
2193  * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock,\r
2194  * and adjust system voltages to the new AUDIOPLL rate. The function will not\r
2195  * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL,\r
2196  * so these should be setup prior to and after exiting the function.\r
2197  */\r
2198 pll_error_t CLOCK_SetupAudioPLLPrecFract(pll_setup_t *pSetup, uint32_t flagcfg)\r
2199 {\r
2200     if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)\r
2201     {\r
2202         /* Turn on the ext clock if system pll input select clk_in */\r
2203         CLOCK_Enable_SysOsc(true);\r
2204     }\r
2205     /* Enable power VD3 for PLLs */\r
2206     POWER_SetPLL();\r
2207     /* Power off PLL during setup changes */\r
2208     POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
2209 \r
2210     pSetup->flags = flagcfg;\r
2211 \r
2212     /* Write PLL setup data */\r
2213     SYSCON->AUDPLLCTRL = pSetup->pllctrl;\r
2214     SYSCON->AUDPLLNDEC = pSetup->pllndec;\r
2215     SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */\r
2216     SYSCON->AUDPLLPDEC = pSetup->pllpdec;\r
2217     SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */\r
2218     SYSCON->AUDPLLMDEC = pSetup->pllmdec;\r
2219     SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(0); /* enable fractional function */\r
2220     SYSCON->AUDPLLFRAC = pSetup->audpllfrac;\r
2221     SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT);\r
2222 \r
2223     /* Enable peripheral states by setting low */\r
2224     POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
2225 \r
2226     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
2227     {\r
2228         while (CLOCK_IsAudioPLLLocked() == false)\r
2229         {\r
2230         }\r
2231     }\r
2232 \r
2233     /* Update current programmed PLL rate var */\r
2234     CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pSetup);\r
2235 \r
2236     return kStatus_PLL_Success;\r
2237 }\r
2238 \r
2239 /* Set Audio PLL output based on the passed Audio PLL setup data */\r
2240 /*! brief       Set AUDIO PLL output based on the passed AUDIO PLL setup data\r
2241  *  param       pControl        : Pointer to populated PLL control structure to generate setup with\r
2242  *  param       pSetup          : Pointer to PLL setup structure to be filled\r
2243  *  return      PLL_ERROR_SUCCESS on success, or PLL setup error code\r
2244  *  note        Actual frequency for setup may vary from the desired frequency based on the\r
2245  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.\r
2246  */\r
2247 pll_error_t CLOCK_SetupAudioPLLData(pll_config_t *pControl, pll_setup_t *pSetup)\r
2248 {\r
2249     uint32_t inRate;\r
2250     pll_error_t pllError;\r
2251 \r
2252     /* Determine input rate for the PLL */\r
2253     if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)\r
2254     {\r
2255         inRate = pControl->inputRate;\r
2256     }\r
2257     else\r
2258     {\r
2259         inRate = CLOCK_GetAudioPLLInClockRate();\r
2260     }\r
2261 \r
2262     /* PLL flag options */\r
2263     pllError        = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup);\r
2264     pSetup->pllRate = pControl->desiredRate;\r
2265     return pllError;\r
2266 }\r
2267 \r
2268 /* Setup PLL Frequency from pre-calculated value */\r
2269 /**\r
2270  * brief        Set PLL output from PLL setup structure (precise frequency)\r
2271  * param        pSetup  : Pointer to populated PLL setup structure\r
2272  * return       kStatus_PLL_Success on success, or PLL setup error code\r
2273  * note This function will power off the PLL, setup the PLL with the\r
2274  * new setup data, and then optionally powerup the PLL, wait for PLL lock,\r
2275  * and adjust system voltages to the new PLL rate. The function will not\r
2276  * alter any source clocks (ie, main systen clock) that may use the PLL,\r
2277  * so these should be setup prior to and after exiting the function.\r
2278  */\r
2279 pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup)\r
2280 {\r
2281     if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U)\r
2282     {\r
2283         /* Turn on the ext clock if system pll input select clk_in */\r
2284         CLOCK_Enable_SysOsc(true);\r
2285     }\r
2286     /* Enable power VD3 for PLLs */\r
2287     POWER_SetPLL();\r
2288     /* Power off PLL during setup changes */\r
2289     POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);\r
2290 \r
2291     /* Write PLL setup data */\r
2292     SYSCON->SYSPLLCTRL = pSetup->pllctrl;\r
2293     SYSCON->SYSPLLNDEC = pSetup->pllndec;\r
2294     SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */\r
2295     SYSCON->SYSPLLPDEC = pSetup->pllpdec;\r
2296     SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */\r
2297     SYSCON->SYSPLLMDEC = pSetup->pllmdec;\r
2298     SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */\r
2299 \r
2300     /* Flags for lock or power on */\r
2301     if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)\r
2302     {\r
2303         /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */\r
2304         uint32_t maxCCO    = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/\r
2305         uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);\r
2306 \r
2307         /* Initialize  and power up PLL */\r
2308         SYSCON->SYSPLLMDEC = maxCCO;\r
2309         POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);\r
2310 \r
2311         /* Set mreq to activate */\r
2312         SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);\r
2313 \r
2314         /* Delay for 72 uSec @ 12Mhz */\r
2315         SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2316 \r
2317         /* clear mreq to prepare for restoring mreq */\r
2318         SYSCON->SYSPLLMDEC = curSSCTRL;\r
2319 \r
2320         /* set original value back and activate */\r
2321         SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);\r
2322 \r
2323         /* Enable peripheral states by setting low */\r
2324         POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);\r
2325     }\r
2326     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
2327     {\r
2328         while (CLOCK_IsSystemPLLLocked() == false)\r
2329         {\r
2330         }\r
2331     }\r
2332 \r
2333     /* Update current programmed PLL rate var */\r
2334     s_Pll_Freq = pSetup->pllRate;\r
2335 \r
2336     return kStatus_PLL_Success;\r
2337 }\r
2338 \r
2339 /* Setup Audio PLL Frequency from pre-calculated value */\r
2340 /**\r
2341  * brief        Set Audio PLL output from Audio PLL setup structure (precise frequency)\r
2342  * param        pSetup  : Pointer to populated PLL setup structure\r
2343  * return       kStatus_PLL_Success on success, or Audio PLL setup error code\r
2344  * note This function will power off the PLL, setup the Audio PLL with the\r
2345  * new setup data, and then optionally powerup the PLL, wait for Audio PLL lock,\r
2346  * and adjust system voltages to the new PLL rate. The function will not\r
2347  * alter any source clocks (ie, main systen clock) that may use the Audio PLL,\r
2348  * so these should be setup prior to and after exiting the function.\r
2349  */\r
2350 pll_error_t CLOCK_SetAudioPLLFreq(const pll_setup_t *pSetup)\r
2351 {\r
2352     if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)\r
2353     {\r
2354         /* Turn on the ext clock if system pll input select clk_in */\r
2355         CLOCK_Enable_SysOsc(true);\r
2356     }\r
2357     /* Enable power VD3 for PLLs */\r
2358     POWER_SetPLL();\r
2359     /* Power off Audio PLL during setup changes */\r
2360     POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
2361 \r
2362     /* Write Audio PLL setup data */\r
2363     SYSCON->AUDPLLCTRL = pSetup->pllctrl;\r
2364     SYSCON->AUDPLLFRAC = pSetup->audpllfrac;\r
2365     SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT); /* latch */\r
2366     SYSCON->AUDPLLNDEC = pSetup->pllndec;\r
2367     SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_AUDPLLNDEC_NREQ_SHIFT); /* latch */\r
2368     SYSCON->AUDPLLPDEC = pSetup->pllpdec;\r
2369     SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_AUDPLLPDEC_PREQ_SHIFT); /* latch */\r
2370     SYSCON->AUDPLLMDEC = pSetup->pllmdec;\r
2371     SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_AUDPLLMDEC_MREQ_SHIFT); /* latch */\r
2372     SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1);                            /* disable fractional function */\r
2373 \r
2374     /* Flags for lock or power on */\r
2375     if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)\r
2376     {\r
2377         /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */\r
2378         uint32_t maxCCO    = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/\r
2379         uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);\r
2380 \r
2381         /* Initialize  and power up PLL */\r
2382         SYSCON->SYSPLLMDEC = maxCCO;\r
2383         POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
2384 \r
2385         /* Set mreq to activate */\r
2386         SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);\r
2387 \r
2388         /* Delay for 72 uSec @ 12Mhz */\r
2389         SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2390 \r
2391         /* clear mreq to prepare for restoring mreq */\r
2392         SYSCON->SYSPLLMDEC = curSSCTRL;\r
2393 \r
2394         /* set original value back and activate */\r
2395         SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);\r
2396 \r
2397         /* Enable peripheral states by setting low */\r
2398         POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);\r
2399     }\r
2400     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)\r
2401     {\r
2402         while (CLOCK_IsAudioPLLLocked() == false)\r
2403         {\r
2404         }\r
2405     }\r
2406 \r
2407     /* Update current programmed PLL rate var */\r
2408     s_Audio_Pll_Freq = pSetup->pllRate;\r
2409 \r
2410     return kStatus_PLL_Success;\r
2411 }\r
2412 \r
2413 /* Setup USB PLL Frequency from pre-calculated value */\r
2414 /**\r
2415  * brief        Set USB PLL output from USB PLL setup structure (precise frequency)\r
2416  * param        pSetup  : Pointer to populated USB PLL setup structure\r
2417  * return       kStatus_PLL_Success on success, or USB PLL setup error code\r
2418  * note This function will power off the USB PLL, setup the PLL with the\r
2419  * new setup data, and then optionally powerup the USB PLL, wait for USB PLL lock,\r
2420  * and adjust system voltages to the new USB PLL rate. The function will not\r
2421  * alter any source clocks (ie, usb pll clock) that may use the USB PLL,\r
2422  * so these should be setup prior to and after exiting the function.\r
2423  */\r
2424 pll_error_t CLOCK_SetUsbPLLFreq(const usb_pll_setup_t *pSetup)\r
2425 {\r
2426     uint32_t usbpllctrl, fccoHz;\r
2427     uint8_t msel, psel, nsel;\r
2428     bool pllDirectInput, pllDirectOutput, pllfbsel;\r
2429 \r
2430     msel            = pSetup->msel;\r
2431     psel            = pSetup->psel;\r
2432     nsel            = pSetup->nsel;\r
2433     pllDirectOutput = pSetup->direct;\r
2434     pllDirectInput  = pSetup->bypass;\r
2435     pllfbsel        = pSetup->fbsel;\r
2436 \r
2437     /* Input clock into the PLL cannot be lower than this */\r
2438     if (pSetup->inputRate < USB_PLL_LOWER_IN_LIMIT)\r
2439     {\r
2440         return kStatus_PLL_InputTooLow;\r
2441     }\r
2442 \r
2443     if (pllfbsel)\r
2444     {\r
2445         /*integer_mode: Fout = M*(Fin/N),  Fcco = 2*P*M*(Fin/N) */\r
2446         fccoHz = (pSetup->inputRate / ((uint32_t)nsel + 1U)) * 2U * (msel + 1U) * SWITCH_USB_PSEL(psel);\r
2447 \r
2448         /* USB PLL CCO out rate cannot be lower than this */\r
2449         if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ)\r
2450         {\r
2451             return kStatus_PLL_CCOTooLow;\r
2452         }\r
2453         /* USB PLL CCO out rate cannot be Higher than this */\r
2454         if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ)\r
2455         {\r
2456             return kStatus_PLL_CCOTooHigh;\r
2457         }\r
2458     }\r
2459     else\r
2460     {\r
2461         /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */\r
2462         fccoHz = pSetup->inputRate / ((uint32_t)nsel + 1U) * (msel + 1U);\r
2463 \r
2464         /* USB PLL CCO out rate cannot be lower than this */\r
2465         if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ)\r
2466         {\r
2467             return kStatus_PLL_CCOTooLow;\r
2468         }\r
2469         /* USB PLL CCO out rate cannot be Higher than this */\r
2470         if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ)\r
2471         {\r
2472             return kStatus_PLL_CCOTooHigh;\r
2473         }\r
2474     }\r
2475 \r
2476     /* If configure the USB HOST clock, VD5 power for USB PHY should be enable\r
2477        before the PLL is working */\r
2478     /* Turn on the ext clock for usb pll input */\r
2479     CLOCK_Enable_SysOsc(true);\r
2480 \r
2481     /* Enable power VD3 for PLLs */\r
2482     POWER_SetPLL();\r
2483 \r
2484     /* Power on the VD5 for USB PHY */\r
2485     POWER_SetUsbPhy();\r
2486 \r
2487     /* Power off USB PLL during setup changes */\r
2488     POWER_EnablePD(kPDRUNCFG_PD_USB_PLL);\r
2489 \r
2490     /* Write USB PLL setup data */\r
2491     usbpllctrl = USB_PLL_NSEL_VAL_SET(nsel) |                                  /* NSEL VALUE */\r
2492                  USB_PLL_PSEL_VAL_SET(psel) |                                  /* PSEL VALUE */\r
2493                  USB_PLL_MSEL_VAL_SET(msel) |                                  /* MSEL VALUE */\r
2494                  (uint32_t)pllDirectInput << SYSCON_USBPLLCTRL_BYPASS_SHIFT |  /* BYPASS DISABLE */\r
2495                  (uint32_t)pllDirectOutput << SYSCON_USBPLLCTRL_DIRECT_SHIFT | /* DIRECTO DISABLE */\r
2496                  (uint32_t)pllfbsel << SYSCON_USBPLLCTRL_FBSEL_SHIFT;          /* FBSEL SELECT */\r
2497 \r
2498     SYSCON->USBPLLCTRL = usbpllctrl;\r
2499 \r
2500     POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);\r
2501 \r
2502     /* Delay for 72 uSec @ 12Mhz for the usb pll to lock */\r
2503     SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2504     if (false == pllDirectInput)\r
2505     {\r
2506         while (CLOCK_IsUsbPLLLocked() == false)\r
2507         {\r
2508         }\r
2509     }\r
2510     CLOCK_GetUsbPLLOutFromSetupUpdate(pSetup);\r
2511     return kStatus_PLL_Success;\r
2512 }\r
2513 \r
2514 /* Set System PLL clock based on the input frequency and multiplier */\r
2515 /*! brief       Set PLL output based on the multiplier and input frequency\r
2516  * param        multiply_by     : multiplier\r
2517  * param        input_freq      : Clock input frequency of the PLL\r
2518  * return       Nothing\r
2519  * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this\r
2520  * function does not disable or enable PLL power, wait for PLL lock,\r
2521  * or adjust system voltages. These must be done in the application.\r
2522  * The function will not alter any source clocks (ie, main systen clock)\r
2523  * that may use the PLL, so these should be setup prior to and after\r
2524  * exiting the function.\r
2525  */\r
2526 void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq)\r
2527 {\r
2528     uint32_t cco_freq = input_freq * multiply_by;\r
2529     uint32_t pdec     = 1U;\r
2530     uint32_t selr;\r
2531     uint32_t seli;\r
2532     uint32_t selp;\r
2533     uint32_t mdec, ndec;\r
2534 \r
2535     uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO(1);\r
2536 \r
2537     while (cco_freq < 275000000U)\r
2538     {\r
2539         multiply_by <<= 1U; /* double value in each iteration */\r
2540         pdec <<= 1U;        /* correspondingly double pdec to cancel effect of double msel */\r
2541         cco_freq = input_freq * multiply_by;\r
2542     }\r
2543     selr = 0U;\r
2544     if (multiply_by < 60U)\r
2545     {\r
2546         seli = (multiply_by & 0x3cU) + 4U;\r
2547         selp = (multiply_by >> 1U) + 1U;\r
2548     }\r
2549     else\r
2550     {\r
2551         selp = 31U;\r
2552         if (multiply_by > 16384U)\r
2553         {\r
2554             seli = 1U;\r
2555         }\r
2556         else if (multiply_by > 8192U)\r
2557         {\r
2558             seli = 2U;\r
2559         }\r
2560         else if (multiply_by > 2048U)\r
2561         {\r
2562             seli = 4U;\r
2563         }\r
2564         else if (multiply_by >= 501U)\r
2565         {\r
2566             seli = 8U;\r
2567         }\r
2568         else\r
2569         {\r
2570             seli = 4U * (1024U / (multiply_by + 9U));\r
2571         }\r
2572     }\r
2573 \r
2574     if (pdec > 1U)\r
2575     {\r
2576         directo = 0U;        /* use post divider */\r
2577         pdec    = pdec / 2U; /* Account for minus 1 encoding */\r
2578                              /* Translate P value */\r
2579         switch (pdec)\r
2580         {\r
2581             case 1U:\r
2582                 pdec = 0x62U; /* 1  * 2 */\r
2583                 break;\r
2584             case 2U:\r
2585                 pdec = 0x42U; /* 2  * 2 */\r
2586                 break;\r
2587             case 4U:\r
2588                 pdec = 0x02U; /* 4  * 2 */\r
2589                 break;\r
2590             case 8U:\r
2591                 pdec = 0x0bU; /* 8  * 2 */\r
2592                 break;\r
2593             case 16U:\r
2594                 pdec = 0x11U; /* 16 * 2 */\r
2595                 break;\r
2596             case 32U:\r
2597                 pdec = 0x08U; /* 32 * 2 */\r
2598                 break;\r
2599             default:\r
2600                 pdec = 0x08U;\r
2601                 break;\r
2602         }\r
2603     }\r
2604 \r
2605     mdec = PLL_MDEC_VAL_SET(pllEncodeM(multiply_by));\r
2606     ndec = 0x302U; /* pre divide by 1 (hardcoded) */\r
2607 \r
2608     SYSCON->SYSPLLCTRL = directo | (selr << SYSCON_SYSPLLCTRL_SELR_SHIFT) | (seli << SYSCON_SYSPLLCTRL_SELI_SHIFT) |\r
2609                          (selp << SYSCON_SYSPLLCTRL_SELP_SHIFT);\r
2610     SYSCON->SYSPLLPDEC = pdec | (1U << 7U);   /* set Pdec value and assert preq */\r
2611     SYSCON->SYSPLLNDEC = ndec | (1UL << 10U); /* set Pdec value and assert preq */\r
2612     SYSCON->SYSPLLMDEC = (1UL << 17U) | mdec; /* select non sscg MDEC value, assert mreq and select mdec value */\r
2613 }\r
2614 \r
2615 /* Enable USB DEVICE FULL SPEED clock */\r
2616 /*! brief Enable USB Device FS clock.\r
2617  * param        src     : clock source\r
2618  * param        freq: clock frequency\r
2619  * Enable USB Device Full Speed clock.\r
2620  */\r
2621 bool CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src, uint32_t freq)\r
2622 {\r
2623     bool ret = true;\r
2624 \r
2625     CLOCK_DisableClock(kCLOCK_Usbd0);\r
2626 \r
2627     if (kCLOCK_UsbSrcFro == src)\r
2628     {\r
2629         switch (freq)\r
2630         {\r
2631             case 96000000U:\r
2632                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */\r
2633                 break;\r
2634 \r
2635             case 48000000U:\r
2636                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */\r
2637                 break;\r
2638 \r
2639             default:\r
2640                 ret = false;\r
2641                 break;\r
2642         }\r
2643         /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */\r
2644         SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |\r
2645                           SYSCON_FROCTRL_USBCLKADJ_MASK;\r
2646         /* Select FRO 96 or 48 MHz */\r
2647         CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);\r
2648     }\r
2649     else\r
2650     {\r
2651         /*Set the USB PLL as the Usb0 CLK*/\r
2652         POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);\r
2653 \r
2654         usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};\r
2655 \r
2656         (void)CLOCK_SetUsbPLLFreq(&pll_setup);\r
2657         CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);\r
2658         CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK);\r
2659         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2660     }\r
2661     CLOCK_EnableClock(kCLOCK_Usbd0);\r
2662     CLOCK_EnableClock(kCLOCK_UsbRam1);\r
2663 \r
2664     return ret;\r
2665 }\r
2666 \r
2667 /* Enable USB HOST FULL SPEED clock */\r
2668 /*! brief Enable USB HOST FS clock.\r
2669  * param        src     : clock source\r
2670  * param        freq: clock frequency\r
2671  * Enable USB HOST Full Speed clock.\r
2672  */\r
2673 bool CLOCK_EnableUsbfs0HostClock(clock_usb_src_t src, uint32_t freq)\r
2674 {\r
2675     bool ret = true;\r
2676 \r
2677     CLOCK_DisableClock(kCLOCK_Usbhmr0);\r
2678     CLOCK_DisableClock(kCLOCK_Usbhsl0);\r
2679 \r
2680     if (kCLOCK_UsbSrcFro == src)\r
2681     {\r
2682         switch (freq)\r
2683         {\r
2684             case 96000000U:\r
2685                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */\r
2686                 break;\r
2687 \r
2688             case 48000000U:\r
2689                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */\r
2690                 break;\r
2691 \r
2692             default:\r
2693                 ret = false;\r
2694                 break;\r
2695         }\r
2696         /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */\r
2697         SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |\r
2698                           SYSCON_FROCTRL_USBCLKADJ_MASK;\r
2699         /* Select FRO 96 or 48 MHz */\r
2700         CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);\r
2701     }\r
2702     else\r
2703     {\r
2704         /*Set the USB PLL as the Usb0 CLK*/\r
2705         POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);\r
2706 \r
2707         usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};\r
2708 \r
2709         (void)CLOCK_SetUsbPLLFreq(&pll_setup);\r
2710         CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);\r
2711         CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK);\r
2712         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2713     }\r
2714     CLOCK_EnableClock(kCLOCK_Usbhmr0);\r
2715     CLOCK_EnableClock(kCLOCK_Usbhsl0);\r
2716     CLOCK_EnableClock(kCLOCK_UsbRam1);\r
2717 \r
2718     return ret;\r
2719 }\r
2720 \r
2721 /* Enable USB DEVICE HIGH SPEED clock */\r
2722 /*! brief Enable USB Device HS clock.\r
2723  * param        src     : clock source\r
2724  * param        freq: clock frequency\r
2725  * Enable USB Device High Speed clock.\r
2726  */\r
2727 bool CLOCK_EnableUsbhs0DeviceClock(clock_usb_src_t src, uint32_t freq)\r
2728 {\r
2729     bool ret = true;\r
2730     CLOCK_DisableClock(kCLOCK_Usbd1);\r
2731     /* Power on the VD5 for USB PHY */\r
2732     POWER_SetUsbPhy();\r
2733     if (kCLOCK_UsbSrcFro == src)\r
2734     {\r
2735         switch (freq)\r
2736         {\r
2737             case 96000000U:\r
2738                 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */\r
2739                 break;\r
2740 \r
2741             case 48000000U:\r
2742                 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */\r
2743                 break;\r
2744 \r
2745             default:\r
2746                 ret = false;\r
2747                 break;\r
2748         }\r
2749         /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */\r
2750         SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |\r
2751                           SYSCON_FROCTRL_USBCLKADJ_MASK;\r
2752         /* Select FRO 96 or 48 MHz */\r
2753         CLOCK_AttachClk(kFRO_HF_to_USB1_CLK);\r
2754     }\r
2755     else\r
2756     {\r
2757         SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2758         usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};\r
2759 \r
2760         (void)CLOCK_SetUsbPLLFreq(&pll_setup);\r
2761 \r
2762         /* Select USB PLL output as USB clock src */\r
2763         CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false);\r
2764         CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK);\r
2765     }\r
2766 \r
2767     SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2768     /* Enable USB1D and USB1RAM */\r
2769     CLOCK_EnableClock(kCLOCK_Usbd1);\r
2770     CLOCK_EnableClock(kCLOCK_UsbRam1);\r
2771     POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */\r
2772     return ret;\r
2773 }\r
2774 \r
2775 /* Enable USB HOST HIGH SPEED clock */\r
2776 /*! brief Enable USB HOST HS clock.\r
2777  * param        src     : clock source\r
2778  * param        freq: clock frequency\r
2779  * Enable USB HOST High Speed clock.\r
2780  */\r
2781 bool CLOCK_EnableUsbhs0HostClock(clock_usb_src_t src, uint32_t freq)\r
2782 {\r
2783     bool ret = true;\r
2784     CLOCK_DisableClock(kCLOCK_Usbh1);\r
2785     /* Power on the VD5 for USB PHY */\r
2786     POWER_SetUsbPhy();\r
2787     if (kCLOCK_UsbSrcFro == src)\r
2788     {\r
2789         switch (freq)\r
2790         {\r
2791             case 96000000U:\r
2792                 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */\r
2793                 break;\r
2794 \r
2795             case 48000000U:\r
2796                 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */\r
2797                 break;\r
2798 \r
2799             default:\r
2800                 ret = false;\r
2801                 break;\r
2802         }\r
2803         /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */\r
2804         SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |\r
2805                           SYSCON_FROCTRL_USBCLKADJ_MASK;\r
2806         /* Select FRO 96 or 48 MHz */\r
2807         CLOCK_AttachClk(kFRO_HF_to_USB1_CLK);\r
2808     }\r
2809     else\r
2810     {\r
2811         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2812         usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};\r
2813 \r
2814         (void)CLOCK_SetUsbPLLFreq(&pll_setup);\r
2815 \r
2816         /* Select USB PLL output as USB clock src */\r
2817         CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false);\r
2818         CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK);\r
2819     }\r
2820 \r
2821     SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
2822     /* Enable USBh1 and USB1RAM */\r
2823     CLOCK_EnableClock(kCLOCK_Usbh1);\r
2824     CLOCK_EnableClock(kCLOCK_UsbRam1);\r
2825     POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */\r
2826     return ret;\r
2827 }\r