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