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