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 USB_NVALMAX (0x4U)
24 #define USB_PVALMAX (0x8U)
25 #define USB_MVALMAX (0x100U)
26
27 #define PLL_MAX_N_DIV 0x100U
28 #define USB_PLL_MAX_N_DIV 0x100U
29
30 #define PLL_MDEC_VAL_P (0U) /*!< MDEC is in bits 16 downto 0 */
31 #define PLL_MDEC_VAL_M (0x1FFFFUL << PLL_MDEC_VAL_P) /*!< NDEC is in bits 9 downto 0 */
32 #define PLL_NDEC_VAL_P (0U) /*!< NDEC is in bits 9:0 */
33 #define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P)
34 #define PLL_PDEC_VAL_P (0U) /*!< PDEC is in bits 6:0 */
35 #define PLL_PDEC_VAL_M (0x7FUL << PLL_PDEC_VAL_P)
36
37 #define PLL_MIN_CCO_FREQ_MHZ (275000000U)
38 #define PLL_MAX_CCO_FREQ_MHZ (550000000U)
39 #define PLL_LOWER_IN_LIMIT (4000U) /*!< Minimum PLL input rate */
40 #define PLL_MIN_IN_SSMODE (2000000U)
41 #define PLL_MAX_IN_SSMODE (4000000U)
42
43 /*!< Middle of the range values for spread-spectrum */
44 #define PLL_SSCG_MF_FREQ_VALUE 4U
45 #define PLL_SSCG_MC_COMP_VALUE 2U
46 #define PLL_SSCG_MR_DEPTH_VALUE 4U
47 #define PLL_SSCG_DITHER_VALUE 0U
48
49 /*!< USB PLL CCO MAX AND MIN FREQ */
50 #define USB_PLL_MIN_CCO_FREQ_MHZ (156000000U)
51 #define USB_PLL_MAX_CCO_FREQ_MHZ (320000000U)
52 #define USB_PLL_LOWER_IN_LIMIT (1000000U) /*!< Minimum PLL input rate */
53
54 #define USB_PLL_MSEL_VAL_P (0U) /*!< MSEL is in bits 7 downto 0 */
55 #define USB_PLL_MSEL_VAL_M (0xFFU)
56 #define USB_PLL_PSEL_VAL_P (8U) /*!< PDEC is in bits 9:8 */
57 #define USB_PLL_PSEL_VAL_M (0x3U)
58 #define USB_PLL_NSEL_VAL_P (10U) /*!< NDEC is in bits 11:10 */
59 #define USB_PLL_NSEL_VAL_M (0x3U)
60
61 /*!< SYS PLL NDEC reg */
62 #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
63 /*!< SYS PLL PDEC reg */
64 #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
65 /*!< SYS PLL MDEC reg */
66 #define PLL_MDEC_VAL_SET(value) (((unsigned long)(value) << PLL_MDEC_VAL_P) & PLL_MDEC_VAL_M)
67
68 /*!< SYS PLL NSEL reg */
69 #define USB_PLL_NSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_NSEL_VAL_M) << USB_PLL_NSEL_VAL_P)
70 /*!< SYS PLL PSEL reg */
71 #define USB_PLL_PSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_PSEL_VAL_M) << USB_PLL_PSEL_VAL_P)
72 /*!< SYS PLL MSEL reg */
73 #define USB_PLL_MSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_MSEL_VAL_M) << USB_PLL_MSEL_VAL_P)
74
75 /*!< FRAC control */
76 #define AUDIO_PLL_FRACT_MD_P (0U)
77 #define AUDIO_PLL_FRACT_MD_INT_P (15U)
78 #define AUDIO_PLL_FRACT_MD_M (0x7FFFUL << AUDIO_PLL_FRACT_MD_P)
79 #define AUDIO_PLL_FRACT_MD_INT_M (0x7FUL << AUDIO_PLL_FRACT_MD_INT_P)
80
81 #define AUDIO_PLL_MD_FRACT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_P) & PLL_FRAC_MD_FRACT_M)
82 #define AUDIO_PLL_MD_INT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_INT_P) & AUDIO_PLL_FRACT_MD_INT_M)
83
84 /* Saved value of PLL output rate, computed whenever needed to save run-time
85 computation on each call to retrive the PLL rate. */
86 static uint32_t s_Pll_Freq;
87 static uint32_t s_Usb_Pll_Freq;
88 static uint32_t s_Audio_Pll_Freq;
89
90 /** External clock rate on the CLKIN pin in Hz. If not used,
91 set this to 0. Otherwise, set it to the exact rate in Hz this pin is
92 being driven at. */
93 static const uint32_t s_I2S_Mclk_Freq = 0U;
94 static const uint32_t s_Ext_Clk_Freq = 12000000U;
95 static const uint32_t s_Lcd_Clk_In_Freq = 0U;
96
97 /*******************************************************************************
98 * Variables
99 ******************************************************************************/
100
101 /*******************************************************************************
102 * Prototypes
103 ******************************************************************************/
104 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
105 static uint32_t pllEncodeN(uint32_t N);
106 /* Find decoded N value for raw NDEC value */
107 static uint32_t pllDecodeN(uint32_t NDEC);
108 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
109 static uint32_t pllEncodeP(uint32_t P);
110 /* Find decoded P value for raw PDEC value */
111 static uint32_t pllDecodeP(uint32_t PDEC);
112 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
113 static uint32_t pllEncodeM(uint32_t M);
114 /* Find decoded M value for raw MDEC value */
115 static uint32_t pllDecodeM(uint32_t MDEC);
116 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
117 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
118 /* Get predivider (N) from PLL NDEC setting */
119 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg);
120 /* Get postdivider (P) from PLL PDEC setting */
121 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg);
122 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
123 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg);
124 /* Convert the binary to fractional part */
125 static double Binary2Fractional(uint32_t binaryPart);
126 /* Get the greatest common divisor */
127 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
128 /* Set PLL output based on desired output rate */
129 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup);
130
131 /* Update local PLL rate variable */
132 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup);
133 static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup);
134
135 static const uint8_t wdtFreqLookup[32] = {0, 8, 12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41,
136 42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61};
137 /*******************************************************************************
138 * Code
139 ******************************************************************************/
140
141 /* Clock Selection for IP */
142 /**
143 * brief Configure the clock selection muxes.
144 * param connection : Clock to be configured.
145 * return Nothing
146 */
CLOCK_AttachClk(clock_attach_id_t connection)147 void CLOCK_AttachClk(clock_attach_id_t connection)
148 {
149 uint8_t mux;
150 uint8_t sel;
151 uint16_t item;
152 uint32_t tmp32 = (uint32_t)connection;
153 uint32_t i;
154 volatile uint32_t *pClkSel;
155
156 pClkSel = &(SYSCON->MAINCLKSELA);
157
158 if (kNONE_to_NONE != connection)
159 {
160 for (i = 0U; i < 2U; i++)
161 {
162 if (tmp32 == 0U)
163 {
164 break;
165 }
166 item = (uint16_t)GET_ID_ITEM(tmp32);
167 if (0U != item)
168 {
169 mux = GET_ID_ITEM_MUX(item);
170 sel = GET_ID_ITEM_SEL(item);
171 if (mux == CM_ASYNCAPB)
172 {
173 SYSCON->ASYNCAPBCTRL = SYSCON_ASYNCAPBCTRL_ENABLE(1);
174 ASYNC_SYSCON->ASYNCAPBCLKSELA = sel;
175 }
176 else
177 {
178 ((volatile uint32_t *)pClkSel)[mux] = sel;
179 }
180 }
181 tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */
182 }
183 }
184 }
185
186 /* Return the actual clock attach id */
187 /**
188 * brief Get the actual clock attach id.
189 * This fuction uses the offset in input attach id, then it reads the actual source value in
190 * the register and combine the offset to obtain an actual attach id.
191 * param attachId : Clock attach id to get.
192 * return Clock source value.
193 */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)194 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
195 {
196 uint8_t mux;
197 uint32_t actualSel;
198 uint32_t tmp32 = (uint32_t)attachId;
199 uint32_t i;
200 uint32_t actualAttachId = 0U;
201 uint32_t selector = GET_ID_SELECTOR(tmp32);
202 volatile uint32_t *pClkSel;
203
204 pClkSel = &(SYSCON->MAINCLKSELA);
205
206 if (kNONE_to_NONE == attachId)
207 {
208 return kNONE_to_NONE;
209 }
210
211 for (i = 0U; i < 2U; i++)
212 {
213 mux = GET_ID_ITEM_MUX(tmp32);
214 if (0U != tmp32)
215 {
216 if (mux == CM_ASYNCAPB)
217 {
218 actualSel = ASYNC_SYSCON->ASYNCAPBCLKSELA;
219 }
220 else
221 {
222 actualSel = ((volatile uint32_t *)pClkSel)[mux];
223 }
224
225 /* Consider the combination of two registers */
226 actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
227 }
228 tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */
229 }
230
231 actualAttachId |= selector;
232
233 return (clock_attach_id_t)actualAttachId;
234 }
235
236 /* Set IP Clock Divider */
237 /**
238 * brief Setup peripheral clock dividers.
239 * param div_name : Clock divider name
240 * param divided_by_value: Value to be divided
241 * param reset : Whether to reset the divider counter.
242 * return Nothing
243 */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)244 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
245 {
246 volatile uint32_t *pClkDiv;
247
248 pClkDiv = &(SYSCON->SYSTICKCLKDIV);
249 if (reset)
250 {
251 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 29U;
252 }
253 if (divided_by_value == 0U) /*!< halt */
254 {
255 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 30U;
256 }
257 else
258 {
259 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = (divided_by_value - 1U);
260 }
261 }
262
263 /* Set FRO Clocking */
264 /**
265 * brief Initialize the Core clock to given frequency (12, 48 or 96 MHz).
266 * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
267 * enabled.
268 * param iFreq : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
269 * return returns success or fail status.
270 */
CLOCK_SetupFROClocking(uint32_t iFreq)271 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
272 {
273 uint32_t usb_adj;
274 if ((iFreq != 12000000U) && (iFreq != 48000000U) && (iFreq != 96000000U))
275 {
276 return kStatus_Fail;
277 }
278 /* Power up the FRO and set this as the base clock */
279 POWER_DisablePD(kPDRUNCFG_PD_FRO_EN);
280 /* back up the value of whether USB adj is selected, in which case we will have a value of 1 else 0 */
281 usb_adj = ((SYSCON->FROCTRL) & SYSCON_FROCTRL_USBCLKADJ_MASK) >> SYSCON_FROCTRL_USBCLKADJ_SHIFT;
282
283 if (iFreq > 12000000U)
284 {
285 /* Call ROM API to set FRO */
286 set_fro_frequency(iFreq);
287 if (iFreq == 96000000U)
288 {
289 SYSCON->FROCTRL |= (SYSCON_FROCTRL_SEL(1) | SYSCON_FROCTRL_WRTRIM(1) | SYSCON_FROCTRL_USBCLKADJ(usb_adj) |
290 SYSCON_FROCTRL_HSPDCLK(1));
291 }
292 else
293 {
294 SYSCON->FROCTRL |= (SYSCON_FROCTRL_SEL(0) | SYSCON_FROCTRL_WRTRIM(1) | SYSCON_FROCTRL_USBCLKADJ(usb_adj) |
295 SYSCON_FROCTRL_HSPDCLK(1));
296 }
297 }
298 else
299 {
300 SYSCON->FROCTRL &= ~SYSCON_FROCTRL_HSPDCLK(1);
301 }
302
303 return kStatus_Success;
304 }
305
306 /* Get CLOCK OUT Clk */
307 /*! brief Return Frequency of ClockOut
308 * return Frequency of ClockOut
309 */
CLOCK_GetClockOutClkFreq(void)310 uint32_t CLOCK_GetClockOutClkFreq(void)
311 {
312 uint32_t freq = 0U;
313
314 switch (SYSCON->CLKOUTSELA)
315 {
316 case 0U:
317 freq = CLOCK_GetCoreSysClkFreq();
318 break;
319
320 case 1U:
321 freq = CLOCK_GetExtClkFreq();
322 break;
323
324 case 2U:
325 freq = CLOCK_GetWdtOscFreq();
326 break;
327
328 case 3U:
329 freq = CLOCK_GetFroHfFreq();
330 break;
331
332 case 4U:
333 freq = CLOCK_GetPllOutFreq();
334 break;
335
336 case 5U:
337 freq = CLOCK_GetUsbPllOutFreq();
338 break;
339
340 case 6U:
341 freq = CLOCK_GetAudioPllOutFreq();
342 break;
343
344 case 7U:
345 freq = CLOCK_GetOsc32KFreq();
346 break;
347
348 default:
349 freq = 0U;
350 break;
351 }
352 return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
353 }
354
355 /* Get SPIFI Clk */
356 /*! brief Return Frequency of Spifi Clock
357 * return Frequency of Spifi.
358 */
CLOCK_GetSpifiClkFreq(void)359 uint32_t CLOCK_GetSpifiClkFreq(void)
360 {
361 uint32_t freq = 0U;
362
363 switch (SYSCON->SPIFICLKSEL)
364 {
365 case 0U:
366 freq = CLOCK_GetCoreSysClkFreq();
367 break;
368 case 1U:
369 freq = CLOCK_GetPllOutFreq();
370 break;
371 case 2U:
372 freq = CLOCK_GetUsbPllOutFreq();
373 break;
374 case 3U:
375 freq = CLOCK_GetFroHfFreq();
376 break;
377 case 4U:
378 freq = CLOCK_GetAudioPllOutFreq();
379 break;
380 case 7U:
381 freq = 0U;
382 break;
383 default:
384 freq = 0U;
385 break;
386 }
387
388 return freq / ((SYSCON->SPIFICLKDIV & 0xffU) + 1U);
389 }
390
391 /* Get ADC Clk */
392 /*! brief Return Frequency of Adc Clock
393 * return Frequency of Adc Clock.
394 */
CLOCK_GetAdcClkFreq(void)395 uint32_t CLOCK_GetAdcClkFreq(void)
396 {
397 uint32_t freq = 0U;
398
399 switch (SYSCON->ADCCLKSEL)
400 {
401 case 0U:
402 freq = CLOCK_GetFroHfFreq();
403 break;
404 case 1U:
405 freq = CLOCK_GetPllOutFreq();
406 break;
407 case 2U:
408 freq = CLOCK_GetUsbPllOutFreq();
409 break;
410 case 3U:
411 freq = CLOCK_GetAudioPllOutFreq();
412 break;
413 case 7U:
414 freq = 0U;
415 break;
416 default:
417 freq = 0U;
418 break;
419 }
420
421 return freq / ((SYSCON->ADCCLKDIV & 0xffU) + 1U);
422 }
423
424 /* Get USB0 Clk */
425 /*! brief Return Frequency of Usb0 Clock
426 * return Frequency of Usb0 Clock.
427 */
CLOCK_GetUsb0ClkFreq(void)428 uint32_t CLOCK_GetUsb0ClkFreq(void)
429 {
430 uint32_t freq = 0U;
431
432 switch (SYSCON->USB0CLKSEL)
433 {
434 case 0U:
435 freq = CLOCK_GetFroHfFreq();
436 break;
437 case 1U:
438 freq = CLOCK_GetPllOutFreq();
439 break;
440 case 2U:
441 freq = CLOCK_GetUsbPllOutFreq();
442 break;
443 case 7U:
444 freq = 0U;
445 break;
446
447 default:
448 freq = 0U;
449 break;
450 }
451
452 return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
453 }
454
455 /* Get USB1 Clk */
456 /*! brief Return Frequency of Usb1 Clock
457 * return Frequency of Usb1 Clock.
458 */
CLOCK_GetUsb1ClkFreq(void)459 uint32_t CLOCK_GetUsb1ClkFreq(void)
460 {
461 uint32_t freq = 0U;
462
463 switch (SYSCON->USB1CLKSEL)
464 {
465 case 0U:
466 freq = CLOCK_GetCoreSysClkFreq();
467 break;
468 case 1U:
469 freq = CLOCK_GetPllOutFreq();
470 break;
471 case 2U:
472 freq = CLOCK_GetUsbPllOutFreq();
473 break;
474 case 7U:
475 freq = 0U;
476 break;
477
478 default:
479 freq = 0U;
480 break;
481 }
482
483 return freq / ((SYSCON->USB1CLKDIV & 0xffU) + 1U);
484 }
485
486 /* Get MCLK Clk */
487 /*! brief Return Frequency of MClk Clock
488 * return Frequency of MClk Clock.
489 */
CLOCK_GetMclkClkFreq(void)490 uint32_t CLOCK_GetMclkClkFreq(void)
491 {
492 uint32_t freq = 0U;
493
494 switch (SYSCON->MCLKCLKSEL)
495 {
496 case 0U:
497 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFCLKDIV & 0xffu) + 1U);
498 break;
499 case 1U:
500 freq = CLOCK_GetAudioPllOutFreq();
501 break;
502 case 7U:
503 freq = 0U;
504 break;
505
506 default:
507 freq = 0U;
508 break;
509 }
510
511 return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
512 }
513
514 /* Get SCTIMER Clk */
515 /*! brief Return Frequency of SCTimer Clock
516 * return Frequency of SCTimer Clock.
517 */
CLOCK_GetSctClkFreq(void)518 uint32_t CLOCK_GetSctClkFreq(void)
519 {
520 uint32_t freq = 0U;
521
522 switch (SYSCON->SCTCLKSEL)
523 {
524 case 0U:
525 freq = CLOCK_GetCoreSysClkFreq();
526 break;
527 case 1U:
528 freq = CLOCK_GetPllOutFreq();
529 break;
530 case 2U:
531 freq = CLOCK_GetFroHfFreq();
532 break;
533 case 3U:
534 freq = CLOCK_GetAudioPllOutFreq();
535 break;
536 case 7U:
537 freq = 0U;
538 break;
539
540 default:
541 freq = 0U;
542 break;
543 }
544
545 return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
546 }
547
548 /* Get SDIO Clk */
549 /*! brief Return Frequency of SDIO Clock
550 * return Frequency of SDIO Clock.
551 */
CLOCK_GetSdioClkFreq(void)552 uint32_t CLOCK_GetSdioClkFreq(void)
553 {
554 uint32_t freq = 0U;
555
556 switch (SYSCON->SDIOCLKSEL)
557 {
558 case 0U:
559 freq = CLOCK_GetCoreSysClkFreq();
560 break;
561 case 1U:
562 freq = CLOCK_GetPllOutFreq();
563 break;
564 case 2U:
565 freq = CLOCK_GetUsbPllOutFreq();
566 break;
567 case 3U:
568 freq = CLOCK_GetFroHfFreq();
569 break;
570 case 4U:
571 freq = CLOCK_GetAudioPllOutFreq();
572 break;
573 case 7U:
574 freq = 0U;
575 break;
576 default:
577 freq = 0U;
578 break;
579 }
580
581 return freq / ((SYSCON->SDIOCLKDIV & 0xffU) + 1U);
582 }
583
584 /* Get LCD Clk */
585 /*! brief Return Frequency of LCD Clock
586 * return Frequency of LCD Clock.
587 */
CLOCK_GetLcdClkFreq(void)588 uint32_t CLOCK_GetLcdClkFreq(void)
589 {
590 uint32_t freq = 0U;
591
592 switch (SYSCON->LCDCLKSEL)
593 {
594 case 0U:
595 freq = CLOCK_GetCoreSysClkFreq();
596 break;
597 case 1U:
598 freq = CLOCK_GetLcdClkIn();
599 break;
600 case 2U:
601 freq = CLOCK_GetFroHfFreq();
602 break;
603 case 3U:
604 freq = 0U;
605 break;
606
607 default:
608 freq = 0U;
609 break;
610 }
611
612 return freq / ((SYSCON->LCDCLKDIV & 0xffU) + 1U);
613 }
614
615 /* Get LCD CLK IN Clk */
616 /*! brief Return Frequency of LCD CLKIN Clock
617 * return Frequency of LCD CLKIN Clock.
618 */
CLOCK_GetLcdClkIn(void)619 uint32_t CLOCK_GetLcdClkIn(void)
620 {
621 return s_Lcd_Clk_In_Freq;
622 }
623
624 /* Get FRO 12M Clk */
625 /*! brief Return Frequency of FRO 12MHz
626 * return Frequency of FRO 12MHz
627 */
CLOCK_GetFro12MFreq(void)628 uint32_t CLOCK_GetFro12MFreq(void)
629 {
630 return (0U != (SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK)) ? 0U : 12000000U;
631 }
632
633 /* Get EXT OSC Clk */
634 /*! brief Return Frequency of External Clock
635 * return Frequency of External Clock. If no external clock is used returns 0.
636 */
CLOCK_GetExtClkFreq(void)637 uint32_t CLOCK_GetExtClkFreq(void)
638 {
639 return s_Ext_Clk_Freq;
640 }
641
642 /* Get WATCH DOG Clk */
643 /*! brief Return Frequency of Watchdog Oscillator
644 * return Frequency of Watchdog Oscillator
645 */
CLOCK_GetWdtOscFreq(void)646 uint32_t CLOCK_GetWdtOscFreq(void)
647 {
648 uint8_t freq_sel, div_sel;
649 if (0U != (SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_WDT_OSC_MASK))
650 {
651 return 0U;
652 }
653 else
654 {
655 div_sel = (uint8_t)(((SYSCON->WDTOSCCTRL & 0x1fU) + 1U) << 1U);
656 freq_sel =
657 wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)];
658 return ((uint32_t)freq_sel * 50000U) / ((uint32_t)div_sel);
659 }
660 }
661
662 /* Get HF FRO Clk */
663 /*! brief Return Frequency of High-Freq output of FRO
664 * return Frequency of High-Freq output of FRO
665 */
CLOCK_GetFroHfFreq(void)666 uint32_t CLOCK_GetFroHfFreq(void)
667 {
668 uint32_t freq;
669
670 if ((0U != (SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK)) ||
671 (0U == (SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK)))
672 {
673 freq = 0U;
674 }
675 else
676 {
677 if (0U != (SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK))
678 {
679 freq = 96000000U;
680 }
681 else
682 {
683 freq = 48000000U;
684 }
685 }
686
687 return freq;
688 }
689
690 /* Get SYSTEM PLL Clk */
691 /*! brief Return Frequency of PLL
692 * return Frequency of PLL
693 */
CLOCK_GetPllOutFreq(void)694 uint32_t CLOCK_GetPllOutFreq(void)
695 {
696 return s_Pll_Freq;
697 }
698
699 /* Get AUDIO PLL Clk */
700 /*! brief Return Frequency of AUDIO PLL
701 * return Frequency of PLL
702 */
CLOCK_GetAudioPllOutFreq(void)703 uint32_t CLOCK_GetAudioPllOutFreq(void)
704 {
705 return s_Audio_Pll_Freq;
706 }
707
708 /* Get USB PLL Clk */
709 /*! brief Return Frequency of USB PLL
710 * return Frequency of PLL
711 */
CLOCK_GetUsbPllOutFreq(void)712 uint32_t CLOCK_GetUsbPllOutFreq(void)
713 {
714 return s_Usb_Pll_Freq;
715 }
716
717 /* Get RTC OSC Clk */
718 /*! brief Return Frequency of 32kHz osc
719 * return Frequency of 32kHz osc
720 */
CLOCK_GetOsc32KFreq(void)721 uint32_t CLOCK_GetOsc32KFreq(void)
722 {
723 return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */
724 }
725
726 /* Get MAIN Clk */
727 /*! brief Return Frequency of Core System
728 * return Frequency of Core System
729 */
CLOCK_GetCoreSysClkFreq(void)730 uint32_t CLOCK_GetCoreSysClkFreq(void)
731 {
732 uint32_t freq = 0U;
733
734 switch (SYSCON->MAINCLKSELB)
735 {
736 case 0U:
737 if (SYSCON->MAINCLKSELA == 0U)
738 {
739 freq = CLOCK_GetFro12MFreq();
740 }
741 else if (SYSCON->MAINCLKSELA == 1U)
742 {
743 freq = CLOCK_GetExtClkFreq();
744 }
745 else if (SYSCON->MAINCLKSELA == 2U)
746 {
747 freq = CLOCK_GetWdtOscFreq();
748 }
749 else if (SYSCON->MAINCLKSELA == 3U)
750 {
751 freq = CLOCK_GetFroHfFreq();
752 }
753 else
754 {
755 /* For MISRA C-2012 Rule 15.7 */
756 }
757 break;
758 case 2U:
759 freq = CLOCK_GetPllOutFreq();
760 break;
761
762 case 3U:
763 freq = CLOCK_GetOsc32KFreq();
764 break;
765
766 default:
767 freq = 0U;
768 break;
769 }
770
771 return freq;
772 }
773
774 /* Get I2S MCLK Clk */
775 /*! brief Return Frequency of I2S MCLK Clock
776 * return Frequency of I2S MCLK Clock
777 */
CLOCK_GetI2SMClkFreq(void)778 uint32_t CLOCK_GetI2SMClkFreq(void)
779 {
780 return s_I2S_Mclk_Freq;
781 }
782
783 /* Get ASYNC APB Clk */
784 /*! brief Return Frequency of Asynchronous APB Clock
785 * return Frequency of Asynchronous APB Clock Clock
786 */
CLOCK_GetAsyncApbClkFreq(void)787 uint32_t CLOCK_GetAsyncApbClkFreq(void)
788 {
789 async_clock_src_t clkSrc;
790 uint32_t clkRate;
791
792 clkSrc = CLOCK_GetAsyncApbClkSrc();
793
794 switch (clkSrc)
795 {
796 case kCLOCK_AsyncMainClk:
797 clkRate = CLOCK_GetCoreSysClkFreq();
798 break;
799 case kCLOCK_AsyncFro12Mhz:
800 clkRate = CLK_FRO_12MHZ;
801 break;
802 default:
803 clkRate = 0U;
804 break;
805 }
806
807 return clkRate;
808 }
809
810 /* Get MCAN Clk */
811 /*! brief Return Frequency of MCAN Clock
812 * param MCanSel : 0U: MCAN0; 1U: MCAN1
813 * return Frequency of MCAN Clock
814 */
CLOCK_GetMCanClkFreq(uint32_t MCanSel)815 uint32_t CLOCK_GetMCanClkFreq(uint32_t MCanSel)
816 {
817 uint32_t freq = 0U;
818 switch (MCanSel)
819 {
820 case 0U:
821 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN0CLKDIV & 0xffU) + 1U);
822 break;
823 case 1U:
824 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN1CLKDIV & 0xffU) + 1U);
825 break;
826
827 default:
828 freq = 0U;
829 break;
830 }
831
832 return freq;
833 }
834
835 /* Get FLEXCOMM Clk */
836 /*! brief Return Frequency of Flexcomm functional Clock
837 * return Frequency of Flexcomm functional Clock
838 */
CLOCK_GetFlexCommClkFreq(uint32_t id)839 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
840 {
841 uint32_t freq = 0U;
842
843 switch (SYSCON->FCLKSEL[id])
844 {
845 case 0U:
846 freq = CLOCK_GetFro12MFreq();
847 break;
848 case 1U:
849 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFCLKDIV & SYSCON_FROHFCLKDIV_DIV_MASK) + 1U);
850 break;
851 case 2U:
852 freq = CLOCK_GetPllOutFreq();
853 break;
854 case 3U:
855 freq = CLOCK_GetI2SMClkFreq();
856 break;
857 case 4U:
858 freq = CLOCK_GetFrgClkFreq();
859 break;
860
861 default:
862 freq = 0U;
863 break;
864 }
865
866 return freq;
867 }
868
869 /* Get FRG Clk */
870 /*! brief Return Frequency of FRG input clock
871 * return Frequency value
872 */
CLOCK_GetFRGInputClock(void)873 uint32_t CLOCK_GetFRGInputClock(void)
874 {
875 uint32_t freq = 0U;
876
877 switch (SYSCON->FRGCLKSEL)
878 {
879 case 0U:
880 freq = CLOCK_GetCoreSysClkFreq();
881 break;
882 case 1U:
883 freq = CLOCK_GetPllOutFreq();
884 break;
885 case 2U:
886 freq = CLOCK_GetFro12MFreq();
887 break;
888 case 3U:
889 freq = CLOCK_GetFroHfFreq();
890 break;
891
892 default:
893 freq = 0U;
894 break;
895 }
896
897 return freq;
898 }
899
900 /* Get FRG Clk */
901 /*! brief Return Frequency of frg
902 * return Frequency of FRG
903 */
CLOCK_GetFrgClkFreq(void)904 uint32_t CLOCK_GetFrgClkFreq(void)
905 {
906 uint32_t freq = 0U;
907
908 if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK)
909 {
910 freq = (uint32_t)(((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /
911 ((SYSCON_FRGCTRL_DIV_MASK + 1U) +
912 ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));
913 }
914 else
915 {
916 freq = 0U;
917 }
918
919 return freq;
920 }
921
922 /* Get DMIC Clk */
923 /*! brief Return Frequency of dmic
924 * return Frequency of DMIC
925 */
CLOCK_GetDmicClkFreq(void)926 uint32_t CLOCK_GetDmicClkFreq(void)
927 {
928 uint32_t freq = 0U;
929
930 switch (SYSCON->DMICCLKSEL)
931 {
932 case 0U:
933 freq = CLOCK_GetFro12MFreq();
934 break;
935 case 1U:
936 freq = CLOCK_GetFroHfFreq();
937 break;
938 case 2U:
939 freq = CLOCK_GetPllOutFreq();
940 break;
941 case 3U:
942 freq = CLOCK_GetI2SMClkFreq();
943 break;
944 case 4U:
945 freq = CLOCK_GetCoreSysClkFreq();
946 break;
947 case 5U:
948 freq = CLOCK_GetWdtOscFreq();
949 break;
950 default:
951 freq = 0U;
952 break;
953 }
954
955 return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U);
956 }
957
958 /* Set FRG Clk */
959 /**
960 * brief Set the frg output frequency.
961 * param freq : output frequency
962 * return 0 : the frequency range is out of range.
963 * 1 : switch successfully.
964 */
CLOCK_SetFRGClock(uint32_t freq)965 uint32_t CLOCK_SetFRGClock(uint32_t freq)
966 {
967 assert(0U != freq);
968
969 uint32_t input = CLOCK_GetFRGInputClock();
970 uint32_t mul;
971 uint32_t ret;
972
973 if ((freq > 48000000U) || (freq > input) || (input / freq >= 2U))
974 {
975 /* FRG output frequency should be less than equal to 48MHz */
976 ret = 0U;
977 }
978 else
979 {
980 mul = (uint32_t)((((uint64_t)input - freq) * 256ULL) / ((uint64_t)freq));
981 SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK;
982 ret = 1U;
983 }
984
985 return ret;
986 }
987
988 /* Set IP Clk */
989 /*! brief Return Frequency of selected clock
990 * return Frequency of selected clock
991 */
CLOCK_GetFreq(clock_name_t clockName)992 uint32_t CLOCK_GetFreq(clock_name_t clockName)
993 {
994 uint32_t freq;
995 switch (clockName)
996 {
997 case kCLOCK_CoreSysClk:
998 freq = CLOCK_GetCoreSysClkFreq();
999 break;
1000 case kCLOCK_BusClk:
1001 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
1002 break;
1003 case kCLOCK_ClockOut:
1004 freq = CLOCK_GetClockOutClkFreq();
1005 break;
1006 case kCLOCK_Mclk:
1007 freq = CLOCK_GetMclkClkFreq();
1008 break;
1009 case kCLOCK_FroHf:
1010 freq = CLOCK_GetFroHfFreq();
1011 break;
1012 case kCLOCK_Fro12M:
1013 freq = CLOCK_GetFro12MFreq();
1014 break;
1015 case kCLOCK_ExtClk:
1016 freq = CLOCK_GetExtClkFreq();
1017 break;
1018 case kCLOCK_PllOut:
1019 freq = CLOCK_GetPllOutFreq();
1020 break;
1021 case kCLOCK_WdtOsc:
1022 freq = CLOCK_GetWdtOscFreq();
1023 break;
1024 case kCLOCK_Frg:
1025 freq = CLOCK_GetFrgClkFreq();
1026 break;
1027
1028 case kCLOCK_AsyncApbClk:
1029 freq = CLOCK_GetAsyncApbClkFreq();
1030 break;
1031 case kCLOCK_FlexI2S:
1032 freq = CLOCK_GetI2SMClkFreq();
1033 break;
1034 default:
1035 freq = 0U;
1036 break;
1037 }
1038
1039 return freq;
1040 }
1041
1042 /* Set the FLASH wait states for the passed frequency */
1043 /**
1044 * brief Set the flash wait states for the input freuqency.
1045 * param iFreq : Input frequency
1046 * return Nothing
1047 */
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)1048 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)
1049 {
1050 if (iFreq <= 12000000U)
1051 {
1052 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash1Cycle);
1053 }
1054 else if (iFreq <= 24000000U)
1055 {
1056 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash2Cycle);
1057 }
1058 else if (iFreq <= 36000000U)
1059 {
1060 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash3Cycle);
1061 }
1062 else if (iFreq <= 60000000U)
1063 {
1064 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash4Cycle);
1065 }
1066 else if (iFreq <= 96000000U)
1067 {
1068 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash5Cycle);
1069 }
1070 else if (iFreq <= 120000000U)
1071 {
1072 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash6Cycle);
1073 }
1074 else if (iFreq <= 144000000U)
1075 {
1076 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash7Cycle);
1077 }
1078 else if (iFreq <= 168000000U)
1079 {
1080 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash8Cycle);
1081 }
1082 else
1083 {
1084 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash9Cycle);
1085 }
1086 }
1087
1088 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
pllEncodeN(uint32_t N)1089 static uint32_t pllEncodeN(uint32_t N)
1090 {
1091 uint32_t x, i;
1092
1093 /* Find NDec */
1094 switch (N)
1095 {
1096 case 0U:
1097 x = 0x3FFU;
1098 break;
1099
1100 case 1U:
1101 x = 0x302U;
1102 break;
1103
1104 case 2U:
1105 x = 0x202U;
1106 break;
1107
1108 default:
1109 x = 0x080U;
1110 for (i = N; i <= NVALMAX; i++)
1111 {
1112 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
1113 }
1114 break;
1115 }
1116
1117 return x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P);
1118 }
1119
1120 /* Find decoded N value for raw NDEC value */
pllDecodeN(uint32_t NDEC)1121 static uint32_t pllDecodeN(uint32_t NDEC)
1122 {
1123 uint32_t n, x, i;
1124
1125 /* Find NDec */
1126 switch (NDEC)
1127 {
1128 case 0x3FFU:
1129 n = 0U;
1130 break;
1131
1132 case 0x302U:
1133 n = 1U;
1134 break;
1135
1136 case 0x202U:
1137 n = 2U;
1138 break;
1139
1140 default:
1141 x = 0x080U;
1142 n = 0xFFFFFFFFU;
1143 for (i = NVALMAX; (i >= 3U); i--)
1144 {
1145 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
1146 if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)
1147 {
1148 /* Decoded value of NDEC */
1149 n = i;
1150 break;
1151 }
1152 }
1153 break;
1154 }
1155
1156 return n;
1157 }
1158
1159 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
pllEncodeP(uint32_t P)1160 static uint32_t pllEncodeP(uint32_t P)
1161 {
1162 uint32_t x, i;
1163
1164 /* Find PDec */
1165 switch (P)
1166 {
1167 case 0U:
1168 x = 0x7FU;
1169 break;
1170
1171 case 1U:
1172 x = 0x62U;
1173 break;
1174
1175 case 2U:
1176 x = 0x42U;
1177 break;
1178
1179 default:
1180 x = 0x10U;
1181 for (i = P; i <= PVALMAX; i++)
1182 {
1183 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
1184 }
1185 break;
1186 }
1187
1188 return x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P);
1189 }
1190
1191 /* Find decoded P value for raw PDEC value */
pllDecodeP(uint32_t PDEC)1192 static uint32_t pllDecodeP(uint32_t PDEC)
1193 {
1194 uint32_t p, x, i;
1195
1196 /* Find PDec */
1197 switch (PDEC)
1198 {
1199 case 0x7FU:
1200 p = 0U;
1201 break;
1202
1203 case 0x62U:
1204 p = 1U;
1205 break;
1206
1207 case 0x42U:
1208 p = 2U;
1209 break;
1210
1211 default:
1212 x = 0x10U;
1213 p = 0xFFFFFFFFU;
1214 for (i = PVALMAX; (i >= 3U); i--)
1215 {
1216 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
1217 if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC)
1218 {
1219 /* Decoded value of PDEC */
1220 p = i;
1221 break;
1222 }
1223 }
1224 break;
1225 }
1226
1227 return p;
1228 }
1229
1230 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
pllEncodeM(uint32_t M)1231 static uint32_t pllEncodeM(uint32_t M)
1232 {
1233 uint32_t i, x;
1234
1235 /* Find MDec */
1236 switch (M)
1237 {
1238 case 0U:
1239 x = 0x1FFFFU;
1240 break;
1241
1242 case 1U:
1243 x = 0x18003U;
1244 break;
1245
1246 case 2U:
1247 x = 0x10003U;
1248 break;
1249
1250 default:
1251 x = 0x04000U;
1252 for (i = M; i <= MVALMAX; i++)
1253 {
1254 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
1255 }
1256 break;
1257 }
1258
1259 return x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P);
1260 }
1261
1262 /* Find decoded M value for raw MDEC value */
pllDecodeM(uint32_t MDEC)1263 static uint32_t pllDecodeM(uint32_t MDEC)
1264 {
1265 uint32_t m, i, x;
1266
1267 /* Find MDec */
1268 switch (MDEC)
1269 {
1270 case 0x1FFFFU:
1271 m = 0U;
1272 break;
1273
1274 case 0x18003U:
1275 m = 1U;
1276 break;
1277
1278 case 0x10003U:
1279 m = 2U;
1280 break;
1281
1282 default:
1283 x = 0x04000U;
1284 m = 0xFFFFFFFFU;
1285 for (i = MVALMAX; (i >= 3U); i--)
1286 {
1287 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
1288 if ((x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P)) == MDEC)
1289 {
1290 /* Decoded value of MDEC */
1291 m = i;
1292 break;
1293 }
1294 }
1295 break;
1296 }
1297
1298 return m;
1299 }
1300
1301 /* 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)1302 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
1303 {
1304 /* bandwidth: compute selP from Multiplier */
1305 if (M < 60U)
1306 {
1307 *pSelP = (M >> 1U) + 1U;
1308 }
1309 else
1310 {
1311 *pSelP = PVALMAX - 1U;
1312 }
1313
1314 /* bandwidth: compute selI from Multiplier */
1315 if (M > 16384U)
1316 {
1317 *pSelI = 1U;
1318 }
1319 else if (M > 8192U)
1320 {
1321 *pSelI = 2U;
1322 }
1323 else if (M > 2048U)
1324 {
1325 *pSelI = 4U;
1326 }
1327 else if (M >= 501U)
1328 {
1329 *pSelI = 8U;
1330 }
1331 else if (M >= 60U)
1332 {
1333 *pSelI = 4U * (1024U / (M + 9U));
1334 }
1335 else
1336 {
1337 *pSelI = (M & 0x3CU) + 4U;
1338 }
1339
1340 if (*pSelI > ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT))
1341 {
1342 *pSelI = ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT);
1343 }
1344
1345 *pSelR = 0U;
1346 }
1347
1348 /* Get predivider (N) from PLL NDEC setting */
findPllPreDiv(uint32_t ctrlReg,uint32_t nDecReg)1349 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)
1350 {
1351 uint32_t preDiv = 1;
1352
1353 /* Direct input is not used? */
1354 if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT)) == 0U)
1355 {
1356 /* Decode NDEC value to get (N) pre divider */
1357 preDiv = pllDecodeN(nDecReg & 0x3FFU);
1358 if (preDiv == 0U)
1359 {
1360 preDiv = 1U;
1361 }
1362 }
1363
1364 /* Adjusted by 1, directi is used to bypass */
1365 return preDiv;
1366 }
1367
1368 /* Get postdivider (P) from PLL PDEC setting */
findPllPostDiv(uint32_t ctrlReg,uint32_t pDecReg)1369 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)
1370 {
1371 uint32_t postDiv = 1U;
1372
1373 /* Direct input is not used? */
1374 if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U)
1375 {
1376 /* Decode PDEC value to get (P) post divider */
1377 postDiv = 2U * pllDecodeP(pDecReg & 0x7FU);
1378 if (postDiv == 0U)
1379 {
1380 postDiv = 2U;
1381 }
1382 }
1383
1384 /* Adjusted by 1, directo is used to bypass */
1385 return postDiv;
1386 }
1387
1388 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
findPllMMult(uint32_t ctrlReg,uint32_t mDecReg)1389 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)
1390 {
1391 uint32_t mMult = 1U;
1392
1393 /* Decode MDEC value to get (M) multiplier */
1394 mMult = pllDecodeM(mDecReg & 0x1FFFFU);
1395
1396 if (mMult == 0U)
1397 {
1398 mMult = 1U;
1399 }
1400
1401 return mMult;
1402 }
1403
1404 /* Convert the binary to fractional part */
Binary2Fractional(uint32_t binaryPart)1405 static double Binary2Fractional(uint32_t binaryPart)
1406 {
1407 double fractional = 0.0;
1408 for (uint32_t i = 0U; i <= 14U; i++)
1409 {
1410 fractional += (double)(uint32_t)((binaryPart >> i) & 0x1UL) / (double)(uint32_t)(1UL << (15U - i));
1411 }
1412 return fractional;
1413 }
1414
1415 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1416 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1417 {
1418 uint32_t tmp;
1419
1420 while (n != 0U)
1421 {
1422 tmp = n;
1423 n = m % n;
1424 m = tmp;
1425 }
1426
1427 return m;
1428 }
1429
1430 /*
1431 * Set PLL output based on desired output rate.
1432 * In this function, the it calculates the PLL setting for output frequency from input clock
1433 * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1434 * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1435 */
CLOCK_GetPllConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup)1436 static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)
1437 {
1438 uint32_t nDivOutHz, fccoHz, multFccoDiv;
1439 uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1440 uint32_t pllDirectInput, pllDirectOutput;
1441 uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1442
1443 /* Baseline parameters (no input or output dividers) */
1444 pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */
1445 pllPostDivider = 0U; /* 0 implies post-divider will be disabled */
1446 pllDirectOutput = 1U;
1447 multFccoDiv = 2U;
1448
1449 /* Verify output rate parameter */
1450 if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1451 {
1452 /* Maximum PLL output with post divider=1 cannot go above this frequency */
1453 return kStatus_PLL_OutputTooHigh;
1454 }
1455 if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1456 {
1457 /* Minmum PLL output with maximum post divider cannot go below this frequency */
1458 return kStatus_PLL_OutputTooLow;
1459 }
1460
1461 /* Verify input rate parameter */
1462 if (finHz < PLL_LOWER_IN_LIMIT)
1463 {
1464 /* Input clock into the PLL cannot be lower than this */
1465 return kStatus_PLL_InputTooLow;
1466 }
1467
1468 /* Find the optimal CCO frequency for the output and input that
1469 will keep it inside the PLL CCO range. This may require
1470 tweaking the post-divider for the PLL. */
1471 fccoHz = foutHz;
1472 while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1473 {
1474 /* CCO output is less than minimum CCO range, so the CCO output
1475 needs to be bumped up and the post-divider is used to bring
1476 the PLL output back down. */
1477 pllPostDivider++;
1478 if (pllPostDivider > PVALMAX)
1479 {
1480 return kStatus_PLL_OutsideIntLimit;
1481 }
1482
1483 /* Target CCO goes up, PLL output goes down */
1484 fccoHz = foutHz * (pllPostDivider * 2U);
1485 pllDirectOutput = 0U;
1486 }
1487
1488 /* Determine if a pre-divider is needed to get the best frequency */
1489 if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz))
1490 {
1491 uint32_t a = FindGreatestCommonDivisor(fccoHz, (multFccoDiv * finHz));
1492
1493 if (a > 20000U)
1494 {
1495 a = (multFccoDiv * finHz) / a;
1496 if ((a != 0U) && (a < PLL_MAX_N_DIV))
1497 {
1498 pllPreDivider = a;
1499 }
1500 }
1501 }
1502
1503 /* Bypass pre-divider hardware if pre-divider is 1 */
1504 if (pllPreDivider > 1U)
1505 {
1506 pllDirectInput = 0U;
1507 }
1508 else
1509 {
1510 pllDirectInput = 1U;
1511 }
1512
1513 /* Determine PLL multipler */
1514 nDivOutHz = (finHz / pllPreDivider);
1515 pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv;
1516
1517 /* Find optimal values for filter */
1518 /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1519 if ((nDivOutHz * ((multFccoDiv * pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1520 {
1521 pllMultiplier++;
1522 }
1523
1524 /* Setup filtering */
1525 pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1526 uplimoff = 0U;
1527
1528 /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1529 pSetup->pllmdec = PLL_MDEC_VAL_SET(pllEncodeM(pllMultiplier));
1530
1531 /* Get encoded values for N (prediv) and P (postdiv) */
1532 pSetup->pllndec = PLL_NDEC_VAL_SET(pllEncodeN(pllPreDivider));
1533 pSetup->pllpdec = PLL_PDEC_VAL_SET(pllEncodeP(pllPostDivider));
1534
1535 /* PLL control */
1536 pSetup->pllctrl = (pllSelR << SYSCON_SYSPLLCTRL_SELR_SHIFT) | /* Filter coefficient */
1537 (pllSelI << SYSCON_SYSPLLCTRL_SELI_SHIFT) | /* Filter coefficient */
1538 (pllSelP << SYSCON_SYSPLLCTRL_SELP_SHIFT) | /* Filter coefficient */
1539 (0UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT) | /* PLL bypass mode disabled */
1540 (uplimoff << SYSCON_SYSPLLCTRL_UPLIMOFF_SHIFT) | /* SS/fractional mode disabled */
1541 (pllDirectInput << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT) | /* Bypass pre-divider? */
1542 (pllDirectOutput << SYSCON_SYSPLLCTRL_DIRECTO_SHIFT); /* Bypass post-divider? */
1543
1544 return kStatus_PLL_Success;
1545 }
1546
1547 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1548 /* Alloct the static buffer for cache. */
1549 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1550 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1551 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1552 static uint32_t s_PllSetupCacheIdx = 0U;
1553 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1554
1555 /*
1556 * Calculate the PLL setting values from input clock freq to output freq.
1557 */
CLOCK_GetPllConfig(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup)1558 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)
1559 {
1560 pll_error_t retErr;
1561 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1562 uint32_t i;
1563
1564 for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1565 {
1566 if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]))
1567 {
1568 /* Hit the target in cache buffer. */
1569 pSetup->pllctrl = s_PllSetupCacheStruct[i].pllctrl;
1570 pSetup->pllndec = s_PllSetupCacheStruct[i].pllndec;
1571 pSetup->pllpdec = s_PllSetupCacheStruct[i].pllpdec;
1572 pSetup->pllmdec = s_PllSetupCacheStruct[i].pllmdec;
1573 retErr = kStatus_PLL_Success;
1574 break;
1575 }
1576 }
1577
1578 if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1579 {
1580 return retErr;
1581 }
1582 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1583
1584 /* No cache or did not hit the cache. */
1585 retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup);
1586
1587 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1588 if (kStatus_PLL_Success == retErr)
1589 {
1590 /* Cache the most recent calulation result into buffer. */
1591 s_FinHzCache[s_PllSetupCacheIdx] = finHz;
1592 s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1593
1594 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl = pSetup->pllctrl;
1595 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec = pSetup->pllndec;
1596 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec = pSetup->pllpdec;
1597 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllmdec = pSetup->pllmdec;
1598 /* Update the index for next available buffer. */
1599 s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1600 }
1601 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1602
1603 return retErr;
1604 }
1605
1606 /* Update SYSTEM PLL rate variable */
CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t * pSetup)1607 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup)
1608 {
1609 s_Pll_Freq = CLOCK_GetSystemPLLOutFromSetup(pSetup);
1610 }
1611
1612 /* Update AUDIO PLL rate variable */
CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t * pSetup)1613 static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup)
1614 {
1615 s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromSetup(pSetup);
1616 }
1617
1618 /* Update AUDIO Fractional PLL rate variable */
CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t * pSetup)1619 static void CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t *pSetup)
1620 {
1621 s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromFractSetup(pSetup);
1622 }
1623
1624 /* Update USB PLL rate variable */
CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t * pSetup)1625 static void CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t *pSetup)
1626 {
1627 s_Usb_Pll_Freq = CLOCK_GetUsbPLLOutFromSetup(pSetup);
1628 }
1629
1630 /* Return System PLL input clock rate */
1631 /*! brief Return System PLL input clock rate
1632 * return System PLL input clock rate
1633 */
CLOCK_GetSystemPLLInClockRate(void)1634 uint32_t CLOCK_GetSystemPLLInClockRate(void)
1635 {
1636 uint32_t clkRate = 0U;
1637
1638 switch ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK))
1639 {
1640 case 0x00U:
1641 clkRate = CLK_FRO_12MHZ;
1642 break;
1643
1644 case 0x01U:
1645 clkRate = CLOCK_GetExtClkFreq();
1646 break;
1647
1648 case 0x02U:
1649 clkRate = CLOCK_GetWdtOscFreq();
1650 break;
1651
1652 case 0x03U:
1653 clkRate = CLOCK_GetOsc32KFreq();
1654 break;
1655
1656 default:
1657 clkRate = 0U;
1658 break;
1659 }
1660
1661 return clkRate;
1662 }
1663
1664 /* Return Audio PLL input clock rate */
1665 /*! brief Return Audio PLL input clock rate
1666 * return Audio PLL input clock rate
1667 */
CLOCK_GetAudioPLLInClockRate(void)1668 uint32_t CLOCK_GetAudioPLLInClockRate(void)
1669 {
1670 uint32_t clkRate = 0U;
1671
1672 switch ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK))
1673 {
1674 case 0x00U:
1675 clkRate = CLK_FRO_12MHZ;
1676 break;
1677
1678 case 0x01U:
1679 clkRate = CLOCK_GetExtClkFreq();
1680 break;
1681
1682 default:
1683 clkRate = 0U;
1684 break;
1685 }
1686
1687 return clkRate;
1688 }
1689
1690 /* Return System PLL output clock rate from setup structure */
1691 /*! brief Return System PLL output clock rate from setup structure
1692 * param pSetup : Pointer to a PLL setup structure
1693 * return System PLL output clock rate the setup structure will generate
1694 */
CLOCK_GetSystemPLLOutFromSetup(pll_setup_t * pSetup)1695 uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup)
1696 {
1697 uint32_t prediv, postdiv, mMult, inPllRate;
1698 uint64_t workRate;
1699
1700 inPllRate = CLOCK_GetSystemPLLInClockRate();
1701 /* If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock*/
1702 if ((pSetup->pllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U)
1703 {
1704 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1705 /*
1706 * 1. Pre-divider
1707 * Pre-divider is only available when the DIRECTI is disabled.
1708 */
1709 if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK))
1710 {
1711 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1712 }
1713 else
1714 {
1715 prediv = 1U; /* The pre-divider is bypassed. */
1716 }
1717 /*
1718 * 2. Post-divider
1719 * Post-divider is only available when the DIRECTO is disabled.
1720 */
1721 if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK))
1722 {
1723 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1724 }
1725 else
1726 {
1727 postdiv = 1U; /* The post-divider is bypassed. */
1728 }
1729 /* Adjust input clock */
1730 inPllRate = inPllRate / prediv;
1731
1732 /* MDEC used for rate */
1733 mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);
1734 workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1735
1736 workRate = workRate / ((uint64_t)postdiv);
1737 workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/
1738 }
1739 else
1740 {
1741 /* In bypass mode */
1742 workRate = (uint64_t)inPllRate;
1743 }
1744
1745 return (uint32_t)workRate;
1746 }
1747
1748 /* Return Usb PLL output clock rate from setup structure */
1749 /*! brief Return System USB PLL output clock rate from setup structure
1750 * param pSetup : Pointer to a PLL setup structure
1751 * return System PLL output clock rate the setup structure will generate
1752 */
CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t * pSetup)1753 uint32_t CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t *pSetup)
1754 {
1755 uint32_t nsel, psel, msel, inPllRate;
1756 uint64_t workRate;
1757 inPllRate = CLOCK_GetExtClkFreq();
1758 msel = pSetup->msel;
1759 psel = pSetup->psel;
1760 nsel = pSetup->nsel;
1761
1762 if (pSetup->fbsel)
1763 {
1764 /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */
1765 workRate = (uint64_t)(inPllRate) * (msel + 1ULL) / (nsel + 1ULL);
1766 }
1767 else
1768 {
1769 /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */
1770 workRate = ((uint64_t)inPllRate / (nsel + 1ULL)) * (msel + 1ULL) / (2U * (1UL << (psel & 3U)));
1771 }
1772
1773 return (uint32_t)workRate;
1774 }
1775
1776 /* Return Audio PLL output clock rate from setup structure */
1777 /*! brief Return System AUDIO PLL output clock rate from setup structure
1778 * param pSetup : Pointer to a PLL setup structure
1779 * return System PLL output clock rate the setup structure will generate
1780 */
CLOCK_GetAudioPLLOutFromSetup(pll_setup_t * pSetup)1781 uint32_t CLOCK_GetAudioPLLOutFromSetup(pll_setup_t *pSetup)
1782 {
1783 uint32_t prediv, postdiv, mMult, inPllRate;
1784 uint64_t workRate;
1785
1786 inPllRate = CLOCK_GetAudioPLLInClockRate();
1787 if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)
1788 {
1789 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1790 /*
1791 * 1. Pre-divider
1792 * Pre-divider is only available when the DIRECTI is disabled.
1793 */
1794 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))
1795 {
1796 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1797 }
1798 else
1799 {
1800 prediv = 1U; /* The pre-divider is bypassed. */
1801 }
1802 /*
1803 * 2. Post-divider
1804 * Post-divider is only available when the DIRECTO is disabled.
1805 */
1806 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))
1807 {
1808 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1809 }
1810 else
1811 {
1812 postdiv = 1U; /* The post-divider is bypassed. */
1813 }
1814 /* Adjust input clock */
1815 inPllRate = inPllRate / prediv;
1816
1817 /* MDEC used for rate */
1818 mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);
1819 workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1820
1821 workRate = workRate / ((uint64_t)postdiv);
1822 workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/
1823 }
1824 else
1825 {
1826 /* In bypass mode */
1827 workRate = (uint64_t)inPllRate;
1828 }
1829
1830 return (uint32_t)workRate;
1831 }
1832
1833 /* Return Audio PLL output clock rate from audio fractioanl setup structure */
1834 /*! brief Return System AUDIO PLL output clock rate from audio fractioanl setup structure
1835 * param pSetup : Pointer to a PLL setup structure
1836 * return System PLL output clock rate the setup structure will generate
1837 */
CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t * pSetup)1838 uint32_t CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t *pSetup)
1839 {
1840 uint32_t prediv, postdiv, inPllRate;
1841 double workRate, mMultFactional;
1842
1843 inPllRate = CLOCK_GetAudioPLLInClockRate();
1844 if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)
1845 {
1846 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1847 /*
1848 * 1. Pre-divider
1849 * Pre-divider is only available when the DIRECTI is disabled.
1850 */
1851 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))
1852 {
1853 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1854 }
1855 else
1856 {
1857 prediv = 1U; /* The pre-divider is bypassed. */
1858 }
1859 /*
1860 * 2. Post-divider
1861 * Post-divider is only available when the DIRECTO is disabled.
1862 */
1863 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))
1864 {
1865 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1866 }
1867 else
1868 {
1869 postdiv = 1U; /* The post-divider is bypassed. */
1870 }
1871 /* Adjust input clock */
1872 inPllRate = inPllRate / prediv;
1873
1874 mMultFactional =
1875 (double)(uint32_t)(pSetup->audpllfrac >> 15U) + (double)Binary2Fractional(pSetup->audpllfrac & 0x7FFFU);
1876 workRate = (double)inPllRate * (double)mMultFactional;
1877
1878 workRate = workRate / ((double)postdiv);
1879 workRate = workRate * 2.0; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/
1880 }
1881 else
1882 {
1883 /* In bypass mode */
1884 workRate = (double)inPllRate;
1885 }
1886
1887 return (uint32_t)workRate;
1888 }
1889
1890 /* Set the current PLL Rate */
1891 /*! brief Store the current PLL rate
1892 * param rate: Current rate of the PLL
1893 * return Nothing
1894 **/
CLOCK_SetStoredPLLClockRate(uint32_t rate)1895 void CLOCK_SetStoredPLLClockRate(uint32_t rate)
1896 {
1897 s_Pll_Freq = rate;
1898 }
1899
1900 /* Set the current Audio PLL Rate */
1901 /*! brief Store the current AUDIO PLL rate
1902 * param rate: Current rate of the PLL
1903 * return Nothing
1904 **/
CLOCK_SetStoredAudioPLLClockRate(uint32_t rate)1905 void CLOCK_SetStoredAudioPLLClockRate(uint32_t rate)
1906 {
1907 s_Audio_Pll_Freq = rate;
1908 }
1909
1910 /* Set the current Usb PLL Rate */
1911 /*! brief Set USB PLL output frequency
1912 * param rate : frequency value
1913 *
1914 */
CLOCK_SetStoredUsbPLLClockRate(uint32_t rate)1915 void CLOCK_SetStoredUsbPLLClockRate(uint32_t rate)
1916 {
1917 s_Usb_Pll_Freq = rate;
1918 }
1919
1920 /* Return System PLL output clock rate */
1921 /*! brief Return System PLL output clock rate
1922 * param recompute : Forces a PLL rate recomputation if true
1923 * return System PLL output clock rate
1924 * note The PLL rate is cached in the driver in a variable as
1925 * the rate computation function can take some time to perform. It
1926 * is recommended to use 'false' with the 'recompute' parameter.
1927 */
CLOCK_GetSystemPLLOutClockRate(bool recompute)1928 uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute)
1929 {
1930 pll_setup_t Setup;
1931 uint32_t rate;
1932
1933 if ((recompute) || (s_Pll_Freq == 0U))
1934 {
1935 Setup.pllctrl = SYSCON->SYSPLLCTRL;
1936 Setup.pllndec = SYSCON->SYSPLLNDEC;
1937 Setup.pllpdec = SYSCON->SYSPLLPDEC;
1938 Setup.pllmdec = SYSCON->SYSPLLMDEC;
1939
1940 CLOCK_GetSystemPLLOutFromSetupUpdate(&Setup);
1941 }
1942
1943 rate = s_Pll_Freq;
1944
1945 return rate;
1946 }
1947
1948 /* Return AUDIO PLL output clock rate */
1949 /*! brief Return System AUDIO PLL output clock rate
1950 * param recompute : Forces a AUDIO PLL rate recomputation if true
1951 * return System AUDIO PLL output clock rate
1952 * note The AUDIO PLL rate is cached in the driver in a variable as
1953 * the rate computation function can take some time to perform. It
1954 * is recommended to use 'false' with the 'recompute' parameter.
1955 */
CLOCK_GetAudioPLLOutClockRate(bool recompute)1956 uint32_t CLOCK_GetAudioPLLOutClockRate(bool recompute)
1957 {
1958 pll_setup_t Setup;
1959 uint32_t rate;
1960
1961 if ((recompute) || (s_Audio_Pll_Freq == 0U))
1962 {
1963 Setup.pllctrl = SYSCON->AUDPLLCTRL;
1964 Setup.pllndec = SYSCON->AUDPLLNDEC;
1965 Setup.pllpdec = SYSCON->AUDPLLPDEC;
1966 Setup.pllmdec = SYSCON->AUDPLLMDEC;
1967
1968 CLOCK_GetAudioPLLOutFromSetupUpdate(&Setup);
1969 }
1970
1971 rate = s_Audio_Pll_Freq;
1972 return rate;
1973 }
1974
1975 /* Return USB PLL output clock rate */
1976 /*! brief Return System USB PLL output clock rate
1977 * param recompute : Forces a USB PLL rate recomputation if true
1978 * return System USB PLL output clock rate
1979 * note The USB PLL rate is cached in the driver in a variable as
1980 * the rate computation function can take some time to perform. It
1981 * is recommended to use 'false' with the 'recompute' parameter.
1982 */
CLOCK_GetUsbPLLOutClockRate(bool recompute)1983 uint32_t CLOCK_GetUsbPLLOutClockRate(bool recompute)
1984 {
1985 usb_pll_setup_t Setup;
1986 uint32_t rate;
1987 uint32_t usbPllCtrl;
1988
1989 if ((recompute) || (s_Usb_Pll_Freq == 0U))
1990 {
1991 usbPllCtrl = SYSCON->USBPLLCTRL;
1992 Setup.msel = (uint8_t)((usbPllCtrl & SYSCON_USBPLLCTRL_MSEL_MASK) >> SYSCON_USBPLLCTRL_MSEL_SHIFT);
1993 Setup.psel = (uint8_t)((usbPllCtrl & SYSCON_USBPLLCTRL_PSEL_MASK) >> SYSCON_USBPLLCTRL_PSEL_SHIFT);
1994 Setup.nsel = (uint8_t)((usbPllCtrl & SYSCON_USBPLLCTRL_NSEL_MASK) >> SYSCON_USBPLLCTRL_NSEL_SHIFT);
1995 Setup.fbsel = (0U != (usbPllCtrl & SYSCON_USBPLLCTRL_FBSEL_MASK));
1996 Setup.bypass = (0U != (usbPllCtrl & SYSCON_USBPLLCTRL_BYPASS_MASK));
1997 Setup.direct = (0U != (usbPllCtrl & SYSCON_USBPLLCTRL_DIRECT_MASK));
1998 CLOCK_GetUsbPLLOutFromSetupUpdate(&Setup);
1999 }
2000
2001 rate = s_Usb_Pll_Freq;
2002 return rate;
2003 }
2004
2005 /* Set PLL output based on the passed PLL setup data */
2006 /*! brief Set PLL output based on the passed PLL setup data
2007 * param pControl : Pointer to populated PLL control structure to generate setup with
2008 * param pSetup : Pointer to PLL setup structure to be filled
2009 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2010 * note Actual frequency for setup may vary from the desired frequency based on the
2011 * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
2012 */
CLOCK_SetupPLLData(pll_config_t * pControl,pll_setup_t * pSetup)2013 pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
2014 {
2015 uint32_t inRate;
2016 pll_error_t pllError;
2017
2018 /* Determine input rate for the PLL */
2019 if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)
2020 {
2021 inRate = pControl->inputRate;
2022 }
2023 else
2024 {
2025 inRate = CLOCK_GetSystemPLLInClockRate();
2026 }
2027
2028 /* PLL flag options */
2029 pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup);
2030 pSetup->pllRate = pControl->desiredRate;
2031 return pllError;
2032 }
2033
2034 /* Set PLL output from PLL setup structure */
2035 /*! brief Set PLL output from PLL setup structure (precise frequency)
2036 * param pSetup : Pointer to populated PLL setup structure
2037 * param flagcfg : Flag configuration for PLL config structure
2038 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2039 * note This function will power off the PLL, setup the PLL with the
2040 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2041 * and adjust system voltages to the new PLL rate. The function will not
2042 * alter any source clocks (ie, main systen clock) that may use the PLL,
2043 * so these should be setup prior to and after exiting the function.
2044 */
CLOCK_SetupSystemPLLPrec(pll_setup_t * pSetup,uint32_t flagcfg)2045 pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)
2046 {
2047 if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U)
2048 {
2049 /* Turn on the ext clock if system pll input select clk_in */
2050 CLOCK_Enable_SysOsc(true);
2051 }
2052 /* Enable power for PLLs */
2053 POWER_SetPLL();
2054 /* Power off PLL during setup changes */
2055 POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);
2056 /*!< Set FLASH waitstates for core */
2057 CLOCK_SetFLASHAccessCyclesForFreq(pSetup->pllRate);
2058 pSetup->flags = flagcfg;
2059
2060 /* Write PLL setup data */
2061 SYSCON->SYSPLLCTRL = pSetup->pllctrl;
2062 SYSCON->SYSPLLNDEC = pSetup->pllndec;
2063 SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
2064 SYSCON->SYSPLLPDEC = pSetup->pllpdec;
2065 SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
2066 SYSCON->SYSPLLMDEC = pSetup->pllmdec;
2067 SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */
2068
2069 /* Flags for lock or power on */
2070 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)
2071 {
2072 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
2073 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
2074 uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);
2075
2076 /* Initialize and power up PLL */
2077 SYSCON->SYSPLLMDEC = maxCCO;
2078 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
2079
2080 /* Set mreq to activate */
2081 SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);
2082
2083 /* Delay for 72 uSec @ 12Mhz */
2084 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2085
2086 /* clear mreq to prepare for restoring mreq */
2087 SYSCON->SYSPLLMDEC = curSSCTRL;
2088
2089 /* set original value back and activate */
2090 SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);
2091
2092 /* Enable peripheral states by setting low */
2093 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
2094 }
2095 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2096 {
2097 while (CLOCK_IsSystemPLLLocked() == false)
2098 {
2099 }
2100 }
2101
2102 /* Update current programmed PLL rate var */
2103 CLOCK_GetSystemPLLOutFromSetupUpdate(pSetup);
2104
2105 /* System voltage adjustment, occurs prior to setting main system clock */
2106 if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0U)
2107 {
2108 POWER_SetVoltageForFreq(s_Pll_Freq);
2109 }
2110
2111 return kStatus_PLL_Success;
2112 }
2113
2114 /* Set AUDIO PLL output from AUDIO PLL setup structure */
2115 /*! brief Set AUDIO PLL output from AUDIOPLL setup structure (precise frequency)
2116 * param pSetup : Pointer to populated PLL setup structure
2117 * param flagcfg : Flag configuration for PLL config structure
2118 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2119 * note This function will power off the PLL, setup the PLL with the
2120 * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock,
2121 * and adjust system voltages to the new AUDIOPLL rate. The function will not
2122 * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL,
2123 * so these should be setup prior to and after exiting the function.
2124 */
CLOCK_SetupAudioPLLPrec(pll_setup_t * pSetup,uint32_t flagcfg)2125 pll_error_t CLOCK_SetupAudioPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)
2126 {
2127 if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)
2128 {
2129 /* Turn on the ext clock if system pll input select clk_in */
2130 CLOCK_Enable_SysOsc(true);
2131 }
2132 /* Enable power VD3 for PLLs */
2133 POWER_SetPLL();
2134 /* Power off PLL during setup changes */
2135 POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);
2136
2137 pSetup->flags = flagcfg;
2138
2139 /* Write PLL setup data */
2140 SYSCON->AUDPLLCTRL = pSetup->pllctrl;
2141 SYSCON->AUDPLLNDEC = pSetup->pllndec;
2142 SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
2143 SYSCON->AUDPLLPDEC = pSetup->pllpdec;
2144 SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
2145 SYSCON->AUDPLLMDEC = pSetup->pllmdec;
2146 SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */
2147 SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1); /* disable fractional function */
2148
2149 /* Flags for lock or power on */
2150 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)
2151 {
2152 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
2153 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
2154 uint32_t curSSCTRL = SYSCON->AUDPLLMDEC & ~(1UL << 17U);
2155
2156 /* Initialize and power up PLL */
2157 SYSCON->AUDPLLMDEC = maxCCO;
2158 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2159
2160 /* Set mreq to activate */
2161 SYSCON->AUDPLLMDEC = maxCCO | (1UL << 17U);
2162
2163 /* Delay for 72 uSec @ 12Mhz */
2164 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2165
2166 /* clear mreq to prepare for restoring mreq */
2167 SYSCON->AUDPLLMDEC = curSSCTRL;
2168
2169 /* set original value back and activate */
2170 SYSCON->AUDPLLMDEC = curSSCTRL | (1UL << 17U);
2171
2172 /* Enable peripheral states by setting low */
2173 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2174 }
2175 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2176 {
2177 while (CLOCK_IsAudioPLLLocked() == false)
2178 {
2179 }
2180 }
2181
2182 /* Update current programmed PLL rate var */
2183 CLOCK_GetAudioPLLOutFromSetupUpdate(pSetup);
2184
2185 return kStatus_PLL_Success;
2186 }
2187
2188 /* Set AUDIO PLL output from AUDIO PLL fractional setup structure */
2189 /*! brief Set AUDIO PLL output from AUDIOPLL setup structure using the Audio Fractional divider register(precise
2190 * frequency)
2191 * param pSetup : Pointer to populated PLL setup structure
2192 * param flagcfg : Flag configuration for PLL config structure
2193 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2194 * note This function will power off the PLL, setup the PLL with the
2195 * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock,
2196 * and adjust system voltages to the new AUDIOPLL rate. The function will not
2197 * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL,
2198 * so these should be setup prior to and after exiting the function.
2199 */
CLOCK_SetupAudioPLLPrecFract(pll_setup_t * pSetup,uint32_t flagcfg)2200 pll_error_t CLOCK_SetupAudioPLLPrecFract(pll_setup_t *pSetup, uint32_t flagcfg)
2201 {
2202 if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)
2203 {
2204 /* Turn on the ext clock if system pll input select clk_in */
2205 CLOCK_Enable_SysOsc(true);
2206 }
2207 /* Enable power VD3 for PLLs */
2208 POWER_SetPLL();
2209 /* Power off PLL during setup changes */
2210 POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);
2211
2212 pSetup->flags = flagcfg;
2213
2214 /* Write PLL setup data */
2215 SYSCON->AUDPLLCTRL = pSetup->pllctrl;
2216 SYSCON->AUDPLLNDEC = pSetup->pllndec;
2217 SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
2218 SYSCON->AUDPLLPDEC = pSetup->pllpdec;
2219 SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
2220 SYSCON->AUDPLLMDEC = pSetup->pllmdec;
2221 SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(0); /* enable fractional function */
2222 SYSCON->AUDPLLFRAC = pSetup->audpllfrac;
2223 SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT);
2224
2225 /* Enable peripheral states by setting low */
2226 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2227
2228 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2229 {
2230 while (CLOCK_IsAudioPLLLocked() == false)
2231 {
2232 }
2233 }
2234
2235 /* Update current programmed PLL rate var */
2236 CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pSetup);
2237
2238 return kStatus_PLL_Success;
2239 }
2240
2241 /* Set Audio PLL output based on the passed Audio PLL setup data */
2242 /*! brief Set AUDIO PLL output based on the passed AUDIO PLL setup data
2243 * param pControl : Pointer to populated PLL control structure to generate setup with
2244 * param pSetup : Pointer to PLL setup structure to be filled
2245 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2246 * note Actual frequency for setup may vary from the desired frequency based on the
2247 * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
2248 */
CLOCK_SetupAudioPLLData(pll_config_t * pControl,pll_setup_t * pSetup)2249 pll_error_t CLOCK_SetupAudioPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
2250 {
2251 uint32_t inRate;
2252 pll_error_t pllError;
2253
2254 /* Determine input rate for the PLL */
2255 if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)
2256 {
2257 inRate = pControl->inputRate;
2258 }
2259 else
2260 {
2261 inRate = CLOCK_GetAudioPLLInClockRate();
2262 }
2263
2264 /* PLL flag options */
2265 pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup);
2266 pSetup->pllRate = pControl->desiredRate;
2267 return pllError;
2268 }
2269
2270 /* Setup PLL Frequency from pre-calculated value */
2271 /**
2272 * brief Set PLL output from PLL setup structure (precise frequency)
2273 * param pSetup : Pointer to populated PLL setup structure
2274 * return kStatus_PLL_Success on success, or PLL setup error code
2275 * note This function will power off the PLL, setup the PLL with the
2276 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2277 * and adjust system voltages to the new PLL rate. The function will not
2278 * alter any source clocks (ie, main systen clock) that may use the PLL,
2279 * so these should be setup prior to and after exiting the function.
2280 */
CLOCK_SetPLLFreq(const pll_setup_t * pSetup)2281 pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup)
2282 {
2283 if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U)
2284 {
2285 /* Turn on the ext clock if system pll input select clk_in */
2286 CLOCK_Enable_SysOsc(true);
2287 }
2288 /* Enable power VD3 for PLLs */
2289 POWER_SetPLL();
2290 /* Power off PLL during setup changes */
2291 POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);
2292
2293 /* Write PLL setup data */
2294 SYSCON->SYSPLLCTRL = pSetup->pllctrl;
2295 SYSCON->SYSPLLNDEC = pSetup->pllndec;
2296 SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
2297 SYSCON->SYSPLLPDEC = pSetup->pllpdec;
2298 SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
2299 SYSCON->SYSPLLMDEC = pSetup->pllmdec;
2300 SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */
2301
2302 /* Flags for lock or power on */
2303 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)
2304 {
2305 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
2306 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
2307 uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);
2308
2309 /* Initialize and power up PLL */
2310 SYSCON->SYSPLLMDEC = maxCCO;
2311 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
2312
2313 /* Set mreq to activate */
2314 SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);
2315
2316 /* Delay for 72 uSec @ 12Mhz */
2317 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2318
2319 /* clear mreq to prepare for restoring mreq */
2320 SYSCON->SYSPLLMDEC = curSSCTRL;
2321
2322 /* set original value back and activate */
2323 SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);
2324
2325 /* Enable peripheral states by setting low */
2326 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
2327 }
2328 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2329 {
2330 while (CLOCK_IsSystemPLLLocked() == false)
2331 {
2332 }
2333 }
2334
2335 /* Update current programmed PLL rate var */
2336 s_Pll_Freq = pSetup->pllRate;
2337
2338 return kStatus_PLL_Success;
2339 }
2340
2341 /* Setup Audio PLL Frequency from pre-calculated value */
2342 /**
2343 * brief Set Audio PLL output from Audio PLL setup structure (precise frequency)
2344 * param pSetup : Pointer to populated PLL setup structure
2345 * return kStatus_PLL_Success on success, or Audio PLL setup error code
2346 * note This function will power off the PLL, setup the Audio PLL with the
2347 * new setup data, and then optionally powerup the PLL, wait for Audio PLL lock,
2348 * and adjust system voltages to the new PLL rate. The function will not
2349 * alter any source clocks (ie, main systen clock) that may use the Audio PLL,
2350 * so these should be setup prior to and after exiting the function.
2351 */
CLOCK_SetAudioPLLFreq(const pll_setup_t * pSetup)2352 pll_error_t CLOCK_SetAudioPLLFreq(const pll_setup_t *pSetup)
2353 {
2354 if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)
2355 {
2356 /* Turn on the ext clock if system pll input select clk_in */
2357 CLOCK_Enable_SysOsc(true);
2358 }
2359 /* Enable power VD3 for PLLs */
2360 POWER_SetPLL();
2361 /* Power off Audio PLL during setup changes */
2362 POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);
2363
2364 /* Write Audio PLL setup data */
2365 SYSCON->AUDPLLCTRL = pSetup->pllctrl;
2366 SYSCON->AUDPLLFRAC = pSetup->audpllfrac;
2367 SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT); /* latch */
2368 SYSCON->AUDPLLNDEC = pSetup->pllndec;
2369 SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_AUDPLLNDEC_NREQ_SHIFT); /* latch */
2370 SYSCON->AUDPLLPDEC = pSetup->pllpdec;
2371 SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_AUDPLLPDEC_PREQ_SHIFT); /* latch */
2372 SYSCON->AUDPLLMDEC = pSetup->pllmdec;
2373 SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_AUDPLLMDEC_MREQ_SHIFT); /* latch */
2374 SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1); /* disable fractional function */
2375
2376 /* Flags for lock or power on */
2377 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)
2378 {
2379 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
2380 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
2381 uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);
2382
2383 /* Initialize and power up PLL */
2384 SYSCON->SYSPLLMDEC = maxCCO;
2385 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2386
2387 /* Set mreq to activate */
2388 SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);
2389
2390 /* Delay for 72 uSec @ 12Mhz */
2391 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2392
2393 /* clear mreq to prepare for restoring mreq */
2394 SYSCON->SYSPLLMDEC = curSSCTRL;
2395
2396 /* set original value back and activate */
2397 SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);
2398
2399 /* Enable peripheral states by setting low */
2400 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2401 }
2402 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2403 {
2404 while (CLOCK_IsAudioPLLLocked() == false)
2405 {
2406 }
2407 }
2408
2409 /* Update current programmed PLL rate var */
2410 s_Audio_Pll_Freq = pSetup->pllRate;
2411
2412 return kStatus_PLL_Success;
2413 }
2414
2415 /* Setup USB PLL Frequency from pre-calculated value */
2416 /**
2417 * brief Set USB PLL output from USB PLL setup structure (precise frequency)
2418 * param pSetup : Pointer to populated USB PLL setup structure
2419 * return kStatus_PLL_Success on success, or USB PLL setup error code
2420 * note This function will power off the USB PLL, setup the PLL with the
2421 * new setup data, and then optionally powerup the USB PLL, wait for USB PLL lock,
2422 * and adjust system voltages to the new USB PLL rate. The function will not
2423 * alter any source clocks (ie, usb pll clock) that may use the USB PLL,
2424 * so these should be setup prior to and after exiting the function.
2425 */
CLOCK_SetUsbPLLFreq(const usb_pll_setup_t * pSetup)2426 pll_error_t CLOCK_SetUsbPLLFreq(const usb_pll_setup_t *pSetup)
2427 {
2428 uint32_t usbpllctrl, fccoHz;
2429 uint8_t msel, psel, nsel;
2430 bool pllDirectInput, pllDirectOutput, pllfbsel;
2431
2432 msel = pSetup->msel;
2433 psel = pSetup->psel;
2434 nsel = pSetup->nsel;
2435 pllDirectOutput = pSetup->direct;
2436 pllDirectInput = pSetup->bypass;
2437 pllfbsel = pSetup->fbsel;
2438
2439 /* Input clock into the PLL cannot be lower than this */
2440 if (pSetup->inputRate < USB_PLL_LOWER_IN_LIMIT)
2441 {
2442 return kStatus_PLL_InputTooLow;
2443 }
2444
2445 if (pllfbsel)
2446 {
2447 /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */
2448 fccoHz = (pSetup->inputRate / (nsel + 1UL)) * 2UL * (msel + 1UL) * (1UL << (psel & 3U));
2449
2450 /* USB PLL CCO out rate cannot be lower than this */
2451 if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ)
2452 {
2453 return kStatus_PLL_CCOTooLow;
2454 }
2455 /* USB PLL CCO out rate cannot be Higher than this */
2456 if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ)
2457 {
2458 return kStatus_PLL_CCOTooHigh;
2459 }
2460 }
2461 else
2462 {
2463 /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */
2464 fccoHz = pSetup->inputRate / (nsel + 1UL) * (msel + 1UL);
2465
2466 /* USB PLL CCO out rate cannot be lower than this */
2467 if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ)
2468 {
2469 return kStatus_PLL_CCOTooLow;
2470 }
2471 /* USB PLL CCO out rate cannot be Higher than this */
2472 if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ)
2473 {
2474 return kStatus_PLL_CCOTooHigh;
2475 }
2476 }
2477
2478 /* If configure the USB HOST clock, VD5 power for USB PHY should be enable
2479 before the PLL is working */
2480 /* Turn on the ext clock for usb pll input */
2481 CLOCK_Enable_SysOsc(true);
2482
2483 /* Enable power VD3 for PLLs */
2484 POWER_SetPLL();
2485
2486 /* Power on the VD5 for USB PHY */
2487 POWER_SetUsbPhy();
2488
2489 /* Power off USB PLL during setup changes */
2490 POWER_EnablePD(kPDRUNCFG_PD_USB_PLL);
2491
2492 /* Write USB PLL setup data */
2493 usbpllctrl = USB_PLL_NSEL_VAL_SET(nsel) | /* NSEL VALUE */
2494 USB_PLL_PSEL_VAL_SET(psel) | /* PSEL VALUE */
2495 USB_PLL_MSEL_VAL_SET(msel) | /* MSEL VALUE */
2496 (uint32_t)pllDirectInput << SYSCON_USBPLLCTRL_BYPASS_SHIFT | /* BYPASS DISABLE */
2497 (uint32_t)pllDirectOutput << SYSCON_USBPLLCTRL_DIRECT_SHIFT | /* DIRECTO DISABLE */
2498 (uint32_t)pllfbsel << SYSCON_USBPLLCTRL_FBSEL_SHIFT; /* FBSEL SELECT */
2499
2500 SYSCON->USBPLLCTRL = usbpllctrl;
2501
2502 POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);
2503
2504 /* Delay for 72 uSec @ 12Mhz for the usb pll to lock */
2505 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2506 if (false == pllDirectInput)
2507 {
2508 while (CLOCK_IsUsbPLLLocked() == false)
2509 {
2510 }
2511 }
2512 CLOCK_GetUsbPLLOutFromSetupUpdate(pSetup);
2513 return kStatus_PLL_Success;
2514 }
2515
2516 /* Set System PLL clock based on the input frequency and multiplier */
2517 /*! brief Set PLL output based on the multiplier and input frequency
2518 * param multiply_by : multiplier
2519 * param input_freq : Clock input frequency of the PLL
2520 * return Nothing
2521 * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
2522 * function does not disable or enable PLL power, wait for PLL lock,
2523 * or adjust system voltages. These must be done in the application.
2524 * The function will not alter any source clocks (ie, main systen clock)
2525 * that may use the PLL, so these should be setup prior to and after
2526 * exiting the function.
2527 */
CLOCK_SetupSystemPLLMult(uint32_t multiply_by,uint32_t input_freq)2528 void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq)
2529 {
2530 uint32_t cco_freq = input_freq * multiply_by;
2531 uint32_t pdec = 1U;
2532 uint32_t selr;
2533 uint32_t seli;
2534 uint32_t selp;
2535 uint32_t mdec, ndec;
2536
2537 uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO(1);
2538
2539 while (cco_freq < 275000000U)
2540 {
2541 multiply_by <<= 1U; /* double value in each iteration */
2542 pdec <<= 1U; /* correspondingly double pdec to cancel effect of double msel */
2543 cco_freq = input_freq * multiply_by;
2544 }
2545 selr = 0U;
2546 if (multiply_by < 60U)
2547 {
2548 seli = (multiply_by & 0x3cU) + 4U;
2549 selp = (multiply_by >> 1U) + 1U;
2550 }
2551 else
2552 {
2553 selp = 31U;
2554 if (multiply_by > 16384U)
2555 {
2556 seli = 1U;
2557 }
2558 else if (multiply_by > 8192U)
2559 {
2560 seli = 2U;
2561 }
2562 else if (multiply_by > 2048U)
2563 {
2564 seli = 4U;
2565 }
2566 else if (multiply_by >= 501U)
2567 {
2568 seli = 8U;
2569 }
2570 else
2571 {
2572 seli = 4U * (1024U / (multiply_by + 9U));
2573 }
2574 }
2575
2576 if (pdec > 1U)
2577 {
2578 directo = 0U; /* use post divider */
2579 pdec = pdec / 2U; /* Account for minus 1 encoding */
2580 /* Translate P value */
2581 switch (pdec)
2582 {
2583 case 1U:
2584 pdec = 0x62U; /* 1 * 2 */
2585 break;
2586 case 2U:
2587 pdec = 0x42U; /* 2 * 2 */
2588 break;
2589 case 4U:
2590 pdec = 0x02U; /* 4 * 2 */
2591 break;
2592 case 8U:
2593 pdec = 0x0bU; /* 8 * 2 */
2594 break;
2595 case 16U:
2596 pdec = 0x11U; /* 16 * 2 */
2597 break;
2598 case 32U:
2599 pdec = 0x08U; /* 32 * 2 */
2600 break;
2601 default:
2602 pdec = 0x08U;
2603 break;
2604 }
2605 }
2606
2607 mdec = PLL_MDEC_VAL_SET(pllEncodeM(multiply_by));
2608 ndec = 0x302U; /* pre divide by 1 (hardcoded) */
2609
2610 SYSCON->SYSPLLCTRL = directo | (selr << SYSCON_SYSPLLCTRL_SELR_SHIFT) | (seli << SYSCON_SYSPLLCTRL_SELI_SHIFT) |
2611 (selp << SYSCON_SYSPLLCTRL_SELP_SHIFT);
2612 SYSCON->SYSPLLPDEC = pdec | (1UL << 7U); /* set Pdec value and assert preq */
2613 SYSCON->SYSPLLNDEC = ndec | (1UL << 10U); /* set Pdec value and assert preq */
2614 SYSCON->SYSPLLMDEC = (1UL << 17U) | mdec; /* select non sscg MDEC value, assert mreq and select mdec value */
2615 }
2616
2617 /* Enable USB DEVICE FULL SPEED clock */
2618 /*! brief Enable USB Device FS clock.
2619 * param src : clock source
2620 * param freq: clock frequency
2621 * Enable USB Device Full Speed clock.
2622 */
CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src,uint32_t freq)2623 bool CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src, uint32_t freq)
2624 {
2625 bool ret = true;
2626
2627 CLOCK_DisableClock(kCLOCK_Usbd0);
2628
2629 if (kCLOCK_UsbSrcFro == src)
2630 {
2631 switch (freq)
2632 {
2633 case 96000000U:
2634 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2635 break;
2636
2637 case 48000000U:
2638 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
2639 break;
2640
2641 default:
2642 ret = false;
2643 break;
2644 }
2645 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
2646 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
2647 SYSCON_FROCTRL_USBCLKADJ_MASK;
2648 /* Select FRO 96 or 48 MHz */
2649 CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
2650 }
2651 else
2652 {
2653 /*Set the USB PLL as the Usb0 CLK*/
2654 POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);
2655
2656 usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};
2657
2658 (void)CLOCK_SetUsbPLLFreq(&pll_setup);
2659 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2660 CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK);
2661 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2662 }
2663 CLOCK_EnableClock(kCLOCK_Usbd0);
2664 CLOCK_EnableClock(kCLOCK_UsbRam1);
2665
2666 return ret;
2667 }
2668
2669 /* Enable USB HOST FULL SPEED clock */
2670 /*! brief Enable USB HOST FS clock.
2671 * param src : clock source
2672 * param freq: clock frequency
2673 * Enable USB HOST Full Speed clock.
2674 */
CLOCK_EnableUsbfs0HostClock(clock_usb_src_t src,uint32_t freq)2675 bool CLOCK_EnableUsbfs0HostClock(clock_usb_src_t src, uint32_t freq)
2676 {
2677 bool ret = true;
2678
2679 CLOCK_DisableClock(kCLOCK_Usbhmr0);
2680 CLOCK_DisableClock(kCLOCK_Usbhsl0);
2681
2682 if (kCLOCK_UsbSrcFro == src)
2683 {
2684 switch (freq)
2685 {
2686 case 96000000U:
2687 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2688 break;
2689
2690 case 48000000U:
2691 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
2692 break;
2693
2694 default:
2695 ret = false;
2696 break;
2697 }
2698 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
2699 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
2700 SYSCON_FROCTRL_USBCLKADJ_MASK;
2701 /* Select FRO 96 or 48 MHz */
2702 CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
2703 }
2704 else
2705 {
2706 /*Set the USB PLL as the Usb0 CLK*/
2707 POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);
2708
2709 usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};
2710
2711 (void)CLOCK_SetUsbPLLFreq(&pll_setup);
2712 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2713 CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK);
2714 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2715 }
2716 CLOCK_EnableClock(kCLOCK_Usbhmr0);
2717 CLOCK_EnableClock(kCLOCK_Usbhsl0);
2718 CLOCK_EnableClock(kCLOCK_UsbRam1);
2719
2720 return ret;
2721 }
2722
2723 /* Enable USB DEVICE HIGH SPEED clock */
2724 /*! brief Enable USB Device HS clock.
2725 * param src : clock source
2726 * param freq: clock frequency
2727 * Enable USB Device High Speed clock.
2728 */
CLOCK_EnableUsbhs0DeviceClock(clock_usb_src_t src,uint32_t freq)2729 bool CLOCK_EnableUsbhs0DeviceClock(clock_usb_src_t src, uint32_t freq)
2730 {
2731 bool ret = true;
2732 CLOCK_DisableClock(kCLOCK_Usbd1);
2733 /* Power on the VD5 for USB PHY */
2734 POWER_SetUsbPhy();
2735 if (kCLOCK_UsbSrcFro == src)
2736 {
2737 switch (freq)
2738 {
2739 case 96000000U:
2740 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2741 break;
2742
2743 case 48000000U:
2744 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
2745 break;
2746
2747 default:
2748 ret = false;
2749 break;
2750 }
2751 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
2752 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
2753 SYSCON_FROCTRL_USBCLKADJ_MASK;
2754 /* Select FRO 96 or 48 MHz */
2755 CLOCK_AttachClk(kFRO_HF_to_USB1_CLK);
2756 }
2757 else
2758 {
2759 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2760 usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};
2761
2762 (void)CLOCK_SetUsbPLLFreq(&pll_setup);
2763
2764 /* Select USB PLL output as USB clock src */
2765 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false);
2766 CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK);
2767 }
2768
2769 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2770 /* Enable USB1D and USB1RAM */
2771 CLOCK_EnableClock(kCLOCK_Usbd1);
2772 CLOCK_EnableClock(kCLOCK_UsbRam1);
2773 POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */
2774 return ret;
2775 }
2776
2777 /* Enable USB HOST HIGH SPEED clock */
2778 /*! brief Enable USB HOST HS clock.
2779 * param src : clock source
2780 * param freq: clock frequency
2781 * Enable USB HOST High Speed clock.
2782 */
CLOCK_EnableUsbhs0HostClock(clock_usb_src_t src,uint32_t freq)2783 bool CLOCK_EnableUsbhs0HostClock(clock_usb_src_t src, uint32_t freq)
2784 {
2785 bool ret = true;
2786 CLOCK_DisableClock(kCLOCK_Usbh1);
2787 /* Power on the VD5 for USB PHY */
2788 POWER_SetUsbPhy();
2789 if (kCLOCK_UsbSrcFro == src)
2790 {
2791 switch (freq)
2792 {
2793 case 96000000U:
2794 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2795 break;
2796
2797 case 48000000U:
2798 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
2799 break;
2800
2801 default:
2802 ret = false;
2803 break;
2804 }
2805 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
2806 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
2807 SYSCON_FROCTRL_USBCLKADJ_MASK;
2808 /* Select FRO 96 or 48 MHz */
2809 CLOCK_AttachClk(kFRO_HF_to_USB1_CLK);
2810 }
2811 else
2812 {
2813 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2814 usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};
2815
2816 (void)CLOCK_SetUsbPLLFreq(&pll_setup);
2817
2818 /* Select USB PLL output as USB clock src */
2819 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false);
2820 CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK);
2821 }
2822
2823 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2824 /* Enable USBh1 and USB1RAM */
2825 CLOCK_EnableClock(kCLOCK_Usbh1);
2826 CLOCK_EnableClock(kCLOCK_UsbRam1);
2827 POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */
2828 return ret;
2829 }
2830