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