aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S69/drivers/fsl_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S69/drivers/fsl_clock.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S69/drivers/fsl_clock.c2093
1 files changed, 2093 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S69/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S69/drivers/fsl_clock.c
new file mode 100644
index 000000000..9c4c1c4b1
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S69/drivers/fsl_clock.c
@@ -0,0 +1,2093 @@
1/*
2 * Copyright 2017 - 2020 , NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include "fsl_clock.h"
9#include "fsl_power.h"
10/*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13/* Component ID definition, used by tools. */
14#ifndef FSL_COMPONENT_ID
15#define FSL_COMPONENT_ID "platform.drivers.clock"
16#endif
17#define NVALMAX (0x100U)
18#define PVALMAX (0x20U)
19#define MVALMAX (0x10000U)
20
21#define PLL_MAX_N_DIV 0x100U
22
23/*--------------------------------------------------------------------------
24!!! If required these #defines can be moved to chip library file
25----------------------------------------------------------------------------*/
26
27#define PLL_SSCG1_MDEC_VAL_P (10U) /* MDEC is in bits 25 downto 10 */
28#define PLL_SSCG1_MDEC_VAL_M (0xFFFFULL << PLL_SSCG1_MDEC_VAL_P)
29#define PLL_NDEC_VAL_P (0U) /* NDEC is in bits 9:0 */
30#define PLL_NDEC_VAL_M (0xFFUL << PLL_NDEC_VAL_P)
31#define PLL_PDEC_VAL_P (0U) /*!< PDEC is in bits 6:0 */
32#define PLL_PDEC_VAL_M (0x1FUL << PLL_PDEC_VAL_P)
33
34#define PLL_MIN_CCO_FREQ_MHZ (275000000U)
35#define PLL_MAX_CCO_FREQ_MHZ (550000000U)
36#define PLL_LOWER_IN_LIMIT (2000U) /*!< Minimum PLL input rate */
37#define PLL_HIGHER_IN_LIMIT (150000000U) /*!< Maximum PLL input rate */
38#define PLL_MIN_IN_SSMODE (3000000U)
39#define PLL_MAX_IN_SSMODE \
40 (100000000U) /*!< Not find the value in UM, Just use the maximum frequency which device support */
41
42/* PLL NDEC reg */
43#define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
44/* PLL PDEC reg */
45#define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
46/* SSCG control1 */
47#define PLL_SSCG1_MDEC_VAL_SET(value) (((uint64_t)(value) << PLL_SSCG1_MDEC_VAL_P) & PLL_SSCG1_MDEC_VAL_M)
48
49/* PLL0 SSCG control1 */
50#define PLL0_SSCG_MD_FRACT_P 0U
51#define PLL0_SSCG_MD_INT_P 25U
52#define PLL0_SSCG_MD_FRACT_M (0x1FFFFFFUL << PLL0_SSCG_MD_FRACT_P)
53#define PLL0_SSCG_MD_INT_M ((uint64_t)0xFFUL << PLL0_SSCG_MD_INT_P)
54
55#define PLL0_SSCG_MD_FRACT_SET(value) (((uint64_t)(value) << PLL0_SSCG_MD_FRACT_P) & PLL0_SSCG_MD_FRACT_M)
56#define PLL0_SSCG_MD_INT_SET(value) (((uint64_t)(value) << PLL0_SSCG_MD_INT_P) & PLL0_SSCG_MD_INT_M)
57
58/* Saved value of PLL output rate, computed whenever needed to save run-time
59 computation on each call to retrive the PLL rate. */
60static uint32_t s_Pll0_Freq;
61static uint32_t s_Pll1_Freq;
62
63/** External clock rate on the CLKIN pin in Hz. If not used,
64 set this to 0. Otherwise, set it to the exact rate in Hz this pin is
65 being driven at. */
66static uint32_t s_Ext_Clk_Freq = 16000000U;
67static uint32_t s_I2S_Mclk_Freq = 0U;
68static uint32_t s_PLU_ClkIn_Freq = 0U;
69
70/*******************************************************************************
71 * Variables
72 ******************************************************************************/
73
74/*******************************************************************************
75 * Prototypes
76 ******************************************************************************/
77/* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
78static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
79/* Get predivider (N) from PLL0 NDEC setting */
80static uint32_t findPll0PreDiv(void);
81/* Get predivider (N) from PLL1 NDEC setting */
82static uint32_t findPll1PreDiv(void);
83/* Get postdivider (P) from PLL0 PDEC setting */
84static uint32_t findPll0PostDiv(void);
85/* Get multiplier (M) from PLL0 MDEC and SSCG settings */
86static float findPll0MMult(void);
87/* Get the greatest common divisor */
88static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
89/* Set PLL output based on desired output rate */
90static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
91/* Update local PLL rate variable */
92static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup);
93
94/*******************************************************************************
95 * Code
96 ******************************************************************************/
97
98/* Clock Selection for IP */
99/**
100 * brief Configure the clock selection muxes.
101 * param connection : Clock to be configured.
102 * return Nothing
103 */
104void CLOCK_AttachClk(clock_attach_id_t connection)
105{
106 uint8_t mux;
107 uint8_t sel;
108 uint16_t item;
109 uint32_t tmp32 = (uint32_t)connection;
110 uint32_t i;
111 volatile uint32_t *pClkSel;
112
113 pClkSel = &(SYSCON->SYSTICKCLKSELX[0]);
114
115 if (kNONE_to_NONE != connection)
116 {
117 for (i = 0U; i < 2U; i++)
118 {
119 if (tmp32 == 0U)
120 {
121 break;
122 }
123 item = (uint16_t)GET_ID_ITEM(tmp32);
124 if (item != 0U)
125 {
126 mux = GET_ID_ITEM_MUX(item);
127 sel = GET_ID_ITEM_SEL(item);
128 if (mux == CM_RTCOSC32KCLKSEL)
129 {
130 PMC->RTCOSC32K |= sel;
131 }
132 else
133 {
134 pClkSel[mux] = sel;
135 }
136 }
137 tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
138 }
139 }
140}
141
142/* Return the actual clock attach id */
143/**
144 * brief Get the actual clock attach id.
145 * This fuction uses the offset in input attach id, then it reads the actual source value in
146 * the register and combine the offset to obtain an actual attach id.
147 * param attachId : Clock attach id to get.
148 * return Clock source value.
149 */
150clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
151{
152 uint8_t mux;
153 uint8_t actualSel;
154 uint32_t tmp32 = (uint32_t)attachId;
155 uint32_t i;
156 uint32_t actualAttachId = 0U;
157 uint32_t selector = GET_ID_SELECTOR(tmp32);
158 volatile uint32_t *pClkSel;
159
160 pClkSel = &(SYSCON->SYSTICKCLKSELX[0]);
161
162 if (kNONE_to_NONE == attachId)
163 {
164 return kNONE_to_NONE;
165 }
166
167 for (i = 0U; i < 2U; i++)
168 {
169 mux = GET_ID_ITEM_MUX(tmp32);
170 if (tmp32 != 0UL)
171 {
172 if (mux == CM_RTCOSC32KCLKSEL)
173 {
174 actualSel = (uint8_t)(PMC->RTCOSC32K);
175 }
176 else
177 {
178 actualSel = (uint8_t)(pClkSel[mux]);
179 }
180
181 /* Consider the combination of two registers */
182 actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
183 }
184 tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */
185 }
186
187 actualAttachId |= selector;
188
189 return (clock_attach_id_t)actualAttachId;
190}
191
192/* Set IP Clock Divider */
193/**
194 * brief Setup peripheral clock dividers.
195 * param div_name : Clock divider name
196 * param divided_by_value: Value to be divided
197 * param reset : Whether to reset the divider counter.
198 * return Nothing
199 */
200void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
201{
202 volatile uint32_t *pClkDiv;
203
204 pClkDiv = &(SYSCON->SYSTICKCLKDIV0);
205 if ((div_name >= kCLOCK_DivFlexFrg0) && (div_name <= kCLOCK_DivFlexFrg7))
206 {
207 /*!< Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1+ MULT /DIV), DIV = 0xFF */
208 ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] =
209 SYSCON_FLEXFRG0CTRL_DIV_MASK | SYSCON_FLEXFRG0CTRL_MULT(divided_by_value);
210 }
211 else
212 {
213 if (reset)
214 {
215 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 29U;
216 }
217 if (divided_by_value == 0U) /*!< halt */
218 {
219 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 30U;
220 }
221 else
222 {
223 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = (divided_by_value - 1U);
224 }
225 }
226}
227
228/* Set RTC 1KHz Clock Divider */
229/**
230 * brief Setup rtc 1khz clock divider.
231 * param divided_by_value: Value to be divided
232 * return Nothing
233 */
234void CLOCK_SetRtc1khzClkDiv(uint32_t divided_by_value)
235{
236 PMC->RTCOSC32K |= (((divided_by_value - 28U) << PMC_RTCOSC32K_CLK1KHZDIV_SHIFT) | PMC_RTCOSC32K_CLK1KHZDIV_MASK);
237}
238
239/* Set RTC 1KHz Clock Divider */
240/**
241 * brief Setup rtc 1hz clock divider.
242 * param divided_by_value: Value to be divided
243 * return Nothing
244 */
245void CLOCK_SetRtc1hzClkDiv(uint32_t divided_by_value)
246{
247 if (divided_by_value == 0U) /*!< halt */
248 {
249 PMC->RTCOSC32K |= (1UL << PMC_RTCOSC32K_CLK1HZDIVHALT_SHIFT);
250 }
251 else
252 {
253 PMC->RTCOSC32K |=
254 (((divided_by_value - 31744U) << PMC_RTCOSC32K_CLK1HZDIV_SHIFT) | PMC_RTCOSC32K_CLK1HZDIV_MASK);
255 }
256}
257
258/* Set FRO Clocking */
259/**
260 * brief Initialize the Core clock to given frequency (12, 48 or 96 MHz).
261 * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
262 * enabled.
263 * param iFreq : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
264 * return returns success or fail status.
265 */
266status_t CLOCK_SetupFROClocking(uint32_t iFreq)
267{
268 if ((iFreq != 12000000U) && (iFreq != 48000000U) && (iFreq != 96000000U))
269 {
270 return kStatus_Fail;
271 }
272 /* Enable Analog Control module */
273 SYSCON->PRESETCTRLCLR[2] = (1UL << SYSCON_PRESETCTRL2_ANALOG_CTRL_RST_SHIFT);
274 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL_MASK;
275 /* Power up the FRO192M */
276 POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
277
278 if (iFreq == 96000000U)
279 {
280 ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_96MHZCLK(1);
281 }
282 /* always enable
283 else if (iFreq == 48000000U)
284 {
285 ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_48MHZCLK(1);
286 }*/
287 else
288 {
289 ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_12MHZCLK(1);
290 }
291 return kStatus_Success;
292}
293
294/* Set the FLASH wait states for the passed frequency */
295/**
296 * brief Set the flash wait states for the input freuqency.
297 * param iFreq: Input frequency
298 * return Nothing
299 */
300void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)
301{
302 uint32_t num_wait_states; /* Flash Controller & FMC internal number of Wait States (minus 1) */
303
304 if (iFreq <= 11000000UL)
305 {
306 /* [0 - 11 MHz] */
307 num_wait_states = 0UL;
308 }
309 else if (iFreq <= 22000000UL)
310 {
311 /* [11 MHz - 22 MHz] */
312 num_wait_states = 1UL;
313 }
314 else if (iFreq <= 33000000UL)
315 {
316 /* [22 MHz - 33 MHz] */
317 num_wait_states = 2UL;
318 }
319 else if (iFreq <= 44000000UL)
320 {
321 /* [33 MHz - 44 MHz] */
322 num_wait_states = 3UL;
323 }
324 else if (iFreq <= 55000000UL)
325 {
326 /* [44 MHz - 55 MHz] */
327 num_wait_states = 4UL;
328 }
329 else if (iFreq <= 66000000UL)
330 {
331 /* [55 MHz - 662 MHz] */
332 num_wait_states = 5UL;
333 }
334 else if (iFreq <= 77000000UL)
335 {
336 /* [66 MHz - 77 MHz] */
337 num_wait_states = 6UL;
338 }
339 else if (iFreq <= 88000000UL)
340 {
341 /* [77 MHz - 88 MHz] */
342 num_wait_states = 7UL;
343 }
344 else if (iFreq <= 100000000UL)
345 {
346 /* [88 MHz - 100 MHz] */
347 num_wait_states = 8UL;
348 }
349 else if (iFreq <= 115000000UL)
350 {
351 /* [100 MHz - 115 MHz] */
352 num_wait_states = 9UL;
353 }
354 else if (iFreq <= 130000000UL)
355 {
356 /* [115 MHz - 130 MHz] */
357 num_wait_states = 10UL;
358 }
359 else if (iFreq <= 150000000UL)
360 {
361 /* [130 MHz - 150 MHz] */
362 num_wait_states = 11UL;
363 }
364 else
365 {
366 /* Above 150 MHz */
367 num_wait_states = 12UL;
368 }
369
370 FLASH->INT_CLR_STATUS = 0x1FUL; /* Clear all status flags */
371
372 FLASH->DATAW[0] = (FLASH->DATAW[0] & 0xFFFFFFF0UL) |
373 (num_wait_states & (SYSCON_FMCCR_FLASHTIM_MASK >> SYSCON_FMCCR_FLASHTIM_SHIFT));
374
375 FLASH->CMD = 0x2; /* CMD_SET_READ_MODE */
376
377 /* Wait until the cmd is completed (without error) */
378 while (0UL == (FLASH->INT_STATUS & FLASH_INT_STATUS_DONE_MASK))
379 {
380 ;
381 }
382
383 /* Adjust FMC waiting time cycles (num_wait_states) */
384 SYSCON->FMCCR = (SYSCON->FMCCR & ~SYSCON_FMCCR_FLASHTIM_MASK) |
385 ((num_wait_states << SYSCON_FMCCR_FLASHTIM_SHIFT) & SYSCON_FMCCR_FLASHTIM_MASK);
386}
387
388/* Set EXT OSC Clk */
389/**
390 * brief Initialize the external osc clock to given frequency.
391 * param iFreq : Desired frequency (must be equal to exact rate in Hz)
392 * return returns success or fail status.
393 */
394status_t CLOCK_SetupExtClocking(uint32_t iFreq)
395{
396 if (iFreq >= 32000000U)
397 {
398 return kStatus_Fail;
399 }
400 /* Turn on power for crystal 32 MHz */
401 POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);
402 POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);
403 /* Enable clock_in clock for clock module. */
404 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;
405
406 s_Ext_Clk_Freq = iFreq;
407 return kStatus_Success;
408}
409
410/* Set I2S MCLK Clk */
411/**
412 * brief Initialize the I2S MCLK clock to given frequency.
413 * param iFreq : Desired frequency (must be equal to exact rate in Hz)
414 * return returns success or fail status.
415 */
416status_t CLOCK_SetupI2SMClkClocking(uint32_t iFreq)
417{
418 s_I2S_Mclk_Freq = iFreq;
419 return kStatus_Success;
420}
421
422/* Set PLU CLKIN Clk */
423/**
424 * brief Initialize the PLU CLKIN clock to given frequency.
425 * param iFreq : Desired frequency (must be equal to exact rate in Hz)
426 * return returns success or fail status.
427 */
428status_t CLOCK_SetupPLUClkInClocking(uint32_t iFreq)
429{
430 s_PLU_ClkIn_Freq = iFreq;
431 return kStatus_Success;
432}
433
434/* Get CLOCK OUT Clk */
435/*! brief Return Frequency of ClockOut
436 * return Frequency of ClockOut
437 */
438uint32_t CLOCK_GetClockOutClkFreq(void)
439{
440 uint32_t freq = 0U;
441
442 switch (SYSCON->CLKOUTSEL)
443 {
444 case 0U:
445 freq = CLOCK_GetCoreSysClkFreq();
446 break;
447
448 case 1U:
449 freq = CLOCK_GetPll0OutFreq();
450 break;
451
452 case 2U:
453 freq = CLOCK_GetExtClkFreq();
454 break;
455
456 case 3U:
457 freq = CLOCK_GetFroHfFreq();
458 break;
459
460 case 4U:
461 freq = CLOCK_GetFro1MFreq();
462 break;
463
464 case 5U:
465 freq = CLOCK_GetPll1OutFreq();
466 break;
467
468 case 6U:
469 freq = CLOCK_GetOsc32KFreq();
470 break;
471
472 case 7U:
473 freq = 0U;
474 break;
475
476 default:
477 assert(false);
478 break;
479 }
480 return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
481}
482
483/* Get ADC Clk */
484/*! brief Return Frequency of Adc Clock
485 * return Frequency of Adc.
486 */
487uint32_t CLOCK_GetAdcClkFreq(void)
488{
489 uint32_t freq = 0U;
490
491 switch (SYSCON->ADCCLKSEL)
492 {
493 case 0U:
494 freq = CLOCK_GetCoreSysClkFreq();
495 break;
496 case 1U:
497 freq = CLOCK_GetPll0OutFreq();
498 break;
499 case 2U:
500 freq = CLOCK_GetFroHfFreq();
501 break;
502 case 7U:
503 freq = 0U;
504 break;
505
506 default:
507 assert(false);
508 break;
509 }
510
511 return freq / ((SYSCON->ADCCLKDIV & SYSCON_ADCCLKDIV_DIV_MASK) + 1U);
512}
513
514/* Get USB0 Clk */
515/*! brief Return Frequency of Usb0 Clock
516 * return Frequency of Usb0 Clock.
517 */
518uint32_t CLOCK_GetUsb0ClkFreq(void)
519{
520 uint32_t freq = 0U;
521
522 switch (SYSCON->USB0CLKSEL)
523 {
524 case 0U:
525 freq = CLOCK_GetCoreSysClkFreq();
526 break;
527 case 1U:
528 freq = CLOCK_GetPll0OutFreq();
529 break;
530 case 3U:
531 freq = CLOCK_GetFroHfFreq();
532 break;
533 case 5U:
534 freq = CLOCK_GetPll1OutFreq();
535 break;
536 case 7U:
537 freq = 0U;
538 break;
539
540 default:
541 assert(false);
542 break;
543 }
544
545 return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
546}
547
548/* Get USB1 Clk */
549/*! brief Return Frequency of Usb1 Clock
550 * return Frequency of Usb1 Clock.
551 */
552uint32_t CLOCK_GetUsb1ClkFreq(void)
553{
554 return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
555}
556
557/* Get MCLK Clk */
558/*! brief Return Frequency of MClk Clock
559 * return Frequency of MClk Clock.
560 */
561uint32_t CLOCK_GetMclkClkFreq(void)
562{
563 uint32_t freq = 0U;
564
565 switch (SYSCON->MCLKCLKSEL)
566 {
567 case 0U:
568 freq = CLOCK_GetFroHfFreq();
569 break;
570 case 1U:
571 freq = CLOCK_GetPll0OutFreq();
572 break;
573 case 7U:
574 freq = 0U;
575 break;
576
577 default:
578 assert(false);
579 break;
580 }
581
582 return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
583}
584
585/* Get SCTIMER Clk */
586/*! brief Return Frequency of SCTimer Clock
587 * return Frequency of SCTimer Clock.
588 */
589uint32_t CLOCK_GetSctClkFreq(void)
590{
591 uint32_t freq = 0U;
592
593 switch (SYSCON->SCTCLKSEL)
594 {
595 case 0U:
596 freq = CLOCK_GetCoreSysClkFreq();
597 break;
598 case 1U:
599 freq = CLOCK_GetPll0OutFreq();
600 break;
601 case 2U:
602 freq = CLOCK_GetExtClkFreq();
603 break;
604 case 3U:
605 freq = CLOCK_GetFroHfFreq();
606 break;
607 case 5U:
608 freq = CLOCK_GetI2SMClkFreq();
609 break;
610 case 7U:
611 freq = 0U;
612 break;
613
614 default:
615 assert(false);
616 break;
617 }
618
619 return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
620}
621
622/* Get SDIO Clk */
623/*! brief Return Frequency of SDIO Clock
624 * return Frequency of SDIO Clock.
625 */
626uint32_t CLOCK_GetSdioClkFreq(void)
627{
628 uint32_t freq = 0U;
629
630 switch (SYSCON->SDIOCLKSEL)
631 {
632 case 0U:
633 freq = CLOCK_GetCoreSysClkFreq();
634 break;
635 case 1U:
636 freq = CLOCK_GetPll0OutFreq();
637 break;
638 case 3U:
639 freq = CLOCK_GetFroHfFreq();
640 break;
641 case 5U:
642 freq = CLOCK_GetPll1OutFreq();
643 break;
644 case 7U:
645 freq = 0U;
646 break;
647 default:
648 assert(false);
649 break;
650 }
651
652 return freq / ((SYSCON->SDIOCLKDIV & 0xffU) + 1U);
653}
654
655/* Get FRO 12M Clk */
656/*! brief Return Frequency of FRO 12MHz
657 * return Frequency of FRO 12MHz
658 */
659uint32_t CLOCK_GetFro12MFreq(void)
660{
661 return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
662}
663
664/* Get FRO 1M Clk */
665/*! brief Return Frequency of FRO 1MHz
666 * return Frequency of FRO 1MHz
667 */
668uint32_t CLOCK_GetFro1MFreq(void)
669{
670 return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
671}
672
673/* Get EXT OSC Clk */
674/*! brief Return Frequency of External Clock
675 * return Frequency of External Clock. If no external clock is used returns 0.
676 */
677uint32_t CLOCK_GetExtClkFreq(void)
678{
679 return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
680}
681
682/* Get WATCH DOG Clk */
683/*! brief Return Frequency of Watchdog
684 * return Frequency of Watchdog
685 */
686uint32_t CLOCK_GetWdtClkFreq(void)
687{
688 return CLOCK_GetFro1MFreq() / ((SYSCON->WDTCLKDIV & SYSCON_WDTCLKDIV_DIV_MASK) + 1U);
689}
690
691/* Get HF FRO Clk */
692/*! brief Return Frequency of High-Freq output of FRO
693 * return Frequency of High-Freq output of FRO
694 */
695uint32_t CLOCK_GetFroHfFreq(void)
696{
697 return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
698}
699
700/* Get SYSTEM PLL Clk */
701/*! brief Return Frequency of PLL
702 * return Frequency of PLL
703 */
704uint32_t CLOCK_GetPll0OutFreq(void)
705{
706 return s_Pll0_Freq;
707}
708
709/* Get USB PLL Clk */
710/*! brief Return Frequency of USB PLL
711 * return Frequency of PLL
712 */
713uint32_t CLOCK_GetPll1OutFreq(void)
714{
715 return s_Pll1_Freq;
716}
717
718/* Get RTC OSC Clk */
719/*! brief Return Frequency of 32kHz osc
720 * return Frequency of 32kHz osc
721 */
722uint32_t CLOCK_GetOsc32KFreq(void)
723{
724 return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
725 (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
726 CLK_RTC_32K_CLK :
727 ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
728 (0UL != (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
729 CLK_RTC_32K_CLK :
730 0U;
731}
732
733/* Get MAIN Clk */
734/*! brief Return Frequency of Core System
735 * return Frequency of Core System
736 */
737uint32_t CLOCK_GetCoreSysClkFreq(void)
738{
739 uint32_t freq = 0U;
740
741 switch (SYSCON->MAINCLKSELB)
742 {
743 case 0U:
744 if (SYSCON->MAINCLKSELA == 0U)
745 {
746 freq = CLOCK_GetFro12MFreq();
747 }
748 else if (SYSCON->MAINCLKSELA == 1U)
749 {
750 freq = CLOCK_GetExtClkFreq();
751 }
752 else if (SYSCON->MAINCLKSELA == 2U)
753 {
754 freq = CLOCK_GetFro1MFreq();
755 }
756 else if (SYSCON->MAINCLKSELA == 3U)
757 {
758 freq = CLOCK_GetFroHfFreq();
759 }
760 else
761 {
762 /* Add comments to prevent the case of MISRA C-2012 rule 15.7. */
763 }
764 break;
765 case 1U:
766 freq = CLOCK_GetPll0OutFreq();
767 break;
768 case 2U:
769 freq = CLOCK_GetPll1OutFreq();
770 break;
771
772 case 3U:
773 freq = CLOCK_GetOsc32KFreq();
774 break;
775
776 default:
777 freq = 0U;
778 break;
779 }
780
781 return freq;
782}
783
784/* Get I2S MCLK Clk */
785/*! brief Return Frequency of I2S MCLK Clock
786 * return Frequency of I2S MCLK Clock
787 */
788uint32_t CLOCK_GetI2SMClkFreq(void)
789{
790 return s_I2S_Mclk_Freq;
791}
792
793/* Get PLU CLKIN Clk */
794/*! brief Return Frequency of PLU CLKIN Clock
795 * return Frequency of PLU CLKIN Clock
796 */
797uint32_t CLOCK_GetPLUClkInFreq(void)
798{
799 return s_PLU_ClkIn_Freq;
800}
801
802/* Get FLEXCOMM input clock */
803/*! brief Return Frequency of flexcomm input clock
804 * param id : flexcomm instance id
805 * return Frequency value
806 */
807uint32_t CLOCK_GetFlexCommInputClock(uint32_t id)
808{
809 uint32_t freq = 0U;
810
811 switch (SYSCON->FCCLKSELX[id])
812 {
813 case 0U:
814 freq = CLOCK_GetCoreSysClkFreq();
815 break;
816 case 1U:
817 freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLL0CLKDIV & 0xffU) + 1U);
818 break;
819 case 2U:
820 freq = CLOCK_GetFro12MFreq();
821 break;
822 case 3U:
823 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
824 break;
825 case 4U:
826 freq = CLOCK_GetFro1MFreq();
827 break;
828 case 5U:
829 freq = CLOCK_GetI2SMClkFreq();
830 break;
831 case 6U:
832 freq = CLOCK_GetOsc32KFreq();
833 break;
834 case 7U:
835 freq = 0U;
836 break;
837
838 default:
839 assert(false);
840 break;
841 }
842
843 return freq;
844}
845
846/* Get FLEXCOMM Clk */
847uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
848{
849 uint32_t freq = 0U;
850 uint32_t temp;
851
852 freq = CLOCK_GetFlexCommInputClock(id);
853 temp = SYSCON->FLEXFRGXCTRL[id] & SYSCON_FLEXFRG0CTRL_MULT_MASK;
854 return freq / (1U + (temp) / ((SYSCON->FLEXFRGXCTRL[id] & SYSCON_FLEXFRG0CTRL_DIV_MASK) + 1U));
855}
856
857/* Get HS_LPSI Clk */
858uint32_t CLOCK_GetHsLspiClkFreq(void)
859{
860 uint32_t freq = 0U;
861
862 switch (SYSCON->HSLSPICLKSEL)
863 {
864 case 0U:
865 freq = CLOCK_GetCoreSysClkFreq();
866 break;
867 case 1U:
868 freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLL0CLKDIV & 0xffU) + 1U);
869 break;
870 case 2U:
871 freq = CLOCK_GetFro12MFreq();
872 break;
873 case 3U:
874 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
875 break;
876 case 4U:
877 freq = CLOCK_GetFro1MFreq();
878 break;
879 case 6U:
880 freq = CLOCK_GetOsc32KFreq();
881 break;
882 case 7U:
883 freq = 0U;
884 break;
885
886 default:
887 assert(false);
888 break;
889 }
890
891 return freq;
892}
893
894/* Get CTimer Clk */
895/*! brief Return Frequency of CTimer functional Clock
896 * return Frequency of CTimer functional Clock
897 */
898uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
899{
900 uint32_t freq = 0U;
901
902 switch (SYSCON->CTIMERCLKSELX[id])
903 {
904 case 0U:
905 freq = CLOCK_GetCoreSysClkFreq();
906 break;
907 case 1U:
908 freq = CLOCK_GetPll0OutFreq();
909 break;
910 case 3U:
911 freq = CLOCK_GetFroHfFreq();
912 break;
913 case 4U:
914 freq = CLOCK_GetFro1MFreq();
915 break;
916 case 5U:
917 freq = CLOCK_GetI2SMClkFreq();
918 break;
919 case 6U:
920 freq = CLOCK_GetOsc32KFreq();
921 break;
922 case 7U:
923 freq = 0U;
924 break;
925
926 default:
927 assert(false);
928 break;
929 }
930
931 return freq;
932}
933
934/* Get Systick Clk */
935/*! brief Return Frequency of SystickClock
936 * return Frequency of Systick Clock
937 */
938uint32_t CLOCK_GetSystickClkFreq(uint32_t id)
939{
940 volatile uint32_t *pSystickClkDiv;
941 pSystickClkDiv = &(SYSCON->SYSTICKCLKDIV0);
942 uint32_t freq = 0U;
943
944 switch (SYSCON->SYSTICKCLKSELX[id])
945 {
946 case 0U:
947 freq = CLOCK_GetCoreSysClkFreq() / ((((volatile uint32_t *)pSystickClkDiv)[(uint32_t)id] & 0xffU) + 1U);
948 break;
949 case 1U:
950 freq = CLOCK_GetFro1MFreq();
951 break;
952 case 2U:
953 freq = CLOCK_GetOsc32KFreq();
954 break;
955 case 7U:
956 freq = 0U;
957 break;
958
959 default:
960 freq = 0U;
961 break;
962 }
963
964 return freq;
965}
966
967/* Set FlexComm Clock */
968/**
969 * brief Set the flexcomm output frequency.
970 * param id : flexcomm instance id
971 * freq : output frequency
972 * return 0 : the frequency range is out of range.
973 * 1 : switch successfully.
974 */
975uint32_t CLOCK_SetFlexCommClock(uint32_t id, uint32_t freq)
976{
977 uint32_t input = CLOCK_GetFlexCommClkFreq(id);
978 uint32_t mul;
979
980 if ((freq > 48000000UL) || (freq > input) || (input / freq >= 2UL))
981 {
982 /* FRG output frequency should be less than equal to 48MHz */
983 return 0UL;
984 }
985 else
986 {
987 mul = (uint32_t)((((uint64_t)input - freq) * 256ULL) / ((uint64_t)freq));
988 SYSCON->FLEXFRGXCTRL[id] = (mul << 8U) | 0xFFU;
989 return 1UL;
990 }
991}
992
993/* Get IP Clk */
994/*! brief Return Frequency of selected clock
995 * return Frequency of selected clock
996 */
997uint32_t CLOCK_GetFreq(clock_name_t clockName)
998{
999 uint32_t freq;
1000 switch (clockName)
1001 {
1002 case kCLOCK_CoreSysClk:
1003 freq = CLOCK_GetCoreSysClkFreq();
1004 break;
1005 case kCLOCK_BusClk:
1006 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
1007 break;
1008 case kCLOCK_ClockOut:
1009 freq = CLOCK_GetClockOutClkFreq();
1010 break;
1011 case kCLOCK_Pll1Out:
1012 freq = CLOCK_GetPll1OutFreq();
1013 break;
1014 case kCLOCK_Mclk:
1015 freq = CLOCK_GetMclkClkFreq();
1016 break;
1017 case kCLOCK_FroHf:
1018 freq = CLOCK_GetFroHfFreq();
1019 break;
1020 case kCLOCK_Fro12M:
1021 freq = CLOCK_GetFro12MFreq();
1022 break;
1023 case kCLOCK_ExtClk:
1024 freq = CLOCK_GetExtClkFreq();
1025 break;
1026 case kCLOCK_Pll0Out:
1027 freq = CLOCK_GetPll0OutFreq();
1028 break;
1029 case kCLOCK_FlexI2S:
1030 freq = CLOCK_GetI2SMClkFreq();
1031 break;
1032 default:
1033 freq = 0U;
1034 break;
1035 }
1036 return freq;
1037}
1038
1039/* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
1040static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
1041{
1042 uint32_t seli, selp;
1043 /* bandwidth: compute selP from Multiplier */
1044 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
1045 {
1046 selp = (M >> 2U) + 1U;
1047 if (selp >= 31U)
1048 {
1049 selp = 31U;
1050 }
1051 *pSelP = selp;
1052
1053 if (M >= 8000UL)
1054 {
1055 seli = 1UL;
1056 }
1057 else if (M >= 122UL)
1058 {
1059 seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
1060 }
1061 else
1062 {
1063 seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1064 }
1065
1066 if (seli >= 63UL)
1067 {
1068 seli = 63UL;
1069 }
1070 *pSelI = seli;
1071
1072 *pSelR = 0U;
1073 }
1074 else
1075 {
1076 /* Note: If the spread spectrum mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
1077 *pSelP = 3U;
1078 *pSelI = 4U;
1079 *pSelR = 4U;
1080 }
1081}
1082
1083/* Get predivider (N) from PLL0 NDEC setting */
1084static uint32_t findPll0PreDiv(void)
1085{
1086 uint32_t preDiv = 1UL;
1087
1088 /* Direct input is not used? */
1089 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
1090 {
1091 preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
1092 if (preDiv == 0UL)
1093 {
1094 preDiv = 1UL;
1095 }
1096 }
1097 return preDiv;
1098}
1099
1100/* Get predivider (N) from PLL1 NDEC setting */
1101static uint32_t findPll1PreDiv(void)
1102{
1103 uint32_t preDiv = 1UL;
1104
1105 /* Direct input is not used? */
1106 if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
1107 {
1108 preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
1109 if (preDiv == 0UL)
1110 {
1111 preDiv = 1UL;
1112 }
1113 }
1114 return preDiv;
1115}
1116
1117/* Get postdivider (P) from PLL0 PDEC setting */
1118static uint32_t findPll0PostDiv(void)
1119{
1120 uint32_t postDiv = 1UL;
1121
1122 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1123 {
1124 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1125 {
1126 postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
1127 }
1128 else
1129 {
1130 postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
1131 }
1132 if (postDiv == 0UL)
1133 {
1134 postDiv = 2UL;
1135 }
1136 }
1137 return postDiv;
1138}
1139
1140/* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
1141static float findPll0MMult(void)
1142{
1143 float mMult = 1.0F;
1144 float mMult_fract;
1145 uint32_t mMult_int;
1146
1147 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
1148 {
1149 mMult =
1150 (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
1151 }
1152 else
1153 {
1154 mMult_int = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
1155 mMult_int = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL0_SSCG_MD_INT_P);
1156 mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL0_SSCG_MD_FRACT_M) /
1157 (float)(uint32_t)(1UL << PLL0_SSCG_MD_INT_P));
1158 mMult = (float)mMult_int + mMult_fract;
1159 }
1160 if (mMult == 0.0F)
1161 {
1162 mMult = 1.0F;
1163 }
1164 return mMult;
1165}
1166
1167/* Find greatest common divisor between m and n */
1168static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1169{
1170 uint32_t tmp;
1171
1172 while (n != 0U)
1173 {
1174 tmp = n;
1175 n = m % n;
1176 m = tmp;
1177 }
1178
1179 return m;
1180}
1181
1182/*
1183 * Set PLL0 output based on desired output rate.
1184 * In this function, the it calculates the PLL0 setting for output frequency from input clock
1185 * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1186 * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1187 */
1188static pll_error_t CLOCK_GetPll0ConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1189{
1190 uint32_t nDivOutHz, fccoHz;
1191 uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1192 uint32_t pllDirectInput, pllDirectOutput;
1193 uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1194
1195 /* Baseline parameters (no input or output dividers) */
1196 pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */
1197 pllPostDivider = 1U; /* 1 implies post-divider will be disabled */
1198 pllDirectOutput = 1U;
1199
1200 /* Verify output rate parameter */
1201 if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1202 {
1203 /* Maximum PLL output with post divider=1 cannot go above this frequency */
1204 return kStatus_PLL_OutputTooHigh;
1205 }
1206 if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1207 {
1208 /* Minmum PLL output with maximum post divider cannot go below this frequency */
1209 return kStatus_PLL_OutputTooLow;
1210 }
1211
1212 /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
1213 if (useSS)
1214 {
1215 /* Verify input rate parameter */
1216 if (finHz < PLL_MIN_IN_SSMODE)
1217 {
1218 /* Input clock into the PLL cannot be lower than this */
1219 return kStatus_PLL_InputTooLow;
1220 }
1221 /* PLL input in SS mode must be under 20MHz */
1222 if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
1223 {
1224 return kStatus_PLL_InputTooHigh;
1225 }
1226 }
1227 else
1228 {
1229 /* Verify input rate parameter */
1230 if (finHz < PLL_LOWER_IN_LIMIT)
1231 {
1232 /* Input clock into the PLL cannot be lower than this */
1233 return kStatus_PLL_InputTooLow;
1234 }
1235 if (finHz > PLL_HIGHER_IN_LIMIT)
1236 {
1237 /* Input clock into the PLL cannot be higher than this */
1238 return kStatus_PLL_InputTooHigh;
1239 }
1240 }
1241
1242 /* Find the optimal CCO frequency for the output and input that
1243 will keep it inside the PLL CCO range. This may require
1244 tweaking the post-divider for the PLL. */
1245 fccoHz = foutHz;
1246 while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1247 {
1248 /* CCO output is less than minimum CCO range, so the CCO output
1249 needs to be bumped up and the post-divider is used to bring
1250 the PLL output back down. */
1251 pllPostDivider++;
1252 if (pllPostDivider > PVALMAX)
1253 {
1254 return kStatus_PLL_OutsideIntLimit;
1255 }
1256
1257 /* Target CCO goes up, PLL output goes down */
1258 /* divide-by-2 divider in the post-divider is always work*/
1259 fccoHz = foutHz * (pllPostDivider * 2U);
1260 pllDirectOutput = 0U;
1261 }
1262
1263 /* Determine if a pre-divider is needed to get the best frequency */
1264 if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
1265 {
1266 uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
1267
1268 if (a > PLL_LOWER_IN_LIMIT)
1269 {
1270 a = finHz / a;
1271 if ((a != 0U) && (a < PLL_MAX_N_DIV))
1272 {
1273 pllPreDivider = a;
1274 }
1275 }
1276 }
1277
1278 /* Bypass pre-divider hardware if pre-divider is 1 */
1279 if (pllPreDivider > 1U)
1280 {
1281 pllDirectInput = 0U;
1282 }
1283 else
1284 {
1285 pllDirectInput = 1U;
1286 }
1287
1288 /* Determine PLL multipler */
1289 nDivOutHz = (finHz / pllPreDivider);
1290 pllMultiplier = (fccoHz / nDivOutHz);
1291
1292 /* Find optimal values for filter */
1293 if (useSS == false)
1294 {
1295 /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1296 if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1297 {
1298 pllMultiplier++;
1299 }
1300
1301 /* Setup filtering */
1302 pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1303 uplimoff = 0U;
1304
1305 /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1306 pSetup->pllsscg[1] =
1307 (uint32_t)((PLL_SSCG1_MDEC_VAL_SET(pllMultiplier)) | (1UL << SYSCON_PLL0SSCG1_SEL_EXT_SHIFT));
1308 }
1309 else
1310 {
1311 uint64_t fc;
1312
1313 /* Filtering will be handled by SSC */
1314 pllSelR = 0U;
1315 pllSelI = 0U;
1316 pllSelP = 0U;
1317 uplimoff = 1U;
1318
1319 /* The PLL multiplier will get very close and slightly under the
1320 desired target frequency. A small fractional component can be
1321 added to fine tune the frequency upwards to the target. */
1322 fc = (((uint64_t)fccoHz % (uint64_t)nDivOutHz) << 25U) / nDivOutHz;
1323
1324 /* Set multiplier */
1325 pSetup->pllsscg[0] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) | PLL0_SSCG_MD_FRACT_SET((uint32_t)fc));
1326 pSetup->pllsscg[1] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) >> 32U);
1327 }
1328
1329 /* Get encoded values for N (prediv) and P (postdiv) */
1330 pSetup->pllndec = PLL_NDEC_VAL_SET(pllPreDivider);
1331 pSetup->pllpdec = PLL_PDEC_VAL_SET(pllPostDivider);
1332
1333 /* PLL control */
1334 pSetup->pllctrl = (pllSelR << SYSCON_PLL0CTRL_SELR_SHIFT) | /* Filter coefficient */
1335 (pllSelI << SYSCON_PLL0CTRL_SELI_SHIFT) | /* Filter coefficient */
1336 (pllSelP << SYSCON_PLL0CTRL_SELP_SHIFT) | /* Filter coefficient */
1337 (0UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT) | /* PLL bypass mode disabled */
1338 (uplimoff << SYSCON_PLL0CTRL_LIMUPOFF_SHIFT) | /* SS/fractional mode disabled */
1339 (pllDirectInput << SYSCON_PLL0CTRL_BYPASSPREDIV_SHIFT) | /* Bypass pre-divider? */
1340 (pllDirectOutput << SYSCON_PLL0CTRL_BYPASSPOSTDIV_SHIFT) | /* Bypass post-divider? */
1341 (1UL << SYSCON_PLL0CTRL_CLKEN_SHIFT); /* Ensure the PLL clock output */
1342
1343 return kStatus_PLL_Success;
1344}
1345
1346#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1347/* Alloct the static buffer for cache. */
1348static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1349static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1350static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1351static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {false};
1352static uint32_t s_PllSetupCacheIdx = 0U;
1353#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1354
1355/*
1356 * Calculate the PLL setting values from input clock freq to output freq.
1357 */
1358static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1359{
1360 pll_error_t retErr;
1361#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1362 uint32_t i;
1363
1364 for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1365 {
1366 if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
1367 {
1368 /* Hit the target in cache buffer. */
1369 pSetup->pllctrl = s_PllSetupCacheStruct[i].pllctrl;
1370 pSetup->pllndec = s_PllSetupCacheStruct[i].pllndec;
1371 pSetup->pllpdec = s_PllSetupCacheStruct[i].pllpdec;
1372 pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
1373 pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
1374 retErr = kStatus_PLL_Success;
1375 break;
1376 }
1377 }
1378
1379 if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1380 {
1381 return retErr;
1382 }
1383#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1384
1385 retErr = CLOCK_GetPll0ConfigInternal(finHz, foutHz, pSetup, useSS);
1386
1387#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1388 /* Cache the most recent calulation result into buffer. */
1389 s_FinHzCache[s_PllSetupCacheIdx] = finHz;
1390 s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1391 s_UseSSCache[s_PllSetupCacheIdx] = useSS;
1392
1393 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl = pSetup->pllctrl;
1394 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec = pSetup->pllndec;
1395 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec = pSetup->pllpdec;
1396 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
1397 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
1398 /* Update the index for next available buffer. */
1399 s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1400#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1401
1402 return retErr;
1403}
1404
1405/* Update local PLL rate variable */
1406static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup)
1407{
1408 s_Pll0_Freq = CLOCK_GetPLL0OutFromSetup(pSetup);
1409}
1410
1411/* Return System PLL input clock rate */
1412/*! brief Return PLL0 input clock rate
1413 * return PLL0 input clock rate
1414 */
1415uint32_t CLOCK_GetPLL0InClockRate(void)
1416{
1417 uint32_t clkRate = 0U;
1418
1419 switch ((SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK))
1420 {
1421 case 0x00U:
1422 clkRate = CLK_FRO_12MHZ;
1423 break;
1424
1425 case 0x01U:
1426 clkRate = CLOCK_GetExtClkFreq();
1427 break;
1428
1429 case 0x02U:
1430 clkRate = CLOCK_GetFro1MFreq();
1431 break;
1432
1433 case 0x03U:
1434 clkRate = CLOCK_GetOsc32KFreq();
1435 break;
1436
1437 default:
1438 clkRate = 0U;
1439 break;
1440 }
1441
1442 return clkRate;
1443}
1444
1445/* Return PLL1 input clock rate */
1446uint32_t CLOCK_GetPLL1InClockRate(void)
1447{
1448 uint32_t clkRate = 0U;
1449
1450 switch ((SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK))
1451 {
1452 case 0x00U:
1453 clkRate = CLK_FRO_12MHZ;
1454 break;
1455
1456 case 0x01U:
1457 clkRate = CLOCK_GetExtClkFreq();
1458 break;
1459
1460 case 0x02U:
1461 clkRate = CLOCK_GetFro1MFreq();
1462 break;
1463
1464 case 0x03U:
1465 clkRate = CLOCK_GetOsc32KFreq();
1466 break;
1467
1468 default:
1469 clkRate = 0U;
1470 break;
1471 }
1472
1473 return clkRate;
1474}
1475
1476/* Return PLL0 output clock rate from setup structure */
1477/*! brief Return PLL0 output clock rate from setup structure
1478 * param pSetup : Pointer to a PLL setup structure
1479 * return PLL0 output clock rate the setup structure will generate
1480 */
1481uint32_t CLOCK_GetPLL0OutFromSetup(pll_setup_t *pSetup)
1482{
1483 uint32_t clkRate = 0;
1484 uint32_t prediv, postdiv;
1485 float workRate = 0.0F;
1486
1487 /* Get the input clock frequency of PLL. */
1488 clkRate = CLOCK_GetPLL0InClockRate();
1489
1490 if (((pSetup->pllctrl & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) &&
1491 ((pSetup->pllctrl & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) &&
1492 ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) &&
1493 ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
1494 {
1495 prediv = findPll0PreDiv();
1496 postdiv = findPll0PostDiv();
1497 /* Adjust input clock */
1498 clkRate = clkRate / prediv;
1499 /* MDEC used for rate */
1500 workRate = (float)clkRate * (float)findPll0MMult();
1501 workRate /= (float)postdiv;
1502 }
1503
1504 return (uint32_t)workRate;
1505}
1506
1507/* Set the current PLL0 Rate */
1508/*! brief Store the current PLL rate
1509 * param rate: Current rate of the PLL
1510 * return Nothing
1511 **/
1512void CLOCK_SetStoredPLL0ClockRate(uint32_t rate)
1513{
1514 s_Pll0_Freq = rate;
1515}
1516
1517/* Return PLL0 output clock rate */
1518/*! brief Return PLL0 output clock rate
1519 * param recompute : Forces a PLL rate recomputation if true
1520 * return PLL0 output clock rate
1521 * note The PLL rate is cached in the driver in a variable as
1522 * the rate computation function can take some time to perform. It
1523 * is recommended to use 'false' with the 'recompute' parameter.
1524 */
1525uint32_t CLOCK_GetPLL0OutClockRate(bool recompute)
1526{
1527 pll_setup_t Setup;
1528 uint32_t rate;
1529
1530 if ((recompute) || (s_Pll0_Freq == 0U))
1531 {
1532 Setup.pllctrl = SYSCON->PLL0CTRL;
1533 Setup.pllndec = SYSCON->PLL0NDEC;
1534 Setup.pllpdec = SYSCON->PLL0PDEC;
1535 Setup.pllsscg[0] = SYSCON->PLL0SSCG0;
1536 Setup.pllsscg[1] = SYSCON->PLL0SSCG1;
1537
1538 CLOCK_GetPLL0OutFromSetupUpdate(&Setup);
1539 }
1540
1541 rate = s_Pll0_Freq;
1542
1543 return rate;
1544}
1545
1546/* Set PLL0 output based on the passed PLL setup data */
1547/*! brief Set PLL output based on the passed PLL setup data
1548 * param pControl : Pointer to populated PLL control structure to generate setup with
1549 * param pSetup : Pointer to PLL setup structure to be filled
1550 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
1551 * note Actual frequency for setup may vary from the desired frequency based on the
1552 * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1553 */
1554pll_error_t CLOCK_SetupPLL0Data(pll_config_t *pControl, pll_setup_t *pSetup)
1555{
1556 uint32_t inRate;
1557 bool useSS = ((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0U);
1558
1559 pll_error_t pllError;
1560
1561 /* Determine input rate for the PLL */
1562 if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)
1563 {
1564 inRate = pControl->inputRate;
1565 }
1566 else
1567 {
1568 inRate = CLOCK_GetPLL0InClockRate();
1569 }
1570
1571 /* PLL flag options */
1572 pllError = CLOCK_GetPll0Config(inRate, pControl->desiredRate, pSetup, useSS);
1573 if ((useSS) && (pllError == kStatus_PLL_Success))
1574 {
1575 /* If using SS mode, then some tweaks are made to the generated setup */
1576 pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
1577 if (pControl->mfDither)
1578 {
1579 pSetup->pllsscg[1] |= (1UL << SYSCON_PLL0SSCG1_DITHER_SHIFT);
1580 }
1581 }
1582
1583 return pllError;
1584}
1585
1586/* Set PLL0 output from PLL setup structure */
1587/*! brief Set PLL output from PLL setup structure (precise frequency)
1588 * param pSetup : Pointer to populated PLL setup structure
1589 * param flagcfg : Flag configuration for PLL config structure
1590 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
1591 * note This function will power off the PLL, setup the PLL with the
1592 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1593 * and adjust system voltages to the new PLL rate. The function will not
1594 * alter any source clocks (ie, main systen clock) that may use the PLL,
1595 * so these should be setup prior to and after exiting the function.
1596 */
1597pll_error_t CLOCK_SetupPLL0Prec(pll_setup_t *pSetup, uint32_t flagcfg)
1598{
1599 uint32_t inRate, clkRate, prediv;
1600
1601 /* Power off PLL during setup changes */
1602 POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1603 POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1604
1605 pSetup->flags = flagcfg;
1606
1607 /* Write PLL setup data */
1608 SYSCON->PLL0CTRL = pSetup->pllctrl;
1609 SYSCON->PLL0NDEC = pSetup->pllndec;
1610 SYSCON->PLL0NDEC = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1611 SYSCON->PLL0PDEC = pSetup->pllpdec;
1612 SYSCON->PLL0PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1613 SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1614 SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1615 SYSCON->PLL0SSCG1 =
1616 pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT); /* latch */
1617
1618 POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1619 POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1620
1621 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1622 {
1623 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
1624 {
1625 inRate = CLOCK_GetPLL0InClockRate();
1626 prediv = findPll0PreDiv();
1627 /* Adjust input clock */
1628 clkRate = inRate / prediv;
1629 /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
1630 if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
1631 {
1632 while (CLOCK_IsPLL0Locked() == false)
1633 {
1634 }
1635 }
1636 else
1637 {
1638 SDK_DelayAtLeastUs(6000U,
1639 SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1640 to insure the PLL will be stable */
1641 }
1642 }
1643 else /* spread spectrum mode */
1644 {
1645 SDK_DelayAtLeastUs(6000U,
1646 SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
1647 insure the PLL will be stable */
1648 }
1649 }
1650
1651 /* Update current programmed PLL rate var */
1652 CLOCK_GetPLL0OutFromSetupUpdate(pSetup);
1653
1654 /* System voltage adjustment, occurs prior to setting main system clock */
1655 if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0U)
1656 {
1657 POWER_SetVoltageForFreq(s_Pll0_Freq);
1658 }
1659
1660 return kStatus_PLL_Success;
1661}
1662
1663/* Setup PLL Frequency from pre-calculated value */
1664/**
1665 * brief Set PLL0 output from PLL setup structure (precise frequency)
1666 * param pSetup : Pointer to populated PLL setup structure
1667 * return kStatus_PLL_Success on success, or PLL setup error code
1668 * note This function will power off the PLL, setup the PLL with the
1669 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1670 * and adjust system voltages to the new PLL rate. The function will not
1671 * alter any source clocks (ie, main systen clock) that may use the PLL,
1672 * so these should be setup prior to and after exiting the function.
1673 */
1674pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
1675{
1676 uint32_t inRate, clkRate, prediv;
1677 /* Power off PLL during setup changes */
1678 POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1679 POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1680
1681 /* Write PLL setup data */
1682 SYSCON->PLL0CTRL = pSetup->pllctrl;
1683 SYSCON->PLL0NDEC = pSetup->pllndec;
1684 SYSCON->PLL0NDEC = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1685 SYSCON->PLL0PDEC = pSetup->pllpdec;
1686 SYSCON->PLL0PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1687 SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1688 SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1689 SYSCON->PLL0SSCG1 =
1690 pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* latch */
1691
1692 POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1693 POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1694
1695 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1696 {
1697 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
1698 {
1699 inRate = CLOCK_GetPLL0InClockRate();
1700 prediv = findPll0PreDiv();
1701 /* Adjust input clock */
1702 clkRate = inRate / prediv;
1703 /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
1704 if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
1705 {
1706 while (CLOCK_IsPLL0Locked() == false)
1707 {
1708 }
1709 }
1710 else
1711 {
1712 SDK_DelayAtLeastUs(6000U,
1713 SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1714 to insure the PLL will be stable */
1715 }
1716 }
1717 else /* spread spectrum mode */
1718 {
1719 SDK_DelayAtLeastUs(6000U,
1720 SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
1721 insure the PLL will be stable */
1722 }
1723 }
1724
1725 /* Update current programmed PLL rate var */
1726 s_Pll0_Freq = pSetup->pllRate;
1727
1728 return kStatus_PLL_Success;
1729}
1730
1731/* Setup PLL1 Frequency from pre-calculated value */
1732/**
1733 * brief Set PLL1 output from PLL setup structure (precise frequency)
1734 * param pSetup : Pointer to populated PLL setup structure
1735 * return kStatus_PLL_Success on success, or PLL setup error code
1736 * note This function will power off the PLL, setup the PLL with the
1737 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1738 * and adjust system voltages to the new PLL rate. The function will not
1739 * alter any source clocks (ie, main systen clock) that may use the PLL,
1740 * so these should be setup prior to and after exiting the function.
1741 */
1742pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
1743{
1744 uint32_t inRate, clkRate, prediv;
1745 /* Power off PLL during setup changes */
1746 POWER_EnablePD(kPDRUNCFG_PD_PLL1);
1747
1748 /* Write PLL setup data */
1749 SYSCON->PLL1CTRL = pSetup->pllctrl;
1750 SYSCON->PLL1NDEC = pSetup->pllndec;
1751 SYSCON->PLL1NDEC = pSetup->pllndec | (1UL << SYSCON_PLL1NDEC_NREQ_SHIFT); /* latch */
1752 SYSCON->PLL1PDEC = pSetup->pllpdec;
1753 SYSCON->PLL1PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL1PDEC_PREQ_SHIFT); /* latch */
1754 SYSCON->PLL1MDEC = pSetup->pllmdec;
1755 SYSCON->PLL1MDEC = pSetup->pllmdec | (1UL << SYSCON_PLL1MDEC_MREQ_SHIFT); /* latch */
1756
1757 POWER_DisablePD(kPDRUNCFG_PD_PLL1);
1758
1759 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1760 {
1761 inRate = CLOCK_GetPLL1InClockRate();
1762 prediv = findPll1PreDiv();
1763 /* Adjust input clock */
1764 clkRate = inRate / prediv;
1765 /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
1766 if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
1767 {
1768 while (CLOCK_IsPLL1Locked() == false)
1769 {
1770 }
1771 }
1772 else
1773 {
1774 SDK_DelayAtLeastUs(6000U,
1775 SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
1776 insure the PLL will be stable */
1777 }
1778 }
1779
1780 /* Update current programmed PLL rate var */
1781 s_Pll1_Freq = pSetup->pllRate;
1782
1783 return kStatus_PLL_Success;
1784}
1785
1786/* Set PLL0 clock based on the input frequency and multiplier */
1787/*! brief Set PLL0 output based on the multiplier and input frequency
1788 * param multiply_by : multiplier
1789 * param input_freq : Clock input frequency of the PLL
1790 * return Nothing
1791 * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
1792 * function does not disable or enable PLL power, wait for PLL lock,
1793 * or adjust system voltages. These must be done in the application.
1794 * The function will not alter any source clocks (ie, main systen clock)
1795 * that may use the PLL, so these should be setup prior to and after
1796 * exiting the function.
1797 */
1798void CLOCK_SetupPLL0Mult(uint32_t multiply_by, uint32_t input_freq)
1799{
1800 uint32_t cco_freq = input_freq * multiply_by;
1801 uint32_t pdec = 1U;
1802 uint32_t selr;
1803 uint32_t seli;
1804 uint32_t selp;
1805 uint32_t mdec, ndec;
1806
1807 while (cco_freq < 275000000U)
1808 {
1809 multiply_by <<= 1U; /* double value in each iteration */
1810 pdec <<= 1U; /* correspondingly double pdec to cancel effect of double msel */
1811 cco_freq = input_freq * multiply_by;
1812 }
1813
1814 selr = 0U;
1815
1816 if (multiply_by >= 8000UL)
1817 {
1818 seli = 1UL;
1819 }
1820 else if (multiply_by >= 122UL)
1821 {
1822 seli = (uint32_t)(8000UL / multiply_by); /*floor(8000/M) */
1823 }
1824 else
1825 {
1826 seli = 2UL * ((uint32_t)(multiply_by / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1827 }
1828
1829 if (seli >= 63U)
1830 {
1831 seli = 63U;
1832 }
1833
1834 {
1835 selp = 31U;
1836 }
1837
1838 if (pdec > 1U)
1839 {
1840 pdec = pdec / 2U; /* Account for minus 1 encoding */
1841 /* Translate P value */
1842 }
1843
1844 mdec = (uint32_t)PLL_SSCG1_MDEC_VAL_SET(multiply_by);
1845 ndec = 0x1U; /* pre divide by 1 (hardcoded) */
1846
1847 SYSCON->PLL0CTRL = SYSCON_PLL0CTRL_CLKEN_MASK | SYSCON_PLL0CTRL_BYPASSPOSTDIV(0) |
1848 SYSCON_PLL0CTRL_BYPASSPOSTDIV2(0) | (selr << SYSCON_PLL0CTRL_SELR_SHIFT) |
1849 (seli << SYSCON_PLL0CTRL_SELI_SHIFT) | (selp << SYSCON_PLL0CTRL_SELP_SHIFT);
1850 SYSCON->PLL0PDEC = pdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* set Pdec value and assert preq */
1851 SYSCON->PLL0NDEC = ndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* set Pdec value and assert preq */
1852 SYSCON->PLL0SSCG1 =
1853 mdec | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* select non sscg MDEC value, assert mreq and select mdec value */
1854}
1855
1856/* Enable USB DEVICE FULL SPEED clock */
1857/*! brief Enable USB Device FS clock.
1858 * param src : clock source
1859 * param freq: clock frequency
1860 * Enable USB Device Full Speed clock.
1861 */
1862bool CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src, uint32_t freq)
1863{
1864 bool ret = true;
1865
1866 CLOCK_DisableClock(kCLOCK_Usbd0);
1867
1868 if (kCLOCK_UsbfsSrcFro == src)
1869 {
1870 switch (freq)
1871 {
1872 case 96000000U:
1873 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
1874 break;
1875
1876 default:
1877 ret = false;
1878 break;
1879 }
1880 /* Turn ON FRO HF */
1881 POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
1882 /* Enable FRO 96MHz output */
1883 ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
1884 /* Select FRO 96 or 48 MHz */
1885 CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
1886 }
1887 else
1888 {
1889 /*!< Configure XTAL32M */
1890 POWER_DisablePD(kPDRUNCFG_PD_XTAL32M); /* Ensure XTAL32M is powered */
1891 POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M); /* Ensure XTAL32M is powered */
1892 (void)CLOCK_SetupExtClocking(16000000U); /* Enable clk_in clock */
1893 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clk_in from XTAL32M clock */
1894 ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system */
1895
1896 /*!< Set up PLL1 */
1897 POWER_DisablePD(kPDRUNCFG_PD_PLL1);
1898 CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
1899 const pll_setup_t pll1Setup = {
1900 .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
1901 .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
1902 .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
1903 .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
1904 .pllRate = 48000000U,
1905 .flags = PLL_SETUPFLAG_WAITLOCK};
1906 (void)CLOCK_SetPLL1Freq(&pll1Setup);
1907
1908 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
1909 CLOCK_AttachClk(kPLL1_to_USB0_CLK);
1910 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1911 }
1912 CLOCK_EnableClock(kCLOCK_Usbd0);
1913 CLOCK_EnableClock(kCLOCK_UsbRam1);
1914
1915 return ret;
1916}
1917
1918/* Enable USB HOST FULL SPEED clock */
1919/*! brief Enable USB HOST FS clock.
1920 * param src : clock source
1921 * param freq: clock frequency
1922 * Enable USB HOST Full Speed clock.
1923 */
1924bool CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src, uint32_t freq)
1925{
1926 bool ret = true;
1927
1928 CLOCK_DisableClock(kCLOCK_Usbhmr0);
1929 CLOCK_DisableClock(kCLOCK_Usbhsl0);
1930
1931 if (kCLOCK_UsbfsSrcFro == src)
1932 {
1933 switch (freq)
1934 {
1935 case 96000000U:
1936 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
1937 break;
1938
1939 default:
1940 ret = false;
1941 break;
1942 }
1943 /* Turn ON FRO HF */
1944 POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
1945 /* Enable FRO 96MHz output */
1946 ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
1947 /* Select FRO 96 MHz */
1948 CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
1949 }
1950 else
1951 {
1952 /*!< Configure XTAL32M */
1953 POWER_DisablePD(kPDRUNCFG_PD_XTAL32M); /* Ensure XTAL32M is powered */
1954 POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M); /* Ensure XTAL32M is powered */
1955 (void)CLOCK_SetupExtClocking(16000000U); /* Enable clk_in clock */
1956 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clk_in from XTAL32M clock */
1957 ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system */
1958
1959 /*!< Set up PLL1 */
1960 POWER_DisablePD(kPDRUNCFG_PD_PLL1);
1961 CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
1962 const pll_setup_t pll1Setup = {
1963 .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
1964 .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
1965 .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
1966 .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
1967 .pllRate = 48000000U,
1968 .flags = PLL_SETUPFLAG_WAITLOCK};
1969 (void)CLOCK_SetPLL1Freq(&pll1Setup);
1970
1971 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
1972 CLOCK_AttachClk(kPLL1_to_USB0_CLK);
1973 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1974 }
1975 CLOCK_EnableClock(kCLOCK_Usbhmr0);
1976 CLOCK_EnableClock(kCLOCK_Usbhsl0);
1977 CLOCK_EnableClock(kCLOCK_UsbRam1);
1978
1979 return ret;
1980}
1981
1982/* Enable USB PHY clock */
1983bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
1984{
1985 volatile uint32_t i;
1986 uint32_t phyPllDiv = 0U;
1987 uint16_t multiplier = 0U;
1988 bool ret = true;
1989
1990 POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);
1991 POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);
1992 POWER_DisablePD(kPDRUNCFG_PD_FRO32K); /*!< Ensure FRO32k is on */
1993 POWER_DisablePD(kPDRUNCFG_PD_XTAL32K); /*!< Ensure xtal32k is on */
1994 POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /*!< Ensure xtal32k is on */
1995 POWER_DisablePD(kPDRUNCFG_PD_LDOUSBHS); /*!< Ensure xtal32k is on */
1996
1997 /* wait to make sure PHY power is fully up */
1998 i = 100000U;
1999 while ((i--) != 0U)
2000 {
2001 __ASM("nop");
2002 }
2003
2004 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL(1);
2005 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_PHY(1);
2006
2007 USBPHY->CTRL_CLR = USBPHY_CTRL_SFTRST_MASK;
2008
2009 multiplier = (uint16_t)(480000000UL / freq);
2010
2011 switch (multiplier)
2012 {
2013 case 15U:
2014 {
2015 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
2016 break;
2017 }
2018 case 16U:
2019 {
2020 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
2021 break;
2022 }
2023 case 20U:
2024 {
2025 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
2026 break;
2027 }
2028 case 24U:
2029 {
2030 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U);
2031 break;
2032 }
2033 case 25U:
2034 {
2035 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U);
2036 break;
2037 }
2038 case 30U:
2039 {
2040 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U);
2041 break;
2042 }
2043 case 40U:
2044 {
2045 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(7U);
2046 break;
2047 }
2048 default:
2049 {
2050 ret = false;
2051 break;
2052 }
2053 }
2054
2055 if (ret)
2056 {
2057 USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~USBPHY_PLL_SIC_PLL_DIV_SEL(0x7)) | phyPllDiv;
2058 USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_REG_ENABLE_MASK;
2059 USBPHY->PLL_SIC_CLR = (1UL << 16U); // Reserved. User must set this bit to 0x0
2060 USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_POWER_MASK;
2061 USBPHY->PLL_SIC_SET = USBPHY_PLL_SIC_SET_PLL_EN_USB_CLKS_MASK;
2062
2063 USBPHY->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK;
2064 USBPHY->PWD_SET = 0x0;
2065 }
2066
2067 return ret;
2068}
2069
2070/* Enable USB DEVICE HIGH SPEED clock */
2071bool CLOCK_EnableUsbhs0DeviceClock(clock_usbhs_src_t src, uint32_t freq)
2072{
2073 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_RAM(1);
2074 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_DEV(1);
2075
2076 /* 16 MHz will be driven by the tb on the xtal1 pin of XTAL32M */
2077 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clock_in clock for clock module. */
2078 ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT(1);
2079 return true;
2080}
2081
2082/* Enable USB HOST HIGH SPEED clock */
2083bool CLOCK_EnableUsbhs0HostClock(clock_usbhs_src_t src, uint32_t freq)
2084{
2085 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_RAM(1);
2086 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_USB1_HOST(1);
2087
2088 /* 16 MHz will be driven by the tb on the xtal1 pin of XTAL32M */
2089 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clock_in clock for clock module. */
2090 ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT(1);
2091
2092 return true;
2093}