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