1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016 - 2020 , 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 (item != 0U)
168 {
169 mux = (uint8_t)GET_ID_ITEM_MUX(item);
170 sel = (uint8_t)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 uint32_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 = (uint8_t)GET_ID_ITEM_MUX(tmp32);
214 if (tmp32 != 0UL)
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 assert(false);
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 assert(false);
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 assert(false);
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 assert(false);
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 assert(false);
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 assert(false);
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 assert(false);
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 assert(false);
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 assert(false);
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 ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ? 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 ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_WDT_OSC_MASK) != 0UL)
650 {
651 return 0U;
652 }
653 else
654 {
655 div_sel = (uint8_t)((SYSCON->WDTOSCCTRL & 0x1fUL) + 1UL) << 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 if (((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ||
669 ((SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK) == 0UL))
670 {
671 return 0U;
672 }
673
674 if ((SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK) != 0UL)
675 {
676 return 96000000U;
677 }
678 else
679 {
680 return 48000000U;
681 }
682 }
683
684 /* Get SYSTEM PLL Clk */
685 /*! brief Return Frequency of PLL
686 * return Frequency of PLL
687 */
CLOCK_GetPllOutFreq(void)688 uint32_t CLOCK_GetPllOutFreq(void)
689 {
690 return s_Pll_Freq;
691 }
692
693 /* Get AUDIO PLL Clk */
694 /*! brief Return Frequency of AUDIO PLL
695 * return Frequency of PLL
696 */
CLOCK_GetAudioPllOutFreq(void)697 uint32_t CLOCK_GetAudioPllOutFreq(void)
698 {
699 return s_Audio_Pll_Freq;
700 }
701
702 /* Get USB PLL Clk */
703 /*! brief Return Frequency of USB PLL
704 * return Frequency of PLL
705 */
CLOCK_GetUsbPllOutFreq(void)706 uint32_t CLOCK_GetUsbPllOutFreq(void)
707 {
708 return s_Usb_Pll_Freq;
709 }
710
711 /* Get RTC OSC Clk */
712 /*! brief Return Frequency of 32kHz osc
713 * return Frequency of 32kHz osc
714 */
CLOCK_GetOsc32KFreq(void)715 uint32_t CLOCK_GetOsc32KFreq(void)
716 {
717 return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */
718 }
719
720 /* Get MAIN Clk */
721 /*! brief Return Frequency of Core System
722 * return Frequency of Core System
723 */
CLOCK_GetCoreSysClkFreq(void)724 uint32_t CLOCK_GetCoreSysClkFreq(void)
725 {
726 uint32_t freq = 0U;
727
728 switch (SYSCON->MAINCLKSELB)
729 {
730 case 0U:
731 if (SYSCON->MAINCLKSELA == 0U)
732 {
733 freq = CLOCK_GetFro12MFreq();
734 }
735 else if (SYSCON->MAINCLKSELA == 1U)
736 {
737 freq = CLOCK_GetExtClkFreq();
738 }
739 else if (SYSCON->MAINCLKSELA == 2U)
740 {
741 freq = CLOCK_GetWdtOscFreq();
742 }
743 else if (SYSCON->MAINCLKSELA == 3U)
744 {
745 freq = CLOCK_GetFroHfFreq();
746 }
747 else
748 {
749 /* Misra Compliance. */
750 }
751 break;
752 case 2U:
753 freq = CLOCK_GetPllOutFreq();
754 break;
755
756 case 3U:
757 freq = CLOCK_GetOsc32KFreq();
758 break;
759
760 default:
761 assert(false);
762 break;
763 }
764
765 return freq;
766 }
767
768 /* Get I2S MCLK Clk */
769 /*! brief Return Frequency of I2S MCLK Clock
770 * return Frequency of I2S MCLK Clock
771 */
CLOCK_GetI2SMClkFreq(void)772 uint32_t CLOCK_GetI2SMClkFreq(void)
773 {
774 return s_I2S_Mclk_Freq;
775 }
776
777 /* Get ASYNC APB Clk */
778 /*! brief Return Frequency of Asynchronous APB Clock
779 * return Frequency of Asynchronous APB Clock Clock
780 */
CLOCK_GetAsyncApbClkFreq(void)781 uint32_t CLOCK_GetAsyncApbClkFreq(void)
782 {
783 async_clock_src_t clkSrc;
784 uint32_t clkRate;
785
786 clkSrc = CLOCK_GetAsyncApbClkSrc();
787
788 switch (clkSrc)
789 {
790 case kCLOCK_AsyncMainClk:
791 clkRate = CLOCK_GetCoreSysClkFreq();
792 break;
793 case kCLOCK_AsyncFro12Mhz:
794 clkRate = CLK_FRO_12MHZ;
795 break;
796 default:
797 clkRate = 0U;
798 break;
799 }
800
801 return clkRate;
802 }
803
804 /* Get MCAN Clk */
805 /*! brief Return Frequency of MCAN Clock
806 * param MCanSel : 0U: MCAN0; 1U: MCAN1
807 * return Frequency of MCAN Clock
808 */
CLOCK_GetMCanClkFreq(uint32_t MCanSel)809 uint32_t CLOCK_GetMCanClkFreq(uint32_t MCanSel)
810 {
811 uint32_t freq = 0U;
812 switch (MCanSel)
813 {
814 case 0U:
815 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN0CLKDIV & 0xffU) + 1U);
816 break;
817 case 1U:
818 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN1CLKDIV & 0xffU) + 1U);
819 break;
820
821 default:
822 assert(false);
823 break;
824 }
825
826 return freq;
827 }
828
829 /* Get FLEXCOMM Clk */
830 /*! brief Return Frequency of Flexcomm functional Clock
831 * return Frequency of Flexcomm functional Clock
832 */
CLOCK_GetFlexCommClkFreq(uint32_t id)833 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
834 {
835 uint32_t freq = 0U;
836
837 switch (SYSCON->FCLKSEL[id])
838 {
839 case 0U:
840 freq = CLOCK_GetFro12MFreq();
841 break;
842 case 1U:
843 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFCLKDIV & SYSCON_FROHFCLKDIV_DIV_MASK) + 1U);
844 break;
845 case 2U:
846 freq = CLOCK_GetPllOutFreq();
847 break;
848 case 3U:
849 freq = CLOCK_GetI2SMClkFreq();
850 break;
851 case 4U:
852 freq = CLOCK_GetFrgClkFreq();
853 break;
854
855 default:
856 assert(false);
857 break;
858 }
859
860 return freq;
861 }
862
863 /* Get FRG Clk */
864 /*! brief Return Frequency of FRG input clock
865 * return Frequency value
866 */
CLOCK_GetFRGInputClock(void)867 uint32_t CLOCK_GetFRGInputClock(void)
868 {
869 uint32_t freq = 0U;
870
871 switch (SYSCON->FRGCLKSEL)
872 {
873 case 0U:
874 freq = CLOCK_GetCoreSysClkFreq();
875 break;
876 case 1U:
877 freq = CLOCK_GetPllOutFreq();
878 break;
879 case 2U:
880 freq = CLOCK_GetFro12MFreq();
881 break;
882 case 3U:
883 freq = CLOCK_GetFroHfFreq();
884 break;
885
886 default:
887 assert(false);
888 break;
889 }
890
891 return freq;
892 }
893
894 /* Get FRG Clk */
895 /*! brief Return Frequency of frg
896 * return Frequency of FRG
897 */
CLOCK_GetFrgClkFreq(void)898 uint32_t CLOCK_GetFrgClkFreq(void)
899 {
900 uint32_t freq = 0UL;
901
902 if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK)
903 {
904 freq = (uint32_t)((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1UL)) /
905 ((SYSCON_FRGCTRL_DIV_MASK + 1UL) +
906 ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT));
907 }
908 else
909 {
910 freq = 0UL;
911 }
912
913 return freq;
914 }
915
916 /* Get DMIC Clk */
917 /*! brief Return Frequency of dmic
918 * return Frequency of DMIC
919 */
CLOCK_GetDmicClkFreq(void)920 uint32_t CLOCK_GetDmicClkFreq(void)
921 {
922 uint32_t freq = 0UL;
923
924 switch (SYSCON->DMICCLKSEL)
925 {
926 case 0U:
927 freq = CLOCK_GetFro12MFreq();
928 break;
929 case 1U:
930 freq = CLOCK_GetFroHfFreq();
931 break;
932 case 2U:
933 freq = CLOCK_GetPllOutFreq();
934 break;
935 case 3U:
936 freq = CLOCK_GetI2SMClkFreq();
937 break;
938 case 4U:
939 freq = CLOCK_GetCoreSysClkFreq();
940 break;
941 case 5U:
942 freq = CLOCK_GetWdtOscFreq();
943 break;
944 default:
945 assert(false);
946 break;
947 }
948
949 return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U);
950 }
951
952 /* Set FRG Clk */
953 /**
954 * brief Set the frg output frequency.
955 * param freq : output frequency
956 * return 0 : the frequency range is out of range.
957 * 1 : switch successfully.
958 */
CLOCK_SetFRGClock(uint32_t freq)959 uint32_t CLOCK_SetFRGClock(uint32_t freq)
960 {
961 assert(freq);
962
963 uint32_t input = CLOCK_GetFRGInputClock();
964 uint32_t mul;
965
966 if ((freq > 48000000UL) || (freq > input) || (input / freq >= 2UL))
967 {
968 /* FRG output frequency should be less than equal to 48MHz */
969 return 0UL;
970 }
971 else
972 {
973 mul = ((input - freq) * 256UL) / freq;
974 SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK;
975 return 1UL;
976 }
977 }
978
979 /* Set IP Clk */
980 /*! brief Return Frequency of selected clock
981 * return Frequency of selected clock
982 */
CLOCK_GetFreq(clock_name_t clockName)983 uint32_t CLOCK_GetFreq(clock_name_t clockName)
984 {
985 uint32_t freq;
986 switch (clockName)
987 {
988 case kCLOCK_CoreSysClk:
989 freq = CLOCK_GetCoreSysClkFreq();
990 break;
991 case kCLOCK_BusClk:
992 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
993 break;
994 case kCLOCK_ClockOut:
995 freq = CLOCK_GetClockOutClkFreq();
996 break;
997 case kCLOCK_Mclk:
998 freq = CLOCK_GetMclkClkFreq();
999 break;
1000 case kCLOCK_FroHf:
1001 freq = CLOCK_GetFroHfFreq();
1002 break;
1003 case kCLOCK_Fro12M:
1004 freq = CLOCK_GetFro12MFreq();
1005 break;
1006 case kCLOCK_ExtClk:
1007 freq = CLOCK_GetExtClkFreq();
1008 break;
1009 case kCLOCK_PllOut:
1010 freq = CLOCK_GetPllOutFreq();
1011 break;
1012 case kCLOCK_WdtOsc:
1013 freq = CLOCK_GetWdtOscFreq();
1014 break;
1015 case kCLOCK_Frg:
1016 freq = CLOCK_GetFrgClkFreq();
1017 break;
1018 case kCLOCK_AsyncApbClk:
1019 freq = CLOCK_GetAsyncApbClkFreq();
1020 break;
1021 case kCLOCK_FlexI2S:
1022 freq = CLOCK_GetI2SMClkFreq();
1023 break;
1024 default:
1025 freq = 0U;
1026 break;
1027 }
1028
1029 return freq;
1030 }
1031
1032 /* Set the FLASH wait states for the passed frequency */
1033 /**
1034 * brief Set the flash wait states for the input freuqency.
1035 * param iFreq : Input frequency
1036 * return Nothing
1037 */
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)1038 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)
1039 {
1040 if (iFreq <= 12000000U)
1041 {
1042 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash1Cycle);
1043 }
1044 else if (iFreq <= 24000000U)
1045 {
1046 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash2Cycle);
1047 }
1048 else if (iFreq <= 36000000U)
1049 {
1050 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash3Cycle);
1051 }
1052 else if (iFreq <= 60000000U)
1053 {
1054 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash4Cycle);
1055 }
1056 else if (iFreq <= 96000000U)
1057 {
1058 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash5Cycle);
1059 }
1060 else if (iFreq <= 120000000U)
1061 {
1062 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash6Cycle);
1063 }
1064 else if (iFreq <= 144000000U)
1065 {
1066 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash7Cycle);
1067 }
1068 /* At 220 MHz the system clock/access time can be lower when compared to 180 MHz because the power library optimizes
1069 * the on-chip voltage regulator */
1070 else if ((iFreq <= 168000000U) || ((iFreq > 180000000U) && (iFreq <= 220000000U)))
1071 {
1072 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash8Cycle);
1073 }
1074 else
1075 {
1076 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash9Cycle);
1077 }
1078 }
1079
1080 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
pllEncodeN(uint32_t N)1081 static uint32_t pllEncodeN(uint32_t N)
1082 {
1083 uint32_t x, i;
1084
1085 /* Find NDec */
1086 switch (N)
1087 {
1088 case 0U:
1089 x = 0x3FFU;
1090 break;
1091
1092 case 1U:
1093 x = 0x302U;
1094 break;
1095
1096 case 2U:
1097 x = 0x202U;
1098 break;
1099
1100 default:
1101 x = 0x080U;
1102 for (i = N; i <= NVALMAX; i++)
1103 {
1104 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
1105 }
1106 break;
1107 }
1108
1109 return x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P);
1110 }
1111
1112 /* Find decoded N value for raw NDEC value */
pllDecodeN(uint32_t NDEC)1113 static uint32_t pllDecodeN(uint32_t NDEC)
1114 {
1115 uint32_t n, x, i;
1116
1117 /* Find NDec */
1118 switch (NDEC)
1119 {
1120 case 0x3FFU:
1121 n = 0U;
1122 break;
1123
1124 case 0x302U:
1125 n = 1U;
1126 break;
1127
1128 case 0x202U:
1129 n = 2U;
1130 break;
1131
1132 default:
1133 x = 0x080U;
1134 n = 0xFFFFFFFFU;
1135 for (i = NVALMAX; i >= 3U; i--)
1136 {
1137 if (n != 0xFFFFFFFFUL)
1138 {
1139 break;
1140 }
1141 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
1142 if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)
1143 {
1144 /* Decoded value of NDEC */
1145 n = i;
1146 }
1147 }
1148 break;
1149 }
1150
1151 return n;
1152 }
1153
1154 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
pllEncodeP(uint32_t P)1155 static uint32_t pllEncodeP(uint32_t P)
1156 {
1157 uint32_t x, i;
1158
1159 /* Find PDec */
1160 switch (P)
1161 {
1162 case 0U:
1163 x = 0x7FU;
1164 break;
1165
1166 case 1U:
1167 x = 0x62U;
1168 break;
1169
1170 case 2U:
1171 x = 0x42U;
1172 break;
1173
1174 default:
1175 x = 0x10U;
1176 for (i = P; i <= PVALMAX; i++)
1177 {
1178 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
1179 }
1180 break;
1181 }
1182
1183 return x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P);
1184 }
1185
1186 /* Find decoded P value for raw PDEC value */
pllDecodeP(uint32_t PDEC)1187 static uint32_t pllDecodeP(uint32_t PDEC)
1188 {
1189 uint32_t p, x, i;
1190
1191 /* Find PDec */
1192 switch (PDEC)
1193 {
1194 case 0x7FU:
1195 p = 0U;
1196 break;
1197
1198 case 0x62U:
1199 p = 1U;
1200 break;
1201
1202 case 0x42U:
1203 p = 2U;
1204 break;
1205
1206 default:
1207 x = 0x10U;
1208 p = 0xFFFFFFFFU;
1209 for (i = PVALMAX; i >= 3U; i--)
1210 {
1211 if (p != 0XFFFFFFFFUL)
1212 {
1213 break;
1214 }
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 }
1222 }
1223 break;
1224 }
1225
1226 return p;
1227 }
1228
1229 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
pllEncodeM(uint32_t M)1230 static uint32_t pllEncodeM(uint32_t M)
1231 {
1232 uint32_t i, x;
1233
1234 /* Find MDec */
1235 switch (M)
1236 {
1237 case 0U:
1238 x = 0x1FFFFU;
1239 break;
1240
1241 case 1U:
1242 x = 0x18003U;
1243 break;
1244
1245 case 2U:
1246 x = 0x10003U;
1247 break;
1248
1249 default:
1250 x = 0x04000U;
1251 for (i = M; i <= MVALMAX; i++)
1252 {
1253 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
1254 }
1255 break;
1256 }
1257
1258 return x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P);
1259 }
1260
1261 /* Find decoded M value for raw MDEC value */
pllDecodeM(uint32_t MDEC)1262 static uint32_t pllDecodeM(uint32_t MDEC)
1263 {
1264 uint32_t m, i, x;
1265
1266 /* Find MDec */
1267 switch (MDEC)
1268 {
1269 case 0x1FFFFU:
1270 m = 0U;
1271 break;
1272
1273 case 0x18003U:
1274 m = 1U;
1275 break;
1276
1277 case 0x10003U:
1278 m = 2U;
1279 break;
1280
1281 default:
1282 x = 0x04000U;
1283 m = 0xFFFFFFFFU;
1284 for (i = MVALMAX; i >= 3U; i--)
1285 {
1286 if (m != 0xFFFFFFFFUL)
1287 {
1288 break;
1289 }
1290 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
1291 if ((x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P)) == MDEC)
1292 {
1293 /* Decoded value of MDEC */
1294 m = i;
1295 }
1296 }
1297 break;
1298 }
1299
1300 return m;
1301 }
1302
1303 /* 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)1304 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
1305 {
1306 /* bandwidth: compute selP from Multiplier */
1307 if (M < 60U)
1308 {
1309 *pSelP = (M >> 1U) + 1U;
1310 }
1311 else
1312 {
1313 *pSelP = PVALMAX - 1U;
1314 }
1315
1316 /* bandwidth: compute selI from Multiplier */
1317 if (M > 16384U)
1318 {
1319 *pSelI = 1U;
1320 }
1321 else if (M > 8192U)
1322 {
1323 *pSelI = 2U;
1324 }
1325 else if (M > 2048U)
1326 {
1327 *pSelI = 4U;
1328 }
1329 else if (M >= 501U)
1330 {
1331 *pSelI = 8U;
1332 }
1333 else if (M >= 60U)
1334 {
1335 *pSelI = 4U * (1024U / (M + 9U));
1336 }
1337 else
1338 {
1339 *pSelI = (M & 0x3CU) + 4U;
1340 }
1341
1342 if (*pSelI > ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT))
1343 {
1344 *pSelI = ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT);
1345 }
1346
1347 *pSelR = 0U;
1348 }
1349
1350 /* Get predivider (N) from PLL NDEC setting */
findPllPreDiv(uint32_t ctrlReg,uint32_t nDecReg)1351 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)
1352 {
1353 uint32_t preDiv = 1;
1354
1355 /* Direct input is not used? */
1356 if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT)) == 0U)
1357 {
1358 /* Decode NDEC value to get (N) pre divider */
1359 preDiv = pllDecodeN(nDecReg & 0x3FFU);
1360 if (preDiv == 0U)
1361 {
1362 preDiv = 1U;
1363 }
1364 }
1365
1366 /* Adjusted by 1, directi is used to bypass */
1367 return preDiv;
1368 }
1369
1370 /* Get postdivider (P) from PLL PDEC setting */
findPllPostDiv(uint32_t ctrlReg,uint32_t pDecReg)1371 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)
1372 {
1373 uint32_t postDiv = 1U;
1374
1375 /* Direct input is not used? */
1376 if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U)
1377 {
1378 /* Decode PDEC value to get (P) post divider */
1379 postDiv = 2U * pllDecodeP(pDecReg & 0x7FU);
1380 if (postDiv == 0U)
1381 {
1382 postDiv = 2U;
1383 }
1384 }
1385
1386 /* Adjusted by 1, directo is used to bypass */
1387 return postDiv;
1388 }
1389
1390 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
findPllMMult(uint32_t ctrlReg,uint32_t mDecReg)1391 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)
1392 {
1393 uint32_t mMult = 1U;
1394
1395 /* Decode MDEC value to get (M) multiplier */
1396 mMult = pllDecodeM(mDecReg & 0x1FFFFU);
1397
1398 if (mMult == 0U)
1399 {
1400 mMult = 1U;
1401 }
1402
1403 return mMult;
1404 }
1405
1406 /* Convert the binary to fractional part */
Binary2Fractional(uint32_t binaryPart)1407 static double Binary2Fractional(uint32_t binaryPart)
1408 {
1409 double fractional = 0.0;
1410 for (uint32_t i = 0; i <= 14UL; i++)
1411 {
1412 fractional += (double)(uint32_t)((binaryPart >> i) & 0x1UL) / (double)(uint32_t)(1UL << (15U - i));
1413 }
1414 return fractional;
1415 }
1416
1417 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1418 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1419 {
1420 uint32_t tmp32;
1421
1422 while (n != 0U)
1423 {
1424 tmp32 = n;
1425 n = m % n;
1426 m = tmp32;
1427 }
1428
1429 return m;
1430 }
1431
1432 /*
1433 * Set PLL output based on desired output rate.
1434 * In this function, the it calculates the PLL setting for output frequency from input clock
1435 * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1436 * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1437 */
CLOCK_GetPllConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup)1438 static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)
1439 {
1440 uint32_t nDivOutHz, fccoHz, multFccoDiv;
1441 uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1442 uint32_t pllDirectInput, pllDirectOutput;
1443 uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1444
1445 /* Baseline parameters (no input or output dividers) */
1446 pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */
1447 pllPostDivider = 0U; /* 0 implies post-divider will be disabled */
1448 pllDirectOutput = 1U;
1449 multFccoDiv = 2U;
1450
1451 /* Verify output rate parameter */
1452 if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1453 {
1454 /* Maximum PLL output with post divider=1 cannot go above this frequency */
1455 return kStatus_PLL_OutputTooHigh;
1456 }
1457 if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1458 {
1459 /* Minmum PLL output with maximum post divider cannot go below this frequency */
1460 return kStatus_PLL_OutputTooLow;
1461 }
1462
1463 /* Verify input rate parameter */
1464 if (finHz < PLL_LOWER_IN_LIMIT)
1465 {
1466 /* Input clock into the PLL cannot be lower than this */
1467 return kStatus_PLL_InputTooLow;
1468 }
1469
1470 /* Find the optimal CCO frequency for the output and input that
1471 will keep it inside the PLL CCO range. This may require
1472 tweaking the post-divider for the PLL. */
1473 fccoHz = foutHz;
1474 while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1475 {
1476 /* CCO output is less than minimum CCO range, so the CCO output
1477 needs to be bumped up and the post-divider is used to bring
1478 the PLL output back down. */
1479 pllPostDivider++;
1480 if (pllPostDivider > PVALMAX)
1481 {
1482 return kStatus_PLL_OutsideIntLimit;
1483 }
1484
1485 /* Target CCO goes up, PLL output goes down */
1486 fccoHz = foutHz * (pllPostDivider * 2U);
1487 pllDirectOutput = 0U;
1488 }
1489
1490 /* Determine if a pre-divider is needed to get the best frequency */
1491 if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz))
1492 {
1493 uint32_t a = FindGreatestCommonDivisor(fccoHz, (multFccoDiv * finHz));
1494
1495 if (a > 20000U)
1496 {
1497 a = (multFccoDiv * finHz) / a;
1498 if ((a != 0U) && (a < PLL_MAX_N_DIV))
1499 {
1500 pllPreDivider = a;
1501 }
1502 }
1503 }
1504
1505 /* Bypass pre-divider hardware if pre-divider is 1 */
1506 if (pllPreDivider > 1U)
1507 {
1508 pllDirectInput = 0U;
1509 }
1510 else
1511 {
1512 pllDirectInput = 1U;
1513 }
1514
1515 /* Determine PLL multipler */
1516 nDivOutHz = (finHz / pllPreDivider);
1517 pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv;
1518
1519 /* Find optimal values for filter */
1520 /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1521 if ((nDivOutHz * ((multFccoDiv * pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1522 {
1523 pllMultiplier++;
1524 }
1525
1526 /* Setup filtering */
1527 pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1528 uplimoff = 0U;
1529
1530 /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1531 pSetup->pllmdec = PLL_MDEC_VAL_SET(pllEncodeM(pllMultiplier));
1532
1533 /* Get encoded values for N (prediv) and P (postdiv) */
1534 pSetup->pllndec = PLL_NDEC_VAL_SET(pllEncodeN(pllPreDivider));
1535 pSetup->pllpdec = PLL_PDEC_VAL_SET(pllEncodeP(pllPostDivider));
1536
1537 /* PLL control */
1538 pSetup->pllctrl = (pllSelR << SYSCON_SYSPLLCTRL_SELR_SHIFT) | /* Filter coefficient */
1539 (pllSelI << SYSCON_SYSPLLCTRL_SELI_SHIFT) | /* Filter coefficient */
1540 (pllSelP << SYSCON_SYSPLLCTRL_SELP_SHIFT) | /* Filter coefficient */
1541 (0UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT) | /* PLL bypass mode disabled */
1542 (uplimoff << SYSCON_SYSPLLCTRL_UPLIMOFF_SHIFT) | /* SS/fractional mode disabled */
1543 (pllDirectInput << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT) | /* Bypass pre-divider? */
1544 (pllDirectOutput << SYSCON_SYSPLLCTRL_DIRECTO_SHIFT); /* Bypass post-divider? */
1545
1546 return kStatus_PLL_Success;
1547 }
1548
1549 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1550 /* Alloct the static buffer for cache. */
1551 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1552 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1553 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1554 static uint32_t s_PllSetupCacheIdx = 0U;
1555 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1556
1557 /*
1558 * Calculate the PLL setting values from input clock freq to output freq.
1559 */
CLOCK_GetPllConfig(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup)1560 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)
1561 {
1562 pll_error_t retErr;
1563 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1564 uint32_t i;
1565
1566 for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1567 {
1568 if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]))
1569 {
1570 /* Hit the target in cache buffer. */
1571 pSetup->pllctrl = s_PllSetupCacheStruct[i].pllctrl;
1572 pSetup->pllndec = s_PllSetupCacheStruct[i].pllndec;
1573 pSetup->pllpdec = s_PllSetupCacheStruct[i].pllpdec;
1574 pSetup->pllmdec = s_PllSetupCacheStruct[i].pllmdec;
1575 retErr = kStatus_PLL_Success;
1576 break;
1577 }
1578 }
1579
1580 if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1581 {
1582 return retErr;
1583 }
1584 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1585
1586 /* No cache or did not hit the cache. */
1587 retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup);
1588
1589 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1590 if (kStatus_PLL_Success == retErr)
1591 {
1592 /* Cache the most recent calulation result into buffer. */
1593 s_FinHzCache[s_PllSetupCacheIdx] = finHz;
1594 s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1595
1596 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl = pSetup->pllctrl;
1597 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec = pSetup->pllndec;
1598 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec = pSetup->pllpdec;
1599 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllmdec = pSetup->pllmdec;
1600 /* Update the index for next available buffer. */
1601 s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1602 }
1603 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1604
1605 return retErr;
1606 }
1607
1608 /* Update SYSTEM PLL rate variable */
CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t * pSetup)1609 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup)
1610 {
1611 s_Pll_Freq = CLOCK_GetSystemPLLOutFromSetup(pSetup);
1612 }
1613
1614 /* Update AUDIO PLL rate variable */
CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t * pSetup)1615 static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup)
1616 {
1617 s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromSetup(pSetup);
1618 }
1619
1620 /* Update AUDIO Fractional PLL rate variable */
CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t * pSetup)1621 static void CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t *pSetup)
1622 {
1623 s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromFractSetup(pSetup);
1624 }
1625
1626 /* Update USB PLL rate variable */
CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t * pSetup)1627 static void CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t *pSetup)
1628 {
1629 s_Usb_Pll_Freq = CLOCK_GetUsbPLLOutFromSetup(pSetup);
1630 }
1631
1632 /* Return System PLL input clock rate */
1633 /*! brief Return System PLL input clock rate
1634 * return System PLL input clock rate
1635 */
CLOCK_GetSystemPLLInClockRate(void)1636 uint32_t CLOCK_GetSystemPLLInClockRate(void)
1637 {
1638 uint32_t clkRate = 0U;
1639
1640 switch ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK))
1641 {
1642 case 0x00U:
1643 clkRate = CLK_FRO_12MHZ;
1644 break;
1645
1646 case 0x01U:
1647 clkRate = CLOCK_GetExtClkFreq();
1648 break;
1649
1650 case 0x02U:
1651 clkRate = CLOCK_GetWdtOscFreq();
1652 break;
1653
1654 case 0x03U:
1655 clkRate = CLOCK_GetOsc32KFreq();
1656 break;
1657
1658 default:
1659 clkRate = 0U;
1660 break;
1661 }
1662
1663 return clkRate;
1664 }
1665
1666 /* Return Audio PLL input clock rate */
1667 /*! brief Return Audio PLL input clock rate
1668 * return Audio PLL input clock rate
1669 */
CLOCK_GetAudioPLLInClockRate(void)1670 uint32_t CLOCK_GetAudioPLLInClockRate(void)
1671 {
1672 uint32_t clkRate = 0U;
1673
1674 switch ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK))
1675 {
1676 case 0x00U:
1677 clkRate = CLK_FRO_12MHZ;
1678 break;
1679
1680 case 0x01U:
1681 clkRate = CLOCK_GetExtClkFreq();
1682 break;
1683
1684 default:
1685 clkRate = 0U;
1686 break;
1687 }
1688
1689 return clkRate;
1690 }
1691
1692 /* Return System PLL output clock rate from setup structure */
1693 /*! brief Return System PLL output clock rate from setup structure
1694 * param pSetup : Pointer to a PLL setup structure
1695 * return System PLL output clock rate the setup structure will generate
1696 */
CLOCK_GetSystemPLLOutFromSetup(pll_setup_t * pSetup)1697 uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup)
1698 {
1699 uint32_t prediv, postdiv, mMult, inPllRate;
1700 uint64_t workRate;
1701
1702 inPllRate = CLOCK_GetSystemPLLInClockRate();
1703 /* If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock*/
1704 if ((pSetup->pllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U)
1705 {
1706 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1707 /*
1708 * 1. Pre-divider
1709 * Pre-divider is only available when the DIRECTI is disabled.
1710 */
1711 if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK))
1712 {
1713 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1714 }
1715 else
1716 {
1717 prediv = 1U; /* The pre-divider is bypassed. */
1718 }
1719 /*
1720 * 2. Post-divider
1721 * Post-divider is only available when the DIRECTO is disabled.
1722 */
1723 if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK))
1724 {
1725 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1726 }
1727 else
1728 {
1729 postdiv = 1U; /* The post-divider is bypassed. */
1730 }
1731 /* Adjust input clock */
1732 inPllRate = inPllRate / prediv;
1733
1734 /* MDEC used for rate */
1735 mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);
1736 workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1737
1738 workRate = workRate / ((uint64_t)postdiv);
1739 workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/
1740 }
1741 else
1742 {
1743 /* In bypass mode */
1744 workRate = (uint64_t)inPllRate;
1745 }
1746
1747 return (uint32_t)workRate;
1748 }
1749
1750 /* Return Usb PLL output clock rate from setup structure */
1751 /*! brief Return System USB PLL output clock rate from setup structure
1752 * param pSetup : Pointer to a PLL setup structure
1753 * return System PLL output clock rate the setup structure will generate
1754 */
CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t * pSetup)1755 uint32_t CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t *pSetup)
1756 {
1757 uint32_t nsel, psel, msel, inPllRate;
1758 uint64_t workRate;
1759 inPllRate = CLOCK_GetExtClkFreq();
1760 msel = pSetup->msel;
1761 psel = pSetup->psel;
1762 nsel = pSetup->nsel;
1763
1764 if (pSetup->fbsel)
1765 {
1766 /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */
1767 workRate = (inPllRate) * (msel + 1ULL) / (nsel + 1ULL);
1768 }
1769 else
1770 {
1771 /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */
1772 workRate = (inPllRate / (nsel + 1ULL)) * (msel + 1ULL) / (2ULL * (1ULL << (psel & 3ULL)));
1773 }
1774
1775 return (uint32_t)workRate;
1776 }
1777
1778 /* Return Audio PLL output clock rate from setup structure */
1779 /*! brief Return System AUDIO PLL output clock rate from setup structure
1780 * param pSetup : Pointer to a PLL setup structure
1781 * return System PLL output clock rate the setup structure will generate
1782 */
CLOCK_GetAudioPLLOutFromSetup(pll_setup_t * pSetup)1783 uint32_t CLOCK_GetAudioPLLOutFromSetup(pll_setup_t *pSetup)
1784 {
1785 uint32_t prediv, postdiv, mMult, inPllRate;
1786 uint64_t workRate;
1787
1788 inPllRate = CLOCK_GetAudioPLLInClockRate();
1789 if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)
1790 {
1791 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1792 /*
1793 * 1. Pre-divider
1794 * Pre-divider is only available when the DIRECTI is disabled.
1795 */
1796 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))
1797 {
1798 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1799 }
1800 else
1801 {
1802 prediv = 1U; /* The pre-divider is bypassed. */
1803 }
1804 /*
1805 * 2. Post-divider
1806 * Post-divider is only available when the DIRECTO is disabled.
1807 */
1808 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))
1809 {
1810 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1811 }
1812 else
1813 {
1814 postdiv = 1U; /* The post-divider is bypassed. */
1815 }
1816 /* Adjust input clock */
1817 inPllRate = inPllRate / prediv;
1818
1819 /* MDEC used for rate */
1820 mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);
1821 workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1822
1823 workRate = workRate / ((uint64_t)postdiv);
1824 workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/
1825 }
1826 else
1827 {
1828 /* In bypass mode */
1829 workRate = (uint64_t)inPllRate;
1830 }
1831
1832 return (uint32_t)workRate;
1833 }
1834
1835 /* Return Audio PLL output clock rate from audio fractioanl setup structure */
1836 /*! brief Return System AUDIO PLL output clock rate from audio fractioanl setup structure
1837 * param pSetup : Pointer to a PLL setup structure
1838 * return System PLL output clock rate the setup structure will generate
1839 */
CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t * pSetup)1840 uint32_t CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t *pSetup)
1841 {
1842 uint32_t prediv, postdiv, inPllRate;
1843 double workRate, mMultFactional;
1844
1845 inPllRate = CLOCK_GetAudioPLLInClockRate();
1846 if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)
1847 {
1848 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1849 /*
1850 * 1. Pre-divider
1851 * Pre-divider is only available when the DIRECTI is disabled.
1852 */
1853 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))
1854 {
1855 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1856 }
1857 else
1858 {
1859 prediv = 1U; /* The pre-divider is bypassed. */
1860 }
1861 /*
1862 * 2. Post-divider
1863 * Post-divider is only available when the DIRECTO is disabled.
1864 */
1865 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))
1866 {
1867 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1868 }
1869 else
1870 {
1871 postdiv = 1U; /* The post-divider is bypassed. */
1872 }
1873 /* Adjust input clock */
1874 inPllRate = inPllRate / prediv;
1875
1876 mMultFactional = (double)(uint32_t)(pSetup->audpllfrac >> 15U) +
1877 (double)(uint32_t)Binary2Fractional(pSetup->audpllfrac & 0x7FFFU);
1878 workRate = (double)inPllRate * (double)mMultFactional;
1879
1880 workRate = workRate / ((double)postdiv);
1881 workRate = workRate * 2.0; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/
1882 }
1883 else
1884 {
1885 /* In bypass mode */
1886 workRate = (double)inPllRate;
1887 }
1888
1889 return (uint32_t)workRate;
1890 }
1891
1892 /* Set the current PLL Rate */
1893 /*! brief Store the current PLL rate
1894 * param rate: Current rate of the PLL
1895 * return Nothing
1896 **/
CLOCK_SetStoredPLLClockRate(uint32_t rate)1897 void CLOCK_SetStoredPLLClockRate(uint32_t rate)
1898 {
1899 s_Pll_Freq = rate;
1900 }
1901
1902 /* Set the current Audio PLL Rate */
1903 /*! brief Store the current AUDIO PLL rate
1904 * param rate: Current rate of the PLL
1905 * return Nothing
1906 **/
CLOCK_SetStoredAudioPLLClockRate(uint32_t rate)1907 void CLOCK_SetStoredAudioPLLClockRate(uint32_t rate)
1908 {
1909 s_Audio_Pll_Freq = rate;
1910 }
1911
1912 /* Set the current Usb PLL Rate */
1913 /*! brief Set USB PLL output frequency
1914 * param rate : frequency value
1915 *
1916 */
CLOCK_SetStoredUsbPLLClockRate(uint32_t rate)1917 void CLOCK_SetStoredUsbPLLClockRate(uint32_t rate)
1918 {
1919 s_Usb_Pll_Freq = rate;
1920 }
1921
1922 /* Return System PLL output clock rate */
1923 /*! brief Return System PLL output clock rate
1924 * param recompute : Forces a PLL rate recomputation if true
1925 * return System PLL output clock rate
1926 * note The PLL rate is cached in the driver in a variable as
1927 * the rate computation function can take some time to perform. It
1928 * is recommended to use 'false' with the 'recompute' parameter.
1929 */
CLOCK_GetSystemPLLOutClockRate(bool recompute)1930 uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute)
1931 {
1932 pll_setup_t Setup;
1933 uint32_t rate;
1934
1935 if ((recompute) || (s_Pll_Freq == 0U))
1936 {
1937 Setup.pllctrl = SYSCON->SYSPLLCTRL;
1938 Setup.pllndec = SYSCON->SYSPLLNDEC;
1939 Setup.pllpdec = SYSCON->SYSPLLPDEC;
1940 Setup.pllmdec = SYSCON->SYSPLLMDEC;
1941
1942 CLOCK_GetSystemPLLOutFromSetupUpdate(&Setup);
1943 }
1944
1945 rate = s_Pll_Freq;
1946
1947 return rate;
1948 }
1949
1950 /* Return AUDIO PLL output clock rate */
1951 /*! brief Return System AUDIO PLL output clock rate
1952 * param recompute : Forces a AUDIO PLL rate recomputation if true
1953 * return System AUDIO PLL output clock rate
1954 * note The AUDIO PLL rate is cached in the driver in a variable as
1955 * the rate computation function can take some time to perform. It
1956 * is recommended to use 'false' with the 'recompute' parameter.
1957 */
CLOCK_GetAudioPLLOutClockRate(bool recompute)1958 uint32_t CLOCK_GetAudioPLLOutClockRate(bool recompute)
1959 {
1960 pll_setup_t Setup;
1961 uint32_t rate;
1962
1963 if ((recompute) || (s_Audio_Pll_Freq == 0U))
1964 {
1965 Setup.pllctrl = SYSCON->AUDPLLCTRL;
1966 Setup.pllndec = SYSCON->AUDPLLNDEC;
1967 Setup.pllpdec = SYSCON->AUDPLLPDEC;
1968 Setup.pllmdec = SYSCON->AUDPLLMDEC;
1969
1970 CLOCK_GetAudioPLLOutFromSetupUpdate(&Setup);
1971 }
1972
1973 rate = s_Audio_Pll_Freq;
1974 return rate;
1975 }
1976
1977 /* Return USB PLL output clock rate */
1978 /*! brief Return System USB PLL output clock rate
1979 * param recompute : Forces a USB PLL rate recomputation if true
1980 * return System USB PLL output clock rate
1981 * note The USB PLL rate is cached in the driver in a variable as
1982 * the rate computation function can take some time to perform. It
1983 * is recommended to use 'false' with the 'recompute' parameter.
1984 */
CLOCK_GetUsbPLLOutClockRate(bool recompute)1985 uint32_t CLOCK_GetUsbPLLOutClockRate(bool recompute)
1986 {
1987 usb_pll_setup_t Setup;
1988 uint32_t rate;
1989
1990 if ((recompute) || (s_Usb_Pll_Freq == 0U))
1991 {
1992 Setup.msel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_MSEL_SHIFT) & SYSCON_USBPLLCTRL_MSEL_MASK);
1993 Setup.psel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_PSEL_SHIFT) & SYSCON_USBPLLCTRL_PSEL_MASK);
1994 Setup.nsel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_NSEL_SHIFT) & SYSCON_USBPLLCTRL_NSEL_MASK);
1995 Setup.fbsel = (bool)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_FBSEL_SHIFT) & SYSCON_USBPLLCTRL_FBSEL_MASK);
1996 Setup.bypass = (bool)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_BYPASS_SHIFT) & SYSCON_USBPLLCTRL_BYPASS_MASK);
1997 Setup.direct = (bool)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_DIRECT_SHIFT) & 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(1U); /* 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(0U); /* 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)) != 0UL)
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(1U); /* disable fractional function */
2375
2376 /* Flags for lock or power on */
2377 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0UL)
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 & 3UL));
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(1U);
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