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