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             default:
1738                 freq = 0U;
1739                 break;
1740         }
1741     }
1742 
1743     div = ((id == 0U) ? ((SYSCON->WDT0CLKDIV & SYSCON_WDT0CLKDIV_DIV_MASK) + 1U) :
1744                         ((SYSCON->WDT1CLKDIV & SYSCON_WDT1CLKDIV_DIV_MASK) + 1U));
1745 
1746     return freq / div;
1747 }
1748 
1749 /* Get OSTIMER Clk */
1750 /*! brief  Return Frequency of OSTIMER
1751  *  return Frequency of OSTIMER
1752  */
CLOCK_GetOstimerClkFreq(void)1753 uint32_t CLOCK_GetOstimerClkFreq(void)
1754 {
1755     uint32_t freq = 0U;
1756 
1757     switch (SYSCON->OSTIMERCLKSEL)
1758     {
1759         case 0U:
1760             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToWake);
1761             break;
1762         case 1U:
1763             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToWake);
1764             break;
1765         case 2U:
1766             freq = CLOCK_GetClk1MFreq();
1767             break;
1768         default:
1769             freq = 0U;
1770             break;
1771     }
1772 
1773     return freq;
1774 }
1775 
1776 /* Get CMP Function Clk */
1777 /*! brief  Return Frequency of CMP Function
1778  *  return Frequency of CMP Function
1779  */
CLOCK_GetCmpFClkFreq(uint32_t id)1780 uint32_t CLOCK_GetCmpFClkFreq(uint32_t id)
1781 {
1782     uint32_t freq = 0U;
1783     uint32_t div  = 0U;
1784 
1785     switch ((id == 0U) ? (SYSCON->CMP0FCLKSEL) : ((id == 1U) ? (SYSCON->CMP1FCLKSEL) : (SYSCON->CMP2FCLKSEL)))
1786     {
1787         case 1U:
1788             freq = CLOCK_GetPll0OutFreq();
1789             break;
1790         case 2U:
1791             freq = CLOCK_GetFroHfFreq();
1792             break;
1793         case 3U:
1794             freq = CLOCK_GetFro12MFreq();
1795             break;
1796         case 4U:
1797             freq = CLOCK_GetExtClkFreq();
1798             break;
1799         case 5U:
1800             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1801             break;
1802         case 6U:
1803             // freq = CLOCK_GetUPllOutFreq();
1804         default:
1805             freq = 0U;
1806             break;
1807     }
1808 
1809     div = ((id == 0U) ? ((SYSCON->CMP0FCLKDIV & SYSCON_CMP0FCLKDIV_DIV_MASK) + 1U) :
1810                         ((id == 1U) ? ((SYSCON->CMP1FCLKDIV & SYSCON_CMP1FCLKDIV_DIV_MASK) + 1U) :
1811                                       ((SYSCON->CMP2FCLKDIV & SYSCON_CMP2FCLKDIV_DIV_MASK) + 1U)));
1812 
1813     return freq / div;
1814 }
1815 
1816 /* Get CMP Round Robin Clk */
1817 /*! brief  Return Frequency of CMP Round Robin
1818  *  return Frequency of CMP Round Robin
1819  */
CLOCK_GetCmpRRClkFreq(uint32_t id)1820 uint32_t CLOCK_GetCmpRRClkFreq(uint32_t id)
1821 {
1822     uint32_t freq = 0U;
1823     uint32_t div  = 0U;
1824 
1825     switch ((id == 0U) ? (SYSCON->CMP0RRCLKSEL) : ((id == 1U) ? (SYSCON->CMP1RRCLKSEL) : (SYSCON->CMP2RRCLKSEL)))
1826     {
1827         case 1U:
1828             freq = CLOCK_GetPll0OutFreq();
1829             break;
1830         case 2U:
1831             freq = CLOCK_GetFroHfFreq();
1832             break;
1833         case 3U:
1834             freq = CLOCK_GetFro12MFreq();
1835             break;
1836         case 4U:
1837             freq = CLOCK_GetExtClkFreq();
1838             break;
1839         case 5U:
1840             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1841             break;
1842         case 6U:
1843             // freq = CLOCK_GetUPllOutFreq();
1844         default:
1845             freq = 0U;
1846             break;
1847     }
1848 
1849     div = ((id == 0U) ? ((SYSCON->CMP0RRCLKDIV & SYSCON_CMP0RRCLKDIV_DIV_MASK) + 1U) :
1850                         ((id == 1U) ? ((SYSCON->CMP1RRCLKDIV & SYSCON_CMP1RRCLKDIV_DIV_MASK) + 1U) :
1851                                       ((SYSCON->CMP2RRCLKDIV & SYSCON_CMP2RRCLKDIV_DIV_MASK) + 1U)));
1852 
1853     return freq / div;
1854 }
1855 
1856 /* Get SAI Clk */
1857 /*! brief  Return Frequency of SAI
1858  *  return Frequency of SAI
1859  */
CLOCK_GetSaiClkFreq(uint32_t id)1860 uint32_t CLOCK_GetSaiClkFreq(uint32_t id)
1861 {
1862     uint32_t freq = 0U;
1863     uint32_t div  = 0U;
1864 
1865     switch ((id == 0U) ? (SYSCON->SAI0CLKSEL) : (SYSCON->SAI1CLKSEL))
1866     {
1867         case 1U:
1868             freq = CLOCK_GetPll0OutFreq();
1869             break;
1870         case 2U:
1871             freq = CLOCK_GetExtClkFreq();
1872             break;
1873         case 3U:
1874             freq = CLOCK_GetFroHfFreq();
1875             break;
1876         case 4U:
1877             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1878             break;
1879         case 6U:
1880             // freq = CLOCK_GetUPllOutFreq();
1881         default:
1882             freq = 0U;
1883             break;
1884     }
1885 
1886     div = ((id == 0U) ? ((SYSCON->SAI0CLKDIV & SYSCON_SAI0CLKDIV_DIV_MASK) + 1U) :
1887                         ((SYSCON->SAI1CLKDIV & SYSCON_SAI1CLKDIV_DIV_MASK) + 1U));
1888 
1889     return freq / div;
1890 }
1891 
1892 /* Get SAI MCLK */
1893 /*! brief  Initialize the SAI MCLK to given frequency.
1894  *  return Nothing
1895  */
CLOCK_SetupSaiMclk(uint32_t id,uint32_t iFreq)1896 void CLOCK_SetupSaiMclk(uint32_t id, uint32_t iFreq)
1897 {
1898     s_Sai_Mclk_Freq[id] = iFreq;
1899 
1900     return;
1901 }
1902 
1903 /* Get SAI TX BCLK */
1904 /*! brief  Initialize the SAI TX BCLK to given frequency.
1905  *  return Nothing
1906  */
CLOCK_SetupSaiTxBclk(uint32_t id,uint32_t iFreq)1907 void CLOCK_SetupSaiTxBclk(uint32_t id, uint32_t iFreq)
1908 {
1909     s_Sai_Tx_Bclk_Freq[id] = iFreq;
1910 
1911     return;
1912 }
1913 
1914 /* Get SAI RX BCLK */
1915 /*! brief  Initialize the SAI RX BCLK to given frequency.
1916  *  return Nothing
1917  */
CLOCK_SetupSaiRxBclk(uint32_t id,uint32_t iFreq)1918 void CLOCK_SetupSaiRxBclk(uint32_t id, uint32_t iFreq)
1919 {
1920     s_Sai_Rx_Bclk_Freq[id] = iFreq;
1921 
1922     return;
1923 }
1924 
1925 /* Get SAI MCLK */
1926 /*! brief  Return Frequency of SAI MCLK
1927  *  return Frequency of SAI MCLK
1928  */
CLOCK_GetSaiMclkFreq(uint32_t id)1929 uint32_t CLOCK_GetSaiMclkFreq(uint32_t id)
1930 {
1931     return s_Sai_Mclk_Freq[id];
1932 }
1933 
1934 /* Get SAI TX BCLK */
1935 /*! brief  Return Frequency of SAI TX BCLK
1936  *  return Frequency of SAI TX BCLK
1937  */
CLOCK_GetSaiTxBclkFreq(uint32_t id)1938 uint32_t CLOCK_GetSaiTxBclkFreq(uint32_t id)
1939 {
1940     return s_Sai_Tx_Bclk_Freq[id];
1941 }
1942 
1943 /* Get SAI RX BCLK */
1944 /*! brief  Return Frequency of SAI RX BCLK
1945  *  return Frequency of SAI RX BCLK
1946  */
CLOCK_GetSaiRxBclkFreq(uint32_t id)1947 uint32_t CLOCK_GetSaiRxBclkFreq(uint32_t id)
1948 {
1949     return s_Sai_Rx_Bclk_Freq[id];
1950 }
1951 
1952 /* Get EMVSIM Clk */
1953 /*! brief  Return Frequency of EMVSIM
1954  *  return Frequency of EMVSIM
1955  */
CLOCK_GetEmvsimClkFreq(uint32_t id)1956 uint32_t CLOCK_GetEmvsimClkFreq(uint32_t id)
1957 {
1958     uint32_t freq = 0U;
1959     uint32_t div  = 0U;
1960 
1961     switch ((id == 0U) ? (SYSCON->EMVSIM0CLKSEL) : (SYSCON->EMVSIM1CLKSEL))
1962     {
1963         case 1U:
1964             freq = CLOCK_GetPll0OutFreq();
1965             break;
1966         case 2U:
1967             freq = CLOCK_GetExtClkFreq();
1968             break;
1969         case 3U:
1970             freq = CLOCK_GetFroHfFreq();
1971             break;
1972         case 4U:
1973             freq = CLOCK_GetFro12MFreq();
1974             break;
1975         case 5U:
1976             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
1977             break;
1978         default:
1979             freq = 0U;
1980             break;
1981     }
1982 
1983     div = ((id == 0U) ? ((SYSCON->EMVSIM0CLKDIV & SYSCON_EMVSIM0CLKDIV_DIV_MASK) + 1U) :
1984                         ((SYSCON->EMVSIM1CLKDIV & SYSCON_EMVSIM1CLKDIV_DIV_MASK) + 1U));
1985 
1986     return freq / div;
1987 }
1988 
1989 /* Return System PLL input clock rate */
1990 /*! brief    Return  PLL0 input clock rate
1991  *  return    PLL0 input clock rate
1992  */
CLOCK_GetPLL0InClockRate(void)1993 uint32_t CLOCK_GetPLL0InClockRate(void)
1994 {
1995     uint32_t clkRate = 0U;
1996 
1997     switch ((SCG0->APLLCTRL & SCG_APLLCTRL_SOURCE_MASK) >> SCG_APLLCTRL_SOURCE_SHIFT)
1998     {
1999         case 0x00U:
2000             clkRate = CLOCK_GetExtClkFreq();
2001             break;
2002         case 0x01U:
2003             clkRate = CLOCK_GetClk48MFreq();
2004             break;
2005         case 0x02U:
2006             clkRate = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2007             break;
2008         default:
2009             clkRate = 0U;
2010             break;
2011     }
2012 
2013     return clkRate;
2014 }
2015 
2016 /* Return PLL1 input clock rate */
CLOCK_GetPLL1InClockRate(void)2017 uint32_t CLOCK_GetPLL1InClockRate(void)
2018 {
2019     uint32_t clkRate = 0U;
2020 
2021     switch ((SCG0->SPLLCTRL & SCG_SPLLCTRL_SOURCE_MASK) >> SCG_SPLLCTRL_SOURCE_SHIFT)
2022     {
2023         case 0x00U:
2024             clkRate = CLOCK_GetExtClkFreq();
2025             break;
2026         case 0x01U:
2027             clkRate = CLOCK_GetClk48MFreq();
2028             break;
2029         case 0x02U:
2030             clkRate = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2031             break;
2032         default:
2033             clkRate = 0U;
2034             break;
2035     }
2036 
2037     return clkRate;
2038 }
2039 
2040 /* Return PLL output clock rate from setup structure */
2041 /*! brief    Return PLL0 output clock rate from setup structure
2042  *  param    pSetup : Pointer to a PLL setup structure
2043  *  return   PLL0 output clock rate the setup structure will generate
2044  */
CLOCK_GetPLLOutFromSetup(pll_setup_t * pSetup)2045 uint32_t CLOCK_GetPLLOutFromSetup(pll_setup_t *pSetup)
2046 {
2047     uint32_t clkRate = 0;
2048     uint32_t prediv, postdiv;
2049     float workRate = 0.0F;
2050 
2051     /* Get the input clock frequency of PLL. */
2052     clkRate = CLOCK_GetPLLInClockRateFromSetup(pSetup);
2053 
2054     prediv  = findPllPreDivFromSetup(pSetup);
2055     postdiv = findPllPostDivFromSetup(pSetup);
2056     /* Adjust input clock */
2057     clkRate = clkRate / prediv;
2058     /* MDEC used for rate */
2059     workRate = (float)clkRate * (float)findPllMMultFromSetup(pSetup);
2060     workRate /= (float)postdiv;
2061 
2062     return (uint32_t)workRate;
2063 }
2064 
2065 /* Set PLL output based on the passed PLL setup data */
2066 /*! brief    Set PLL output based on the passed PLL setup data
2067  *  param    pControl    : Pointer to populated PLL control structure to generate setup with
2068  *  param    pSetup      : Pointer to PLL setup structure to be filled
2069  *  return   PLL_ERROR_SUCCESS on success, or PLL setup error code
2070  *  note Actual frequency for setup may vary from the desired frequency based on the
2071  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.
2072  */
CLOCK_SetupPLLData(pll_config_t * pControl,pll_setup_t * pSetup)2073 pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
2074 {
2075     uint32_t inRate;
2076     bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0UL);
2077 
2078     pll_error_t pllError;
2079 
2080     /* Get PLL Input Clock Rate */
2081     switch (pControl->inputSource)
2082     {
2083         case (uint32_t)kPll_ClkSrcSysOsc:
2084             inRate = CLOCK_GetExtClkFreq();
2085             break;
2086         case (uint32_t)kPll_ClkSrcFirc:
2087             inRate = CLOCK_GetClk48MFreq();
2088             break;
2089         case (uint32_t)kPll_ClkSrcRosc:
2090             inRate = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2091             break;
2092         default:
2093             inRate = 0U;
2094             break;
2095     }
2096 
2097     /* PLL flag options */
2098     pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup, useSS);
2099     pSetup->pllctrl |= (uint32_t)pControl->inputSource;
2100     if ((useSS) && (pllError == kStatus_PLL_Success))
2101     {
2102         /* If using SS mode, then some tweaks are made to the generated setup */
2103         pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
2104         if (pControl->mfDither)
2105         {
2106             pSetup->pllsscg[1] |= (1UL << SCG_APLLSSCG1_DITHER_SHIFT);
2107         }
2108     }
2109 
2110     return pllError;
2111 }
2112 
2113 /* Setup PLL Frequency from pre-calculated value */
2114 /**
2115  * brief Set PLL0 output from PLL setup structure (precise frequency)
2116  * param pSetup  : Pointer to populated PLL setup structure
2117  * return    kStatus_PLL_Success on success, or PLL setup error code
2118  * note  This function will power off the PLL, setup the PLL with the
2119  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2120  * and adjust system voltages to the new PLL rate. The function will not
2121  * alter any source clocks (ie, main systen clock) that may use the PLL,
2122  * so these should be setup prior to and after exiting the function.
2123  */
CLOCK_SetPLL0Freq(const pll_setup_t * pSetup)2124 pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
2125 {
2126     uint32_t inRate, clkRate, prediv;
2127 
2128     /* Enable LDO */
2129     SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
2130 
2131     /* Power off PLL0 and disable PLL0 clock during setup changes */
2132     SCG0->APLLCSR &= ~(SCG_APLLCSR_APLLPWREN_MASK | SCG_APLLCSR_APLLCLKEN_MASK);
2133 
2134     /* Write PLL setup data */
2135     SCG0->APLLCTRL  = pSetup->pllctrl;
2136     SCG0->APLLNDIV  = pSetup->pllndiv;
2137     SCG0->APLLNDIV  = pSetup->pllndiv | (1UL << SCG_APLLNDIV_NREQ_SHIFT); /* latch */
2138     SCG0->APLLPDIV  = pSetup->pllpdiv;
2139     SCG0->APLLPDIV  = pSetup->pllpdiv | (1UL << SCG_APLLPDIV_PREQ_SHIFT); /* latch */
2140     SCG0->APLLMDIV  = pSetup->pllmdiv;
2141     SCG0->APLLMDIV  = pSetup->pllmdiv | (1UL << SCG_APLLMDIV_MREQ_SHIFT); /* latch */
2142     SCG0->APLLSSCG0 = pSetup->pllsscg[0];
2143     SCG0->APLLSSCG1 = pSetup->pllsscg[1];
2144 
2145     /* Unlock APLLLOCK_CNFG register */
2146     SCG0->TRIM_LOCK = 0x5a5a0001;
2147 
2148     /* Configure lock time of APLL stable, value = 500us/x+300, where x is the period of clk_ref (clk_in/N). */
2149     inRate = CLOCK_GetPLL0InClockRate();
2150     prediv = findPll0PreDiv();
2151     /* Adjust input clock */
2152     clkRate             = inRate / prediv;
2153     SCG0->APLLLOCK_CNFG = SCG_APLLLOCK_CNFG_LOCK_TIME(clkRate / 2000U + 300U);
2154 
2155     /* Power on PLL0 and enable PLL0 clock */
2156     SCG0->APLLCSR |= (SCG_APLLCSR_APLLPWREN_MASK | SCG_APLLCSR_APLLCLKEN_MASK);
2157 
2158     /* Wait for APLL lock */
2159     while (CLOCK_IsPLL0Locked() == false)
2160     {
2161     }
2162 
2163     if (pSetup->pllRate != CLOCK_GetPll0OutFreq())
2164     {
2165         return kStatus_PLL_OutputError;
2166     }
2167 
2168     return kStatus_PLL_Success;
2169 }
2170 
2171 /* Setup PLL1 Frequency from pre-calculated value */
2172 /**
2173  * brief Set PLL1 output from PLL setup structure (precise frequency)
2174  * param pSetup  : Pointer to populated PLL setup structure
2175  * return    kStatus_PLL_Success on success, or PLL setup error code
2176  * note  This function will power off the PLL, setup the PLL with the
2177  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2178  * and adjust system voltages to the new PLL rate. The function will not
2179  * alter any source clocks (ie, main systen clock) that may use the PLL,
2180  * so these should be setup prior to and after exiting the function.
2181  */
CLOCK_SetPLL1Freq(const pll_setup_t * pSetup)2182 pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
2183 {
2184     uint32_t inRate, clkRate, prediv;
2185 
2186     /* Enable LDO */
2187     SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
2188 
2189     /* Power off PLL1 and disable PLL1 clock during setup changes */
2190     SCG0->SPLLCSR &= ~(SCG_SPLLCSR_SPLLPWREN_MASK | SCG_SPLLCSR_SPLLCLKEN_MASK);
2191 
2192     /* Write PLL setup data */
2193     SCG0->SPLLCTRL  = pSetup->pllctrl;
2194     SCG0->SPLLNDIV  = pSetup->pllndiv;
2195     SCG0->SPLLNDIV  = pSetup->pllndiv | (1UL << SCG_SPLLNDIV_NREQ_SHIFT); /* latch */
2196     SCG0->SPLLPDIV  = pSetup->pllpdiv;
2197     SCG0->SPLLPDIV  = pSetup->pllpdiv | (1UL << SCG_SPLLPDIV_PREQ_SHIFT); /* latch */
2198     SCG0->SPLLMDIV  = pSetup->pllmdiv;
2199     SCG0->SPLLMDIV  = pSetup->pllmdiv | (1UL << SCG_SPLLMDIV_MREQ_SHIFT); /* latch */
2200     SCG0->SPLLSSCG0 = pSetup->pllsscg[0];
2201     SCG0->SPLLSSCG1 = pSetup->pllsscg[1];
2202 
2203     /* Unlock SPLLLOCK_CNFG register */
2204     SCG0->TRIM_LOCK = 0x5a5a0001;
2205 
2206     /* Configure lock time of APLL stable, value = 500μs/x+300, where x is the period of clk_ref (clk_in/N). */
2207     inRate = CLOCK_GetPLL1InClockRate();
2208     prediv = findPll1PreDiv();
2209     /* Adjust input clock */
2210     clkRate             = inRate / prediv;
2211     SCG0->SPLLLOCK_CNFG = SCG_SPLLLOCK_CNFG_LOCK_TIME(clkRate / 2000U + 300U);
2212 
2213     /* Power on PLL1 and enable PLL1 clock */
2214     SCG0->SPLLCSR |= (SCG_SPLLCSR_SPLLPWREN_MASK | SCG_SPLLCSR_SPLLCLKEN_MASK);
2215 
2216     /* Wait for APLL lock */
2217     while (CLOCK_IsPLL1Locked() == false)
2218     {
2219     }
2220 
2221     if (pSetup->pllRate != CLOCK_GetPll1OutFreq())
2222     {
2223         return kStatus_PLL_OutputError;
2224     }
2225 
2226     return kStatus_PLL_Success;
2227 }
2228 
2229 /*! @brief Enable the OSTIMER 32k clock.
2230  *  @return  Nothing
2231  */
CLOCK_EnableOstimer32kClock(void)2232 void CLOCK_EnableOstimer32kClock(void)
2233 {
2234     // PMC->OSEVENTTIMER |= PMC_OSEVENTTIMER_CLOCKENABLE_MASK;
2235 }
2236 
2237 /* Get FRO 12M Clk */
2238 /*! brief  Return Frequency of FRO 12MHz
2239  *  return Frequency of FRO 12MHz
2240  */
CLOCK_GetFro12MFreq(void)2241 static uint32_t CLOCK_GetFro12MFreq(void)
2242 {
2243     return ((SCG0->SIRCCSR & SCG_SIRCCSR_SIRC_CLK_PERIPH_EN_MASK) != 0UL) ? 12000000U : 0U;
2244 }
2245 
2246 /* Get CLK 1M Clk */
2247 /*! brief  Return Frequency of CLK 1MHz
2248  *  return Frequency of CLK 1MHz
2249  */
CLOCK_GetClk1MFreq(void)2250 static uint32_t CLOCK_GetClk1MFreq(void)
2251 {
2252     return 1000000U;
2253 }
2254 
2255 /* Get HF FRO Clk */
2256 /*! brief  Return Frequency of High-Freq output of FRO
2257  *  return Frequency of High-Freq output of FRO
2258  */
CLOCK_GetFroHfFreq(void)2259 static uint32_t CLOCK_GetFroHfFreq(void)
2260 {
2261     uint32_t freq;
2262 
2263     if ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRCEN_MASK) == 0UL)
2264     {
2265         freq = 0;
2266     }
2267     else if ((SCG0->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) != 0UL)
2268     {
2269         freq = 144000000U;
2270     }
2271     else
2272     {
2273         freq = 48000000U;
2274     }
2275 
2276     return freq;
2277 }
2278 
2279 /* Get CLK 48M Clk */
2280 /*! brief  Return Frequency of CLK 48MHz
2281  *  return Frequency of CLK 48MHz
2282  */
CLOCK_GetClk48MFreq(void)2283 static uint32_t CLOCK_GetClk48MFreq(void)
2284 {
2285     return ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRC_SCLK_PERIPH_EN_MASK) != 0U) ? 48000000U : 0U;
2286 }
2287 
2288 /* Get CLK 144M Clk */
2289 /*! brief  Return Frequency of CLK 144MHz
2290  *  return Frequency of CLK 144MHz
2291  */
CLOCK_GetClk144MFreq(void)2292 static uint32_t CLOCK_GetClk144MFreq(void)
2293 {
2294     return ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRC_FCLK_PERIPH_EN_MASK) != 0U) ? 144000000U : 0U;
2295 }
2296 
2297 /* Get CLK 16K Clk */
2298 /*! brief  Return Frequency of CLK 16KHz
2299  *  return Frequency of CLK 16KHz
2300  */
CLOCK_GetClk16KFreq(uint32_t id)2301 static uint32_t CLOCK_GetClk16KFreq(uint32_t id)
2302 {
2303     return ((VBAT0->FROCTLA & VBAT_FROCTLA_FRO_EN_MASK) != 0U) ?
2304                (((VBAT0->FROCLKE & VBAT_FROCLKE_CLKE(id)) != 0UL) ? 16000U : 0U) :
2305                0U;
2306 }
2307 
2308 /* Get EXT OSC Clk */
2309 /*! brief  Return Frequency of External Clock
2310  *  return Frequency of External Clock. If no external clock is used returns 0.
2311  */
CLOCK_GetExtClkFreq(void)2312 static uint32_t CLOCK_GetExtClkFreq(void)
2313 {
2314     return ((SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
2315 }
2316 
2317 /* Get RTC OSC Clk */
2318 /*! brief  Return Frequency of 32kHz osc
2319  *  return Frequency of 32kHz osc
2320  */
CLOCK_GetOsc32KFreq(uint32_t id)2321 static uint32_t CLOCK_GetOsc32KFreq(uint32_t id)
2322 {
2323     return ((SCG0->ROSCCSR & SCG_ROSCCSR_ROSCVLD_MASK) != 0UL) ?
2324                (((VBAT0->OSCCLKE & VBAT_OSCCLKE_CLKE(id)) != 0UL) ? s_Xtal32_Freq : 0U) :
2325                0U;
2326 }
2327 
2328 /* Get MAIN Clk */
2329 /*! @brief  Return Frequency of main
2330  *  @return Frequency of the main
2331  */
CLOCK_GetMainClkFreq(void)2332 uint32_t CLOCK_GetMainClkFreq(void)
2333 {
2334     uint32_t freq = 0U;
2335 
2336     switch ((SCG0->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT)
2337     {
2338         case 1U:
2339             freq = CLOCK_GetExtClkFreq();
2340             break;
2341         case 2U:
2342             freq = CLOCK_GetFro12MFreq();
2343             break;
2344         case 3U:
2345             freq = CLOCK_GetFroHfFreq();
2346             break;
2347         case 4U:
2348             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToWake);
2349             break;
2350         case 5U:
2351             freq = CLOCK_GetPll0OutFreq();
2352             break;
2353         case 6U:
2354             freq = CLOCK_GetPll1OutFreq();
2355             break;
2356         case 7U:
2357             // freq = CLOCK_GetUPllOutFreq();
2358             break;
2359         default:
2360             freq = 0U;
2361             break;
2362     }
2363 
2364     return freq;
2365 }
2366 
2367 /* Get cpu Clk */
2368 /*! brief  Return Frequency of Core System
2369  *  return Frequency of Core System
2370  */
CLOCK_GetCoreSysClkFreq(void)2371 uint32_t CLOCK_GetCoreSysClkFreq(void)
2372 {
2373     uint32_t freq = 0U;
2374 
2375     freq = CLOCK_GetMainClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
2376 
2377     return freq;
2378 }
2379 
2380 /* Get Systick Clk */
2381 /*! brief  Return Frequency of SystickClock
2382  *  return Frequency of Systick Clock
2383  */
CLOCK_GetSystickClkFreq(uint32_t id)2384 static uint32_t CLOCK_GetSystickClkFreq(uint32_t id)
2385 {
2386     uint32_t freq = 0U;
2387 
2388     switch ((id == 0U) ? SYSCON->SYSTICKCLKSEL0 : SYSCON->SYSTICKCLKSEL1)
2389     {
2390         case 0U:
2391             freq = CLOCK_GetMainClkFreq() / (((SYSCON->SYSTICKCLKDIV[id]) & 0xffU) + 1U);
2392             break;
2393         case 1U:
2394             freq = CLOCK_GetClk1MFreq();
2395             break;
2396         case 2U:
2397             freq = CLOCK_GetLposcFreq();
2398             break;
2399         default:
2400             freq = 0U;
2401             break;
2402     }
2403 
2404     return freq;
2405 }
2406 
2407 /* Get CLOCK OUT Clk */
2408 /*! brief  Return Frequency of ClockOut
2409  *  return Frequency of ClockOut
2410  */
CLOCK_GetClockOutClkFreq(void)2411 static uint32_t CLOCK_GetClockOutClkFreq(void)
2412 {
2413     uint32_t freq = 0U;
2414 
2415     switch (SYSCON->CLKOUTSEL)
2416     {
2417         case 0U:
2418             freq = CLOCK_GetMainClkFreq();
2419             break;
2420         case 1U:
2421             freq = CLOCK_GetPll0OutFreq();
2422             break;
2423         case 2U:
2424             freq = CLOCK_GetExtClkFreq();
2425             break;
2426         case 3U:
2427             freq = CLOCK_GetFroHfFreq();
2428             break;
2429         case 4U:
2430             freq = CLOCK_GetFro12MFreq();
2431             break;
2432         case 5U:
2433             freq = CLOCK_GetPll1OutFreq() / (((SYSCON->PLL1CLK0DIV) & 0xffU) + 1U);
2434             break;
2435         case 6U:
2436             freq = CLOCK_GetLposcFreq();
2437             break;
2438         case 7U:
2439             // freq = CLOCK_GetUPllOutFreq();
2440             break;
2441         default:
2442             freq = 0U;
2443             break;
2444     }
2445     return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
2446 }
2447 
2448 /* Get LP_OSC Clk */
2449 /*! brief  Return Frequency of LP_OSC
2450  *  return Frequency of LP_OSC
2451  */
CLOCK_GetLposcFreq(void)2452 static uint32_t CLOCK_GetLposcFreq(void)
2453 {
2454     uint32_t freq = 0U;
2455 
2456     switch ((RTC0->CTRL & RTC_CTRL_CLK_SEL_MASK) >> RTC_CTRL_CLK_SEL_SHIFT)
2457     {
2458         case 1U:
2459             freq = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2460             break;
2461         case 2U:
2462             freq = CLOCK_GetClk16KFreq((uint32_t)kCLOCK_Clk16KToVbat);
2463             break;
2464         default:
2465             freq = 0U;
2466             break;
2467     }
2468 
2469     return freq;
2470 }
2471 
2472 /* 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)2473 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
2474 {
2475     uint32_t seli, selp;
2476     /* bandwidth: compute selP from Multiplier */
2477     if ((SCG0->APLLCTRL & SCG_APLLCTRL_LIMUPOFF_MASK) == 0UL) /* normal mode */
2478     {
2479         selp = (M >> 2U) + 1U;
2480         if (selp >= 31U)
2481         {
2482             selp = 31U;
2483         }
2484         *pSelP = selp;
2485 
2486         if (M >= 8000UL)
2487         {
2488             seli = 1UL;
2489         }
2490         else if (M >= 122UL)
2491         {
2492             seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
2493         }
2494         else
2495         {
2496             seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
2497         }
2498 
2499         if (seli >= 63UL)
2500         {
2501             seli = 63UL;
2502         }
2503         *pSelI = seli;
2504 
2505         *pSelR = 0U;
2506     }
2507     else
2508     {
2509         /* Note: If the spread spectrum and fractional mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
2510         *pSelP = 3U;
2511         *pSelI = 4U;
2512         *pSelR = 4U;
2513     }
2514 }
2515 
2516 /* Get predivider (N) from PLL0 NDIV setting */
findPll0PreDiv(void)2517 static uint32_t findPll0PreDiv(void)
2518 {
2519     uint32_t preDiv = 1UL;
2520 
2521     /* Direct input is not used? */
2522     if ((SCG0->APLLCTRL & SCG_APLLCTRL_BYPASSPREDIV_MASK) == 0UL)
2523     {
2524         preDiv = SCG0->APLLNDIV & SCG_APLLNDIV_NDIV_MASK;
2525         if (preDiv == 0UL)
2526         {
2527             preDiv = 1UL;
2528         }
2529     }
2530     return preDiv;
2531 }
2532 
2533 /* Get predivider (N) from PLL1 NDIV setting */
findPll1PreDiv(void)2534 static uint32_t findPll1PreDiv(void)
2535 {
2536     uint32_t preDiv = 1UL;
2537 
2538     /* Direct input is not used? */
2539     if ((SCG0->SPLLCTRL & SCG_SPLLCTRL_BYPASSPREDIV_MASK) == 0UL)
2540     {
2541         preDiv = SCG0->SPLLNDIV & SCG_SPLLNDIV_NDIV_MASK;
2542         if (preDiv == 0UL)
2543         {
2544             preDiv = 1UL;
2545         }
2546     }
2547     return preDiv;
2548 }
2549 
2550 /* Get postdivider (P) from PLL0 PDIV setting */
findPll0PostDiv(void)2551 static uint32_t findPll0PostDiv(void)
2552 {
2553     uint32_t postDiv = 1UL;
2554 
2555     if ((SCG0->APLLCTRL & SCG_APLLCTRL_BYPASSPOSTDIV_MASK) == 0UL)
2556     {
2557         if ((SCG0->APLLCTRL & SCG_APLLCTRL_BYPASSPOSTDIV2_MASK) != 0UL)
2558         {
2559             postDiv = SCG0->APLLPDIV & SCG_APLLPDIV_PDIV_MASK;
2560         }
2561         else
2562         {
2563             postDiv = 2UL * (SCG0->APLLPDIV & SCG_APLLPDIV_PDIV_MASK);
2564         }
2565         if (postDiv == 0UL)
2566         {
2567             postDiv = 2UL;
2568         }
2569     }
2570 
2571     return postDiv;
2572 }
2573 
2574 /* Get postdivider (P) from PLL1 PDIV setting. */
findPll1PostDiv(void)2575 static uint32_t findPll1PostDiv(void)
2576 {
2577     uint32_t postDiv = 1UL;
2578 
2579     if ((SCG0->SPLLCTRL & SCG_SPLLCTRL_BYPASSPOSTDIV_MASK) == 0UL)
2580     {
2581         if ((SCG0->SPLLCTRL & SCG_SPLLCTRL_BYPASSPOSTDIV2_MASK) != 0UL)
2582         {
2583             postDiv = SCG0->SPLLPDIV & SCG_SPLLPDIV_PDIV_MASK;
2584         }
2585         else
2586         {
2587             postDiv = 2UL * (SCG0->SPLLPDIV & SCG_SPLLPDIV_PDIV_MASK);
2588         }
2589         if (postDiv == 0UL)
2590         {
2591             postDiv = 2UL;
2592         }
2593     }
2594 
2595     return postDiv;
2596 }
2597 
2598 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)2599 static float findPll0MMult(void)
2600 {
2601     float mMult = 1.0F;
2602     float mMult_fract;
2603     uint32_t mMult_int;
2604 
2605     if ((SCG0->APLLSSCG1 & SCG_APLLSSCG1_SEL_SS_MDIV_MASK) == 0UL)
2606     {
2607         mMult = (float)(uint32_t)(SCG0->APLLMDIV & SCG_APLLMDIV_MDIV_MASK);
2608     }
2609     else
2610     {
2611         mMult_int = ((SCG0->APLLSSCG1 & SCG_APLLSSCG1_SS_MDIV_MSB_MASK) << 7U);
2612         mMult_int = mMult_int | ((SCG0->APLLSSCG0) >> PLL_SSCG_MD_INT_P);
2613         mMult_fract =
2614             ((float)(uint32_t)((SCG0->APLLSSCG0) & PLL_SSCG_MD_FRACT_M) / (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P));
2615         mMult = (float)mMult_int + mMult_fract;
2616     }
2617     if (0ULL == ((uint64_t)mMult))
2618     {
2619         mMult = 1.0F;
2620     }
2621     return mMult;
2622 }
2623 
2624 /* Get multiplier (M) from PLL1 MDEC. */
findPll1MMult(void)2625 static float findPll1MMult(void)
2626 {
2627     float mMult = 1.0F;
2628     float mMult_fract;
2629     uint32_t mMult_int;
2630 
2631     if ((SCG0->SPLLSSCG1 & SCG_SPLLSSCG1_SEL_SS_MDIV_MASK) == 0UL)
2632     {
2633         mMult = (float)(uint32_t)(SCG0->SPLLMDIV & SCG_SPLLMDIV_MDIV_MASK);
2634     }
2635     else
2636     {
2637         mMult_int = ((SCG0->SPLLSSCG1 & SCG_SPLLSSCG1_SS_MDIV_MSB_MASK) << 7U);
2638         mMult_int = mMult_int | ((SCG0->SPLLSSCG0) >> PLL_SSCG_MD_INT_P);
2639         mMult_fract =
2640             ((float)(uint32_t)((SCG0->SPLLSSCG0) & PLL_SSCG_MD_FRACT_M) / (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P));
2641         mMult = (float)mMult_int + mMult_fract;
2642     }
2643     if (0ULL == ((uint64_t)mMult))
2644     {
2645         mMult = 1.0F;
2646     }
2647     return mMult;
2648 }
2649 
2650 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)2651 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
2652 {
2653     uint32_t tmp;
2654 
2655     while (n != 0U)
2656     {
2657         tmp = n;
2658         n   = m % n;
2659         m   = tmp;
2660     }
2661 
2662     return m;
2663 }
2664 
2665 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
2666 /* Alloct the static buffer for cache. */
2667 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
2668 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]  = {0};
2669 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
2670 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]      = {false};
2671 static uint32_t s_PllSetupCacheIdx                                  = 0U;
2672 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
2673 
2674 /*
2675  * Calculate the PLL setting values from input clock freq to output freq.
2676  */
CLOCK_GetPllConfig(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)2677 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
2678 {
2679     pll_error_t retErr;
2680 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
2681     uint32_t i;
2682 
2683     for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
2684     {
2685         if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
2686         {
2687             /* Hit the target in cache buffer. */
2688             pSetup->pllctrl    = s_PllSetupCacheStruct[i].pllctrl;
2689             pSetup->pllndiv    = s_PllSetupCacheStruct[i].pllndiv;
2690             pSetup->pllmdiv    = s_PllSetupCacheStruct[i].pllmdiv;
2691             pSetup->pllpdiv    = s_PllSetupCacheStruct[i].pllpdiv;
2692             pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
2693             pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
2694             retErr             = kStatus_PLL_Success;
2695             break;
2696         }
2697     }
2698 
2699     if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
2700     {
2701         return retErr;
2702     }
2703 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
2704 
2705     retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup, useSS);
2706 
2707 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
2708     /* Cache the most recent calulation result into buffer. */
2709     s_FinHzCache[s_PllSetupCacheIdx]  = finHz;
2710     s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
2711     s_UseSSCache[s_PllSetupCacheIdx]  = useSS;
2712 
2713     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl    = pSetup->pllctrl;
2714     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndiv    = pSetup->pllndiv;
2715     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllmdiv    = pSetup->pllmdiv;
2716     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdiv    = pSetup->pllpdiv;
2717     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
2718     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
2719     /* Update the index for next available buffer. */
2720     s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
2721 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
2722 
2723     return retErr;
2724 }
2725 
2726 /*
2727  * Set PLL output based on desired output rate.
2728  * In this function, the it calculates the PLL0 setting for output frequency from input clock
2729  * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
2730  * the "pllctrl", "pllndiv", "pllpdiv", "pllmdiv" would updated in this function.
2731  */
CLOCK_GetPllConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)2732 static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
2733 {
2734     uint32_t nDivOutHz, fccoHz;
2735     uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
2736     uint32_t pllDirectInput, pllDirectOutput;
2737     uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
2738 
2739     /* Baseline parameters (no input or output dividers) */
2740     pllPreDivider   = 1U; /* 1 implies pre-divider will be disabled */
2741     pllPostDivider  = 1U; /* 1 implies post-divider will be disabled */
2742     pllDirectOutput = 1U;
2743 
2744     /* Verify output rate parameter */
2745     if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
2746     {
2747         /* Maximum PLL output with post divider=1 cannot go above this frequency */
2748         return kStatus_PLL_OutputTooHigh;
2749     }
2750     if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
2751     {
2752         /* Minmum PLL output with maximum post divider cannot go below this frequency */
2753         return kStatus_PLL_OutputTooLow;
2754     }
2755 
2756     /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
2757     if (useSS)
2758     {
2759         /* Verify input rate parameter */
2760         if (finHz < PLL_MIN_IN_SSMODE)
2761         {
2762             /* Input clock into the PLL cannot be lower than this */
2763             return kStatus_PLL_InputTooLow;
2764         }
2765         /* PLL input in SS mode must be under 20MHz */
2766         if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
2767         {
2768             return kStatus_PLL_InputTooHigh;
2769         }
2770     }
2771     else
2772     {
2773         /* Verify input rate parameter */
2774         if (finHz < PLL_LOWER_IN_LIMIT)
2775         {
2776             /* Input clock into the PLL cannot be lower than this */
2777             return kStatus_PLL_InputTooLow;
2778         }
2779         if (finHz > PLL_HIGHER_IN_LIMIT)
2780         {
2781             /* Input clock into the PLL cannot be higher than this */
2782             return kStatus_PLL_InputTooHigh;
2783         }
2784     }
2785 
2786     /* Find the optimal CCO frequency for the output and input that
2787        will keep it inside the PLL CCO range. This may require
2788        tweaking the post-divider for the PLL. */
2789     fccoHz = foutHz;
2790     while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
2791     {
2792         /* CCO output is less than minimum CCO range, so the CCO output
2793            needs to be bumped up and the post-divider is used to bring
2794            the PLL output back down. */
2795         pllPostDivider++;
2796         if (pllPostDivider > PVALMAX)
2797         {
2798             return kStatus_PLL_OutsideIntLimit;
2799         }
2800 
2801         /* Target CCO goes up, PLL output goes down */
2802         /* divide-by-2 divider in the post-divider is always work*/
2803         fccoHz          = foutHz * (pllPostDivider * 2U);
2804         pllDirectOutput = 0U;
2805     }
2806 
2807     /* Determine if a pre-divider is needed to get the best frequency */
2808     if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
2809     {
2810         uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
2811 
2812         if (a > PLL_LOWER_IN_LIMIT)
2813         {
2814             a = finHz / a;
2815             if ((a != 0U) && (a < PLL_MAX_N_DIV))
2816             {
2817                 pllPreDivider = a;
2818             }
2819         }
2820     }
2821 
2822     /* Bypass pre-divider hardware if pre-divider is 1 */
2823     if (pllPreDivider > 1U)
2824     {
2825         pllDirectInput = 0U;
2826     }
2827     else
2828     {
2829         pllDirectInput = 1U;
2830     }
2831 
2832     /* Determine PLL multipler */
2833     nDivOutHz     = (finHz / pllPreDivider);
2834     pllMultiplier = (fccoHz / nDivOutHz);
2835 
2836     /* Find optimal values for filter */
2837     if (useSS == false)
2838     {
2839         /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
2840         if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
2841         {
2842             pllMultiplier++;
2843         }
2844 
2845         /* Setup filtering */
2846         pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
2847         uplimoff = 0U;
2848 
2849         /* Get encoded value for M (mult) and use manual filter, disable SS mode */
2850         pSetup->pllmdiv = (uint32_t)PLL_MDIV_VAL_SET(pllMultiplier);
2851         pSetup->pllsscg[1] &= ~SCG_APLLSSCG1_SEL_SS_MDIV_MASK;
2852     }
2853     else
2854     {
2855         uint64_t fc;
2856 
2857         /* Filtering will be handled by SSC */
2858         pllSelR  = 0UL;
2859         pllSelI  = 0UL;
2860         pllSelP  = 0UL;
2861         uplimoff = 1U;
2862 
2863         /* The PLL multiplier will get very close and slightly under the
2864            desired target frequency. A small fractional component can be
2865            added to fine tune the frequency upwards to the target. */
2866         fc = ((uint64_t)(uint32_t)(fccoHz % nDivOutHz) << 25UL) / nDivOutHz;
2867 
2868         /* Set multiplier */
2869         pSetup->pllsscg[0] = (uint32_t)(PLL_SSCG_MD_INT_SET(pllMultiplier) | PLL_SSCG_MD_FRACT_SET((uint32_t)fc));
2870         pSetup->pllsscg[1] = (uint32_t)(PLL_SSCG_MD_INT_SET(pllMultiplier) >> 32U) | SCG_APLLSSCG1_SEL_SS_MDIV_MASK;
2871     }
2872 
2873     /* Get encoded values for N (prediv) and P (postdiv) */
2874     pSetup->pllndiv = PLL_NDIV_VAL_SET(pllPreDivider);
2875     pSetup->pllpdiv = PLL_PDIV_VAL_SET(pllPostDivider);
2876 
2877     /* PLL control */
2878     pSetup->pllctrl = (pllSelR << SCG_APLLCTRL_SELR_SHIFT) |                 /* Filter coefficient */
2879                       (pllSelI << SCG_APLLCTRL_SELI_SHIFT) |                 /* Filter coefficient */
2880                       (pllSelP << SCG_APLLCTRL_SELP_SHIFT) |                 /* Filter coefficient */
2881                       (uplimoff << SCG_APLLCTRL_LIMUPOFF_SHIFT) |            /* SS/fractional mode disabled */
2882                       (pllDirectInput << SCG_APLLCTRL_BYPASSPREDIV_SHIFT) |  /* Bypass pre-divider? */
2883                       (pllDirectOutput << SCG_APLLCTRL_BYPASSPOSTDIV_SHIFT); /* Bypass post-divider? */
2884 
2885     return kStatus_PLL_Success;
2886 }
2887 
2888 /* Get PLL input clock rate from setup structure */
CLOCK_GetPLLInClockRateFromSetup(pll_setup_t * pSetup)2889 static uint32_t CLOCK_GetPLLInClockRateFromSetup(pll_setup_t *pSetup)
2890 {
2891     uint32_t clkRate = 0U;
2892 
2893     switch ((pSetup->pllctrl & SCG_APLLCTRL_SOURCE_MASK) >> SCG_APLLCTRL_SOURCE_SHIFT)
2894     {
2895         case 0x00U:
2896             clkRate = CLOCK_GetExtClkFreq();
2897             break;
2898         case 0x01U:
2899             clkRate = CLOCK_GetClk48MFreq();
2900             break;
2901         case 0x02U:
2902             clkRate = CLOCK_GetOsc32KFreq((uint32_t)kCLOCK_Osc32kToVbat);
2903             break;
2904         default:
2905             clkRate = 0U;
2906             break;
2907     }
2908 
2909     return clkRate;
2910 }
2911 
2912 /* Get predivider (N) from from setup structure */
findPllPreDivFromSetup(pll_setup_t * pSetup)2913 static uint32_t findPllPreDivFromSetup(pll_setup_t *pSetup)
2914 {
2915     uint32_t preDiv = 1UL;
2916 
2917     /* Direct input is not used? */
2918     if ((pSetup->pllctrl & SCG_APLLCTRL_BYPASSPREDIV_MASK) == 0UL)
2919     {
2920         preDiv = pSetup->pllndiv & SCG_APLLNDIV_NDIV_MASK;
2921         if (preDiv == 0UL)
2922         {
2923             preDiv = 1UL;
2924         }
2925     }
2926     return preDiv;
2927 }
2928 
2929 /* Get postdivider (P) from from setup structure */
findPllPostDivFromSetup(pll_setup_t * pSetup)2930 static uint32_t findPllPostDivFromSetup(pll_setup_t *pSetup)
2931 {
2932     uint32_t postDiv = 1UL;
2933 
2934     if ((pSetup->pllctrl & SCG_APLLCTRL_BYPASSPOSTDIV_MASK) == 0UL)
2935     {
2936         if ((pSetup->pllctrl & SCG_APLLCTRL_BYPASSPOSTDIV2_MASK) != 0UL)
2937         {
2938             postDiv = pSetup->pllpdiv & SCG_APLLPDIV_PDIV_MASK;
2939         }
2940         else
2941         {
2942             postDiv = 2UL * (pSetup->pllpdiv & SCG_APLLPDIV_PDIV_MASK);
2943         }
2944         if (postDiv == 0UL)
2945         {
2946             postDiv = 2UL;
2947         }
2948     }
2949 
2950     return postDiv;
2951 }
2952 
2953 /* Get multiplier (M) from from setup structure */
findPllMMultFromSetup(pll_setup_t * pSetup)2954 static float findPllMMultFromSetup(pll_setup_t *pSetup)
2955 {
2956     float mMult = 1.0F;
2957     float mMult_fract;
2958     uint32_t mMult_int;
2959 
2960     if ((pSetup->pllsscg[1] & SCG_APLLSSCG1_SEL_SS_MDIV_MASK) == 0UL)
2961     {
2962         mMult = (float)(uint32_t)(pSetup->pllmdiv & SCG_APLLMDIV_MDIV_MASK);
2963     }
2964     else
2965     {
2966         mMult_int   = ((pSetup->pllsscg[1] & SCG_APLLSSCG1_SS_MDIV_MSB_MASK) << 7U);
2967         mMult_int   = mMult_int | ((pSetup->pllsscg[0]) >> PLL_SSCG_MD_INT_P);
2968         mMult_fract = ((float)(uint32_t)((pSetup->pllsscg[0]) & PLL_SSCG_MD_FRACT_M) /
2969                        (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P));
2970         mMult       = (float)mMult_int + mMult_fract;
2971     }
2972     if (0ULL == ((uint64_t)mMult))
2973     {
2974         mMult = 1.0F;
2975     }
2976     return mMult;
2977 }
2978 
2979 /*! brief Enable USB FS clock.
2980  * Enable USB Full Speed clock.
2981  */
CLOCK_EnableUsbfsClock(void)2982 bool CLOCK_EnableUsbfsClock(void)
2983 {
2984     SYSCON->USB0CLKSEL = 0x3U; /* Clk 48 MHz clock */
2985     CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1);
2986     SYSCON->USB0CLKDIV &= (uint32_t) ~(SYSCON_USB0CLKDIV_HALT_MASK | SYSCON_USB0CLKDIV_RESET_MASK);
2987     /* Wait until clock change completes */
2988     while ((SYSCON->USB0CLKDIV & SYSCON_SYSTICKCLKDIV_UNSTAB_MASK) != 0U)
2989     {
2990     }
2991     return true;
2992 }
2993 
2994 /*! brief Enable USB HS PHY PLL clock.
2995  *
2996  * This function enables the internal 480MHz USB PHY PLL clock.
2997  *
2998  * param src  USB HS PHY PLL clock source.
2999  * param freq The frequency specified by src.
3000  * retval true The clock is set successfully.
3001  * retval false The clock source is invalid to get proper USB HS clock.
3002  */
CLOCK_EnableUsbhsPhyPllClock(clock_usb_phy_src_t src,uint32_t freq)3003 bool CLOCK_EnableUsbhsPhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
3004 {
3005     uint32_t phyPllDiv  = 0U;
3006     uint16_t multiplier = 0U;
3007     bool err            = false;
3008 
3009     USBPHY->CTRL_CLR    = USBPHY_CTRL_SFTRST_MASK;
3010     USBPHY->ANACTRL_SET = USBPHY_ANACTRL_LVI_EN_MASK;
3011     USBPHY->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_POWER(1) | USBPHY_PLL_SIC_PLL_REG_ENABLE_MASK);
3012     if ((480000000UL % freq) != 0UL)
3013     {
3014         return false;
3015     }
3016     multiplier = (uint16_t)(480000000UL / freq);
3017 
3018     switch (multiplier)
3019     {
3020         case 15:
3021         {
3022             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
3023             break;
3024         }
3025         case 16:
3026         {
3027             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
3028             break;
3029         }
3030         case 20:
3031         {
3032             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
3033             break;
3034         }
3035         case 22:
3036         {
3037             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(3U);
3038             break;
3039         }
3040         case 24:
3041         {
3042             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U);
3043             break;
3044         }
3045         case 25:
3046         {
3047             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U);
3048             break;
3049         }
3050         case 30:
3051         {
3052             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U);
3053             break;
3054         }
3055         case 40:
3056         {
3057             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(7U);
3058             break;
3059         }
3060         default:
3061         {
3062             err = true;
3063             break;
3064         }
3065     }
3066 
3067     if (err)
3068     {
3069         return false;
3070     }
3071 
3072     USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~(USBPHY_PLL_SIC_PLL_DIV_SEL_MASK)) | phyPllDiv;
3073 
3074     USBPHY->PLL_SIC_CLR = USBPHY_PLL_SIC_PLL_BYPASS_MASK;
3075     USBPHY->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK);
3076 
3077     USBPHY->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK;
3078     USBPHY->PWD      = 0x0U;
3079 
3080     while (0UL == (USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK))
3081     {
3082     }
3083 
3084     return true;
3085 }
3086 
3087 /*! brief Disable USB HS PHY PLL clock.
3088  *
3089  * This function disables USB HS PHY PLL clock.
3090  */
CLOCK_DisableUsbhsPhyPllClock(void)3091 void CLOCK_DisableUsbhsPhyPllClock(void)
3092 {
3093     USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
3094 }
3095 
3096 /*! brief Enable USB HS clock.
3097  * retval true The clock is set successfully.
3098  * retval false The clock source is invalid to get proper USB HS clock.
3099  */
CLOCK_EnableUsbhsClock(void)3100 bool CLOCK_EnableUsbhsClock(void)
3101 {
3102     USBHS1__USBC->USBCMD |= USBHS_USBCMD_RST_MASK;
3103     /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/
3104     for (uint32_t i = 0; i < 400000U; i++)
3105     {
3106         __ASM("nop");
3107     }
3108     return true;
3109 }
3110 
3111 /**
3112  * @brief   FIRC Auto Trim With SOF.
3113  * @return  returns success or fail status.
3114  */
CLOCK_FIRCAutoTrimWithSOF(void)3115 status_t CLOCK_FIRCAutoTrimWithSOF(void)
3116 {
3117     /* System OSC Clock Monitor is disabled */
3118     CLOCK_SetSysOscMonitorMode(kSCG_SysOscMonitorDisable);
3119 
3120     firc_trim_config_t fircAutoTrimConfig = {
3121         .trimMode = kSCG_FircTrimUpdate,        /* FIRC trim is enabled and trim value update is enabled */
3122         .trimSrc  = kSCG_FircTrimSrcUsb0,       /* Trim source is USB0 start of frame (1kHz) */
3123         .trimDiv  = 1U,                         /* Divided value */
3124         .trimCoar = 0U,                         /* Trim value, see Reference Manual for more information */
3125         .trimFine = 0U,                         /* Trim value, see Reference Manual for more information */
3126     };
3127     CLOCK_FROHFTrimConfig(fircAutoTrimConfig);
3128 
3129     return (status_t)kStatus_Success;
3130 }
3131