1 /*
2  * Copyright 2017 - 2021 , NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_clock.h"
9 #include "fsl_power.h"
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.clock"
16 #endif
17 #define NVALMAX (0x100U)
18 #define PVALMAX (0x20U)
19 #define MVALMAX (0x10000U)
20 
21 #define PLL_MAX_N_DIV 0x100U
22 
23 /*--------------------------------------------------------------------------
24 !!! If required these #defines can be moved to chip library file
25 ----------------------------------------------------------------------------*/
26 
27 #define PLL_SSCG1_MDEC_VAL_P (10U) /* MDEC is in bits  25 downto 10 */
28 #define PLL_SSCG1_MDEC_VAL_M (0xFFFFULL << PLL_SSCG1_MDEC_VAL_P)
29 #define PLL_NDEC_VAL_P       (0U) /* NDEC is in bits  9:0 */
30 #define PLL_NDEC_VAL_M       (0xFFUL << PLL_NDEC_VAL_P)
31 #define PLL_PDEC_VAL_P       (0U) /*!<  PDEC is in bits 6:0 */
32 #define PLL_PDEC_VAL_M       (0x1FUL << PLL_PDEC_VAL_P)
33 
34 #define PLL_MIN_CCO_FREQ_MHZ (275000000U)
35 #define PLL_MAX_CCO_FREQ_MHZ (550000000U)
36 #define PLL_LOWER_IN_LIMIT   (2000U)      /*!<  Minimum PLL input rate */
37 #define PLL_HIGHER_IN_LIMIT  (150000000U) /*!<  Maximum PLL input rate */
38 #define PLL_MIN_IN_SSMODE    (3000000U)
39 #define PLL_MAX_IN_SSMODE \
40     (100000000U) /*!<  Not find the value in UM, Just use the maximum frequency which device support */
41 
42 /* PLL NDEC reg */
43 #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
44 /* PLL PDEC reg */
45 #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
46 /* SSCG control1 */
47 #define PLL_SSCG1_MDEC_VAL_SET(value) (((uint64_t)(value) << PLL_SSCG1_MDEC_VAL_P) & PLL_SSCG1_MDEC_VAL_M)
48 
49 /* PLL0 SSCG control1 */
50 #define PLL0_SSCG_MD_FRACT_P 0U
51 #define PLL0_SSCG_MD_INT_P   25U
52 #define PLL0_SSCG_MD_FRACT_M (0x1FFFFFFUL << PLL0_SSCG_MD_FRACT_P)
53 #define PLL0_SSCG_MD_INT_M   ((uint64_t)0xFFUL << PLL0_SSCG_MD_INT_P)
54 
55 #define PLL0_SSCG_MD_FRACT_SET(value) (((uint64_t)(value) << PLL0_SSCG_MD_FRACT_P) & PLL0_SSCG_MD_FRACT_M)
56 #define PLL0_SSCG_MD_INT_SET(value)   (((uint64_t)(value) << PLL0_SSCG_MD_INT_P) & PLL0_SSCG_MD_INT_M)
57 
58 /* Saved value of PLL output rate, computed whenever needed to save run-time
59    computation on each call to retrive the PLL rate. */
60 static uint32_t s_Pll0_Freq;
61 static uint32_t s_Pll1_Freq;
62 
63 /** External clock rate on the CLKIN pin in Hz. If not used,
64     set this to 0. Otherwise, set it to the exact rate in Hz this pin is
65     being driven at. */
66 static uint32_t s_Ext_Clk_Freq   = 16000000U;
67 static uint32_t s_I2S_Mclk_Freq  = 0U;
68 static uint32_t s_PLU_ClkIn_Freq = 0U;
69 
70 /*******************************************************************************
71  * Variables
72  ******************************************************************************/
73 
74 /*******************************************************************************
75  * Prototypes
76  ******************************************************************************/
77 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
78 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
79 /* Get predivider (N) from PLL0 NDEC setting */
80 static uint32_t findPll0PreDiv(void);
81 /* Get predivider (N) from PLL1 NDEC setting */
82 static uint32_t findPll1PreDiv(void);
83 /* Get postdivider (P) from PLL0 PDEC setting */
84 static uint32_t findPll0PostDiv(void);
85 /* Get multiplier (M) from PLL0 MDEC and SSCG settings */
86 static float findPll0MMult(void);
87 /* Get the greatest common divisor */
88 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
89 /* Set PLL output based on desired output rate */
90 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
91 /* Update local PLL rate variable */
92 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup);
93 
94 /*******************************************************************************
95  * Code
96  ******************************************************************************/
97 
98 /* Clock Selection for IP */
99 /**
100  * brief   Configure the clock selection muxes.
101  * param   connection  : Clock to be configured.
102  * return  Nothing
103  */
CLOCK_AttachClk(clock_attach_id_t connection)104 void CLOCK_AttachClk(clock_attach_id_t connection)
105 {
106     uint8_t mux;
107     uint8_t sel;
108     uint16_t item;
109     uint32_t tmp32 = (uint32_t)connection;
110     uint32_t i;
111     volatile uint32_t *pClkSel;
112 
113     pClkSel = &(SYSCON->SYSTICKCLKSELX[0]);
114 
115     if (kNONE_to_NONE != connection)
116     {
117         for (i = 0U; i < 2U; i++)
118         {
119             if (tmp32 == 0U)
120             {
121                 break;
122             }
123             item = (uint16_t)GET_ID_ITEM(tmp32);
124             if (item != 0U)
125             {
126                 mux = GET_ID_ITEM_MUX(item);
127                 sel = GET_ID_ITEM_SEL(item);
128                 if (mux == CM_RTCOSC32KCLKSEL)
129                 {
130                     PMC->RTCOSC32K = (PMC->RTCOSC32K & ~PMC_RTCOSC32K_SEL_MASK) | PMC_RTCOSC32K_SEL(sel);
131                 }
132                 else
133                 {
134                     pClkSel[mux] = sel;
135                 }
136             }
137             tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
138         }
139     }
140 }
141 
142 /* Return the actual clock attach id */
143 /**
144  * brief   Get the actual clock attach id.
145  * This fuction uses the offset in input attach id, then it reads the actual source value in
146  * the register and combine the offset to obtain an actual attach id.
147  * param   attachId  : Clock attach id to get.
148  * return  Clock source value.
149  */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)150 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
151 {
152     uint8_t mux;
153     uint8_t actualSel;
154     uint32_t tmp32 = (uint32_t)attachId;
155     uint32_t i;
156     uint32_t actualAttachId = 0U;
157     uint32_t selector       = GET_ID_SELECTOR(tmp32);
158     volatile uint32_t *pClkSel;
159 
160     pClkSel = &(SYSCON->SYSTICKCLKSELX[0]);
161 
162     if (kNONE_to_NONE == attachId)
163     {
164         return kNONE_to_NONE;
165     }
166 
167     for (i = 0U; i < 2U; i++)
168     {
169         mux = GET_ID_ITEM_MUX(tmp32);
170         if (tmp32 != 0UL)
171         {
172             if (mux == CM_RTCOSC32KCLKSEL)
173             {
174                 actualSel = (uint8_t)(PMC->RTCOSC32K);
175             }
176             else
177             {
178                 actualSel = (uint8_t)(pClkSel[mux]);
179             }
180 
181             /* Consider the combination of two registers */
182             actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
183         }
184         tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!<  pick up next descriptor */
185     }
186 
187     actualAttachId |= selector;
188 
189     return (clock_attach_id_t)actualAttachId;
190 }
191 
192 /* Set IP Clock Divider */
193 /**
194  * brief   Setup peripheral clock dividers.
195  * param   div_name    : Clock divider name
196  * param divided_by_value: Value to be divided
197  * param reset :  Whether to reset the divider counter.
198  * return  Nothing
199  */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)200 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
201 {
202     volatile uint32_t *pClkDiv;
203 
204     pClkDiv = &(SYSCON->SYSTICKCLKDIV0);
205     if ((div_name >= kCLOCK_DivFlexFrg0) && (div_name <= kCLOCK_DivFlexFrg7))
206     {
207         /*!<  Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1+ MULT /DIV), DIV = 0xFF */
208         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] =
209             SYSCON_FLEXFRG0CTRL_DIV_MASK | SYSCON_FLEXFRG0CTRL_MULT(divided_by_value);
210     }
211     else
212     {
213         if (reset)
214         {
215             ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 29U;
216         }
217         if (divided_by_value == 0U) /*!<  halt */
218         {
219             ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 30U;
220         }
221         else
222         {
223             ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = (divided_by_value - 1U);
224         }
225     }
226 }
227 
228 /* Set RTC 1KHz Clock Divider */
229 /**
230  * brief   Setup rtc 1khz clock divider.
231  * param divided_by_value: Value to be divided
232  * return  Nothing
233  */
CLOCK_SetRtc1khzClkDiv(uint32_t divided_by_value)234 void CLOCK_SetRtc1khzClkDiv(uint32_t divided_by_value)
235 {
236     PMC->RTCOSC32K |= (((divided_by_value - 28U) << PMC_RTCOSC32K_CLK1KHZDIV_SHIFT) | PMC_RTCOSC32K_CLK1KHZDIV_MASK);
237 }
238 
239 /* Set RTC 1KHz Clock Divider */
240 /**
241  * brief   Setup rtc 1hz clock divider.
242  * param divided_by_value: Value to be divided
243  * return  Nothing
244  */
CLOCK_SetRtc1hzClkDiv(uint32_t divided_by_value)245 void CLOCK_SetRtc1hzClkDiv(uint32_t divided_by_value)
246 {
247     if (divided_by_value == 0U) /*!<  halt */
248     {
249         PMC->RTCOSC32K |= (1UL << PMC_RTCOSC32K_CLK1HZDIVHALT_SHIFT);
250     }
251     else
252     {
253         PMC->RTCOSC32K |=
254             (((divided_by_value - 31744U) << PMC_RTCOSC32K_CLK1HZDIV_SHIFT) | PMC_RTCOSC32K_CLK1HZDIV_MASK);
255     }
256 }
257 
258 /* Set FRO Clocking */
259 /**
260  * brief   Initialize the Core clock to given frequency (12, 48 or 96 MHz).
261  * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
262  * enabled.
263  * param   iFreq   : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
264  * return  returns success or fail status.
265  */
CLOCK_SetupFROClocking(uint32_t iFreq)266 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
267 {
268     if ((iFreq != 12000000U) && (iFreq != 48000000U) && (iFreq != 96000000U))
269     {
270         return kStatus_Fail;
271     }
272     /* Enable Analog Control module */
273     SYSCON->PRESETCTRLCLR[2] = (1UL << SYSCON_PRESETCTRL2_ANALOG_CTRL_RST_SHIFT);
274     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL_MASK;
275     /* Power up the FRO192M */
276     POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
277 
278     if (iFreq == 96000000U)
279     {
280         ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_96MHZCLK(1);
281     }
282     /* always enable
283     else if (iFreq == 48000000U)
284     {
285         ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_48MHZCLK(1);
286     }*/
287     else
288     {
289         ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_12MHZCLK(1);
290     }
291     return kStatus_Success;
292 }
293 
294 /* Set the FLASH wait states for the passed frequency */
295 /**
296  * brief    Set the flash wait states for the input freuqency.
297  * param    iFreq: Input frequency
298  * return    Nothing
299  */
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)300 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)
301 {
302     uint32_t num_wait_states; /* Flash Controller & FMC internal number of Wait States (minus 1) */
303     uint32_t prefetch_enable_mask = SYSCON->FMCCR & SYSCON_FMCCR_PREFEN_MASK;
304 
305     if (iFreq <= 11000000UL)
306     {
307         /* [0 - 11 MHz] */
308         num_wait_states = 0UL;
309     }
310     else if (iFreq <= 22000000UL)
311     {
312         /* [11 MHz - 22 MHz] */
313         num_wait_states = 1UL;
314     }
315     else if (iFreq <= 33000000UL)
316     {
317         /* [22 MHz - 33 MHz] */
318         num_wait_states = 2UL;
319     }
320     else if (iFreq <= 44000000UL)
321     {
322         /* [33 MHz - 44 MHz] */
323         num_wait_states = 3UL;
324     }
325     else if (iFreq <= 55000000UL)
326     {
327         /* [44 MHz - 55 MHz] */
328         num_wait_states = 4UL;
329     }
330     else if (iFreq <= 66000000UL)
331     {
332         /* [55 MHz - 662 MHz] */
333         num_wait_states = 5UL;
334     }
335     else if (iFreq <= 77000000UL)
336     {
337         /* [66 MHz - 77 MHz] */
338         num_wait_states = 6UL;
339     }
340     else if (iFreq <= 88000000UL)
341     {
342         /* [77 MHz - 88 MHz] */
343         num_wait_states = 7UL;
344     }
345     else if (iFreq <= 100000000UL)
346     {
347         /* [88 MHz - 100 MHz] */
348         num_wait_states = 8UL;
349     }
350     else if (iFreq <= 115000000UL)
351     {
352         /* [100 MHz - 115 MHz] */
353         num_wait_states = 9UL;
354     }
355     else if (iFreq <= 130000000UL)
356     {
357         /* [115 MHz - 130 MHz] */
358         num_wait_states = 10UL;
359     }
360     else if (iFreq <= 150000000UL)
361     {
362         /* [130 MHz - 150 MHz] */
363         num_wait_states = 11UL;
364     }
365     else
366     {
367         /* Above 150 MHz */
368         num_wait_states = 12UL;
369     }
370 
371     /*The prefetch bit must be disabled before any flash commands*/
372     SYSCON->FMCCR &= ~SYSCON_FMCCR_PREFEN_MASK;
373 
374     FLASH->INT_CLR_STATUS = 0x1FUL; /* Clear all status flags */
375 
376     FLASH->DATAW[0] = (FLASH->DATAW[0] & 0xFFFFFFF0UL) |
377                       (num_wait_states & (SYSCON_FMCCR_FLASHTIM_MASK >> SYSCON_FMCCR_FLASHTIM_SHIFT));
378 
379     FLASH->CMD = 0x2; /* CMD_SET_READ_MODE */
380 
381     /* Wait until the cmd is completed (without error) */
382     while (0UL == (FLASH->INT_STATUS & FLASH_INT_STATUS_DONE_MASK))
383     {
384         ;
385     }
386 
387     /* Adjust FMC waiting time cycles (num_wait_states) */
388     SYSCON->FMCCR = (SYSCON->FMCCR & ~SYSCON_FMCCR_FLASHTIM_MASK) |
389                     ((num_wait_states << SYSCON_FMCCR_FLASHTIM_SHIFT) & SYSCON_FMCCR_FLASHTIM_MASK);
390 
391     /* restore prefetch enable */
392     SYSCON->FMCCR |= prefetch_enable_mask;
393 }
394 
395 /* Set EXT OSC Clk */
396 /**
397  * brief   Initialize the external osc clock to given frequency.
398  * Crystal oscillator with an operating frequency of 12 MHz to 32 MHz.
399  * Option for external clock input (bypass mode) for clock frequencies of up to 25 MHz.
400  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
401  * return  returns success or fail status.
402  */
CLOCK_SetupExtClocking(uint32_t iFreq)403 status_t CLOCK_SetupExtClocking(uint32_t iFreq)
404 {
405     if (iFreq > 32000000U)
406     {
407         return kStatus_Fail;
408     }
409     /* Turn on power for crystal 32 MHz */
410     POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);
411     POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);
412     /* Enable clock_in clock for clock module. */
413     SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;
414 
415     /* Wait for external osc clock to be valid. */
416     while((ANACTRL->XO32M_STATUS & ANACTRL_XO32M_STATUS_XO_READY_MASK) == 0U)
417     {
418     }
419 
420     s_Ext_Clk_Freq = iFreq;
421     return kStatus_Success;
422 }
423 
424 /* Set I2S MCLK Clk */
425 /**
426  * brief   Initialize the I2S MCLK clock to given frequency.
427  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
428  * return  returns success or fail status.
429  */
CLOCK_SetupI2SMClkClocking(uint32_t iFreq)430 status_t CLOCK_SetupI2SMClkClocking(uint32_t iFreq)
431 {
432     s_I2S_Mclk_Freq = iFreq;
433     return kStatus_Success;
434 }
435 
436 /* Set PLU CLKIN Clk */
437 /**
438  * brief   Initialize the PLU CLKIN clock to given frequency.
439  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
440  * return  returns success or fail status.
441  */
CLOCK_SetupPLUClkInClocking(uint32_t iFreq)442 status_t CLOCK_SetupPLUClkInClocking(uint32_t iFreq)
443 {
444     s_PLU_ClkIn_Freq = iFreq;
445     return kStatus_Success;
446 }
447 
448 /* Get CLOCK OUT Clk */
449 /*! brief  Return Frequency of ClockOut
450  *  return Frequency of ClockOut
451  */
CLOCK_GetClockOutClkFreq(void)452 uint32_t CLOCK_GetClockOutClkFreq(void)
453 {
454     uint32_t freq = 0U;
455 
456     switch (SYSCON->CLKOUTSEL)
457     {
458         case 0U:
459             freq = CLOCK_GetCoreSysClkFreq();
460             break;
461 
462         case 1U:
463             freq = CLOCK_GetPll0OutFreq();
464             break;
465 
466         case 2U:
467             freq = CLOCK_GetExtClkFreq();
468             break;
469 
470         case 3U:
471             freq = CLOCK_GetFroHfFreq();
472             break;
473 
474         case 4U:
475             freq = CLOCK_GetFro1MFreq();
476             break;
477 
478         case 5U:
479             freq = CLOCK_GetPll1OutFreq();
480             break;
481 
482         case 6U:
483             freq = CLOCK_GetOsc32KFreq();
484             break;
485 
486         case 7U:
487             freq = 0U;
488             break;
489 
490         default:
491             assert(false);
492             break;
493     }
494     return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
495 }
496 
497 /* Get ADC Clk */
498 /*! brief  Return Frequency of Adc Clock
499  *  return Frequency of Adc.
500  */
CLOCK_GetAdcClkFreq(void)501 uint32_t CLOCK_GetAdcClkFreq(void)
502 {
503     uint32_t freq = 0U;
504 
505     switch (SYSCON->ADCCLKSEL)
506     {
507         case 0U:
508             freq = CLOCK_GetCoreSysClkFreq();
509             break;
510         case 1U:
511             freq = CLOCK_GetPll0OutFreq();
512             break;
513         case 2U:
514             freq = CLOCK_GetFroHfFreq();
515             break;
516         case 7U:
517             freq = 0U;
518             break;
519 
520         default:
521             assert(false);
522             break;
523     }
524 
525     return freq / ((SYSCON->ADCCLKDIV & SYSCON_ADCCLKDIV_DIV_MASK) + 1U);
526 }
527 
528 /* Get USB0 Clk */
529 /*! brief  Return Frequency of Usb0 Clock
530  *  return Frequency of Usb0 Clock.
531  */
CLOCK_GetUsb0ClkFreq(void)532 uint32_t CLOCK_GetUsb0ClkFreq(void)
533 {
534     uint32_t freq = 0U;
535 
536     switch (SYSCON->USB0CLKSEL)
537     {
538         case 0U:
539             freq = CLOCK_GetCoreSysClkFreq();
540             break;
541         case 1U:
542             freq = CLOCK_GetPll0OutFreq();
543             break;
544         case 3U:
545             freq = CLOCK_GetFroHfFreq();
546             break;
547         case 5U:
548             freq = CLOCK_GetPll1OutFreq();
549             break;
550         case 7U:
551             freq = 0U;
552             break;
553 
554         default:
555             assert(false);
556             break;
557     }
558 
559     return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
560 }
561 
562 /* Get USB1 Clk */
563 /*! brief  Return Frequency of Usb1 Clock
564  *  return Frequency of Usb1 Clock.
565  */
CLOCK_GetUsb1ClkFreq(void)566 uint32_t CLOCK_GetUsb1ClkFreq(void)
567 {
568     return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
569 }
570 
571 /* Get MCLK Clk */
572 /*! brief  Return Frequency of MClk Clock
573  *  return Frequency of MClk Clock.
574  */
CLOCK_GetMclkClkFreq(void)575 uint32_t CLOCK_GetMclkClkFreq(void)
576 {
577     uint32_t freq = 0U;
578 
579     switch (SYSCON->MCLKCLKSEL)
580     {
581         case 0U:
582             freq = CLOCK_GetFroHfFreq();
583             break;
584         case 1U:
585             freq = CLOCK_GetPll0OutFreq();
586             break;
587         case 7U:
588             freq = 0U;
589             break;
590 
591         default:
592             assert(false);
593             break;
594     }
595 
596     return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
597 }
598 
599 /* Get SCTIMER Clk */
600 /*! brief  Return Frequency of SCTimer Clock
601  *  return Frequency of SCTimer Clock.
602  */
CLOCK_GetSctClkFreq(void)603 uint32_t CLOCK_GetSctClkFreq(void)
604 {
605     uint32_t freq = 0U;
606 
607     switch (SYSCON->SCTCLKSEL)
608     {
609         case 0U:
610             freq = CLOCK_GetCoreSysClkFreq();
611             break;
612         case 1U:
613             freq = CLOCK_GetPll0OutFreq();
614             break;
615         case 2U:
616             freq = CLOCK_GetExtClkFreq();
617             break;
618         case 3U:
619             freq = CLOCK_GetFroHfFreq();
620             break;
621         case 5U:
622             freq = CLOCK_GetI2SMClkFreq();
623             break;
624         case 7U:
625             freq = 0U;
626             break;
627 
628         default:
629             assert(false);
630             break;
631     }
632 
633     return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
634 }
635 
636 /* Get SDIO Clk */
637 /*! brief  Return Frequency of SDIO Clock
638  *  return Frequency of SDIO Clock.
639  */
CLOCK_GetSdioClkFreq(void)640 uint32_t CLOCK_GetSdioClkFreq(void)
641 {
642     uint32_t freq = 0U;
643 
644     switch (SYSCON->SDIOCLKSEL)
645     {
646         case 0U:
647             freq = CLOCK_GetCoreSysClkFreq();
648             break;
649         case 1U:
650             freq = CLOCK_GetPll0OutFreq();
651             break;
652         case 3U:
653             freq = CLOCK_GetFroHfFreq();
654             break;
655         case 5U:
656             freq = CLOCK_GetPll1OutFreq();
657             break;
658         case 7U:
659             freq = 0U;
660             break;
661         default:
662             assert(false);
663             break;
664     }
665 
666     return freq / ((SYSCON->SDIOCLKDIV & 0xffU) + 1U);
667 }
668 
669 /* Get FRO 12M Clk */
670 /*! brief  Return Frequency of FRO 12MHz
671  *  return Frequency of FRO 12MHz
672  */
CLOCK_GetFro12MFreq(void)673 uint32_t CLOCK_GetFro12MFreq(void)
674 {
675     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
676 }
677 
678 /* Get FRO 1M Clk */
679 /*! brief  Return Frequency of FRO 1MHz
680  *  return Frequency of FRO 1MHz
681  */
CLOCK_GetFro1MFreq(void)682 uint32_t CLOCK_GetFro1MFreq(void)
683 {
684     return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
685 }
686 
687 /* Get EXT OSC Clk */
688 /*! brief  Return Frequency of External Clock
689  *  return Frequency of External Clock. If no external clock is used returns 0.
690  */
CLOCK_GetExtClkFreq(void)691 uint32_t CLOCK_GetExtClkFreq(void)
692 {
693     return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
694 }
695 
696 /* Get WATCH DOG Clk */
697 /*! brief  Return Frequency of Watchdog
698  *  return Frequency of Watchdog
699  */
CLOCK_GetWdtClkFreq(void)700 uint32_t CLOCK_GetWdtClkFreq(void)
701 {
702     return CLOCK_GetFro1MFreq() / ((SYSCON->WDTCLKDIV & SYSCON_WDTCLKDIV_DIV_MASK) + 1U);
703 }
704 
705 /* Get HF FRO Clk */
706 /*! brief  Return Frequency of High-Freq output of FRO
707  *  return Frequency of High-Freq output of FRO
708  */
CLOCK_GetFroHfFreq(void)709 uint32_t CLOCK_GetFroHfFreq(void)
710 {
711     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
712 }
713 
714 /* Get SYSTEM PLL Clk */
715 /*! brief  Return Frequency of PLL
716  *  return Frequency of PLL
717  */
CLOCK_GetPll0OutFreq(void)718 uint32_t CLOCK_GetPll0OutFreq(void)
719 {
720     return s_Pll0_Freq;
721 }
722 
723 /* Get USB PLL Clk */
724 /*! brief  Return Frequency of USB PLL
725  *  return Frequency of PLL
726  */
CLOCK_GetPll1OutFreq(void)727 uint32_t CLOCK_GetPll1OutFreq(void)
728 {
729     return s_Pll1_Freq;
730 }
731 
732 /* Get RTC OSC Clk */
733 /*! brief  Return Frequency of 32kHz osc
734  *  return Frequency of 32kHz osc
735  */
CLOCK_GetOsc32KFreq(void)736 uint32_t CLOCK_GetOsc32KFreq(void)
737 {
738     return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
739             (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
740                CLK_RTC_32K_CLK :
741                ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
742                 (0UL != (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
743                CLK_RTC_32K_CLK :
744                0U;
745 }
746 
747 /* Get MAIN Clk */
748 /*! brief  Return Frequency of Core System
749  *  return Frequency of Core System
750  */
CLOCK_GetCoreSysClkFreq(void)751 uint32_t CLOCK_GetCoreSysClkFreq(void)
752 {
753     uint32_t freq = 0U;
754 
755     switch (SYSCON->MAINCLKSELB)
756     {
757         case 0U:
758             if (SYSCON->MAINCLKSELA == 0U)
759             {
760                 freq = CLOCK_GetFro12MFreq();
761             }
762             else if (SYSCON->MAINCLKSELA == 1U)
763             {
764                 freq = CLOCK_GetExtClkFreq();
765             }
766             else if (SYSCON->MAINCLKSELA == 2U)
767             {
768                 freq = CLOCK_GetFro1MFreq();
769             }
770             else if (SYSCON->MAINCLKSELA == 3U)
771             {
772                 freq = CLOCK_GetFroHfFreq();
773             }
774             else
775             {
776                 /* Add comments to prevent the case of MISRA C-2012 rule 15.7. */
777             }
778             break;
779         case 1U:
780             freq = CLOCK_GetPll0OutFreq();
781             break;
782         case 2U:
783             freq = CLOCK_GetPll1OutFreq();
784             break;
785 
786         case 3U:
787             freq = CLOCK_GetOsc32KFreq();
788             break;
789 
790         default:
791             freq = 0U;
792             break;
793     }
794 
795     return freq;
796 }
797 
798 /* Get I2S MCLK Clk */
799 /*! brief  Return Frequency of I2S MCLK Clock
800  *  return Frequency of I2S MCLK Clock
801  */
CLOCK_GetI2SMClkFreq(void)802 uint32_t CLOCK_GetI2SMClkFreq(void)
803 {
804     return s_I2S_Mclk_Freq;
805 }
806 
807 /* Get PLU CLKIN Clk */
808 /*! brief  Return Frequency of PLU CLKIN Clock
809  *  return Frequency of PLU CLKIN Clock
810  */
CLOCK_GetPLUClkInFreq(void)811 uint32_t CLOCK_GetPLUClkInFreq(void)
812 {
813     return s_PLU_ClkIn_Freq;
814 }
815 
816 /* Get FLEXCOMM input clock */
817 /*! brief  Return Frequency of flexcomm input clock
818  *  param  id     : flexcomm instance id
819  *  return Frequency value
820  */
CLOCK_GetFlexCommInputClock(uint32_t id)821 uint32_t CLOCK_GetFlexCommInputClock(uint32_t id)
822 {
823     uint32_t freq = 0U;
824 
825     switch (SYSCON->FCCLKSELX[id])
826     {
827         case 0U:
828             freq = CLOCK_GetCoreSysClkFreq();
829             break;
830         case 1U:
831             freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLL0CLKDIV & 0xffU) + 1U);
832             break;
833         case 2U:
834             freq = CLOCK_GetFro12MFreq();
835             break;
836         case 3U:
837             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
838             break;
839         case 4U:
840             freq = CLOCK_GetFro1MFreq();
841             break;
842         case 5U:
843             freq = CLOCK_GetI2SMClkFreq();
844             break;
845         case 6U:
846             freq = CLOCK_GetOsc32KFreq();
847             break;
848         case 7U:
849             freq = 0U;
850             break;
851 
852         default:
853             assert(false);
854             break;
855     }
856 
857     return freq;
858 }
859 
860 /* Get FLEXCOMM Clk */
CLOCK_GetFlexCommClkFreq(uint32_t id)861 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
862 {
863     uint32_t freq   = 0U;
864     uint32_t frgMul = 0U;
865     uint32_t frgDiv = 0U;
866 
867     freq   = CLOCK_GetFlexCommInputClock(id);
868     frgMul = (SYSCON->FLEXFRGXCTRL[id] & SYSCON_FLEXFRG0CTRL_MULT_MASK) >> 8U;
869     frgDiv = SYSCON->FLEXFRGXCTRL[id] & SYSCON_FLEXFRG0CTRL_DIV_MASK;
870     return (uint32_t)(((uint64_t)freq * ((uint64_t)frgDiv + 1ULL)) / (frgMul + frgDiv + 1UL));
871 }
872 
873 /* Get HS_LPSI Clk */
CLOCK_GetHsLspiClkFreq(void)874 uint32_t CLOCK_GetHsLspiClkFreq(void)
875 {
876     uint32_t freq = 0U;
877 
878     switch (SYSCON->HSLSPICLKSEL)
879     {
880         case 0U:
881             freq = CLOCK_GetCoreSysClkFreq();
882             break;
883         case 1U:
884             freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLL0CLKDIV & 0xffU) + 1U);
885             break;
886         case 2U:
887             freq = CLOCK_GetFro12MFreq();
888             break;
889         case 3U:
890             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
891             break;
892         case 4U:
893             freq = CLOCK_GetFro1MFreq();
894             break;
895         case 6U:
896             freq = CLOCK_GetOsc32KFreq();
897             break;
898         case 7U:
899             freq = 0U;
900             break;
901 
902         default:
903             assert(false);
904             break;
905     }
906 
907     return freq;
908 }
909 
910 /* Get CTimer Clk */
911 /*! brief  Return Frequency of CTimer functional Clock
912  *  return Frequency of CTimer functional Clock
913  */
CLOCK_GetCTimerClkFreq(uint32_t id)914 uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
915 {
916     uint32_t freq = 0U;
917 
918     switch (SYSCON->CTIMERCLKSELX[id])
919     {
920         case 0U:
921             freq = CLOCK_GetCoreSysClkFreq();
922             break;
923         case 1U:
924             freq = CLOCK_GetPll0OutFreq();
925             break;
926         case 3U:
927             freq = CLOCK_GetFroHfFreq();
928             break;
929         case 4U:
930             freq = CLOCK_GetFro1MFreq();
931             break;
932         case 5U:
933             freq = CLOCK_GetI2SMClkFreq();
934             break;
935         case 6U:
936             freq = CLOCK_GetOsc32KFreq();
937             break;
938         case 7U:
939             freq = 0U;
940             break;
941 
942         default:
943             assert(false);
944             break;
945     }
946 
947     return freq;
948 }
949 
950 /* Get Systick Clk */
951 /*! brief  Return Frequency of SystickClock
952  *  return Frequency of Systick Clock
953  */
CLOCK_GetSystickClkFreq(uint32_t id)954 uint32_t CLOCK_GetSystickClkFreq(uint32_t id)
955 {
956     volatile uint32_t *pSystickClkDiv;
957     pSystickClkDiv = &(SYSCON->SYSTICKCLKDIV0);
958     uint32_t freq  = 0U;
959 
960     switch (SYSCON->SYSTICKCLKSELX[id])
961     {
962         case 0U:
963             freq = CLOCK_GetCoreSysClkFreq() / ((((volatile uint32_t *)pSystickClkDiv)[(uint32_t)id] & 0xffU) + 1U);
964             break;
965         case 1U:
966             freq = CLOCK_GetFro1MFreq();
967             break;
968         case 2U:
969             freq = CLOCK_GetOsc32KFreq();
970             break;
971         case 7U:
972             freq = 0U;
973             break;
974 
975         default:
976             freq = 0U;
977             break;
978     }
979 
980     return freq;
981 }
982 
983 /* Set FlexComm Clock */
984 /**
985  * brief   Set the flexcomm output frequency.
986  * param   id      : flexcomm instance id
987  *          freq    : output frequency
988  * return  0   : the frequency range is out of range.
989  *          1   : switch successfully.
990  */
CLOCK_SetFlexCommClock(uint32_t id,uint32_t freq)991 uint32_t CLOCK_SetFlexCommClock(uint32_t id, uint32_t freq)
992 {
993     uint32_t input = CLOCK_GetFlexCommClkFreq(id);
994     uint32_t mul;
995 
996     if ((freq > 48000000UL) || (freq > input) || (input / freq >= 2UL))
997     {
998         /* FRG output frequency should be less than equal to 48MHz */
999         return 0UL;
1000     }
1001     else
1002     {
1003         mul                      = (uint32_t)((((uint64_t)input - freq) * 256ULL) / ((uint64_t)freq));
1004         SYSCON->FLEXFRGXCTRL[id] = (mul << 8U) | 0xFFU;
1005         return 1UL;
1006     }
1007 }
1008 
1009 /* Get IP Clk */
1010 /*! brief  Return Frequency of selected clock
1011  *  return Frequency of selected clock
1012  */
CLOCK_GetFreq(clock_name_t clockName)1013 uint32_t CLOCK_GetFreq(clock_name_t clockName)
1014 {
1015     uint32_t freq;
1016     switch (clockName)
1017     {
1018         case kCLOCK_CoreSysClk:
1019             freq = CLOCK_GetCoreSysClkFreq();
1020             break;
1021         case kCLOCK_BusClk:
1022             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
1023             break;
1024         case kCLOCK_ClockOut:
1025             freq = CLOCK_GetClockOutClkFreq();
1026             break;
1027         case kCLOCK_Pll1Out:
1028             freq = CLOCK_GetPll1OutFreq();
1029             break;
1030         case kCLOCK_Mclk:
1031             freq = CLOCK_GetMclkClkFreq();
1032             break;
1033         case kCLOCK_FroHf:
1034             freq = CLOCK_GetFroHfFreq();
1035             break;
1036         case kCLOCK_Fro12M:
1037             freq = CLOCK_GetFro12MFreq();
1038             break;
1039         case kCLOCK_ExtClk:
1040             freq = CLOCK_GetExtClkFreq();
1041             break;
1042         case kCLOCK_Pll0Out:
1043             freq = CLOCK_GetPll0OutFreq();
1044             break;
1045         case kCLOCK_FlexI2S:
1046             freq = CLOCK_GetI2SMClkFreq();
1047             break;
1048         default:
1049             freq = 0U;
1050             break;
1051     }
1052     return freq;
1053 }
1054 
1055 /* 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)1056 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
1057 {
1058     uint32_t seli, selp;
1059     /* bandwidth: compute selP from Multiplier */
1060     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1061     {
1062         selp = (M >> 2U) + 1U;
1063         if (selp >= 31U)
1064         {
1065             selp = 31U;
1066         }
1067         *pSelP = selp;
1068 
1069         if (M >= 8000UL)
1070         {
1071             seli = 1UL;
1072         }
1073         else if (M >= 122UL)
1074         {
1075             seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
1076         }
1077         else
1078         {
1079             seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1080         }
1081 
1082         if (seli >= 63UL)
1083         {
1084             seli = 63UL;
1085         }
1086         *pSelI = seli;
1087 
1088         *pSelR = 0U;
1089     }
1090     else
1091     {
1092         /* Note: If the spread spectrum mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
1093         *pSelP = 3U;
1094         *pSelI = 4U;
1095         *pSelR = 4U;
1096     }
1097 }
1098 
1099 /* Get predivider (N) from PLL0 NDEC setting */
findPll0PreDiv(void)1100 static uint32_t findPll0PreDiv(void)
1101 {
1102     uint32_t preDiv = 1UL;
1103 
1104     /* Direct input is not used? */
1105     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
1106     {
1107         preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
1108         if (preDiv == 0UL)
1109         {
1110             preDiv = 1UL;
1111         }
1112     }
1113     return preDiv;
1114 }
1115 
1116 /* Get predivider (N) from PLL1 NDEC setting */
findPll1PreDiv(void)1117 static uint32_t findPll1PreDiv(void)
1118 {
1119     uint32_t preDiv = 1UL;
1120 
1121     /* Direct input is not used? */
1122     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
1123     {
1124         preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
1125         if (preDiv == 0UL)
1126         {
1127             preDiv = 1UL;
1128         }
1129     }
1130     return preDiv;
1131 }
1132 
1133 /* Get postdivider (P) from PLL0 PDEC setting */
findPll0PostDiv(void)1134 static uint32_t findPll0PostDiv(void)
1135 {
1136     uint32_t postDiv = 1UL;
1137 
1138     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1139     {
1140         if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1141         {
1142             postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
1143         }
1144         else
1145         {
1146             postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
1147         }
1148         if (postDiv == 0UL)
1149         {
1150             postDiv = 2UL;
1151         }
1152     }
1153     return postDiv;
1154 }
1155 
1156 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)1157 static float findPll0MMult(void)
1158 {
1159     float mMult = 1.0F;
1160     float mMult_fract;
1161     uint32_t mMult_int;
1162 
1163     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
1164     {
1165         mMult =
1166             (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
1167     }
1168     else
1169     {
1170         mMult_int   = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
1171         mMult_int   = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL0_SSCG_MD_INT_P);
1172         mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL0_SSCG_MD_FRACT_M) /
1173                        (float)(uint32_t)(1UL << PLL0_SSCG_MD_INT_P));
1174         mMult       = (float)mMult_int + mMult_fract;
1175     }
1176     if (0ULL == ((uint64_t)mMult))
1177     {
1178         mMult = 1.0F;
1179     }
1180     return mMult;
1181 }
1182 
1183 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1184 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1185 {
1186     uint32_t tmp;
1187 
1188     while (n != 0U)
1189     {
1190         tmp = n;
1191         n   = m % n;
1192         m   = tmp;
1193     }
1194 
1195     return m;
1196 }
1197 
1198 /*
1199  * Set PLL0 output based on desired output rate.
1200  * In this function, the it calculates the PLL0 setting for output frequency from input clock
1201  * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1202  * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1203  */
CLOCK_GetPll0ConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1204 static pll_error_t CLOCK_GetPll0ConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1205 {
1206     uint32_t nDivOutHz, fccoHz;
1207     uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1208     uint32_t pllDirectInput, pllDirectOutput;
1209     uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1210 
1211     /* Baseline parameters (no input or output dividers) */
1212     pllPreDivider   = 1U; /* 1 implies pre-divider will be disabled */
1213     pllPostDivider  = 1U; /* 1 implies post-divider will be disabled */
1214     pllDirectOutput = 1U;
1215 
1216     /* Verify output rate parameter */
1217     if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1218     {
1219         /* Maximum PLL output with post divider=1 cannot go above this frequency */
1220         return kStatus_PLL_OutputTooHigh;
1221     }
1222     if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1223     {
1224         /* Minmum PLL output with maximum post divider cannot go below this frequency */
1225         return kStatus_PLL_OutputTooLow;
1226     }
1227 
1228     /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
1229     if (useSS)
1230     {
1231         /* Verify input rate parameter */
1232         if (finHz < PLL_MIN_IN_SSMODE)
1233         {
1234             /* Input clock into the PLL cannot be lower than this */
1235             return kStatus_PLL_InputTooLow;
1236         }
1237         /* PLL input in SS mode must be under 20MHz */
1238         if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
1239         {
1240             return kStatus_PLL_InputTooHigh;
1241         }
1242     }
1243     else
1244     {
1245         /* Verify input rate parameter */
1246         if (finHz < PLL_LOWER_IN_LIMIT)
1247         {
1248             /* Input clock into the PLL cannot be lower than this */
1249             return kStatus_PLL_InputTooLow;
1250         }
1251         if (finHz > PLL_HIGHER_IN_LIMIT)
1252         {
1253             /* Input clock into the PLL cannot be higher than this */
1254             return kStatus_PLL_InputTooHigh;
1255         }
1256     }
1257 
1258     /* Find the optimal CCO frequency for the output and input that
1259        will keep it inside the PLL CCO range. This may require
1260        tweaking the post-divider for the PLL. */
1261     fccoHz = foutHz;
1262     while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1263     {
1264         /* CCO output is less than minimum CCO range, so the CCO output
1265            needs to be bumped up and the post-divider is used to bring
1266            the PLL output back down. */
1267         pllPostDivider++;
1268         if (pllPostDivider > PVALMAX)
1269         {
1270             return kStatus_PLL_OutsideIntLimit;
1271         }
1272 
1273         /* Target CCO goes up, PLL output goes down */
1274         /* divide-by-2 divider in the post-divider is always work*/
1275         fccoHz          = foutHz * (pllPostDivider * 2U);
1276         pllDirectOutput = 0U;
1277     }
1278 
1279     /* Determine if a pre-divider is needed to get the best frequency */
1280     if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
1281     {
1282         uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
1283 
1284         if (a > PLL_LOWER_IN_LIMIT)
1285         {
1286             a = finHz / a;
1287             if ((a != 0U) && (a < PLL_MAX_N_DIV))
1288             {
1289                 pllPreDivider = a;
1290             }
1291         }
1292     }
1293 
1294     /* Bypass pre-divider hardware if pre-divider is 1 */
1295     if (pllPreDivider > 1U)
1296     {
1297         pllDirectInput = 0U;
1298     }
1299     else
1300     {
1301         pllDirectInput = 1U;
1302     }
1303 
1304     /* Determine PLL multipler */
1305     nDivOutHz     = (finHz / pllPreDivider);
1306     pllMultiplier = (fccoHz / nDivOutHz);
1307 
1308     /* Find optimal values for filter */
1309     if (useSS == false)
1310     {
1311         /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1312         if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1313         {
1314             pllMultiplier++;
1315         }
1316 
1317         /* Setup filtering */
1318         pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1319         uplimoff = 0U;
1320 
1321         /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1322         pSetup->pllsscg[1] =
1323             (uint32_t)((PLL_SSCG1_MDEC_VAL_SET(pllMultiplier)) | (1UL << SYSCON_PLL0SSCG1_SEL_EXT_SHIFT));
1324     }
1325     else
1326     {
1327         uint64_t fc;
1328 
1329         /* Filtering will be handled by SSC */
1330         pllSelR  = 0U;
1331         pllSelI  = 0U;
1332         pllSelP  = 0U;
1333         uplimoff = 1U;
1334 
1335         /* The PLL multiplier will get very close and slightly under the
1336            desired target frequency. A small fractional component can be
1337            added to fine tune the frequency upwards to the target. */
1338         fc = (((uint64_t)fccoHz % (uint64_t)nDivOutHz) << 25U) / nDivOutHz;
1339 
1340         /* Set multiplier */
1341         pSetup->pllsscg[0] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) | PLL0_SSCG_MD_FRACT_SET((uint32_t)fc));
1342         pSetup->pllsscg[1] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) >> 32U);
1343     }
1344 
1345     /* Get encoded values for N (prediv) and P (postdiv) */
1346     pSetup->pllndec = PLL_NDEC_VAL_SET(pllPreDivider);
1347     pSetup->pllpdec = PLL_PDEC_VAL_SET(pllPostDivider);
1348 
1349     /* PLL control */
1350     pSetup->pllctrl = (pllSelR << SYSCON_PLL0CTRL_SELR_SHIFT) |                  /* Filter coefficient */
1351                       (pllSelI << SYSCON_PLL0CTRL_SELI_SHIFT) |                  /* Filter coefficient */
1352                       (pllSelP << SYSCON_PLL0CTRL_SELP_SHIFT) |                  /* Filter coefficient */
1353                       (0UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT) |                 /* PLL bypass mode disabled */
1354                       (uplimoff << SYSCON_PLL0CTRL_LIMUPOFF_SHIFT) |             /* SS/fractional mode disabled */
1355                       (pllDirectInput << SYSCON_PLL0CTRL_BYPASSPREDIV_SHIFT) |   /* Bypass pre-divider? */
1356                       (pllDirectOutput << SYSCON_PLL0CTRL_BYPASSPOSTDIV_SHIFT) | /* Bypass post-divider? */
1357                       (1UL << SYSCON_PLL0CTRL_CLKEN_SHIFT);                      /* Ensure the PLL clock output */
1358 
1359     return kStatus_PLL_Success;
1360 }
1361 
1362 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1363 /* Alloct the static buffer for cache. */
1364 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1365 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]  = {0};
1366 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1367 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]      = {false};
1368 static uint32_t s_PllSetupCacheIdx                                  = 0U;
1369 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1370 
1371 /*
1372  * Calculate the PLL setting values from input clock freq to output freq.
1373  */
CLOCK_GetPll0Config(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1374 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1375 {
1376     pll_error_t retErr;
1377 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1378     uint32_t i;
1379 
1380     for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1381     {
1382         if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
1383         {
1384             /* Hit the target in cache buffer. */
1385             pSetup->pllctrl    = s_PllSetupCacheStruct[i].pllctrl;
1386             pSetup->pllndec    = s_PllSetupCacheStruct[i].pllndec;
1387             pSetup->pllpdec    = s_PllSetupCacheStruct[i].pllpdec;
1388             pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
1389             pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
1390             retErr             = kStatus_PLL_Success;
1391             break;
1392         }
1393     }
1394 
1395     if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1396     {
1397         return retErr;
1398     }
1399 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1400 
1401     retErr = CLOCK_GetPll0ConfigInternal(finHz, foutHz, pSetup, useSS);
1402 
1403 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1404     /* Cache the most recent calulation result into buffer. */
1405     s_FinHzCache[s_PllSetupCacheIdx]  = finHz;
1406     s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1407     s_UseSSCache[s_PllSetupCacheIdx]  = useSS;
1408 
1409     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl    = pSetup->pllctrl;
1410     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec    = pSetup->pllndec;
1411     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec    = pSetup->pllpdec;
1412     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
1413     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
1414     /* Update the index for next available buffer. */
1415     s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1416 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1417 
1418     return retErr;
1419 }
1420 
1421 /* Update local PLL rate variable */
CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t * pSetup)1422 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup)
1423 {
1424     s_Pll0_Freq = CLOCK_GetPLL0OutFromSetup(pSetup);
1425 }
1426 
1427 /* Return System PLL input clock rate */
1428 /*! brief    Return  PLL0 input clock rate
1429  *  return    PLL0 input clock rate
1430  */
CLOCK_GetPLL0InClockRate(void)1431 uint32_t CLOCK_GetPLL0InClockRate(void)
1432 {
1433     uint32_t clkRate = 0U;
1434 
1435     switch ((SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK))
1436     {
1437         case 0x00U:
1438             clkRate = CLK_FRO_12MHZ;
1439             break;
1440 
1441         case 0x01U:
1442             clkRate = CLOCK_GetExtClkFreq();
1443             break;
1444 
1445         case 0x02U:
1446             clkRate = CLOCK_GetFro1MFreq();
1447             break;
1448 
1449         case 0x03U:
1450             clkRate = CLOCK_GetOsc32KFreq();
1451             break;
1452 
1453         default:
1454             clkRate = 0U;
1455             break;
1456     }
1457 
1458     return clkRate;
1459 }
1460 
1461 /* Return PLL1 input clock rate */
CLOCK_GetPLL1InClockRate(void)1462 uint32_t CLOCK_GetPLL1InClockRate(void)
1463 {
1464     uint32_t clkRate = 0U;
1465 
1466     switch ((SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK))
1467     {
1468         case 0x00U:
1469             clkRate = CLK_FRO_12MHZ;
1470             break;
1471 
1472         case 0x01U:
1473             clkRate = CLOCK_GetExtClkFreq();
1474             break;
1475 
1476         case 0x02U:
1477             clkRate = CLOCK_GetFro1MFreq();
1478             break;
1479 
1480         case 0x03U:
1481             clkRate = CLOCK_GetOsc32KFreq();
1482             break;
1483 
1484         default:
1485             clkRate = 0U;
1486             break;
1487     }
1488 
1489     return clkRate;
1490 }
1491 
1492 /* Return PLL0 output clock rate from setup structure */
1493 /*! brief    Return PLL0 output clock rate from setup structure
1494  *  param    pSetup : Pointer to a PLL setup structure
1495  *  return   PLL0 output clock rate the setup structure will generate
1496  */
CLOCK_GetPLL0OutFromSetup(pll_setup_t * pSetup)1497 uint32_t CLOCK_GetPLL0OutFromSetup(pll_setup_t *pSetup)
1498 {
1499     uint32_t clkRate = 0;
1500     uint32_t prediv, postdiv;
1501     float workRate = 0.0F;
1502 
1503     /* Get the input clock frequency of PLL. */
1504     clkRate = CLOCK_GetPLL0InClockRate();
1505 
1506     if (((pSetup->pllctrl & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) &&
1507         ((pSetup->pllctrl & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) &&
1508         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) &&
1509         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
1510     {
1511         prediv  = findPll0PreDiv();
1512         postdiv = findPll0PostDiv();
1513         /* Adjust input clock */
1514         clkRate = clkRate / prediv;
1515         /* MDEC used for rate */
1516         workRate = (float)clkRate * (float)findPll0MMult();
1517         workRate /= (float)postdiv;
1518     }
1519 
1520     return (uint32_t)workRate;
1521 }
1522 
1523 /* Set the current PLL0 Rate */
1524 /*! brief Store the current PLL rate
1525  *  param    rate: Current rate of the PLL
1526  *  return   Nothing
1527  **/
CLOCK_SetStoredPLL0ClockRate(uint32_t rate)1528 void CLOCK_SetStoredPLL0ClockRate(uint32_t rate)
1529 {
1530     s_Pll0_Freq = rate;
1531 }
1532 
1533 /* Return PLL0 output clock rate */
1534 /*! brief    Return  PLL0 output clock rate
1535  *  param    recompute   : Forces a PLL rate recomputation if true
1536  *  return    PLL0 output clock rate
1537  *  note The PLL rate is cached in the driver in a variable as
1538  *  the rate computation function can take some time to perform. It
1539  *  is recommended to use 'false' with the 'recompute' parameter.
1540  */
CLOCK_GetPLL0OutClockRate(bool recompute)1541 uint32_t CLOCK_GetPLL0OutClockRate(bool recompute)
1542 {
1543     pll_setup_t Setup;
1544     uint32_t rate;
1545 
1546     if ((recompute) || (s_Pll0_Freq == 0U))
1547     {
1548         Setup.pllctrl    = SYSCON->PLL0CTRL;
1549         Setup.pllndec    = SYSCON->PLL0NDEC;
1550         Setup.pllpdec    = SYSCON->PLL0PDEC;
1551         Setup.pllsscg[0] = SYSCON->PLL0SSCG0;
1552         Setup.pllsscg[1] = SYSCON->PLL0SSCG1;
1553 
1554         CLOCK_GetPLL0OutFromSetupUpdate(&Setup);
1555     }
1556 
1557     rate = s_Pll0_Freq;
1558 
1559     return rate;
1560 }
1561 
1562 /* Set PLL0 output based on the passed PLL setup data */
1563 /*! brief    Set PLL output based on the passed PLL setup data
1564  *  param    pControl    : Pointer to populated PLL control structure to generate setup with
1565  *  param    pSetup      : Pointer to PLL setup structure to be filled
1566  *  return   PLL_ERROR_SUCCESS on success, or PLL setup error code
1567  *  note Actual frequency for setup may vary from the desired frequency based on the
1568  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1569  */
CLOCK_SetupPLL0Data(pll_config_t * pControl,pll_setup_t * pSetup)1570 pll_error_t CLOCK_SetupPLL0Data(pll_config_t *pControl, pll_setup_t *pSetup)
1571 {
1572     uint32_t inRate;
1573     bool useSS = ((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0U);
1574 
1575     pll_error_t pllError;
1576 
1577     /* Determine input rate for the PLL */
1578     if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)
1579     {
1580         inRate = pControl->inputRate;
1581     }
1582     else
1583     {
1584         inRate = CLOCK_GetPLL0InClockRate();
1585     }
1586 
1587     /* PLL flag options */
1588     pllError = CLOCK_GetPll0Config(inRate, pControl->desiredRate, pSetup, useSS);
1589     if ((useSS) && (pllError == kStatus_PLL_Success))
1590     {
1591         /* If using SS mode, then some tweaks are made to the generated setup */
1592         pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
1593         if (pControl->mfDither)
1594         {
1595             pSetup->pllsscg[1] |= (1UL << SYSCON_PLL0SSCG1_DITHER_SHIFT);
1596         }
1597     }
1598 
1599     return pllError;
1600 }
1601 
1602 /* Set PLL0 output from PLL setup structure */
1603 /*! brief    Set PLL output from PLL setup structure (precise frequency)
1604  * param pSetup  : Pointer to populated PLL setup structure
1605  * param flagcfg : Flag configuration for PLL config structure
1606  * return    PLL_ERROR_SUCCESS on success, or PLL setup error code
1607  * note  This function will power off the PLL, setup the PLL with the
1608  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1609  * and adjust system voltages to the new PLL rate. The function will not
1610  * alter any source clocks (ie, main systen clock) that may use the PLL,
1611  * so these should be setup prior to and after exiting the function.
1612  */
CLOCK_SetupPLL0Prec(pll_setup_t * pSetup,uint32_t flagcfg)1613 pll_error_t CLOCK_SetupPLL0Prec(pll_setup_t *pSetup, uint32_t flagcfg)
1614 {
1615     uint32_t inRate, clkRate, prediv;
1616     uint32_t pll_lock_wait_time     = 0U;
1617     uint32_t max_pll_lock_wait_time = 0U;
1618     /* Power off PLL during setup changes */
1619     POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1620     POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1621 
1622     pSetup->flags = flagcfg;
1623 
1624     /* Write PLL setup data */
1625     SYSCON->PLL0CTRL  = pSetup->pllctrl;
1626     SYSCON->PLL0NDEC  = pSetup->pllndec;
1627     SYSCON->PLL0NDEC  = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1628     SYSCON->PLL0PDEC  = pSetup->pllpdec;
1629     SYSCON->PLL0PDEC  = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1630     SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1631     SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1632     SYSCON->PLL0SSCG1 =
1633         pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT); /* latch */
1634 
1635     POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1636     POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1637 
1638     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1639     {
1640         if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1641         {
1642             inRate = CLOCK_GetPLL0InClockRate();
1643             prediv = findPll0PreDiv();
1644             /* Adjust input clock */
1645             clkRate = inRate / prediv;
1646 
1647             /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is stable.
1648                The lock bit could be used to shorten the wait time when freq<20MHZ */
1649             max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1650 
1651             if (clkRate < 20000000UL)
1652             {
1653                 pll_lock_wait_time = 0U;
1654                 while ((CLOCK_IsPLL0Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1655                 {
1656                     pll_lock_wait_time += 100U;
1657                     SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1658                 }
1659             }
1660             else
1661             {
1662                 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1663             }
1664         }
1665         else /* spread spectrum mode */
1666         {
1667             SDK_DelayAtLeastUs(6000U,
1668                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1669                                                                            to insure the PLL will be stable */
1670         }
1671     }
1672 
1673     /* Update current programmed PLL rate var */
1674     CLOCK_GetPLL0OutFromSetupUpdate(pSetup);
1675 
1676     /* System voltage adjustment, occurs prior to setting main system clock */
1677     if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0U)
1678     {
1679         POWER_SetVoltageForFreq(s_Pll0_Freq);
1680     }
1681 
1682     return kStatus_PLL_Success;
1683 }
1684 
1685 /* Setup PLL Frequency from pre-calculated value */
1686 /**
1687  * brief Set PLL0 output from PLL setup structure (precise frequency)
1688  * param pSetup  : Pointer to populated PLL setup structure
1689  * return    kStatus_PLL_Success on success, or PLL setup error code
1690  * note  This function will power off the PLL, setup the PLL with the
1691  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1692  * and adjust system voltages to the new PLL rate. The function will not
1693  * alter any source clocks (ie, main systen clock) that may use the PLL,
1694  * so these should be setup prior to and after exiting the function.
1695  */
CLOCK_SetPLL0Freq(const pll_setup_t * pSetup)1696 pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
1697 {
1698     uint32_t inRate, clkRate, prediv;
1699     uint32_t pll_lock_wait_time     = 0U;
1700     uint32_t max_pll_lock_wait_time = 0U;
1701     /* Power off PLL during setup changes */
1702     POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1703     POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1704 
1705     /* Write PLL setup data */
1706     SYSCON->PLL0CTRL  = pSetup->pllctrl;
1707     SYSCON->PLL0NDEC  = pSetup->pllndec;
1708     SYSCON->PLL0NDEC  = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1709     SYSCON->PLL0PDEC  = pSetup->pllpdec;
1710     SYSCON->PLL0PDEC  = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1711     SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1712     SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1713     SYSCON->PLL0SSCG1 =
1714         pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* latch */
1715 
1716     POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1717     POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1718 
1719     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1720     {
1721         if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1722         {
1723             inRate = CLOCK_GetPLL0InClockRate();
1724             prediv = findPll0PreDiv();
1725             /* Adjust input clock */
1726             clkRate = inRate / prediv;
1727 
1728             /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is
1729                stable. The lock bit could be used to shorten the wait time when freq<20MHZ */
1730             max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1731 
1732             if (clkRate < 20000000UL)
1733             {
1734                 pll_lock_wait_time = 0U;
1735                 while ((CLOCK_IsPLL0Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1736                 {
1737                     pll_lock_wait_time += 100U;
1738                     SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1739                 }
1740             }
1741             else
1742             {
1743                 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1744             }
1745         }
1746         else /* spread spectrum mode */
1747         {
1748             SDK_DelayAtLeastUs(6000U,
1749                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1750                                                                            to insure the PLL will be stable */
1751         }
1752     }
1753 
1754     /* Update current programmed PLL rate var */
1755     s_Pll0_Freq = pSetup->pllRate;
1756 
1757     return kStatus_PLL_Success;
1758 }
1759 
1760 /* Setup PLL1 Frequency from pre-calculated value */
1761 /**
1762  * brief Set PLL1 output from PLL setup structure (precise frequency)
1763  * param pSetup  : Pointer to populated PLL setup structure
1764  * return    kStatus_PLL_Success on success, or PLL setup error code
1765  * note  This function will power off the PLL, setup the PLL with the
1766  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1767  * and adjust system voltages to the new PLL rate. The function will not
1768  * alter any source clocks (ie, main systen clock) that may use the PLL,
1769  * so these should be setup prior to and after exiting the function.
1770  */
CLOCK_SetPLL1Freq(const pll_setup_t * pSetup)1771 pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
1772 {
1773     uint32_t inRate, clkRate, prediv;
1774     uint32_t pll_lock_wait_time     = 0U;
1775     uint32_t max_pll_lock_wait_time = 0U;
1776     /* Power off PLL during setup changes */
1777     POWER_EnablePD(kPDRUNCFG_PD_PLL1);
1778 
1779     /* Write PLL setup data */
1780     SYSCON->PLL1CTRL = pSetup->pllctrl;
1781     SYSCON->PLL1NDEC = pSetup->pllndec;
1782     SYSCON->PLL1NDEC = pSetup->pllndec | (1UL << SYSCON_PLL1NDEC_NREQ_SHIFT); /* latch */
1783     SYSCON->PLL1PDEC = pSetup->pllpdec;
1784     SYSCON->PLL1PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL1PDEC_PREQ_SHIFT); /* latch */
1785     SYSCON->PLL1MDEC = pSetup->pllmdec;
1786     SYSCON->PLL1MDEC = pSetup->pllmdec | (1UL << SYSCON_PLL1MDEC_MREQ_SHIFT); /* latch */
1787 
1788     POWER_DisablePD(kPDRUNCFG_PD_PLL1);
1789 
1790     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1791     {
1792         inRate = CLOCK_GetPLL1InClockRate();
1793         prediv = findPll1PreDiv();
1794         /* Adjust input clock */
1795         clkRate = inRate / prediv;
1796 
1797         /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is stable.
1798            The lock bit could be used to shorten the wait time when freq<20MHZ */
1799         max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1800 
1801         if (clkRate < 20000000UL)
1802         {
1803             pll_lock_wait_time = 0U;
1804             while ((CLOCK_IsPLL1Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1805             {
1806                 pll_lock_wait_time += 100U;
1807                 SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1808             }
1809         }
1810         else
1811         {
1812             SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1813         }
1814     }
1815 
1816     /* Update current programmed PLL rate var */
1817     s_Pll1_Freq = pSetup->pllRate;
1818 
1819     return kStatus_PLL_Success;
1820 }
1821 
1822 /* Set PLL0 clock based on the input frequency and multiplier */
1823 /*! brief    Set PLL0 output based on the multiplier and input frequency
1824  * param multiply_by : multiplier
1825  * param input_freq  : Clock input frequency of the PLL
1826  * return    Nothing
1827  * note  Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
1828  * function does not disable or enable PLL power, wait for PLL lock,
1829  * or adjust system voltages. These must be done in the application.
1830  * The function will not alter any source clocks (ie, main systen clock)
1831  * that may use the PLL, so these should be setup prior to and after
1832  * exiting the function.
1833  */
CLOCK_SetupPLL0Mult(uint32_t multiply_by,uint32_t input_freq)1834 void CLOCK_SetupPLL0Mult(uint32_t multiply_by, uint32_t input_freq)
1835 {
1836     uint32_t cco_freq = input_freq * multiply_by;
1837     uint32_t pdec     = 1U;
1838     uint32_t selr;
1839     uint32_t seli;
1840     uint32_t selp;
1841     uint32_t mdec, ndec;
1842 
1843     while (cco_freq < 275000000U)
1844     {
1845         multiply_by <<= 1U; /* double value in each iteration */
1846         pdec <<= 1U;        /* correspondingly double pdec to cancel effect of double msel */
1847         cco_freq = input_freq * multiply_by;
1848     }
1849 
1850     selr = 0U;
1851 
1852     if (multiply_by >= 8000UL)
1853     {
1854         seli = 1UL;
1855     }
1856     else if (multiply_by >= 122UL)
1857     {
1858         seli = (uint32_t)(8000UL / multiply_by); /*floor(8000/M) */
1859     }
1860     else
1861     {
1862         seli = 2UL * ((uint32_t)(multiply_by / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1863     }
1864 
1865     if (seli >= 63U)
1866     {
1867         seli = 63U;
1868     }
1869 
1870     {
1871         selp = 31U;
1872     }
1873 
1874     if (pdec > 1U)
1875     {
1876         pdec = pdec / 2U; /* Account for minus 1 encoding */
1877                           /* Translate P value */
1878     }
1879 
1880     mdec = (uint32_t)PLL_SSCG1_MDEC_VAL_SET(multiply_by);
1881     ndec = 0x1U; /* pre divide by 1 (hardcoded) */
1882 
1883     SYSCON->PLL0CTRL = SYSCON_PLL0CTRL_CLKEN_MASK | SYSCON_PLL0CTRL_BYPASSPOSTDIV(0) |
1884                        SYSCON_PLL0CTRL_BYPASSPOSTDIV2(0) | (selr << SYSCON_PLL0CTRL_SELR_SHIFT) |
1885                        (seli << SYSCON_PLL0CTRL_SELI_SHIFT) | (selp << SYSCON_PLL0CTRL_SELP_SHIFT);
1886     SYSCON->PLL0PDEC = pdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* set Pdec value and assert preq */
1887     SYSCON->PLL0NDEC = ndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* set Pdec value and assert preq */
1888     SYSCON->PLL0SSCG1 =
1889         mdec | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* select non sscg MDEC value, assert mreq and select mdec value */
1890 }
1891 
1892 /* Enable USB DEVICE FULL SPEED clock */
1893 /*! brief Enable USB Device FS clock.
1894  * param src : clock source
1895  * param freq: clock frequency
1896  * Enable USB Device Full Speed clock.
1897  */
CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src,uint32_t freq)1898 bool CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src, uint32_t freq)
1899 {
1900     bool ret = true;
1901 
1902     CLOCK_DisableClock(kCLOCK_Usbd0);
1903 
1904     if (kCLOCK_UsbfsSrcFro == src)
1905     {
1906         switch (freq)
1907         {
1908             case 96000000U:
1909                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
1910                 break;
1911 
1912             default:
1913                 ret = false;
1914                 break;
1915         }
1916         /* Turn ON FRO HF */
1917         POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
1918         /* Enable FRO 96MHz output */
1919         ANACTRL->FRO192M_CTRL =
1920             ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK | ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK;
1921         /* Select FRO 96 or 48 MHz */
1922         CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
1923     }
1924     else
1925     {
1926         /*!< Configure XTAL32M */
1927         POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);                                /* Ensure XTAL32M is powered */
1928         POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);                               /* Ensure XTAL32M is powered */
1929         (void)CLOCK_SetupExtClocking(16000000U);                              /* Enable clk_in clock */
1930         SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;               /* Enable clk_in from XTAL32M clock  */
1931         ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system  */
1932 
1933         /*!< Set up PLL1 */
1934         POWER_DisablePD(kPDRUNCFG_PD_PLL1);
1935         CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
1936         const pll_setup_t pll1Setup = {
1937             .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
1938             .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
1939             .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
1940             .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
1941             .pllRate = 48000000U,
1942             .flags   = PLL_SETUPFLAG_WAITLOCK};
1943         (void)CLOCK_SetPLL1Freq(&pll1Setup);
1944 
1945         CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
1946         CLOCK_AttachClk(kPLL1_to_USB0_CLK);
1947         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1948     }
1949     CLOCK_EnableClock(kCLOCK_Usbd0);
1950     CLOCK_EnableClock(kCLOCK_UsbRam1);
1951 
1952     return ret;
1953 }
1954 
1955 /* Enable USB HOST FULL SPEED clock */
1956 /*! brief Enable USB HOST FS clock.
1957  * param src : clock source
1958  * param freq: clock frequency
1959  * Enable USB HOST Full Speed clock.
1960  */
CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src,uint32_t freq)1961 bool CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src, uint32_t freq)
1962 {
1963     bool ret = true;
1964 
1965     CLOCK_DisableClock(kCLOCK_Usbhmr0);
1966     CLOCK_DisableClock(kCLOCK_Usbhsl0);
1967 
1968     if (kCLOCK_UsbfsSrcFro == src)
1969     {
1970         switch (freq)
1971         {
1972             case 96000000U:
1973                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
1974                 break;
1975 
1976             default:
1977                 ret = false;
1978                 break;
1979         }
1980         /* Turn ON FRO HF */
1981         POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
1982         /* Enable FRO 96MHz output */
1983         ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
1984         /* Select FRO 96 MHz */
1985         CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
1986     }
1987     else
1988     {
1989         /*!< Configure XTAL32M */
1990         POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);                                /* Ensure XTAL32M is powered */
1991         POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);                               /* Ensure XTAL32M is powered */
1992         (void)CLOCK_SetupExtClocking(16000000U);                              /* Enable clk_in clock */
1993         SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;               /* Enable clk_in from XTAL32M clock  */
1994         ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system  */
1995 
1996         /*!< Set up PLL1 */
1997         POWER_DisablePD(kPDRUNCFG_PD_PLL1);
1998         CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
1999         const pll_setup_t pll1Setup = {
2000             .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
2001             .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
2002             .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
2003             .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
2004             .pllRate = 48000000U,
2005             .flags   = PLL_SETUPFLAG_WAITLOCK};
2006         (void)CLOCK_SetPLL1Freq(&pll1Setup);
2007 
2008         CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2009         CLOCK_AttachClk(kPLL1_to_USB0_CLK);
2010         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2011     }
2012     CLOCK_EnableClock(kCLOCK_Usbhmr0);
2013     CLOCK_EnableClock(kCLOCK_Usbhsl0);
2014     CLOCK_EnableClock(kCLOCK_UsbRam1);
2015 
2016     return ret;
2017 }
2018 
2019 /* Enable USB PHY clock */
CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src,uint32_t freq)2020 bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
2021 {
2022     volatile uint32_t i;
2023     uint32_t phyPllDiv  = 0U;
2024     uint16_t multiplier = 0U;
2025     bool ret            = true;
2026 
2027     POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);
2028     POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);
2029     POWER_DisablePD(kPDRUNCFG_PD_FRO32K);   /*!< Ensure FRO32k is on  */
2030     POWER_DisablePD(kPDRUNCFG_PD_XTAL32K);  /*!< Ensure xtal32k is on  */
2031     POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /*!< Ensure xtal32k is on  */
2032     POWER_DisablePD(kPDRUNCFG_PD_LDOUSBHS); /*!< Ensure xtal32k is on  */
2033 
2034     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL(1);
2035     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_PHY(1);
2036 
2037     /* wait to make sure PHY power is fully up */
2038     i = 100000U;
2039     while ((i--) != 0U)
2040     {
2041         __ASM("nop");
2042     }
2043 
2044     USBPHY->CTRL_CLR = USBPHY_CTRL_SFTRST_MASK;
2045 
2046     multiplier = (uint16_t)(480000000UL / freq);
2047 
2048     switch (multiplier)
2049     {
2050         case 15U:
2051         {
2052             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
2053             break;
2054         }
2055         case 16U:
2056         {
2057             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
2058             break;
2059         }
2060         case 20U:
2061         {
2062             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
2063             break;
2064         }
2065         case 24U:
2066         {
2067             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U);
2068             break;
2069         }
2070         case 25U:
2071         {
2072             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U);
2073             break;
2074         }
2075         case 30U:
2076         {
2077             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U);
2078             break;
2079         }
2080         case 40U:
2081         {
2082             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(7U);
2083             break;
2084         }
2085         default:
2086         {
2087             ret = false;
2088             break;
2089         }
2090     }
2091 
2092     if (ret)
2093     {
2094         USBPHY->PLL_SIC     = (USBPHY->PLL_SIC & ~USBPHY_PLL_SIC_PLL_DIV_SEL(0x7)) | phyPllDiv;
2095         USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_REG_ENABLE_MASK;
2096         USBPHY->PLL_SIC_CLR = (1UL << 16U); // Reserved. User must set this bit to 0x0
2097         USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_POWER_MASK;
2098         USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_EN_USB_CLKS_MASK;
2099 
2100         USBPHY->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK;
2101     }
2102 
2103     return ret;
2104 }
2105 
2106 /* Enable USB DEVICE HIGH SPEED clock */
CLOCK_EnableUsbhs0DeviceClock(clock_usbhs_src_t src,uint32_t freq)2107 bool CLOCK_EnableUsbhs0DeviceClock(clock_usbhs_src_t src, uint32_t freq)
2108 {
2109     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_RAM(1);
2110     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_DEV(1);
2111 
2112     /* 16 MHz will be driven by the tb on the xtal1 pin of XTAL32M */
2113     SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clock_in clock for clock module. */
2114     ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT(1);
2115     return true;
2116 }
2117 
2118 /* Enable USB HOST HIGH SPEED clock */
CLOCK_EnableUsbhs0HostClock(clock_usbhs_src_t src,uint32_t freq)2119 bool CLOCK_EnableUsbhs0HostClock(clock_usbhs_src_t src, uint32_t freq)
2120 {
2121     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_RAM(1);
2122     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_HOST(1);
2123 
2124     /* 16 MHz will be driven by the tb on the xtal1 pin of XTAL32M */
2125     SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clock_in clock for clock module. */
2126     ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT(1);
2127 
2128     return true;
2129 }
2130 
2131 /*! @brief Enable the OSTIMER 32k clock.
2132  *  @return  Nothing
2133  */
CLOCK_EnableOstimer32kClock(void)2134 void CLOCK_EnableOstimer32kClock(void)
2135 {
2136     PMC->OSTIMERr |= PMC_OSTIMER_CLOCKENABLE_MASK;
2137 }
2138