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 /* Peripheral FLASH_NMPA base address */
59 #define FLASH_NMPA_BASE (0x3FC00u)
60 /* Return values from Config (N-2) page of flash */
61 #define GET_HFXO_TRIM()  (*(uint32_t *)(FLASH_NMPA_BASE + 0xC0U)) // (0x3FCC0)
62 #define GET_32KXO_TRIM() (*(uint32_t *)(FLASH_NMPA_BASE + 0xC4U)) // (0x3FCC4)
63 
64 #define XO_SLAVE_EN (1)
65 
66 /* Saved value of PLL output rate, computed whenever needed to save run-time
67    computation on each call to retrive the PLL rate. */
68 static uint32_t s_Pll0_Freq;
69 static uint32_t s_Pll1_Freq;
70 
71 /** External clock rate on the CLKIN pin in Hz. If not used,
72     set this to 0. Otherwise, set it to the exact rate in Hz this pin is
73     being driven at. */
74 static uint32_t s_Ext_Clk_Freq  = 16000000U;
75 static uint32_t s_I2S_Mclk_Freq = 0U;
76 
77 /*******************************************************************************
78  * Variables
79  ******************************************************************************/
80 
81 /*******************************************************************************
82  * Prototypes
83  ******************************************************************************/
84 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
85 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
86 /* Get predivider (N) from PLL0 NDEC setting */
87 static uint32_t findPll0PreDiv(void);
88 /* Get predivider (N) from PLL1 NDEC setting */
89 static uint32_t findPll1PreDiv(void);
90 /* Get postdivider (P) from PLL0 PDEC setting */
91 static uint32_t findPll0PostDiv(void);
92 /* Get postdivider (P) from PLL1 PDEC setting. */
93 static uint32_t findPll1PostDiv(void);
94 /* Get multiplier (M) from PLL0 MDEC and SSCG settings */
95 static float findPll0MMult(void);
96 /* Get multiplier (M) from PLL1 MDEC. */
97 static uint32_t findPll1MMult(void);
98 /* Get the greatest common divisor */
99 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
100 /* Set PLL output based on desired output rate */
101 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
102 /* Update local PLL rate variable */
103 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup);
104 /* Update local PLL1 rate variable */
105 static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup);
106 /* Compensate for discontinuity in the capacitor banks */
107 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity);
108 /* Enables and sets LDO for High Frequency crystal oscillator */
109 static void CLOCK_SetXtalHfLdo(void);
110 
111 /*******************************************************************************
112  * Code
113  ******************************************************************************/
114 
115 /* Clock Selection for IP */
116 /**
117  * brief   Configure the clock selection muxes.
118  * param   connection  : Clock to be configured.
119  * return  Nothing
120  */
CLOCK_AttachClk(clock_attach_id_t connection)121 void CLOCK_AttachClk(clock_attach_id_t connection)
122 {
123     uint16_t mux;
124     uint8_t sel;
125     uint16_t item;
126     uint32_t tmp32 = (uint32_t)connection;
127     uint32_t i;
128     volatile uint32_t *pClkSel;
129 
130     pClkSel = &(SYSCON->SYSTICKCLKSEL0);
131 
132     if (kNONE_to_NONE != connection)
133     {
134         for (i = 0U; i < 2U; i++)
135         {
136             if (tmp32 == 0U)
137             {
138                 break;
139             }
140             item = (uint16_t)GET_ID_ITEM(tmp32);
141             if (item != 0U)
142             {
143                 mux = (uint16_t)GET_ID_ITEM_MUX(item);
144                 sel = (uint8_t)GET_ID_ITEM_SEL(item);
145                 if (mux == CM_RTCOSC32KCLKSEL)
146                 {
147                     PMC->RTCOSC32K = (PMC->RTCOSC32K & ~PMC_RTCOSC32K_SEL_MASK) | PMC_RTCOSC32K_SEL(sel);
148                 }
149                 else if (mux == CM_OSTIMERCLKSEL)
150                 {
151                     PMC->OSEVENTTIMER =
152                         (PMC->OSEVENTTIMER & ~PMC_OSEVENTTIMER_SELCLOCK_MASK) | PMC_OSEVENTTIMER_SELCLOCK(sel);
153                 }
154                 else
155                 {
156                     ((volatile uint32_t *)pClkSel)[mux] = sel;
157                 }
158             }
159             tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
160         }
161     }
162 }
163 
164 /* Return the actual clock attach id */
165 /**
166  * brief   Get the actual clock attach id.
167  * This fuction uses the offset in input attach id, then it reads the actual source value in
168  * the register and combine the offset to obtain an actual attach id.
169  * param   attachId  : Clock attach id to get.
170  * return  Clock source value.
171  */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)172 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
173 {
174     uint16_t mux;
175     uint32_t actualSel;
176     uint32_t tmp32 = (uint32_t)attachId;
177     uint32_t i;
178     uint32_t actualAttachId = 0U;
179     uint32_t selector       = GET_ID_SELECTOR(tmp32);
180     volatile uint32_t *pClkSel;
181 
182     pClkSel = &(SYSCON->SYSTICKCLKSEL0);
183 
184     if (kNONE_to_NONE == attachId)
185     {
186         return kNONE_to_NONE;
187     }
188 
189     for (i = 0U; i < 2U; i++)
190     {
191         mux = (uint16_t)GET_ID_ITEM_MUX(tmp32);
192         if (tmp32 != 0UL)
193         {
194             if (mux == CM_RTCOSC32KCLKSEL)
195             {
196                 actualSel = ((PMC->RTCOSC32K) & PMC_RTCOSC32K_SEL_MASK) >> PMC_RTCOSC32K_SEL_SHIFT;
197             }
198             else if (mux == CM_OSTIMERCLKSEL)
199             {
200                 actualSel = ((PMC->OSEVENTTIMER) & PMC_OSEVENTTIMER_SELCLOCK_MASK) >> PMC_OSEVENTTIMER_SELCLOCK_SHIFT;
201             }
202             else
203             {
204                 actualSel = (uint32_t)((volatile uint32_t *)pClkSel)[mux];
205             }
206 
207             /* Consider the combination of two registers */
208             actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
209         }
210         tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!<  pick up next descriptor */
211     }
212 
213     actualAttachId |= selector;
214 
215     return (clock_attach_id_t)actualAttachId;
216 }
217 
218 /* Set IP Clock Divider */
219 /**
220  * brief   Setup peripheral clock dividers.
221  * param   div_name    : Clock divider name
222  * param divided_by_value: Value to be divided
223  * param reset :  Whether to reset the divider counter.
224  * return  Nothing
225  */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)226 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
227 {
228     volatile uint32_t *pClkDiv;
229 
230     pClkDiv = &(SYSCON->SYSTICKCLKDIV[0]);
231     if ((div_name >= kCLOCK_DivFlexFrg0) && (div_name <= kCLOCK_DivFlexFrg7))
232     {
233         /*!<  Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1+ MULT /DIV), DIV = 0xFF */
234         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] =
235             SYSCON_FRGCTRL_DIV_MASK | SYSCON_FRGCTRL_MULT(divided_by_value);
236     }
237     else
238     {
239         if (reset)
240         {
241             ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = 1UL << 29U;
242         }
243         if (divided_by_value == 0U) /*!<  halt */
244         {
245             ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = 1UL << 30U;
246         }
247         else
248         {
249             ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = (divided_by_value - 1U);
250         }
251     }
252 }
253 
254 /* Set FRO Clocking */
255 /**
256  * brief   Initialize the Core clock to given frequency (12, 48 or 96 MHz).
257  * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
258  * enabled.
259  * param   iFreq   : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
260  * return  returns success or fail status.
261  */
CLOCK_SetupFROClocking(uint32_t iFreq)262 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
263 {
264     if ((iFreq != 12000000U) && (iFreq != 96000000U))
265     {
266         return kStatus_Fail;
267     }
268     /* Enable Analog Control module */
269     SYSCON->PRESETCTRLCLR[2] = SYSCON_PRESETCTRL2_ANACTRL_RST_MASK;
270     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL_MASK;
271 
272     /* Initialize FRO192 trim */
273     CLOCK_FroHfTrim();
274 
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  */
300 typedef struct
301 {
302     uint32_t waitstate;
303     uint32_t freqMax;
304 } WaitStateInterval_t;
305 
306 /* clang-format off */
307 /* Wait state if frequency is inferior to the one specified */
308 static const WaitStateInterval_t IntervalList[] = {
309     {0, 11000000},
310     {1, 22000000},
311     {2, 33000000},
312     {3, 44000000},
313     {4, 55000000},
314     {5, 66000000},
315     {6, 77000000},
316     {7, 88000000},
317     {8, 100000000},
318     {9, 115000000},
319     {10, 130000000},
320     {11, 150000000} /* Maximum allowed frequency (150 MHz) */
321 };
322 /* clang-format on */
323 
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)324 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)
325 {
326     /* Flash Controller & FMC internal number of Wait States (minus 1) */
327     uint32_t num_wait_states      = 15UL; /* Default to the maximum number of wait states */
328     uint32_t prefetch_enable_mask = SYSCON->FMCCR & SYSCON_FMCCR_PREFEN_MASK;
329 
330     for (size_t cnt = 0; cnt < (sizeof(IntervalList) / sizeof(WaitStateInterval_t)); cnt++)
331     {
332         if (system_freq_hz <= IntervalList[cnt].freqMax)
333         {
334             num_wait_states = IntervalList[cnt].waitstate;
335             break;
336         }
337     }
338 
339     /* Adjust FMC waiting time cycles (num_wait_states) */
340     SYSCON->FMCCR = (SYSCON->FMCCR & 0xFFFF0FFFUL) | ((num_wait_states & 0xFUL) << 12UL);
341 
342     /*The prefetch bit must be disabled before any flash commands*/
343     SYSCON->FMCCR &= ~SYSCON_FMCCR_PREFEN_MASK;
344 
345     FLASH->INTSTAT_CLR = 0xF; /* Clear all status flags */
346 
347     FLASH->DATAW[0] = (FLASH->DATAW[0] & 0xFFFFFFF0UL) | (num_wait_states & 0xFUL);
348 
349     FLASH->CMD = 0x2; /* CMD_SET_READ_MODE */
350 
351     /* Wait until the cmd is completed (without error) */
352     while ((FLASH->INTSTAT & FLASH_INTSTAT_DONE_MASK) == 0UL)
353     {
354     }
355 
356     /* restore prefetch enable */
357     SYSCON->FMCCR |= prefetch_enable_mask;
358 }
359 
360 /* Set EXT OSC Clk */
361 /**
362  * brief   Initialize the external osc clock to given frequency.
363  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
364  * return  returns success or fail status.
365  */
CLOCK_SetupExtClocking(uint32_t iFreq)366 status_t CLOCK_SetupExtClocking(uint32_t iFreq)
367 {
368     if (iFreq >= 32000000U)
369     {
370         return kStatus_Fail;
371     }
372     /* Turn on power for crystal 32 MHz */
373     POWER_DisablePD(kPDRUNCFG_PD_XTALHF);
374     POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF);
375     /* Enable clock_in clock for clock module. */
376     SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;
377 
378     /* Wait for external osc clock to be valid. */
379     while((ANACTRL->XO32M_STATUS & ANACTRL_XO32M_STATUS_XO_READY_MASK) == 0U)
380     {
381     }
382 
383     s_Ext_Clk_Freq = iFreq;
384     return kStatus_Success;
385 }
386 
387 /* Set I2S MCLK Clk */
388 /**
389  * brief   Initialize the I2S MCLK clock to given frequency.
390  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
391  * return  returns success or fail status.
392  */
CLOCK_SetupI2SMClkClocking(uint32_t iFreq)393 status_t CLOCK_SetupI2SMClkClocking(uint32_t iFreq)
394 {
395     s_I2S_Mclk_Freq = iFreq;
396     return kStatus_Success;
397 }
398 
399 /* Get CLOCK OUT Clk */
400 /*! brief  Return Frequency of ClockOut
401  *  return Frequency of ClockOut
402  */
CLOCK_GetClockOutClkFreq(void)403 uint32_t CLOCK_GetClockOutClkFreq(void)
404 {
405     uint32_t freq = 0U;
406 
407     switch (SYSCON->CLKOUTSEL)
408     {
409         case 0U:
410             freq = CLOCK_GetCoreSysClkFreq();
411             break;
412 
413         case 1U:
414             freq = CLOCK_GetPll0OutFreq();
415             break;
416 
417         case 2U:
418             freq = CLOCK_GetExtClkFreq();
419             break;
420 
421         case 3U:
422             freq = CLOCK_GetFroHfFreq();
423             break;
424 
425         case 4U:
426             freq = CLOCK_GetFro1MFreq();
427             break;
428 
429         case 5U:
430             freq = CLOCK_GetPll1OutFreq();
431             break;
432 
433         case 6U:
434             freq = CLOCK_GetOsc32KFreq();
435             break;
436 
437         case 7U:
438             freq = 0U;
439             break;
440 
441         default:
442             freq = 0U;
443             break;
444     }
445     return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
446 }
447 
448 /* Get CAN Clk */
449 /*! brief  Return Frequency of Can Clock
450  *  return Frequency of Can.
451  */
CLOCK_GetMCanClkFreq(void)452 uint32_t CLOCK_GetMCanClkFreq(void)
453 {
454     uint32_t freq = 0U;
455 
456     switch (SYSCON->CANCLKSEL)
457     {
458         case 0U:
459             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CANCLKDIV & SYSCON_CANCLKDIV_DIV_MASK) + 1U);
460             break;
461         case 1U:
462             freq = CLOCK_GetFro1MFreq();
463             break;
464         case 2U:
465             freq = CLOCK_GetOsc32KFreq();
466             break;
467         case 7U:
468             freq = 0U;
469             break;
470 
471         default:
472             freq = 0U;
473             break;
474     }
475 
476     return freq;
477 }
478 
479 /* Get ADC Clk */
480 /*! brief  Return Frequency of Adc Clock
481  *  return Frequency of Adc.
482  */
CLOCK_GetAdcClkFreq(uint32_t id)483 uint32_t CLOCK_GetAdcClkFreq(uint32_t id)
484 {
485     uint32_t freq = 0U;
486     uint32_t div  = 0U;
487 
488     switch ((id == 0U) ? (SYSCON->ADC0CLKSEL) : (SYSCON->ADC1CLKSEL))
489     {
490         case 0U:
491             freq = CLOCK_GetCoreSysClkFreq();
492             break;
493         case 1U:
494             freq = CLOCK_GetPll0OutFreq();
495             break;
496         case 2U:
497             freq = CLOCK_GetFroHfFreq();
498             break;
499         default:
500             freq = 0U;
501             break;
502     }
503 
504     div = ((id == 0U) ? ((SYSCON->ADC0CLKDIV & SYSCON_ADC0CLKDIV_DIV_MASK) + 1U) :
505                        ((SYSCON->ADC1CLKDIV & SYSCON_ADC1CLKDIV_DIV_MASK) + 1U));
506 
507     return freq / div;
508 }
509 
510 /* Get USB0 Clk */
511 /*! brief  Return Frequency of Usb0 Clock
512  *  return Frequency of Usb0 Clock.
513  */
CLOCK_GetUsb0ClkFreq(void)514 uint32_t CLOCK_GetUsb0ClkFreq(void)
515 {
516     uint32_t freq = 0U;
517 
518     switch (SYSCON->USB0CLKSEL)
519     {
520         case 0U:
521             freq = CLOCK_GetCoreSysClkFreq();
522             break;
523         case 1U:
524             freq = CLOCK_GetPll0OutFreq();
525             break;
526         case 3U:
527             freq = CLOCK_GetFroHfFreq();
528             break;
529         case 5U:
530             freq = CLOCK_GetPll1OutFreq();
531             break;
532         case 7U:
533             freq = 0U;
534             break;
535 
536         default:
537             freq = 0U;
538             break;
539     }
540 
541     return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
542 }
543 
544 /* Get MCLK Clk */
545 /*! brief  Return Frequency of MClk Clock
546  *  return Frequency of MClk Clock.
547  */
CLOCK_GetMclkClkFreq(void)548 uint32_t CLOCK_GetMclkClkFreq(void)
549 {
550     uint32_t freq = 0U;
551 
552     switch (SYSCON->MCLKCLKSEL)
553     {
554         case 0U:
555             freq = CLOCK_GetFroHfFreq();
556             break;
557         case 1U:
558             freq = CLOCK_GetPll0OutFreq();
559             break;
560         case 7U:
561             freq = 0U;
562             break;
563 
564         default:
565             freq = 0U;
566             break;
567     }
568 
569     return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
570 }
571 
572 /* Get SCTIMER Clk */
573 /*! brief  Return Frequency of SCTimer Clock
574  *  return Frequency of SCTimer Clock.
575  */
CLOCK_GetSctClkFreq(void)576 uint32_t CLOCK_GetSctClkFreq(void)
577 {
578     uint32_t freq = 0U;
579 
580     switch (SYSCON->SCTCLKSEL)
581     {
582         case 0U:
583             freq = CLOCK_GetCoreSysClkFreq();
584             break;
585         case 1U:
586             freq = CLOCK_GetPll0OutFreq();
587             break;
588         case 2U:
589             freq = CLOCK_GetExtClkFreq();
590             break;
591         case 3U:
592             freq = CLOCK_GetFroHfFreq();
593             break;
594         case 4U:
595             freq = CLOCK_GetPll1OutFreq();
596             break;
597         case 5U:
598             freq = CLOCK_GetI2SMClkFreq();
599             break;
600         case 7U:
601             freq = 0U;
602             break;
603 
604         default:
605             freq = 0U;
606             break;
607     }
608 
609     return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
610 }
611 
612 /* Get FRO 12M Clk */
613 /*! brief  Return Frequency of FRO 12MHz
614  *  return Frequency of FRO 12MHz
615  */
CLOCK_GetFro12MFreq(void)616 uint32_t CLOCK_GetFro12MFreq(void)
617 {
618     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
619 }
620 
621 /* Get FRO 1M Clk */
622 /*! brief  Return Frequency of FRO 1MHz
623  *  return Frequency of FRO 1MHz
624  */
CLOCK_GetFro1MFreq(void)625 uint32_t CLOCK_GetFro1MFreq(void)
626 {
627     return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
628 }
629 
630 /* Get EXT OSC Clk */
631 /*! brief  Return Frequency of External Clock
632  *  return Frequency of External Clock. If no external clock is used returns 0.
633  */
CLOCK_GetExtClkFreq(void)634 uint32_t CLOCK_GetExtClkFreq(void)
635 {
636     return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
637 }
638 
639 /* Get WATCH DOG Clk */
640 /*! brief  Return Frequency of Watchdog
641  *  return Frequency of Watchdog
642  */
CLOCK_GetWdtClkFreq(void)643 uint32_t CLOCK_GetWdtClkFreq(void)
644 {
645     return CLOCK_GetFro1MFreq() / ((SYSCON->WDTCLKDIV & SYSCON_WDTCLKDIV_DIV_MASK) + 1U);
646 }
647 
648 /* Get HF FRO Clk */
649 /*! brief  Return Frequency of High-Freq output of FRO
650  *  return Frequency of High-Freq output of FRO
651  */
CLOCK_GetFroHfFreq(void)652 uint32_t CLOCK_GetFroHfFreq(void)
653 {
654     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
655 }
656 
657 /* Get SYSTEM PLL Clk */
658 /*! brief  Return Frequency of PLL
659  *  return Frequency of PLL
660  */
CLOCK_GetPll0OutFreq(void)661 uint32_t CLOCK_GetPll0OutFreq(void)
662 {
663     return s_Pll0_Freq;
664 }
665 
666 /* Get USB PLL Clk */
667 /*! brief  Return Frequency of USB PLL
668  *  return Frequency of PLL
669  */
CLOCK_GetPll1OutFreq(void)670 uint32_t CLOCK_GetPll1OutFreq(void)
671 {
672     return s_Pll1_Freq;
673 }
674 
675 /* Get RTC OSC Clk */
676 /*! brief  Return Frequency of 32kHz osc
677  *  return Frequency of 32kHz osc
678  */
CLOCK_GetOsc32KFreq(void)679 uint32_t CLOCK_GetOsc32KFreq(void)
680 {
681     return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
682             (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
683                CLK_RTC_32K_CLK :
684                ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
685                 ((PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK) != 0UL)) ?
686                CLK_RTC_32K_CLK :
687                0UL;
688 }
689 
690 /* Get Flexcomm 32K Clk */
691 /*! brief  Return Frequency of Flexcomm 32kHz
692  *  return Frequency of Flexcomm 32kHz
693  */
CLOCK_GetFC32KFreq(void)694 uint32_t CLOCK_GetFC32KFreq(void)
695 {
696     return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
697             (0UL == (SYSCON->FC32KCLKSEL & SYSCON_FC32KCLKSEL_FC32KCLKSEL_MASK))) ?
698                CLK_RTC_32K_CLK :
699                ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
700                 ((SYSCON->FC32KCLKSEL & SYSCON_FC32KCLKSEL_FC32KCLKSEL_MASK) != 0UL)) ?
701                CLK_RTC_32K_CLK :
702                0UL;
703 }
704 
705 /* Get MAIN Clk */
706 /*! brief  Return Frequency of Core System
707  *  return Frequency of Core System
708  */
CLOCK_GetCoreSysClkFreq(void)709 uint32_t CLOCK_GetCoreSysClkFreq(void)
710 {
711     uint32_t freq = 0U;
712 
713     switch (SYSCON->MAINCLKSELB)
714     {
715         case 0U:
716             if (SYSCON->MAINCLKSELA == 0U)
717             {
718                 freq = CLOCK_GetFro12MFreq();
719             }
720             else if (SYSCON->MAINCLKSELA == 1U)
721             {
722                 freq = CLOCK_GetExtClkFreq();
723             }
724             else if (SYSCON->MAINCLKSELA == 2U)
725             {
726                 freq = CLOCK_GetFro1MFreq();
727             }
728             else if (SYSCON->MAINCLKSELA == 3U)
729             {
730                 freq = CLOCK_GetFroHfFreq();
731             }
732             else
733             {
734                 /* Added comments to avoid the violation of MISRA C-2012 rule 15.7 */
735             }
736             break;
737         case 1U:
738             freq = CLOCK_GetPll0OutFreq();
739             break;
740         case 2U:
741             freq = CLOCK_GetPll1OutFreq();
742             break;
743 
744         case 3U:
745             freq = CLOCK_GetOsc32KFreq();
746             break;
747 
748         default:
749             freq = 0U;
750             break;
751     }
752 
753     return freq;
754 }
755 
756 /* Get I2S MCLK Clk */
757 /*! brief  Return Frequency of I2S MCLK Clock
758  *  return Frequency of I2S MCLK Clock
759  */
CLOCK_GetI2SMClkFreq(void)760 uint32_t CLOCK_GetI2SMClkFreq(void)
761 {
762     return s_I2S_Mclk_Freq;
763 }
764 
765 /* Get PLLClkDiv Clk */
CLOCK_GetPllClkDivFreq(void)766 uint32_t CLOCK_GetPllClkDivFreq(void)
767 {
768     uint32_t freq = 0U;
769 
770     switch (SYSCON->PLLCLKDIVSEL)
771     {
772         case 0U:
773             freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLLCLKDIV & SYSCON_PLLCLKDIV_DIV_MASK) + 1U);
774             break;
775         case 1U:
776             freq = CLOCK_GetPll1OutFreq() /
777                    ((SYSCON->PLLCLKDIV & SYSCON_PLLCLKDIV_DIV_MASK) + 1U); // register name should be checked
778             break;
779         default:
780             freq = 0U;
781             break;
782     }
783     /* todo: pll_clk_div = pll_clk/div*/
784     return freq;
785 }
786 
787 /* Get FRG Clk */
CLOCK_GetFrgFreq(uint32_t id)788 uint32_t CLOCK_GetFrgFreq(uint32_t id)
789 {
790     uint32_t freq = 0U;
791 
792     switch (SYSCON->FRGCLKSEL[id])
793     {
794         case 0U:
795             freq = CLOCK_GetCoreSysClkFreq();
796             break;
797         case 1U:
798             freq = CLOCK_GetPllClkDivFreq();
799             break;
800         case 2U:
801             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
802             break;
803         default:
804             freq = 0U;
805             break;
806     }
807     return (uint32_t)(((uint64_t)freq * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /
808                       ((SYSCON_FRGCTRL_DIV_MASK + 1U) +
809                        ((SYSCON->FRGCTRL[id] & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));
810 }
811 
812 /* Get FLEXCOMM Clk */
CLOCK_GetFlexCommClkFreq(uint32_t id)813 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
814 {
815     uint32_t freq = 0U;
816 
817     switch (SYSCON->FCCLKSEL[id])
818     {
819         case 0U:
820             freq = CLOCK_GetCoreSysClkFreq();
821             break;
822         case 1U:
823             freq = CLOCK_GetFrgFreq(id);
824             break;
825         case 2U:
826             freq = CLOCK_GetFro12MFreq();
827             break;
828         case 3U:
829             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
830             break;
831         case 4U:
832             freq = CLOCK_GetFro1MFreq();
833             break;
834         case 5U:
835             freq = CLOCK_GetI2SMClkFreq();
836             break;
837         case 6U:
838             freq = CLOCK_GetOsc32KFreq();
839             break;
840         case 7U:
841             freq = 0U;
842             break;
843 
844         default:
845             freq = 0U;
846             break;
847     }
848 
849     return freq / ((SYSCON->FLEXCOMMCLKDIV[id] & 0xffU) + 1U);
850 }
851 
852 /* Get HS_LPSI Clk */
CLOCK_GetHsLspiClkFreq(void)853 uint32_t CLOCK_GetHsLspiClkFreq(void)
854 {
855     uint32_t freq = 0U;
856 
857     switch (SYSCON->HSSPICLKSEL)
858     {
859         case 0U:
860             freq = CLOCK_GetCoreSysClkFreq();
861             break;
862         case 1U:
863             freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLLCLKDIV & 0xffU) + 1U);
864             break;
865         case 2U:
866             freq = CLOCK_GetFro12MFreq();
867             break;
868         case 3U:
869             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
870             break;
871         case 4U:
872             freq = CLOCK_GetFro1MFreq();
873             break;
874         case 6U:
875             freq = CLOCK_GetOsc32KFreq();
876             break;
877         case 7U:
878             freq = 0U;
879             break;
880 
881         default:
882             freq = 0U;
883             break;
884     }
885 
886     return freq;
887 }
888 
889 /* Get CTimer Clk */
890 /*! brief  Return Frequency of CTimer functional Clock
891  *  return Frequency of CTimer functional Clock
892  */
CLOCK_GetCTimerClkFreq(uint32_t id)893 uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
894 {
895     uint32_t freq = 0U;
896 
897     switch (SYSCON->CTIMERCLKSEL[id])
898     {
899         case 0U:
900             freq = CLOCK_GetCoreSysClkFreq();
901             break;
902         case 1U:
903             freq = CLOCK_GetPll0OutFreq();
904             break;
905         case 2U:
906             freq = CLOCK_GetPll1OutFreq();
907             break;
908         case 3U:
909             freq = CLOCK_GetFroHfFreq();
910             break;
911         case 4U:
912             freq = CLOCK_GetFro1MFreq();
913             break;
914         case 5U:
915             freq = CLOCK_GetI2SMClkFreq();
916             break;
917         case 6U:
918             freq = CLOCK_GetOsc32KFreq();
919             break;
920         case 7U:
921             freq = 0U;
922             break;
923 
924         default:
925             freq = 0U;
926             break;
927     }
928 
929     return freq / ((SYSCON->CTIMERCLKDIV[id] & 0xffU) + 1U);
930 }
931 
932 /* Get Systick Clk */
933 /*! brief  Return Frequency of SystickClock
934  *  return Frequency of Systick Clock
935  */
CLOCK_GetSystickClkFreq(void)936 uint32_t CLOCK_GetSystickClkFreq(void)
937 {
938     uint32_t freq = 0U;
939 
940     switch (SYSCON->SYSTICKCLKSEL0)
941     {
942         case 0U:
943             /*Niobe4mini just has one SYSTICKSEL and SYSTICKDIV register, Fix coverity problem in this way temporarily
944              */
945             freq = CLOCK_GetCoreSysClkFreq() / (((SYSCON->SYSTICKCLKDIV[0]) & 0xffU) + 1U);
946             break;
947         case 1U:
948             freq = CLOCK_GetFro1MFreq();
949             break;
950         case 2U:
951             freq = CLOCK_GetOsc32KFreq();
952             break;
953         case 7U:
954             freq = 0U;
955             break;
956 
957         default:
958             freq = 0U;
959             break;
960     }
961 
962     return freq;
963 }
964 
965 /* Get DAC Clk */
966 /*! brief  Return Frequency of DAC Clock
967  *  return Frequency of DAC.
968  */
CLOCK_GetDacClkFreq(uint32_t id)969 uint32_t CLOCK_GetDacClkFreq(uint32_t id)
970 {
971     uint32_t freq = 0U;
972 
973     switch (SYSCON->DAC[id].CLKSEL)
974     {
975         case 0U:
976             freq = CLOCK_GetCoreSysClkFreq();
977             break;
978         case 1U:
979             freq = CLOCK_GetPll0OutFreq();
980             break;
981         case 3U:
982             freq = CLOCK_GetFroHfFreq();
983             break;
984         case 4U:
985             freq = CLOCK_GetFro12MFreq();
986             break;
987         case 5U:
988             freq = CLOCK_GetPll1OutFreq();
989             break;
990         case 6U:
991             freq = CLOCK_GetFro1MFreq();
992             break;
993         default:
994             freq = 0U;
995             break;
996     }
997 
998     return freq / ((SYSCON->DAC[id].CLKDIV & SYSCON_DAC_CLKDIV_DIV_MASK) + 1U);
999 }
1000 
1001 /* Get FlexSpi Clk */
1002 /*! brief  Return Frequency of FlexSpi clock
1003  *  return Frequency of FlexSpi Clock
1004  */
CLOCK_GetFlexSpiClkFreq(void)1005 uint32_t CLOCK_GetFlexSpiClkFreq(void)
1006 {
1007     uint32_t freq = 0U;
1008 
1009     switch (SYSCON->FLEXSPICLKSEL)
1010     {
1011         case 0U:
1012             freq = CLOCK_GetCoreSysClkFreq();
1013             break;
1014         case 1U:
1015             freq = CLOCK_GetPll0OutFreq();
1016             break;
1017         case 3U:
1018             freq = CLOCK_GetFroHfFreq();
1019             break;
1020         case 5U:
1021             freq = CLOCK_GetPll1OutFreq();
1022             break;
1023         case 7U:
1024             freq = 0U;
1025             break;
1026         default:
1027             freq = 0U;
1028             break;
1029     }
1030 
1031     return freq / ((SYSCON->FLEXSPICLKDIV & SYSCON_FLEXSPICLKDIV_DIV_MASK) + 1U);
1032 }
1033 
1034 /* Get DMIC Clk */
1035 /*! brief  Return Frequency of DMIC clock
1036  *  return Frequency of DMIC Clock
1037  */
CLOCK_GetDmicClkFreq(void)1038 uint32_t CLOCK_GetDmicClkFreq(void)
1039 {
1040     uint32_t freq = 0U;
1041 
1042     switch (SYSCON->DMICFCLKSEL)
1043     {
1044         case 0U:
1045             freq = CLOCK_GetCoreSysClkFreq();
1046             break;
1047         case 1U:
1048             freq = CLOCK_GetPll0OutFreq();
1049             break;
1050         case 2U:
1051             freq = CLOCK_GetExtClkFreq();
1052             break;
1053         case 3U:
1054             freq = CLOCK_GetFroHfFreq();
1055             break;
1056         case 4U:
1057             freq = CLOCK_GetPll1OutFreq();
1058             break;
1059         case 5U:
1060             freq = CLOCK_GetI2SMClkFreq();
1061             break;
1062         default:
1063             freq = 0U;
1064             break;
1065     }
1066 
1067     return freq / ((SYSCON->DMICFCLKDIV & SYSCON_DMICFCLKDIV_DIV_MASK) + 1U);
1068 }
1069 
1070 /* Get I3C function Clk */
1071 /*! brief  Return Frequency of I3C function clock
1072  *  return Frequency of I3C function Clock
1073  */
CLOCK_GetI3cClkFreq(void)1074 uint32_t CLOCK_GetI3cClkFreq(void)
1075 {
1076     uint32_t freq = 0U;
1077 
1078     switch (SYSCON->I3CFCLKSEL)
1079     {
1080         case 0U:
1081             freq = CLOCK_GetCoreSysClkFreq();
1082             break;
1083         case 1U:
1084             freq = CLOCK_GetPllClkDivFreq();
1085             break;
1086         default:
1087             freq = 0U;
1088             break;
1089     }
1090 
1091     return freq / ((SYSCON->I3CFCLKDIV & SYSCON_I3CFCLKDIV_DIV_MASK) + 1U);
1092 }
1093 
1094 /* Get I3C function slow TC Clk */
1095 /*! brief  Return Frequency of I3C function Slow TC clock
1096  *  return Frequency of I3C function slow TC Clock
1097  */
CLOCK_GetI3cSTCClkFreq(void)1098 uint32_t CLOCK_GetI3cSTCClkFreq(void)
1099 {
1100     uint32_t freq = 0U;
1101 
1102     switch (SYSCON->I3CFCLKSTCSEL)
1103     {
1104         case 0U:
1105             freq = CLOCK_GetI3cClkFreq();
1106             break;
1107         case 1U:
1108             freq = CLOCK_GetFro1MFreq();
1109             break;
1110         default:
1111             freq = 0U;
1112             break;
1113     }
1114 
1115     return freq / ((SYSCON->I3CFCLKSTCDIV & SYSCON_I3CFCLKSTCDIV_DIV_MASK) + 1U);
1116 }
1117 
1118 /* Get I3C function slow Clk */
1119 /*! brief  Return Frequency of I3C function Slow clock
1120  *  return Frequency of I3C function slow Clock
1121  */
CLOCK_GetI3cSClkFreq(void)1122 uint32_t CLOCK_GetI3cSClkFreq(void)
1123 {
1124     uint32_t freq = 0U;
1125 
1126     switch (SYSCON->I3CFCLKSSEL)
1127     {
1128         case 0U:
1129             freq = CLOCK_GetFro1MFreq();
1130             break;
1131         default:
1132             freq = 0U;
1133             break;
1134     }
1135 
1136     return freq / ((SYSCON->I3CFCLKSDIV & SYSCON_I3CFCLKSDIV_DIV_MASK) + 1U);
1137 }
1138 
1139 /* Get IP Clk */
1140 /*! brief  Return Frequency of selected clock
1141  *  return Frequency of selected clock
1142  */
CLOCK_GetFreq(clock_name_t clockName)1143 uint32_t CLOCK_GetFreq(clock_name_t clockName)
1144 {
1145     uint32_t freq;
1146     switch (clockName)
1147     {
1148         case kCLOCK_CoreSysClk:
1149             freq = CLOCK_GetCoreSysClkFreq();
1150             break;
1151         case kCLOCK_BusClk:
1152             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
1153             break;
1154         case kCLOCK_ClockOut:
1155             freq = CLOCK_GetClockOutClkFreq();
1156             break;
1157         case kCLOCK_Pll1Out:
1158             freq = CLOCK_GetPll1OutFreq();
1159             break;
1160         case kCLOCK_Mclk:
1161             freq = CLOCK_GetMclkClkFreq();
1162             break;
1163         case kCLOCK_FroHf:
1164             freq = CLOCK_GetFroHfFreq();
1165             break;
1166         case kCLOCK_Fro12M:
1167             freq = CLOCK_GetFro12MFreq();
1168             break;
1169         case kCLOCK_Fro1M:
1170             freq = CLOCK_GetFro1MFreq();
1171             break;
1172         case kCLOCK_ExtClk:
1173             freq = CLOCK_GetExtClkFreq();
1174             break;
1175         case kCLOCK_Pll0Out:
1176             freq = CLOCK_GetPll0OutFreq();
1177             break;
1178         case kCLOCK_FlexI2S:
1179             freq = CLOCK_GetI2SMClkFreq();
1180             break;
1181         default:
1182             freq = 0U;
1183             break;
1184     }
1185     return freq;
1186 }
1187 
1188 /* 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)1189 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
1190 {
1191     uint32_t seli, selp;
1192     /* bandwidth: compute selP from Multiplier */
1193     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1194     {
1195         selp = (M >> 2U) + 1U;
1196         if (selp >= 31U)
1197         {
1198             selp = 31U;
1199         }
1200         *pSelP = selp;
1201 
1202         if (M >= 8000UL)
1203         {
1204             seli = 1UL;
1205         }
1206         else if (M >= 122UL)
1207         {
1208             seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
1209         }
1210         else
1211         {
1212             seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1213         }
1214 
1215         if (seli >= 63UL)
1216         {
1217             seli = 63UL;
1218         }
1219         *pSelI = seli;
1220 
1221         *pSelR = 0UL;
1222     }
1223     else
1224     {
1225         /* Note: If the spread spectrum mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
1226         *pSelP = 3U;
1227         *pSelI = 4U;
1228         *pSelR = 4U;
1229     }
1230 }
1231 
1232 /* Get predivider (N) from PLL0 NDEC setting */
findPll0PreDiv(void)1233 static uint32_t findPll0PreDiv(void)
1234 {
1235     uint32_t preDiv = 1UL;
1236 
1237     /* Direct input is not used? */
1238     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
1239     {
1240         preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
1241         if (preDiv == 0UL)
1242         {
1243             preDiv = 1UL;
1244         }
1245     }
1246     return preDiv;
1247 }
1248 
1249 /* Get predivider (N) from PLL1 NDEC setting */
findPll1PreDiv(void)1250 static uint32_t findPll1PreDiv(void)
1251 {
1252     uint32_t preDiv = 1UL;
1253 
1254     /* Direct input is not used? */
1255     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
1256     {
1257         preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
1258         if (preDiv == 0UL)
1259         {
1260             preDiv = 1UL;
1261         }
1262     }
1263     return preDiv;
1264 }
1265 
1266 /* Get postdivider (P) from PLL0 PDEC setting */
findPll0PostDiv(void)1267 static uint32_t findPll0PostDiv(void)
1268 {
1269     uint32_t postDiv = 1UL;
1270 
1271     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1272     {
1273         if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1274         {
1275             postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
1276         }
1277         else
1278         {
1279             postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
1280         }
1281         if (postDiv == 0UL)
1282         {
1283             postDiv = 2UL;
1284         }
1285     }
1286     return postDiv;
1287 }
1288 
1289 /* Get postdivider (P) from PLL1 PDEC setting. */
findPll1PostDiv(void)1290 static uint32_t findPll1PostDiv(void)
1291 {
1292     uint32_t postDiv = 1UL;
1293 
1294     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1295     {
1296         if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1297         {
1298             postDiv = SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK;
1299         }
1300         else
1301         {
1302             postDiv = 2UL * (SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK);
1303         }
1304         if (postDiv == 0UL)
1305         {
1306             postDiv = 2UL;
1307         }
1308     }
1309 
1310     return postDiv;
1311 }
1312 
1313 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)1314 static float findPll0MMult(void)
1315 {
1316     float mMult = 1.0F;
1317     float mMult_fract;
1318     uint32_t mMult_int;
1319 
1320     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
1321     {
1322         mMult =
1323             (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
1324     }
1325     else
1326     {
1327         mMult_int   = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
1328         mMult_int   = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL0_SSCG_MD_INT_P);
1329         mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL0_SSCG_MD_FRACT_M) /
1330                        (float)(uint32_t)(1UL << PLL0_SSCG_MD_INT_P));
1331         mMult       = (float)mMult_int + mMult_fract;
1332     }
1333     if (0ULL == ((uint64_t)mMult))
1334     {
1335         mMult = 1.0F;
1336     }
1337     return mMult;
1338 }
1339 
1340 /* Get multiplier (M) from PLL1 MDEC. */
findPll1MMult(void)1341 static uint32_t findPll1MMult(void)
1342 {
1343     uint32_t mMult = 1UL;
1344 
1345     mMult = SYSCON->PLL1MDEC & SYSCON_PLL1MDEC_MDIV_MASK;
1346 
1347     if (mMult == 0UL)
1348     {
1349         mMult = 1UL;
1350     }
1351 
1352     return mMult;
1353 }
1354 
1355 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1356 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1357 {
1358     uint32_t tmp;
1359 
1360     while (n != 0U)
1361     {
1362         tmp = n;
1363         n   = m % n;
1364         m   = tmp;
1365     }
1366 
1367     return m;
1368 }
1369 
1370 /*
1371  * Set PLL0 output based on desired output rate.
1372  * In this function, the it calculates the PLL0 setting for output frequency from input clock
1373  * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1374  * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1375  */
CLOCK_GetPll0ConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1376 static pll_error_t CLOCK_GetPll0ConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1377 {
1378     uint32_t nDivOutHz, fccoHz;
1379     uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1380     uint32_t pllDirectInput, pllDirectOutput;
1381     uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1382 
1383     /* Baseline parameters (no input or output dividers) */
1384     pllPreDivider   = 1U; /* 1 implies pre-divider will be disabled */
1385     pllPostDivider  = 1U; /* 1 implies post-divider will be disabled */
1386     pllDirectOutput = 1U;
1387 
1388     /* Verify output rate parameter */
1389     if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1390     {
1391         /* Maximum PLL output with post divider=1 cannot go above this frequency */
1392         return kStatus_PLL_OutputTooHigh;
1393     }
1394     if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1395     {
1396         /* Minmum PLL output with maximum post divider cannot go below this frequency */
1397         return kStatus_PLL_OutputTooLow;
1398     }
1399 
1400     /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
1401     if (useSS)
1402     {
1403         /* Verify input rate parameter */
1404         if (finHz < PLL_MIN_IN_SSMODE)
1405         {
1406             /* Input clock into the PLL cannot be lower than this */
1407             return kStatus_PLL_InputTooLow;
1408         }
1409         /* PLL input in SS mode must be under 20MHz */
1410         if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
1411         {
1412             return kStatus_PLL_InputTooHigh;
1413         }
1414     }
1415     else
1416     {
1417         /* Verify input rate parameter */
1418         if (finHz < PLL_LOWER_IN_LIMIT)
1419         {
1420             /* Input clock into the PLL cannot be lower than this */
1421             return kStatus_PLL_InputTooLow;
1422         }
1423         if (finHz > PLL_HIGHER_IN_LIMIT)
1424         {
1425             /* Input clock into the PLL cannot be higher than this */
1426             return kStatus_PLL_InputTooHigh;
1427         }
1428     }
1429 
1430     /* Find the optimal CCO frequency for the output and input that
1431        will keep it inside the PLL CCO range. This may require
1432        tweaking the post-divider for the PLL. */
1433     fccoHz = foutHz;
1434     while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1435     {
1436         /* CCO output is less than minimum CCO range, so the CCO output
1437            needs to be bumped up and the post-divider is used to bring
1438            the PLL output back down. */
1439         pllPostDivider++;
1440         if (pllPostDivider > PVALMAX)
1441         {
1442             return kStatus_PLL_OutsideIntLimit;
1443         }
1444 
1445         /* Target CCO goes up, PLL output goes down */
1446         /* divide-by-2 divider in the post-divider is always work*/
1447         fccoHz          = foutHz * (pllPostDivider * 2U);
1448         pllDirectOutput = 0U;
1449     }
1450 
1451     /* Determine if a pre-divider is needed to get the best frequency */
1452     if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
1453     {
1454         uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
1455 
1456         if (a > PLL_LOWER_IN_LIMIT)
1457         {
1458             a = finHz / a;
1459             if ((a != 0U) && (a < PLL_MAX_N_DIV))
1460             {
1461                 pllPreDivider = a;
1462             }
1463         }
1464     }
1465 
1466     /* Bypass pre-divider hardware if pre-divider is 1 */
1467     if (pllPreDivider > 1U)
1468     {
1469         pllDirectInput = 0U;
1470     }
1471     else
1472     {
1473         pllDirectInput = 1U;
1474     }
1475 
1476     /* Determine PLL multipler */
1477     nDivOutHz     = (finHz / pllPreDivider);
1478     pllMultiplier = (fccoHz / nDivOutHz);
1479 
1480     /* Find optimal values for filter */
1481     if (useSS == false)
1482     {
1483         /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1484         if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1485         {
1486             pllMultiplier++;
1487         }
1488 
1489         /* Setup filtering */
1490         pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1491         uplimoff = 0U;
1492 
1493         /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1494         pSetup->pllsscg[1] =
1495             (uint32_t)((PLL_SSCG1_MDEC_VAL_SET(pllMultiplier)) | (1UL << SYSCON_PLL0SSCG1_SEL_EXT_SHIFT));
1496     }
1497     else
1498     {
1499         uint64_t fc;
1500 
1501         /* Filtering will be handled by SSC */
1502         pllSelR  = 0UL;
1503         pllSelI  = 0UL;
1504         pllSelP  = 0UL;
1505         uplimoff = 1U;
1506 
1507         /* The PLL multiplier will get very close and slightly under the
1508            desired target frequency. A small fractional component can be
1509            added to fine tune the frequency upwards to the target. */
1510         fc = ((uint64_t)(uint32_t)(fccoHz % nDivOutHz) << 25UL) / nDivOutHz;
1511 
1512         /* Set multiplier */
1513         pSetup->pllsscg[0] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) | PLL0_SSCG_MD_FRACT_SET((uint32_t)fc));
1514         pSetup->pllsscg[1] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) >> 32U);
1515     }
1516 
1517     /* Get encoded values for N (prediv) and P (postdiv) */
1518     pSetup->pllndec = PLL_NDEC_VAL_SET(pllPreDivider);
1519     pSetup->pllpdec = PLL_PDEC_VAL_SET(pllPostDivider);
1520 
1521     /* PLL control */
1522     pSetup->pllctrl = (pllSelR << SYSCON_PLL0CTRL_SELR_SHIFT) |                  /* Filter coefficient */
1523                       (pllSelI << SYSCON_PLL0CTRL_SELI_SHIFT) |                  /* Filter coefficient */
1524                       (pllSelP << SYSCON_PLL0CTRL_SELP_SHIFT) |                  /* Filter coefficient */
1525                       (0UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT) |                 /* PLL bypass mode disabled */
1526                       (uplimoff << SYSCON_PLL0CTRL_LIMUPOFF_SHIFT) |             /* SS/fractional mode disabled */
1527                       (pllDirectInput << SYSCON_PLL0CTRL_BYPASSPREDIV_SHIFT) |   /* Bypass pre-divider? */
1528                       (pllDirectOutput << SYSCON_PLL0CTRL_BYPASSPOSTDIV_SHIFT) | /* Bypass post-divider? */
1529                       (1UL << SYSCON_PLL0CTRL_CLKEN_SHIFT);                      /* Ensure the PLL clock output */
1530 
1531     return kStatus_PLL_Success;
1532 }
1533 
1534 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1535 /* Alloct the static buffer for cache. */
1536 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1537 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]  = {0};
1538 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1539 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]      = {false};
1540 static uint32_t s_PllSetupCacheIdx                                  = 0U;
1541 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1542 
1543 /*
1544  * Calculate the PLL setting values from input clock freq to output freq.
1545  */
CLOCK_GetPll0Config(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1546 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1547 {
1548     pll_error_t retErr;
1549 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1550     uint32_t i;
1551 
1552     for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1553     {
1554         if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
1555         {
1556             /* Hit the target in cache buffer. */
1557             pSetup->pllctrl    = s_PllSetupCacheStruct[i].pllctrl;
1558             pSetup->pllndec    = s_PllSetupCacheStruct[i].pllndec;
1559             pSetup->pllpdec    = s_PllSetupCacheStruct[i].pllpdec;
1560             pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
1561             pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
1562             retErr             = kStatus_PLL_Success;
1563             break;
1564         }
1565     }
1566 
1567     if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1568     {
1569         return retErr;
1570     }
1571 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1572 
1573     retErr = CLOCK_GetPll0ConfigInternal(finHz, foutHz, pSetup, useSS);
1574 
1575 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1576     /* Cache the most recent calulation result into buffer. */
1577     s_FinHzCache[s_PllSetupCacheIdx]  = finHz;
1578     s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1579     s_UseSSCache[s_PllSetupCacheIdx]  = useSS;
1580 
1581     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl    = pSetup->pllctrl;
1582     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec    = pSetup->pllndec;
1583     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec    = pSetup->pllpdec;
1584     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
1585     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
1586     /* Update the index for next available buffer. */
1587     s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1588 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1589 
1590     return retErr;
1591 }
1592 
1593 /* Update local PLL rate variable */
CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t * pSetup)1594 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup)
1595 {
1596     s_Pll0_Freq = CLOCK_GetPLL0OutFromSetup(pSetup);
1597 }
1598 
1599 /* Update local PLL1 rate variable */
CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t * pSetup)1600 static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup)
1601 {
1602     s_Pll1_Freq = CLOCK_GetPLL1OutFromSetup(pSetup);
1603 }
1604 
1605 /* Return System PLL input clock rate */
1606 /*! brief    Return  PLL0 input clock rate
1607  *  return    PLL0 input clock rate
1608  */
CLOCK_GetPLL0InClockRate(void)1609 uint32_t CLOCK_GetPLL0InClockRate(void)
1610 {
1611     uint32_t clkRate = 0U;
1612 
1613     switch ((SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK))
1614     {
1615         case 0x00U:
1616             clkRate = CLK_FRO_12MHZ;
1617             break;
1618 
1619         case 0x01U:
1620             clkRate = CLOCK_GetExtClkFreq();
1621             break;
1622 
1623         case 0x02U:
1624             clkRate = CLOCK_GetFro1MFreq();
1625             break;
1626 
1627         case 0x03U:
1628             clkRate = CLOCK_GetOsc32KFreq();
1629             break;
1630 
1631         default:
1632             clkRate = 0U;
1633             break;
1634     }
1635 
1636     return clkRate;
1637 }
1638 
1639 /* Return PLL1 input clock rate */
CLOCK_GetPLL1InClockRate(void)1640 uint32_t CLOCK_GetPLL1InClockRate(void)
1641 {
1642     uint32_t clkRate = 0U;
1643 
1644     switch ((SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK))
1645     {
1646         case 0x00U:
1647             clkRate = CLK_FRO_12MHZ;
1648             break;
1649 
1650         case 0x01U:
1651             clkRate = CLOCK_GetExtClkFreq();
1652             break;
1653 
1654         case 0x02U:
1655             clkRate = CLOCK_GetFro1MFreq();
1656             break;
1657 
1658         case 0x03U:
1659             clkRate = CLOCK_GetOsc32KFreq();
1660             break;
1661 
1662         default:
1663             clkRate = 0U;
1664             break;
1665     }
1666 
1667     return clkRate;
1668 }
1669 
1670 /* Return PLL0 output clock rate from setup structure */
1671 /*! brief    Return PLL0 output clock rate from setup structure
1672  *  param    pSetup : Pointer to a PLL setup structure
1673  *  return   PLL0 output clock rate the setup structure will generate
1674  */
CLOCK_GetPLL0OutFromSetup(pll_setup_t * pSetup)1675 uint32_t CLOCK_GetPLL0OutFromSetup(pll_setup_t *pSetup)
1676 {
1677     uint32_t clkRate = 0;
1678     uint32_t prediv, postdiv;
1679     float workRate = 0.0F;
1680 
1681     /* Get the input clock frequency of PLL. */
1682     clkRate = CLOCK_GetPLL0InClockRate();
1683 
1684     if (((pSetup->pllctrl & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) &&
1685         ((pSetup->pllctrl & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) &&
1686         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) &&
1687         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
1688     {
1689         prediv  = findPll0PreDiv();
1690         postdiv = findPll0PostDiv();
1691         /* Adjust input clock */
1692         clkRate = clkRate / prediv;
1693         /* MDEC used for rate */
1694         workRate = (float)clkRate * (float)findPll0MMult();
1695         workRate /= (float)postdiv;
1696     }
1697 
1698     return (uint32_t)workRate;
1699 }
1700 
1701 /* Return PLL1 output clock rate from setup structure */
1702 /*! brief    Return PLL1 output clock rate from setup structure
1703  *  param    pSetup : Pointer to a PLL setup structure
1704  *  return   PLL0 output clock rate the setup structure will generate
1705  */
CLOCK_GetPLL1OutFromSetup(pll_setup_t * pSetup)1706 uint32_t CLOCK_GetPLL1OutFromSetup(pll_setup_t *pSetup)
1707 {
1708     uint32_t clkRate = 0;
1709     uint32_t prediv, postdiv;
1710     uint32_t workRate = 0UL;
1711 
1712     /* Get the input clock frequency of PLL. */
1713     clkRate = CLOCK_GetPLL1InClockRate();
1714 
1715     if (((pSetup->pllctrl & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) &&
1716         ((pSetup->pllctrl & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) &&
1717         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL))
1718     {
1719         prediv  = findPll1PreDiv();
1720         postdiv = findPll1PostDiv();
1721         /* Adjust input clock */
1722         clkRate = clkRate / prediv;
1723         /* MDEC used for rate */
1724         workRate = clkRate * findPll1MMult();
1725         workRate /= postdiv;
1726     }
1727 
1728     return workRate;
1729 }
1730 
1731 /* Set the current PLL0 Rate */
1732 /*! brief Store the current PLL rate
1733  *  param    rate: Current rate of the PLL
1734  *  return   Nothing
1735  **/
CLOCK_SetStoredPLL0ClockRate(uint32_t rate)1736 void CLOCK_SetStoredPLL0ClockRate(uint32_t rate)
1737 {
1738     s_Pll0_Freq = rate;
1739 }
1740 
1741 /* Return PLL0 output clock rate */
1742 /*! brief    Return  PLL0 output clock rate
1743  *  param    recompute   : Forces a PLL rate recomputation if true
1744  *  return    PLL0 output clock rate
1745  *  note The PLL rate is cached in the driver in a variable as
1746  *  the rate computation function can take some time to perform. It
1747  *  is recommended to use 'false' with the 'recompute' parameter.
1748  */
CLOCK_GetPLL0OutClockRate(bool recompute)1749 uint32_t CLOCK_GetPLL0OutClockRate(bool recompute)
1750 {
1751     pll_setup_t Setup;
1752     uint32_t rate;
1753 
1754     if ((recompute) || (s_Pll0_Freq == 0U))
1755     {
1756         Setup.pllctrl    = SYSCON->PLL0CTRL;
1757         Setup.pllndec    = SYSCON->PLL0NDEC;
1758         Setup.pllpdec    = SYSCON->PLL0PDEC;
1759         Setup.pllsscg[0] = SYSCON->PLL0SSCG0;
1760         Setup.pllsscg[1] = SYSCON->PLL0SSCG1;
1761 
1762         CLOCK_GetPLL0OutFromSetupUpdate(&Setup);
1763     }
1764 
1765     rate = s_Pll0_Freq;
1766 
1767     return rate;
1768 }
1769 
1770 /*! brief    Return  PLL1 output clock rate
1771  *  param    recompute   : Forces a PLL rate recomputation if true
1772  *  return    PLL1 output clock rate
1773  *  note The PLL rate is cached in the driver in a variable as
1774  *  the rate computation function can take some time to perform. It
1775  *  is recommended to use 'false' with the 'recompute' parameter.
1776  */
CLOCK_GetPLL1OutClockRate(bool recompute)1777 uint32_t CLOCK_GetPLL1OutClockRate(bool recompute)
1778 {
1779     pll_setup_t Setup;
1780     uint32_t rate;
1781 
1782     if ((recompute) || (s_Pll1_Freq == 0U))
1783     {
1784         Setup.pllctrl = SYSCON->PLL1CTRL;
1785         Setup.pllndec = SYSCON->PLL1NDEC;
1786         Setup.pllpdec = SYSCON->PLL1PDEC;
1787         Setup.pllmdec = SYSCON->PLL1MDEC;
1788         CLOCK_GetPLL1OutFromSetupUpdate(&Setup);
1789     }
1790 
1791     rate = s_Pll1_Freq;
1792 
1793     return rate;
1794 }
1795 
1796 /* Set PLL0 output based on the passed PLL setup data */
1797 /*! brief    Set PLL output based on the passed PLL setup data
1798  *  param    pControl    : Pointer to populated PLL control structure to generate setup with
1799  *  param    pSetup      : Pointer to PLL setup structure to be filled
1800  *  return   PLL_ERROR_SUCCESS on success, or PLL setup error code
1801  *  note Actual frequency for setup may vary from the desired frequency based on the
1802  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1803  */
CLOCK_SetupPLL0Data(pll_config_t * pControl,pll_setup_t * pSetup)1804 pll_error_t CLOCK_SetupPLL0Data(pll_config_t *pControl, pll_setup_t *pSetup)
1805 {
1806     uint32_t inRate;
1807     bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0UL);
1808 
1809     pll_error_t pllError;
1810 
1811     /* Determine input rate for the PLL */
1812     if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0UL)
1813     {
1814         inRate = pControl->inputRate;
1815     }
1816     else
1817     {
1818         inRate = CLOCK_GetPLL0InClockRate();
1819     }
1820 
1821     /* PLL flag options */
1822     pllError = CLOCK_GetPll0Config(inRate, pControl->desiredRate, pSetup, useSS);
1823     if ((useSS) && (pllError == kStatus_PLL_Success))
1824     {
1825         /* If using SS mode, then some tweaks are made to the generated setup */
1826         pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
1827         if (pControl->mfDither)
1828         {
1829             pSetup->pllsscg[1] |= (1UL << SYSCON_PLL0SSCG1_DITHER_SHIFT);
1830         }
1831     }
1832 
1833     return pllError;
1834 }
1835 
1836 /* Set PLL0 output from PLL setup structure */
1837 /*! brief    Set PLL output from PLL setup structure (precise frequency)
1838  * param pSetup  : Pointer to populated PLL setup structure
1839  * param flagcfg : Flag configuration for PLL config structure
1840  * return    PLL_ERROR_SUCCESS on success, or PLL setup error code
1841  * note  This function will power off the PLL, setup the PLL with the
1842  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1843  * and adjust system voltages to the new PLL rate. The function will not
1844  * alter any source clocks (ie, main systen clock) that may use the PLL,
1845  * so these should be setup prior to and after exiting the function.
1846  */
CLOCK_SetupPLL0Prec(pll_setup_t * pSetup,uint32_t flagcfg)1847 pll_error_t CLOCK_SetupPLL0Prec(pll_setup_t *pSetup, uint32_t flagcfg)
1848 {
1849     uint32_t inRate, clkRate, prediv;
1850     uint32_t pll_lock_wait_time     = 0U;
1851     uint32_t max_pll_lock_wait_time = 0U;
1852     /* Power off PLL during setup changes */
1853     POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1854     POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1855 
1856     pSetup->flags = flagcfg;
1857 
1858     /* Write PLL setup data */
1859     SYSCON->PLL0CTRL  = pSetup->pllctrl;
1860     SYSCON->PLL0NDEC  = pSetup->pllndec;
1861     SYSCON->PLL0NDEC  = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1862     SYSCON->PLL0PDEC  = pSetup->pllpdec;
1863     SYSCON->PLL0PDEC  = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1864     SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1865     SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1866     SYSCON->PLL0SSCG1 =
1867         pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT); /* latch */
1868 
1869     POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1870     POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1871 
1872     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1873     {
1874         if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1875         {
1876             inRate = CLOCK_GetPLL0InClockRate();
1877             prediv = findPll0PreDiv();
1878             /* Adjust input clock */
1879             clkRate = inRate / prediv;
1880 
1881             /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is stable.
1882                The lock bit could be used to shorten the wait time when freq<20MHZ */
1883             max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1884 
1885             if (clkRate < 20000000UL)
1886             {
1887                 pll_lock_wait_time = 0U;
1888                 while ((CLOCK_IsPLL0Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1889                 {
1890                     pll_lock_wait_time += 100U;
1891                     SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1892                 }
1893             }
1894             else
1895             {
1896                 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1897             }
1898         }
1899         else /* spread spectrum mode */
1900         {
1901             SDK_DelayAtLeastUs(6000U,
1902                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
1903                                                                            insure the PLL will be stable */
1904         }
1905     }
1906 
1907     /* Update current programmed PLL rate var */
1908     CLOCK_GetPLL0OutFromSetupUpdate(pSetup);
1909 
1910     /* System voltage adjustment, occurs prior to setting main system clock */
1911     if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0UL)
1912     {
1913         POWER_SetVoltageForFreq(s_Pll0_Freq);
1914     }
1915 
1916     return kStatus_PLL_Success;
1917 }
1918 
1919 /* Setup PLL Frequency from pre-calculated value */
1920 /**
1921  * brief Set PLL0 output from PLL setup structure (precise frequency)
1922  * param pSetup  : Pointer to populated PLL setup structure
1923  * return    kStatus_PLL_Success on success, or PLL setup error code
1924  * note  This function will power off the PLL, setup the PLL with the
1925  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1926  * and adjust system voltages to the new PLL rate. The function will not
1927  * alter any source clocks (ie, main systen clock) that may use the PLL,
1928  * so these should be setup prior to and after exiting the function.
1929  */
CLOCK_SetPLL0Freq(const pll_setup_t * pSetup)1930 pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
1931 {
1932     uint32_t inRate, clkRate, prediv;
1933     uint32_t pll_lock_wait_time     = 0U;
1934     uint32_t max_pll_lock_wait_time = 0U;
1935     /* Power off PLL during setup changes */
1936     POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1937     POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1938 
1939     /* Write PLL setup data */
1940     SYSCON->PLL0CTRL  = pSetup->pllctrl;
1941     SYSCON->PLL0NDEC  = pSetup->pllndec;
1942     SYSCON->PLL0NDEC  = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1943     SYSCON->PLL0PDEC  = pSetup->pllpdec;
1944     SYSCON->PLL0PDEC  = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1945     SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1946     SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1947     SYSCON->PLL0SSCG1 =
1948         pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* latch */
1949 
1950     POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1951     POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1952 
1953     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1954     {
1955         if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1956         {
1957             inRate = CLOCK_GetPLL0InClockRate();
1958             prediv = findPll0PreDiv();
1959             /* Adjust input clock */
1960             clkRate = inRate / prediv;
1961 
1962             /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is
1963                stable. The lock bit could be used to shorten the wait time when freq<20MHZ */
1964             max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1965 
1966             if (clkRate < 20000000UL)
1967             {
1968                 pll_lock_wait_time = 0U;
1969                 while ((CLOCK_IsPLL0Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1970                 {
1971                     pll_lock_wait_time += 100U;
1972                     SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1973                 }
1974             }
1975             else
1976             {
1977                 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1978             }
1979         }
1980         else /* spread spectrum mode */
1981         {
1982             SDK_DelayAtLeastUs(6000U,
1983                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1984                                                                            to insure the PLL will be stable */
1985         }
1986     }
1987 
1988     /* Update current programmed PLL rate var */
1989     s_Pll0_Freq = pSetup->pllRate;
1990 
1991     return kStatus_PLL_Success;
1992 }
1993 
1994 /* Setup PLL1 Frequency from pre-calculated value */
1995 /**
1996  * brief Set PLL1 output from PLL setup structure (precise frequency)
1997  * param pSetup  : Pointer to populated PLL setup structure
1998  * return    kStatus_PLL_Success on success, or PLL setup error code
1999  * note  This function will power off the PLL, setup the PLL with the
2000  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2001  * and adjust system voltages to the new PLL rate. The function will not
2002  * alter any source clocks (ie, main systen clock) that may use the PLL,
2003  * so these should be setup prior to and after exiting the function.
2004  */
CLOCK_SetPLL1Freq(const pll_setup_t * pSetup)2005 pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
2006 {
2007     uint32_t inRate, clkRate, prediv;
2008     uint32_t pll_lock_wait_time     = 0U;
2009     uint32_t max_pll_lock_wait_time = 0U;
2010     /* Power off PLL during setup changes */
2011     POWER_EnablePD(kPDRUNCFG_PD_PLL1);
2012 
2013     /* Write PLL setup data */
2014     SYSCON->PLL1CTRL = pSetup->pllctrl;
2015     SYSCON->PLL1NDEC = pSetup->pllndec;
2016     SYSCON->PLL1NDEC = pSetup->pllndec | (1UL << SYSCON_PLL1NDEC_NREQ_SHIFT); /* latch */
2017     SYSCON->PLL1PDEC = pSetup->pllpdec;
2018     SYSCON->PLL1PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL1PDEC_PREQ_SHIFT); /* latch */
2019     SYSCON->PLL1MDEC = pSetup->pllmdec;
2020     SYSCON->PLL1MDEC = pSetup->pllmdec | (1UL << SYSCON_PLL1MDEC_MREQ_SHIFT); /* latch */
2021 
2022     POWER_DisablePD(kPDRUNCFG_PD_PLL1);
2023 
2024     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2025     {
2026         inRate = CLOCK_GetPLL1InClockRate();
2027         prediv = findPll1PreDiv();
2028         /* Adjust input clock */
2029         clkRate = inRate / prediv;
2030 
2031         /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is stable.
2032            The lock bit could be used to shorten the wait time when freq<20MHZ */
2033         max_pll_lock_wait_time = 500U + (400000000U / clkRate);
2034 
2035         if (clkRate < 20000000UL)
2036         {
2037             pll_lock_wait_time = 0U;
2038             while ((CLOCK_IsPLL1Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
2039             {
2040                 pll_lock_wait_time += 100U;
2041                 SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2042             }
2043         }
2044         else
2045         {
2046             SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2047         }
2048     }
2049 
2050     /* Update current programmed PLL rate var */
2051     s_Pll1_Freq = pSetup->pllRate;
2052 
2053     return kStatus_PLL_Success;
2054 }
2055 
2056 /* Set PLL0 clock based on the input frequency and multiplier */
2057 /*! brief    Set PLL0 output based on the multiplier and input frequency
2058  * param multiply_by : multiplier
2059  * param input_freq  : Clock input frequency of the PLL
2060  * return    Nothing
2061  * note  Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
2062  * function does not disable or enable PLL power, wait for PLL lock,
2063  * or adjust system voltages. These must be done in the application.
2064  * The function will not alter any source clocks (ie, main systen clock)
2065  * that may use the PLL, so these should be setup prior to and after
2066  * exiting the function.
2067  */
CLOCK_SetupPLL0Mult(uint32_t multiply_by,uint32_t input_freq)2068 void CLOCK_SetupPLL0Mult(uint32_t multiply_by, uint32_t input_freq)
2069 {
2070     uint32_t cco_freq = input_freq * multiply_by;
2071     uint32_t pdec     = 1U;
2072     uint32_t selr;
2073     uint32_t seli;
2074     uint32_t selp;
2075     uint32_t mdec, ndec;
2076 
2077     while (cco_freq < 275000000U)
2078     {
2079         multiply_by <<= 1U; /* double value in each iteration */
2080         pdec <<= 1U;        /* correspondingly double pdec to cancel effect of double msel */
2081         cco_freq = input_freq * multiply_by;
2082     }
2083 
2084     selr = 0U;
2085 
2086     if (multiply_by >= 8000UL)
2087     {
2088         seli = 1UL;
2089     }
2090     else if (multiply_by >= 122UL)
2091     {
2092         seli = (uint32_t)(8000UL / multiply_by); /*floor(8000/M) */
2093     }
2094     else
2095     {
2096         seli = 2UL * ((uint32_t)(multiply_by / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
2097     }
2098 
2099     if (seli >= 63U)
2100     {
2101         seli = 63U;
2102     }
2103 
2104     {
2105         selp = 31U;
2106     }
2107 
2108     if (pdec > 1U)
2109     {
2110         pdec = pdec / 2U; /* Account for minus 1 encoding */
2111                           /* Translate P value */
2112     }
2113 
2114     mdec = (uint32_t)PLL_SSCG1_MDEC_VAL_SET(multiply_by);
2115     ndec = 0x1U; /* pre divide by 1 (hardcoded) */
2116 
2117     SYSCON->PLL0CTRL = SYSCON_PLL0CTRL_CLKEN_MASK | SYSCON_PLL0CTRL_BYPASSPOSTDIV(0) |
2118                        SYSCON_PLL0CTRL_BYPASSPOSTDIV2(0) | (selr << SYSCON_PLL0CTRL_SELR_SHIFT) |
2119                        (seli << SYSCON_PLL0CTRL_SELI_SHIFT) | (selp << SYSCON_PLL0CTRL_SELP_SHIFT);
2120     SYSCON->PLL0PDEC  = pdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT);  /* set Pdec value and assert preq */
2121     SYSCON->PLL0NDEC  = ndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT);  /* set Pdec value and assert preq */
2122     SYSCON->PLL0SSCG1 = mdec | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* select non sscg MDEC value, assert
2123                                                                         mreq and select mdec value */
2124 }
2125 
2126 /* Enable USB DEVICE FULL SPEED clock */
2127 /*! brief Enable USB Device FS clock.
2128  * param src : clock source
2129  * param freq: clock frequency
2130  * Enable USB Device Full Speed clock.
2131  */
CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src,uint32_t freq)2132 bool CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src, uint32_t freq)
2133 {
2134     bool ret = true;
2135 
2136     CLOCK_DisableClock(kCLOCK_Usbd0);
2137 
2138     if (kCLOCK_UsbfsSrcFro == src)
2139     {
2140         switch (freq)
2141         {
2142             case 96000000U:
2143                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2144                 break;
2145 
2146             default:
2147                 ret = false;
2148                 break;
2149         }
2150         /* Turn ON FRO HF */
2151         POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
2152         /* Enable FRO 96MHz output */
2153         ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
2154         /* Select FRO 96 or 48 MHz */
2155         CLOCK_AttachClk(kFRO_HF_to_USB0);
2156     }
2157     else
2158     {
2159         /*!< Configure XTAL32M */
2160         POWER_DisablePD(kPDRUNCFG_PD_XTALHF);                                 /* Ensure XTAL32M is powered */
2161         POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF);                              /* Ensure XTAL32M is powered */
2162         (void)CLOCK_SetupExtClocking(16000000U);                              /* Enable clk_in clock */
2163         SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;               /* Enable clk_in from XTAL32M clock  */
2164         ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system  */
2165 
2166         /*!< Set up PLL1 */
2167         POWER_DisablePD(kPDRUNCFG_PD_PLL1);
2168         CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
2169         const pll_setup_t pll1Setup = {
2170             .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
2171             .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
2172             .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
2173             .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
2174             .pllRate = 48000000U,
2175             .flags   = PLL_SETUPFLAG_WAITLOCK};
2176         (void)CLOCK_SetPLL1Freq(&pll1Setup);
2177 
2178         CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2179         CLOCK_AttachClk(kPLL1_to_USB0);
2180         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2181     }
2182     CLOCK_EnableClock(kCLOCK_Usbd0);
2183 
2184     return ret;
2185 }
2186 
2187 /* Enable USB HOST FULL SPEED clock */
2188 /*! brief Enable USB HOST FS clock.
2189  * param src : clock source
2190  * param freq: clock frequency
2191  * Enable USB HOST Full Speed clock.
2192  */
CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src,uint32_t freq)2193 bool CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src, uint32_t freq)
2194 {
2195     bool ret = true;
2196 
2197     if (kCLOCK_UsbfsSrcFro == src)
2198     {
2199         switch (freq)
2200         {
2201             case 96000000U:
2202                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2203                 break;
2204 
2205             default:
2206                 ret = false;
2207                 break;
2208         }
2209         /* Turn ON FRO HF */
2210         POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
2211         /* Enable FRO 96MHz output */
2212         ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
2213         /* Select FRO 96 MHz */
2214         CLOCK_AttachClk(kFRO_HF_to_USB0);
2215     }
2216     else
2217     {
2218         /*!< Configure XTAL32M */
2219         POWER_DisablePD(kPDRUNCFG_PD_XTALHF);                                 /* Ensure XTAL32M is powered */
2220         POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF);                              /* Ensure XTAL32M is powered */
2221         (void)CLOCK_SetupExtClocking(16000000U);                              /* Enable clk_in clock */
2222         SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;               /* Enable clk_in from XTAL32M clock  */
2223         ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system  */
2224 
2225         /*!< Set up PLL1 */
2226         POWER_DisablePD(kPDRUNCFG_PD_PLL1);
2227         CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
2228         const pll_setup_t pll1Setup = {
2229             .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
2230             .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
2231             .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
2232             .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
2233             .pllRate = 48000000U,
2234             .flags   = PLL_SETUPFLAG_WAITLOCK};
2235         (void)CLOCK_SetPLL1Freq(&pll1Setup);
2236 
2237         CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2238         CLOCK_AttachClk(kPLL1_to_USB0);
2239         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2240     }
2241     CLOCK_EnableClock(kCLOCK_Usbhmr0);
2242     CLOCK_EnableClock(kCLOCK_Usbhsl0);
2243 
2244     return ret;
2245 }
2246 
2247 /*! @brief Enable the OSTIMER 32k clock.
2248  *  @return  Nothing
2249  */
CLOCK_EnableOstimer32kClock(void)2250 void CLOCK_EnableOstimer32kClock(void)
2251 {
2252     PMC->OSEVENTTIMER |= PMC_OSEVENTTIMER_CLOCKENABLE_MASK;
2253 }
2254 
2255 /* Sets board-specific trim values for High Frequency crystal oscillator */
2256 /*! brief Sets board-specific trim values for High Frequency crystal oscillator.
2257  * param pi32_hfXtalIecLoadpF_x100 : Load capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
2258  * becomes 120 param pi32_hfXtalPPcbParCappF_x100 : PCB +ve parasitic capacitance, pF x 100. For
2259  * example, 6pF becomes 600, 1.2pF becomes 120 param pi32_hfXtalNPcbParCappF_x100 : PCB -ve parasitic
2260  * capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF becomes 120 return   none note Following
2261  * default Values can be used: pi32_32MfXtalIecLoadpF_x100 Load capacitance, pF x 100 : 600
2262  * pi32_32MfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100 : 20
2263  * pi32_32MfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100 : 40 Sets board-specific trim
2264  * values for High Frequency crystal oscillator.
2265  */
CLOCK_XtalHfCapabankTrim(int32_t pi32_hfXtalIecLoadpF_x100,int32_t pi32_hfXtalPPcbParCappF_x100,int32_t pi32_hfXtalNPcbParCappF_x100)2266 void CLOCK_XtalHfCapabankTrim(int32_t pi32_hfXtalIecLoadpF_x100,
2267                               int32_t pi32_hfXtalPPcbParCappF_x100,
2268                               int32_t pi32_hfXtalNPcbParCappF_x100)
2269 {
2270     uint32_t u32XOTrimValue;
2271     uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF, u8XOSlave;
2272     int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
2273     int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
2274     uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
2275     uint32_t u32RegVal;
2276 
2277     /* Enable and set LDO, if not already done */
2278     CLOCK_SetXtalHfLdo();
2279     /* Get Cal values from Flash */
2280     u32XOTrimValue = GET_HFXO_TRIM();
2281     /* Check validity and apply */
2282     if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15) & 1UL)))
2283     {
2284         /* These fields are 7 bits, unsigned */
2285         u8IECXinCapCal6pF  = (uint8_t)((u32XOTrimValue >> 1) & 0x7fUL);
2286         u8IECXinCapCal8pF  = (uint8_t)((u32XOTrimValue >> 8) & 0x7fUL);
2287         u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16) & 0x7fUL);
2288         u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23) & 0x7fUL);
2289         /* This field is 1 bit */
2290         u8XOSlave = (uint8_t)((u32XOTrimValue >> 30) & 0x1UL);
2291         /* Linear fit coefficients calculation */
2292         iaXin_x4  = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
2293         ibXin     = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
2294         iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
2295         ibXout    = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
2296     }
2297     else
2298     {
2299         iaXin_x4  = 20;  // gain in LSB/pF
2300         ibXin     = -9;  // offset in LSB
2301         iaXout_x4 = 20;  // gain in LSB/pF
2302         ibXout    = -13; // offset in LSB
2303         u8XOSlave = 0;
2304     }
2305     /* In & out load cap calculation with derating */
2306     iXOCapInpF_x100 =
2307         (int32_t)(2 * pi32_hfXtalIecLoadpF_x100 - pi32_hfXtalNPcbParCappF_x100 + 39 * (XO_SLAVE_EN - (int8_t)u8XOSlave) - 15);
2308     iXOCapOutpF_x100 = 2 * pi32_hfXtalIecLoadpF_x100 - pi32_hfXtalPPcbParCappF_x100 - 21;
2309     /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
2310     u8XOCapInCtrl  = (uint8_t)(int32_t)((((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400));
2311     u8XOCapOutCtrl = (uint8_t)(int32_t)((((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400));
2312     /* Read register and clear fields to be written */
2313     u32RegVal = ANACTRL->XO32M_CTRL;
2314     u32RegVal &= ~(ANACTRL_XO32M_CTRL_OSC_CAP_IN_MASK | ANACTRL_XO32M_CTRL_OSC_CAP_OUT_MASK);
2315     /* Configuration of 32 MHz XO output buffers */
2316 #if (XO_SLAVE_EN == 0)
2317     u32RegVal &= ~(ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK);
2318 #else
2319     u32RegVal |= ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
2320 #endif
2321     /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
2322     u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_IN_SHIFT;
2323     u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_OUT_SHIFT;
2324     /* Write back to register */
2325     ANACTRL->XO32M_CTRL = u32RegVal;
2326 }
2327 
2328 /* Sets board-specific trim values for 32kHz XTAL */
2329 /*! brief Sets board-specific trim values for 32kHz XTAL.
2330  * param pi32_32kfXtalIecLoadpF_x100 : Load capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
2331  * becomes 120 param pi32_32kfXtalPPcbParCappF_x100 : PCB +ve parasitic capacitance, pF x 100. For
2332  * example, 6pF becomes 600, 1.2pF becomes 120 param pi32_32kfXtalNPcbParCappF_x100 : PCB -ve parasitic
2333  * capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF becomes 120 return   none note Following
2334  * default Values can be used: pi32_32kfXtalIecLoadpF_x100 Load capacitance, pF x 100 : 600
2335  * pi32_32kfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100 : 40
2336  * pi32_32kfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100 : 40 Sets board-specific trim
2337  * values for 32kHz XTAL.
2338  */
CLOCK_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,int32_t pi32_32kfXtalPPcbParCappF_x100,int32_t pi32_32kfXtalNPcbParCappF_x100)2339 void CLOCK_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
2340                                  int32_t pi32_32kfXtalPPcbParCappF_x100,
2341                                  int32_t pi32_32kfXtalNPcbParCappF_x100)
2342 {
2343     uint32_t u32XOTrimValue;
2344     uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF;
2345     int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
2346     int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
2347     uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
2348     uint32_t u32RegVal;
2349     /* Get Cal values from Flash */
2350     u32XOTrimValue = GET_32KXO_TRIM();
2351     /* check validity and apply */
2352     if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15) & 1UL)))
2353     {
2354         /* These fields are 7 bits, unsigned */
2355         u8IECXinCapCal6pF  = (uint8_t)((u32XOTrimValue >> 1) & 0x7fUL);
2356         u8IECXinCapCal8pF  = (uint8_t)((u32XOTrimValue >> 8) & 0x7fUL);
2357         u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16) & 0x7fUL);
2358         u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23) & 0x7fUL);
2359         /* Linear fit coefficients calculation */
2360         iaXin_x4  = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
2361         ibXin     = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
2362         iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
2363         ibXout    = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
2364     }
2365     else
2366     {
2367         iaXin_x4  = 16; // gain in LSB/pF
2368         ibXin     = 12; // offset in LSB
2369         iaXout_x4 = 16; // gain in LSB/pF
2370         ibXout    = 11; // offset in LSB
2371     }
2372 
2373     /* In & out load cap calculation with derating */
2374     iXOCapInpF_x100  = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalNPcbParCappF_x100 - 130;
2375     iXOCapOutpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalPPcbParCappF_x100 - 41;
2376 
2377     /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
2378     u8XOCapInCtrl  = (uint8_t)(int32_t)((((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400));
2379     u8XOCapOutCtrl = (uint8_t)(int32_t)((((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400));
2380 
2381     /* Read register and clear fields to be written */
2382     u32RegVal = PMC->XTAL32K;
2383     u32RegVal &= ~(PMC_XTAL32K_CAPBANKIN_MASK | PMC_XTAL32K_CAPBANKOUT_MASK);
2384 
2385     /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
2386     u32RegVal |= (uint32_t)(CLOCK_u8OscCapConvert(u8XOCapInCtrl, 23)) << PMC_XTAL32K_CAPBANKIN_SHIFT;
2387     u32RegVal |= (uint32_t)(CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 23)) << PMC_XTAL32K_CAPBANKOUT_SHIFT;
2388 
2389     /* Write back to register */
2390     PMC->XTAL32K = u32RegVal;
2391 }
2392 
2393 /* Enables and sets LDO for High Frequency crystal oscillator. */
2394 /*! brief Enables and sets LDO for High Frequency crystal oscillator.
2395  * return   none
2396  * Sets Enables and sets LDO for High Frequency crystal oscillator.
2397  */
CLOCK_SetXtalHfLdo(void)2398 static void CLOCK_SetXtalHfLdo(void)
2399 {
2400     uint32_t temp;
2401     const uint32_t u32Mask =
2402         (ANACTRL_LDO_XO32M_VOUT_MASK | ANACTRL_LDO_XO32M_IBIAS_MASK | ANACTRL_LDO_XO32M_STABMODE_MASK);
2403 
2404     const uint32_t u32Value =
2405         (ANACTRL_LDO_XO32M_VOUT(0x5) | ANACTRL_LDO_XO32M_IBIAS(0x2) | ANACTRL_LDO_XO32M_STABMODE(0x1));
2406 
2407     /* Enable & set-up XTAL 32 MHz clock LDO */
2408     temp = ANACTRL->LDO_XO32M;
2409 
2410     if ((temp & u32Mask) != u32Value)
2411     {
2412         temp &= ~u32Mask;
2413 
2414         /*
2415          * Enable the XTAL32M LDO
2416          * Adjust the output voltage level, 0x5 for 1.1V
2417          * Adjust the biasing current, 0x2 value
2418          * Stability configuration, 0x1 default mode
2419          */
2420         temp |= u32Value;
2421 
2422         ANACTRL->LDO_XO32M = temp;
2423 
2424         /* Delay for LDO to be up */
2425         // CLOCK_uDelay(20);
2426     }
2427 
2428     /* Enable LDO XO32M */
2429     PMC->PDRUNCFGCLR0 = PMC_PDRUNCFG0_PDEN_LDOXTALHF_MASK;
2430 }
2431 
2432 /**
2433  * @brief
2434  * @param
2435  * @return
2436  */
CLOCK_u8OscCapConvert(uint8_t u8OscCap,uint8_t u8CapBankDiscontinuity)2437 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity)
2438 {
2439     /* Compensate for discontinuity in the capacitor banks */
2440     if (u8OscCap < 64U)
2441     {
2442         if (u8OscCap >= u8CapBankDiscontinuity)
2443         {
2444             u8OscCap -= u8CapBankDiscontinuity;
2445         }
2446         else
2447         {
2448             u8OscCap = 0;
2449         }
2450     }
2451     else
2452     {
2453         if (u8OscCap <= (127U - u8CapBankDiscontinuity))
2454         {
2455             u8OscCap += u8CapBankDiscontinuity;
2456         }
2457         else
2458         {
2459             u8OscCap = 127;
2460         }
2461     }
2462     return u8OscCap;
2463 }
2464 
2465 /*!
2466  * brief  Initialize the trim value for FRO HF .
2467  */
CLOCK_FroHfTrim(void)2468 void CLOCK_FroHfTrim(void)
2469 {
2470     volatile unsigned int Fro192mCtrlEfuse = 0;
2471     Fro192mCtrlEfuse                       = ANACTRL->FRO192M_CTRL;
2472     ANACTRL->ANALOG_CTRL_CFG               = ANACTRL->ANALOG_CTRL_CFG | ANACTRL_ANALOG_CTRL_CFG_FRO192M_TRIM_SRC_MASK;
2473     ANACTRL->FRO192M_CTRL                  = ANACTRL_FRO192M_CTRL_WRTRIM_MASK | Fro192mCtrlEfuse;
2474 }
2475