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