]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/mcg/fsl_mcg_hal_modes.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[tmk_keyboard.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_Freescale / TARGET_KPSDK_MCUS / TARGET_KPSDK_CODE / hal / mcg / fsl_mcg_hal_modes.c
1 /*
2 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * o Redistributions of source code must retain the above copyright notice, this list
9 * of conditions and the following disclaimer.
10 *
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.
14 *
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.
18 *
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.
29 */
30
31 #include "fsl_mcg_hal_modes.h"
32
33 /*******************************************************************************
34 * Definitions
35 ******************************************************************************/
36
37 /*******************************************************************************
38 * Code
39 ******************************************************************************/
40
41 /*****************************************************************
42 * MCG clock mode transition functions
43 *
44 * FEI -> FEE
45 * FEI -> FBI
46 * FEI -> FBE
47 *
48 * FEE -> FEI
49 * FEE -> FBI
50 * FEE -> FBE
51 *
52 * FBI -> FEI
53 * FBI -> FEE
54 * FBI -> FBE
55 * FBI -> BLPI
56 *
57 * BLPI -> FBI
58 *
59 * FBE -> FEE
60 * FBE -> FEI
61 * FBE -> FBI
62 * FBE -> PBE
63 * FBE -> BLPE
64 *
65 * PBE -> FBE
66 * PBE -> PEE
67 * PBE -> BLPE
68 *
69 * BLPE -> FBE
70 * BLPE -> PBE
71 *
72 * PEE -> PBE
73 *
74 *****************************************************************/
75 /*FUNCTION******************************************************************************
76 *
77 * Functon name : CLOCK_HAL_GetMcgMode
78 * Description : internal function will check the mcg registers and determine
79 * the current mcg mode
80 *
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)
84 {
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) */
90 #else
91 )
92 #endif
93 {
94 return kMcgModeFEI; /* return FEI code */
95 }
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) */
101 #else
102 )
103 #endif
104 {
105 return kMcgModePEE; /* return PEE code */
106 }
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) */
112 #endif
113 (CLOCK_HAL_GetLowPowerMode(baseAddr) == kMcgLowPowerSelNormal)) /* MCG_C2[LP] bit is not set (LP=0) */
114 {
115 return kMcgModePBE; /* return PBE code */
116 }
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) */
122 #endif
123 (CLOCK_HAL_GetLowPowerMode(baseAddr) == kMcgLowPowerSelNormal)) /* MCG_C2[LP] bit is not set (LP=0) */
124 {
125 return kMcgModeFBE; /* return FBE code */
126 }
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) */
131 {
132 return kMcgModeBLPE; /* return BLPE code */
133 }
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) */
139 #endif
140 (CLOCK_HAL_GetLowPowerMode(baseAddr) == kMcgLowPowerSelLowPower))/* MCG_C2[LP] bit is set (LP=1) */
141 {
142 return kMcgModeBLPI; /* return BLPI code */
143 }
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) */
149 #endif
150 (CLOCK_HAL_GetLowPowerMode(baseAddr) == kMcgLowPowerSelNormal)) /* MCG_C2[LP] bit is not set (LP=0) */
151 {
152 return kMcgModeFBI; /* return FBI code */
153 }
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) */
159 #else
160 )
161 #endif
162 {
163 return kMcgModeFEE; /* return FEE code */
164 }
165 else
166 {
167 return kMcgModeError; /* error unknown mode */
168 }
169 } /* CLOCK_HAL_GetMcgMode */
170
171 /*FUNCTION******************************************************************************
172 *
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.
176 *
177 * Parameters: fllRef - fll reference clock in Hz.
178 *
179 * Return value : fll output frequency (Hz) or error code
180 *END***********************************************************************************/
181 uint32_t CLOCK_HAL_GetFllFrequency(uint32_t baseAddr, int32_t fllRef)
182 {
183 int32_t fllFreqHz = 0;
184
185 /* Check that only allowed ranges have been selected */
186 if (CLOCK_HAL_GetDigitalControlledOscRangeMode(baseAddr) > kMcgDigitalControlledOscRangeSelMid)
187 {
188 return kMcgErrFllDrstDrsRange; /* return error code if DRS range 2 or 3 selected */
189 }
190
191 /* if DMX32 set */
192 if (CLOCK_HAL_GetDmx32(baseAddr))
193 {
194 /* determine multiplier based on DRS */
195 switch (CLOCK_HAL_GetDigitalControlledOscRangeMode(baseAddr))
196 {
197 case 0:
198 fllFreqHz = (fllRef * kMcgConstant732);
199 if (fllFreqHz < kMcgConstant20000000)
200 {
201 return kMcgErrFllRange0Min;
202 }
203 else if (fllFreqHz > kMcgConstant25000000)
204 {
205 return kMcgErrFllRange0Max;
206 }
207 break;
208 case 1:
209 fllFreqHz = (fllRef * kMcgConstant1464);
210 if (fllFreqHz < kMcgConstant40000000)
211 {
212 return kMcgErrFllRange1Min;
213 }
214 else if (fllFreqHz > kMcgConstant50000000)
215 {
216 return kMcgErrFllRange1Max;
217 }
218 break;
219 case 2:
220 fllFreqHz = (fllRef * kMcgConstant2197);
221 if (fllFreqHz < kMcgConstant60000000)
222 {
223 return kMcgErrFllRange2Min;
224 }
225 else if (fllFreqHz > kMcgConstant75000000)
226 {
227 return kMcgErrFllRange2Max;
228 }
229 break;
230 case 3:
231 fllFreqHz = (fllRef * kMcgConstant2929);
232 if (fllFreqHz < kMcgConstant80000000)
233 {
234 return kMcgErrFllRange3Min;
235 }
236 else if (fllFreqHz > kMcgConstant100000000)
237 {
238 return kMcgErrFllRange3Max;
239 }
240 break;
241 default:
242 break;
243 }
244 }
245 /* if DMX32 = 0 */
246 else
247 {
248 /* determine multiplier based on DRS */
249 switch (CLOCK_HAL_GetDigitalControlledOscRangeMode(baseAddr))
250 {
251 case 0:
252 fllFreqHz = (fllRef * kMcgConstant640);
253 if (fllFreqHz < kMcgConstant20000000)
254 {
255 return kMcgErrFllRange0Min;
256 }
257 else if (fllFreqHz > kMcgConstant25000000)
258 {
259 return kMcgErrFllRange0Max;
260 }
261 break;
262 case 1:
263 fllFreqHz = (fllRef * kMcgConstant1280);
264 if (fllFreqHz < kMcgConstant40000000)
265 {
266 return kMcgErrFllRange1Min;
267 }
268 else if (fllFreqHz > kMcgConstant50000000)
269 {
270 return kMcgErrFllRange1Max;
271 }
272 break;
273 case 2:
274 fllFreqHz = (fllRef * kMcgConstant1920);
275 if (fllFreqHz < kMcgConstant60000000)
276 {
277 return kMcgErrFllRange2Min;
278 }
279 else if (fllFreqHz > kMcgConstant75000000)
280 {
281 return kMcgErrFllRange2Max;
282 }
283 break;
284 case 3:
285 fllFreqHz = (fllRef * kMcgConstant2560);
286 if (fllFreqHz < kMcgConstant80000000)
287 {
288 return kMcgErrFllRange3Min;
289 }
290 else if (fllFreqHz > kMcgConstant100000000)
291 {
292 return kMcgErrFllRange3Max;
293 }
294 break;
295 default:
296 break;
297 }
298 }
299 return fllFreqHz;
300 } /* CLOCK_HAL_GetFllFrequency */
301
302
303 /*FUNCTION******************************************************************************
304 *
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.
308 *
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
315 * oscselVal - 0
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
330 *
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)
334 {
335 uint8_t frDivVal;
336 uint32_t mcgOut, fllRefFreq, i;
337
338 /* check if in FEI mode */
339 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFEI)
340 {
341 return kMcgErrNotInFeiMode; /* return error code */
342 }
343
344 /* check external frequency is less than the maximum frequency */
345 if (crystalVal > kMcgConstant50000000)
346 {
347 return kMcgErrOscEtalRange; /* - external frequency is bigger than max frequency */
348 }
349
350 /* check crystal frequency is within spec. if crystal osc is being used */
351 if (oscselVal == kMcgOscselOsc)
352 {
353 if (erefsVal)
354 {
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))
359 {
360 return kMcgErrOscXtalRange; /* - crystal frequency outside allowed range */
361 }
362
363 /* config the hgo settings */
364 CLOCK_HAL_SetHighGainOsc0Mode(baseAddr, hgoVal);
365 }
366
367 /* config the erefs0 settings */
368 CLOCK_HAL_SetExternalRefSel0Mode(baseAddr, erefsVal);
369 }
370
371 /*
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
375 */
376 if (crystalVal <= kMcgConstant40000)
377 {
378 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelLow);
379 }
380 else if (crystalVal <= kMcgConstant8000000)
381 {
382 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelHigh);
383 }
384 else
385 {
386 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelVeryHigh);
387 }
388
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)
392 {
393 frDivVal = kMcgConstant0;
394 }
395 else if (crystalVal <= kMcgConstant2500000)
396 {
397 frDivVal = kMcgConstant1;
398 }
399 else if (crystalVal <= kMcgConstant5000000)
400 {
401 frDivVal = kMcgConstant2;
402 }
403 else if (crystalVal <= kMcgConstant10000000)
404 {
405 frDivVal = kMcgConstant3;
406 }
407 else if (crystalVal <= kMcgConstant20000000)
408 {
409 frDivVal = kMcgConstant4;
410 }
411 else
412 {
413 frDivVal = kMcgConstant5;
414 }
415
416 /* The FLL ref clk divide value depends on FRDIV and the RANGE value */
417 if (CLOCK_HAL_GetRange0Mode(baseAddr) > kMcgFreqRangeSelLow)
418 {
419 fllRefFreq = ((crystalVal) / (kMcgConstant32 << frDivVal));
420 }
421 else
422 {
423 fllRefFreq = ((crystalVal) / (kMcgConstant1 << frDivVal));
424 }
425
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)
430 {
431 return mcgOut; /* If error code returned, return the code to calling function */
432 }
433
434 /*
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
438 */
439 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr, kMcgClkSelOut, frDivVal, kMcgInternalRefClkSrcExternal);
440
441 /* if the external oscillator is used need to wait for OSCINIT to set */
442 if ((oscselVal == kMcgOscselOsc) && (erefsVal))
443 {
444 for (i = 0 ; i < kMcgConstant20000000 ; i++)
445 {
446 if (CLOCK_HAL_GetOscInit0(baseAddr))
447 {
448 break; /* jump out early if OSCINIT sets before loop finishes */
449 }
450 }
451
452 if (!CLOCK_HAL_GetOscInit0(baseAddr))
453 {
454 /* check bit is really set and return with error if not set */
455 return kMcgErrOscSetTimeout;
456 }
457 }
458
459 /* Wait for clock status bits to show clock source is FLL */
460 for (i = 0 ; i < kMcgConstant2000 ; i++)
461 {
462 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatFll)
463 {
464 break; // jump out early if CLKST shows FLL selected before loop finishes
465 }
466 }
467
468 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatFll)
469 {
470 return kMcgErrClkst0; // check FLL is really selected and return with error if not
471 }
472
473 /*
474 * Now in FEE
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.
478 */
479 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr, true);
480
481 return mcgOut; /* MCGOUT frequency equals FLL frequency */
482 } /* CLOCK_HAL_SetFeiToFeeMode */
483
484 /*FUNCTION******************************************************************************
485 *
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.
489 *
490 * Parameters: ircFreq - internal reference clock frequency value
491 * ircSelect - slow or fast clock selection
492 * 0: slow, 1: fast
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)
496 {
497 uint8_t fcrDivVal;
498 uint16_t i;
499
500 /* Check MCG is in FEI mode */
501 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFEI)
502 {
503 return kMcgErrNotInFeiMode; /* return error code */
504 }
505
506
507 /* Check that the irc frequency matches the selected IRC */
508 if (!(ircSelect))
509 {
510 if ((ircFreq < kMcgConstant31250) || (ircFreq > kMcgConstant39063))
511 {
512 return kMcgErrIrcSlowRange;
513 }
514 }
515 else
516 {
517 if ((ircFreq < kMcgConstant3000000) || (ircFreq > kMcgConstant5000000))
518 {
519 return kMcgErrIrcFastRange;
520 } /* Fast IRC freq */
521 }
522
523 /* Select the desired IRC */
524 CLOCK_HAL_SetInternalRefClkSelMode(baseAddr, ircSelect);
525
526 /* Change the CLKS mux to select the IRC as the MCGOUT */
527 CLOCK_HAL_SetClkSrcMode(baseAddr, kMcgClkSelInternal);
528
529 /* Set LP bit to enable the FLL */
530 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelNormal);
531
532 /* wait until internal reference switches to requested irc. */
533 if (ircSelect == kMcgInternalRefClkSelSlow)
534 {
535 for (i = 0 ; i < kMcgConstant2000 ; i++)
536 {
537 if (!(MCG_S & MCG_S_IRCST_MASK))
538 {
539 break; /* jump out early if IRCST clears before loop finishes */
540 }
541 }
542 if (MCG_S & MCG_S_IRCST_MASK)
543 {
544 /* check bit is really clear and return with error if set */
545 return kMcgErrIrcstClearTimeout;
546 }
547 }
548 else
549 {
550 for (i = 0 ; i < kMcgConstant2000 ; i++)
551 {
552 if (MCG_S & MCG_S_IRCST_MASK)
553 {
554 break; /* jump out early if IRCST sets before loop finishes */
555 }
556 }
557 if (!(MCG_S & MCG_S_IRCST_MASK))
558 {
559 /* check bit is really set and return with error if not set */
560 return kMcgErrIrefstSetTimeout1;
561 }
562 }
563
564 /* Wait for clock status bits to update */
565 for (i = 0 ; i < kMcgConstant2000 ; i++)
566 {
567 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatInternalRef)
568 {
569 break; /* jump out early if CLKST shows IRC slected before loop finishes */
570 }
571 }
572
573 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatInternalRef)
574 {
575 /* check IRC is really selected and return with error if not */
576 return kMcgErrClkst1;
577 }
578
579 /* Now in FBI mode */
580 if (ircSelect == kMcgInternalRefClkSelFast)
581 {
582 fcrDivVal = CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr);
583
584 /* MCGOUT frequency equals fast IRC frequency divided by 2 */
585 return (ircFreq / fcrDivVal);
586 }
587 else
588 {
589 return ircFreq; /* MCGOUT frequency equals slow IRC frequency */
590 }
591 } /* CLOCK_HAL_SetFeiToFbiMode */
592
593 /*FUNCTION******************************************************************************
594 *
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.
598 *
599 * Parameters: oscselVal - oscillator selection value
600 * 0 - OSC 0, 1 - RTC 32k, 2 - IRC 48M
601 * crystalVal - external clock frequency in Hz
602 * oscselVal - 0
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)
611 *
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)
615 {
616 uint8_t frDivVal;
617 int16_t i;
618
619 /* check if in FEI mode */
620 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFEI)
621 {
622 return kMcgErrNotInFeiMode; /* return error code */
623 }
624
625 /* check external frequency is less than the maximum frequency */
626 if (crystalVal > kMcgConstant50000000)
627 {
628 /* - external frequency is bigger than max frequency */
629 return kMcgErrOscEtalRange;
630 }
631
632 /* check crystal frequency is within spec. if crystal osc is being used */
633 if (oscselVal == kMcgOscselOsc)
634 {
635 if (erefsVal)
636 {
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))
641 {
642 /* - crystal frequency outside allowed range */
643 return kMcgErrOscXtalRange;
644 }
645
646 /* config the hgo settings */
647 CLOCK_HAL_SetHighGainOsc0Mode(baseAddr, hgoVal);
648 }
649
650 /* config the erefs0 settings */
651 CLOCK_HAL_SetExternalRefSel0Mode(baseAddr, erefsVal);
652 }
653
654 /*
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
658 */
659 if (crystalVal <= kMcgConstant40000)
660 {
661 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelLow);
662 }
663 else if (crystalVal <= kMcgConstant8000000)
664 {
665 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelHigh);
666 }
667 else
668 {
669 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelVeryHigh);
670 }
671
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)
675 {
676 frDivVal = kMcgConstant0;
677 }
678 else if (crystalVal <= kMcgConstant2500000)
679 {
680 frDivVal = kMcgConstant1;
681 }
682 else if (crystalVal <= kMcgConstant5000000)
683 {
684 frDivVal = kMcgConstant2;
685 }
686 else if (crystalVal <= kMcgConstant10000000)
687 {
688 frDivVal = kMcgConstant3;
689 }
690 else if (crystalVal <= kMcgConstant20000000)
691 {
692 frDivVal = kMcgConstant4;
693 }
694 else
695 {
696 frDivVal = kMcgConstant5;
697 }
698
699 /* Set LP bit to enable the FLL */
700 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelNormal);
701
702 /*
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
706 */
707 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr, kMcgClkSelExternal, frDivVal, kMcgInternalRefClkSrcExternal);
708
709 /* if the external oscillator is used need to wait for OSCINIT to set */
710 if ((oscselVal == kMcgOscselOsc) && (erefsVal))
711 {
712 for (i = 0 ; i < kMcgConstant10000 ; i++)
713 {
714 if (CLOCK_HAL_GetOscInit0(baseAddr))
715 {
716 break; /* jump out early if OSCINIT sets before loop finishes */
717 }
718 }
719
720 if (!CLOCK_HAL_GetOscInit0(baseAddr))
721 {
722 /* check bit is really set and return with error if not set */
723 return kMcgErrOscSetTimeout;
724 }
725 }
726
727 /* wait for Reference clock Status bit to clear */
728 for (i = 0 ; i < kMcgConstant2000 ; i++)
729 {
730 if (!CLOCK_HAL_GetInternalRefStatMode(baseAddr))
731 {
732 break; /* jump out early if IREFST clears before loop finishes */
733 }
734 }
735
736 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr))
737 {
738 /* check bit is really clear and return with error if not set */
739 return kMcgErrIrefstClearTimeOut;
740 }
741
742 /* Wait for clock status bits to show clock source is ext ref clk */
743 for (i = 0 ; i < kMcgConstant2000 ; i++)
744 {
745 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatExternalRef)
746 {
747 break; /* jump out early if CLKST shows EXT CLK slected before loop finishes */
748 }
749 }
750
751 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatExternalRef)
752 {
753 return kMcgErrClkst2; /* check EXT CLK is really selected and return with error if not */
754 }
755
756 /*
757 * Now in FBE
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.
760 */
761 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr, true);
762
763 return crystalVal; /* MCGOUT frequency equals external clock frequency */
764 } /* CLOCK_HAL_SetFeiToFbeMode */
765
766 /*FUNCTION******************************************************************************
767 *
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.
771 *
772 * Parameters: ircFreq - internal reference clock frequency value (slow)
773 *
774 * Return value : MCGCLKOUT frequency (Hz) or error code
775 *END***********************************************************************************/
776 uint32_t CLOCK_HAL_SetFeeToFeiMode(uint32_t baseAddr, uint32_t ircFreq)
777 {
778 int16_t i;
779 uint32_t mcgOut;
780
781 /* Check MCG is in FEE mode */
782 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFEE)
783 {
784 return kMcgErrNotInFeeMode; /* return error code */
785 }
786
787 /* Check IRC frequency is within spec. */
788 if ((ircFreq < kMcgConstant31250) || (ircFreq > kMcgConstant39063))
789 {
790 return kMcgErrIrcSlowRange;
791 }
792
793 /* Check resulting FLL frequency */
794 mcgOut = CLOCK_HAL_GetFllFrequency(baseAddr, ircFreq);
795 if (mcgOut < kMcgErrMax)
796 {
797 /* If error code returned, return the code to calling function */
798 return mcgOut;
799 }
800
801 /* Ensure clock monitor is disabled before switching to FEI otherwise
802 * a loss of clock will trigger
803 */
804 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr, false);
805
806 /* Change FLL reference clock from external to internal by setting IREFS bit */
807 CLOCK_HAL_SetInternalRefSelMode(baseAddr, kMcgInternalRefClkSrcSlow);
808
809 /* wait for Reference clock to switch to internal reference */
810 for (i = 0 ; i < kMcgConstant2000 ; i++)
811 {
812 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr) == kMcgInternalRefStatInternal)
813 {
814 break; /* jump out early if IREFST sets before loop finishes */
815 }
816 }
817
818 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr) != kMcgInternalRefStatInternal)
819 {
820 /* check bit is really set and return with error if not set */
821 return kMcgErrIrefstSetTimeout;
822 }
823
824 /* Now in FEI mode */
825 return mcgOut;
826 } /* CLOCK_HAL_SetFeeToFeiMode */
827
828 /*FUNCTION******************************************************************************
829 *
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.
833 *
834 * Parameters: ircFreq - internal reference clock frequency value
835 * ircSelect - slow or fast clock selection
836 * 0: slow, 1: fast
837 *
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)
841 {
842 uint8_t fcrDivVal;
843 int16_t i;
844
845 /* Check MCG is in FEE mode */
846 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFEE)
847 {
848 return kMcgErrNotInFeeMode; /* return error code */
849 }
850
851 /* Check that the irc frequency matches the selected IRC */
852 if (!(ircSelect))
853 {
854 if ((ircFreq < kMcgConstant31250) || (ircFreq > kMcgConstant39063))
855 {
856 return kMcgErrIrcSlowRange;
857 }
858 }
859 else
860 {
861 if ((ircFreq < kMcgConstant3000000) || (ircFreq > kMcgConstant5000000))
862 {
863 return kMcgErrIrcFastRange;
864 } /* Fast IRC freq */
865 }
866
867 /* Select the required IRC */
868 CLOCK_HAL_SetInternalRefClkSelMode(baseAddr, ircSelect);
869
870 /* Make sure the clock monitor is disabled before switching modes otherwise it will trigger */
871 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr, false);
872
873 /* Select the IRC as the CLKS mux selection */
874 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr, kMcgClkSelInternal, CLOCK_HAL_GetFllExternalRefDivider(baseAddr), kMcgInternalRefClkSrcSlow);
875
876 /* wait until internal reference switches to requested irc. */
877 if (ircSelect == kMcgInternalRefClkSelSlow)
878 {
879 for (i = 0 ; i < kMcgConstant2000 ; i++)
880 {
881 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr) == kMcgInternalRefClkStatSlow)
882 {
883 break; /* jump out early if IRCST clears before loop finishes */
884 }
885 }
886 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr) != kMcgInternalRefClkStatSlow)
887 {
888 /* check bit is really clear and return with error if set */
889 return kMcgErrIrcstClearTimeout;
890 }
891 }
892 else
893 {
894 for (i = 0 ; i < kMcgConstant2000 ; i++)
895 {
896 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr) == kMcgInternalRefClkStatFast)
897 {
898 break; /* jump out early if IRCST sets before loop finishes */
899 }
900 }
901 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr) != kMcgInternalRefClkStatFast)
902 {
903 /* check bit is really set and return with error if not set */
904 return kMcgErrIrefstSetTimeout1;
905 }
906 }
907
908 /* Wait for clock status bits to update */
909 for (i = 0 ; i < kMcgConstant2000 ; i++)
910 {
911 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatInternalRef)
912 {
913 break; /* jump out early if CLKST shows IRC slected before loop finishes */
914 }
915 }
916
917 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatInternalRef)
918 {
919 return kMcgErrClkst1; /* check IRC is really selected and return with error if not */
920 }
921
922 /* wait for Reference clock Status bit to set */
923 for (i = 0 ; i < kMcgConstant2000 ; i++)
924 {
925 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr) == kMcgInternalRefStatInternal)
926 {
927 break; /* jump out early if IREFST sets before loop finishes */
928 }
929 }
930
931 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr) != kMcgInternalRefStatInternal)
932 {
933 /* check bit is really set and return with error if not set */
934 return kMcgErrIrefstSetTimeout;
935 }
936
937 /* Now in FBI mode */
938 if (ircSelect == kMcgInternalRefClkSelFast)
939 {
940 fcrDivVal = CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr);
941
942 return (ircFreq / fcrDivVal); /* MCGOUT frequency equals fast IRC frequency divided by 2 */
943 }
944 else
945 {
946 return ircFreq; /* MCGOUT frequency equals slow IRC frequency */
947 }
948 } /* CLOCK_HAL_SetFeeToFbiMode */
949
950 /*FUNCTION******************************************************************************
951 *
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.
955 *
956 * Parameters: crystalVal - external reference clock frequency value
957 *
958 * Return value : MCGCLKOUT frequency (Hz) or error code
959 *END***********************************************************************************/
960 uint32_t CLOCK_HAL_SetFeeToFbeMode(uint32_t baseAddr, uint32_t crystalVal)
961 {
962 uint16_t i;
963
964 /* Check MCG is in FEE mode */
965 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFEE)
966 {
967 return kMcgErrNotInFeeMode; /* return error code */
968 }
969
970 /* Set CLKS field to 2 to switch CLKS mux to select ext ref clock */
971 CLOCK_HAL_SetClkSrcMode(baseAddr, kMcgClkSelExternal);
972
973 /* Wait for clock status bits to show clock source is ext ref clk */
974 for (i = 0 ; i < kMcgConstant2000 ; i++)
975 {
976 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatExternalRef)
977 {
978 break; /* jump out early if CLKST shows EXT CLK slected before loop finishes */
979 }
980 }
981
982 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatExternalRef)
983 {
984 return kMcgErrClkst2; /* check EXT CLK is really selected and return with error if not */
985 }
986
987 /* Now in FBE mode */
988 return crystalVal;
989 } /* CLOCK_HAL_SetFeeToFbeMode */
990
991 /*FUNCTION******************************************************************************
992 *
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.
996 *
997 * Parameters: ircFreq - internal reference clock frequency value (slow)
998 *
999 * Return value : MCGCLKOUT frequency (Hz) or error code
1000 *END***********************************************************************************/
1001 uint32_t CLOCK_HAL_SetFbiToFeiMode(uint32_t baseAddr, uint32_t ircFreq)
1002 {
1003 int16_t i;
1004 int32_t mcgOut;
1005
1006 /* check if in FBI mode */
1007 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBI)
1008 {
1009 return kMcgErrNotInFbiMode; /* MCG not in correct mode return fail code */
1010 }
1011
1012 /* Check IRC frequency is within spec. */
1013 if ((ircFreq < 31250) || (ircFreq > 39063))
1014 {
1015 return kMcgErrIrcSlowRange;
1016 }
1017
1018 /* Check resulting FLL frequency */
1019 mcgOut = CLOCK_HAL_GetFllFrequency(baseAddr, ircFreq);
1020 if (mcgOut < kMcgErrMax)
1021 {
1022 /* If error code returned, return the code to calling function */
1023 return mcgOut;
1024 }
1025
1026 /* Change the CLKS mux to select the FLL output as MCGOUT */
1027 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr, kMcgClkSelOut, CLOCK_HAL_GetFllExternalRefDivider(baseAddr), kMcgInternalRefClkSrcSlow);
1028
1029 /* wait for Reference clock Status bit to clear */
1030 for (i = 0 ; i < kMcgConstant2000 ; i++)
1031 {
1032 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr))
1033 {
1034 break; /* jump out early if IREFST clears before loop finishes */
1035 }
1036 }
1037
1038 if (!CLOCK_HAL_GetInternalRefStatMode(baseAddr))
1039 {
1040 /* check bit is really set and return with error if not set */
1041 return kMcgErrIrefstSetTimeout;
1042 }
1043
1044 /* Wait for clock status bits to show clock source is ext ref clk */
1045 for (i = 0 ; i < kMcgConstant2000 ; i++)
1046 {
1047 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatFll)
1048 {
1049 break; /* jump out early if CLKST shows FLL slected before loop finishes */
1050 }
1051 }
1052
1053 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatFll)
1054 {
1055 return kMcgErrClkst0; /* check FLL is really selected and return with error if not */
1056 }
1057
1058 /* Now in FEI mode */
1059 return mcgOut;
1060 } /* CLOCK_HAL_SetFbiToFeiMode */
1061
1062 /*FUNCTION******************************************************************************
1063 *
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.
1067 *
1068 * Parameters: oscselVal - oscillator selection value
1069 * 0 - OSC 0, 1 - RTC 32k, 2 - IRC 48M
1070 * crystalVal - external clock frequency in Hz
1071 * oscselVal - 0
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)
1080 *
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)
1084 {
1085 uint8_t frDivVal;
1086 uint32_t i;
1087 uint32_t mcgOut, fllRefFreq;
1088
1089 /* check if in FBI mode */
1090 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBI)
1091 {
1092 return kMcgErrNotInFbiMode; /* MCG not in correct mode return fail code */
1093 }
1094
1095 /* check external frequency is less than the maximum frequency */
1096 if (crystalVal > kMcgConstant50000000)
1097 {
1098 return kMcgErrOscEtalRange;
1099 }
1100
1101 /* check crystal frequency is within spec. if crystal osc is being used */
1102 if (oscselVal == kMcgOscselOsc)
1103 {
1104 if (erefsVal)
1105 {
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))
1110 {
1111 return kMcgErrOscXtalRange; /* - crystal frequency outside allowed range */
1112 }
1113
1114 /* config the hgo settings */
1115 CLOCK_HAL_SetHighGainOsc0Mode(baseAddr, hgoVal);
1116 }
1117
1118 /* config the erefs0 settings */
1119 CLOCK_HAL_SetExternalRefSel0Mode(baseAddr, erefsVal);
1120 }
1121
1122 /*
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
1126 */
1127 if (crystalVal <= kMcgConstant40000)
1128 {
1129 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelLow);
1130 }
1131 else if (crystalVal <= kMcgConstant8000000)
1132 {
1133 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelHigh);
1134 }
1135 else
1136 {
1137 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelVeryHigh);
1138 }
1139
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.
1143 */
1144 if (crystalVal <= kMcgConstant1250000)
1145 {
1146 frDivVal = kMcgConstant0;
1147 }
1148 else if (crystalVal <= kMcgConstant2500000)
1149 {
1150 frDivVal = kMcgConstant1;
1151 }
1152 else if (crystalVal <= kMcgConstant5000000)
1153 {
1154 frDivVal = kMcgConstant2;
1155 }
1156 else if (crystalVal <= kMcgConstant10000000)
1157 {
1158 frDivVal = kMcgConstant3;
1159 }
1160 else if (crystalVal <= kMcgConstant20000000)
1161 {
1162 frDivVal = kMcgConstant4;
1163 }
1164 else
1165 {
1166 frDivVal = kMcgConstant5;
1167 }
1168
1169 /* The FLL ref clk divide value depends on FRDIV and the RANGE value */
1170 if (CLOCK_HAL_GetRange0Mode(baseAddr) > kMcgFreqRangeSelLow)
1171 {
1172 fllRefFreq = ((crystalVal) / (kMcgConstant32 << frDivVal));
1173 }
1174 else
1175 {
1176 fllRefFreq = ((crystalVal) / (kMcgConstant1 << frDivVal));
1177 }
1178
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)
1183 {
1184 return mcgOut; /* If error code returned, return the code to calling function */
1185 }
1186
1187 /*
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
1191 */
1192 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr, kMcgClkSelOut, frDivVal, kMcgInternalRefClkSrcExternal);
1193
1194 /* if the external oscillator is used need to wait for OSCINIT to set */
1195 if ((oscselVal == kMcgOscselOsc) && (erefsVal))
1196 {
1197 for (i = 0 ; i < kMcgConstant20000000 ; i++)
1198 {
1199 if (CLOCK_HAL_GetOscInit0(baseAddr))
1200 {
1201 break; /* jump out early if OSCINIT sets before loop finishes */
1202 }
1203 }
1204
1205 if (!CLOCK_HAL_GetOscInit0(baseAddr))
1206 {
1207 /* check bit is really set and return with error if not set */
1208 return kMcgErrOscSetTimeout;
1209 }
1210 }
1211
1212 /* Wait for clock status bits to show clock source is FLL */
1213 for (i = 0 ; i < kMcgConstant2000 ; i++)
1214 {
1215 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatFll)
1216 {
1217 break; // jump out early if CLKST shows FLL selected before loop finishes
1218 }
1219 }
1220
1221 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatFll)
1222 {
1223 return kMcgErrClkst0; // check FLL is really selected and return with error if not
1224 }
1225
1226 /*
1227 * Now in FEE
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.
1231 */
1232 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr, true);
1233
1234 return mcgOut; /* MCGOUT frequency equals FLL frequency */
1235 } /* CLOCK_HAL_SetFbiToFeeMode */
1236
1237 /*FUNCTION******************************************************************************
1238 *
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.
1242 *
1243 * Parameters: oscselVal - oscillator selection value
1244 * 0 - OSC 0, 1 - RTC 32k, 2 - IRC 48M
1245 * crystalVal - external clock frequency in Hz
1246 * oscselVal - 0
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)
1255 *
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)
1259 {
1260 uint8_t frDivVal;
1261 uint16_t i;
1262
1263 /* check if in FBI mode */
1264 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBI)
1265 {
1266 return kMcgErrNotInFbiMode; /* MCG not in correct mode return fail code */
1267 }
1268
1269 /* check external frequency is less than the maximum frequency */
1270 if (crystalVal > kMcgConstant50000000)
1271 {
1272 return kMcgErrOscEtalRange;
1273 }
1274
1275 /* check crystal frequency is within spec. if crystal osc is being used */
1276 if (oscselVal == kMcgOscselOsc)
1277 {
1278 if (erefsVal)
1279 {
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))
1284 {
1285 return kMcgErrOscXtalRange; /* - crystal frequency outside allowed range */
1286 }
1287
1288 /* config the hgo settings */
1289 CLOCK_HAL_SetHighGainOsc0Mode(baseAddr, hgoVal);
1290 }
1291
1292 /* config the erefs0 settings */
1293 CLOCK_HAL_SetExternalRefSel0Mode(baseAddr, erefsVal);
1294 }
1295
1296 /*
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
1300 */
1301 if (crystalVal <= kMcgConstant40000)
1302 {
1303 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelLow);
1304 }
1305 else if (crystalVal <= kMcgConstant8000000)
1306 {
1307 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelHigh);
1308 }
1309 else
1310 {
1311 CLOCK_HAL_SetRange0Mode(baseAddr, kMcgFreqRangeSelVeryHigh);
1312 }
1313
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.
1317 */
1318 if (crystalVal <= kMcgConstant1250000)
1319 {
1320 frDivVal = kMcgConstant0;
1321 }
1322 else if (crystalVal <= kMcgConstant2500000)
1323 {
1324 frDivVal = kMcgConstant1;
1325 }
1326 else if (crystalVal <= kMcgConstant5000000)
1327 {
1328 frDivVal = kMcgConstant2;
1329 }
1330 else if (crystalVal <= kMcgConstant10000000)
1331 {
1332 frDivVal = kMcgConstant3;
1333 }
1334 else if (crystalVal <= kMcgConstant20000000)
1335 {
1336 frDivVal = kMcgConstant4;
1337 }
1338 else
1339 {
1340 frDivVal = kMcgConstant5;
1341 }
1342
1343 /* Set LP bit to enable the FLL */
1344 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelNormal);
1345
1346 /*
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
1350 */
1351 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr, kMcgClkSelExternal, frDivVal, kMcgInternalRefClkSrcExternal);
1352
1353 /* if the external oscillator is used need to wait for OSCINIT to set */
1354 if ((oscselVal == kMcgOscselOsc) && (erefsVal))
1355 {
1356 for (i = 0 ; i < kMcgConstant10000 ; i++)
1357 {
1358 if (CLOCK_HAL_GetOscInit0(baseAddr))
1359 {
1360 break; /* jump out early if OSCINIT sets before loop finishes */
1361 }
1362 }
1363
1364 if (!CLOCK_HAL_GetOscInit0(baseAddr))
1365 {
1366 /* check bit is really set and return with error if not set */
1367 return kMcgErrOscSetTimeout;
1368 }
1369 }
1370
1371 /* wait for Reference clock Status bit to clear */
1372 for (i = 0 ; i < kMcgConstant2000 ; i++)
1373 {
1374 if (!CLOCK_HAL_GetInternalRefStatMode(baseAddr))
1375 {
1376 break; /* jump out early if IREFST clears before loop finishes */
1377 }
1378 }
1379
1380 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr))
1381 {
1382 /* check bit is really clear and return with error if not set */
1383 return kMcgErrIrefstClearTimeOut;
1384 }
1385
1386 /* Wait for clock status bits to show clock source is ext ref clk */
1387 for (i = 0 ; i < kMcgConstant2000 ; i++)
1388 {
1389 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatExternalRef)
1390 {
1391 break; /* jump out early if CLKST shows EXT CLK slected before loop finishes */
1392 }
1393 }
1394
1395 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatExternalRef)
1396 {
1397 return kMcgErrClkst2; /* check EXT CLK is really selected and return with error if not */
1398 }
1399
1400 /*
1401 * Now in FBE
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.
1404 */
1405 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr, true);
1406
1407 return crystalVal; /* MCGOUT frequency equals external clock frequency */
1408 } /* CLOCK_HAL_SetFbiToFbeMode */
1409
1410 /*FUNCTION******************************************************************************
1411 *
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.
1416 *
1417 * Parameters: ircFreq - internal reference clock frequency value
1418 * ircSelect - slow or fast clock selection
1419 * 0: slow, 1: fast
1420 *
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)
1424 {
1425 uint8_t fcrDivVal;
1426
1427 /* check if in FBI mode */
1428 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBI)
1429 {
1430 return kMcgErrNotInFbiMode; /* MCG not in correct mode return fail code */
1431 }
1432
1433 /* Set LP bit to disable the FLL and enter BLPI */
1434 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelLowPower);
1435
1436 /* Now in BLPI */
1437 if (ircSelect == kMcgInternalRefClkSelFast)
1438 {
1439 fcrDivVal = CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr);
1440 return (ircFreq / fcrDivVal); /* MCGOUT frequency equals fast IRC frequency divided by 2 */
1441 }
1442 else
1443 {
1444 return ircFreq; /* MCGOUT frequency equals slow IRC frequency */
1445 }
1446 } /* CLOCK_HAL_SetFbiToBlpiMode */
1447
1448 /*FUNCTION******************************************************************************
1449 *
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.
1454 *
1455 * Parameters: ircFreq - internal reference clock frequency value
1456 * ircSelect - slow or fast clock selection
1457 * 0: slow, 1: fast
1458 *
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)
1462 {
1463 uint8_t fcrDivVal;
1464
1465 /* check if in BLPI mode */
1466 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeBLPI)
1467 {
1468 return kMcgErrNotInBlpiMode; /* MCG not in correct mode return fail code */
1469 }
1470
1471 /* Clear LP bit to enable the FLL and enter FBI mode */
1472 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelNormal);
1473
1474 /* Now in FBI mode */
1475 if (ircSelect)
1476 {
1477 fcrDivVal = CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr);
1478 return (ircFreq / fcrDivVal); /* MCGOUT frequency equals fast IRC frequency divided by 2 */
1479 }
1480 else
1481 {
1482 return ircFreq; /* MCGOUT frequency equals slow IRC frequency */
1483 }
1484 } /* CLOCK_HAL_SetBlpiToFbiMode */
1485
1486 /*FUNCTION******************************************************************************
1487 *
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.
1491 *
1492 * Parameters: crystalVal - external reference clock frequency value
1493 *
1494 * Return value : MCGCLKOUT frequency (Hz) or error code
1495 *END***********************************************************************************/
1496 uint32_t CLOCK_HAL_SetFbeToFeeMode(uint32_t baseAddr, uint32_t crystalVal)
1497 {
1498 uint16_t i, fllRefFreq, frDivVal;
1499 uint32_t mcgOut;
1500
1501 /* Check MCG is in FBE mode */
1502 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBE)
1503 {
1504 return kMcgErrNotInFbeMode; /* return error code */
1505 }
1506
1507 /* get curretn frdiv value */
1508 frDivVal = CLOCK_HAL_GetFllExternalRefDivider(baseAddr);
1509
1510 /* The FLL ref clk divide value depends on FRDIV and the RANGE value */
1511 if (CLOCK_HAL_GetRange0Mode(baseAddr) > kMcgFreqRangeSelLow)
1512 {
1513 fllRefFreq = ((crystalVal) / (kMcgConstant32 << frDivVal));
1514 }
1515 else
1516 {
1517 fllRefFreq = ((crystalVal) / (kMcgConstant1 << frDivVal));
1518 }
1519
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)
1524 {
1525 return mcgOut; /* If error code returned, return the code to calling function */
1526 }
1527
1528 /* Clear CLKS field to switch CLKS mux to select FLL output */
1529 CLOCK_HAL_SetClkSrcMode(baseAddr, kMcgClkSelOut);
1530
1531 /* Wait for clock status bits to show clock source is FLL */
1532 for (i = 0 ; i < kMcgConstant2000 ; i++)
1533 {
1534 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatFll)
1535 {
1536 break; // jump out early if CLKST shows FLL selected before loop finishes
1537 }
1538 }
1539
1540 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatFll)
1541 {
1542 return kMcgErrClkst0; // check FLL is really selected and return with error if not
1543 }
1544
1545 /* Now in FEE mode */
1546 return mcgOut;
1547 } /* CLOCK_HAL_SetFbeToFeeMode */
1548
1549 /*FUNCTION******************************************************************************
1550 *
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.
1554 *
1555 * Parameters: ircFreq - internal reference clock frequency value (slow)
1556 *
1557 * Return value : MCGCLKOUT frequency (Hz) or error code
1558 *END***********************************************************************************/
1559 uint32_t CLOCK_HAL_SetFbeToFeiMode(uint32_t baseAddr, uint32_t ircFreq)
1560 {
1561 uint16_t i;
1562 uint32_t mcgOut;
1563
1564 /* Check MCG is in FBE mode */
1565 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBE)
1566 {
1567 return kMcgErrNotInFbeMode; /* return error code */
1568 }
1569
1570 /* Check IRC frequency is within spec. */
1571 if ((ircFreq < kMcgConstant31250) || (ircFreq > kMcgConstant39063))
1572 {
1573 return kMcgErrIrcSlowRange;
1574 }
1575
1576 /* Check resulting FLL frequency */
1577 mcgOut = CLOCK_HAL_GetFllFrequency(baseAddr, ircFreq);
1578 if (mcgOut < kMcgErrMax)
1579 {
1580 /* If error code returned, return the code to calling function */
1581 return mcgOut;
1582 }
1583
1584 /*
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.
1587 */
1588 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr, false);
1589
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);
1592
1593 /* wait for Reference clock to switch to internal reference */
1594 for (i = 0 ; i < kMcgConstant2000 ; i++)
1595 {
1596 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr) == kMcgInternalRefStatInternal)
1597 {
1598 break; /* jump out early if IREFST sets before loop finishes */
1599 }
1600 }
1601
1602 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr) != kMcgInternalRefStatInternal)
1603 {
1604 /* check bit is really set and return with error if not set */
1605 return kMcgErrIrefstSetTimeout;
1606 }
1607
1608 /* Wait for clock status bits to show clock source is FLL output */
1609 for (i = 0 ; i < kMcgConstant2000 ; i++)
1610 {
1611 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatFll)
1612 {
1613 /* jump out early if CLKST shows FLL output slected before loop finishes */
1614 break;
1615 }
1616 }
1617
1618 /* check FLL output is really selected */
1619 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatFll)
1620 {
1621 /* return with error if not */
1622 return kMcgErrClkst0;
1623 }
1624
1625 /* Now in FEI mode */
1626 return mcgOut;
1627 } /* CLOCK_HAL_SetFbeToFeiMode */
1628
1629 /*FUNCTION******************************************************************************
1630 *
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.
1634 *
1635 * Parameters: ircFreq - internal reference clock frequency value
1636 * ircSelect - slow or fast clock selection
1637 * 0: slow, 1: fast
1638 *
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)
1642 {
1643 uint8_t fcrDivVal;
1644 uint16_t i;
1645
1646 /* Check MCG is in FBE mode */
1647 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBE)
1648 {
1649 return kMcgErrNotInFbeMode; /* return error code */
1650 }
1651
1652 /* Check that the irc frequency matches the selected IRC */
1653 if (!(ircSelect))
1654 {
1655 if ((ircFreq < kMcgConstant31250) || (ircFreq > kMcgConstant39063))
1656 {
1657 return kMcgErrIrcSlowRange;
1658 }
1659 }
1660 else
1661 {
1662 if ((ircFreq < kMcgConstant3000000) || (ircFreq > kMcgConstant5000000))
1663 {
1664 return kMcgErrIrcFastRange;
1665 } /* Fast IRC freq */
1666 }
1667
1668 /* Select the required IRC */
1669 CLOCK_HAL_SetInternalRefClkSelMode(baseAddr, ircSelect);
1670
1671 /* Make sure the clock monitor is disabled before switching modes otherwise it will trigger */
1672 CLOCK_HAL_SetClkMonitor0Cmd(baseAddr, false);
1673
1674 /* Select the IRC as the CLKS mux selection */
1675 CLOCK_HAL_SetClksFrdivInternalRefSelect(baseAddr, kMcgClkSelInternal, CLOCK_HAL_GetFllExternalRefDivider(baseAddr), kMcgInternalRefClkSrcSlow);
1676
1677 /* wait until internal reference switches to requested irc. */
1678 if (ircSelect == kMcgInternalRefClkSelSlow)
1679 {
1680 for (i = 0 ; i < kMcgConstant2000 ; i++)
1681 {
1682 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr) == kMcgInternalRefClkStatSlow)
1683 {
1684 break; /* jump out early if IRCST clears before loop finishes */
1685 }
1686 }
1687 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr) != kMcgInternalRefClkStatSlow)
1688 {
1689 /* check bit is really clear and return with error if set */
1690 return kMcgErrIrcstClearTimeout;
1691 }
1692 }
1693 else
1694 {
1695 for (i = 0 ; i < kMcgConstant2000 ; i++)
1696 {
1697 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr) == kMcgInternalRefClkStatFast)
1698 {
1699 break; /* jump out early if IRCST sets before loop finishes */
1700 }
1701 }
1702 if (CLOCK_HAL_GetInternalRefClkStatMode(baseAddr) != kMcgInternalRefClkStatFast)
1703 {
1704 /* check bit is really set and return with error if not set */
1705 return kMcgErrIrefstSetTimeout1;
1706 }
1707 }
1708
1709 /* Wait for clock status bits to update */
1710 for (i = 0 ; i < kMcgConstant2000 ; i++)
1711 {
1712 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatInternalRef)
1713 {
1714 break; /* jump out early if CLKST shows IRC slected before loop finishes */
1715 }
1716 }
1717
1718 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatInternalRef)
1719 {
1720 return kMcgErrClkst1; /* check IRC is really selected and return with error if not */
1721 }
1722
1723 /* wait for Reference clock Status bit to set */
1724 for (i = 0 ; i < kMcgConstant2000 ; i++)
1725 {
1726 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr) == kMcgInternalRefStatInternal)
1727 {
1728 break; /* jump out early if IREFST sets before loop finishes */
1729 }
1730 }
1731
1732 if (CLOCK_HAL_GetInternalRefStatMode(baseAddr) != kMcgInternalRefStatInternal)
1733 {
1734 /* check bit is really set and return with error if not set */
1735 return kMcgErrIrefstSetTimeout;
1736 }
1737
1738 /* Now in FBI mode */
1739 if (ircSelect == kMcgInternalRefClkSelFast)
1740 {
1741 fcrDivVal = CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr);
1742
1743 return (ircFreq / fcrDivVal); /* MCGOUT frequency equals fast IRC frequency divided by 2 */
1744 }
1745 else
1746 {
1747 return ircFreq; /* MCGOUT frequency equals slow IRC frequency */
1748 }
1749 } /* CLOCK_HAL_SetFbeToFbiMode */
1750
1751 #if FSL_FEATURE_MCG_HAS_PLL
1752
1753 /*FUNCTION******************************************************************************
1754 *
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
1766 *
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)
1771 {
1772 uint16_t i;
1773 uint32_t pllFreq;
1774
1775 /* Check MCG is in FBE mode */
1776 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBE)
1777 {
1778 return kMcgErrNotInFbeMode; /* return error code */
1779 }
1780
1781 /*
1782 * As the external frequency (osc0) has already been checked when FBE mode was enterred
1783 * it is not checked here.
1784 */
1785
1786 /* Check PLL divider settings are within spec.*/
1787 if ((prdivVal < 1) || (prdivVal > FSL_FEATURE_MCG_PLL_PRDIV_MAX))
1788 {
1789 return kMcgErrPllPrdidRange;
1790 }
1791
1792 if ((vdivVal < FSL_FEATURE_MCG_PLL_VDIV_BASE) || (vdivVal > (FSL_FEATURE_MCG_PLL_VDIV_BASE + 31)))
1793 {
1794 return kMcgErrPllVdivRange;
1795 }
1796
1797 /* Check PLL reference clock frequency is within spec. */
1798 if (((crystalVal / prdivVal) < kMcgConstant8000000) || ((crystalVal / prdivVal) > kMcgConstant32000000))
1799 {
1800 return kMcgErrPllRefClkRange;
1801 }
1802
1803 /* Check PLL output frequency is within spec. */
1804 pllFreq = (crystalVal / prdivVal) * vdivVal;
1805 if ((pllFreq < kMcgConstant180000000) || (pllFreq > kMcgConstant360000000))
1806 {
1807 return kMcgErrPllOutClkRange;
1808 }
1809
1810 #if FSL_FEATURE_MCG_HAS_PLL1
1811 /* set pllcsSelect */
1812 CLOCK_HAL_SetPllcs(pllcsSelect);
1813
1814 if (pllcsSelect == kMcgPllcsSelectPll0)
1815 #endif
1816 {
1817 /*
1818 * Configure MCG_C5
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.
1821 */
1822
1823 CLOCK_HAL_SetPllExternalRefDivider0(baseAddr, prdivVal - 1);
1824
1825 /*
1826 * Configure MCG_C6
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
1831 */
1832
1833 CLOCK_HAL_SetVoltCtrlOscDivider0(baseAddr, vdivVal - FSL_FEATURE_MCG_PLL_VDIV_BASE);
1834 CLOCK_HAL_SetPllSelMode(baseAddr, kMcgPllSelPllClkSel);
1835
1836 // wait for PLLST status bit to set
1837 for (i = 0 ; i < kMcgConstant2000 ; i++)
1838 {
1839 if (CLOCK_HAL_GetPllStatMode(baseAddr) == kMcgPllStatPllClkSel)
1840 {
1841 /* jump out early if PLLST sets before loop finishes */
1842 break;
1843 }
1844 }
1845
1846 /* check bit is really set */
1847 if ((CLOCK_HAL_GetPllStatMode(baseAddr) != kMcgPllStatPllClkSel))
1848 {
1849 /* return with error if not set */
1850 return kMcgErrPllstSetTimeout;
1851 }
1852
1853 /* Wait for LOCK bit to set */
1854 for (i = 0 ; i < kMcgConstant2000 ; i++)
1855 {
1856 if (CLOCK_HAL_GetLock0Mode(baseAddr) == kMcgLockLocked)
1857 {
1858 /* jump out early if LOCK sets before loop finishes */
1859 break;
1860 }
1861 }
1862
1863 /* check bit is really set */
1864 if ((CLOCK_HAL_GetLock0Mode(baseAddr) != kMcgLockLocked))
1865 {
1866 /* return with error if not set */
1867 return kMcgErrPllLockBit;
1868 }
1869
1870 #if FSL_FEATURE_MCG_USE_PLLREFSEL
1871 /* wait for PLLCST status bit to clear */
1872 for (i = 0 ; i < kMcgConstant2000 ; i++)
1873 {
1874 if (CLOCK_HAL_GetPllcst(baseAddr) == kMcgPllcsSelectPll0)
1875 {
1876 /* jump out early if PLLST sets before loop finishes */
1877 break;
1878 }
1879 }
1880
1881 /* check bit is really set */
1882 if (CLOCK_HAL_GetPllcst(baseAddr) != kMcgPllcsSelectPll0)
1883 {
1884 /* return with error if not set */
1885 return kMcgErrPllcst;
1886 }
1887 #endif
1888 }
1889 #if FSL_FEATURE_MCG_HAS_PLL1
1890 else
1891 {
1892 /*
1893 * Configure MCG_C11
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.
1896 */
1897 CLOCK_HAL_SetPrdiv1(prdivVal - 1);
1898
1899 /*
1900 * Configure MCG_C12
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
1905 * in MCG_C12
1906 */
1907
1908 CLOCK_HAL_SetVdiv1(vdivVal - FSL_FEATURE_MCG_PLL_VDIV_BASE);
1909 CLOCK_HAL_SetPllSelMode(kMcgPllSelPllClkSel);
1910
1911 // wait for PLLST status bit to set
1912 for (i = 0 ; i < kMcgConstant2000 ; i++)
1913 {
1914 if (CLOCK_HAL_GetPllStatMode(baseAddr) == kMcgPllStatPllClkSel)
1915 {
1916 /* jump out early if PLLST sets before loop finishes */
1917 break;
1918 }
1919 }
1920
1921 /* check bit is really set */
1922 if ((CLOCK_HAL_GetPllStatMode(baseAddr) != kMcgPllStatPllClkSel))
1923 {
1924 /* return with error if not set */
1925 return kMcgErrPllstSetTimeout;
1926 }
1927
1928 /* Wait for LOCK bit to set */
1929 for (i = 0 ; i < kMcgConstant2000 ; i++)
1930 {
1931 if (CLOCK_HAL_GetLock1(baseAddr) == kMcgLockLocked)
1932 {
1933 /* jump out early if LOCK sets before loop finishes */
1934 break;
1935 }
1936 }
1937
1938 /* check bit is really set */
1939 if ((CLOCK_HAL_GetLock1(baseAddr) != kMcgLockLocked))
1940 {
1941 /* return with error if not set */
1942 return kMcgErrPllLockBit;
1943 }
1944
1945 /* wait for PLLCST status bit to clear */
1946 for (i = 0 ; i < kMcgConstant2000 ; i++)
1947 {
1948 if (CLOCK_HAL_GetPllcst(baseAddr) == kMcgPllcsSelectPll1)
1949 {
1950 /* jump out early if PLLST sets before loop finishes */
1951 break;
1952 }
1953 }
1954
1955 /* check bit is really set */
1956 if (CLOCK_HAL_GetPllcst(baseAddr) != kMcgPllcsSelectPll1)
1957 {
1958 /* return with error if not set */
1959 return kMcgErrPllcst;
1960 }
1961 }
1962 #endif /* PLL1 is selected */
1963
1964 /* now in PBE */
1965
1966 /* MCGOUT frequency equals external clock frequency */
1967 return crystalVal;
1968 } /* CLOCK_HAL_SetFbeToPbeMode */
1969 #endif
1970
1971 /*FUNCTION******************************************************************************
1972 *
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.
1976 *
1977 * Parameters: crystalVal - external clock frequency in Hz
1978 *
1979 * Return value : MCGCLKOUT frequency (Hz) or error code
1980 *END***********************************************************************************/
1981 uint32_t CLOCK_HAL_SetFbeToBlpeMode(uint32_t baseAddr, uint32_t crystalVal)
1982 {
1983 /* Check MCG is in FBE mode */
1984 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeFBE)
1985 {
1986 return kMcgErrNotInFbeMode; /* return error code */
1987 }
1988
1989 /* To move from FBE to BLPE the LP bit must be set */
1990 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelLowPower);
1991
1992 /* now in FBE mode */
1993
1994 /* MCGOUT frequency equals external clock frequency */
1995 return crystalVal;
1996 } /* CLOCK_HAL_SetFbeToBlpeMode */
1997
1998 #if FSL_FEATURE_MCG_HAS_PLL
1999
2000 /*FUNCTION******************************************************************************
2001 *
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.
2005 *
2006 * Parameters: crystalVal - external clock frequency in Hz
2007 *
2008 * Return value : MCGCLKOUT frequency (Hz) or error code
2009 *END***********************************************************************************/
2010 uint32_t CLOCK_HAL_SetPbeToFbeMode(uint32_t baseAddr, uint32_t crystalVal)
2011 {
2012 int16_t i;
2013
2014 /* Check MCG is in PBE mode */
2015 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModePBE)
2016 {
2017 return kMcgErrNotInPbeMode; /* return error code */
2018 }
2019
2020 /*
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
2023 */
2024
2025 CLOCK_HAL_SetPllSelMode(baseAddr, kMcgPllSelFll);
2026
2027 /* wait for PLLST status bit to set */
2028 for (i = 0 ; i < kMcgConstant2000 ; i++)
2029 {
2030 if (CLOCK_HAL_GetPllStatMode(baseAddr) == kMcgPllStatFll)
2031 {
2032 /* jump out early if PLLST clears before loop finishes */
2033 break;
2034 }
2035 }
2036
2037 /* check bit is really clear */
2038 if (CLOCK_HAL_GetPllStatMode(baseAddr) != kMcgPllStatFll)
2039 {
2040 /* return with error if not clear */
2041 return kMcgErrPllstClearTimeout;
2042 }
2043
2044 /* Now in FBE mode */
2045
2046 /* MCGOUT frequency equals external clock frequency */
2047 return crystalVal;
2048 } /* CLOCK_HAL_SetPbeToFbeMode */
2049
2050 /*FUNCTION******************************************************************************
2051 *
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.
2055 *
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
2061 *
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)
2065 {
2066 uint8_t prDiv, vDiv;
2067 uint16_t i;
2068 uint32_t mcgOut;
2069
2070 /* Check MCG is in PBE mode */
2071 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModePBE)
2072 {
2073 return kMcgErrNotInPbeMode; /* return error code */
2074 }
2075
2076 /* As the PLL settings have already been checked when PBE mode was enterred they are not checked here */
2077
2078 /* Check the PLL state before transitioning to PEE mode */
2079
2080 #if FSL_FEATURE_MCG_HAS_PLL1
2081 /* Check the selected PLL state before transitioning to PEE mode */
2082 if (pllcsSelect == kMcgPllcsSelectPll1)
2083 {
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++)
2087 {
2088 if (CLOCK_HAL_GetLock1(baseAddr) == kMcgLockLocked)
2089 {
2090 /* jump out early if LOCK sets before loop finishes */
2091 break;
2092 }
2093 }
2094
2095 /* check bit is really set */
2096 if ((CLOCK_HAL_GetLock1(baseAddr) != kMcgLockLocked))
2097 {
2098 /* return with error if not set */
2099 return kMcgErrPllLockBit;
2100 }
2101
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);
2105 }
2106 else
2107 #endif
2108 {
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++)
2112 {
2113 if (CLOCK_HAL_GetLock0Mode(baseAddr) == kMcgLockLocked)
2114 {
2115 /* jump out early if LOCK sets before loop finishes */
2116 break;
2117 }
2118 }
2119
2120 /* check bit is really set */
2121 if ((CLOCK_HAL_GetLock0Mode(baseAddr) != kMcgLockLocked))
2122 {
2123 /* return with error if not set */
2124 return kMcgErrPllLockBit;
2125 }
2126
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);
2130 }
2131
2132 /* clear CLKS to switch CLKS mux to select PLL as MCG_OUT */
2133 CLOCK_HAL_SetClkSrcMode(baseAddr, kMcgClkSelOut);
2134
2135 /* Wait for clock status bits to update */
2136 for (i = 0 ; i < kMcgConstant2000 ; i++)
2137 {
2138 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatPll)
2139 {
2140 break; /* jump out early if CLKST = 3 before loop finishes */
2141 }
2142 }
2143
2144 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatPll)
2145 {
2146 return kMcgErrClkst3; /* check CLKST is set correctly and return with error if not */
2147 }
2148
2149 /* Now in PEE */
2150
2151 /* MCGOUT equals PLL output frequency with any special divider */
2152 mcgOut = (crystalVal / prDiv) * vDiv;
2153
2154 return mcgOut;
2155 } /* CLOCK_HAL_SetPbeToPeeMode */
2156
2157 /*FUNCTION******************************************************************************
2158 *
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.
2162 *
2163 * Parameters: crystalVal - external clock frequency in Hz
2164 *
2165 * Return value : MCGCLKOUT frequency (Hz) or error code
2166 *END***********************************************************************************/
2167 uint32_t CLOCK_HAL_SetPbeToBlpeMode(uint32_t baseAddr, uint32_t crystalVal)
2168 {
2169 /* Check MCG is in PBE mode */
2170 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModePBE)
2171 {
2172 return kMcgErrNotInPbeMode; /* return error code */
2173 }
2174
2175 /* To enter BLPE mode the LP bit must be set, disabling the PLL */
2176 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelLowPower);
2177
2178 /* Now in BLPE mode */
2179 return crystalVal;
2180 } /* CLOCK_HAL_SetPbeToBlpeMode */
2181
2182 /*FUNCTION******************************************************************************
2183 *
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.
2187 *
2188 * Parameters: crystalVal - external clock frequency in Hz
2189 *
2190 * Return value : MCGCLKOUT frequency (Hz) or error code
2191 *END***********************************************************************************/
2192 uint32_t CLOCK_HAL_SetPeeToPbeMode(uint32_t baseAddr, uint32_t crystalVal)
2193 {
2194 uint16_t i;
2195
2196 /* Check MCG is in PEE mode */
2197 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModePEE)
2198 {
2199 return kMcgErrNotInPeeMode; /* return error code */
2200 }
2201
2202 /*
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
2205 */
2206 /* As CLKS is already 0 the CLKS value can simply be OR'ed into the register */
2207 CLOCK_HAL_SetClkSrcMode(baseAddr, kMcgClkSelExternal);
2208
2209 /* Wait for clock status bits to update */
2210 for (i = 0 ; i < kMcgConstant2000 ; i++)
2211 {
2212 if (CLOCK_HAL_GetClkStatMode(baseAddr) == kMcgClkStatExternalRef)
2213 {
2214 break; /* jump out early if CLKST shows EXT CLK slected before loop finishes */
2215 }
2216 }
2217
2218 if (CLOCK_HAL_GetClkStatMode(baseAddr) != kMcgClkStatExternalRef)
2219 {
2220 return kMcgErrClkst2; /* check EXT CLK is really selected and return with error if not */
2221 }
2222
2223 /* Now in PBE mode */
2224 return crystalVal; /* MCGOUT frequency equals external clock frequency */
2225 } /* CLOCK_HAL_SetPeeToPbeMode */
2226
2227 /*FUNCTION******************************************************************************
2228 *
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
2240 *
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)
2244 {
2245 uint16_t i;
2246 uint32_t pllFreq;
2247
2248 /* Check MCG is in BLPE mode */
2249 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeBLPE)
2250 {
2251 return kMcgErrNotInBlpeMode; /* return error code */
2252 }
2253
2254 /*
2255 * As the external frequency (osc0) has already been checked when FBE mode was enterred
2256 * it is not checked here.
2257 */
2258
2259 /* Check PLL divider settings are within spec.*/
2260 if ((prdivVal < 1) || (prdivVal > FSL_FEATURE_MCG_PLL_PRDIV_MAX))
2261 {
2262 return kMcgErrPllPrdidRange;
2263 }
2264
2265 if ((vdivVal < FSL_FEATURE_MCG_PLL_VDIV_BASE) || (vdivVal > (FSL_FEATURE_MCG_PLL_VDIV_BASE + 31)))
2266 {
2267 return kMcgErrPllVdivRange;
2268 }
2269
2270 /* Check PLL reference clock frequency is within spec. */
2271 if (((crystalVal / prdivVal) < kMcgConstant8000000) || ((crystalVal / prdivVal) > kMcgConstant32000000))
2272 {
2273 return kMcgErrPllRefClkRange;
2274 }
2275
2276 /* Check PLL output frequency is within spec. */
2277 pllFreq = (crystalVal / prdivVal) * vdivVal;
2278 if ((pllFreq < kMcgConstant180000000) || (pllFreq > kMcgConstant360000000))
2279 {
2280 return kMcgErrPllOutClkRange;
2281 }
2282
2283 #if FSL_FEATURE_MCG_HAS_PLL1
2284 /* set pllcsSelect */
2285 CLOCK_HAL_SetPllcs(pllcsSelect);
2286
2287 if (pllcsSelect == kMcgPllcsSelectPll0)
2288 #endif
2289 {
2290 /*
2291 * Configure MCG_C5
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.
2294 */
2295
2296 CLOCK_HAL_SetPllExternalRefDivider0(baseAddr, prdivVal - 1);
2297
2298 /*
2299 * Configure MCG_C6
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
2304 */
2305
2306 CLOCK_HAL_SetVoltCtrlOscDivider0(baseAddr, vdivVal - FSL_FEATURE_MCG_PLL_VDIV_BASE);
2307 CLOCK_HAL_SetPllSelMode(baseAddr, kMcgPllSelPllClkSel);
2308
2309 /* Set LP bit to enable the PLL */
2310 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelNormal);
2311
2312 // wait for PLLST status bit to set
2313 for (i = 0 ; i < kMcgConstant2000 ; i++)
2314 {
2315 if (CLOCK_HAL_GetPllStatMode(baseAddr) == kMcgPllStatPllClkSel)
2316 {
2317 /* jump out early if PLLST sets before loop finishes */
2318 break;
2319 }
2320 }
2321
2322 /* check bit is really set */
2323 if ((CLOCK_HAL_GetPllStatMode(baseAddr) != kMcgPllStatPllClkSel))
2324 {
2325 /* return with error if not set */
2326 return kMcgErrPllstSetTimeout;
2327 }
2328
2329 /* Wait for LOCK bit to set */
2330 for (i = 0 ; i < kMcgConstant2000 ; i++)
2331 {
2332 if (CLOCK_HAL_GetLock0Mode(baseAddr) == kMcgLockLocked)
2333 {
2334 /* jump out early if LOCK sets before loop finishes */
2335 break;
2336 }
2337 }
2338
2339 /* check bit is really set */
2340 if ((CLOCK_HAL_GetLock0Mode(baseAddr) != kMcgLockLocked))
2341 {
2342 /* return with error if not set */
2343 return kMcgErrPllLockBit;
2344 }
2345
2346 #if FSL_FEATURE_MCG_USE_PLLREFSEL
2347 /* wait for PLLCST status bit to clear */
2348 for (i = 0 ; i < kMcgConstant2000 ; i++)
2349 {
2350 if (CLOCK_HAL_GetPllcst(baseAddr) == kMcgPllcsSelectPll0)
2351 {
2352 /* jump out early if PLLST sets before loop finishes */
2353 break;
2354 }
2355 }
2356
2357 /* check bit is really set */
2358 if (CLOCK_HAL_GetPllcst(baseAddr) != kMcgPllcsSelectPll0)
2359 {
2360 /* return with error if not set */
2361 return kMcgErrPllcst;
2362 }
2363 #endif
2364 }
2365 #if FSL_FEATURE_MCG_HAS_PLL1
2366 else
2367 {
2368 /*
2369 * Configure MCG_C11
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.
2372 */
2373 CLOCK_HAL_SetPrdiv1(prdivVal - 1);
2374
2375 /*
2376 * Configure MCG_C12
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
2381 * in MCG_C12
2382 */
2383
2384 CLOCK_HAL_SetVdiv1(vdivVal - FSL_FEATURE_MCG_PLL_VDIV_BASE);
2385 CLOCK_HAL_SetPllSelMode(kMcgPllSelPllClkSel);
2386
2387 /* Set LP bit to enable the PLL */
2388 CLOCK_HAL_SetLowPowerMode(kMcgLowPowerSelNormal);
2389
2390 // wait for PLLST status bit to set
2391 for (i = 0 ; i < kMcgConstant2000 ; i++)
2392 {
2393 if (CLOCK_HAL_GetPllStatMode(baseAddr) == kMcgPllStatPllClkSel)
2394 {
2395 /* jump out early if PLLST sets before loop finishes */
2396 break;
2397 }
2398 }
2399
2400 /* check bit is really set */
2401 if ((CLOCK_HAL_GetPllStatMode(baseAddr) != kMcgPllStatPllClkSel))
2402 {
2403 /* return with error if not set */
2404 return kMcgErrPllstSetTimeout;
2405 }
2406
2407 /* Wait for LOCK bit to set */
2408 for (i = 0 ; i < kMcgConstant2000 ; i++)
2409 {
2410 if (CLOCK_HAL_GetLock1(baseAddr) == kMcgLockLocked)
2411 {
2412 /* jump out early if LOCK sets before loop finishes */
2413 break;
2414 }
2415 }
2416
2417 /* check bit is really set */
2418 if ((CLOCK_HAL_GetLock1(baseAddr) != kMcgLockLocked))
2419 {
2420 /* return with error if not set */
2421 return kMcgErrPllLockBit;
2422 }
2423
2424 /* wait for PLLCST status bit to clear */
2425 for (i = 0 ; i < kMcgConstant2000 ; i++)
2426 {
2427 if (CLOCK_HAL_GetPllcst(baseAddr) == kMcgPllcsSelectPll1)
2428 {
2429 /* jump out early if PLLST sets before loop finishes */
2430 break;
2431 }
2432 }
2433
2434 /* check bit is really set */
2435 if (CLOCK_HAL_GetPllcst(baseAddr) != kMcgPllcsSelectPll1)
2436 {
2437 /* return with error if not set */
2438 return kMcgErrPllcst;
2439 }
2440 }
2441 #endif /* PLL1 is selected */
2442
2443 /* now in PBE */
2444
2445 /* MCGOUT frequency equals external clock frequency */
2446 return crystalVal;
2447 } /* CLOCK_HAL_SetBlpeToPbeMode */
2448 #endif
2449
2450 /*FUNCTION******************************************************************************
2451 *
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.
2455 *
2456 * Parameters: crystalVal - external reference clock frequency value
2457 *
2458 * Return value : MCGCLKOUT frequency (Hz) or error code
2459 *END***********************************************************************************/
2460 uint32_t CLOCK_HAL_SetBlpeToFbeMode(uint32_t baseAddr, uint32_t crystalVal)
2461 {
2462 #if FSL_FEATURE_MCG_HAS_PLL
2463 uint16_t i;
2464 #endif
2465
2466 /* Check MCG is in BLPE mode */
2467 if (CLOCK_HAL_GetMcgMode(baseAddr) != kMcgModeBLPE)
2468 {
2469 return kMcgErrNotInBlpeMode; /* return error code */
2470 }
2471
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);
2476 #endif
2477 CLOCK_HAL_SetLowPowerMode(baseAddr, kMcgLowPowerSelNormal);
2478
2479 #if FSL_FEATURE_MCG_HAS_PLL
2480 /* wait for PLLST status bit to set */
2481 for (i = 0 ; i < kMcgConstant2000 ; i++)
2482 {
2483 if (CLOCK_HAL_GetPllStatMode(baseAddr) == kMcgPllStatFll)
2484 {
2485 /* jump out early if PLLST clears before loop finishes */
2486 break;
2487 }
2488 }
2489
2490 /* check bit is really clear */
2491 if (CLOCK_HAL_GetPllStatMode(baseAddr) != kMcgPllStatFll)
2492 {
2493 /* return with error if not clear */
2494 return kMcgErrPllstClearTimeout;
2495 }
2496 #endif
2497 /* now in FBE mode */
2498
2499 /* MCGOUT frequency equals external clock frequency */
2500 return crystalVal;
2501 } /* CLOCK_HAL_SetBlpeToFbeMode */
Imprint / Impressum