2 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * o Redistributions of source code must retain the above copyright notice, this list
9 * of conditions and the following disclaimer.
11 * o Redistributions in binary form must reproduce the above copyright notice, this
12 * list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
15 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "fsl_mcg_hal_modes.h"
33 /*******************************************************************************
35 ******************************************************************************/
37 /*******************************************************************************
39 ******************************************************************************/
41 /*****************************************************************
42 * MCG clock mode transition functions
74 *****************************************************************/
75 /*FUNCTION******************************************************************************
77 * Functon name : CLOCK_HAL_GetMcgMode
78 * Description : internal function will check the mcg registers and determine
79 * the current mcg mode
81 * Return value : mcgMode or error code mcg_modes_t defined in fsl_mcg_hal_modes.h
82 *END***********************************************************************************/
83 mcg_modes_t
CLOCK_HAL_GetMcgMode(uint32_t baseAddr
)
85 /* Check MSG is in FEI mode */
86 if ((CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatFll
) && /* CLKS mux is FLL output (CLKST=0) */
87 (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatInternal
) /* FLL ref is internal ref clk (IREFST=1) */
88 #if FSL_FEATURE_MCG_HAS_PLL
89 && (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatFll
)) /* PLLS mux is FLL (PLLST=0) */
94 return kMcgModeFEI
; /* return FEI code */
96 /* Check MCG is in PEE mode */
97 else if ((CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatPll
) && /* CLKS mux is PLL output (CLKST=3) */
98 (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatExternal
) /* FLL ref is external ref clk (IREFST=0) */
99 #if FSL_FEATURE_MCG_HAS_PLL
100 && (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatPllClkSel
)) /* PLLS mux is PLL or PLLCS (PLLST=1) */
105 return kMcgModePEE
; /* return PEE code */
107 /* Check MCG is in PBE mode */
108 else if ((CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatExternalRef
) && /* CLKS mux is external ref clk (CLKST=2) */
109 (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatExternal
) && /* FLL ref is external ref clk (IREFST=0) */
110 #if FSL_FEATURE_MCG_HAS_PLL
111 (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatPllClkSel
) && /* PLLS mux is PLL or PLLCS (PLLST=1) */
113 (CLOCK_HAL_GetLowPowerMode(baseAddr
) == kMcgLowPowerSelNormal
)) /* MCG_C2[LP] bit is not set (LP=0) */
115 return kMcgModePBE
; /* return PBE code */
117 /* Check MCG is in FBE mode */
118 else if ((CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatExternalRef
) && /* CLKS mux is external ref clk (CLKST=2) */
119 (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatExternal
) && /* FLL ref is external ref clk (IREFST=0) */
120 #if FSL_FEATURE_MCG_HAS_PLL
121 (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatFll
) && /* PLLS mux is FLL (PLLST=0) */
123 (CLOCK_HAL_GetLowPowerMode(baseAddr
) == kMcgLowPowerSelNormal
)) /* MCG_C2[LP] bit is not set (LP=0) */
125 return kMcgModeFBE
; /* return FBE code */
127 /* Check MCG is in BLPE mode */
128 else if ((CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatExternalRef
) && /* CLKS mux is external ref clk (CLKST=2) */
129 (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatExternal
) && /* FLL ref is external ref clk (IREFST=0) */
130 (CLOCK_HAL_GetLowPowerMode(baseAddr
) == kMcgLowPowerSelLowPower
))/* MCG_C2[LP] bit is set (LP=1) */
132 return kMcgModeBLPE
; /* return BLPE code */
134 /* Check if in BLPI mode */
135 else if ((CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatInternalRef
) && /* CLKS mux in internal ref clk (CLKST=1) */
136 (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatInternal
) && /* FLL ref is internal ref clk (IREFST=1) */
137 #if FSL_FEATURE_MCG_HAS_PLL
138 (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatFll
) && /* PLLS mux is FLL (PLLST=0) */
140 (CLOCK_HAL_GetLowPowerMode(baseAddr
) == kMcgLowPowerSelLowPower
))/* MCG_C2[LP] bit is set (LP=1) */
142 return kMcgModeBLPI
; /* return BLPI code */
144 /* Check if in FBI mode */
145 else if ((CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatInternalRef
) && /* CLKS mux in internal ref clk (CLKST=1) */
146 (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatInternal
) && /* FLL ref is internal ref clk (IREFST=1) */
147 #if FSL_FEATURE_MCG_HAS_PLL
148 (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatFll
) && /* PLLS mux is FLL (PLLST=0) */
150 (CLOCK_HAL_GetLowPowerMode(baseAddr
) == kMcgLowPowerSelNormal
)) /* MCG_C2[LP] bit is not set (LP=0) */
152 return kMcgModeFBI
; /* return FBI code */
154 /* Check MCG is in FEE mode */
155 else if ((CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatFll
) && /* CLKS mux is FLL output (CLKST=0) */
156 (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatExternal
) /* FLL ref is external ref clk (IREFST=0) */
157 #if FSL_FEATURE_MCG_HAS_PLL
158 && (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatFll
)) /* PLLS mux is FLL (PLLST=0) */
163 return kMcgModeFEE
; /* return FEE code */
167 return kMcgModeError
; /* error unknown mode */
169 } /* CLOCK_HAL_GetMcgMode */
171 /*FUNCTION******************************************************************************
173 * Functon name : CLOCK_HAL_GetFllFrequency
174 * Description : internal function to check the fll frequency
175 * This function will calculate and check the fll frequency value based on input value.
177 * Parameters: fllRef - fll reference clock in Hz.
179 * Return value : fll output frequency (Hz) or error code
180 *END***********************************************************************************/
181 uint32_t CLOCK_HAL_GetFllFrequency(uint32_t baseAddr
, int32_t fllRef
)
183 int32_t fllFreqHz
= 0;
185 /* Check that only allowed ranges have been selected */
186 if (CLOCK_HAL_GetDigitalControlledOscRangeMode(baseAddr
) > kMcgDigitalControlledOscRangeSelMid
)
188 return kMcgErrFllDrstDrsRange
; /* return error code if DRS range 2 or 3 selected */
192 if (CLOCK_HAL_GetDmx32(baseAddr
))
194 /* determine multiplier based on DRS */
195 switch (CLOCK_HAL_GetDigitalControlledOscRangeMode(baseAddr
))
198 fllFreqHz
= (fllRef
* kMcgConstant732
);
199 if (fllFreqHz
< kMcgConstant20000000
)
201 return kMcgErrFllRange0Min
;
203 else if (fllFreqHz
> kMcgConstant25000000
)
205 return kMcgErrFllRange0Max
;
209 fllFreqHz
= (fllRef
* kMcgConstant1464
);
210 if (fllFreqHz
< kMcgConstant40000000
)
212 return kMcgErrFllRange1Min
;
214 else if (fllFreqHz
> kMcgConstant50000000
)
216 return kMcgErrFllRange1Max
;
220 fllFreqHz
= (fllRef
* kMcgConstant2197
);
221 if (fllFreqHz
< kMcgConstant60000000
)
223 return kMcgErrFllRange2Min
;
225 else if (fllFreqHz
> kMcgConstant75000000
)
227 return kMcgErrFllRange2Max
;
231 fllFreqHz
= (fllRef
* kMcgConstant2929
);
232 if (fllFreqHz
< kMcgConstant80000000
)
234 return kMcgErrFllRange3Min
;
236 else if (fllFreqHz
> kMcgConstant100000000
)
238 return kMcgErrFllRange3Max
;
248 /* determine multiplier based on DRS */
249 switch (CLOCK_HAL_GetDigitalControlledOscRangeMode(baseAddr
))
252 fllFreqHz
= (fllRef
* kMcgConstant640
);
253 if (fllFreqHz
< kMcgConstant20000000
)
255 return kMcgErrFllRange0Min
;
257 else if (fllFreqHz
> kMcgConstant25000000
)
259 return kMcgErrFllRange0Max
;
263 fllFreqHz
= (fllRef
* kMcgConstant1280
);
264 if (fllFreqHz
< kMcgConstant40000000
)
266 return kMcgErrFllRange1Min
;
268 else if (fllFreqHz
> kMcgConstant50000000
)
270 return kMcgErrFllRange1Max
;
274 fllFreqHz
= (fllRef
* kMcgConstant1920
);
275 if (fllFreqHz
< kMcgConstant60000000
)
277 return kMcgErrFllRange2Min
;
279 else if (fllFreqHz
> kMcgConstant75000000
)
281 return kMcgErrFllRange2Max
;
285 fllFreqHz
= (fllRef
* kMcgConstant2560
);
286 if (fllFreqHz
< kMcgConstant80000000
)
288 return kMcgErrFllRange3Min
;
290 else if (fllFreqHz
> kMcgConstant100000000
)
292 return kMcgErrFllRange3Max
;
300 } /* CLOCK_HAL_GetFllFrequency */
303 /*FUNCTION******************************************************************************
305 * Functon name : CLOCK_HAL_SetFeiToFeeMode
306 * Description : Mode transition FEI to FEE mode
307 * This function transitions the MCG from FEI mode to FEE mode.
309 * Parameters: oscselVal - oscillator selection value
310 * (eunm defined in mcg_oscsel_select_t)
311 * 0: kMcgOscselOsc, Selects System Oscillator (OSCCLK)
312 * 1: kMcgOscselRtc, Selects 32 kHz RTC Oscillator
313 * 2: kMcgOscselIrc, Selects 48 MHz IRC Oscillator (K70)
314 * crystalVal - external clock frequency in Hz
316 * erefsVal - 0: osc0 external clock frequency
317 * erefsVal - 1: osc0 crystal clock frequency
318 * oscselVal - 1: RTC 32Khz clock source frequency
319 * oscselVal - 2: IRC 48Mhz clock source frequency
320 * hgoVal - selects whether low power or high gain mode is selected
321 * for the crystal oscillator. This value is only valid when
322 * oscselVal is 0 and erefsVal is 1.
323 * (enum defined in mcg_high_gain_osc_select_t)
324 * 0: kMcgHgoSelectLow, Configure for low-power operation
325 * 1: kMcgHgoSelectHigh, Configure for high-gain operation
326 * erefsVal - selects external clock or crystal osc
327 * (enum defined in mcg_external_ref_clock_select_t)
328 * 0: kMcgErefClockSelectExt, External reference clock requested
329 * 1: kMcgErefClockSelectOsc, Oscillator requested
331 * Return value : MCGCLKOUT frequency (Hz) or error code
332 *END***********************************************************************************/
333 uint32_t CLOCK_HAL_SetFeiToFeeMode(uint32_t baseAddr
, mcg_oscsel_select_t oscselVal
, uint32_t crystalVal
, mcg_high_gain_osc_select_t hgoVal
, mcg_external_ref_clock_select_t erefsVal
)
336 uint32_t mcgOut
, fllRefFreq
, i
;
338 /* check if in FEI mode */
339 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFEI
)
341 return kMcgErrNotInFeiMode
; /* return error code */
344 /* check external frequency is less than the maximum frequency */
345 if (crystalVal
> kMcgConstant50000000
)
347 return kMcgErrOscEtalRange
; /* - external frequency is bigger than max frequency */
350 /* check crystal frequency is within spec. if crystal osc is being used */
351 if (oscselVal
== kMcgOscselOsc
)
355 /* return error if one of the available crystal options is not available */
356 if ((crystalVal
< kMcgConstant30000
) ||
357 ((crystalVal
> kMcgConstant40000
) && (crystalVal
< kMcgConstant3000000
)) ||
358 (crystalVal
> kMcgConstant32000000
))
360 return kMcgErrOscXtalRange
; /* - crystal frequency outside allowed range */
363 /* config the hgo settings */
364 CLOCK_HAL_SetHighGainOsc0Mode(baseAddr
, hgoVal
);
367 /* config the erefs0 settings */
368 CLOCK_HAL_SetExternalRefSel0Mode(baseAddr
, erefsVal
);
372 * the RANGE value is determined by the external frequency. Since the RANGE parameter
373 * affects the FRDIV divide value it still needs to be set correctly even if the
374 * oscillator is not being used
376 if (crystalVal
<= kMcgConstant40000
)
378 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelLow
);
380 else if (crystalVal
<= kMcgConstant8000000
)
382 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelHigh
);
386 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelVeryHigh
);
389 /* determine FRDIV based on reference clock frequency */
390 /* since the external frequency has already been checked only the maximum frequency for each FRDIV value needs to be compared here. */
391 if (crystalVal
<= kMcgConstant1250000
)
393 frDivVal
= kMcgConstant0
;
395 else if (crystalVal
<= kMcgConstant2500000
)
397 frDivVal
= kMcgConstant1
;
399 else if (crystalVal
<= kMcgConstant5000000
)
401 frDivVal
= kMcgConstant2
;
403 else if (crystalVal
<= kMcgConstant10000000
)
405 frDivVal
= kMcgConstant3
;
407 else if (crystalVal
<= kMcgConstant20000000
)
409 frDivVal
= kMcgConstant4
;
413 frDivVal
= kMcgConstant5
;
416 /* The FLL ref clk divide value depends on FRDIV and the RANGE value */
417 if (CLOCK_HAL_GetRange0Mode(baseAddr
) > kMcgFreqRangeSelLow
)
419 fllRefFreq
= ((crystalVal
) / (kMcgConstant32
<< frDivVal
));
423 fllRefFreq
= ((crystalVal
) / (kMcgConstant1
<< frDivVal
));
426 /* Check resulting FLL frequency */
427 /* FLL reference frequency calculated from ext ref freq and FRDIV */
428 mcgOut
= CLOCK_HAL_GetFllFrequency(baseAddr
, fllRefFreq
);
429 if (mcgOut
< kMcgErrMax
)
431 return mcgOut
; /* If error code returned, return the code to calling function */
435 * Select external oscilator and Reference Divider and clear IREFS to start ext osc
436 * If IRCLK is required it must be enabled outside of this driver, existing state will
437 * be maintained CLKS=0, FRDIV=frdivVal, IREFS=0
439 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr
, kMcgClkSelOut
, frDivVal
, kMcgInternalRefClkSrcExternal
);
441 /* if the external oscillator is used need to wait for OSCINIT to set */
442 if ((oscselVal
== kMcgOscselOsc
) && (erefsVal
))
444 for (i
= 0 ; i
< kMcgConstant20000000
; i
++)
446 if (CLOCK_HAL_GetOscInit0(baseAddr
))
448 break; /* jump out early if OSCINIT sets before loop finishes */
452 if (!CLOCK_HAL_GetOscInit0(baseAddr
))
454 /* check bit is really set and return with error if not set */
455 return kMcgErrOscSetTimeout
;
459 /* Wait for clock status bits to show clock source is FLL */
460 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
462 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatFll
)
464 break; // jump out early if CLKST shows FLL selected before loop finishes
468 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatFll
)
470 return kMcgErrClkst0
; // check FLL is really selected and return with error if not
475 * It is recommended that the clock monitor is enabled when using an external clock as the
476 * clock source/reference.
477 * It is enabled here but can be removed if this is not required.
479 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr
, true);
481 return mcgOut
; /* MCGOUT frequency equals FLL frequency */
482 } /* CLOCK_HAL_SetFeiToFeeMode */
484 /*FUNCTION******************************************************************************
486 * Functon name : CLOCK_HAL_SetFeiToFbiMode
487 * Description : Mode transition FEI to FBI mode
488 * This function transitions the MCG from FEI mode to FBI mode.
490 * Parameters: ircFreq - internal reference clock frequency value
491 * ircSelect - slow or fast clock selection
493 * Return value : MCGCLKOUT frequency (Hz) or error code
494 *END***********************************************************************************/
495 uint32_t CLOCK_HAL_SetFeiToFbiMode(uint32_t baseAddr
, uint32_t ircFreq
, mcg_internal_ref_clock_select_t ircSelect
)
500 /* Check MCG is in FEI mode */
501 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFEI
)
503 return kMcgErrNotInFeiMode
; /* return error code */
507 /* Check that the irc frequency matches the selected IRC */
510 if ((ircFreq
< kMcgConstant31250
) || (ircFreq
> kMcgConstant39063
))
512 return kMcgErrIrcSlowRange
;
517 if ((ircFreq
< kMcgConstant3000000
) || (ircFreq
> kMcgConstant5000000
))
519 return kMcgErrIrcFastRange
;
520 } /* Fast IRC freq */
523 /* Select the desired IRC */
524 CLOCK_HAL_SetInternalRefClkSelMode(baseAddr
, ircSelect
);
526 /* Change the CLKS mux to select the IRC as the MCGOUT */
527 CLOCK_HAL_SetClkSrcMode(baseAddr
, kMcgClkSelInternal
);
529 /* Set LP bit to enable the FLL */
530 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelNormal
);
532 /* wait until internal reference switches to requested irc. */
533 if (ircSelect
== kMcgInternalRefClkSelSlow
)
535 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
537 if (!(MCG_S
& MCG_S_IRCST_MASK
))
539 break; /* jump out early if IRCST clears before loop finishes */
542 if (MCG_S
& MCG_S_IRCST_MASK
)
544 /* check bit is really clear and return with error if set */
545 return kMcgErrIrcstClearTimeout
;
550 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
552 if (MCG_S
& MCG_S_IRCST_MASK
)
554 break; /* jump out early if IRCST sets before loop finishes */
557 if (!(MCG_S
& MCG_S_IRCST_MASK
))
559 /* check bit is really set and return with error if not set */
560 return kMcgErrIrefstSetTimeout1
;
564 /* Wait for clock status bits to update */
565 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
567 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatInternalRef
)
569 break; /* jump out early if CLKST shows IRC slected before loop finishes */
573 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatInternalRef
)
575 /* check IRC is really selected and return with error if not */
576 return kMcgErrClkst1
;
579 /* Now in FBI mode */
580 if (ircSelect
== kMcgInternalRefClkSelFast
)
582 fcrDivVal
= CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr
);
584 /* MCGOUT frequency equals fast IRC frequency divided by 2 */
585 return (ircFreq
/ fcrDivVal
);
589 return ircFreq
; /* MCGOUT frequency equals slow IRC frequency */
591 } /* CLOCK_HAL_SetFeiToFbiMode */
593 /*FUNCTION******************************************************************************
595 * Functon name : CLOCK_HAL_SetFeiToFbeMode
596 * Description : Mode transition FEI to FBE mode
597 * This function transitions the MCG from FEI mode to FBE mode.
599 * Parameters: oscselVal - oscillator selection value
600 * 0 - OSC 0, 1 - RTC 32k, 2 - IRC 48M
601 * crystalVal - external clock frequency in Hz
603 * erefsVal - 0: osc0 external clock frequency
604 * erefsVal - 1: osc0 crystal clock frequency
605 * oscselVal - 1: RTC 32Khz clock source frequency
606 * oscselVal - 2: IRC 48Mhz clock source frequency
607 * hgoVal - selects whether low power or high gain mode is selected
608 * for the crystal oscillator. This value is only valid when
609 * oscselVal is 0 and erefsVal is 1.
610 * erefsVal - selects external clock (=0) or crystal osc (=1)
612 * Return value : MCGCLKOUT frequency (Hz) or error code
613 *END***********************************************************************************/
614 uint32_t CLOCK_HAL_SetFeiToFbeMode(uint32_t baseAddr
, mcg_oscsel_select_t oscselVal
, uint32_t crystalVal
, mcg_high_gain_osc_select_t hgoVal
, mcg_external_ref_clock_select_t erefsVal
)
619 /* check if in FEI mode */
620 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFEI
)
622 return kMcgErrNotInFeiMode
; /* return error code */
625 /* check external frequency is less than the maximum frequency */
626 if (crystalVal
> kMcgConstant50000000
)
628 /* - external frequency is bigger than max frequency */
629 return kMcgErrOscEtalRange
;
632 /* check crystal frequency is within spec. if crystal osc is being used */
633 if (oscselVal
== kMcgOscselOsc
)
637 /* return error if one of the available crystal options is not available */
638 if ((crystalVal
< kMcgConstant30000
) ||
639 ((crystalVal
> kMcgConstant40000
) && (crystalVal
< kMcgConstant3000000
)) ||
640 (crystalVal
> kMcgConstant32000000
))
642 /* - crystal frequency outside allowed range */
643 return kMcgErrOscXtalRange
;
646 /* config the hgo settings */
647 CLOCK_HAL_SetHighGainOsc0Mode(baseAddr
, hgoVal
);
650 /* config the erefs0 settings */
651 CLOCK_HAL_SetExternalRefSel0Mode(baseAddr
, erefsVal
);
655 * the RANGE value is determined by the external frequency. Since the RANGE parameter
656 * affects the FRDIV divide value it still needs to be set correctly even if the
657 * oscillator is not being used
659 if (crystalVal
<= kMcgConstant40000
)
661 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelLow
);
663 else if (crystalVal
<= kMcgConstant8000000
)
665 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelHigh
);
669 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelVeryHigh
);
672 /* determine FRDIV based on reference clock frequency */
673 /* since the external frequency has already been checked only the maximum frequency for each FRDIV value needs to be compared here. */
674 if (crystalVal
<= kMcgConstant1250000
)
676 frDivVal
= kMcgConstant0
;
678 else if (crystalVal
<= kMcgConstant2500000
)
680 frDivVal
= kMcgConstant1
;
682 else if (crystalVal
<= kMcgConstant5000000
)
684 frDivVal
= kMcgConstant2
;
686 else if (crystalVal
<= kMcgConstant10000000
)
688 frDivVal
= kMcgConstant3
;
690 else if (crystalVal
<= kMcgConstant20000000
)
692 frDivVal
= kMcgConstant4
;
696 frDivVal
= kMcgConstant5
;
699 /* Set LP bit to enable the FLL */
700 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelNormal
);
703 * Select external oscilator and Reference Divider and clear IREFS to start ext osc
704 * If IRCLK is required it must be enabled outside of this driver, existing state will
705 * be maintained CLKS=0, FRDIV=frdivVal, IREFS=0
707 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr
, kMcgClkSelExternal
, frDivVal
, kMcgInternalRefClkSrcExternal
);
709 /* if the external oscillator is used need to wait for OSCINIT to set */
710 if ((oscselVal
== kMcgOscselOsc
) && (erefsVal
))
712 for (i
= 0 ; i
< kMcgConstant10000
; i
++)
714 if (CLOCK_HAL_GetOscInit0(baseAddr
))
716 break; /* jump out early if OSCINIT sets before loop finishes */
720 if (!CLOCK_HAL_GetOscInit0(baseAddr
))
722 /* check bit is really set and return with error if not set */
723 return kMcgErrOscSetTimeout
;
727 /* wait for Reference clock Status bit to clear */
728 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
730 if (!CLOCK_HAL_GetInternalRefStatMode(baseAddr
))
732 break; /* jump out early if IREFST clears before loop finishes */
736 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
))
738 /* check bit is really clear and return with error if not set */
739 return kMcgErrIrefstClearTimeOut
;
742 /* Wait for clock status bits to show clock source is ext ref clk */
743 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
745 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatExternalRef
)
747 break; /* jump out early if CLKST shows EXT CLK slected before loop finishes */
751 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatExternalRef
)
753 return kMcgErrClkst2
; /* check EXT CLK is really selected and return with error if not */
758 * It is recommended that the clock monitor is enabled when using an external clock as the clock source/reference.
759 * It is enabled here but can be removed if this is not required.
761 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr
, true);
763 return crystalVal
; /* MCGOUT frequency equals external clock frequency */
764 } /* CLOCK_HAL_SetFeiToFbeMode */
766 /*FUNCTION******************************************************************************
768 * Functon name : CLOCK_HAL_SetFeeToFeiMode
769 * Description : Mode transition FEE to FEI mode
770 * This function transitions the MCG from FEE mode to FEI mode.
772 * Parameters: ircFreq - internal reference clock frequency value (slow)
774 * Return value : MCGCLKOUT frequency (Hz) or error code
775 *END***********************************************************************************/
776 uint32_t CLOCK_HAL_SetFeeToFeiMode(uint32_t baseAddr
, uint32_t ircFreq
)
781 /* Check MCG is in FEE mode */
782 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFEE
)
784 return kMcgErrNotInFeeMode
; /* return error code */
787 /* Check IRC frequency is within spec. */
788 if ((ircFreq
< kMcgConstant31250
) || (ircFreq
> kMcgConstant39063
))
790 return kMcgErrIrcSlowRange
;
793 /* Check resulting FLL frequency */
794 mcgOut
= CLOCK_HAL_GetFllFrequency(baseAddr
, ircFreq
);
795 if (mcgOut
< kMcgErrMax
)
797 /* If error code returned, return the code to calling function */
801 /* Ensure clock monitor is disabled before switching to FEI otherwise
802 * a loss of clock will trigger
804 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr
, false);
806 /* Change FLL reference clock from external to internal by setting IREFS bit */
807 CLOCK_HAL_SetInternalRefSelMode(baseAddr
, kMcgInternalRefClkSrcSlow
);
809 /* wait for Reference clock to switch to internal reference */
810 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
812 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatInternal
)
814 break; /* jump out early if IREFST sets before loop finishes */
818 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) != kMcgInternalRefStatInternal
)
820 /* check bit is really set and return with error if not set */
821 return kMcgErrIrefstSetTimeout
;
824 /* Now in FEI mode */
826 } /* CLOCK_HAL_SetFeeToFeiMode */
828 /*FUNCTION******************************************************************************
830 * Functon name : CLOCK_HAL_SetFeeToFbiMode
831 * Description : Mode transition FEE to FBI mode
832 * This function transitions the MCG from FEE mode to FBI mode.
834 * Parameters: ircFreq - internal reference clock frequency value
835 * ircSelect - slow or fast clock selection
838 * Return value : MCGCLKOUT frequency (Hz) or error code
839 *END***********************************************************************************/
840 uint32_t CLOCK_HAL_SetFeeToFbiMode(uint32_t baseAddr
, uint32_t ircFreq
, mcg_internal_ref_clock_select_t ircSelect
)
845 /* Check MCG is in FEE mode */
846 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFEE
)
848 return kMcgErrNotInFeeMode
; /* return error code */
851 /* Check that the irc frequency matches the selected IRC */
854 if ((ircFreq
< kMcgConstant31250
) || (ircFreq
> kMcgConstant39063
))
856 return kMcgErrIrcSlowRange
;
861 if ((ircFreq
< kMcgConstant3000000
) || (ircFreq
> kMcgConstant5000000
))
863 return kMcgErrIrcFastRange
;
864 } /* Fast IRC freq */
867 /* Select the required IRC */
868 CLOCK_HAL_SetInternalRefClkSelMode(baseAddr
, ircSelect
);
870 /* Make sure the clock monitor is disabled before switching modes otherwise it will trigger */
871 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr
, false);
873 /* Select the IRC as the CLKS mux selection */
874 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr
, kMcgClkSelInternal
, CLOCK_HAL_GetFllExternalRefDivider(baseAddr
), kMcgInternalRefClkSrcSlow
);
876 /* wait until internal reference switches to requested irc. */
877 if (ircSelect
== kMcgInternalRefClkSelSlow
)
879 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
881 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr
) == kMcgInternalRefClkStatSlow
)
883 break; /* jump out early if IRCST clears before loop finishes */
886 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr
) != kMcgInternalRefClkStatSlow
)
888 /* check bit is really clear and return with error if set */
889 return kMcgErrIrcstClearTimeout
;
894 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
896 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr
) == kMcgInternalRefClkStatFast
)
898 break; /* jump out early if IRCST sets before loop finishes */
901 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr
) != kMcgInternalRefClkStatFast
)
903 /* check bit is really set and return with error if not set */
904 return kMcgErrIrefstSetTimeout1
;
908 /* Wait for clock status bits to update */
909 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
911 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatInternalRef
)
913 break; /* jump out early if CLKST shows IRC slected before loop finishes */
917 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatInternalRef
)
919 return kMcgErrClkst1
; /* check IRC is really selected and return with error if not */
922 /* wait for Reference clock Status bit to set */
923 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
925 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatInternal
)
927 break; /* jump out early if IREFST sets before loop finishes */
931 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) != kMcgInternalRefStatInternal
)
933 /* check bit is really set and return with error if not set */
934 return kMcgErrIrefstSetTimeout
;
937 /* Now in FBI mode */
938 if (ircSelect
== kMcgInternalRefClkSelFast
)
940 fcrDivVal
= CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr
);
942 return (ircFreq
/ fcrDivVal
); /* MCGOUT frequency equals fast IRC frequency divided by 2 */
946 return ircFreq
; /* MCGOUT frequency equals slow IRC frequency */
948 } /* CLOCK_HAL_SetFeeToFbiMode */
950 /*FUNCTION******************************************************************************
952 * Functon name : CLOCK_HAL_SetFeeToFbeMode
953 * Description : Mode transition FEE to FBE mode
954 * This function transitions the MCG from FEE mode to FBE mode.
956 * Parameters: crystalVal - external reference clock frequency value
958 * Return value : MCGCLKOUT frequency (Hz) or error code
959 *END***********************************************************************************/
960 uint32_t CLOCK_HAL_SetFeeToFbeMode(uint32_t baseAddr
, uint32_t crystalVal
)
964 /* Check MCG is in FEE mode */
965 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFEE
)
967 return kMcgErrNotInFeeMode
; /* return error code */
970 /* Set CLKS field to 2 to switch CLKS mux to select ext ref clock */
971 CLOCK_HAL_SetClkSrcMode(baseAddr
, kMcgClkSelExternal
);
973 /* Wait for clock status bits to show clock source is ext ref clk */
974 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
976 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatExternalRef
)
978 break; /* jump out early if CLKST shows EXT CLK slected before loop finishes */
982 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatExternalRef
)
984 return kMcgErrClkst2
; /* check EXT CLK is really selected and return with error if not */
987 /* Now in FBE mode */
989 } /* CLOCK_HAL_SetFeeToFbeMode */
991 /*FUNCTION******************************************************************************
993 * Functon name : CLOCK_HAL_SetFbiToFeiMode
994 * Description : Mode transition FBI to FEI mode
995 * This function transitions the MCG from FBI mode to FEI mode.
997 * Parameters: ircFreq - internal reference clock frequency value (slow)
999 * Return value : MCGCLKOUT frequency (Hz) or error code
1000 *END***********************************************************************************/
1001 uint32_t CLOCK_HAL_SetFbiToFeiMode(uint32_t baseAddr
, uint32_t ircFreq
)
1006 /* check if in FBI mode */
1007 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBI
)
1009 return kMcgErrNotInFbiMode
; /* MCG not in correct mode return fail code */
1012 /* Check IRC frequency is within spec. */
1013 if ((ircFreq
< 31250) || (ircFreq
> 39063))
1015 return kMcgErrIrcSlowRange
;
1018 /* Check resulting FLL frequency */
1019 mcgOut
= CLOCK_HAL_GetFllFrequency(baseAddr
, ircFreq
);
1020 if (mcgOut
< kMcgErrMax
)
1022 /* If error code returned, return the code to calling function */
1026 /* Change the CLKS mux to select the FLL output as MCGOUT */
1027 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr
, kMcgClkSelOut
, CLOCK_HAL_GetFllExternalRefDivider(baseAddr
), kMcgInternalRefClkSrcSlow
);
1029 /* wait for Reference clock Status bit to clear */
1030 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1032 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
))
1034 break; /* jump out early if IREFST clears before loop finishes */
1038 if (!CLOCK_HAL_GetInternalRefStatMode(baseAddr
))
1040 /* check bit is really set and return with error if not set */
1041 return kMcgErrIrefstSetTimeout
;
1044 /* Wait for clock status bits to show clock source is ext ref clk */
1045 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1047 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatFll
)
1049 break; /* jump out early if CLKST shows FLL slected before loop finishes */
1053 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatFll
)
1055 return kMcgErrClkst0
; /* check FLL is really selected and return with error if not */
1058 /* Now in FEI mode */
1060 } /* CLOCK_HAL_SetFbiToFeiMode */
1062 /*FUNCTION******************************************************************************
1064 * Functon name : CLOCK_HAL_SetFbiToFeeMode
1065 * Description : Mode transition FBI to FEE mode
1066 * This function transitions the MCG from FBI mode to FEE mode.
1068 * Parameters: oscselVal - oscillator selection value
1069 * 0 - OSC 0, 1 - RTC 32k, 2 - IRC 48M
1070 * crystalVal - external clock frequency in Hz
1072 * erefsVal - 0: osc0 external clock frequency
1073 * erefsVal - 1: osc0 crystal clock frequency
1074 * oscselVal - 1: RTC 32Khz clock source frequency
1075 * oscselVal - 2: IRC 48Mhz clock source frequency
1076 * hgoVal - selects whether low power or high gain mode is selected
1077 * for the crystal oscillator. This value is only valid when
1078 * oscselVal is 0 and erefsVal is 1.
1079 * erefsVal - selects external clock (=0) or crystal osc (=1)
1081 * Return value : MCGCLKOUT frequency (Hz) or error code
1082 *END***********************************************************************************/
1083 uint32_t CLOCK_HAL_SetFbiToFeeMode(uint32_t baseAddr
, mcg_oscsel_select_t oscselVal
, uint32_t crystalVal
, mcg_high_gain_osc_select_t hgoVal
, mcg_external_ref_clock_select_t erefsVal
)
1087 uint32_t mcgOut
, fllRefFreq
;
1089 /* check if in FBI mode */
1090 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBI
)
1092 return kMcgErrNotInFbiMode
; /* MCG not in correct mode return fail code */
1095 /* check external frequency is less than the maximum frequency */
1096 if (crystalVal
> kMcgConstant50000000
)
1098 return kMcgErrOscEtalRange
;
1101 /* check crystal frequency is within spec. if crystal osc is being used */
1102 if (oscselVal
== kMcgOscselOsc
)
1106 /* return error if one of the available crystal options is not available */
1107 if ((crystalVal
< kMcgConstant30000
) ||
1108 ((crystalVal
> kMcgConstant40000
) && (crystalVal
< kMcgConstant3000000
)) ||
1109 (crystalVal
> kMcgConstant32000000
))
1111 return kMcgErrOscXtalRange
; /* - crystal frequency outside allowed range */
1114 /* config the hgo settings */
1115 CLOCK_HAL_SetHighGainOsc0Mode(baseAddr
, hgoVal
);
1118 /* config the erefs0 settings */
1119 CLOCK_HAL_SetExternalRefSel0Mode(baseAddr
, erefsVal
);
1123 * the RANGE value is determined by the external frequency. Since the RANGE parameter
1124 * affects the FRDIV divide value it still needs to be set correctly even if the
1125 * oscillator is not being used
1127 if (crystalVal
<= kMcgConstant40000
)
1129 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelLow
);
1131 else if (crystalVal
<= kMcgConstant8000000
)
1133 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelHigh
);
1137 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelVeryHigh
);
1140 /* determine FRDIV based on reference clock frequency */
1141 /* since the external frequency has already been checked only the maximum frequency for each FRDIV
1142 * value needs to be compared here.
1144 if (crystalVal
<= kMcgConstant1250000
)
1146 frDivVal
= kMcgConstant0
;
1148 else if (crystalVal
<= kMcgConstant2500000
)
1150 frDivVal
= kMcgConstant1
;
1152 else if (crystalVal
<= kMcgConstant5000000
)
1154 frDivVal
= kMcgConstant2
;
1156 else if (crystalVal
<= kMcgConstant10000000
)
1158 frDivVal
= kMcgConstant3
;
1160 else if (crystalVal
<= kMcgConstant20000000
)
1162 frDivVal
= kMcgConstant4
;
1166 frDivVal
= kMcgConstant5
;
1169 /* The FLL ref clk divide value depends on FRDIV and the RANGE value */
1170 if (CLOCK_HAL_GetRange0Mode(baseAddr
) > kMcgFreqRangeSelLow
)
1172 fllRefFreq
= ((crystalVal
) / (kMcgConstant32
<< frDivVal
));
1176 fllRefFreq
= ((crystalVal
) / (kMcgConstant1
<< frDivVal
));
1179 /* Check resulting FLL frequency */
1180 /* FLL reference frequency calculated from ext ref freq and FRDIV */
1181 mcgOut
= CLOCK_HAL_GetFllFrequency(baseAddr
, fllRefFreq
);
1182 if (mcgOut
< kMcgErrMax
)
1184 return mcgOut
; /* If error code returned, return the code to calling function */
1188 * Select external oscilator and Reference Divider and clear IREFS to start ext osc
1189 * If IRCLK is required it must be enabled outside of this driver, existing state will
1190 * be maintained CLKS=0, FRDIV=frdivVal, IREFS=0
1192 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr
, kMcgClkSelOut
, frDivVal
, kMcgInternalRefClkSrcExternal
);
1194 /* if the external oscillator is used need to wait for OSCINIT to set */
1195 if ((oscselVal
== kMcgOscselOsc
) && (erefsVal
))
1197 for (i
= 0 ; i
< kMcgConstant20000000
; i
++)
1199 if (CLOCK_HAL_GetOscInit0(baseAddr
))
1201 break; /* jump out early if OSCINIT sets before loop finishes */
1205 if (!CLOCK_HAL_GetOscInit0(baseAddr
))
1207 /* check bit is really set and return with error if not set */
1208 return kMcgErrOscSetTimeout
;
1212 /* Wait for clock status bits to show clock source is FLL */
1213 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1215 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatFll
)
1217 break; // jump out early if CLKST shows FLL selected before loop finishes
1221 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatFll
)
1223 return kMcgErrClkst0
; // check FLL is really selected and return with error if not
1228 * It is recommended that the clock monitor is enabled when using an external clock as the
1229 * clock source/reference.
1230 * It is enabled here but can be removed if this is not required.
1232 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr
, true);
1234 return mcgOut
; /* MCGOUT frequency equals FLL frequency */
1235 } /* CLOCK_HAL_SetFbiToFeeMode */
1237 /*FUNCTION******************************************************************************
1239 * Functon name : CLOCK_HAL_SetFbiToFbeMode
1240 * Description : Mode transition FBI to FBE mode
1241 * This function transitions the MCG from FBI mode to FBE mode.
1243 * Parameters: oscselVal - oscillator selection value
1244 * 0 - OSC 0, 1 - RTC 32k, 2 - IRC 48M
1245 * crystalVal - external clock frequency in Hz
1247 * erefsVal - 0: osc0 external clock frequency
1248 * erefsVal - 1: osc0 crystal clock frequency
1249 * oscselVal - 1: RTC 32Khz clock source frequency
1250 * oscselVal - 2: IRC 48Mhz clock source frequency
1251 * hgoVal - selects whether low power or high gain mode is selected
1252 * for the crystal oscillator. This value is only valid when
1253 * oscselVal is 0 and erefsVal is 1.
1254 * erefsVal - selects external clock (=0) or crystal osc (=1)
1256 * Return value : MCGCLKOUT frequency (Hz) or error code
1257 *END***********************************************************************************/
1258 uint32_t CLOCK_HAL_SetFbiToFbeMode(uint32_t baseAddr
, mcg_oscsel_select_t oscselVal
, uint32_t crystalVal
, mcg_high_gain_osc_select_t hgoVal
, mcg_external_ref_clock_select_t erefsVal
)
1263 /* check if in FBI mode */
1264 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBI
)
1266 return kMcgErrNotInFbiMode
; /* MCG not in correct mode return fail code */
1269 /* check external frequency is less than the maximum frequency */
1270 if (crystalVal
> kMcgConstant50000000
)
1272 return kMcgErrOscEtalRange
;
1275 /* check crystal frequency is within spec. if crystal osc is being used */
1276 if (oscselVal
== kMcgOscselOsc
)
1280 /* return error if one of the available crystal options is not available */
1281 if ((crystalVal
< kMcgConstant30000
) ||
1282 ((crystalVal
> kMcgConstant40000
) && (crystalVal
< kMcgConstant3000000
)) ||
1283 (crystalVal
> kMcgConstant32000000
))
1285 return kMcgErrOscXtalRange
; /* - crystal frequency outside allowed range */
1288 /* config the hgo settings */
1289 CLOCK_HAL_SetHighGainOsc0Mode(baseAddr
, hgoVal
);
1292 /* config the erefs0 settings */
1293 CLOCK_HAL_SetExternalRefSel0Mode(baseAddr
, erefsVal
);
1297 * the RANGE value is determined by the external frequency. Since the RANGE parameter
1298 * affects the FRDIV divide value it still needs to be set correctly even if the
1299 * oscillator is not being used
1301 if (crystalVal
<= kMcgConstant40000
)
1303 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelLow
);
1305 else if (crystalVal
<= kMcgConstant8000000
)
1307 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelHigh
);
1311 CLOCK_HAL_SetRange0Mode(baseAddr
, kMcgFreqRangeSelVeryHigh
);
1314 /* determine FRDIV based on reference clock frequency */
1315 /* since the external frequency has already been checked only the maximum frequency for each FRDIV
1316 * value needs to be compared here.
1318 if (crystalVal
<= kMcgConstant1250000
)
1320 frDivVal
= kMcgConstant0
;
1322 else if (crystalVal
<= kMcgConstant2500000
)
1324 frDivVal
= kMcgConstant1
;
1326 else if (crystalVal
<= kMcgConstant5000000
)
1328 frDivVal
= kMcgConstant2
;
1330 else if (crystalVal
<= kMcgConstant10000000
)
1332 frDivVal
= kMcgConstant3
;
1334 else if (crystalVal
<= kMcgConstant20000000
)
1336 frDivVal
= kMcgConstant4
;
1340 frDivVal
= kMcgConstant5
;
1343 /* Set LP bit to enable the FLL */
1344 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelNormal
);
1347 * Select external oscilator and Reference Divider and clear IREFS to start ext osc
1348 * If IRCLK is required it must be enabled outside of this driver, existing state will be maintained
1349 * CLKS=2, FRDIV=frdiv_val, IREFS=0
1351 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr
, kMcgClkSelExternal
, frDivVal
, kMcgInternalRefClkSrcExternal
);
1353 /* if the external oscillator is used need to wait for OSCINIT to set */
1354 if ((oscselVal
== kMcgOscselOsc
) && (erefsVal
))
1356 for (i
= 0 ; i
< kMcgConstant10000
; i
++)
1358 if (CLOCK_HAL_GetOscInit0(baseAddr
))
1360 break; /* jump out early if OSCINIT sets before loop finishes */
1364 if (!CLOCK_HAL_GetOscInit0(baseAddr
))
1366 /* check bit is really set and return with error if not set */
1367 return kMcgErrOscSetTimeout
;
1371 /* wait for Reference clock Status bit to clear */
1372 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1374 if (!CLOCK_HAL_GetInternalRefStatMode(baseAddr
))
1376 break; /* jump out early if IREFST clears before loop finishes */
1380 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
))
1382 /* check bit is really clear and return with error if not set */
1383 return kMcgErrIrefstClearTimeOut
;
1386 /* Wait for clock status bits to show clock source is ext ref clk */
1387 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1389 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatExternalRef
)
1391 break; /* jump out early if CLKST shows EXT CLK slected before loop finishes */
1395 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatExternalRef
)
1397 return kMcgErrClkst2
; /* check EXT CLK is really selected and return with error if not */
1402 * It is recommended that the clock monitor is enabled when using an external clock as the clock source/reference.
1403 * It is enabled here but can be removed if this is not required.
1405 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr
, true);
1407 return crystalVal
; /* MCGOUT frequency equals external clock frequency */
1408 } /* CLOCK_HAL_SetFbiToFbeMode */
1410 /*FUNCTION******************************************************************************
1412 * Functon name : CLOCK_HAL_SetFbiToBlpiMode
1413 * Description : Mode transition FBI to BLPI mode
1414 * This function transitions the MCG from FBI mode to BLPI mode.This is
1415 * achieved by setting the MCG_C2[LP] bit.
1417 * Parameters: ircFreq - internal reference clock frequency value
1418 * ircSelect - slow or fast clock selection
1421 * Return value : MCGCLKOUT frequency (Hz) or error code
1422 *END***********************************************************************************/
1423 uint32_t CLOCK_HAL_SetFbiToBlpiMode(uint32_t baseAddr
, uint32_t ircFreq
, mcg_internal_ref_clock_select_t ircSelect
)
1427 /* check if in FBI mode */
1428 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBI
)
1430 return kMcgErrNotInFbiMode
; /* MCG not in correct mode return fail code */
1433 /* Set LP bit to disable the FLL and enter BLPI */
1434 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelLowPower
);
1437 if (ircSelect
== kMcgInternalRefClkSelFast
)
1439 fcrDivVal
= CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr
);
1440 return (ircFreq
/ fcrDivVal
); /* MCGOUT frequency equals fast IRC frequency divided by 2 */
1444 return ircFreq
; /* MCGOUT frequency equals slow IRC frequency */
1446 } /* CLOCK_HAL_SetFbiToBlpiMode */
1448 /*FUNCTION******************************************************************************
1450 * Functon name : CLOCK_HAL_SetBlpiToFbiMode
1451 * Description : Mode transition BLPI to FBI mode
1452 * This function transitions the MCG from BLPI mode to FBI mode.This is
1453 * achieved by clearing the MCG_C2[LP] bit.
1455 * Parameters: ircFreq - internal reference clock frequency value
1456 * ircSelect - slow or fast clock selection
1459 * Return value : MCGCLKOUT frequency (Hz) or error code
1460 *END***********************************************************************************/
1461 uint32_t CLOCK_HAL_SetBlpiToFbiMode(uint32_t baseAddr
, uint32_t ircFreq
, uint8_t ircSelect
)
1465 /* check if in BLPI mode */
1466 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeBLPI
)
1468 return kMcgErrNotInBlpiMode
; /* MCG not in correct mode return fail code */
1471 /* Clear LP bit to enable the FLL and enter FBI mode */
1472 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelNormal
);
1474 /* Now in FBI mode */
1477 fcrDivVal
= CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr
);
1478 return (ircFreq
/ fcrDivVal
); /* MCGOUT frequency equals fast IRC frequency divided by 2 */
1482 return ircFreq
; /* MCGOUT frequency equals slow IRC frequency */
1484 } /* CLOCK_HAL_SetBlpiToFbiMode */
1486 /*FUNCTION******************************************************************************
1488 * Functon name : CLOCK_HAL_SetFbeToFeeMode
1489 * Description : Mode transition FBE to FEE mode
1490 * This function transitions the MCG from FBE mode to FEE mode.
1492 * Parameters: crystalVal - external reference clock frequency value
1494 * Return value : MCGCLKOUT frequency (Hz) or error code
1495 *END***********************************************************************************/
1496 uint32_t CLOCK_HAL_SetFbeToFeeMode(uint32_t baseAddr
, uint32_t crystalVal
)
1498 uint16_t i
, fllRefFreq
, frDivVal
;
1501 /* Check MCG is in FBE mode */
1502 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBE
)
1504 return kMcgErrNotInFbeMode
; /* return error code */
1507 /* get curretn frdiv value */
1508 frDivVal
= CLOCK_HAL_GetFllExternalRefDivider(baseAddr
);
1510 /* The FLL ref clk divide value depends on FRDIV and the RANGE value */
1511 if (CLOCK_HAL_GetRange0Mode(baseAddr
) > kMcgFreqRangeSelLow
)
1513 fllRefFreq
= ((crystalVal
) / (kMcgConstant32
<< frDivVal
));
1517 fllRefFreq
= ((crystalVal
) / (kMcgConstant1
<< frDivVal
));
1520 /* Check resulting FLL frequency */
1521 /* FLL reference frequency calculated from ext ref freq and FRDIV */
1522 mcgOut
= CLOCK_HAL_GetFllFrequency(baseAddr
, fllRefFreq
);
1523 if (mcgOut
< kMcgErrMax
)
1525 return mcgOut
; /* If error code returned, return the code to calling function */
1528 /* Clear CLKS field to switch CLKS mux to select FLL output */
1529 CLOCK_HAL_SetClkSrcMode(baseAddr
, kMcgClkSelOut
);
1531 /* Wait for clock status bits to show clock source is FLL */
1532 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1534 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatFll
)
1536 break; // jump out early if CLKST shows FLL selected before loop finishes
1540 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatFll
)
1542 return kMcgErrClkst0
; // check FLL is really selected and return with error if not
1545 /* Now in FEE mode */
1547 } /* CLOCK_HAL_SetFbeToFeeMode */
1549 /*FUNCTION******************************************************************************
1551 * Functon name : CLOCK_HAL_SetFbeToFeiMode
1552 * Description : Mode transition FBE to FEI mode
1553 * This function transitions the MCG from FBE mode to FEI mode.
1555 * Parameters: ircFreq - internal reference clock frequency value (slow)
1557 * Return value : MCGCLKOUT frequency (Hz) or error code
1558 *END***********************************************************************************/
1559 uint32_t CLOCK_HAL_SetFbeToFeiMode(uint32_t baseAddr
, uint32_t ircFreq
)
1564 /* Check MCG is in FBE mode */
1565 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBE
)
1567 return kMcgErrNotInFbeMode
; /* return error code */
1570 /* Check IRC frequency is within spec. */
1571 if ((ircFreq
< kMcgConstant31250
) || (ircFreq
> kMcgConstant39063
))
1573 return kMcgErrIrcSlowRange
;
1576 /* Check resulting FLL frequency */
1577 mcgOut
= CLOCK_HAL_GetFllFrequency(baseAddr
, ircFreq
);
1578 if (mcgOut
< kMcgErrMax
)
1580 /* If error code returned, return the code to calling function */
1585 * Ensure clock monitor is disabled before switching to FEI otherwise
1586 * a loss of clock will trigger. This assumes OSC0 is used as the external clock source.
1588 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr
, false);
1590 // Move to FEI by setting CLKS to 0 and enabling the slow IRC as the FLL reference clock
1591 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr
, kMcgClkSelOut
, CLOCK_HAL_GetFllExternalRefDivider(baseAddr
), kMcgInternalRefClkSrcSlow
);
1593 /* wait for Reference clock to switch to internal reference */
1594 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1596 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatInternal
)
1598 break; /* jump out early if IREFST sets before loop finishes */
1602 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) != kMcgInternalRefStatInternal
)
1604 /* check bit is really set and return with error if not set */
1605 return kMcgErrIrefstSetTimeout
;
1608 /* Wait for clock status bits to show clock source is FLL output */
1609 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1611 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatFll
)
1613 /* jump out early if CLKST shows FLL output slected before loop finishes */
1618 /* check FLL output is really selected */
1619 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatFll
)
1621 /* return with error if not */
1622 return kMcgErrClkst0
;
1625 /* Now in FEI mode */
1627 } /* CLOCK_HAL_SetFbeToFeiMode */
1629 /*FUNCTION******************************************************************************
1631 * Functon name : CLOCK_HAL_SetFbeToFbiMode
1632 * Description : Mode transition FBE to FBI mode
1633 * This function transitions the MCG from FBE mode to FBI mode.
1635 * Parameters: ircFreq - internal reference clock frequency value
1636 * ircSelect - slow or fast clock selection
1639 * Return value : MCGCLKOUT frequency (Hz) or error code
1640 *END***********************************************************************************/
1641 uint32_t CLOCK_HAL_SetFbeToFbiMode(uint32_t baseAddr
, uint32_t ircFreq
, mcg_internal_ref_clock_select_t ircSelect
)
1646 /* Check MCG is in FBE mode */
1647 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBE
)
1649 return kMcgErrNotInFbeMode
; /* return error code */
1652 /* Check that the irc frequency matches the selected IRC */
1655 if ((ircFreq
< kMcgConstant31250
) || (ircFreq
> kMcgConstant39063
))
1657 return kMcgErrIrcSlowRange
;
1662 if ((ircFreq
< kMcgConstant3000000
) || (ircFreq
> kMcgConstant5000000
))
1664 return kMcgErrIrcFastRange
;
1665 } /* Fast IRC freq */
1668 /* Select the required IRC */
1669 CLOCK_HAL_SetInternalRefClkSelMode(baseAddr
, ircSelect
);
1671 /* Make sure the clock monitor is disabled before switching modes otherwise it will trigger */
1672 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr
, false);
1674 /* Select the IRC as the CLKS mux selection */
1675 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr
, kMcgClkSelInternal
, CLOCK_HAL_GetFllExternalRefDivider(baseAddr
), kMcgInternalRefClkSrcSlow
);
1677 /* wait until internal reference switches to requested irc. */
1678 if (ircSelect
== kMcgInternalRefClkSelSlow
)
1680 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1682 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr
) == kMcgInternalRefClkStatSlow
)
1684 break; /* jump out early if IRCST clears before loop finishes */
1687 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr
) != kMcgInternalRefClkStatSlow
)
1689 /* check bit is really clear and return with error if set */
1690 return kMcgErrIrcstClearTimeout
;
1695 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1697 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr
) == kMcgInternalRefClkStatFast
)
1699 break; /* jump out early if IRCST sets before loop finishes */
1702 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr
) != kMcgInternalRefClkStatFast
)
1704 /* check bit is really set and return with error if not set */
1705 return kMcgErrIrefstSetTimeout1
;
1709 /* Wait for clock status bits to update */
1710 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1712 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatInternalRef
)
1714 break; /* jump out early if CLKST shows IRC slected before loop finishes */
1718 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatInternalRef
)
1720 return kMcgErrClkst1
; /* check IRC is really selected and return with error if not */
1723 /* wait for Reference clock Status bit to set */
1724 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1726 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) == kMcgInternalRefStatInternal
)
1728 break; /* jump out early if IREFST sets before loop finishes */
1732 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr
) != kMcgInternalRefStatInternal
)
1734 /* check bit is really set and return with error if not set */
1735 return kMcgErrIrefstSetTimeout
;
1738 /* Now in FBI mode */
1739 if (ircSelect
== kMcgInternalRefClkSelFast
)
1741 fcrDivVal
= CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr
);
1743 return (ircFreq
/ fcrDivVal
); /* MCGOUT frequency equals fast IRC frequency divided by 2 */
1747 return ircFreq
; /* MCGOUT frequency equals slow IRC frequency */
1749 } /* CLOCK_HAL_SetFbeToFbiMode */
1751 #if FSL_FEATURE_MCG_HAS_PLL
1753 /*FUNCTION******************************************************************************
1755 * Functon name : CLOCK_HAL_SetFbeToPbeMode
1756 * Description : Mode transition FBE to PBE mode
1757 * This function transitions the MCG from FBE mode to PBE mode.
1758 * The function requires the desired OSC and PLL be passed in to it for compatibility
1759 * with the future support of OSC/PLL selection
1760 * (This function presently only supports OSC0 as PLL source)
1761 * Parameters: crystalVal - external clock frequency in Hz
1762 * pllcsSelect - 0 to select PLL0, non-zero to select PLL1.
1763 * prdivVal - value to divide the external clock source by to create
1764 * the desired PLL reference clock frequency
1765 * vdivVal - value to multiply the PLL reference clock frequency by
1767 * Return value : MCGCLKOUT frequency (Hz) or error code
1768 *END***********************************************************************************/
1769 uint32_t CLOCK_HAL_SetFbeToPbeMode(uint32_t baseAddr
, uint32_t crystalVal
, mcg_pll_clk_select_t pllcsSelect
,
1770 uint8_t prdivVal
, uint8_t vdivVal
)
1775 /* Check MCG is in FBE mode */
1776 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBE
)
1778 return kMcgErrNotInFbeMode
; /* return error code */
1782 * As the external frequency (osc0) has already been checked when FBE mode was enterred
1783 * it is not checked here.
1786 /* Check PLL divider settings are within spec.*/
1787 if ((prdivVal
< 1) || (prdivVal
> FSL_FEATURE_MCG_PLL_PRDIV_MAX
))
1789 return kMcgErrPllPrdidRange
;
1792 if ((vdivVal
< FSL_FEATURE_MCG_PLL_VDIV_BASE
) || (vdivVal
> (FSL_FEATURE_MCG_PLL_VDIV_BASE
+ 31)))
1794 return kMcgErrPllVdivRange
;
1797 /* Check PLL reference clock frequency is within spec. */
1798 if (((crystalVal
/ prdivVal
) < kMcgConstant8000000
) || ((crystalVal
/ prdivVal
) > kMcgConstant32000000
))
1800 return kMcgErrPllRefClkRange
;
1803 /* Check PLL output frequency is within spec. */
1804 pllFreq
= (crystalVal
/ prdivVal
) * vdivVal
;
1805 if ((pllFreq
< kMcgConstant180000000
) || (pllFreq
> kMcgConstant360000000
))
1807 return kMcgErrPllOutClkRange
;
1810 #if FSL_FEATURE_MCG_HAS_PLL1
1811 /* set pllcsSelect */
1812 CLOCK_HAL_SetPllcs(pllcsSelect
);
1814 if (pllcsSelect
== kMcgPllcsSelectPll0
)
1819 * If the PLL is to run in STOP mode then the PLLSTEN bit needs
1820 * to be OR'ed in here or in user code.
1823 CLOCK_HAL_SetPllExternalRefDivider0(baseAddr
, prdivVal
- 1);
1827 * The PLLS bit is set to enable the PLL, MCGOUT still sourced from ext ref clk
1828 * The clock monitor is not enabled here as it has likely been enabled previously and
1829 * so the value of CME is not altered here.
1830 * The loss of lock interrupt can be enabled by seperate OR'ing in the LOLIE bit in MCG_C6
1833 CLOCK_HAL_SetVoltCtrlOscDivider0(baseAddr
, vdivVal
- FSL_FEATURE_MCG_PLL_VDIV_BASE
);
1834 CLOCK_HAL_SetPllSelMode(baseAddr
, kMcgPllSelPllClkSel
);
1836 // wait for PLLST status bit to set
1837 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1839 if (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatPllClkSel
)
1841 /* jump out early if PLLST sets before loop finishes */
1846 /* check bit is really set */
1847 if ((CLOCK_HAL_GetPllStatMode(baseAddr
) != kMcgPllStatPllClkSel
))
1849 /* return with error if not set */
1850 return kMcgErrPllstSetTimeout
;
1853 /* Wait for LOCK bit to set */
1854 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1856 if (CLOCK_HAL_GetLock0Mode(baseAddr
) == kMcgLockLocked
)
1858 /* jump out early if LOCK sets before loop finishes */
1863 /* check bit is really set */
1864 if ((CLOCK_HAL_GetLock0Mode(baseAddr
) != kMcgLockLocked
))
1866 /* return with error if not set */
1867 return kMcgErrPllLockBit
;
1870 #if FSL_FEATURE_MCG_USE_PLLREFSEL
1871 /* wait for PLLCST status bit to clear */
1872 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1874 if (CLOCK_HAL_GetPllcst(baseAddr
) == kMcgPllcsSelectPll0
)
1876 /* jump out early if PLLST sets before loop finishes */
1881 /* check bit is really set */
1882 if (CLOCK_HAL_GetPllcst(baseAddr
) != kMcgPllcsSelectPll0
)
1884 /* return with error if not set */
1885 return kMcgErrPllcst
;
1889 #if FSL_FEATURE_MCG_HAS_PLL1
1894 * If the PLL is to run in STOP mode
1895 * then the PLLSTEN bit needs to be OR'ed in here or in user code.
1897 CLOCK_HAL_SetPrdiv1(prdivVal
- 1);
1901 * The PLLS bit is set to enable the PLL, MCGOUT still sourced from ext ref clk
1902 * The clock monitor is not enabled here as it has likely been enabled previously
1903 * and so the value of CME is not altered here.
1904 * The loss of lock interrupt can be enabled by seperate OR'ing in the LOLIE bit
1908 CLOCK_HAL_SetVdiv1(vdivVal
- FSL_FEATURE_MCG_PLL_VDIV_BASE
);
1909 CLOCK_HAL_SetPllSelMode(kMcgPllSelPllClkSel
);
1911 // wait for PLLST status bit to set
1912 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1914 if (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatPllClkSel
)
1916 /* jump out early if PLLST sets before loop finishes */
1921 /* check bit is really set */
1922 if ((CLOCK_HAL_GetPllStatMode(baseAddr
) != kMcgPllStatPllClkSel
))
1924 /* return with error if not set */
1925 return kMcgErrPllstSetTimeout
;
1928 /* Wait for LOCK bit to set */
1929 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1931 if (CLOCK_HAL_GetLock1(baseAddr
) == kMcgLockLocked
)
1933 /* jump out early if LOCK sets before loop finishes */
1938 /* check bit is really set */
1939 if ((CLOCK_HAL_GetLock1(baseAddr
) != kMcgLockLocked
))
1941 /* return with error if not set */
1942 return kMcgErrPllLockBit
;
1945 /* wait for PLLCST status bit to clear */
1946 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
1948 if (CLOCK_HAL_GetPllcst(baseAddr
) == kMcgPllcsSelectPll1
)
1950 /* jump out early if PLLST sets before loop finishes */
1955 /* check bit is really set */
1956 if (CLOCK_HAL_GetPllcst(baseAddr
) != kMcgPllcsSelectPll1
)
1958 /* return with error if not set */
1959 return kMcgErrPllcst
;
1962 #endif /* PLL1 is selected */
1966 /* MCGOUT frequency equals external clock frequency */
1968 } /* CLOCK_HAL_SetFbeToPbeMode */
1971 /*FUNCTION******************************************************************************
1973 * Functon name : CLOCK_HAL_SetFbeToBlpeMode
1974 * Description : Mode transition FBE to BLPE mode
1975 * This function transitions the MCG from FBE mode to BLPE mode.
1977 * Parameters: crystalVal - external clock frequency in Hz
1979 * Return value : MCGCLKOUT frequency (Hz) or error code
1980 *END***********************************************************************************/
1981 uint32_t CLOCK_HAL_SetFbeToBlpeMode(uint32_t baseAddr
, uint32_t crystalVal
)
1983 /* Check MCG is in FBE mode */
1984 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeFBE
)
1986 return kMcgErrNotInFbeMode
; /* return error code */
1989 /* To move from FBE to BLPE the LP bit must be set */
1990 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelLowPower
);
1992 /* now in FBE mode */
1994 /* MCGOUT frequency equals external clock frequency */
1996 } /* CLOCK_HAL_SetFbeToBlpeMode */
1998 #if FSL_FEATURE_MCG_HAS_PLL
2000 /*FUNCTION******************************************************************************
2002 * Functon name : CLOCK_HAL_SetPbeToFbeMode
2003 * Description : Mode transition PBE to FBE mode
2004 * This function transitions the MCG from PBE mode to FBE mode.
2006 * Parameters: crystalVal - external clock frequency in Hz
2008 * Return value : MCGCLKOUT frequency (Hz) or error code
2009 *END***********************************************************************************/
2010 uint32_t CLOCK_HAL_SetPbeToFbeMode(uint32_t baseAddr
, uint32_t crystalVal
)
2014 /* Check MCG is in PBE mode */
2015 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModePBE
)
2017 return kMcgErrNotInPbeMode
; /* return error code */
2021 * As we are running from the ext clock, by default the external clock settings are valid
2022 * To move to FBE from PBE simply requires the switching of the PLLS mux to disable the PLL
2025 CLOCK_HAL_SetPllSelMode(baseAddr
, kMcgPllSelFll
);
2027 /* wait for PLLST status bit to set */
2028 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2030 if (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatFll
)
2032 /* jump out early if PLLST clears before loop finishes */
2037 /* check bit is really clear */
2038 if (CLOCK_HAL_GetPllStatMode(baseAddr
) != kMcgPllStatFll
)
2040 /* return with error if not clear */
2041 return kMcgErrPllstClearTimeout
;
2044 /* Now in FBE mode */
2046 /* MCGOUT frequency equals external clock frequency */
2048 } /* CLOCK_HAL_SetPbeToFbeMode */
2050 /*FUNCTION******************************************************************************
2052 * Functon name : CLOCK_HAL_SetPbeToPeeMode
2053 * Description : Mode transition PBE to PEE mode
2054 * This function transitions the MCG from PBE mode to PEE mode.
2056 * Parameters: crystalVal - external clock frequency in Hz
2057 * pllcsSelect - PLLCS select setting
2058 * mcg_pll_clk_select_t is defined in fsl_mcg_hal.h
2059 * 0: kMcgPllcsSelectPll0 PLL0 output clock is selected
2060 * 1: kMcgPllcsSelectPll1 PLL1 output clock is selected
2062 * Return value : MCGCLKOUT frequency (Hz) or error code
2063 *END***********************************************************************************/
2064 uint32_t CLOCK_HAL_SetPbeToPeeMode(uint32_t baseAddr
, uint32_t crystalVal
, mcg_pll_clk_select_t pllcsSelect
)
2066 uint8_t prDiv
, vDiv
;
2070 /* Check MCG is in PBE mode */
2071 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModePBE
)
2073 return kMcgErrNotInPbeMode
; /* return error code */
2076 /* As the PLL settings have already been checked when PBE mode was enterred they are not checked here */
2078 /* Check the PLL state before transitioning to PEE mode */
2080 #if FSL_FEATURE_MCG_HAS_PLL1
2081 /* Check the selected PLL state before transitioning to PEE mode */
2082 if (pllcsSelect
== kMcgPllcsSelectPll1
)
2084 /* Check LOCK bit is set before transitioning MCG to PLL output */
2085 /* already checked in fbe_pbe but good practice to re-check before switch to use PLL */
2086 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2088 if (CLOCK_HAL_GetLock1(baseAddr
) == kMcgLockLocked
)
2090 /* jump out early if LOCK sets before loop finishes */
2095 /* check bit is really set */
2096 if ((CLOCK_HAL_GetLock1(baseAddr
) != kMcgLockLocked
))
2098 /* return with error if not set */
2099 return kMcgErrPllLockBit
;
2102 /* Use actual PLL settings to calculate PLL frequency */
2103 prDiv
= (CLOCK_HAL_GetPrdiv1(baseAddr
) + 1);
2104 vDiv
= (CLOCK_HAL_GetVdiv1(baseAddr
) + FSL_FEATURE_MCG_PLL_VDIV_BASE
);
2109 /* Check LOCK bit is set before transitioning MCG to PLL output */
2110 /* already checked in fbe_pbe but good practice to re-check before switch to use PLL */
2111 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2113 if (CLOCK_HAL_GetLock0Mode(baseAddr
) == kMcgLockLocked
)
2115 /* jump out early if LOCK sets before loop finishes */
2120 /* check bit is really set */
2121 if ((CLOCK_HAL_GetLock0Mode(baseAddr
) != kMcgLockLocked
))
2123 /* return with error if not set */
2124 return kMcgErrPllLockBit
;
2127 /* Use actual PLL settings to calculate PLL frequency */
2128 prDiv
= (CLOCK_HAL_GetPllExternalRefDivider0(baseAddr
) + 1);
2129 vDiv
= (CLOCK_HAL_GetVoltCtrlOscDivider0(baseAddr
) + FSL_FEATURE_MCG_PLL_VDIV_BASE
);
2132 /* clear CLKS to switch CLKS mux to select PLL as MCG_OUT */
2133 CLOCK_HAL_SetClkSrcMode(baseAddr
, kMcgClkSelOut
);
2135 /* Wait for clock status bits to update */
2136 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2138 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatPll
)
2140 break; /* jump out early if CLKST = 3 before loop finishes */
2144 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatPll
)
2146 return kMcgErrClkst3
; /* check CLKST is set correctly and return with error if not */
2151 /* MCGOUT equals PLL output frequency with any special divider */
2152 mcgOut
= (crystalVal
/ prDiv
) * vDiv
;
2155 } /* CLOCK_HAL_SetPbeToPeeMode */
2157 /*FUNCTION******************************************************************************
2159 * Functon name : CLOCK_HAL_SetPbeToBlpeMode
2160 * Description : Mode transition PBE to BLPE mode
2161 * This function transitions the MCG from PBE mode to BLPE mode.
2163 * Parameters: crystalVal - external clock frequency in Hz
2165 * Return value : MCGCLKOUT frequency (Hz) or error code
2166 *END***********************************************************************************/
2167 uint32_t CLOCK_HAL_SetPbeToBlpeMode(uint32_t baseAddr
, uint32_t crystalVal
)
2169 /* Check MCG is in PBE mode */
2170 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModePBE
)
2172 return kMcgErrNotInPbeMode
; /* return error code */
2175 /* To enter BLPE mode the LP bit must be set, disabling the PLL */
2176 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelLowPower
);
2178 /* Now in BLPE mode */
2180 } /* CLOCK_HAL_SetPbeToBlpeMode */
2182 /*FUNCTION******************************************************************************
2184 * Functon name : CLOCK_HAL_SetPeeToPbeMode
2185 * Description : Mode transition PEE to PBE mode
2186 * This function transitions the MCG from PEE mode to PBE mode.
2188 * Parameters: crystalVal - external clock frequency in Hz
2190 * Return value : MCGCLKOUT frequency (Hz) or error code
2191 *END***********************************************************************************/
2192 uint32_t CLOCK_HAL_SetPeeToPbeMode(uint32_t baseAddr
, uint32_t crystalVal
)
2196 /* Check MCG is in PEE mode */
2197 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModePEE
)
2199 return kMcgErrNotInPeeMode
; /* return error code */
2203 * As we are running from the PLL by default the PLL and external clock settings are valid
2204 * To move to PBE from PEE simply requires the switching of the CLKS mux to select the ext clock
2206 /* As CLKS is already 0 the CLKS value can simply be OR'ed into the register */
2207 CLOCK_HAL_SetClkSrcMode(baseAddr
, kMcgClkSelExternal
);
2209 /* Wait for clock status bits to update */
2210 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2212 if (CLOCK_HAL_GetClkStatMode(baseAddr
) == kMcgClkStatExternalRef
)
2214 break; /* jump out early if CLKST shows EXT CLK slected before loop finishes */
2218 if (CLOCK_HAL_GetClkStatMode(baseAddr
) != kMcgClkStatExternalRef
)
2220 return kMcgErrClkst2
; /* check EXT CLK is really selected and return with error if not */
2223 /* Now in PBE mode */
2224 return crystalVal
; /* MCGOUT frequency equals external clock frequency */
2225 } /* CLOCK_HAL_SetPeeToPbeMode */
2227 /*FUNCTION******************************************************************************
2229 * Functon name : CLOCK_HAL_SetBlpeToPbeMode
2230 * Description : Mode transition BLPE to PBE mode
2231 * This function transitions the MCG from BLPE mode to PBE mode.
2232 * The function requires the desired OSC and PLL be passed in to it for compatibility
2233 * with the future support of OSC/PLL selection
2234 * (This function presently only supports OSC0 as PLL source)
2235 * Parameters: crystalVal - external clock frequency in Hz
2236 * pllcsSelect - 0 to select PLL0, non-zero to select PLL1.
2237 * prdivVal - value to divide the external clock source by to create
2238 * the desired PLL reference clock frequency
2239 * vdivVal - value to multiply the PLL reference clock frequency by
2241 * Return value : MCGCLKOUT frequency (Hz) or error code
2242 *END***********************************************************************************/
2243 uint32_t CLOCK_HAL_SetBlpeToPbeMode(uint32_t baseAddr
, uint32_t crystalVal
, mcg_pll_clk_select_t pllcsSelect
, uint8_t prdivVal
, uint8_t vdivVal
)
2248 /* Check MCG is in BLPE mode */
2249 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeBLPE
)
2251 return kMcgErrNotInBlpeMode
; /* return error code */
2255 * As the external frequency (osc0) has already been checked when FBE mode was enterred
2256 * it is not checked here.
2259 /* Check PLL divider settings are within spec.*/
2260 if ((prdivVal
< 1) || (prdivVal
> FSL_FEATURE_MCG_PLL_PRDIV_MAX
))
2262 return kMcgErrPllPrdidRange
;
2265 if ((vdivVal
< FSL_FEATURE_MCG_PLL_VDIV_BASE
) || (vdivVal
> (FSL_FEATURE_MCG_PLL_VDIV_BASE
+ 31)))
2267 return kMcgErrPllVdivRange
;
2270 /* Check PLL reference clock frequency is within spec. */
2271 if (((crystalVal
/ prdivVal
) < kMcgConstant8000000
) || ((crystalVal
/ prdivVal
) > kMcgConstant32000000
))
2273 return kMcgErrPllRefClkRange
;
2276 /* Check PLL output frequency is within spec. */
2277 pllFreq
= (crystalVal
/ prdivVal
) * vdivVal
;
2278 if ((pllFreq
< kMcgConstant180000000
) || (pllFreq
> kMcgConstant360000000
))
2280 return kMcgErrPllOutClkRange
;
2283 #if FSL_FEATURE_MCG_HAS_PLL1
2284 /* set pllcsSelect */
2285 CLOCK_HAL_SetPllcs(pllcsSelect
);
2287 if (pllcsSelect
== kMcgPllcsSelectPll0
)
2292 * If the PLL is to run in STOP mode then the PLLSTEN bit needs
2293 * to be OR'ed in here or in user code.
2296 CLOCK_HAL_SetPllExternalRefDivider0(baseAddr
, prdivVal
- 1);
2300 * The PLLS bit is set to enable the PLL, MCGOUT still sourced from ext ref clk
2301 * The clock monitor is not enabled here as it has likely been enabled previously and
2302 * so the value of CME is not altered here.
2303 * The loss of lock interrupt can be enabled by seperate OR'ing in the LOLIE bit in MCG_C6
2306 CLOCK_HAL_SetVoltCtrlOscDivider0(baseAddr
, vdivVal
- FSL_FEATURE_MCG_PLL_VDIV_BASE
);
2307 CLOCK_HAL_SetPllSelMode(baseAddr
, kMcgPllSelPllClkSel
);
2309 /* Set LP bit to enable the PLL */
2310 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelNormal
);
2312 // wait for PLLST status bit to set
2313 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2315 if (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatPllClkSel
)
2317 /* jump out early if PLLST sets before loop finishes */
2322 /* check bit is really set */
2323 if ((CLOCK_HAL_GetPllStatMode(baseAddr
) != kMcgPllStatPllClkSel
))
2325 /* return with error if not set */
2326 return kMcgErrPllstSetTimeout
;
2329 /* Wait for LOCK bit to set */
2330 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2332 if (CLOCK_HAL_GetLock0Mode(baseAddr
) == kMcgLockLocked
)
2334 /* jump out early if LOCK sets before loop finishes */
2339 /* check bit is really set */
2340 if ((CLOCK_HAL_GetLock0Mode(baseAddr
) != kMcgLockLocked
))
2342 /* return with error if not set */
2343 return kMcgErrPllLockBit
;
2346 #if FSL_FEATURE_MCG_USE_PLLREFSEL
2347 /* wait for PLLCST status bit to clear */
2348 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2350 if (CLOCK_HAL_GetPllcst(baseAddr
) == kMcgPllcsSelectPll0
)
2352 /* jump out early if PLLST sets before loop finishes */
2357 /* check bit is really set */
2358 if (CLOCK_HAL_GetPllcst(baseAddr
) != kMcgPllcsSelectPll0
)
2360 /* return with error if not set */
2361 return kMcgErrPllcst
;
2365 #if FSL_FEATURE_MCG_HAS_PLL1
2370 * If the PLL is to run in STOP mode
2371 * then the PLLSTEN bit needs to be OR'ed in here or in user code.
2373 CLOCK_HAL_SetPrdiv1(prdivVal
- 1);
2377 * The PLLS bit is set to enable the PLL, MCGOUT still sourced from ext ref clk
2378 * The clock monitor is not enabled here as it has likely been enabled previously
2379 * and so the value of CME is not altered here.
2380 * The loss of lock interrupt can be enabled by seperate OR'ing in the LOLIE bit
2384 CLOCK_HAL_SetVdiv1(vdivVal
- FSL_FEATURE_MCG_PLL_VDIV_BASE
);
2385 CLOCK_HAL_SetPllSelMode(kMcgPllSelPllClkSel
);
2387 /* Set LP bit to enable the PLL */
2388 CLOCK_HAL_SetLowPowerMode(kMcgLowPowerSelNormal
);
2390 // wait for PLLST status bit to set
2391 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2393 if (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatPllClkSel
)
2395 /* jump out early if PLLST sets before loop finishes */
2400 /* check bit is really set */
2401 if ((CLOCK_HAL_GetPllStatMode(baseAddr
) != kMcgPllStatPllClkSel
))
2403 /* return with error if not set */
2404 return kMcgErrPllstSetTimeout
;
2407 /* Wait for LOCK bit to set */
2408 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2410 if (CLOCK_HAL_GetLock1(baseAddr
) == kMcgLockLocked
)
2412 /* jump out early if LOCK sets before loop finishes */
2417 /* check bit is really set */
2418 if ((CLOCK_HAL_GetLock1(baseAddr
) != kMcgLockLocked
))
2420 /* return with error if not set */
2421 return kMcgErrPllLockBit
;
2424 /* wait for PLLCST status bit to clear */
2425 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2427 if (CLOCK_HAL_GetPllcst(baseAddr
) == kMcgPllcsSelectPll1
)
2429 /* jump out early if PLLST sets before loop finishes */
2434 /* check bit is really set */
2435 if (CLOCK_HAL_GetPllcst(baseAddr
) != kMcgPllcsSelectPll1
)
2437 /* return with error if not set */
2438 return kMcgErrPllcst
;
2441 #endif /* PLL1 is selected */
2445 /* MCGOUT frequency equals external clock frequency */
2447 } /* CLOCK_HAL_SetBlpeToPbeMode */
2450 /*FUNCTION******************************************************************************
2452 * Functon name : CLOCK_HAL_SetBlpeToFbeMode
2453 * Description : Mode transition BLPE to FBE mode
2454 * This function transitions the MCG from BLPE mode to FBE mode.
2456 * Parameters: crystalVal - external reference clock frequency value
2458 * Return value : MCGCLKOUT frequency (Hz) or error code
2459 *END***********************************************************************************/
2460 uint32_t CLOCK_HAL_SetBlpeToFbeMode(uint32_t baseAddr
, uint32_t crystalVal
)
2462 #if FSL_FEATURE_MCG_HAS_PLL
2466 /* Check MCG is in BLPE mode */
2467 if (CLOCK_HAL_GetMcgMode(baseAddr
) != kMcgModeBLPE
)
2469 return kMcgErrNotInBlpeMode
; /* return error code */
2472 /* To move from BLPE to FBE the PLLS mux be set to select the FLL output*/
2473 /* and the LP bit must be cleared */
2474 #if FSL_FEATURE_MCG_HAS_PLL
2475 CLOCK_HAL_SetPllSelMode(baseAddr
, kMcgPllSelFll
);
2477 CLOCK_HAL_SetLowPowerMode(baseAddr
, kMcgLowPowerSelNormal
);
2479 #if FSL_FEATURE_MCG_HAS_PLL
2480 /* wait for PLLST status bit to set */
2481 for (i
= 0 ; i
< kMcgConstant2000
; i
++)
2483 if (CLOCK_HAL_GetPllStatMode(baseAddr
) == kMcgPllStatFll
)
2485 /* jump out early if PLLST clears before loop finishes */
2490 /* check bit is really clear */
2491 if (CLOCK_HAL_GetPllStatMode(baseAddr
) != kMcgPllStatFll
)
2493 /* return with error if not clear */
2494 return kMcgErrPllstClearTimeout
;
2497 /* now in FBE mode */
2499 /* MCGOUT frequency equals external clock frequency */
2501 } /* CLOCK_HAL_SetBlpeToFbeMode */