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