1 /*
2  * Copyright 2022-2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_clock.h"
9 /*******************************************************************************
10  * Definitions
11  ******************************************************************************/
12 /* Component ID definition, used by tools. */
13 #ifndef FSL_COMPONENT_ID
14 #define FSL_COMPONENT_ID "platform.drivers.clock"
15 #endif
16 
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_NDIV_VAL_P (0U) /* NDIV is in bits  7:0 */
28 #define PLL_NDIV_VAL_M (0xFFUL << PLL_NDIV_VAL_P)
29 #define PLL_MDIV_VAL_P (0U) /* MDIV is in bits  15:0 */
30 #define PLL_MDIV_VAL_M (0xFFFFULL << PLL_MDIV_VAL_P)
31 #define PLL_PDIV_VAL_P (0U) /* PDIV is in bits  4:0 */
32 #define PLL_PDIV_VAL_M (0x1FUL << PLL_PDIV_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   (32000U)     /*!<  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 NDIV reg */
43 #define PLL_NDIV_VAL_SET(value) (((unsigned long)(value) << PLL_NDIV_VAL_P) & PLL_NDIV_VAL_M)
44 /* PLL MDIV reg */
45 #define PLL_MDIV_VAL_SET(value) (((unsigned long long)(value) << PLL_MDIV_VAL_P) & PLL_MDIV_VAL_M)
46 /* PLL PDIV reg */
47 #define PLL_PDIV_VAL_SET(value) (((unsigned long)(value) << PLL_PDIV_VAL_P) & PLL_PDIV_VAL_M)
48 
49 /* PLL SSCG control1 */
50 #define PLL_SSCG_MD_FRACT_P 0U
51 #define PLL_SSCG_MD_INT_P   25U
52 #define PLL_SSCG_MD_FRACT_M (0x1FFFFFFUL << PLL_SSCG_MD_FRACT_P)
53 #define PLL_SSCG_MD_INT_M   ((uint64_t)0xFFUL << PLL_SSCG_MD_INT_P)
54 
55 #define PLL_SSCG_MD_FRACT_SET(value) (((uint64_t)(value) << PLL_SSCG_MD_FRACT_P) & PLL_SSCG_MD_FRACT_M)
56 #define PLL_SSCG_MD_INT_SET(value)   (((uint64_t)(value) << PLL_SSCG_MD_INT_P) & PLL_SSCG_MD_INT_M)
57 
58 /*******************************************************************************
59  * Variables
60  ******************************************************************************/
61 
62 /** External clock rate on the CLKIN pin in Hz. If not used,
63     set this to 0. Otherwise, set it to the exact rate in Hz this pin is
64     being driven at. */
65 volatile static uint32_t s_Ext_Clk_Freq = 16000000U;
66 /*! @brief External XTAL32K clock frequency. */
67 volatile static uint32_t s_Xtal32_Freq = 32768U;
68 /*! @brief SAI MCLK clock frequency. */
69 volatile static uint32_t s_Sai_Mclk_Freq[2] = {0U};
70 /*! @brief SAI TX BCLK clock frequency. */
71 volatile static uint32_t s_Sai_Tx_Bclk_Freq[2] = {0U};
72 /*! @brief SAI RX BCLK clock frequency. */
73 volatile static uint32_t s_Sai_Rx_Bclk_Freq[2] = {0U};
74 /*! @brief ENET TX CLK clock frequency. */
75 volatile static uint32_t s_Enet_Tx_Clk_Freq = 0U;
76 
77 /*! @brief external UPLL clock frequency. */
78 static uint32_t s_extUpllFreq = 0U;
79 
80 /*******************************************************************************
81  * Prototypes
82  ******************************************************************************/
83 /* Get FRO 12M Clk */
84 static uint32_t CLOCK_GetFro12MFreq(void);
85 /* Get CLK 1M Clk */
86 static uint32_t CLOCK_GetClk1MFreq(void);
87 /* Get HF FRO Clk */
88 static uint32_t CLOCK_GetFroHfFreq(void);
89 /* Get CLK 48M Clk */
90 static uint32_t CLOCK_GetClk48MFreq(void);
91 /* Get CLK 144M Clk */
92 static uint32_t CLOCK_GetClk144MFreq(void);
93 /* Get CLK 16K Clk */
94 static uint32_t CLOCK_GetClk16KFreq(uint32_t id);
95 /* Get EXT OSC Clk */
96 static uint32_t CLOCK_GetExtClkFreq(void);
97 /* Get OSC 32K Clk */
98 static uint32_t CLOCK_GetOsc32KFreq(uint32_t id);
99 /* Get Systick Clk */
100 static uint32_t CLOCK_GetSystickClkFreq(uint32_t id);
101 /* Get CLOCK OUT Clk */
102 static uint32_t CLOCK_GetClockOutClkFreq(void);
103 /* Get LP_OSC Clk */
104 static uint32_t CLOCK_GetLposcFreq(void);
105 
106 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
107 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
108 /* Get predivider (N) from PLL0 NDIV setting */
109 static uint32_t findPll0PreDiv(void);
110 /* Get predivider (N) from PLL1 NDIV setting */
111 static uint32_t findPll1PreDiv(void);
112 /* Get postdivider (P) from PLL0 PDIV setting */
113 static uint32_t findPll0PostDiv(void);
114 /* Get postdivider (P) from PLL1 PDIV setting */
115 static uint32_t findPll1PostDiv(void);
116 /* Get multiplier (M) from PLL0 MDIV and SSCG settings */
117 static float findPll0MMult(void);
118 /* Get multiplier (M) from PLL1 MDIV and SSCG settings */
119 static float findPll1MMult(void);
120 /* Get the greatest common divisor */
121 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
122 /* Set PLL output based on desired output rate */
123 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
124 /* Set PLL0 output based on desired output rate */
125 static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
126 /* Get PLL input clock rate from setup structure */
127 static uint32_t CLOCK_GetPLLInClockRateFromSetup(pll_setup_t *pSetup);
128 /* Get predivider (N) from setup structure */
129 static uint32_t findPllPreDivFromSetup(pll_setup_t *pSetup);
130 /* Get postdivider (P) from setup structure */
131 static uint32_t findPllPostDivFromSetup(pll_setup_t *pSetup);
132 /* Get multiplier (M) from setup structure */
133 static float findPllMMultFromSetup(pll_setup_t *pSetup);
134 
135 /*******************************************************************************
136  * Code
137  ******************************************************************************/
138 
139 /**
140  * @brief   Initialize the Core clock to given frequency (48 or 144 MHz).
141  * This function turns on FIRC and select the given frequency as the source of fro_hf
142  * @param   iFreq   : Desired frequency (must be one of CLK_FRO_48MHZ or CLK_FRO_144MHZ)
143  * @return  returns success or fail status.
144  */
CLOCK_SetupFROHFClocking(uint32_t iFreq)145 status_t CLOCK_SetupFROHFClocking(uint32_t iFreq)
146 {
147     if ((iFreq != 48000000U) && (iFreq != 144000000U))
148     {
149         return kStatus_Fail;
150     }
151 
152     /* Select 48MHz or 144MHz for FIRC clock */
153     SCG0->FIRCCFG = SCG_FIRCCFG_RANGE((iFreq == 48000000U) ? 0 : 1);
154 
155     /* Unlock FIRCCSR */
156     SCG0->FIRCCSR &= ~SCG_FIRCCSR_LK_MASK;
157 
158     /* Enable FIRC 48 MHz clock for peripheral use */
159     SCG0->FIRCCSR |= SCG_FIRCCSR_FIRC_SCLK_PERIPH_EN_MASK;
160     /* Enable FIRC 144 MHz clock for peripheral use */
161     SCG0->FIRCCSR |= SCG_FIRCCSR_FIRC_FCLK_PERIPH_EN_MASK;
162 
163     /* Enable FIRC */
164     SCG0->FIRCCSR |= SCG_FIRCCSR_FIRCEN_MASK;
165 
166     /* Wait for FIRC clock to be valid. */
167     while ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) == 0U)
168     {
169     }
170 
171     return kStatus_Success;
172 }
173 
174 /**
175  * @brief   Initialize the external osc clock to given frequency.
176  * @param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
177  * @return  returns success or fail status.
178  */
CLOCK_SetupExtClocking(uint32_t iFreq)179 status_t CLOCK_SetupExtClocking(uint32_t iFreq)
180 {
181     uint8_t range = 0U;
182 
183     if ((iFreq >= 16000000U) && (iFreq < 20000000U))
184     {
185         range = 0U;
186     }
187     else if ((iFreq >= 20000000U) && (iFreq < 30000000U))
188     {
189         range = 1U;
190     }
191     else if ((iFreq >= 30000000U) && (iFreq < 50000000U))
192     {
193         range = 2U;
194     }
195     else if ((iFreq >= 50000000U) && (iFreq < 66000000U))
196     {
197         range = 3U;
198     }
199     else
200     {
201         return kStatus_InvalidArgument;
202     }
203 
204     /* If clock is used by system, return error. */
205     if ((SCG0->SOSCCSR & SCG_SOSCCSR_SOSCSEL_MASK) != 0U)
206     {
207         return (status_t)kStatus_SCG_Busy;
208     }
209 
210     /* If sosc is used by PLL and PLL is used by system, return error. */
211     if ((((SCG0->APLLCTRL & SCG_APLLCTRL_SOURCE_MASK) == 0u) && ((SCG0->APLLCSR & SCG_APLLCSR_APLLSEL_MASK) != 0U)) ||
212         (((SCG0->SPLLCTRL & SCG_SPLLCTRL_SOURCE_MASK) == 0u) && ((SCG0->SPLLCSR & SCG_SPLLCSR_SPLLSEL_MASK) != 0U)))
213     {
214         return (status_t)kStatus_SCG_Busy;
215     }
216 
217     /* If configure register is locked, return error. */
218     if ((SCG0->SOSCCSR & SCG_SOSCCSR_LK_MASK) != 0U)
219     {
220         return kStatus_ReadOnly;
221     }
222 
223     /* De-initializes the SCG SOSC */
224     SCG0->SOSCCSR = SCG_SOSCCSR_SOSCERR_MASK;
225 
226     /* Enable LDO */
227     SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
228 
229     /* Select SOSC source (internal crystal oscillator) and Configure SOSC range */
230     SCG0->SOSCCFG = SCG_SOSCCFG_EREFS_MASK | SCG_SOSCCFG_RANGE(range);
231 
232     /* Unlock SOSCCSR */
233     SCG0->SOSCCSR &= ~SCG_SOSCCSR_LK_MASK;
234 
235     /* Enable SOSC clock monitor and Enable SOSC */
236     SCG0->SOSCCSR |= (SCG_SOSCCSR_SOSCCM_MASK | SCG_SOSCCSR_SOSCEN_MASK);
237 
238     /* Wait for SOSC clock to be valid. */
239     while ((SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) == 0U)
240     {
241     }
242 
243     s_Ext_Clk_Freq = iFreq;
244 
245     return kStatus_Success;
246 }
247 
248 /**
249  * @brief   Initialize the external reference clock to given frequency.
250  * @param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
251  * @return  returns success or fail status.
252  */
CLOCK_SetupExtRefClocking(uint32_t iFreq)253 status_t CLOCK_SetupExtRefClocking(uint32_t iFreq)
254 {
255     uint8_t range = 0U;
256 
257     if ((iFreq >= 16000000U) && (iFreq < 20000000U))
258     {
259         range = 0U;
260     }
261     else if ((iFreq >= 20000000U) && (iFreq < 30000000U))
262     {
263         range = 1U;
264     }
265     else if ((iFreq >= 30000000U) && (iFreq < 50000000U))
266     {
267         range = 2U;
268     }
269     else if ((iFreq >= 50000000U) && (iFreq < 66000000U))
270     {
271         range = 3U;
272     }
273     else
274     {
275         return kStatus_InvalidArgument;
276     }
277 
278     /* If clock is used by system, return error. */
279     if ((SCG0->SOSCCSR & SCG_SOSCCSR_SOSCSEL_MASK) != 0U)
280     {
281         return (status_t)kStatus_SCG_Busy;
282     }
283 
284     /* If sosc is used by PLL and PLL is used by system, return error. */
285     if ((((SCG0->APLLCTRL & SCG_APLLCTRL_SOURCE_MASK) == 0u) && ((SCG0->APLLCSR & SCG_APLLCSR_APLLSEL_MASK) != 0U)) ||
286         (((SCG0->SPLLCTRL & SCG_SPLLCTRL_SOURCE_MASK) == 0u) && ((SCG0->SPLLCSR & SCG_SPLLCSR_SPLLSEL_MASK) != 0U)))
287     {
288         return (status_t)kStatus_SCG_Busy;
289     }
290 
291     /* If configure register is locked, return error. */
292     if ((SCG0->SOSCCSR & SCG_SOSCCSR_LK_MASK) != 0U)
293     {
294         return kStatus_ReadOnly;
295     }
296 
297     /* De-initializes the SCG SOSC */
298     SCG0->SOSCCSR = SCG_SOSCCSR_SOSCERR_MASK;
299 
300     /* Enable LDO */
301     SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
302 
303     /* Select SOSC source (external reference clock)*/
304     SCG0->SOSCCFG &= ~SCG_SOSCCFG_EREFS_MASK;
305 
306     /*Configure SOSC range */
307     SCG0->SOSCCFG |= SCG_SOSCCFG_RANGE(range);
308 
309     /* Unlock SOSCCSR */
310     SCG0->SOSCCSR &= ~SCG_SOSCCSR_LK_MASK;
311 
312     /* Enable SOSC clock monitor and Enable SOSC */
313     SCG0->SOSCCSR |= (SCG_SOSCCSR_SOSCCM_MASK | SCG_SOSCCSR_SOSCEN_MASK);
314 
315     /* Wait for SOSC clock to be valid. */
316     while ((SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) == 0U)
317     {
318     }
319 
320     s_Ext_Clk_Freq = iFreq;
321 
322     return kStatus_Success;
323 }
324 
325 /**
326  * @brief   Initialize the OSC 32K.
327  * @param   id   : OSC 32 kHz output clock to specified modules
328  * @return  returns success or fail status.
329  */
CLOCK_SetupOsc32KClocking(uint32_t id)330 status_t CLOCK_SetupOsc32KClocking(uint32_t id)
331 {
332     /* Enable LDO */
333     SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK | SCG_LDOCSR_VOUT_OK_MASK;
334 
335     VBAT0->OSCCTLA =
336         (VBAT0->OSCCTLA & ~(VBAT_OSCCTLA_MODE_EN_MASK | VBAT_OSCCTLA_CAP_SEL_EN_MASK | VBAT_OSCCTLA_OSC_EN_MASK)) |
337         VBAT_OSCCTLA_MODE_EN(0x0) | VBAT_OSCCTLA_CAP_SEL_EN_MASK | VBAT_OSCCTLA_OSC_EN_MASK;
338     VBAT0->OSCCTLB = VBAT_OSCCTLB_INVERSE(0xFFF7E);
339     /* Wait for STATUSA[OSC_RDY] to set. */
340     while ((VBAT0->STATUSA & VBAT_STATUSA_OSC_RDY_MASK) == 0U)
341     {
342     }
343     VBAT0->OSCLCKA = VBAT_OSCLCKA_LOCK_MASK;
344     VBAT0->OSCLCKB &= ~VBAT_OSCLCKA_LOCK_MASK;
345 
346     VBAT0->OSCCLKE |= VBAT_OSCCLKE_CLKE(id);
347 
348     /* De-initializes the SCG ROSC */
349     SCG0->ROSCCSR = SCG_ROSCCSR_ROSCERR_MASK;
350 
351     /* Unlock ROSCCSR */
352     SCG0->ROSCCSR &= ~SCG_ROSCCSR_LK_MASK;
353 
354     /* Enable SOSC clock monitor and Enable ROSC */
355     SCG0->ROSCCSR |= SCG_ROSCCSR_ROSCCM_MASK;
356 
357     /* Wait for ROSC clock to be valid. */
358     while ((SCG0->ROSCCSR & SCG_ROSCCSR_ROSCVLD_MASK) == 0U)
359     {
360     }
361 
362     s_Xtal32_Freq = 32768U;
363 
364     return kStatus_Success;
365 }
366 
367 /**
368  * @brief   Initialize the CLK16K clock.
369  * @param   id   : CLK 16 kHz output clock to specified modules
370  * @return  returns success or fail status.
371  */
CLOCK_SetupClk16KClocking(uint32_t id)372 status_t CLOCK_SetupClk16KClocking(uint32_t id)
373 {
374     VBAT0->FROCTLA |= VBAT_FROCTLA_FRO_EN_MASK;
375     VBAT0->FROCTLB &= ~VBAT_FROCTLB_INVERSE_MASK;
376 
377     VBAT0->FROLCKA |= VBAT_FROLCKA_LOCK_MASK;
378     VBAT0->FROLCKB &= ~VBAT_FROLCKB_LOCK_MASK;
379 
380     VBAT0->FROCLKE |= VBAT_FROCLKE_CLKE(id);
381 
382     return kStatus_Success;
383 }
384 
385 /**
386  * @brief   Setup FROHF trim.
387  * @param   config   : FROHF trim value
388  * @return  returns success or fail status.
389  */
CLOCK_FROHFTrimConfig(firc_trim_config_t config)390 status_t CLOCK_FROHFTrimConfig(firc_trim_config_t config)
391 {
392     SCG0->FIRCTCFG = SCG_FIRCTCFG_TRIMDIV(config.trimDiv) | SCG_FIRCTCFG_TRIMSRC(config.trimSrc);
393 
394     if (kSCG_FircTrimNonUpdate == config.trimMode)
395     {
396         SCG0->FIRCSTAT = SCG_FIRCSTAT_TRIMFINE(config.trimFine);
397     }
398 
399     /* Set trim mode. */
400     SCG0->FIRCCSR = (uint32_t)config.trimMode;
401 
402     if ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRCERR_MASK) == SCG_FIRCCSR_FIRCERR_MASK)
403     {
404         return (status_t)kStatus_Fail;
405     }
406 
407     return (status_t)kStatus_Success;
408 }
409 
410 /**
411  * @brief   Setup FRO 12M trim.
412  * @param   config   : FRO 12M trim value
413  * @return  returns success or fail status.
414  */
CLOCK_FRO12MTrimConfig(sirc_trim_config_t config)415 status_t CLOCK_FRO12MTrimConfig(sirc_trim_config_t config)
416 {
417     SCG0->SIRCTCFG = SCG_SIRCTCFG_TRIMDIV(config.trimDiv) | SCG_SIRCTCFG_TRIMSRC(config.trimSrc);
418 
419     if (kSCG_SircTrimNonUpdate == config.trimMode)
420     {
421         SCG0->SIRCSTAT = SCG_SIRCSTAT_CCOTRIM(config.cltrim);
422         SCG0->SIRCSTAT = SCG_SIRCSTAT_CCOTRIM(config.ccotrim);
423     }
424 
425     /* Set trim mode. */
426     SCG0->SIRCCSR = (uint32_t)config.trimMode;
427 
428     if ((SCG0->SIRCCSR & SCG_SIRCCSR_SIRCERR_MASK) == SCG_SIRCCSR_SIRCERR_MASK)
429     {
430         return (status_t)kStatus_Fail;
431     }
432 
433     return (status_t)kStatus_Success;
434 }
435 
436 /*!
437  * @brief Sets the system OSC monitor mode.
438  *
439  * This function sets the system OSC monitor mode. The mode can be disabled,
440  * it can generate an interrupt when the error is disabled, or reset when the error is detected.
441  *
442  * @param mode Monitor mode to set.
443  */
CLOCK_SetSysOscMonitorMode(scg_sosc_monitor_mode_t mode)444 void CLOCK_SetSysOscMonitorMode(scg_sosc_monitor_mode_t mode)
445 {
446     uint32_t reg = SCG0->SOSCCSR;
447 
448     reg &= ~(SCG_SOSCCSR_SOSCCM_MASK | SCG_SOSCCSR_SOSCCMRE_MASK);
449 
450     reg |= (uint32_t)mode;
451 
452     SCG0->SOSCCSR = reg;
453 }
454 
455 /*!
456  * @brief Sets the ROSC monitor mode.
457  *
458  * This function sets the ROSC monitor mode. The mode can be disabled,
459  * it can generate an interrupt when the error is disabled, or reset when the error is detected.
460  *
461  * @param mode Monitor mode to set.
462  */
CLOCK_SetRoscMonitorMode(scg_rosc_monitor_mode_t mode)463 void CLOCK_SetRoscMonitorMode(scg_rosc_monitor_mode_t mode)
464 {
465     uint32_t reg = SCG0->ROSCCSR;
466 
467     reg &= ~(SCG_ROSCCSR_ROSCCM_MASK | SCG_ROSCCSR_ROSCCMRE_MASK);
468 
469     reg |= (uint32_t)mode;
470 
471     SCG0->ROSCCSR = reg;
472 }
473 
474 /*!
475  * @brief Sets the UPLL monitor mode.
476  *
477  * This function sets the UPLL monitor mode. The mode can be disabled,
478  * it can generate an interrupt when the error is disabled, or reset when the error is detected.
479  *
480  * @param mode Monitor mode to set.
481  */
CLOCK_SetUpllMonitorMode(scg_upll_monitor_mode_t mode)482 void CLOCK_SetUpllMonitorMode(scg_upll_monitor_mode_t mode)
483 {
484     uint32_t reg = SCG0->UPLLCSR;
485 
486     reg &= ~(SCG_UPLLCSR_UPLLCM_MASK | SCG_UPLLCSR_UPLLCMRE_MASK);
487 
488     reg |= (uint32_t)mode;
489 
490     SCG0->UPLLCSR = reg;
491 }
492 
493 /*!
494  * @brief Sets the PLL0 monitor mode.
495  *
496  * This function sets the PLL0 monitor mode. The mode can be disabled,
497  * it can generate an interrupt when the error is disabled, or reset when the error is detected.
498  *
499  * @param mode Monitor mode to set.
500  */
CLOCK_SetPll0MonitorMode(scg_pll0_monitor_mode_t mode)501 void CLOCK_SetPll0MonitorMode(scg_pll0_monitor_mode_t mode)
502 {
503     uint32_t reg = SCG0->APLLCSR;
504 
505     reg &= ~(SCG_APLLCSR_APLLCM_MASK | SCG_APLLCSR_APLLCMRE_MASK);
506 
507     reg |= (uint32_t)mode;
508 
509     SCG0->APLLCSR = reg;
510 }
511 
512 /*!
513  * @brief Sets the PLL1 monitor mode.
514  *
515  * This function sets the PLL1 monitor mode. The mode can be disabled,
516  * it can generate an interrupt when the error is disabled, or reset when the error is detected.
517  *
518  * @param mode Monitor mode to set.
519  */
CLOCK_SetPll1MonitorMode(scg_pll1_monitor_mode_t mode)520 void CLOCK_SetPll1MonitorMode(scg_pll1_monitor_mode_t mode)
521 {
522     uint32_t reg = SCG0->SPLLCSR;
523 
524     reg &= ~(SCG_SPLLCSR_SPLLCM_MASK | SCG_SPLLCSR_SPLLCMRE_MASK);
525 
526     reg |= (uint32_t)mode;
527 
528     SCG0->SPLLCSR = reg;
529 }
530 
531 /*!
532  * @brief	Set the additional number of wait-states added to account for the ratio of system clock period to flash access
533  * time during full speed power mode.
534  * @param	system_freq_hz	: Input frequency
535  * @param	mode	        : Active run mode (voltage level).
536  * @return	success or fail status
537  */
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz,run_mode_t mode)538 status_t CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz, run_mode_t mode)
539 {
540     uint32_t num_wait_states_added = 3UL; /* Default 3 additional wait states */
541     switch ((uint32_t)mode)
542     {
543         case (uint32_t)kMD_Mode:
544         {
545             if (system_freq_hz > 50000000U)
546             {
547                 return kStatus_Fail;
548             }
549             if (system_freq_hz > 24000000U)
550             {
551                 num_wait_states_added = 1U;
552             }
553             else
554             {
555                 num_wait_states_added = 0U;
556             }
557             break;
558         }
559         case (uint32_t)kSD_Mode:
560         {
561             if (system_freq_hz > 100000000U)
562             {
563                 return kStatus_Fail;
564             }
565             if (system_freq_hz > 64000000U)
566             {
567                 num_wait_states_added = 2U;
568             }
569             else if (system_freq_hz > 36000000U)
570             {
571                 num_wait_states_added = 1U;
572             }
573             else
574             {
575                 num_wait_states_added = 0U;
576             }
577             break;
578         }
579         case (uint32_t)kOD_Mode:
580         {
581             if (system_freq_hz > 150000000U)
582             {
583                 return kStatus_Fail;
584             }
585             if (system_freq_hz > 100000000U)
586             {
587                 num_wait_states_added = 3U;
588             }
589             else if (system_freq_hz > 64000000U)
590             {
591                 num_wait_states_added = 2U;
592             }
593             else if (system_freq_hz > 36000000U)
594             {
595                 num_wait_states_added = 1U;
596             }
597             else
598             {
599                 num_wait_states_added = 0U;
600             }
601             break;
602         }
603         default:
604             num_wait_states_added = 0U;
605             break;
606     }
607 
608     /* additional wait-states are added */
609     FMU0->FCTRL = (FMU0->FCTRL & 0xFFFFFFF0UL) | (num_wait_states_added & 0xFUL);
610 
611     return kStatus_Success;
612 }
613 
614 /*!
615  * @brief Config 32k Crystal Oscillator.
616  *
617  * @param base VBAT peripheral base address.
618  * @param config The pointer to the structure \ref vbat_osc_config_t.
619  */
VBAT_SetOscConfig(VBAT_Type * base,const vbat_osc_config_t * config)620 void VBAT_SetOscConfig(VBAT_Type *base, const vbat_osc_config_t *config)
621 {
622     uint32_t tmp32;
623 
624     if (config->enableCrystalOscillatorBypass == true)
625     {
626         base->OSCCTLA |= VBAT_OSCCTLA_OSC_BYP_EN_MASK;
627         while ((VBAT0->STATUSA & VBAT_STATUSA_OSC_RDY_MASK) == 0U)
628         {
629         }
630     }
631     else
632     {
633         tmp32 = base->OSCCTLA;
634 
635         if (config != NULL)
636         {
637             if (config->enableInternalCapBank)
638             {
639                 tmp32 &= ~(VBAT_OSCCTLA_EXTAL_CAP_SEL_MASK | VBAT_OSCCTLA_XTAL_CAP_SEL_MASK);
640                 tmp32 |= VBAT_OSCCTLA_EXTAL_CAP_SEL(config->extalCap) | VBAT_OSCCTLA_XTAL_CAP_SEL(config->xtalCap);
641                 tmp32 |= VBAT_OSCCTLA_CAP_SEL_EN_MASK;
642             }
643             else
644             {
645                 /* Disable the internal capacitance bank. */
646                 tmp32 &= ~VBAT_OSCCTLA_CAP_SEL_EN_MASK;
647             }
648 
649             tmp32 &= ~(VBAT_OSCCTLA_COARSE_AMP_GAIN_MASK);
650             tmp32 |= VBAT_OSCCTLA_COARSE_AMP_GAIN(config->coarseAdjustment);
651         }
652         base->OSCCTLA = tmp32;
653         while ((VBAT0->STATUSA & VBAT_STATUSA_OSC_RDY_MASK) == 0U)
654         {
655         }
656     }
657 }
658 
659 /* Clock Selection for IP */
660 /**
661  * brief   Configure the clock selection muxes.
662  * param   connection  : Clock to be configured.
663  * return  Nothing
664  */
CLOCK_AttachClk(clock_attach_id_t connection)665 void CLOCK_AttachClk(clock_attach_id_t connection)
666 {
667     uint16_t mux;
668     uint8_t sel;
669     uint16_t item;
670     uint32_t tmp32 = (uint32_t)connection;
671     uint32_t i;
672     volatile uint32_t *pClkSel;
673 
674     pClkSel = &(SYSCON->SYSTICKCLKSEL0);
675 
676     if (kNONE_to_NONE != connection)
677     {
678         for (i = 0U; i < 2U; i++)
679         {
680             if (tmp32 == 0U)
681             {
682                 break;
683             }
684             item = (uint16_t)GET_ID_ITEM(tmp32);
685             if (item != 0U)
686             {
687                 mux = (uint16_t)GET_ID_ITEM_MUX(item);
688                 sel = (uint8_t)GET_ID_ITEM_SEL(item);
689                 if (mux == CM_SCGRCCRSCSCLKSEL)
690                 {
691                     SCG0->RCCR = (SCG0->RCCR & ~(SCG_RCCR_SCS_MASK)) | SCG_RCCR_SCS(sel);
692                     while ((SCG0->CSR & SCG_CSR_SCS_MASK) != SCG_CSR_SCS(sel))
693                     {
694                     }
695                 }
696                 else
697                 {
698                     ((volatile uint32_t *)pClkSel)[mux] = sel;
699                 }
700             }
701             tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
702         }
703     }
704 }
705 
706 /* Return the actual clock attach id */
707 /**
708  * brief   Get the actual clock attach id.
709  * This fuction uses the offset in input attach id, then it reads the actual source value in
710  * the register and combine the offset to obtain an actual attach id.
711  * param   attachId  : Clock attach id to get.
712  * return  Clock source value.
713  */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)714 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
715 {
716     uint16_t mux;
717     uint32_t actualSel;
718     uint32_t tmp32 = (uint32_t)attachId;
719     uint32_t i;
720     uint32_t actualAttachId = 0U;
721     uint32_t selector       = GET_ID_SELECTOR(tmp32);
722     volatile uint32_t *pClkSel;
723 
724     pClkSel = &(SYSCON->SYSTICKCLKSEL0);
725 
726     if (kNONE_to_NONE == attachId)
727     {
728         return kNONE_to_NONE;
729     }
730 
731     for (i = 0U; i < 2U; i++)
732     {
733         mux = (uint16_t)GET_ID_ITEM_MUX(tmp32);
734         if (tmp32 != 0UL)
735         {
736             if (mux == CM_SCGRCCRSCSCLKSEL)
737             {
738                 actualSel = (uint32_t)((SCG0->RCCR & SCG_RCCR_SCS_MASK) >> SCG_RCCR_SCS_SHIFT);
739             }
740             else
741             {
742                 actualSel = (uint32_t)((volatile uint32_t *)pClkSel)[mux];
743             }
744 
745             /* Consider the combination of two registers */
746             actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
747         }
748         tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!<  pick up next descriptor */
749     }
750 
751     actualAttachId |= selector;
752 
753     return (clock_attach_id_t)actualAttachId;
754 }
755 
756 /* Set IP Clock Divider */
757 /**
758  * brief   Setup peripheral clock dividers.
759  * param   div_name    : Clock divider name
760  * param divided_by_value: Value to be divided
761  * return  Nothing
762  */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value)763 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value)
764 {
765     volatile uint32_t *pClkDiv;
766 
767     pClkDiv = &(SYSCON->SYSTICKCLKDIV[0]);
768     /* halt and reset clock dividers */
769     ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 0x3UL << 29U;
770 
771     if (divided_by_value == 0U) /*!<  halt */
772     {
773         ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 30U;
774     }
775     else
776     {
777         ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = (divided_by_value - 1U);
778     }
779 }
780 
781 /* Get IP clock dividers */
782 /**
783  * brief   Get peripheral clock dividers.
784  * param   div_name    : Clock divider name
785  * return  peripheral clock dividers
786  */
CLOCK_GetClkDiv(clock_div_name_t div_name)787 uint32_t CLOCK_GetClkDiv(clock_div_name_t div_name)
788 {
789     uint32_t div;
790     volatile uint32_t *pClkDiv;
791 
792     pClkDiv = &(SYSCON->SYSTICKCLKDIV[0]);
793 
794     if ((uint32_t)(((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] & (0x3UL << 29U)) != 0UL)
795     {
796         div = 0U;
797     }
798     else
799     {
800         div = (uint32_t)((((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] & 0xFFU) + 1U);
801     }
802 
803     return div;
804 }
805 
806 /* Halt IP Clock Divider */
807 /**
808  * brief   Setup peripheral clock dividers.
809  * param   Halt    : Clock divider name
810  * return  Nothing
811  */
CLOCK_HaltClkDiv(clock_div_name_t div_name)812 void CLOCK_HaltClkDiv(clock_div_name_t div_name)
813 {
814     volatile uint32_t *pClkDiv;
815 
816     pClkDiv = &(SYSCON->SYSTICKCLKDIV[0]);
817 
818     /* halt clock dividers */
819     ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 30U;
820 
821     return;
822 }
823 
824 /* enable system clocks */
825 /**
826  * brief   system clocks enable controls.
827  * param   mask : system clocks enable value
828  * return  Nothing
829  */
CLOCK_SetupClockCtrl(uint32_t mask)830 void CLOCK_SetupClockCtrl(uint32_t mask)
831 {
832     SYSCON->CLOCK_CTRL |= mask;
833 
834     return;
835 }
836 
837 /* Get IP Clk */
838 /*! brief  Return Frequency of selected clock
839  *  return Frequency of selected clock
840  */
CLOCK_GetFreq(clock_name_t clockName)841 uint32_t CLOCK_GetFreq(clock_name_t clockName)
842 {
843     uint32_t freq = 0U;
844 
845     switch (clockName)
846     {
847         case kCLOCK_MainClk:
848             freq = CLOCK_GetMainClkFreq();
849             break;
850         case kCLOCK_CoreSysClk:
851             freq = CLOCK_GetCoreSysClkFreq();
852             break;
853         case kCLOCK_BusClk:
854             freq = CLOCK_GetCoreSysClkFreq();
855             break;
856         case kCLOCK_SystickClk0:
857             freq = CLOCK_GetSystickClkFreq(0U);
858             break;
859         case kCLOCK_SystickClk1:
860             freq = CLOCK_GetSystickClkFreq(1U);
861             break;
862         case kCLOCK_ClockOut:
863             freq = CLOCK_GetClockOutClkFreq();
864             break;
865         case kCLOCK_Clk1M:
866             freq = CLOCK_GetClk1MFreq();
867             break;
868         case kCLOCK_Fro12M:
869             freq = CLOCK_GetFro12MFreq();
870             break;
871         case kCLOCK_FroHf:
872             freq = CLOCK_GetFroHfFreq();
873             break;
874         case kCLOCK_Clk48M:
875             freq = CLOCK_GetClk48MFreq();
876             break;
877         case kCLOCK_Clk144M:
878             freq = CLOCK_GetClk144MFreq();
879             break;
880         case kCLOCK_Clk16K0:
881             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToVbat);
882             break;
883         case kCLOCK_Clk16K1:
884             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToVsys);
885             break;
886         case kCLOCK_Clk16K2:
887             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToWake);
888             break;
889         case kCLOCK_Clk16K3:
890             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToMain);
891             break;
892         case kCLOCK_ExtClk:
893             freq = CLOCK_GetExtClkFreq();
894             break;
895         case kCLOCK_Osc32K0:
896             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
897             break;
898         case kCLOCK_Osc32K1:
899             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVsys);
900             break;
901         case kCLOCK_Osc32K2:
902             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToWake);
903             break;
904         case kCLOCK_Osc32K3:
905             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToMain);
906             break;
907         case kCLOCK_Pll0Out:
908             freq = CLOCK_GetPll0OutFreq();
909             break;
910         case kCLOCK_Pll1Out:
911             freq = CLOCK_GetPll1OutFreq();
912             break;
913         case kCLOCK_UsbPllOut:
914             // freq = CLOCK_GetPll0OutFreq();
915             break;
916         case kCLOCK_LpOsc:
917             freq = CLOCK_GetLposcFreq();
918             break;
919         default:
920             freq = 0U;
921             break;
922     }
923     return freq;
924 }
925 
926 /* Get CTimer Clk */
927 /*! brief  Return Frequency of CTimer functional Clock
928  *  return Frequency of CTimer functional Clock
929  */
CLOCK_GetCTimerClkFreq(uint32_t id)930 uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
931 {
932     uint32_t freq = 0U;
933 
934     switch (SYSCON->CTIMERCLKSEL[id])
935     {
936         case 0U:
937             freq = CLOCK_GetClk1MFreq();
938             break;
939         case 1U:
940             freq = CLOCK_GetPll0OutFreq();
941             break;
942         case 2U:
943             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
944             break;
945         case 3U:
946             freq = CLOCK_GetFroHfFreq();
947             break;
948         case 4U:
949             freq = CLOCK_GetFro12MFreq();
950             break;
951         case 5U:
952             freq = CLOCK_GetSaiMclkFreq(0U);
953             break;
954         case 6U:
955             freq = CLOCK_GetLposcFreq();
956             break;
957         case 8U:
958             freq = CLOCK_GetSaiMclkFreq(1U);
959             break;
960         case 9U:
961             freq = CLOCK_GetSaiTxBclkFreq(0U);
962             break;
963         case 10U:
964             freq = CLOCK_GetSaiRxBclkFreq(0U);
965             break;
966         case 11U:
967             freq = CLOCK_GetSaiTxBclkFreq(1U);
968             break;
969         case 12U:
970             freq = CLOCK_GetSaiRxBclkFreq(1U);
971             break;
972         default:
973             freq = 0U;
974             break;
975     }
976 
977     return freq / ((SYSCON->CTIMERCLKDIV[id] & 0xffU) + 1U);
978 }
979 
980 /* Get ADC Clk */
981 /*! brief  Return Frequency of Adc Clock
982  *  return Frequency of Adc.
983  */
CLOCK_GetAdcClkFreq(uint32_t id)984 uint32_t CLOCK_GetAdcClkFreq(uint32_t id)
985 {
986     uint32_t freq = 0U;
987     uint32_t div  = 0U;
988 
989     switch ((id == 0U) ? (SYSCON->ADC0CLKSEL) : (SYSCON->ADC1CLKSEL))
990     {
991         case 1U:
992             freq = CLOCK_GetPll0OutFreq();
993             break;
994         case 2U:
995             freq = CLOCK_GetFroHfFreq();
996             break;
997         case 3U:
998             freq = CLOCK_GetFro12MFreq();
999             break;
1000         case 4U:
1001             freq = CLOCK_GetExtClkFreq();
1002             break;
1003         case 5U:
1004             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1005             break;
1006         case 6U:
1007             // freq = CLOCK_GetUPllOutFreq();
1008             break;
1009         default:
1010             freq = 0U;
1011             break;
1012     }
1013 
1014     div = ((id == 0U) ? ((SYSCON->ADC0CLKDIV & SYSCON_ADC0CLKDIV_DIV_MASK) + 1U) :
1015                         ((SYSCON->ADC1CLKDIV & SYSCON_ADC1CLKDIV_DIV_MASK) + 1U));
1016 
1017     return freq / div;
1018 }
1019 
1020 /* Get USB0 Clk */
1021 /*! brief  Return Frequency of Usb0 Clock
1022  *  return Frequency of Usb0 Clock.
1023  */
CLOCK_GetUsb0ClkFreq(void)1024 uint32_t CLOCK_GetUsb0ClkFreq(void)
1025 {
1026     uint32_t freq = 0U;
1027 
1028     switch (SYSCON->USB0CLKSEL)
1029     {
1030         case 1U:
1031             freq = CLOCK_GetPll0OutFreq();
1032             break;
1033         case 3U:
1034             freq = CLOCK_GetFroHfFreq();
1035             break;
1036         case 4U:
1037             freq = CLOCK_GetExtClkFreq();
1038             break;
1039         case 5U:
1040             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1041             break;
1042         case 6U:
1043             // freq = CLOCK_GetUPllOutFreq();
1044             break;
1045         case 7U:
1046             freq = 0U;
1047             break;
1048 
1049         default:
1050             freq = 0U;
1051             break;
1052     }
1053 
1054     return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
1055 }
1056 
1057 /* Get LPFLEXCOMM Clk */
1058 /*! brief  Return Frequency of LPFLEXCOMM Clock
1059  *  return Frequency of LPFLEXCOMM Clock.
1060  */
CLOCK_GetLPFlexCommClkFreq(uint32_t id)1061 uint32_t CLOCK_GetLPFlexCommClkFreq(uint32_t id)
1062 {
1063     uint32_t freq = 0U;
1064 
1065     switch (SYSCON->FCCLKSEL[id])
1066     {
1067         case 1U:
1068             freq = CLOCK_GetPllClkDivFreq();
1069             break;
1070         case 2U:
1071             freq = CLOCK_GetFro12MFreq();
1072             break;
1073         case 3U:
1074             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
1075             break;
1076         case 4U:
1077             freq = CLOCK_GetClk1MFreq();
1078             break;
1079         case 5U:
1080             // freq = CLOCK_GetUPllOutFreq();
1081             break;
1082         case 6U:
1083             freq = CLOCK_GetLposcFreq();
1084             break;
1085         default:
1086             freq = 0U;
1087             break;
1088     }
1089 
1090     return freq / ((SYSCON->FLEXCOMMCLKDIV[id] & 0xffU) + 1U);
1091 }
1092 
1093 /* Get SCTIMER Clk */
1094 /*! brief  Return Frequency of SCTimer Clock
1095  *  return Frequency of SCTimer Clock.
1096  */
CLOCK_GetSctClkFreq(void)1097 uint32_t CLOCK_GetSctClkFreq(void)
1098 {
1099     uint32_t freq = 0U;
1100 
1101     switch (SYSCON->SCTCLKSEL)
1102     {
1103         case 1U:
1104             freq = CLOCK_GetPll0OutFreq();
1105             break;
1106         case 2U:
1107             freq = CLOCK_GetExtClkFreq();
1108             break;
1109         case 3U:
1110             freq = CLOCK_GetFroHfFreq();
1111             break;
1112         case 4U:
1113             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1114             break;
1115         case 5U:
1116             freq = CLOCK_GetSaiMclkFreq(0U);
1117             break;
1118         case 6U:
1119             // freq = CLOCK_GetUPllOutFreq();
1120             break;
1121         case 8U:
1122             freq = CLOCK_GetSaiMclkFreq(1U);
1123             break;
1124         default:
1125             freq = 0U;
1126             break;
1127     }
1128 
1129     return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
1130 }
1131 
1132 /* Get TSI Clk */
1133 /*! brief  Return Frequency of TSI Clock
1134  *  return Frequency of TSI Clock.
1135  */
CLOCK_GetTsiClkFreq(void)1136 uint32_t CLOCK_GetTsiClkFreq(void)
1137 {
1138     uint32_t freq = 0U;
1139 
1140     switch (SYSCON->TSICLKSEL)
1141     {
1142         case 2U:
1143             freq = CLOCK_GetExtClkFreq();
1144             break;
1145         case 4U:
1146             freq = CLOCK_GetFro12MFreq();
1147             break;
1148         default:
1149             freq = 0U;
1150             break;
1151     }
1152 
1153     return freq / ((SYSCON->TSICLKDIV & 0xffU) + 1U);
1154 }
1155 
1156 /* Get SINC FILTER Clk */
1157 /*! brief  Return Frequency of SINC FILTER Clock
1158  *  return Frequency of SINC FILTER Clock.
1159  */
CLOCK_GetSincFilterClkFreq(void)1160 uint32_t CLOCK_GetSincFilterClkFreq(void)
1161 {
1162     uint32_t freq = 0U;
1163 
1164     switch (SYSCON->SINCFILTCLKSEL)
1165     {
1166         case 1U:
1167             freq = CLOCK_GetPll0OutFreq();
1168             break;
1169         case 2U:
1170             freq = CLOCK_GetExtClkFreq();
1171             break;
1172         case 3U:
1173             freq = CLOCK_GetFroHfFreq();
1174             break;
1175         case 4U:
1176             freq = CLOCK_GetFro12MFreq();
1177             break;
1178         case 5U:
1179             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1180             break;
1181         case 6U:
1182             // freq = CLOCK_GetUPllOutFreq();
1183         default:
1184             freq = 0U;
1185             break;
1186     }
1187 
1188     return freq;
1189 }
1190 
1191 /* Get DAC Clk */
1192 /*! brief  Return Frequency of DAC Clock
1193  *  return Frequency of DAC.
1194  */
CLOCK_GetDacClkFreq(uint32_t id)1195 uint32_t CLOCK_GetDacClkFreq(uint32_t id)
1196 {
1197     uint32_t freq = 0U;
1198 
1199     switch (SYSCON->DAC[id].CLKSEL)
1200     {
1201         case 1U:
1202             freq = CLOCK_GetPll0OutFreq();
1203             break;
1204         case 2U:
1205             freq = CLOCK_GetExtClkFreq();
1206             break;
1207         case 3U:
1208             freq = CLOCK_GetFroHfFreq();
1209             break;
1210         case 4U:
1211             freq = CLOCK_GetFro12MFreq();
1212             break;
1213         case 5U:
1214             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1215             break;
1216         default:
1217             freq = 0U;
1218             break;
1219     }
1220 
1221     return freq / ((SYSCON->DAC[id].CLKDIV & SYSCON_DAC_CLKDIV_DIV_MASK) + 1U);
1222 }
1223 
1224 /* Get FlexSpi Clk */
1225 /*! brief  Return Frequency of FlexSpi clock
1226  *  return Frequency of FlexSpi Clock
1227  */
CLOCK_GetFlexspiClkFreq(void)1228 uint32_t CLOCK_GetFlexspiClkFreq(void)
1229 {
1230     uint32_t freq = 0U;
1231 
1232     switch (SYSCON->FLEXSPICLKSEL)
1233     {
1234         case 1U:
1235             freq = CLOCK_GetPll0OutFreq();
1236             break;
1237         case 3U:
1238             freq = CLOCK_GetFroHfFreq();
1239             break;
1240         case 5U:
1241             freq = CLOCK_GetPll1OutFreq();
1242             break;
1243         case 6U:
1244             // freq = CLOCK_GetUPllOutFreq();
1245         default:
1246             freq = 0U;
1247             break;
1248     }
1249 
1250     return freq / ((SYSCON->FLEXSPICLKDIV & SYSCON_FLEXSPICLKDIV_DIV_MASK) + 1U);
1251 }
1252 
1253 /* Get SYSTEM PLL0 Clk */
1254 /*! brief  Return Frequency of PLL0
1255  *  return Frequency of PLL0
1256  */
CLOCK_GetPll0OutFreq(void)1257 uint32_t CLOCK_GetPll0OutFreq(void)
1258 {
1259     uint32_t clkRate = 0;
1260     uint32_t prediv, postdiv;
1261     float workRate = 0.0F;
1262 
1263     /* Get the input clock frequency of PLL. */
1264     clkRate = CLOCK_GetPLL0InClockRate();
1265 
1266     /* If PLL0 is work */
1267     if (CLOCK_IsPLL0Locked() == true)
1268     {
1269         prediv  = findPll0PreDiv();
1270         postdiv = findPll0PostDiv();
1271         /* Adjust input clock */
1272         clkRate = clkRate / prediv;
1273         /* MDEC used for rate */
1274         workRate = (float)clkRate * (float)findPll0MMult();
1275         workRate /= (float)postdiv;
1276     }
1277 
1278     return (uint32_t)workRate;
1279 }
1280 
1281 /* Get SYSTEM PLL1 Clk */
1282 /*! brief  Return Frequency of PLL1
1283  *  return Frequency of PLL1
1284  */
CLOCK_GetPll1OutFreq(void)1285 uint32_t CLOCK_GetPll1OutFreq(void)
1286 {
1287     uint32_t clkRate = 0;
1288     uint32_t prediv, postdiv;
1289     float workRate = 0.0F;
1290 
1291     /* Get the input clock frequency of PLL. */
1292     clkRate = CLOCK_GetPLL1InClockRate();
1293 
1294     /* If PLL1 is work */
1295     if (CLOCK_IsPLL1Locked() == true)
1296     {
1297         prediv  = findPll1PreDiv();
1298         postdiv = findPll1PostDiv();
1299         /* Adjust input clock */
1300         clkRate = clkRate / prediv;
1301         /* MDEC used for rate */
1302         workRate = (float)clkRate * (float)findPll1MMult();
1303         workRate /= (float)postdiv;
1304     }
1305 
1306     return (uint32_t)workRate;
1307 }
1308 
1309 /* Get PLLClkDiv Clk */
1310 /*! brief  Return Frequency of PLLClkDiv
1311  *  return Frequency of PLLClkDiv
1312  */
CLOCK_GetPllClkDivFreq(void)1313 uint32_t CLOCK_GetPllClkDivFreq(void)
1314 {
1315     uint32_t freq = 0U;
1316 
1317     switch (SYSCON->PLLCLKDIVSEL)
1318     {
1319         case 0U:
1320             freq = CLOCK_GetPll0OutFreq();
1321             break;
1322         case 1U:
1323             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1324             break;
1325         default:
1326             freq = 0U;
1327             break;
1328     }
1329 
1330     return freq / ((SYSCON->PLLCLKDIV & SYSCON_PLLCLKDIV_DIV_MASK) + 1U);
1331 }
1332 
1333 /*!
1334  * brief Gets the external UPLL frequency.
1335  *
1336  * This function gets the external UPLL frequency in Hz.
1337  *
1338  * return The frequency of the external UPLL.
1339  */
CLOCK_GetExtUpllFreq(void)1340 uint32_t CLOCK_GetExtUpllFreq(void)
1341 {
1342     return s_extUpllFreq;
1343 }
1344 
1345 /*!
1346  * brief Sets the external UPLL frequency.
1347  *
1348  * This function sets the external UPLL frequency in Hz.
1349  * Call this function after the external PLL frequency is changed.
1350  * Otherwise, the APIs, which are used to get the frequency, may return an incorrect value.
1351  *
1352  * param The frequency of external UPLL.
1353  */
CLOCK_SetExtUpllFreq(uint32_t freq)1354 void CLOCK_SetExtUpllFreq(uint32_t freq)
1355 {
1356     s_extUpllFreq = freq;
1357 }
1358 
1359 /* Get I3C function Clk */
1360 /*! brief  Return Frequency of I3C function clock
1361  *  return Frequency of I3C function Clock
1362  */
CLOCK_GetI3cClkFreq(uint32_t id)1363 uint32_t CLOCK_GetI3cClkFreq(uint32_t id)
1364 {
1365     uint32_t freq = 0U;
1366     uint32_t div  = 0U;
1367 
1368     switch ((id == 0U) ? (SYSCON->I3C0FCLKSEL) : (SYSCON->I3C1FCLKSEL))
1369     {
1370         case 1U:
1371             freq = CLOCK_GetPll0OutFreq();
1372             break;
1373         case 2U:
1374             freq = CLOCK_GetExtClkFreq();
1375             break;
1376         case 3U:
1377             freq = CLOCK_GetFroHfFreq();
1378             break;
1379         case 5U:
1380             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1381             break;
1382         case 6U:
1383             // freq = CLOCK_GetUPllOutFreq();
1384         default:
1385             freq = 0U;
1386             break;
1387     }
1388 
1389     div = ((id == 0U) ? ((SYSCON->I3C0FCLKDIV & SYSCON_I3C0FCLKDIV_DIV_MASK) + 1U) :
1390                         ((SYSCON->I3C1FCLKDIV & SYSCON_I3C1FCLKDIV_DIV_MASK) + 1U));
1391 
1392     return freq / div;
1393 }
1394 
1395 /* Get I3C function slow TC Clk */
1396 /*! brief  Return Frequency of I3C function Slow TC clock
1397  *  return Frequency of I3C function slow TC Clock
1398  */
CLOCK_GetI3cSTCClkFreq(uint32_t id)1399 uint32_t CLOCK_GetI3cSTCClkFreq(uint32_t id)
1400 {
1401     uint32_t freq = 0U;
1402     uint32_t div  = 0U;
1403 
1404     switch ((id == 0U) ? (SYSCON->I3C0FCLKSTCSEL) : (SYSCON->I3C1FCLKSTCSEL))
1405     {
1406         case 0U:
1407             switch ((id == 0U) ? (SYSCON->I3C0FCLKSEL) : (SYSCON->I3C1FCLKSEL))
1408             {
1409                 case 1U:
1410                     freq = CLOCK_GetPll0OutFreq();
1411                     break;
1412                 case 2U:
1413                     freq = CLOCK_GetExtClkFreq();
1414                     break;
1415                 case 3U:
1416                     freq = CLOCK_GetFroHfFreq();
1417                     break;
1418                 case 5U:
1419                     freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1420                     break;
1421                 case 6U:
1422                     // freq = CLOCK_GetUPllOutFreq();
1423                 default:
1424                     freq = 0U;
1425                     break;
1426             }
1427             break;
1428         case 1U:
1429             freq = CLOCK_GetClk1MFreq();
1430             break;
1431         default:
1432             freq = 0U;
1433             break;
1434     }
1435 
1436     div = ((id == 0U) ? ((SYSCON->I3C0FCLKSTCDIV & SYSCON_I3C0FCLKSTCDIV_DIV_MASK) + 1U) :
1437                         ((SYSCON->I3C1FCLKSTCDIV & SYSCON_I3C1FCLKSTCDIV_DIV_MASK) + 1U));
1438 
1439     return freq / div;
1440 }
1441 
1442 /* Get I3C function slow Clk */
1443 /*! brief  Return Frequency of I3C function Slow clock
1444  *  return Frequency of I3C function slow Clock
1445  */
CLOCK_GetI3cSClkFreq(uint32_t id)1446 uint32_t CLOCK_GetI3cSClkFreq(uint32_t id)
1447 {
1448     uint32_t freq = 0U;
1449     uint32_t div  = 0U;
1450 
1451     switch ((id == 0U) ? (SYSCON->I3C0FCLKSSEL) : (SYSCON->I3C1FCLKSSEL))
1452     {
1453         case 0U:
1454             freq = CLOCK_GetClk1MFreq();
1455             break;
1456         default:
1457             freq = 0U;
1458             break;
1459     }
1460 
1461     div = ((id == 0U) ? ((SYSCON->I3C0FCLKSDIV & SYSCON_I3C0FCLKSDIV_DIV_MASK) + 1U) :
1462                         ((SYSCON->I3C1FCLKSDIV & SYSCON_I3C1FCLKSDIV_DIV_MASK) + 1U));
1463 
1464     return freq / div;
1465 }
1466 
1467 /* Get MICFIL Clk */
1468 /*! brief  Return Frequency of MICFIL
1469  *  return Frequency of MICFIL
1470  */
CLOCK_GetMicfilClkFreq(void)1471 uint32_t CLOCK_GetMicfilClkFreq(void)
1472 {
1473     uint32_t freq = 0U;
1474 
1475     switch (SYSCON->MICFILFCLKSEL)
1476     {
1477         case 0U:
1478             freq = CLOCK_GetFro12MFreq();
1479             break;
1480         case 1U:
1481             freq = CLOCK_GetPll0OutFreq();
1482             break;
1483         case 2U:
1484             freq = CLOCK_GetExtClkFreq();
1485             break;
1486         case 3U:
1487             freq = CLOCK_GetFroHfFreq();
1488             break;
1489         case 4U:
1490             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1491             break;
1492         case 5U:
1493             freq = CLOCK_GetSaiMclkFreq(0U);
1494             break;
1495         case 6U:
1496             // freq = CLOCK_GetUPllOutFreq();
1497         case 8U:
1498             freq = CLOCK_GetSaiMclkFreq(1U);
1499             break;
1500         default:
1501             freq = 0U;
1502             break;
1503     }
1504 
1505     return freq / ((SYSCON->MICFILFCLKDIV & SYSCON_MICFILFCLKDIV_DIV_MASK) + 1U);
1506 }
1507 
1508 /* Get uSDHC Clk */
1509 /*! brief  Return Frequency of uSDHC
1510  *  return Frequency of uSDHC
1511  */
CLOCK_GetUsdhcClkFreq(void)1512 uint32_t CLOCK_GetUsdhcClkFreq(void)
1513 {
1514     uint32_t freq = 0U;
1515 
1516     switch (SYSCON->USDHCCLKSEL)
1517     {
1518         case 1U:
1519             freq = CLOCK_GetPll0OutFreq();
1520             break;
1521         case 2U:
1522             freq = CLOCK_GetExtClkFreq();
1523             break;
1524         case 3U:
1525             freq = CLOCK_GetFroHfFreq();
1526             break;
1527         case 4U:
1528             freq = CLOCK_GetFro12MFreq();
1529             break;
1530         case 5U:
1531             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK1DIV) & 0xffU) + 1U);
1532             break;
1533         case 6U:
1534             // freq = CLOCK_GetUPllOutFreq();
1535         default:
1536             freq = 0U;
1537             break;
1538     }
1539 
1540     return freq / ((SYSCON->USDHCCLKDIV & SYSCON_USDHCCLKDIV_DIV_MASK) + 1U);
1541 }
1542 
1543 /* Get FLEXIO Clk */
1544 /*! brief  Return Frequency of FLEXIO
1545  *  return Frequency of FLEXIO
1546  */
CLOCK_GetFlexioClkFreq(void)1547 uint32_t CLOCK_GetFlexioClkFreq(void)
1548 {
1549     uint32_t freq = 0U;
1550 
1551     switch (SYSCON->FLEXIOCLKSEL)
1552     {
1553         case 1U:
1554             freq = CLOCK_GetPll0OutFreq();
1555             break;
1556         case 2U:
1557             freq = CLOCK_GetExtClkFreq();
1558             break;
1559         case 3U:
1560             freq = CLOCK_GetFroHfFreq();
1561             break;
1562         case 4U:
1563             freq = CLOCK_GetFro12MFreq();
1564             break;
1565         case 5U:
1566             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1567             break;
1568         case 6U:
1569             // freq = CLOCK_GetUPllOutFreq();
1570         default:
1571             freq = 0U;
1572             break;
1573     }
1574 
1575     return freq / ((SYSCON->FLEXIOCLKDIV & SYSCON_FLEXIOCLKDIV_DIV_MASK) + 1U);
1576 }
1577 
1578 /* Get FLEXCAN Clk */
1579 /*! brief  Return Frequency of FLEXCAN
1580  *  return Frequency of FLEXCAN
1581  */
CLOCK_GetFlexcanClkFreq(uint32_t id)1582 uint32_t CLOCK_GetFlexcanClkFreq(uint32_t id)
1583 {
1584     uint32_t freq = 0U;
1585     uint32_t div  = 0U;
1586 
1587     switch ((id == 0U) ? (SYSCON->FLEXCAN0CLKSEL) : (SYSCON->FLEXCAN1CLKSEL))
1588     {
1589         case 1U:
1590             freq = CLOCK_GetPll0OutFreq();
1591             break;
1592         case 2U:
1593             freq = CLOCK_GetExtClkFreq();
1594             break;
1595         case 3U:
1596             freq = CLOCK_GetFroHfFreq();
1597             break;
1598         case 5U:
1599             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1600             break;
1601         case 6U:
1602             // freq = CLOCK_GetUPllOutFreq();
1603         default:
1604             freq = 0U;
1605             break;
1606     }
1607 
1608     div = ((id == 0U) ? ((SYSCON->FLEXCAN0CLKDIV & SYSCON_FLEXCAN0CLKDIV_DIV_MASK) + 1U) :
1609                         ((SYSCON->FLEXCAN1CLKDIV & SYSCON_FLEXCAN1CLKDIV_DIV_MASK) + 1U));
1610 
1611     return freq / div;
1612 }
1613 
1614 /* Get Ethernet RMII Clk */
1615 /*! brief  Return Frequency of Ethernet RMII
1616  *  return Frequency of Ethernet RMII
1617  */
CLOCK_GetEnetRmiiClkFreq(void)1618 uint32_t CLOCK_GetEnetRmiiClkFreq(void)
1619 {
1620     uint32_t freq = 0U;
1621 
1622     switch (SYSCON->ENETRMIICLKSEL)
1623     {
1624         case 1U:
1625             freq = CLOCK_GetPll0OutFreq();
1626             break;
1627         case 2U:
1628             freq = CLOCK_GetExtClkFreq();
1629             break;
1630         case 5U:
1631             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1632             break;
1633         default:
1634             freq = 0U;
1635             break;
1636     }
1637 
1638     return freq / ((SYSCON->ENETRMIICLKDIV & SYSCON_ENETRMIICLKDIV_DIV_MASK) + 1U);
1639 }
1640 
1641 /* Get Ethernet PTP REF Clk */
1642 /*! brief  Return Frequency of Ethernet PTP REF
1643  *  return Frequency of Ethernet PTP REF
1644  */
CLOCK_GetEnetPtpRefClkFreq(void)1645 uint32_t CLOCK_GetEnetPtpRefClkFreq(void)
1646 {
1647     uint32_t freq = 0U;
1648 
1649     switch (SYSCON->ENETPTPREFCLKSEL)
1650     {
1651         case 1U:
1652             freq = CLOCK_GetPll0OutFreq();
1653             break;
1654         case 2U:
1655             freq = CLOCK_GetExtClkFreq();
1656             break;
1657         case 4U: // Todo enet0_tx_clk clock
1658             freq = 0U;
1659             break;
1660         case 5U:
1661             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1662             break;
1663         default:
1664             freq = 0U;
1665             break;
1666     }
1667 
1668     return freq / ((SYSCON->ENETPTPREFCLKDIV & SYSCON_ENETPTPREFCLKDIV_DIV_MASK) + 1U);
1669 }
1670 
1671 /* Get ENET TX CLK */
1672 /*! brief  Initialize the ENET TX CLK to given frequency.
1673  *  return Nothing
1674  */
CLOCK_SetupEnetTxClk(uint32_t iFreq)1675 void CLOCK_SetupEnetTxClk(uint32_t iFreq)
1676 {
1677     s_Enet_Tx_Clk_Freq = iFreq;
1678 
1679     return;
1680 }
1681 
1682 /* Get ENET TX CLK */
1683 /*! brief  Return Frequency of ENET TX CLK
1684  *  return Frequency of ENET TX CLK
1685  */
CLOCK_GetEnetTxClkFreq(void)1686 uint32_t CLOCK_GetEnetTxClkFreq(void)
1687 {
1688     return s_Enet_Tx_Clk_Freq;
1689 }
1690 
1691 /* Get EWM0 Clk */
1692 /*! brief  Return Frequency of EWM0
1693  *  return Frequency of EWM0
1694  */
CLOCK_GetEwm0ClkFreq(void)1695 uint32_t CLOCK_GetEwm0ClkFreq(void)
1696 {
1697     uint32_t freq = 0U;
1698 
1699     switch (SYSCON->EWM0CLKSEL)
1700     {
1701         case 1U:
1702             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToWake);
1703             break;
1704         case 2U:
1705             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToWake);
1706             break;
1707         default:
1708             freq = 0U;
1709             break;
1710     }
1711 
1712     return freq;
1713 }
1714 
1715 /* Get Watchdog Clk */
1716 /*! brief  Return Frequency of Watchdog
1717  *  return Frequency of Watchdog
1718  */
CLOCK_GetWdtClkFreq(uint32_t id)1719 uint32_t CLOCK_GetWdtClkFreq(uint32_t id)
1720 {
1721     uint32_t freq = 0U;
1722     uint32_t div  = 0U;
1723 
1724     if (id == 0U)
1725     {
1726         freq = CLOCK_GetClk1MFreq();
1727     }
1728     else
1729     {
1730         switch (SYSCON->WDT1CLKSEL)
1731         {
1732             case 0U:
1733                 freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToWake);
1734                 break;
1735             case 1U:
1736                 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
1737                 break;
1738             case 2U:
1739                 freq = CLOCK_GetClk1MFreq();
1740                 break;
1741             case 3U:
1742                 freq = CLOCK_GetClk1MFreq();
1743                 break;
1744             default:
1745                 freq = 0U;
1746                 break;
1747         }
1748     }
1749 
1750     div = ((id == 0U) ? ((SYSCON->WDT0CLKDIV & SYSCON_WDT0CLKDIV_DIV_MASK) + 1U) :
1751                         ((SYSCON->WDT1CLKDIV & SYSCON_WDT1CLKDIV_DIV_MASK) + 1U));
1752 
1753     return freq / div;
1754 }
1755 
1756 /* Get OSTIMER Clk */
1757 /*! brief  Return Frequency of OSTIMER
1758  *  return Frequency of OSTIMER
1759  */
CLOCK_GetOstimerClkFreq(void)1760 uint32_t CLOCK_GetOstimerClkFreq(void)
1761 {
1762     uint32_t freq = 0U;
1763 
1764     switch (SYSCON->OSTIMERCLKSEL)
1765     {
1766         case 0U:
1767             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToWake);
1768             break;
1769         case 1U:
1770             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToWake);
1771             break;
1772         case 2U:
1773             freq = CLOCK_GetClk1MFreq();
1774             break;
1775         default:
1776             freq = 0U;
1777             break;
1778     }
1779 
1780     return freq;
1781 }
1782 
1783 /* Get CMP Function Clk */
1784 /*! brief  Return Frequency of CMP Function
1785  *  return Frequency of CMP Function
1786  */
CLOCK_GetCmpFClkFreq(uint32_t id)1787 uint32_t CLOCK_GetCmpFClkFreq(uint32_t id)
1788 {
1789     uint32_t freq = 0U;
1790     uint32_t div  = 0U;
1791 
1792     switch ((id == 0U) ? (SYSCON->CMP0FCLKSEL) : ((id == 1U) ? (SYSCON->CMP1FCLKSEL) : (SYSCON->CMP2FCLKSEL)))
1793     {
1794         case 1U:
1795             freq = CLOCK_GetPll0OutFreq();
1796             break;
1797         case 2U:
1798             freq = CLOCK_GetFroHfFreq();
1799             break;
1800         case 3U:
1801             freq = CLOCK_GetFro12MFreq();
1802             break;
1803         case 4U:
1804             freq = CLOCK_GetExtClkFreq();
1805             break;
1806         case 5U:
1807             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1808             break;
1809         case 6U:
1810             // freq = CLOCK_GetUPllOutFreq();
1811         default:
1812             freq = 0U;
1813             break;
1814     }
1815 
1816     div = ((id == 0U) ? ((SYSCON->CMP0FCLKDIV & SYSCON_CMP0FCLKDIV_DIV_MASK) + 1U) :
1817                         ((id == 1U) ? ((SYSCON->CMP1FCLKDIV & SYSCON_CMP1FCLKDIV_DIV_MASK) + 1U) :
1818                                       ((SYSCON->CMP2FCLKDIV & SYSCON_CMP2FCLKDIV_DIV_MASK) + 1U)));
1819 
1820     return freq / div;
1821 }
1822 
1823 /* Get CMP Round Robin Clk */
1824 /*! brief  Return Frequency of CMP Round Robin
1825  *  return Frequency of CMP Round Robin
1826  */
CLOCK_GetCmpRRClkFreq(uint32_t id)1827 uint32_t CLOCK_GetCmpRRClkFreq(uint32_t id)
1828 {
1829     uint32_t freq = 0U;
1830     uint32_t div  = 0U;
1831 
1832     switch ((id == 0U) ? (SYSCON->CMP0RRCLKSEL) : ((id == 1U) ? (SYSCON->CMP1RRCLKSEL) : (SYSCON->CMP2RRCLKSEL)))
1833     {
1834         case 1U:
1835             freq = CLOCK_GetPll0OutFreq();
1836             break;
1837         case 2U:
1838             freq = CLOCK_GetFroHfFreq();
1839             break;
1840         case 3U:
1841             freq = CLOCK_GetFro12MFreq();
1842             break;
1843         case 4U:
1844             freq = CLOCK_GetExtClkFreq();
1845             break;
1846         case 5U:
1847             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1848             break;
1849         case 6U:
1850             // freq = CLOCK_GetUPllOutFreq();
1851         default:
1852             freq = 0U;
1853             break;
1854     }
1855 
1856     div = ((id == 0U) ? ((SYSCON->CMP0RRCLKDIV & SYSCON_CMP0RRCLKDIV_DIV_MASK) + 1U) :
1857                         ((id == 1U) ? ((SYSCON->CMP1RRCLKDIV & SYSCON_CMP1RRCLKDIV_DIV_MASK) + 1U) :
1858                                       ((SYSCON->CMP2RRCLKDIV & SYSCON_CMP2RRCLKDIV_DIV_MASK) + 1U)));
1859 
1860     return freq / div;
1861 }
1862 
1863 /* Get SAI Clk */
1864 /*! brief  Return Frequency of SAI
1865  *  return Frequency of SAI
1866  */
CLOCK_GetSaiClkFreq(uint32_t id)1867 uint32_t CLOCK_GetSaiClkFreq(uint32_t id)
1868 {
1869     uint32_t freq = 0U;
1870     uint32_t div  = 0U;
1871 
1872     switch ((id == 0U) ? (SYSCON->SAI0CLKSEL) : (SYSCON->SAI1CLKSEL))
1873     {
1874         case 1U:
1875             freq = CLOCK_GetPll0OutFreq();
1876             break;
1877         case 2U:
1878             freq = CLOCK_GetExtClkFreq();
1879             break;
1880         case 3U:
1881             freq = CLOCK_GetFroHfFreq();
1882             break;
1883         case 4U:
1884             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1885             break;
1886         case 6U:
1887             // freq = CLOCK_GetUPllOutFreq();
1888         default:
1889             freq = 0U;
1890             break;
1891     }
1892 
1893     div = ((id == 0U) ? ((SYSCON->SAI0CLKDIV & SYSCON_SAI0CLKDIV_DIV_MASK) + 1U) :
1894                         ((SYSCON->SAI1CLKDIV & SYSCON_SAI1CLKDIV_DIV_MASK) + 1U));
1895 
1896     return freq / div;
1897 }
1898 
1899 /* Get SAI MCLK */
1900 /*! brief  Initialize the SAI MCLK to given frequency.
1901  *  return Nothing
1902  */
CLOCK_SetupSaiMclk(uint32_t id,uint32_t iFreq)1903 void CLOCK_SetupSaiMclk(uint32_t id, uint32_t iFreq)
1904 {
1905     s_Sai_Mclk_Freq[id] = iFreq;
1906 
1907     return;
1908 }
1909 
1910 /* Get SAI TX BCLK */
1911 /*! brief  Initialize the SAI TX BCLK to given frequency.
1912  *  return Nothing
1913  */
CLOCK_SetupSaiTxBclk(uint32_t id,uint32_t iFreq)1914 void CLOCK_SetupSaiTxBclk(uint32_t id, uint32_t iFreq)
1915 {
1916     s_Sai_Tx_Bclk_Freq[id] = iFreq;
1917 
1918     return;
1919 }
1920 
1921 /* Get SAI RX BCLK */
1922 /*! brief  Initialize the SAI RX BCLK to given frequency.
1923  *  return Nothing
1924  */
CLOCK_SetupSaiRxBclk(uint32_t id,uint32_t iFreq)1925 void CLOCK_SetupSaiRxBclk(uint32_t id, uint32_t iFreq)
1926 {
1927     s_Sai_Rx_Bclk_Freq[id] = iFreq;
1928 
1929     return;
1930 }
1931 
1932 /* Get SAI MCLK */
1933 /*! brief  Return Frequency of SAI MCLK
1934  *  return Frequency of SAI MCLK
1935  */
CLOCK_GetSaiMclkFreq(uint32_t id)1936 uint32_t CLOCK_GetSaiMclkFreq(uint32_t id)
1937 {
1938     return s_Sai_Mclk_Freq[id];
1939 }
1940 
1941 /* Get SAI TX BCLK */
1942 /*! brief  Return Frequency of SAI TX BCLK
1943  *  return Frequency of SAI TX BCLK
1944  */
CLOCK_GetSaiTxBclkFreq(uint32_t id)1945 uint32_t CLOCK_GetSaiTxBclkFreq(uint32_t id)
1946 {
1947     return s_Sai_Tx_Bclk_Freq[id];
1948 }
1949 
1950 /* Get SAI RX BCLK */
1951 /*! brief  Return Frequency of SAI RX BCLK
1952  *  return Frequency of SAI RX BCLK
1953  */
CLOCK_GetSaiRxBclkFreq(uint32_t id)1954 uint32_t CLOCK_GetSaiRxBclkFreq(uint32_t id)
1955 {
1956     return s_Sai_Rx_Bclk_Freq[id];
1957 }
1958 
1959 /* Get EMVSIM Clk */
1960 /*! brief  Return Frequency of EMVSIM
1961  *  return Frequency of EMVSIM
1962  */
CLOCK_GetEmvsimClkFreq(uint32_t id)1963 uint32_t CLOCK_GetEmvsimClkFreq(uint32_t id)
1964 {
1965     uint32_t freq = 0U;
1966     uint32_t div  = 0U;
1967 
1968     switch ((id == 0U) ? (SYSCON->EMVSIM0CLKSEL) : (SYSCON->EMVSIM1CLKSEL))
1969     {
1970         case 1U:
1971             freq = CLOCK_GetPll0OutFreq();
1972             break;
1973         case 2U:
1974             freq = CLOCK_GetExtClkFreq();
1975             break;
1976         case 3U:
1977             freq = CLOCK_GetFroHfFreq();
1978             break;
1979         case 4U:
1980             freq = CLOCK_GetFro12MFreq();
1981             break;
1982         case 5U:
1983             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1984             break;
1985         default:
1986             freq = 0U;
1987             break;
1988     }
1989 
1990     div = ((id == 0U) ? ((SYSCON->EMVSIM0CLKDIV & SYSCON_EMVSIM0CLKDIV_DIV_MASK) + 1U) :
1991                         ((SYSCON->EMVSIM1CLKDIV & SYSCON_EMVSIM1CLKDIV_DIV_MASK) + 1U));
1992 
1993     return freq / div;
1994 }
1995 
1996 /* Return System PLL input clock rate */
1997 /*! brief    Return  PLL0 input clock rate
1998  *  return    PLL0 input clock rate
1999  */
CLOCK_GetPLL0InClockRate(void)2000 uint32_t CLOCK_GetPLL0InClockRate(void)
2001 {
2002     uint32_t clkRate = 0U;
2003 
2004     switch ((SCG0->APLLCTRL & SCG_APLLCTRL_SOURCE_MASK) >> SCG_APLLCTRL_SOURCE_SHIFT)
2005     {
2006         case 0x00U:
2007             clkRate = CLOCK_GetExtClkFreq();
2008             break;
2009         case 0x01U:
2010             clkRate = CLOCK_GetClk48MFreq();
2011             break;
2012         case 0x02U:
2013             clkRate = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2014             break;
2015         default:
2016             clkRate = 0U;
2017             break;
2018     }
2019 
2020     return clkRate;
2021 }
2022 
2023 /* Return PLL1 input clock rate */
CLOCK_GetPLL1InClockRate(void)2024 uint32_t CLOCK_GetPLL1InClockRate(void)
2025 {
2026     uint32_t clkRate = 0U;
2027 
2028     switch ((SCG0->SPLLCTRL & SCG_SPLLCTRL_SOURCE_MASK) >> SCG_SPLLCTRL_SOURCE_SHIFT)
2029     {
2030         case 0x00U:
2031             clkRate = CLOCK_GetExtClkFreq();
2032             break;
2033         case 0x01U:
2034             clkRate = CLOCK_GetClk48MFreq();
2035             break;
2036         case 0x02U:
2037             clkRate = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2038             break;
2039         default:
2040             clkRate = 0U;
2041             break;
2042     }
2043 
2044     return clkRate;
2045 }
2046 
2047 /* Return PLL output clock rate from setup structure */
2048 /*! brief    Return PLL0 output clock rate from setup structure
2049  *  param    pSetup : Pointer to a PLL setup structure
2050  *  return   PLL0 output clock rate the setup structure will generate
2051  */
CLOCK_GetPLLOutFromSetup(pll_setup_t * pSetup)2052 uint32_t CLOCK_GetPLLOutFromSetup(pll_setup_t *pSetup)
2053 {
2054     uint32_t clkRate = 0;
2055     uint32_t prediv, postdiv;
2056     float workRate = 0.0F;
2057 
2058     /* Get the input clock frequency of PLL. */
2059     clkRate = CLOCK_GetPLLInClockRateFromSetup(pSetup);
2060 
2061     prediv  = findPllPreDivFromSetup(pSetup);
2062     postdiv = findPllPostDivFromSetup(pSetup);
2063     /* Adjust input clock */
2064     clkRate = clkRate / prediv;
2065     /* MDEC used for rate */
2066     workRate = (float)clkRate * (float)findPllMMultFromSetup(pSetup);
2067     workRate /= (float)postdiv;
2068 
2069     return (uint32_t)workRate;
2070 }
2071 
2072 /* Set PLL output based on the passed PLL setup data */
2073 /*! brief    Set PLL output based on the passed PLL setup data
2074  *  param    pControl    : Pointer to populated PLL control structure to generate setup with
2075  *  param    pSetup      : Pointer to PLL setup structure to be filled
2076  *  return   PLL_ERROR_SUCCESS on success, or PLL setup error code
2077  *  note Actual frequency for setup may vary from the desired frequency based on the
2078  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.
2079  */
CLOCK_SetupPLLData(pll_config_t * pControl,pll_setup_t * pSetup)2080 pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
2081 {
2082     uint32_t inRate;
2083     bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0UL);
2084 
2085     pll_error_t pllError;
2086 
2087     /* Get PLL Input Clock Rate */
2088     switch (pControl->inputSource)
2089     {
2090         case (uint32_t)kPll_ClkSrcSysOsc:
2091             inRate = CLOCK_GetExtClkFreq();
2092             break;
2093         case (uint32_t)kPll_ClkSrcFirc:
2094             inRate = CLOCK_GetClk48MFreq();
2095             break;
2096         case (uint32_t)kPll_ClkSrcRosc:
2097             inRate = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2098             break;
2099         default:
2100             inRate = 0U;
2101             break;
2102     }
2103 
2104     /* PLL flag options */
2105     pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup, useSS);
2106     pSetup->pllctrl |= (uint32_t)pControl->inputSource;
2107     if ((useSS) && (pllError == kStatus_PLL_Success))
2108     {
2109         /* If using SS mode, then some tweaks are made to the generated setup */
2110         pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
2111         if (pControl->mfDither)
2112         {
2113             pSetup->pllsscg[1] |= (1UL << SCG_APLLSSCG1_DITHER_SHIFT);
2114         }
2115     }
2116 
2117     return pllError;
2118 }
2119 
2120 /* Setup PLL Frequency from pre-calculated value */
2121 /**
2122  * brief Set PLL0 output from PLL setup structure (precise frequency)
2123  * param pSetup  : Pointer to populated PLL setup structure
2124  * return    kStatus_PLL_Success on success, or PLL setup error code
2125  * note  This function will power off the PLL, setup the PLL with the
2126  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2127  * and adjust system voltages to the new PLL rate. The function will not
2128  * alter any source clocks (ie, main systen clock) that may use the PLL,
2129  * so these should be setup prior to and after exiting the function.
2130  */
CLOCK_SetPLL0Freq(const pll_setup_t * pSetup)2131 pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
2132 {
2133     uint32_t inRate, clkRate, prediv;
2134 
2135     /* Enable LDO */
2136     SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
2137 
2138     /* Power off PLL0 and disable PLL0 clock during setup changes */
2139     SCG0->APLLCSR &= ~(SCG_APLLCSR_APLLPWREN_MASK | SCG_APLLCSR_APLLCLKEN_MASK);
2140 
2141     /* Write PLL setup data */
2142     SCG0->APLLCTRL  = pSetup->pllctrl;
2143     SCG0->APLLNDIV  = pSetup->pllndiv;
2144     SCG0->APLLNDIV  = pSetup->pllndiv | (1UL << SCG_APLLNDIV_NREQ_SHIFT); /* latch */
2145     SCG0->APLLPDIV  = pSetup->pllpdiv;
2146     SCG0->APLLPDIV  = pSetup->pllpdiv | (1UL << SCG_APLLPDIV_PREQ_SHIFT); /* latch */
2147     SCG0->APLLMDIV  = pSetup->pllmdiv;
2148     SCG0->APLLMDIV  = pSetup->pllmdiv | (1UL << SCG_APLLMDIV_MREQ_SHIFT); /* latch */
2149     SCG0->APLLSSCG0 = pSetup->pllsscg[0];
2150     SCG0->APLLSSCG1 = pSetup->pllsscg[1];
2151 
2152     /* Unlock APLLLOCK_CNFG register */
2153     SCG0->TRIM_LOCK = 0x5a5a0001;
2154 
2155     /* Configure lock time of APLL stable, value = 500us/x+300, where x is the period of clk_ref (clk_in/N). */
2156     inRate = CLOCK_GetPLL0InClockRate();
2157     prediv = findPll0PreDiv();
2158     /* Adjust input clock */
2159     clkRate             = inRate / prediv;
2160     SCG0->APLLLOCK_CNFG = SCG_APLLLOCK_CNFG_LOCK_TIME(clkRate / 2000U + 300U);
2161 
2162     /* Power on PLL0 and enable PLL0 clock */
2163     SCG0->APLLCSR |= (SCG_APLLCSR_APLLPWREN_MASK | SCG_APLLCSR_APLLCLKEN_MASK);
2164 
2165     /* Wait for APLL lock */
2166     while (CLOCK_IsPLL0Locked() == false)
2167     {
2168     }
2169 
2170     if (pSetup->pllRate != CLOCK_GetPll0OutFreq())
2171     {
2172         return kStatus_PLL_OutputError;
2173     }
2174 
2175     return kStatus_PLL_Success;
2176 }
2177 
2178 /* Setup PLL1 Frequency from pre-calculated value */
2179 /**
2180  * brief Set PLL1 output from PLL setup structure (precise frequency)
2181  * param pSetup  : Pointer to populated PLL setup structure
2182  * return    kStatus_PLL_Success on success, or PLL setup error code
2183  * note  This function will power off the PLL, setup the PLL with the
2184  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2185  * and adjust system voltages to the new PLL rate. The function will not
2186  * alter any source clocks (ie, main systen clock) that may use the PLL,
2187  * so these should be setup prior to and after exiting the function.
2188  */
CLOCK_SetPLL1Freq(const pll_setup_t * pSetup)2189 pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
2190 {
2191     uint32_t inRate, clkRate, prediv;
2192 
2193     /* Enable LDO */
2194     SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
2195 
2196     /* Power off PLL1 and disable PLL1 clock during setup changes */
2197     SCG0->SPLLCSR &= ~(SCG_SPLLCSR_SPLLPWREN_MASK | SCG_SPLLCSR_SPLLCLKEN_MASK);
2198 
2199     /* Write PLL setup data */
2200     SCG0->SPLLCTRL  = pSetup->pllctrl;
2201     SCG0->SPLLNDIV  = pSetup->pllndiv;
2202     SCG0->SPLLNDIV  = pSetup->pllndiv | (1UL << SCG_SPLLNDIV_NREQ_SHIFT); /* latch */
2203     SCG0->SPLLPDIV  = pSetup->pllpdiv;
2204     SCG0->SPLLPDIV  = pSetup->pllpdiv | (1UL << SCG_SPLLPDIV_PREQ_SHIFT); /* latch */
2205     SCG0->SPLLMDIV  = pSetup->pllmdiv;
2206     SCG0->SPLLMDIV  = pSetup->pllmdiv | (1UL << SCG_SPLLMDIV_MREQ_SHIFT); /* latch */
2207     SCG0->SPLLSSCG0 = pSetup->pllsscg[0];
2208     SCG0->SPLLSSCG1 = pSetup->pllsscg[1];
2209 
2210     /* Unlock SPLLLOCK_CNFG register */
2211     SCG0->TRIM_LOCK = 0x5a5a0001;
2212 
2213     /* Configure lock time of APLL stable, value = 500μs/x+300, where x is the period of clk_ref (clk_in/N). */
2214     inRate = CLOCK_GetPLL1InClockRate();
2215     prediv = findPll1PreDiv();
2216     /* Adjust input clock */
2217     clkRate             = inRate / prediv;
2218     SCG0->SPLLLOCK_CNFG = SCG_SPLLLOCK_CNFG_LOCK_TIME(clkRate / 2000U + 300U);
2219 
2220     /* Power on PLL1 and enable PLL1 clock */
2221     SCG0->SPLLCSR |= (SCG_SPLLCSR_SPLLPWREN_MASK | SCG_SPLLCSR_SPLLCLKEN_MASK);
2222 
2223     /* Wait for APLL lock */
2224     while (CLOCK_IsPLL1Locked() == false)
2225     {
2226     }
2227 
2228     if (pSetup->pllRate != CLOCK_GetPll1OutFreq())
2229     {
2230         return kStatus_PLL_OutputError;
2231     }
2232 
2233     return kStatus_PLL_Success;
2234 }
2235 
2236 /*! @brief Enable the OSTIMER 32k clock.
2237  *  @return  Nothing
2238  */
CLOCK_EnableOstimer32kClock(void)2239 void CLOCK_EnableOstimer32kClock(void)
2240 {
2241     // PMC->OSEVENTTIMER |= PMC_OSEVENTTIMER_CLOCKENABLE_MASK;
2242 }
2243 
2244 /* Get FRO 12M Clk */
2245 /*! brief  Return Frequency of FRO 12MHz
2246  *  return Frequency of FRO 12MHz
2247  */
CLOCK_GetFro12MFreq(void)2248 static uint32_t CLOCK_GetFro12MFreq(void)
2249 {
2250     return ((SCG0->SIRCCSR & SCG_SIRCCSR_SIRC_CLK_PERIPH_EN_MASK) != 0UL) ? 12000000U : 0U;
2251 }
2252 
2253 /* Get CLK 1M Clk */
2254 /*! brief  Return Frequency of CLK 1MHz
2255  *  return Frequency of CLK 1MHz
2256  */
CLOCK_GetClk1MFreq(void)2257 static uint32_t CLOCK_GetClk1MFreq(void)
2258 {
2259     return 1000000U;
2260 }
2261 
2262 /* Get HF FRO Clk */
2263 /*! brief  Return Frequency of High-Freq output of FRO
2264  *  return Frequency of High-Freq output of FRO
2265  */
CLOCK_GetFroHfFreq(void)2266 static uint32_t CLOCK_GetFroHfFreq(void)
2267 {
2268     uint32_t freq;
2269 
2270     if ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRCEN_MASK) == 0UL)
2271     {
2272         freq = 0;
2273     }
2274     else if ((SCG0->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) != 0UL)
2275     {
2276         freq = 144000000U;
2277     }
2278     else
2279     {
2280         freq = 48000000U;
2281     }
2282 
2283     return freq;
2284 }
2285 
2286 /* Get CLK 48M Clk */
2287 /*! brief  Return Frequency of CLK 48MHz
2288  *  return Frequency of CLK 48MHz
2289  */
CLOCK_GetClk48MFreq(void)2290 static uint32_t CLOCK_GetClk48MFreq(void)
2291 {
2292     return ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRC_SCLK_PERIPH_EN_MASK) != 0U) ? 48000000U : 0U;
2293 }
2294 
2295 /* Get CLK 144M Clk */
2296 /*! brief  Return Frequency of CLK 144MHz
2297  *  return Frequency of CLK 144MHz
2298  */
CLOCK_GetClk144MFreq(void)2299 static uint32_t CLOCK_GetClk144MFreq(void)
2300 {
2301     return ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRC_FCLK_PERIPH_EN_MASK) != 0U) ? 144000000U : 0U;
2302 }
2303 
2304 /* Get CLK 16K Clk */
2305 /*! brief  Return Frequency of CLK 16KHz
2306  *  return Frequency of CLK 16KHz
2307  */
CLOCK_GetClk16KFreq(uint32_t id)2308 static uint32_t CLOCK_GetClk16KFreq(uint32_t id)
2309 {
2310     return ((VBAT0->FROCTLA & VBAT_FROCTLA_FRO_EN_MASK) != 0U) ?
2311                (((VBAT0->FROCLKE & VBAT_FROCLKE_CLKE(id)) != 0UL) ? 16000U : 0U) :
2312                0U;
2313 }
2314 
2315 /* Get EXT OSC Clk */
2316 /*! brief  Return Frequency of External Clock
2317  *  return Frequency of External Clock. If no external clock is used returns 0.
2318  */
CLOCK_GetExtClkFreq(void)2319 static uint32_t CLOCK_GetExtClkFreq(void)
2320 {
2321     return ((SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
2322 }
2323 
2324 /* Get RTC OSC Clk */
2325 /*! brief  Return Frequency of 32kHz osc
2326  *  return Frequency of 32kHz osc
2327  */
CLOCK_GetOsc32KFreq(uint32_t id)2328 static uint32_t CLOCK_GetOsc32KFreq(uint32_t id)
2329 {
2330     return ((SCG0->ROSCCSR & SCG_ROSCCSR_ROSCVLD_MASK) != 0UL) ?
2331                (((VBAT0->OSCCLKE & VBAT_OSCCLKE_CLKE(id)) != 0UL) ? s_Xtal32_Freq : 0U) :
2332                0U;
2333 }
2334 
2335 /* Get MAIN Clk */
2336 /*! @brief  Return Frequency of main
2337  *  @return Frequency of the main
2338  */
CLOCK_GetMainClkFreq(void)2339 uint32_t CLOCK_GetMainClkFreq(void)
2340 {
2341     uint32_t freq = 0U;
2342 
2343     switch ((SCG0->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT)
2344     {
2345         case 1U:
2346             freq = CLOCK_GetExtClkFreq();
2347             break;
2348         case 2U:
2349             freq = CLOCK_GetFro12MFreq();
2350             break;
2351         case 3U:
2352             freq = CLOCK_GetFroHfFreq();
2353             break;
2354         case 4U:
2355             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToWake);
2356             break;
2357         case 5U:
2358             freq = CLOCK_GetPll0OutFreq();
2359             break;
2360         case 6U:
2361             freq = CLOCK_GetPll1OutFreq();
2362             break;
2363         case 7U:
2364             // freq = CLOCK_GetUPllOutFreq();
2365             break;
2366         default:
2367             freq = 0U;
2368             break;
2369     }
2370 
2371     return freq;
2372 }
2373 
2374 /* Get cpu Clk */
2375 /*! brief  Return Frequency of Core System
2376  *  return Frequency of Core System
2377  */
CLOCK_GetCoreSysClkFreq(void)2378 uint32_t CLOCK_GetCoreSysClkFreq(void)
2379 {
2380     uint32_t freq = 0U;
2381 
2382     freq = CLOCK_GetMainClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
2383 
2384     return freq;
2385 }
2386 
2387 /* Get Systick Clk */
2388 /*! brief  Return Frequency of SystickClock
2389  *  return Frequency of Systick Clock
2390  */
CLOCK_GetSystickClkFreq(uint32_t id)2391 static uint32_t CLOCK_GetSystickClkFreq(uint32_t id)
2392 {
2393     uint32_t freq = 0U;
2394 
2395     switch ((id == 0U) ? SYSCON->SYSTICKCLKSEL0 : SYSCON->SYSTICKCLKSEL1)
2396     {
2397         case 0U:
2398             freq = CLOCK_GetMainClkFreq() / (((SYSCON->SYSTICKCLKDIV[id]) & 0xffU) + 1U);
2399             break;
2400         case 1U:
2401             freq = CLOCK_GetClk1MFreq();
2402             break;
2403         case 2U:
2404             freq = CLOCK_GetLposcFreq();
2405             break;
2406         default:
2407             freq = 0U;
2408             break;
2409     }
2410 
2411     return freq;
2412 }
2413 
2414 /* Get CLOCK OUT Clk */
2415 /*! brief  Return Frequency of ClockOut
2416  *  return Frequency of ClockOut
2417  */
CLOCK_GetClockOutClkFreq(void)2418 static uint32_t CLOCK_GetClockOutClkFreq(void)
2419 {
2420     uint32_t freq = 0U;
2421 
2422     switch (SYSCON->CLKOUTSEL)
2423     {
2424         case 0U:
2425             freq = CLOCK_GetMainClkFreq();
2426             break;
2427         case 1U:
2428             freq = CLOCK_GetPll0OutFreq();
2429             break;
2430         case 2U:
2431             freq = CLOCK_GetExtClkFreq();
2432             break;
2433         case 3U:
2434             freq = CLOCK_GetFroHfFreq();
2435             break;
2436         case 4U:
2437             freq = CLOCK_GetFro12MFreq();
2438             break;
2439         case 5U:
2440             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
2441             break;
2442         case 6U:
2443             freq = CLOCK_GetLposcFreq();
2444             break;
2445         case 7U:
2446             // freq = CLOCK_GetUPllOutFreq();
2447             break;
2448         default:
2449             freq = 0U;
2450             break;
2451     }
2452     return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
2453 }
2454 
2455 /* Get LP_OSC Clk */
2456 /*! brief  Return Frequency of LP_OSC
2457  *  return Frequency of LP_OSC
2458  */
CLOCK_GetLposcFreq(void)2459 static uint32_t CLOCK_GetLposcFreq(void)
2460 {
2461     uint32_t freq = 0U;
2462 
2463     switch ((RTC0->CTRL & RTC_CTRL_CLK_SEL_MASK) >> RTC_CTRL_CLK_SEL_SHIFT)
2464     {
2465         case 0U:
2466             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToVbat);
2467             break;
2468         case 1U:
2469             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2470             break;
2471         default:
2472             freq = 0U;
2473             break;
2474     }
2475 
2476     return freq;
2477 }
2478 
2479 /* 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)2480 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
2481 {
2482     uint32_t seli, selp;
2483     /* bandwidth: compute selP from Multiplier */
2484     if ((SCG0->APLLCTRL & SCG_APLLCTRL_LIMUPOFF_MASK) == 0UL) /* normal mode */
2485     {
2486         selp = (M >> 2U) + 1U;
2487         if (selp >= 31U)
2488         {
2489             selp = 31U;
2490         }
2491         *pSelP = selp;
2492 
2493         if (M >= 8000UL)
2494         {
2495             seli = 1UL;
2496         }
2497         else if (M >= 122UL)
2498         {
2499             seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
2500         }
2501         else
2502         {
2503             seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
2504         }
2505 
2506         if (seli >= 63UL)
2507         {
2508             seli = 63UL;
2509         }
2510         *pSelI = seli;
2511 
2512         *pSelR = 0U;
2513     }
2514     else
2515     {
2516         /* Note: If the spread spectrum and fractional mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
2517         *pSelP = 3U;
2518         *pSelI = 4U;
2519         *pSelR = 4U;
2520     }
2521 }
2522 
2523 /* Get predivider (N) from PLL0 NDIV setting */
findPll0PreDiv(void)2524 static uint32_t findPll0PreDiv(void)
2525 {
2526     uint32_t preDiv = 1UL;
2527 
2528     /* Direct input is not used? */
2529     if ((SCG0->APLLCTRL & SCG_APLLCTRL_BYPASSPREDIV_MASK) == 0UL)
2530     {
2531         preDiv = SCG0->APLLNDIV & SCG_APLLNDIV_NDIV_MASK;
2532         if (preDiv == 0UL)
2533         {
2534             preDiv = 1UL;
2535         }
2536     }
2537     return preDiv;
2538 }
2539 
2540 /* Get predivider (N) from PLL1 NDIV setting */
findPll1PreDiv(void)2541 static uint32_t findPll1PreDiv(void)
2542 {
2543     uint32_t preDiv = 1UL;
2544 
2545     /* Direct input is not used? */
2546     if ((SCG0->SPLLCTRL & SCG_SPLLCTRL_BYPASSPREDIV_MASK) == 0UL)
2547     {
2548         preDiv = SCG0->SPLLNDIV & SCG_SPLLNDIV_NDIV_MASK;
2549         if (preDiv == 0UL)
2550         {
2551             preDiv = 1UL;
2552         }
2553     }
2554     return preDiv;
2555 }
2556 
2557 /* Get postdivider (P) from PLL0 PDIV setting */
findPll0PostDiv(void)2558 static uint32_t findPll0PostDiv(void)
2559 {
2560     uint32_t postDiv = 1UL;
2561 
2562     if ((SCG0->APLLCTRL & SCG_APLLCTRL_BYPASSPOSTDIV_MASK) == 0UL)
2563     {
2564         if ((SCG0->APLLCTRL & SCG_APLLCTRL_BYPASSPOSTDIV2_MASK) != 0UL)
2565         {
2566             postDiv = SCG0->APLLPDIV & SCG_APLLPDIV_PDIV_MASK;
2567         }
2568         else
2569         {
2570             postDiv = 2UL * (SCG0->APLLPDIV & SCG_APLLPDIV_PDIV_MASK);
2571         }
2572         if (postDiv == 0UL)
2573         {
2574             postDiv = 2UL;
2575         }
2576     }
2577 
2578     return postDiv;
2579 }
2580 
2581 /* Get postdivider (P) from PLL1 PDIV setting. */
findPll1PostDiv(void)2582 static uint32_t findPll1PostDiv(void)
2583 {
2584     uint32_t postDiv = 1UL;
2585 
2586     if ((SCG0->SPLLCTRL & SCG_SPLLCTRL_BYPASSPOSTDIV_MASK) == 0UL)
2587     {
2588         if ((SCG0->SPLLCTRL & SCG_SPLLCTRL_BYPASSPOSTDIV2_MASK) != 0UL)
2589         {
2590             postDiv = SCG0->SPLLPDIV & SCG_SPLLPDIV_PDIV_MASK;
2591         }
2592         else
2593         {
2594             postDiv = 2UL * (SCG0->SPLLPDIV & SCG_SPLLPDIV_PDIV_MASK);
2595         }
2596         if (postDiv == 0UL)
2597         {
2598             postDiv = 2UL;
2599         }
2600     }
2601 
2602     return postDiv;
2603 }
2604 
2605 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)2606 static float findPll0MMult(void)
2607 {
2608     float mMult = 1.0F;
2609     float mMult_fract;
2610     uint32_t mMult_int;
2611 
2612     if ((SCG0->APLLSSCG1 & SCG_APLLSSCG1_SEL_SS_MDIV_MASK) == 0UL)
2613     {
2614         mMult = (float)(uint32_t)(SCG0->APLLMDIV & SCG_APLLMDIV_MDIV_MASK);
2615     }
2616     else
2617     {
2618         mMult_int = ((SCG0->APLLSSCG1 & SCG_APLLSSCG1_SS_MDIV_MSB_MASK) << 7U);
2619         mMult_int = mMult_int | ((SCG0->APLLSSCG0) >> PLL_SSCG_MD_INT_P);
2620         mMult_fract =
2621             ((float)(uint32_t)((SCG0->APLLSSCG0) & PLL_SSCG_MD_FRACT_M) / (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P));
2622         mMult = (float)mMult_int + mMult_fract;
2623     }
2624     if (0ULL == ((uint64_t)mMult))
2625     {
2626         mMult = 1.0F;
2627     }
2628     return mMult;
2629 }
2630 
2631 /* Get multiplier (M) from PLL1 MDEC. */
findPll1MMult(void)2632 static float findPll1MMult(void)
2633 {
2634     float mMult = 1.0F;
2635     float mMult_fract;
2636     uint32_t mMult_int;
2637 
2638     if ((SCG0->SPLLSSCG1 & SCG_SPLLSSCG1_SEL_SS_MDIV_MASK) == 0UL)
2639     {
2640         mMult = (float)(uint32_t)(SCG0->SPLLMDIV & SCG_SPLLMDIV_MDIV_MASK);
2641     }
2642     else
2643     {
2644         mMult_int = ((SCG0->SPLLSSCG1 & SCG_SPLLSSCG1_SS_MDIV_MSB_MASK) << 7U);
2645         mMult_int = mMult_int | ((SCG0->SPLLSSCG0) >> PLL_SSCG_MD_INT_P);
2646         mMult_fract =
2647             ((float)(uint32_t)((SCG0->SPLLSSCG0) & PLL_SSCG_MD_FRACT_M) / (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P));
2648         mMult = (float)mMult_int + mMult_fract;
2649     }
2650     if (0ULL == ((uint64_t)mMult))
2651     {
2652         mMult = 1.0F;
2653     }
2654     return mMult;
2655 }
2656 
2657 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)2658 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
2659 {
2660     uint32_t tmp;
2661 
2662     while (n != 0U)
2663     {
2664         tmp = n;
2665         n   = m % n;
2666         m   = tmp;
2667     }
2668 
2669     return m;
2670 }
2671 
2672 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
2673 /* Alloct the static buffer for cache. */
2674 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
2675 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]  = {0};
2676 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
2677 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]      = {false};
2678 static uint32_t s_PllSetupCacheIdx                                  = 0U;
2679 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
2680 
2681 /*
2682  * Calculate the PLL setting values from input clock freq to output freq.
2683  */
CLOCK_GetPllConfig(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)2684 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
2685 {
2686     pll_error_t retErr;
2687 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
2688     uint32_t i;
2689 
2690     for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
2691     {
2692         if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
2693         {
2694             /* Hit the target in cache buffer. */
2695             pSetup->pllctrl    = s_PllSetupCacheStruct[i].pllctrl;
2696             pSetup->pllndiv    = s_PllSetupCacheStruct[i].pllndiv;
2697             pSetup->pllmdiv    = s_PllSetupCacheStruct[i].pllmdiv;
2698             pSetup->pllpdiv    = s_PllSetupCacheStruct[i].pllpdiv;
2699             pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
2700             pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
2701             retErr             = kStatus_PLL_Success;
2702             break;
2703         }
2704     }
2705 
2706     if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
2707     {
2708         return retErr;
2709     }
2710 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
2711 
2712     retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup, useSS);
2713 
2714 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
2715     /* Cache the most recent calulation result into buffer. */
2716     s_FinHzCache[s_PllSetupCacheIdx]  = finHz;
2717     s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
2718     s_UseSSCache[s_PllSetupCacheIdx]  = useSS;
2719 
2720     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl    = pSetup->pllctrl;
2721     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndiv    = pSetup->pllndiv;
2722     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllmdiv    = pSetup->pllmdiv;
2723     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdiv    = pSetup->pllpdiv;
2724     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
2725     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
2726     /* Update the index for next available buffer. */
2727     s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
2728 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
2729 
2730     return retErr;
2731 }
2732 
2733 /*
2734  * Set PLL output based on desired output rate.
2735  * In this function, the it calculates the PLL0 setting for output frequency from input clock
2736  * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
2737  * the "pllctrl", "pllndiv", "pllpdiv", "pllmdiv" would updated in this function.
2738  */
CLOCK_GetPllConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)2739 static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
2740 {
2741     uint32_t nDivOutHz, fccoHz;
2742     uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
2743     uint32_t pllDirectInput, pllDirectOutput;
2744     uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
2745 
2746     /* Baseline parameters (no input or output dividers) */
2747     pllPreDivider   = 1U; /* 1 implies pre-divider will be disabled */
2748     pllPostDivider  = 1U; /* 1 implies post-divider will be disabled */
2749     pllDirectOutput = 1U;
2750 
2751     /* Verify output rate parameter */
2752     if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
2753     {
2754         /* Maximum PLL output with post divider=1 cannot go above this frequency */
2755         return kStatus_PLL_OutputTooHigh;
2756     }
2757     if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
2758     {
2759         /* Minmum PLL output with maximum post divider cannot go below this frequency */
2760         return kStatus_PLL_OutputTooLow;
2761     }
2762 
2763     /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
2764     if (useSS)
2765     {
2766         /* Verify input rate parameter */
2767         if (finHz < PLL_MIN_IN_SSMODE)
2768         {
2769             /* Input clock into the PLL cannot be lower than this */
2770             return kStatus_PLL_InputTooLow;
2771         }
2772         /* PLL input in SS mode must be under 20MHz */
2773         if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
2774         {
2775             return kStatus_PLL_InputTooHigh;
2776         }
2777     }
2778     else
2779     {
2780         /* Verify input rate parameter */
2781         if (finHz < PLL_LOWER_IN_LIMIT)
2782         {
2783             /* Input clock into the PLL cannot be lower than this */
2784             return kStatus_PLL_InputTooLow;
2785         }
2786         if (finHz > PLL_HIGHER_IN_LIMIT)
2787         {
2788             /* Input clock into the PLL cannot be higher than this */
2789             return kStatus_PLL_InputTooHigh;
2790         }
2791     }
2792 
2793     /* Find the optimal CCO frequency for the output and input that
2794        will keep it inside the PLL CCO range. This may require
2795        tweaking the post-divider for the PLL. */
2796     fccoHz = foutHz;
2797     while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
2798     {
2799         /* CCO output is less than minimum CCO range, so the CCO output
2800            needs to be bumped up and the post-divider is used to bring
2801            the PLL output back down. */
2802         pllPostDivider++;
2803         if (pllPostDivider > PVALMAX)
2804         {
2805             return kStatus_PLL_OutsideIntLimit;
2806         }
2807 
2808         /* Target CCO goes up, PLL output goes down */
2809         /* divide-by-2 divider in the post-divider is always work*/
2810         fccoHz          = foutHz * (pllPostDivider * 2U);
2811         pllDirectOutput = 0U;
2812     }
2813 
2814     /* Determine if a pre-divider is needed to get the best frequency */
2815     if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
2816     {
2817         uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
2818 
2819         if (a > PLL_LOWER_IN_LIMIT)
2820         {
2821             a = finHz / a;
2822             if ((a != 0U) && (a < PLL_MAX_N_DIV))
2823             {
2824                 pllPreDivider = a;
2825             }
2826         }
2827     }
2828 
2829     /* Bypass pre-divider hardware if pre-divider is 1 */
2830     if (pllPreDivider > 1U)
2831     {
2832         pllDirectInput = 0U;
2833     }
2834     else
2835     {
2836         pllDirectInput = 1U;
2837     }
2838 
2839     /* Determine PLL multipler */
2840     nDivOutHz     = (finHz / pllPreDivider);
2841     pllMultiplier = (fccoHz / nDivOutHz);
2842 
2843     /* Find optimal values for filter */
2844     if (useSS == false)
2845     {
2846         /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
2847         if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
2848         {
2849             pllMultiplier++;
2850         }
2851 
2852         /* Setup filtering */
2853         pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
2854         uplimoff = 0U;
2855 
2856         /* Get encoded value for M (mult) and use manual filter, disable SS mode */
2857         pSetup->pllmdiv = (uint32_t)PLL_MDIV_VAL_SET(pllMultiplier);
2858         pSetup->pllsscg[1] &= ~SCG_APLLSSCG1_SEL_SS_MDIV_MASK;
2859     }
2860     else
2861     {
2862         uint64_t fc;
2863 
2864         /* Filtering will be handled by SSC */
2865         pllSelR  = 0UL;
2866         pllSelI  = 0UL;
2867         pllSelP  = 0UL;
2868         uplimoff = 1U;
2869 
2870         /* The PLL multiplier will get very close and slightly under the
2871            desired target frequency. A small fractional component can be
2872            added to fine tune the frequency upwards to the target. */
2873         fc = ((uint64_t)(uint32_t)(fccoHz % nDivOutHz) << 25UL) / nDivOutHz;
2874 
2875         /* Set multiplier */
2876         pSetup->pllsscg[0] = (uint32_t)(PLL_SSCG_MD_INT_SET(pllMultiplier) | PLL_SSCG_MD_FRACT_SET((uint32_t)fc));
2877         pSetup->pllsscg[1] = (uint32_t)(PLL_SSCG_MD_INT_SET(pllMultiplier) >> 32U) | SCG_APLLSSCG1_SEL_SS_MDIV_MASK;
2878     }
2879 
2880     /* Get encoded values for N (prediv) and P (postdiv) */
2881     pSetup->pllndiv = PLL_NDIV_VAL_SET(pllPreDivider);
2882     pSetup->pllpdiv = PLL_PDIV_VAL_SET(pllPostDivider);
2883 
2884     /* PLL control */
2885     pSetup->pllctrl = (pllSelR << SCG_APLLCTRL_SELR_SHIFT) |                 /* Filter coefficient */
2886                       (pllSelI << SCG_APLLCTRL_SELI_SHIFT) |                 /* Filter coefficient */
2887                       (pllSelP << SCG_APLLCTRL_SELP_SHIFT) |                 /* Filter coefficient */
2888                       (uplimoff << SCG_APLLCTRL_LIMUPOFF_SHIFT) |            /* SS/fractional mode disabled */
2889                       (pllDirectInput << SCG_APLLCTRL_BYPASSPREDIV_SHIFT) |  /* Bypass pre-divider? */
2890                       (pllDirectOutput << SCG_APLLCTRL_BYPASSPOSTDIV_SHIFT); /* Bypass post-divider? */
2891 
2892     return kStatus_PLL_Success;
2893 }
2894 
2895 /* Get PLL input clock rate from setup structure */
CLOCK_GetPLLInClockRateFromSetup(pll_setup_t * pSetup)2896 static uint32_t CLOCK_GetPLLInClockRateFromSetup(pll_setup_t *pSetup)
2897 {
2898     uint32_t clkRate = 0U;
2899 
2900     switch ((pSetup->pllctrl & SCG_APLLCTRL_SOURCE_MASK) >> SCG_APLLCTRL_SOURCE_SHIFT)
2901     {
2902         case 0x00U:
2903             clkRate = CLOCK_GetExtClkFreq();
2904             break;
2905         case 0x01U:
2906             clkRate = CLOCK_GetClk48MFreq();
2907             break;
2908         case 0x02U:
2909             clkRate = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2910             break;
2911         default:
2912             clkRate = 0U;
2913             break;
2914     }
2915 
2916     return clkRate;
2917 }
2918 
2919 /* Get predivider (N) from from setup structure */
findPllPreDivFromSetup(pll_setup_t * pSetup)2920 static uint32_t findPllPreDivFromSetup(pll_setup_t *pSetup)
2921 {
2922     uint32_t preDiv = 1UL;
2923 
2924     /* Direct input is not used? */
2925     if ((pSetup->pllctrl & SCG_APLLCTRL_BYPASSPREDIV_MASK) == 0UL)
2926     {
2927         preDiv = pSetup->pllndiv & SCG_APLLNDIV_NDIV_MASK;
2928         if (preDiv == 0UL)
2929         {
2930             preDiv = 1UL;
2931         }
2932     }
2933     return preDiv;
2934 }
2935 
2936 /* Get postdivider (P) from from setup structure */
findPllPostDivFromSetup(pll_setup_t * pSetup)2937 static uint32_t findPllPostDivFromSetup(pll_setup_t *pSetup)
2938 {
2939     uint32_t postDiv = 1UL;
2940 
2941     if ((pSetup->pllctrl & SCG_APLLCTRL_BYPASSPOSTDIV_MASK) == 0UL)
2942     {
2943         if ((pSetup->pllctrl & SCG_APLLCTRL_BYPASSPOSTDIV2_MASK) != 0UL)
2944         {
2945             postDiv = pSetup->pllpdiv & SCG_APLLPDIV_PDIV_MASK;
2946         }
2947         else
2948         {
2949             postDiv = 2UL * (pSetup->pllpdiv & SCG_APLLPDIV_PDIV_MASK);
2950         }
2951         if (postDiv == 0UL)
2952         {
2953             postDiv = 2UL;
2954         }
2955     }
2956 
2957     return postDiv;
2958 }
2959 
2960 /* Get multiplier (M) from from setup structure */
findPllMMultFromSetup(pll_setup_t * pSetup)2961 static float findPllMMultFromSetup(pll_setup_t *pSetup)
2962 {
2963     float mMult = 1.0F;
2964     float mMult_fract;
2965     uint32_t mMult_int;
2966 
2967     if ((pSetup->pllsscg[1] & SCG_APLLSSCG1_SEL_SS_MDIV_MASK) == 0UL)
2968     {
2969         mMult = (float)(uint32_t)(pSetup->pllmdiv & SCG_APLLMDIV_MDIV_MASK);
2970     }
2971     else
2972     {
2973         mMult_int   = ((pSetup->pllsscg[1] & SCG_APLLSSCG1_SS_MDIV_MSB_MASK) << 7U);
2974         mMult_int   = mMult_int | ((pSetup->pllsscg[0]) >> PLL_SSCG_MD_INT_P);
2975         mMult_fract = ((float)(uint32_t)((pSetup->pllsscg[0]) & PLL_SSCG_MD_FRACT_M) /
2976                        (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P));
2977         mMult       = (float)mMult_int + mMult_fract;
2978     }
2979     if (0ULL == ((uint64_t)mMult))
2980     {
2981         mMult = 1.0F;
2982     }
2983     return mMult;
2984 }
2985 
2986 /*! brief Enable USB FS clock.
2987  * Enable USB Full Speed clock.
2988  */
CLOCK_EnableUsbfsClock(void)2989 bool CLOCK_EnableUsbfsClock(void)
2990 {
2991     SYSCON->USB0CLKSEL = 0x3U; /* Clk 48 MHz clock */
2992     CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1);
2993     SYSCON->USB0CLKDIV &= (uint32_t) ~(SYSCON_USB0CLKDIV_HALT_MASK | SYSCON_USB0CLKDIV_RESET_MASK);
2994     /* Wait until clock change completes */
2995     while ((SYSCON->USB0CLKDIV & SYSCON_SYSTICKCLKDIV_UNSTAB_MASK) != 0U)
2996     {
2997     }
2998     return true;
2999 }
3000 
3001 /*! brief Enable USB HS PHY PLL clock.
3002  *
3003  * This function enables the internal 480MHz USB PHY PLL clock.
3004  *
3005  * param src  USB HS PHY PLL clock source.
3006  * param freq The frequency specified by src.
3007  * retval true The clock is set successfully.
3008  * retval false The clock source is invalid to get proper USB HS clock.
3009  */
CLOCK_EnableUsbhsPhyPllClock(clock_usb_phy_src_t src,uint32_t freq)3010 bool CLOCK_EnableUsbhsPhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
3011 {
3012     uint32_t phyPllDiv  = 0U;
3013     uint16_t multiplier = 0U;
3014     bool err            = false;
3015 
3016     USBPHY->CTRL_CLR    = USBPHY_CTRL_SFTRST_MASK;
3017     USBPHY->ANACTRL_SET = USBPHY_ANACTRL_LVI_EN_MASK;
3018     USBPHY->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_POWER(1) | USBPHY_PLL_SIC_PLL_REG_ENABLE_MASK);
3019     if ((480000000UL % freq) != 0UL)
3020     {
3021         return false;
3022     }
3023     multiplier = (uint16_t)(480000000UL / freq);
3024 
3025     switch (multiplier)
3026     {
3027         case 15:
3028         {
3029             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
3030             break;
3031         }
3032         case 16:
3033         {
3034             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
3035             break;
3036         }
3037         case 20:
3038         {
3039             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
3040             break;
3041         }
3042         case 22:
3043         {
3044             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(3U);
3045             break;
3046         }
3047         case 24:
3048         {
3049             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U);
3050             break;
3051         }
3052         case 25:
3053         {
3054             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U);
3055             break;
3056         }
3057         case 30:
3058         {
3059             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U);
3060             break;
3061         }
3062         case 40:
3063         {
3064             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(7U);
3065             break;
3066         }
3067         default:
3068         {
3069             err = true;
3070             break;
3071         }
3072     }
3073 
3074     if (err)
3075     {
3076         return false;
3077     }
3078 
3079     USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~(USBPHY_PLL_SIC_PLL_DIV_SEL_MASK)) | phyPllDiv;
3080 
3081     USBPHY->PLL_SIC_CLR = USBPHY_PLL_SIC_PLL_BYPASS_MASK;
3082     USBPHY->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK);
3083 
3084     USBPHY->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK;
3085     USBPHY->PWD      = 0x0U;
3086 
3087     while (0UL == (USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK))
3088     {
3089     }
3090 
3091     return true;
3092 }
3093 
3094 /*! brief Disable USB HS PHY PLL clock.
3095  *
3096  * This function disables USB HS PHY PLL clock.
3097  */
CLOCK_DisableUsbhsPhyPllClock(void)3098 void CLOCK_DisableUsbhsPhyPllClock(void)
3099 {
3100     USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
3101 }
3102 
3103 /*! brief Enable USB HS clock.
3104  * retval true The clock is set successfully.
3105  * retval false The clock source is invalid to get proper USB HS clock.
3106  */
CLOCK_EnableUsbhsClock(void)3107 bool CLOCK_EnableUsbhsClock(void)
3108 {
3109     USBHS1__USBC->USBCMD |= USBHS_USBCMD_RST_MASK;
3110     /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/
3111     for (uint32_t i = 0; i < 400000U; i++)
3112     {
3113         __ASM("nop");
3114     }
3115     return true;
3116 }
3117 
3118 /**
3119  * @brief   FIRC Auto Trim With SOF.
3120  * @return  returns success or fail status.
3121  */
CLOCK_FIRCAutoTrimWithSOF(void)3122 status_t CLOCK_FIRCAutoTrimWithSOF(void)
3123 {
3124     /* System OSC Clock Monitor is disabled */
3125     CLOCK_SetSysOscMonitorMode(kSCG_SysOscMonitorDisable);
3126 
3127     firc_trim_config_t fircAutoTrimConfig = {
3128         .trimMode = kSCG_FircTrimUpdate,  /* FIRC trim is enabled and trim value update is enabled */
3129         .trimSrc  = kSCG_FircTrimSrcUsb0, /* Trim source is USB0 start of frame (1kHz) */
3130         .trimDiv  = 1U,                   /* Divided value */
3131         .trimCoar = 0U,                   /* Trim value, see Reference Manual for more information */
3132         .trimFine = 0U,                   /* Trim value, see Reference Manual for more information */
3133     };
3134 
3135     return CLOCK_FROHFTrimConfig(fircAutoTrimConfig);
3136 }
3137