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