1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016 - 2019 , NXP
4 * All rights reserved.
5 *
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 */
9
10 #include "fsl_clock.h"
11 #include "fsl_power.h"
12 /*******************************************************************************
13 * Definitions
14 ******************************************************************************/
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.clock"
18 #endif
19 #define NVALMAX (0x100U)
20 #define PVALMAX (0x20U)
21 #define MVALMAX (0x8000U)
22
23 #define PLL_MAX_N_DIV 0x100U
24
25 #define INDEX_SECTOR_TRIM48 ((uint32_t *)0x01000444U)
26 #define INDEX_SECTOR_TRIM96 ((uint32_t *)0x01000430U)
27 /*--------------------------------------------------------------------------
28 !!! If required these #defines can be moved to chip library file
29 ----------------------------------------------------------------------------*/
30
31 #define PLL_SSCG0_MDEC_VAL_P (0U) /* MDEC is in bits 16 downto 0 */
32 #define PLL_SSCG0_MDEC_VAL_M (0x1FFFFUL << PLL_SSCG0_MDEC_VAL_P) /* NDEC is in bits 9 downto 0 */
33 #define PLL_NDEC_VAL_P (0U) /* NDEC is in bits 9:0 */
34 #define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P)
35 #define PLL_PDEC_VAL_P (0U) /* PDEC is in bits 6:0 */
36 #define PLL_PDEC_VAL_M (0x7FUL << PLL_PDEC_VAL_P)
37
38 #define PLL_MIN_CCO_FREQ_MHZ (75000000U)
39 #define PLL_MAX_CCO_FREQ_MHZ (150000000U)
40 #define PLL_LOWER_IN_LIMIT (4000U) /*!< Minimum PLL input rate */
41 #define PLL_MIN_IN_SSMODE (2000000U)
42 #define PLL_MAX_IN_SSMODE (4000000U)
43
44 /* Middle of the range values for spread-spectrum */
45 #define PLL_SSCG_MF_FREQ_VALUE 4U
46 #define PLL_SSCG_MC_COMP_VALUE 2U
47 #define PLL_SSCG_MR_DEPTH_VALUE 4U
48 #define PLL_SSCG_DITHER_VALUE 0U
49
50 /* PLL NDEC reg */
51 #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
52 /* PLL PDEC reg */
53 #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
54 /* SSCG control0 */
55 #define PLL_SSCG0_MDEC_VAL_SET(value) (((unsigned long)(value) << PLL_SSCG0_MDEC_VAL_P) & PLL_SSCG0_MDEC_VAL_M)
56
57 /* SSCG control1 */
58 #define PLL_SSCG1_MD_FRACT_P 0U
59 #define PLL_SSCG1_MD_INT_P 11U
60 #define PLL_SSCG1_MD_FRACT_M (0x7FFUL << PLL_SSCG1_MD_FRACT_P)
61 #define PLL_SSCG1_MD_INT_M (0xFFUL << PLL_SSCG1_MD_INT_P)
62
63 #define PLL_SSCG1_MD_FRACT_SET(value) (((unsigned long)(value) << PLL_SSCG1_MD_FRACT_P) & PLL_SSCG1_MD_FRACT_M)
64 #define PLL_SSCG1_MD_INT_SET(value) (((unsigned long)(value) << PLL_SSCG1_MD_INT_P) & PLL_SSCG1_MD_INT_M)
65
66 /* Saved value of PLL output rate, computed whenever needed to save run-time
67 computation on each call to retrive the PLL rate. */
68 static uint32_t s_Pll_Freq;
69
70 /* I2S mclk. */
71 static uint32_t s_I2S_Mclk_Freq = 0U;
72
73 /** External clock rate on the CLKIN pin in Hz. If not used,
74 set this to 0. Otherwise, set it to the exact rate in Hz this pin is
75 being driven at. */
76 static const uint32_t s_Ext_Clk_Freq = 0U;
77
78 /*******************************************************************************
79 * Variables
80 ******************************************************************************/
81
82 /*******************************************************************************
83 * Prototypes
84 ******************************************************************************/
85 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
86 static uint32_t pllEncodeN(uint32_t N);
87 /* Find decoded N value for raw NDEC value */
88 static uint32_t pllDecodeN(uint32_t NDEC);
89 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
90 static uint32_t pllEncodeP(uint32_t P);
91 /* Find decoded P value for raw PDEC value */
92 static uint32_t pllDecodeP(uint32_t PDEC);
93 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
94 static uint32_t pllEncodeM(uint32_t M);
95 /* Find decoded M value for raw MDEC value */
96 static uint32_t pllDecodeM(uint32_t MDEC);
97 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
98 static void pllFindSel(uint32_t M, bool bypassFBDIV2, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
99 /* Get predivider (N) from PLL NDEC setting */
100 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg);
101 /* Get postdivider (P) from PLL PDEC setting */
102 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg);
103 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
104 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg);
105 /* Get the greatest common divisor */
106 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
107 /* Set PLL output based on desired output rate */
108 static pll_error_t CLOCK_GetPllConfig(
109 uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useFeedbackDiv2, bool useSS);
110 /* Update local PLL rate variable */
111 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup);
112
113 static const uint8_t wdtFreqLookup[32] = {0, 8, 12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41,
114 42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61};
115 /*******************************************************************************
116 * Code
117 ******************************************************************************/
118
119 /**
120 * brief Configure the clock selection muxes.
121 * param connection : Clock to be configured.
122 * return Nothing
123 */
CLOCK_AttachClk(clock_attach_id_t connection)124 void CLOCK_AttachClk(clock_attach_id_t connection)
125 {
126 uint8_t mux;
127 uint8_t sel;
128 uint16_t item;
129 uint32_t tmp32 = (uint32_t)connection;
130 uint32_t i;
131 volatile uint32_t *pClkSel;
132
133 pClkSel = &(SYSCON->MAINCLKSELA);
134
135 if (kNONE_to_NONE != connection)
136 {
137 for (i = 0U; i < 2U; i++)
138 {
139 if (tmp32 == 0U)
140 {
141 break;
142 }
143 item = (uint16_t)GET_ID_ITEM(tmp32);
144 if (item != 0U)
145 {
146 mux = GET_ID_ITEM_MUX(item);
147 sel = GET_ID_ITEM_SEL(item);
148 if (mux == CM_ASYNCAPB)
149 {
150 ASYNC_SYSCON->ASYNCAPBCLKSELA = sel;
151 }
152 else
153 {
154 ((volatile uint32_t *)pClkSel)[mux] = sel;
155 }
156 }
157 tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
158 }
159 }
160 }
161
162 /* Return the actual clock attach id */
163 /**
164 * brief Get the actual clock attach id.
165 * This fuction uses the offset in input attach id, then it reads the actual source value in
166 * the register and combine the offset to obtain an actual attach id.
167 * param attachId : Clock attach id to get.
168 * return Clock source value.
169 */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)170 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
171 {
172 uint8_t mux;
173 uint8_t actualSel;
174 uint32_t tmp32 = (uint32_t)attachId;
175 uint32_t i;
176 uint32_t actualAttachId = 0U;
177 uint32_t selector = GET_ID_SELECTOR(tmp32);
178 volatile uint32_t *pClkSel;
179
180 pClkSel = &(SYSCON->MAINCLKSELA);
181
182 if (kNONE_to_NONE == attachId)
183 {
184 return kNONE_to_NONE;
185 }
186
187 for (i = 0U; i < 2U; i++)
188 {
189 mux = GET_ID_ITEM_MUX(tmp32);
190 if (tmp32 != 0UL)
191 {
192 if (mux == CM_ASYNCAPB)
193 {
194 actualSel = (uint8_t)(ASYNC_SYSCON->ASYNCAPBCLKSELA);
195 }
196 else
197 {
198 actualSel = (uint8_t)(((volatile uint32_t *)pClkSel)[mux]);
199 }
200
201 /* Consider the combination of two registers */
202 actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
203 }
204 tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */
205 }
206
207 actualAttachId |= selector;
208
209 return (clock_attach_id_t)actualAttachId;
210 }
211
212 /**
213 * brief Setup peripheral clock dividers.
214 * param div_name : Clock divider name
215 * param divided_by_value: Value to be divided
216 * param reset : Whether to reset the divider counter.
217 * return Nothing
218 */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)219 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
220 {
221 volatile uint32_t *pClkDiv;
222
223 pClkDiv = &(SYSCON->SYSTICKCLKDIV);
224 if (reset)
225 {
226 ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 29U;
227 }
228 if (divided_by_value == 0UL) /* halt */
229 {
230 ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 30U;
231 }
232 else
233 {
234 ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = (divided_by_value - 1UL);
235 }
236 }
237
238 /* Set FRO Clocking */
239 /**
240 * brief Initialize the Core clock to given frequency (12, 48 or 96 MHz).
241 * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
242 * enabled.
243 * param iFreq : Desired frequency (must be one of CLK_FRO_12MHZ or CLK_FRO_48MHZ or CLK_FRO_96MHZ)
244 * return returns success or fail status.
245 */
CLOCK_SetupFROClocking(uint32_t iFreq)246 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
247 {
248 uint32_t usb_adj;
249 if ((iFreq != 12000000U) && (iFreq != 48000000U) && (iFreq != 96000000U))
250 {
251 return kStatus_Fail;
252 }
253 /* Power up the FRO and set this as the base clock */
254 POWER_DisablePD(kPDRUNCFG_PD_FRO_EN);
255 /* back up the value of whether USB adj is selected, in which case we will have a value of 1 else 0 */
256 usb_adj = ((SYSCON->FROCTRL) & SYSCON_FROCTRL_USBCLKADJ_MASK) >> SYSCON_FROCTRL_USBCLKADJ_SHIFT;
257 if (iFreq > 12000000U)
258 {
259 if (iFreq == 96000000U)
260 {
261 SYSCON->FROCTRL = ((SYSCON_FROCTRL_TRIM_MASK | SYSCON_FROCTRL_FREQTRIM_MASK) & *INDEX_SECTOR_TRIM96) |
262 SYSCON_FROCTRL_SEL(1) | SYSCON_FROCTRL_WRTRIM(1) | SYSCON_FROCTRL_USBCLKADJ(usb_adj) |
263 SYSCON_FROCTRL_HSPDCLK(1);
264 }
265 else
266 {
267 SYSCON->FROCTRL = ((SYSCON_FROCTRL_TRIM_MASK | SYSCON_FROCTRL_FREQTRIM_MASK) & *INDEX_SECTOR_TRIM48) |
268 SYSCON_FROCTRL_SEL(0) | SYSCON_FROCTRL_WRTRIM(1) | SYSCON_FROCTRL_USBCLKADJ(usb_adj) |
269 SYSCON_FROCTRL_HSPDCLK(1);
270 }
271 }
272 else
273 {
274 SYSCON->FROCTRL &= ~SYSCON_FROCTRL_HSPDCLK(1);
275 }
276
277 return kStatus_Success;
278 }
279
280 /*! brief Return Frequency of FRO 12MHz
281 * return Frequency of FRO 12MHz
282 */
CLOCK_GetFro12MFreq(void)283 uint32_t CLOCK_GetFro12MFreq(void)
284 {
285 return ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ? 0U : 12000000U;
286 }
287
288 /*! brief Return Frequency of External Clock
289 * return Frequency of External Clock. If no external clock is used returns 0.
290 */
CLOCK_GetExtClkFreq(void)291 uint32_t CLOCK_GetExtClkFreq(void)
292 {
293 return (s_Ext_Clk_Freq);
294 }
295 /*! brief Return Frequency of Watchdog Oscillator
296 * return Frequency of Watchdog Oscillator
297 */
CLOCK_GetWdtOscFreq(void)298 uint32_t CLOCK_GetWdtOscFreq(void)
299 {
300 uint8_t freq_sel, div_sel;
301 if ((SYSCON->PDRUNCFG[(uint32_t)kPDRUNCFG_PD_WDT_OSC >> 8UL] & (1UL << ((uint32_t)kPDRUNCFG_PD_WDT_OSC & 0xffU))) !=
302 0UL)
303 {
304 return 0UL;
305 }
306 else
307 {
308 div_sel = (uint8_t)(((SYSCON->WDTOSCCTRL & 0x1fU) + 1UL) << 1U);
309 freq_sel =
310 wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)];
311 return ((uint32_t)freq_sel * 50000U) / ((uint32_t)div_sel);
312 }
313 }
314
315 /* Get HF FRO Clk */
316 /*! brief Return Frequency of High-Freq output of FRO
317 * return Frequency of High-Freq output of FRO
318 */
CLOCK_GetFroHfFreq(void)319 uint32_t CLOCK_GetFroHfFreq(void)
320 {
321 if (((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ||
322 ((SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK) == 0UL))
323 {
324 return 0U;
325 }
326
327 if ((SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK) != 0UL)
328 {
329 return 96000000U;
330 }
331 else
332 {
333 return 48000000U;
334 }
335 }
336
337 /*! brief Return Frequency of PLL
338 * return Frequency of PLL
339 */
CLOCK_GetPllOutFreq(void)340 uint32_t CLOCK_GetPllOutFreq(void)
341 {
342 return s_Pll_Freq;
343 }
344
345 /*! brief Return Frequency of 32kHz osc
346 * return Frequency of 32kHz osc
347 */
CLOCK_GetOsc32KFreq(void)348 uint32_t CLOCK_GetOsc32KFreq(void)
349 {
350 return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */
351 }
352 /*! brief Return Frequency of Core System
353 * return Frequency of Core System
354 */
CLOCK_GetCoreSysClkFreq(void)355 uint32_t CLOCK_GetCoreSysClkFreq(void)
356 {
357 uint32_t freq = 0U;
358
359 switch (SYSCON->MAINCLKSELB)
360 {
361 case 0U:
362 if (SYSCON->MAINCLKSELA == 0U)
363 {
364 freq = CLOCK_GetFro12MFreq();
365 }
366 else if (SYSCON->MAINCLKSELA == 1U)
367 {
368 freq = CLOCK_GetExtClkFreq();
369 }
370 else if (SYSCON->MAINCLKSELA == 2U)
371 {
372 freq = CLOCK_GetWdtOscFreq();
373 }
374 else if (SYSCON->MAINCLKSELA == 3U)
375 {
376 freq = CLOCK_GetFroHfFreq();
377 }
378 else
379 {
380 /* Add comment to prevent the case of MISRA C-2012 rule 15.7. */
381 }
382 break;
383 case 2U:
384 freq = CLOCK_GetPllOutFreq();
385 break;
386
387 case 3U:
388 freq = CLOCK_GetOsc32KFreq();
389 break;
390
391 default:
392 assert(false);
393 break;
394 }
395
396 return freq;
397 }
398 /*! brief Return Frequency of I2S MCLK Clock
399 * return Frequency of I2S MCLK Clock
400 */
CLOCK_GetI2SMClkFreq(void)401 uint32_t CLOCK_GetI2SMClkFreq(void)
402 {
403 return s_I2S_Mclk_Freq;
404 }
405
406 /*! brief Return Frequency of Asynchronous APB Clock
407 * return Frequency of Asynchronous APB Clock Clock
408 */
CLOCK_GetAsyncApbClkFreq(void)409 uint32_t CLOCK_GetAsyncApbClkFreq(void)
410 {
411 async_clock_src_t clkSrc;
412 uint32_t clkRate;
413
414 clkSrc = CLOCK_GetAsyncApbClkSrc();
415
416 switch (clkSrc)
417 {
418 case kCLOCK_AsyncMainClk:
419 clkRate = CLOCK_GetCoreSysClkFreq();
420 break;
421 case kCLOCK_AsyncFro12Mhz:
422 clkRate = CLK_FRO_12MHZ;
423 break;
424 default:
425 clkRate = 0U;
426 break;
427 }
428
429 return clkRate;
430 }
431
432 /* Get FLEXCOMM Clk */
433 /*! brief Return Frequency of Flexcomm functional Clock
434 * return Frequency of Flexcomm functional Clock
435 */
CLOCK_GetFlexCommClkFreq(uint32_t id)436 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
437 {
438 uint32_t freq = 0U;
439
440 switch (SYSCON->FXCOMCLKSEL[id])
441 {
442 case 0U:
443 freq = CLOCK_GetFro12MFreq();
444 break;
445 case 1U:
446 freq = CLOCK_GetFroHfFreq();
447 break;
448 case 2U:
449 freq = CLOCK_GetPllOutFreq();
450 break;
451 case 3U:
452 freq = CLOCK_GetI2SMClkFreq();
453 break;
454 case 4U:
455 freq = CLOCK_GetFrgClkFreq();
456 break;
457
458 default:
459 assert(false);
460 break;
461 }
462
463 return freq;
464 }
465
466 /* Get ADC Clk */
467 /*! brief Return Frequency of Adc Clock
468 * return Frequency of Adc Clock.
469 */
CLOCK_GetAdcClkFreq(void)470 uint32_t CLOCK_GetAdcClkFreq(void)
471 {
472 uint32_t freq = 0U;
473
474 switch (SYSCON->ADCCLKSEL)
475 {
476 case 0U:
477 freq = CLOCK_GetCoreSysClkFreq();
478 break;
479 case 1U:
480 freq = CLOCK_GetPllOutFreq();
481 break;
482 case 2U:
483 freq = CLOCK_GetFroHfFreq();
484 break;
485 case 7U:
486 freq = 0U;
487 break;
488 default:
489 assert(false);
490 break;
491 }
492
493 return freq / ((SYSCON->ADCCLKDIV & 0xffU) + 1U);
494 }
495
496 /* Get FRG Clk */
497 /*! brief Return Input frequency for the Fractional baud rate generator
498 * return Input Frequency for FRG
499 */
CLOCK_GetFRGInputClock(void)500 uint32_t CLOCK_GetFRGInputClock(void)
501 {
502 uint32_t freq = 0U;
503
504 switch (SYSCON->FRGCLKSEL)
505 {
506 case 0U:
507 freq = CLOCK_GetCoreSysClkFreq();
508 break;
509 case 1U:
510 freq = CLOCK_GetPllOutFreq();
511 break;
512 case 2U:
513 freq = CLOCK_GetFro12MFreq();
514 break;
515 case 3U:
516 freq = CLOCK_GetFroHfFreq();
517 break;
518
519 default:
520 assert(false);
521 break;
522 }
523
524 return freq;
525 }
526
527 /* Get DMIC Clk */
528 /*! brief Return Input frequency for the DMIC
529 * return Input Frequency for DMIC
530 */
CLOCK_GetDmicClkFreq(void)531 uint32_t CLOCK_GetDmicClkFreq(void)
532 {
533 uint32_t freq = 0U;
534
535 switch (SYSCON->DMICCLKSEL)
536 {
537 case 0U:
538 freq = CLOCK_GetFro12MFreq();
539 break;
540 case 1U:
541 freq = CLOCK_GetFroHfFreq();
542 break;
543 case 2U:
544 freq = CLOCK_GetPllOutFreq();
545 break;
546 case 3U:
547 freq = CLOCK_GetI2SMClkFreq();
548 break;
549 case 4U:
550 freq = CLOCK_GetCoreSysClkFreq();
551 break;
552 case 5U:
553 freq = CLOCK_GetWdtOscFreq();
554 break;
555 default:
556 assert(false);
557 break;
558 }
559
560 return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U);
561 }
562
563 /*! brief Set output of the Fractional baud rate generator
564 * param freq : Desired output frequency
565 * return Error Code 0 - fail 1 - success
566 */
CLOCK_SetFRGClock(uint32_t freq)567 uint32_t CLOCK_SetFRGClock(uint32_t freq)
568 {
569 uint32_t input = CLOCK_GetFRGInputClock();
570 uint32_t mul;
571
572 if ((freq > 48000000UL) || (freq > input) || (input / freq >= 2UL))
573 {
574 /* FRG output frequency should be less than equal to 48MHz */
575 return 0;
576 }
577 else
578 {
579 mul = (uint32_t)((((uint64_t)input - freq) * 256UL) / ((uint64_t)freq));
580 SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK;
581 return 1;
582 }
583 }
584
585 /* Get FRG Clk */
586 /*! brief Return Input frequency for the FRG
587 * return Input Frequency for FRG
588 */
CLOCK_GetFrgClkFreq(void)589 uint32_t CLOCK_GetFrgClkFreq(void)
590 {
591 uint32_t freq = 0U;
592
593 if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK)
594 {
595 freq = (uint32_t)(((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /
596 ((SYSCON_FRGCTRL_DIV_MASK + 1U) +
597 ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));
598 }
599 else
600 {
601 freq = 0U;
602 }
603
604 return freq;
605 }
606
607 /*! brief Return Frequency of USB
608 * return Frequency of USB
609 */
CLOCK_GetUsbClkFreq(void)610 uint32_t CLOCK_GetUsbClkFreq(void)
611 {
612 uint32_t freq = 0U;
613
614 if (SYSCON->USBCLKSEL == 0U)
615 {
616 freq = CLOCK_GetFroHfFreq();
617 }
618 else if (SYSCON->USBCLKSEL == 1U)
619 {
620 freq = CLOCK_GetPllOutFreq();
621 }
622 else
623 {
624 /* Add comment to prevent the case of MISRA C-2012 rule 15.7. */
625 }
626
627 return freq / ((SYSCON->USBCLKDIV & 0xffU) + 1U);
628 }
629
630 /*! brief Return Frequency of selected clock
631 * return Frequency of selected clock
632 */
CLOCK_GetFreq(clock_name_t clockName)633 uint32_t CLOCK_GetFreq(clock_name_t clockName)
634 {
635 uint32_t freq;
636 switch (clockName)
637 {
638 case kCLOCK_CoreSysClk:
639 freq = CLOCK_GetCoreSysClkFreq();
640 break;
641 case kCLOCK_BusClk:
642 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
643 break;
644 case kCLOCK_FroHf:
645 freq = CLOCK_GetFroHfFreq();
646 break;
647 case kCLOCK_Fro12M:
648 freq = CLOCK_GetFro12MFreq();
649 break;
650 case kCLOCK_PllOut:
651 freq = CLOCK_GetPllOutFreq();
652 break;
653 case kCLOCK_UsbClk:
654 freq = CLOCK_GetUsbClkFreq();
655 break;
656 case kCLOCK_WdtOsc:
657 freq = CLOCK_GetWdtOscFreq();
658 break;
659 case kCLOCK_Frg:
660 freq = CLOCK_GetFrgClkFreq();
661 break;
662 case kCLOCK_AsyncApbClk:
663 freq = CLOCK_GetAsyncApbClkFreq();
664 break;
665 case kCLOCK_FlexI2S:
666 freq = CLOCK_GetI2SMClkFreq();
667 break;
668 default:
669 freq = 0U;
670 break;
671 }
672
673 return freq;
674 }
675
676 /* Set the FLASH wait states for the passed frequency */
677 /**
678 * brief Set the flash wait states for the input freuqency.
679 * param iFreq : Input frequency
680 * return Nothing
681 */
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)682 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)
683 {
684 if (iFreq <= 12000000U)
685 {
686 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash1Cycle);
687 }
688 else if (iFreq <= 24000000U)
689 {
690 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash2Cycle);
691 }
692 else if (iFreq <= 48000000U)
693 {
694 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash3Cycle);
695 }
696 else if (iFreq <= 72000000U)
697 {
698 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash4Cycle);
699 }
700 else if (iFreq <= 84000000U)
701 {
702 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash5Cycle);
703 }
704 else if (iFreq <= 100000000U)
705 {
706 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash6Cycle);
707 }
708 else
709 {
710 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash7Cycle);
711 }
712 }
713
714 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
pllEncodeN(uint32_t N)715 static uint32_t pllEncodeN(uint32_t N)
716 {
717 uint32_t x, i;
718
719 /* Find NDec */
720 switch (N)
721 {
722 case 0U:
723 x = 0x3FFU;
724 break;
725
726 case 1U:
727 x = 0x302U;
728 break;
729
730 case 2U:
731 x = 0x202U;
732 break;
733
734 default:
735 x = 0x080U;
736 for (i = N; i <= NVALMAX; i++)
737 {
738 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
739 }
740 break;
741 }
742
743 return x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P);
744 }
745
746 /* Find decoded N value for raw NDEC value */
pllDecodeN(uint32_t NDEC)747 static uint32_t pllDecodeN(uint32_t NDEC)
748 {
749 uint32_t n, x, i;
750
751 /* Find NDec */
752 switch (NDEC)
753 {
754 case 0x3FFU:
755 n = 0U;
756 break;
757
758 case 0x302U:
759 n = 1U;
760 break;
761
762 case 0x202U:
763 n = 2U;
764 break;
765
766 default:
767 x = 0x080U;
768 n = 0xFFFFFFFFU;
769 for (i = NVALMAX; i >= 3U; i--)
770 {
771 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
772 if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)
773 {
774 /* Decoded value of NDEC */
775 n = i;
776 break;
777 }
778 }
779 break;
780 }
781
782 return n;
783 }
784
785 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
pllEncodeP(uint32_t P)786 static uint32_t pllEncodeP(uint32_t P)
787 {
788 uint32_t x, i;
789
790 /* Find PDec */
791 switch (P)
792 {
793 case 0U:
794 x = 0x7FU;
795 break;
796
797 case 1U:
798 x = 0x62U;
799 break;
800
801 case 2U:
802 x = 0x42U;
803 break;
804
805 default:
806 x = 0x10U;
807 for (i = P; i <= PVALMAX; i++)
808 {
809 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
810 }
811 break;
812 }
813
814 return x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P);
815 }
816
817 /* Find decoded P value for raw PDEC value */
pllDecodeP(uint32_t PDEC)818 static uint32_t pllDecodeP(uint32_t PDEC)
819 {
820 uint32_t p, x, i;
821
822 /* Find PDec */
823 switch (PDEC)
824 {
825 case 0x7FU:
826 p = 0U;
827 break;
828
829 case 0x62U:
830 p = 1U;
831 break;
832
833 case 0x42U:
834 p = 2U;
835 break;
836
837 default:
838 x = 0x10U;
839 p = 0xFFFFFFFFU;
840 for (i = PVALMAX; i >= 3U; i--)
841 {
842 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
843 if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC)
844 {
845 /* Decoded value of PDEC */
846 p = i;
847 break;
848 }
849 }
850 break;
851 }
852
853 return p;
854 }
855
856 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
pllEncodeM(uint32_t M)857 static uint32_t pllEncodeM(uint32_t M)
858 {
859 uint32_t i, x;
860
861 /* Find MDec */
862 switch (M)
863 {
864 case 0U:
865 x = 0x1FFFFU;
866 break;
867
868 case 1U:
869 x = 0x18003U;
870 break;
871
872 case 2U:
873 x = 0x10003U;
874 break;
875
876 default:
877 x = 0x04000U;
878 for (i = M; i <= MVALMAX; i++)
879 {
880 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
881 }
882 break;
883 }
884
885 return x & (PLL_SSCG0_MDEC_VAL_M >> PLL_SSCG0_MDEC_VAL_P);
886 }
887
888 /* Find decoded M value for raw MDEC value */
pllDecodeM(uint32_t MDEC)889 static uint32_t pllDecodeM(uint32_t MDEC)
890 {
891 uint32_t m, i, x;
892
893 /* Find MDec */
894 switch (MDEC)
895 {
896 case 0x1FFFFU:
897 m = 0U;
898 break;
899
900 case 0x18003U:
901 m = 1U;
902 break;
903
904 case 0x10003U:
905 m = 2U;
906 break;
907
908 default:
909 x = 0x04000U;
910 m = 0xFFFFFFFFU;
911 for (i = MVALMAX; i >= 3U; i--)
912 {
913 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
914 if ((x & (PLL_SSCG0_MDEC_VAL_M >> PLL_SSCG0_MDEC_VAL_P)) == MDEC)
915 {
916 /* Decoded value of MDEC */
917 m = i;
918 break;
919 }
920 }
921 break;
922 }
923
924 return m;
925 }
926
927 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
pllFindSel(uint32_t M,bool bypassFBDIV2,uint32_t * pSelP,uint32_t * pSelI,uint32_t * pSelR)928 static void pllFindSel(uint32_t M, bool bypassFBDIV2, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
929 {
930 /* bandwidth: compute selP from Multiplier */
931 if (M < 60U)
932 {
933 *pSelP = (M >> 1U) + 1U;
934 }
935 else
936 {
937 *pSelP = PVALMAX - 1U;
938 }
939
940 /* bandwidth: compute selI from Multiplier */
941 if (M > 16384U)
942 {
943 *pSelI = 1U;
944 }
945 else if (M > 8192U)
946 {
947 *pSelI = 2U;
948 }
949 else if (M > 2048U)
950 {
951 *pSelI = 4U;
952 }
953 else if (M >= 501U)
954 {
955 *pSelI = 8U;
956 }
957 else if (M >= 60U)
958 {
959 *pSelI = 4U * (1024U / (M + 9U));
960 }
961 else
962 {
963 *pSelI = (M & 0x3CU) + 4U;
964 }
965
966 if (*pSelI > ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT))
967 {
968 *pSelI = ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT);
969 }
970
971 *pSelR = 0U;
972 }
973
974 /* Get predivider (N) from PLL NDEC setting */
findPllPreDiv(uint32_t ctrlReg,uint32_t nDecReg)975 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)
976 {
977 uint32_t preDiv = 1;
978
979 /* Direct input is not used? */
980 if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT)) == 0U)
981 {
982 /* Decode NDEC value to get (N) pre divider */
983 preDiv = pllDecodeN(nDecReg & 0x3FFU);
984 if (preDiv == 0U)
985 {
986 preDiv = 1U;
987 }
988 }
989
990 /* Adjusted by 1, directi is used to bypass */
991 return preDiv;
992 }
993
994 /* Get postdivider (P) from PLL PDEC setting */
findPllPostDiv(uint32_t ctrlReg,uint32_t pDecReg)995 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)
996 {
997 uint32_t postDiv = 1U;
998
999 /* Direct input is not used? */
1000 if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U)
1001 {
1002 /* Decode PDEC value to get (P) post divider */
1003 postDiv = 2U * pllDecodeP(pDecReg & 0x7FU);
1004 if (postDiv == 0U)
1005 {
1006 postDiv = 2U;
1007 }
1008 }
1009
1010 /* Adjusted by 1, directo is used to bypass */
1011 return postDiv;
1012 }
1013
1014 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
findPllMMult(uint32_t ctrlReg,uint32_t mDecReg)1015 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)
1016 {
1017 uint32_t mMult = 1U;
1018
1019 /* Decode MDEC value to get (M) multiplier */
1020 mMult = pllDecodeM(mDecReg & 0x1FFFFU);
1021
1022 /* Extra multiply by 2 needed? */
1023 if ((ctrlReg & (SYSCON_SYSPLLCTRL_BYPASSCCODIV2_MASK)) == 0U)
1024 {
1025 mMult = mMult << 1U;
1026 }
1027
1028 if (mMult == 0U)
1029 {
1030 mMult = 1U;
1031 }
1032
1033 return mMult;
1034 }
1035
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1036 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1037 {
1038 uint32_t tmp;
1039
1040 while (n != 0U)
1041 {
1042 tmp = n;
1043 n = m % n;
1044 m = tmp;
1045 }
1046
1047 return m;
1048 }
1049
1050 /*
1051 * Set PLL output based on desired output rate.
1052 * In this function, the it calculates the PLL setting for output frequency from input clock
1053 * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1054 * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1055 */
CLOCK_GetPllConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useFeedbackDiv2,bool useSS)1056 static pll_error_t CLOCK_GetPllConfigInternal(
1057 uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useFeedbackDiv2, bool useSS)
1058 {
1059 uint32_t nDivOutHz, fccoHz, multFccoDiv;
1060 uint32_t pllPreDivider, pllMultiplier, pllBypassFBDIV2, pllPostDivider;
1061 uint32_t pllDirectInput, pllDirectOutput;
1062 uint32_t pllSelP, pllSelI, pllSelR, bandsel, uplimoff;
1063
1064 /* Baseline parameters (no input or output dividers) */
1065 pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */
1066 pllPostDivider = 0U; /* 0 implies post-divider will be disabled */
1067 pllDirectOutput = 1U;
1068 if (useFeedbackDiv2)
1069 {
1070 /* Using feedback divider for M, so disable bypass */
1071 pllBypassFBDIV2 = 0U;
1072 }
1073 else
1074 {
1075 pllBypassFBDIV2 = 1U;
1076 }
1077 multFccoDiv = (2U - pllBypassFBDIV2);
1078
1079 /* Verify output rate parameter */
1080 if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1081 {
1082 /* Maximum PLL output with post divider=1 cannot go above this frequency */
1083 return kStatus_PLL_OutputTooHigh;
1084 }
1085 if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1086 {
1087 /* Minmum PLL output with maximum post divider cannot go below this frequency */
1088 return kStatus_PLL_OutputTooLow;
1089 }
1090
1091 /* If using SS mode, input clock needs to be between 2MHz and 4MHz */
1092 if (useSS)
1093 {
1094 /* Verify input rate parameter */
1095 if (finHz < PLL_MIN_IN_SSMODE)
1096 {
1097 /* Input clock into the PLL cannot be lower than this */
1098 return kStatus_PLL_InputTooLow;
1099 }
1100 /* PLL input in SS mode must be under 4MHz */
1101 pllPreDivider = finHz / ((PLL_MIN_IN_SSMODE + PLL_MAX_IN_SSMODE) / 2U);
1102 if (pllPreDivider > NVALMAX)
1103 {
1104 return kStatus_PLL_InputTooHigh;
1105 }
1106 }
1107 else
1108 {
1109 /* Verify input rate parameter */
1110 if (finHz < PLL_LOWER_IN_LIMIT)
1111 {
1112 /* Input clock into the PLL cannot be lower than this */
1113 return kStatus_PLL_InputTooLow;
1114 }
1115 }
1116
1117 /* Find the optimal CCO frequency for the output and input that
1118 will keep it inside the PLL CCO range. This may require
1119 tweaking the post-divider for the PLL. */
1120 fccoHz = foutHz;
1121 while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1122 {
1123 /* CCO output is less than minimum CCO range, so the CCO output
1124 needs to be bumped up and the post-divider is used to bring
1125 the PLL output back down. */
1126 pllPostDivider++;
1127 if (pllPostDivider > PVALMAX)
1128 {
1129 return kStatus_PLL_OutsideIntLimit;
1130 }
1131
1132 /* Target CCO goes up, PLL output goes down */
1133 fccoHz = foutHz * (pllPostDivider * 2U);
1134 pllDirectOutput = 0U;
1135 }
1136
1137 /* Determine if a pre-divider is needed to get the best frequency */
1138 if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
1139 {
1140 uint32_t a = FindGreatestCommonDivisor(fccoHz, (multFccoDiv * finHz));
1141
1142 if (a > 20000U)
1143 {
1144 a = (multFccoDiv * finHz) / a;
1145 if ((a != 0U) && (a < PLL_MAX_N_DIV))
1146 {
1147 pllPreDivider = a;
1148 }
1149 }
1150 }
1151
1152 /* Bypass pre-divider hardware if pre-divider is 1 */
1153 if (pllPreDivider > 1U)
1154 {
1155 pllDirectInput = 0U;
1156 }
1157 else
1158 {
1159 pllDirectInput = 1U;
1160 }
1161
1162 /* Determine PLL multipler */
1163 nDivOutHz = (finHz / pllPreDivider);
1164 pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv;
1165
1166 /* Find optimal values for filter */
1167 if (useSS == false)
1168 {
1169 /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1170 if ((nDivOutHz * ((multFccoDiv * pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1171 {
1172 pllMultiplier++;
1173 }
1174
1175 /* Setup filtering */
1176 pllFindSel(pllMultiplier, (bool)pllBypassFBDIV2, &pllSelP, &pllSelI, &pllSelR);
1177 bandsel = 1U;
1178 uplimoff = 0U;
1179
1180 /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1181 pSetup->syspllssctrl[0] =
1182 (PLL_SSCG0_MDEC_VAL_SET(pllEncodeM(pllMultiplier)) | (1UL << SYSCON_SYSPLLSSCTRL0_SEL_EXT_SHIFT));
1183
1184 /* Power down SSC, not used */
1185 pSetup->syspllssctrl[1] = (1UL << SYSCON_SYSPLLSSCTRL1_PD_SHIFT);
1186 }
1187 else
1188 {
1189 uint64_t fc;
1190
1191 /* Filtering will be handled by SSC */
1192 pllSelR = 0U;
1193 pllSelI = 0U;
1194 pllSelP = 0U;
1195 bandsel = 0U;
1196 uplimoff = 1U;
1197
1198 /* The PLL multiplier will get very close and slightly under the
1199 desired target frequency. A small fractional component can be
1200 added to fine tune the frequency upwards to the target. */
1201 fc = (((uint64_t)fccoHz % ((uint64_t)multFccoDiv * nDivOutHz)) << 11U) / ((uint64_t)multFccoDiv * nDivOutHz);
1202
1203 /* MDEC set by SSC */
1204 pSetup->syspllssctrl[0U] = 0U;
1205
1206 /* Set multiplier */
1207 pSetup->syspllssctrl[1] = PLL_SSCG1_MD_INT_SET(pllMultiplier) | PLL_SSCG1_MD_FRACT_SET((uint32_t)fc);
1208 }
1209
1210 /* Get encoded values for N (prediv) and P (postdiv) */
1211 pSetup->syspllndec = PLL_NDEC_VAL_SET(pllEncodeN(pllPreDivider));
1212 pSetup->syspllpdec = PLL_PDEC_VAL_SET(pllEncodeP(pllPostDivider));
1213
1214 /* PLL control */
1215 pSetup->syspllctrl = (pllSelR << SYSCON_SYSPLLCTRL_SELR_SHIFT) | /* Filter coefficient */
1216 (pllSelI << SYSCON_SYSPLLCTRL_SELI_SHIFT) | /* Filter coefficient */
1217 (pllSelP << SYSCON_SYSPLLCTRL_SELP_SHIFT) | /* Filter coefficient */
1218 (0UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT) | /* PLL bypass mode disabled */
1219 (pllBypassFBDIV2 << SYSCON_SYSPLLCTRL_BYPASSCCODIV2_SHIFT) | /* Extra M / 2 divider? */
1220 (uplimoff << SYSCON_SYSPLLCTRL_UPLIMOFF_SHIFT) | /* SS/fractional mode disabled */
1221 (bandsel << SYSCON_SYSPLLCTRL_BANDSEL_SHIFT) | /* Manual bandwidth selection enabled */
1222 (pllDirectInput << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT) | /* Bypass pre-divider? */
1223 (pllDirectOutput << SYSCON_SYSPLLCTRL_DIRECTO_SHIFT); /* Bypass post-divider? */
1224
1225 return kStatus_PLL_Success;
1226 }
1227
1228 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1229 /* Alloct the static buffer for cache. */
1230 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1231 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1232 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1233 static bool s_UseFeedbackDiv2Cache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {false};
1234 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {false};
1235 static uint32_t s_PllSetupCacheIdx = 0U;
1236 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1237
1238 /*
1239 * Calculate the PLL setting values from input clock freq to output freq.
1240 */
CLOCK_GetPllConfig(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useFeedbackDiv2,bool useSS)1241 static pll_error_t CLOCK_GetPllConfig(
1242 uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useFeedbackDiv2, bool useSS)
1243 {
1244 pll_error_t retErr;
1245 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1246 uint32_t i;
1247
1248 for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1249 {
1250 if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) &&
1251 (useFeedbackDiv2 == s_UseFeedbackDiv2Cache[i]) && (useSS == s_UseSSCache[i]))
1252 {
1253 /* Hit the target in cache buffer. */
1254 pSetup->syspllctrl = s_PllSetupCacheStruct[i].syspllctrl;
1255 pSetup->syspllndec = s_PllSetupCacheStruct[i].syspllndec;
1256 pSetup->syspllpdec = s_PllSetupCacheStruct[i].syspllpdec;
1257 pSetup->syspllssctrl[0] = s_PllSetupCacheStruct[i].syspllssctrl[0];
1258 pSetup->syspllssctrl[1] = s_PllSetupCacheStruct[i].syspllssctrl[1];
1259 retErr = kStatus_PLL_Success;
1260 break;
1261 }
1262 }
1263
1264 if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1265 {
1266 return retErr;
1267 }
1268 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1269
1270 retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup, useFeedbackDiv2, useSS);
1271
1272 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1273 /* Cache the most recent calulation result into buffer. */
1274 s_FinHzCache[s_PllSetupCacheIdx] = finHz;
1275 s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1276 s_UseFeedbackDiv2Cache[s_PllSetupCacheIdx] = useFeedbackDiv2;
1277 s_UseSSCache[s_PllSetupCacheIdx] = useSS;
1278
1279 s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllctrl = pSetup->syspllctrl;
1280 s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllndec = pSetup->syspllndec;
1281 s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllpdec = pSetup->syspllpdec;
1282 s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllssctrl[0] = pSetup->syspllssctrl[0];
1283 s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllssctrl[1] = pSetup->syspllssctrl[1];
1284 /* Update the index for next available buffer. */
1285 s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1286 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1287
1288 return retErr;
1289 }
1290
1291 /* Update local PLL rate variable */
CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t * pSetup)1292 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup)
1293 {
1294 s_Pll_Freq = CLOCK_GetSystemPLLOutFromSetup(pSetup);
1295 }
1296
1297 /* Return System PLL input clock rate */
1298 /*! brief Return System PLL input clock rate
1299 * return System PLL input clock rate
1300 */
CLOCK_GetSystemPLLInClockRate(void)1301 uint32_t CLOCK_GetSystemPLLInClockRate(void)
1302 {
1303 uint32_t clkRate = 0U;
1304
1305 switch ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK))
1306 {
1307 case 0x00U:
1308 clkRate = CLK_FRO_12MHZ;
1309 break;
1310
1311 case 0x01U:
1312 clkRate = CLOCK_GetExtClkFreq();
1313 break;
1314
1315 case 0x02U:
1316 clkRate = CLOCK_GetWdtOscFreq();
1317 break;
1318
1319 case 0x03U:
1320 clkRate = CLOCK_GetOsc32KFreq();
1321 break;
1322
1323 default:
1324 clkRate = 0U;
1325 break;
1326 }
1327
1328 return clkRate;
1329 }
1330
1331 /* Return System PLL output clock rate from setup structure */
1332 /*! brief Return System PLL output clock rate from setup structure
1333 * param pSetup : Pointer to a PLL setup structure
1334 * return System PLL output clock rate calculated from the setup structure
1335 */
CLOCK_GetSystemPLLOutFromSetup(pll_setup_t * pSetup)1336 uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup)
1337 {
1338 uint32_t prediv, postdiv, mMult, inPllRate;
1339 uint64_t workRate;
1340
1341 /* Get the input clock frequency of PLL. */
1342 inPllRate = CLOCK_GetSystemPLLInClockRate();
1343
1344 /*
1345 * If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock.
1346 */
1347 if ((pSetup->syspllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U)
1348 {
1349 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1350 /*
1351 * 1. Pre-divider
1352 * Pre-divider is only available when the DIRECTI is disabled.
1353 */
1354 if (0U == (pSetup->syspllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK))
1355 {
1356 prediv = findPllPreDiv(pSetup->syspllctrl, pSetup->syspllndec);
1357 }
1358 else
1359 {
1360 prediv = 1U; /* The pre-divider is bypassed. */
1361 }
1362 /* Adjust input clock */
1363 inPllRate = inPllRate / prediv;
1364
1365 /*
1366 * 2. M divider
1367 * If using the SS, use the multiplier.
1368 */
1369 if ((pSetup->syspllssctrl[1] & (SYSCON_SYSPLLSSCTRL1_PD_MASK)) != 0UL)
1370 {
1371 /* MDEC used for rate */
1372 mMult = findPllMMult(pSetup->syspllctrl, pSetup->syspllssctrl[0]);
1373 workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1374 }
1375 else
1376 {
1377 uint64_t fract;
1378
1379 /* SS multipler used for rate */
1380 mMult = (pSetup->syspllssctrl[1] & PLL_SSCG1_MD_INT_M) >> PLL_SSCG1_MD_INT_P;
1381 workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1382
1383 /* Adjust by fractional */
1384 fract = ((uint64_t)(pSetup->syspllssctrl[1]) & PLL_SSCG1_MD_FRACT_M) >> PLL_SSCG1_MD_FRACT_P;
1385 workRate = workRate + ((inPllRate * fract) / 0x800U);
1386 }
1387
1388 /*
1389 * 3. Post-divider
1390 * Post-divider is only available when the DIRECTO is disabled.
1391 */
1392 if (0U == (pSetup->syspllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK))
1393 {
1394 postdiv = findPllPostDiv(pSetup->syspllctrl, pSetup->syspllpdec);
1395 }
1396 else
1397 {
1398 postdiv = 1U; /* The post-divider is bypassed. */
1399 }
1400 workRate = workRate / ((uint64_t)postdiv);
1401 }
1402 else
1403 {
1404 /* In bypass mode */
1405 workRate = (uint64_t)inPllRate;
1406 }
1407
1408 return (uint32_t)workRate;
1409 }
1410
1411 /* Set the current PLL Rate */
1412 /*! brief Store the current PLL rate
1413 * param rate: Current rate of the PLL
1414 * return Nothing
1415 **/
CLOCK_SetStoredPLLClockRate(uint32_t rate)1416 void CLOCK_SetStoredPLLClockRate(uint32_t rate)
1417 {
1418 s_Pll_Freq = rate;
1419 }
1420
1421 /* Return System PLL output clock rate */
1422 /*! brief Return System PLL output clock rate
1423 * param recompute : Forces a PLL rate recomputation if true
1424 * return System PLL output clock rate
1425 * note The PLL rate is cached in the driver in a variable as
1426 * the rate computation function can take some time to perform. It
1427 * is recommended to use 'false' with the 'recompute' parameter.
1428 */
CLOCK_GetSystemPLLOutClockRate(bool recompute)1429 uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute)
1430 {
1431 pll_setup_t Setup;
1432 uint32_t rate;
1433
1434 if ((recompute) || (s_Pll_Freq == 0U))
1435 {
1436 Setup.syspllctrl = SYSCON->SYSPLLCTRL;
1437 Setup.syspllndec = SYSCON->SYSPLLNDEC;
1438 Setup.syspllpdec = SYSCON->SYSPLLPDEC;
1439 Setup.syspllssctrl[0] = SYSCON->SYSPLLSSCTRL0;
1440 Setup.syspllssctrl[1] = SYSCON->SYSPLLSSCTRL1;
1441
1442 CLOCK_GetSystemPLLOutFromSetupUpdate(&Setup);
1443 }
1444
1445 rate = s_Pll_Freq;
1446
1447 return rate;
1448 }
1449
1450 /* Set PLL output based on the passed PLL setup data */
1451 /*! brief Set PLL output based on the passed PLL setup data
1452 * param pControl : Pointer to populated PLL control structure to generate setup with
1453 * param pSetup : Pointer to PLL setup structure to be filled
1454 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
1455 * note Actual frequency for setup may vary from the desired frequency based on the
1456 * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1457 */
CLOCK_SetupPLLData(pll_config_t * pControl,pll_setup_t * pSetup)1458 pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
1459 {
1460 uint32_t inRate;
1461 bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0U);
1462 bool useFbDiv2;
1463
1464 pll_error_t pllError;
1465
1466 /* Determine input rate for the PLL */
1467 if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0UL)
1468 {
1469 inRate = pControl->inputRate;
1470 }
1471 else
1472 {
1473 inRate = CLOCK_GetSystemPLLInClockRate();
1474 }
1475
1476 if ((pSetup->flags & PLL_SETUPFLAG_USEFEEDBACKDIV2) != 0UL)
1477 {
1478 useFbDiv2 = true;
1479 }
1480 else
1481 {
1482 useFbDiv2 = false;
1483 }
1484
1485 /* PLL flag options */
1486 pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup, useFbDiv2, useSS);
1487 if ((useSS) && (pllError == kStatus_PLL_Success))
1488 {
1489 /* If using SS mode, then some tweaks are made to the generated setup */
1490 pSetup->syspllssctrl[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
1491 if (pControl->mfDither)
1492 {
1493 pSetup->syspllssctrl[1] |= (1UL << SYSCON_SYSPLLSSCTRL1_DITHER_SHIFT);
1494 }
1495 }
1496
1497 return pllError;
1498 }
1499
1500 /* Set PLL output from PLL setup structure */
1501 /*! brief Set PLL output from PLL setup structure (precise frequency)
1502 * param pSetup : Pointer to populated PLL setup structure
1503 * param flagcfg : Flag configuration for PLL config structure
1504 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
1505 * note This function will power off the PLL, setup the PLL with the
1506 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1507 * and adjust system voltages to the new PLL rate. The function will not
1508 * alter any source clocks (ie, main systen clock) that may use the PLL,
1509 * so these should be setup prior to and after exiting the function.
1510 */
CLOCK_SetupSystemPLLPrec(pll_setup_t * pSetup,uint32_t flagcfg)1511 pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)
1512 {
1513 /* Power off PLL during setup changes */
1514 POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);
1515
1516 pSetup->flags = flagcfg;
1517
1518 /* Write PLL setup data */
1519 SYSCON->SYSPLLCTRL = pSetup->syspllctrl;
1520 SYSCON->SYSPLLNDEC = pSetup->syspllndec;
1521 SYSCON->SYSPLLNDEC = pSetup->syspllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
1522 SYSCON->SYSPLLPDEC = pSetup->syspllpdec;
1523 SYSCON->SYSPLLPDEC = pSetup->syspllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
1524 SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0];
1525 SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0] | (1UL << SYSCON_SYSPLLSSCTRL0_MREQ_SHIFT); /* latch */
1526 SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1];
1527 SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1] | (1UL << SYSCON_SYSPLLSSCTRL1_MDREQ_SHIFT); /* latch */
1528
1529 /* Flags for lock or power on */
1530 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0UL)
1531 {
1532 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
1533 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
1534 uint32_t curSSCTRL = SYSCON->SYSPLLSSCTRL0 & ~(1UL << 17U);
1535
1536 /* Initialize and power up PLL */
1537 SYSCON->SYSPLLSSCTRL0 = maxCCO;
1538 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
1539
1540 /* Set mreq to activate */
1541 SYSCON->SYSPLLSSCTRL0 = maxCCO | (1UL << 17U);
1542
1543 /* Delay for 72 uSec @ 12Mhz */
1544 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1545
1546 /* clear mreq to prepare for restoring mreq */
1547 SYSCON->SYSPLLSSCTRL0 = curSSCTRL;
1548
1549 /* set original value back and activate */
1550 SYSCON->SYSPLLSSCTRL0 = curSSCTRL | (1UL << 17U);
1551
1552 /* Enable peripheral states by setting low */
1553 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
1554 }
1555 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1556 {
1557 while (CLOCK_IsSystemPLLLocked() == false)
1558 {
1559 }
1560 }
1561
1562 /* Update current programmed PLL rate var */
1563 CLOCK_GetSystemPLLOutFromSetupUpdate(pSetup);
1564
1565 /* System voltage adjustment, occurs prior to setting main system clock */
1566 if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0UL)
1567 {
1568 POWER_SetVoltageForFreq(s_Pll_Freq);
1569 }
1570
1571 return kStatus_PLL_Success;
1572 }
1573
1574 /* Setup PLL Frequency from pre-calculated value */
1575 /**
1576 * brief Set PLL output from PLL setup structure (precise frequency)
1577 * param pSetup : Pointer to populated PLL setup structure
1578 * return kStatus_PLL_Success on success, or PLL setup error code
1579 * note This function will power off the PLL, setup the PLL with the
1580 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1581 * and adjust system voltages to the new PLL rate. The function will not
1582 * alter any source clocks (ie, main systen clock) that may use the PLL,
1583 * so these should be setup prior to and after exiting the function.
1584 */
CLOCK_SetPLLFreq(const pll_setup_t * pSetup)1585 pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup)
1586 {
1587 /* Power off PLL during setup changes */
1588 POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);
1589
1590 /* Write PLL setup data */
1591 SYSCON->SYSPLLCTRL = pSetup->syspllctrl;
1592 SYSCON->SYSPLLNDEC = pSetup->syspllndec;
1593 SYSCON->SYSPLLNDEC = pSetup->syspllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
1594 SYSCON->SYSPLLPDEC = pSetup->syspllpdec;
1595 SYSCON->SYSPLLPDEC = pSetup->syspllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
1596 SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0];
1597 SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0] | (1UL << SYSCON_SYSPLLSSCTRL0_MREQ_SHIFT); /* latch */
1598 SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1];
1599 SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1] | (1UL << SYSCON_SYSPLLSSCTRL1_MDREQ_SHIFT); /* latch */
1600
1601 /* Flags for lock or power on */
1602 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0UL)
1603 {
1604 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
1605 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
1606 uint32_t curSSCTRL = SYSCON->SYSPLLSSCTRL0 & ~(1UL << 17U);
1607
1608 /* Initialize and power up PLL */
1609 SYSCON->SYSPLLSSCTRL0 = maxCCO;
1610 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
1611
1612 /* Set mreq to activate */
1613 SYSCON->SYSPLLSSCTRL0 = maxCCO | (1UL << 17U);
1614
1615 /* Delay for 72 uSec @ 12Mhz */
1616 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1617
1618 /* clear mreq to prepare for restoring mreq */
1619 SYSCON->SYSPLLSSCTRL0 = curSSCTRL;
1620
1621 /* set original value back and activate */
1622 SYSCON->SYSPLLSSCTRL0 = curSSCTRL | (1UL << 17U);
1623
1624 /* Enable peripheral states by setting low */
1625 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
1626 }
1627 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1628 {
1629 while (CLOCK_IsSystemPLLLocked() == false)
1630 {
1631 }
1632 }
1633
1634 /* Update current programmed PLL rate var */
1635 s_Pll_Freq = pSetup->pllRate;
1636
1637 return kStatus_PLL_Success;
1638 }
1639
1640 /* Set System PLL clock based on the input frequency and multiplier */
1641 /*! brief Set PLL output based on the multiplier and input frequency
1642 * param multiply_by : multiplier
1643 * param input_freq : Clock input frequency of the PLL
1644 * return Nothing
1645 * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
1646 * function does not disable or enable PLL power, wait for PLL lock,
1647 * or adjust system voltages. These must be done in the application.
1648 * The function will not alter any source clocks (ie, main systen clock)
1649 * that may use the PLL, so these should be setup prior to and after
1650 * exiting the function.
1651 */
CLOCK_SetupSystemPLLMult(uint32_t multiply_by,uint32_t input_freq)1652 void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq)
1653 {
1654 uint32_t cco_freq = input_freq * multiply_by;
1655 uint32_t pdec = 1U;
1656 uint32_t selr;
1657 uint32_t seli;
1658 uint32_t selp;
1659 uint32_t mdec, ndec;
1660
1661 uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO(1);
1662
1663 while (cco_freq < 75000000U)
1664 {
1665 multiply_by <<= 1U; /* double value in each iteration */
1666 pdec <<= 1U; /* correspondingly double pdec to cancel effect of double msel */
1667 cco_freq = input_freq * multiply_by;
1668 }
1669 selr = 0U;
1670 if (multiply_by < 60U)
1671 {
1672 seli = (multiply_by & 0x3cU) + 4U;
1673 selp = (multiply_by >> 1U) + 1U;
1674 }
1675 else
1676 {
1677 selp = 31U;
1678 if (multiply_by > 16384U)
1679 {
1680 seli = 1U;
1681 }
1682 else if (multiply_by > 8192U)
1683 {
1684 seli = 2U;
1685 }
1686 else if (multiply_by > 2048U)
1687 {
1688 seli = 4U;
1689 }
1690 else if (multiply_by >= 501U)
1691 {
1692 seli = 8U;
1693 }
1694 else
1695 {
1696 seli = 4U * (1024U / (multiply_by + 9U));
1697 }
1698 }
1699
1700 if (pdec > 1U)
1701 {
1702 directo = 0U; /* use post divider */
1703 pdec = pdec / 2U; /* Account for minus 1 encoding */
1704 /* Translate P value */
1705 switch (pdec)
1706 {
1707 case 1U:
1708 pdec = 0x62U; /* 1 * 2 */
1709 break;
1710 case 2U:
1711 pdec = 0x42U; /* 2 * 2 */
1712 break;
1713 case 4U:
1714 pdec = 0x02U; /* 4 * 2 */
1715 break;
1716 case 8U:
1717 pdec = 0x0bU; /* 8 * 2 */
1718 break;
1719 case 16U:
1720 pdec = 0x11U; /* 16 * 2 */
1721 break;
1722 case 32U:
1723 pdec = 0x08U; /* 32 * 2 */
1724 break;
1725 default:
1726 pdec = 0x08U;
1727 break;
1728 }
1729 }
1730
1731 mdec = PLL_SSCG0_MDEC_VAL_SET(pllEncodeM(multiply_by));
1732 ndec = 0x302U; /* pre divide by 1 (hardcoded) */
1733
1734 SYSCON->SYSPLLCTRL = SYSCON_SYSPLLCTRL_BANDSEL(1) | directo | SYSCON_SYSPLLCTRL_BYPASSCCODIV2(1) |
1735 (selr << SYSCON_SYSPLLCTRL_SELR_SHIFT) | (seli << SYSCON_SYSPLLCTRL_SELI_SHIFT) |
1736 (selp << SYSCON_SYSPLLCTRL_SELP_SHIFT);
1737 SYSCON->SYSPLLPDEC = pdec | (1UL << 7U); /* set Pdec value and assert preq */
1738 SYSCON->SYSPLLNDEC = ndec | (1UL << 10U); /* set Pdec value and assert preq */
1739 SYSCON->SYSPLLSSCTRL0 =
1740 (1UL << 18U) | (1UL << 17U) | mdec; /* select non sscg MDEC value, assert mreq and select mdec value */
1741 }
CLOCK_EnableUsbfs0Clock(clock_usb_src_t src,uint32_t freq)1742 bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq)
1743 {
1744 bool ret = true;
1745
1746 CLOCK_DisableClock(kCLOCK_Usbd0);
1747
1748 if (kCLOCK_UsbSrcFro == src)
1749 {
1750 switch (freq)
1751 {
1752 case 96000000U:
1753 CLOCK_SetClkDiv(kCLOCK_DivUsbClk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
1754 break;
1755 case 48000000U:
1756 CLOCK_SetClkDiv(kCLOCK_DivUsbClk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
1757 break;
1758 default:
1759 ret = false;
1760 break;
1761 }
1762 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
1763 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
1764 SYSCON_FROCTRL_USBCLKADJ_MASK;
1765 /* select FRO 96 or 48 MHz */
1766 CLOCK_AttachClk(kFRO_HF_to_USB_CLK);
1767 }
1768 else
1769 {
1770 /*TODO , we only implement FRO as usb clock source*/
1771 ret = false;
1772 }
1773
1774 CLOCK_EnableClock(kCLOCK_Usbd0);
1775
1776 return ret;
1777 }
1778