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