1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2020, NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_clock.h"
10 #include "fsl_common.h"
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.clock"
17 #endif
18 
19 #define OTP_INIT_API      ((void (*)(uint32_t src_clk_freq))FSL_ROM_OTP_INIT_ADDR)
20 #define OTP_DEINIT_API    ((void (*)(void))FSL_ROM_OTP_DEINIT_ADDR)
21 #define OTP_FUSE_READ_API ((void (*)(uint32_t addr, uint32_t * data)) FSL_ROM_OTP_FUSE_READ_ADDR)
22 /* OTP fuse index. */
23 #define FFRO_STABLE_TIME       12
24 #define SFRO_STABLE_TIME       13
25 #define FIRC_48MHZ_TRIM_TEMPCO 48
26 #define FIRC_48MHZ_TRIM_COARSE 49
27 #define FIRC_48MHZ_TRIM_FINE   50
28 #define FIRC_60MHZ_TRIM_TEMPCO 51
29 #define FIRC_60MHZ_TRIM_COARSE 52
30 #define FIRC_60MHZ_TRIM_FINE   53
31 /*******************************************************************************
32  * Variables
33  ******************************************************************************/
34 
35 /* External XTAL (OSC) clock frequency. */
36 volatile uint32_t g_xtalFreq = 0U;
37 /* External CLK_IN pin clock frequency. */
38 volatile uint32_t g_clkinFreq = 0U;
39 /* External MCLK in (mclk_in) clock frequency. If not used,
40    set this to 0. Otherwise, set it to the exact rate in Hz this pin is
41    being driven at.*/
42 volatile uint32_t g_mclkFreq = 0U;
43 
44 /*******************************************************************************
45  * Code
46  ******************************************************************************/
47 /* Clock Selection for IP */
48 /**
49  * brief   Configure the clock selection muxes.
50  * param   connection  : Clock to be configured.
51  * return  Nothing
52  */
CLOCK_AttachClk(clock_attach_id_t connection)53 void CLOCK_AttachClk(clock_attach_id_t connection)
54 {
55     bool final_descriptor = false;
56     uint32_t i;
57     volatile uint32_t *pClkSel;
58 
59     for (i = 0U; (i < 2U) && (!final_descriptor); i++)
60     {
61         connection =
62             (clock_attach_id_t)(uint32_t)(((uint32_t)connection) >> (i * 16U)); /*!<  pick up next descriptor */
63 
64         if (((((uint32_t)connection) & 0x80000000U) | ((((uint32_t)connection) & 0x8000U))) != 0UL)
65         {
66             pClkSel = CLKCTL_TUPLE_REG(CLKCTL1, connection);
67         }
68         else
69         {
70             pClkSel = CLKCTL_TUPLE_REG(CLKCTL0, connection);
71         }
72 
73         if ((((uint32_t)connection) & 0xfffU) != 0UL)
74         {
75             *pClkSel = CLKCTL_TUPLE_SEL(connection);
76         }
77         else
78         {
79             final_descriptor = true;
80         }
81     }
82 }
83 /* Set IP Clock divider */
84 /**
85  * brief   Setup peripheral clock dividers.
86  * param   div_name    : Clock divider name
87  * param   divider     : Value to be divided. Divided clock frequency = Undivided clock frequency / divider.
88  * return  Nothing
89  */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divider)90 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divider)
91 {
92     volatile uint32_t *pClkDiv;
93 
94     if ((((uint32_t)div_name) & 0x80000000U) != 0UL)
95     {
96         pClkDiv = CLKCTL_TUPLE_REG(CLKCTL1, div_name);
97     }
98     else
99     {
100         pClkDiv = CLKCTL_TUPLE_REG(CLKCTL0, div_name);
101     }
102     /* Reset the divider counter */
103     *pClkDiv |= 1UL << 29U;
104 
105     if (divider == 0U) /*!<  halt */
106     {
107         *pClkDiv |= 1UL << 30U;
108     }
109     else
110     {
111         *pClkDiv = divider - 1U;
112 
113         while (((*pClkDiv) & 0x80000000U) != 0UL)
114         {
115         }
116     }
117 }
118 /*! @brief  Return Frequency of High-Freq output of FRO
119  *  @return Frequency of High-Freq output of FRO
120  */
CLOCK_GetFFroFreq(void)121 uint32_t CLOCK_GetFFroFreq(void)
122 {
123     uint32_t freq = 0U;
124     /* FFROCTL0 should not be touched by application */
125     switch ((CLKCTL0->FFROCTL0) & CLKCTL0_FFROCTL0_TRIM_RANGE_MASK)
126     {
127         case CLKCTL0_FFROCTL0_TRIM_RANGE(0):
128             freq = CLK_FRO_48MHZ;
129             break;
130         case CLKCTL0_FFROCTL0_TRIM_RANGE(3):
131             freq = CLK_FRO_60MHZ;
132             break;
133         default:
134             freq = 0U;
135             break;
136     }
137     return freq;
138 }
139 /* Get SYSTEM PLL Clk */
140 /*! brief  Return Frequency of SYSPLL
141  *  return Frequency of SYSPLL
142  */
CLOCK_GetSysPllFreq(void)143 uint32_t CLOCK_GetSysPllFreq(void)
144 {
145     uint32_t freq = 0U;
146     uint64_t freqTmp;
147 
148     switch ((CLKCTL0->SYSPLL0CLKSEL) & CLKCTL0_SYSPLL0CLKSEL_SEL_MASK)
149     {
150         case CLKCTL0_SYSPLL0CLKSEL_SEL(0):
151             freq = CLOCK_GetSFroFreq();
152             break;
153         case CLKCTL0_SYSPLL0CLKSEL_SEL(1):
154             freq = CLOCK_GetXtalInClkFreq();
155             break;
156         case CLKCTL0_SYSPLL0CLKSEL_SEL(2):
157             freq = CLOCK_GetFFroFreq() / 2U;
158             break;
159         default:
160             /* Added comments to prevent the violation of MISRA C-2012 rule. */
161             break;
162     }
163 
164     if (((CLKCTL0->SYSPLL0CTL0) & CLKCTL0_SYSPLL0CTL0_BYPASS_MASK) == 0U)
165     {
166         /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
167         freqTmp = ((uint64_t)freq * ((uint64_t)(CLKCTL0->SYSPLL0NUM))) / ((uint64_t)(CLKCTL0->SYSPLL0DENOM));
168         freq *= ((CLKCTL0->SYSPLL0CTL0) & CLKCTL0_SYSPLL0CTL0_MULT_MASK) >> CLKCTL0_SYSPLL0CTL0_MULT_SHIFT;
169         freq += (uint32_t)freqTmp;
170     }
171     return freq;
172 }
173 /* Get SYSTEM PLL PFDn Clk */
174 /*! brief  Get current output frequency of specific System PLL PFD.
175  *  param   pfd    : pfd name to get frequency.
176  *  return  Frequency of SYSPLL PFD.
177  */
CLOCK_GetSysPfdFreq(clock_pfd_t pfd)178 uint32_t CLOCK_GetSysPfdFreq(clock_pfd_t pfd)
179 {
180     uint32_t freq = CLOCK_GetSysPllFreq();
181 
182     if (((CLKCTL0->SYSPLL0CTL0) & CLKCTL0_SYSPLL0CTL0_BYPASS_MASK) == 0U)
183     {
184         switch (pfd)
185         {
186             case kCLOCK_Pfd0:
187                 freq =
188                     (uint32_t)((uint64_t)freq * 18ULL /
189                                ((CLKCTL0->SYSPLL0PFD & CLKCTL0_SYSPLL0PFD_PFD0_MASK) >> CLKCTL0_SYSPLL0PFD_PFD0_SHIFT));
190                 break;
191 
192             case kCLOCK_Pfd1:
193                 freq =
194                     (uint32_t)((uint64_t)freq * 18ULL /
195                                ((CLKCTL0->SYSPLL0PFD & CLKCTL0_SYSPLL0PFD_PFD1_MASK) >> CLKCTL0_SYSPLL0PFD_PFD1_SHIFT));
196                 break;
197 
198             case kCLOCK_Pfd2:
199                 freq =
200                     (uint32_t)((uint64_t)freq * 18ULL /
201                                ((CLKCTL0->SYSPLL0PFD & CLKCTL0_SYSPLL0PFD_PFD2_MASK) >> CLKCTL0_SYSPLL0PFD_PFD2_SHIFT));
202                 break;
203 
204             case kCLOCK_Pfd3:
205                 freq =
206                     (uint32_t)((uint64_t)freq * 18ULL /
207                                ((CLKCTL0->SYSPLL0PFD & CLKCTL0_SYSPLL0PFD_PFD3_MASK) >> CLKCTL0_SYSPLL0PFD_PFD3_SHIFT));
208                 break;
209 
210             default:
211                 freq = 0U;
212                 break;
213         }
214     }
215 
216     return freq;
217 }
CLOCK_GetMainPllClkFreq(void)218 static uint32_t CLOCK_GetMainPllClkFreq(void)
219 {
220     return CLOCK_GetSysPfdFreq(kCLOCK_Pfd0) / ((CLKCTL0->MAINPLLCLKDIV & CLKCTL0_MAINPLLCLKDIV_DIV_MASK) + 1U);
221 }
CLOCK_GetDspPllClkFreq(void)222 static uint32_t CLOCK_GetDspPllClkFreq(void)
223 {
224     return CLOCK_GetSysPfdFreq(kCLOCK_Pfd1) / ((CLKCTL0->DSPPLLCLKDIV & CLKCTL0_DSPPLLCLKDIV_DIV_MASK) + 1U);
225 }
CLOCK_GetAux0PllClkFreq(void)226 static uint32_t CLOCK_GetAux0PllClkFreq(void)
227 {
228     return CLOCK_GetSysPfdFreq(kCLOCK_Pfd2) / ((CLKCTL0->AUX0PLLCLKDIV & CLKCTL0_AUX0PLLCLKDIV_DIV_MASK) + 1U);
229 }
CLOCK_GetAux1PllClkFreq(void)230 static uint32_t CLOCK_GetAux1PllClkFreq(void)
231 {
232     return CLOCK_GetSysPfdFreq(kCLOCK_Pfd3) / ((CLKCTL0->AUX1PLLCLKDIV & CLKCTL0_AUX1PLLCLKDIV_DIV_MASK) + 1U);
233 }
234 /* Get AUDIO PLL Clk */
235 /*! brief  Return Frequency of AUDIO PLL
236  *  return Frequency of AUDIO PLL
237  */
CLOCK_GetAudioPllFreq(void)238 uint32_t CLOCK_GetAudioPllFreq(void)
239 {
240     uint32_t freq = 0U;
241     uint64_t freqTmp;
242 
243     switch ((CLKCTL1->AUDIOPLL0CLKSEL) & CLKCTL1_AUDIOPLL0CLKSEL_SEL_MASK)
244     {
245         case CLKCTL1_AUDIOPLL0CLKSEL_SEL(0):
246             freq = CLOCK_GetSFroFreq();
247             break;
248         case CLKCTL1_AUDIOPLL0CLKSEL_SEL(1):
249             freq = CLOCK_GetXtalInClkFreq();
250             break;
251         case CLKCTL1_AUDIOPLL0CLKSEL_SEL(2):
252             freq = CLOCK_GetFFroFreq() / 2U;
253             break;
254         default:
255             freq = 0U;
256             break;
257     }
258 
259     if (((CLKCTL1->AUDIOPLL0CTL0) & CLKCTL1_AUDIOPLL0CTL0_BYPASS_MASK) == 0UL)
260     {
261         /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
262         freqTmp = ((uint64_t)freq * ((uint64_t)(CLKCTL1->AUDIOPLL0NUM))) / ((uint64_t)(CLKCTL1->AUDIOPLL0DENOM));
263         freq *= ((CLKCTL1->AUDIOPLL0CTL0) & CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) >> CLKCTL1_AUDIOPLL0CTL0_MULT_SHIFT;
264         freq += (uint32_t)freqTmp;
265     }
266     return freq;
267 }
268 /* Get AUDIO PLL PFDn Clk */
269 /*! brief  Get current output frequency of specific Audio PLL PFD.
270  *  param   pfd    : pfd name to get frequency.
271  *  return  Frequency of AUDIO PLL PFD.
272  */
CLOCK_GetAudioPfdFreq(clock_pfd_t pfd)273 uint32_t CLOCK_GetAudioPfdFreq(clock_pfd_t pfd)
274 {
275     uint32_t freq = CLOCK_GetAudioPllFreq();
276 
277     if (((CLKCTL1->AUDIOPLL0CTL0) & CLKCTL1_AUDIOPLL0CTL0_BYPASS_MASK) == 0UL)
278     {
279         switch (pfd)
280         {
281             case kCLOCK_Pfd0:
282                 freq = (uint32_t)(
283                     (uint64_t)freq * 18ULL /
284                     ((CLKCTL1->AUDIOPLL0PFD & CLKCTL1_AUDIOPLL0PFD_PFD0_MASK) >> CLKCTL1_AUDIOPLL0PFD_PFD0_SHIFT));
285                 break;
286 
287             case kCLOCK_Pfd1:
288                 freq = (uint32_t)(
289                     (uint64_t)freq * 18ULL /
290                     ((CLKCTL1->AUDIOPLL0PFD & CLKCTL1_AUDIOPLL0PFD_PFD1_MASK) >> CLKCTL1_AUDIOPLL0PFD_PFD1_SHIFT));
291                 break;
292 
293             case kCLOCK_Pfd2:
294                 freq = (uint32_t)(
295                     (uint64_t)freq * 18ULL /
296                     ((CLKCTL1->AUDIOPLL0PFD & CLKCTL1_AUDIOPLL0PFD_PFD2_MASK) >> CLKCTL1_AUDIOPLL0PFD_PFD2_SHIFT));
297                 break;
298 
299             case kCLOCK_Pfd3:
300                 freq = (uint32_t)(
301                     (uint64_t)freq * 18ULL /
302                     ((CLKCTL1->AUDIOPLL0PFD & CLKCTL1_AUDIOPLL0PFD_PFD3_MASK) >> CLKCTL1_AUDIOPLL0PFD_PFD3_SHIFT));
303                 break;
304 
305             default:
306                 freq = 0U;
307                 break;
308         }
309     }
310 
311     return freq;
312 }
CLOCK_GetAudioPllClkFreq(void)313 static uint32_t CLOCK_GetAudioPllClkFreq(void)
314 {
315     return CLOCK_GetAudioPfdFreq(kCLOCK_Pfd0) / ((CLKCTL1->AUDIOPLLCLKDIV & CLKCTL1_AUDIOPLLCLKDIV_DIV_MASK) + 1U);
316 }
317 /* Get MAIN Clk */
318 /*! brief  Return Frequency of main clk
319  *  return Frequency of main clk
320  */
CLOCK_GetMainClkFreq(void)321 uint32_t CLOCK_GetMainClkFreq(void)
322 {
323     uint32_t freq = 0U;
324 
325     switch ((CLKCTL0->MAINCLKSELB) & CLKCTL0_MAINCLKSELB_SEL_MASK)
326     {
327         case CLKCTL0_MAINCLKSELB_SEL(0):
328             switch ((CLKCTL0->MAINCLKSELA) & CLKCTL0_MAINCLKSELA_SEL_MASK)
329             {
330                 case CLKCTL0_MAINCLKSELA_SEL(0):
331                     freq = CLOCK_GetFFroFreq() / 4U;
332                     break;
333                 case CLKCTL0_MAINCLKSELA_SEL(1):
334                     freq = CLOCK_GetXtalInClkFreq();
335                     break;
336                 case CLKCTL0_MAINCLKSELA_SEL(2):
337                     freq = CLOCK_GetLpOscFreq();
338                     break;
339                 case CLKCTL0_MAINCLKSELA_SEL(3):
340                     freq = CLOCK_GetFFroFreq();
341                     break;
342                 default:
343                     freq = 0U;
344                     break;
345             }
346             break;
347 
348         case CLKCTL0_MAINCLKSELB_SEL(1):
349             freq = CLOCK_GetSFroFreq();
350             break;
351 
352         case CLKCTL0_MAINCLKSELB_SEL(2):
353             freq = CLOCK_GetMainPllClkFreq();
354             break;
355 
356         case CLKCTL0_MAINCLKSELB_SEL(3):
357             freq = CLOCK_GetOsc32KFreq();
358             break;
359 
360         default:
361             freq = 0U;
362             break;
363     }
364 
365     return freq;
366 }
367 /* Get DSP MAIN Clk */
368 /*! brief  Return Frequency of DSP main clk
369  *  return Frequency of DSP main clk
370  */
CLOCK_GetDspMainClkFreq(void)371 uint32_t CLOCK_GetDspMainClkFreq(void)
372 {
373     uint32_t freq = 0U;
374 
375     switch ((CLKCTL1->DSPCPUCLKSELB) & CLKCTL1_DSPCPUCLKSELB_SEL_MASK)
376     {
377         case CLKCTL1_DSPCPUCLKSELB_SEL(0):
378             switch ((CLKCTL1->DSPCPUCLKSELA) & CLKCTL1_DSPCPUCLKSELA_SEL_MASK)
379             {
380                 case CLKCTL1_DSPCPUCLKSELA_SEL(0):
381                     freq = CLOCK_GetFFroFreq();
382                     break;
383                 case CLKCTL1_DSPCPUCLKSELA_SEL(1):
384                     freq = CLOCK_GetXtalInClkFreq();
385                     break;
386                 case CLKCTL1_DSPCPUCLKSELA_SEL(2):
387                     freq = CLOCK_GetLpOscFreq();
388                     break;
389                 case CLKCTL1_DSPCPUCLKSELA_SEL(3):
390                     freq = CLOCK_GetSFroFreq();
391                     break;
392                 default:
393                     freq = 0U;
394                     break;
395             }
396             break;
397 
398         case CLKCTL1_DSPCPUCLKSELB_SEL(1):
399             freq = CLOCK_GetMainPllClkFreq();
400             break;
401 
402         case CLKCTL1_DSPCPUCLKSELB_SEL(2):
403             freq = CLOCK_GetDspPllClkFreq();
404             break;
405 
406         case CLKCTL1_DSPCPUCLKSELB_SEL(3):
407             freq = CLOCK_GetOsc32KFreq();
408             break;
409 
410         default:
411             freq = 0U;
412             break;
413     }
414 
415     return freq;
416 }
417 /* Get ADC Clk */
418 /*! brief  Return Frequency of Adc Clock
419  *  return Frequency of Adc Clock.
420  */
CLOCK_GetAdcClkFreq(void)421 uint32_t CLOCK_GetAdcClkFreq(void)
422 {
423     uint32_t freq = 0U;
424 
425     switch ((CLKCTL0->ADC0FCLKSEL1) & CLKCTL0_ADC0FCLKSEL1_SEL_MASK)
426     {
427         case CLKCTL0_ADC0FCLKSEL1_SEL(0):
428             switch ((CLKCTL0->ADC0FCLKSEL0) & CLKCTL0_ADC0FCLKSEL0_SEL_MASK)
429             {
430                 case CLKCTL0_ADC0FCLKSEL0_SEL(0):
431                     freq = CLOCK_GetSFroFreq();
432                     break;
433                 case CLKCTL0_ADC0FCLKSEL0_SEL(1):
434                     freq = CLOCK_GetXtalInClkFreq();
435                     break;
436                 case CLKCTL0_ADC0FCLKSEL0_SEL(2):
437                     freq = CLOCK_GetLpOscFreq();
438                     break;
439                 case CLKCTL0_ADC0FCLKSEL0_SEL(3):
440                     freq = CLOCK_GetFFroFreq();
441                     break;
442                 default:
443                     freq = 0U;
444                     break;
445             }
446             break;
447 
448         case CLKCTL0_ADC0FCLKSEL1_SEL(1):
449             freq = CLOCK_GetMainPllClkFreq();
450             break;
451 
452         case CLKCTL0_ADC0FCLKSEL1_SEL(3):
453             freq = CLOCK_GetAux0PllClkFreq();
454             break;
455 
456         case CLKCTL0_ADC0FCLKSEL1_SEL(5):
457             freq = CLOCK_GetAux1PllClkFreq();
458             break;
459 
460         default:
461             freq = 0U;
462             break;
463     }
464 
465     return freq / ((CLKCTL0->ADC0FCLKDIV & CLKCTL0_ADC0FCLKDIV_DIV_MASK) + 1U);
466 }
467 /* Get CLOCK OUT Clk */
468 /*! brief  Return Frequency of ClockOut
469  *  return Frequency of ClockOut
470  */
CLOCK_GetClockOutClkFreq(void)471 uint32_t CLOCK_GetClockOutClkFreq(void)
472 {
473     uint32_t freq = 0U;
474 
475     switch ((CLKCTL1->CLKOUTSEL1) & CLKCTL1_CLKOUTSEL1_SEL_MASK)
476     {
477         case CLKCTL1_CLKOUTSEL1_SEL(0):
478             switch ((CLKCTL1->CLKOUTSEL0) & CLKCTL1_CLKOUTSEL0_SEL_MASK)
479             {
480                 case CLKCTL1_CLKOUTSEL0_SEL(0):
481                     freq = CLOCK_GetSFroFreq();
482                     break;
483                 case CLKCTL1_CLKOUTSEL0_SEL(1):
484                     freq = CLOCK_GetXtalInClkFreq();
485                     break;
486                 case CLKCTL1_CLKOUTSEL0_SEL(2):
487                     freq = CLOCK_GetLpOscFreq();
488                     break;
489                 case CLKCTL1_CLKOUTSEL0_SEL(3):
490                     freq = CLOCK_GetFFroFreq();
491                     break;
492                 case CLKCTL1_CLKOUTSEL0_SEL(4):
493                     freq = CLOCK_GetMainClkFreq();
494                     break;
495                 case CLKCTL1_CLKOUTSEL0_SEL(6):
496                     freq = CLOCK_GetDspMainClkFreq();
497                     break;
498                 default:
499                     freq = 0U;
500                     break;
501             }
502             break;
503 
504         case CLKCTL1_CLKOUTSEL1_SEL(1):
505             freq = CLOCK_GetMainPllClkFreq();
506             break;
507 
508         case CLKCTL1_CLKOUTSEL1_SEL(2):
509             freq = CLOCK_GetAux0PllClkFreq();
510             break;
511 
512         case CLKCTL1_CLKOUTSEL1_SEL(3):
513             freq = CLOCK_GetDspPllClkFreq();
514             break;
515 
516         case CLKCTL1_CLKOUTSEL1_SEL(4):
517             freq = CLOCK_GetAux1PllClkFreq();
518             break;
519 
520         case CLKCTL1_CLKOUTSEL1_SEL(5):
521             freq = CLOCK_GetAudioPllClkFreq();
522             break;
523 
524         case CLKCTL1_CLKOUTSEL1_SEL(6):
525             freq = CLOCK_GetOsc32KFreq();
526             break;
527 
528         default:
529             freq = 0U;
530             break;
531     }
532 
533     return freq / ((CLKCTL1->CLKOUTDIV & CLKCTL1_CLKOUTDIV_DIV_MASK) + 1U);
534 }
535 /* Get FRG Clk */
536 /*! brief  Return Input frequency for the Fractional baud rate generator
537  *  return Input Frequency for FRG
538  */
CLOCK_GetFRGClock(uint32_t id)539 uint32_t CLOCK_GetFRGClock(uint32_t id)
540 {
541     uint32_t freq      = 0U;
542     uint32_t frgPllDiv = 1U;
543     uint32_t clkSel    = 0U;
544     uint32_t frgDiv    = 0U;
545     uint32_t frgMul    = 0U;
546 
547     if (id <= 7UL)
548     {
549         clkSel = CLKCTL1->FLEXCOMM[id].FRGCLKSEL & CLKCTL1_FRGCLKSEL_SEL_MASK;
550         frgMul = ((CLKCTL1->FLEXCOMM[id].FRGCTL) & CLKCTL1_FRGCTL_MULT_MASK) >> CLKCTL1_FRGCTL_MULT_SHIFT;
551         frgDiv = ((CLKCTL1->FLEXCOMM[id].FRGCTL) & CLKCTL1_FRGCTL_DIV_MASK) >> CLKCTL1_FRGCTL_DIV_SHIFT;
552     }
553     else if (id == 14UL)
554     {
555         clkSel = CLKCTL1->FRG14CLKSEL & CLKCTL1_FRG14CLKSEL_SEL_MASK;
556         frgMul = ((CLKCTL1->FRG14CTL) & CLKCTL1_FRGCTL_MULT_MASK) >> CLKCTL1_FRGCTL_MULT_SHIFT;
557         frgDiv = ((CLKCTL1->FRG14CTL) & CLKCTL1_FRGCTL_DIV_MASK) >> CLKCTL1_FRGCTL_DIV_SHIFT;
558     }
559     else if (id == 15UL)
560     {
561         clkSel = CLKCTL1->FRG15CLKSEL & CLKCTL1_FRG14CLKSEL_SEL_MASK;
562         frgMul = ((CLKCTL1->FRG15CTL) & CLKCTL1_FRGCTL_MULT_MASK) >> CLKCTL1_FRGCTL_MULT_SHIFT;
563         frgDiv = ((CLKCTL1->FRG15CTL) & CLKCTL1_FRGCTL_DIV_MASK) >> CLKCTL1_FRGCTL_DIV_SHIFT;
564     }
565     else
566     {
567         assert(false);
568     }
569 
570     switch (clkSel)
571     {
572         case CLKCTL1_FRGCLKSEL_SEL(0):
573             freq = CLOCK_GetMainClkFreq();
574             break;
575 
576         case CLKCTL1_FRGCLKSEL_SEL(1):
577             frgPllDiv = (CLKCTL1->FRGPLLCLKDIV & CLKCTL1_FRGPLLCLKDIV_DIV_MASK) + 1U;
578             freq      = CLOCK_GetMainPllClkFreq() / frgPllDiv;
579             break;
580 
581         case CLKCTL1_FRGCLKSEL_SEL(2):
582             freq = CLOCK_GetSFroFreq();
583             break;
584 
585         case CLKCTL1_FRGCLKSEL_SEL(3):
586             freq = CLOCK_GetFFroFreq();
587             break;
588 
589         default:
590             freq = 0U;
591             break;
592     }
593 
594     return (uint32_t)(((uint64_t)freq * ((uint64_t)frgDiv + 1ULL)) / (frgMul + frgDiv + 1UL));
595 }
596 /* Get FLEXCOMM Clk */
597 /*! brief  Return Frequency of Flexcomm functional Clock
598  *  param   id    : flexcomm index to get frequency.
599  *  return Frequency of Flexcomm functional Clock
600  */
CLOCK_GetFlexCommClkFreq(uint32_t id)601 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
602 {
603     uint32_t freq   = 0U;
604     uint32_t clkSel = 0U;
605 
606     if (id <= 7UL)
607     {
608         clkSel = CLKCTL1->FLEXCOMM[id].FCFCLKSEL;
609     }
610     else if (id == 14UL)
611     {
612         clkSel = CLKCTL1->FC14FCLKSEL;
613     }
614     else if (id == 15UL)
615     {
616         clkSel = CLKCTL1->FC15FCLKSEL;
617     }
618     else
619     {
620         assert(false);
621     }
622 
623     switch (clkSel)
624     {
625         case CLKCTL1_FCFCLKSEL_SEL(0):
626             freq = CLOCK_GetSFroFreq();
627             break;
628 
629         case CLKCTL1_FCFCLKSEL_SEL(1):
630             freq = CLOCK_GetFFroFreq();
631             break;
632 
633         case CLKCTL1_FCFCLKSEL_SEL(2):
634             freq = CLOCK_GetAudioPllClkFreq();
635             break;
636 
637         case CLKCTL1_FCFCLKSEL_SEL(3):
638             freq = CLOCK_GetMclkInClkFreq();
639             break;
640 
641         case CLKCTL1_FCFCLKSEL_SEL(4):
642             freq = CLOCK_GetFRGClock(id);
643             break;
644 
645         default:
646             freq = 0U;
647             break;
648     }
649 
650     return freq;
651 }
652 /* Get CTIMER Clk */
653 /*! brief  Return Frequency of Ctimer Clock
654  *  param   id    : ctimer index to get frequency.
655  *  return Frequency of Ctimer Clock
656  */
CLOCK_GetCTimerClkFreq(uint32_t id)657 uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
658 {
659     uint32_t freq = 0U;
660 
661     switch ((CLKCTL1->CT32BITFCLKSEL[id]) & CLKCTL1_CT32BITFCLKSEL_SEL_MASK)
662     {
663         case CLKCTL1_CT32BITFCLKSEL_SEL(0):
664             freq = CLOCK_GetMainClkFreq();
665             break;
666 
667         case CLKCTL1_CT32BITFCLKSEL_SEL(1):
668             freq = CLOCK_GetSFroFreq();
669             break;
670 
671         case CLKCTL1_CT32BITFCLKSEL_SEL(2):
672             freq = CLOCK_GetFFroFreq();
673             break;
674 
675         case CLKCTL1_CT32BITFCLKSEL_SEL(3):
676             freq = CLOCK_GetAudioPllClkFreq();
677             break;
678 
679         case CLKCTL1_CT32BITFCLKSEL_SEL(4):
680             freq = CLOCK_GetMclkInClkFreq();
681             break;
682 
683         case CLKCTL1_CT32BITFCLKSEL_SEL(5):
684             freq = CLOCK_GetLpOscFreq();
685             break;
686 
687         default:
688             freq = 0U;
689             break;
690     }
691 
692     return freq;
693 }
694 /* Get FLEXSPI Clk */
695 /*! brief  Return Frequency of FLEXSPI Clock
696  *  return Frequency of FLEXSPI.
697  */
CLOCK_GetFlexspiClkFreq(void)698 uint32_t CLOCK_GetFlexspiClkFreq(void)
699 {
700     uint32_t freq = 0U;
701 
702     switch ((CLKCTL0->FLEXSPIFCLKSEL) & CLKCTL0_FLEXSPIFCLKSEL_SEL_MASK)
703     {
704         case CLKCTL0_FLEXSPIFCLKSEL_SEL(0):
705             freq = CLOCK_GetMainClkFreq();
706             break;
707 
708         case CLKCTL0_FLEXSPIFCLKSEL_SEL(1):
709             freq = CLOCK_GetMainPllClkFreq();
710             break;
711 
712         case CLKCTL0_FLEXSPIFCLKSEL_SEL(2):
713             freq = CLOCK_GetAux0PllClkFreq();
714             break;
715 
716         case CLKCTL0_FLEXSPIFCLKSEL_SEL(3):
717             freq = CLOCK_GetFFroFreq();
718             break;
719 
720         case CLKCTL0_FLEXSPIFCLKSEL_SEL(4):
721             freq = CLOCK_GetAux1PllClkFreq();
722             break;
723 
724         default:
725             freq = 0U;
726             break;
727     }
728 
729     return freq / ((CLKCTL0->FLEXSPIFCLKDIV & CLKCTL0_FLEXSPIFCLKDIV_DIV_MASK) + 1U);
730 }
731 
732 /* Get SCT Clk */
733 /*! brief  Return Frequency of sct
734  *  return Frequency of sct clk
735  */
CLOCK_GetSctClkFreq(void)736 uint32_t CLOCK_GetSctClkFreq(void)
737 {
738     uint32_t freq = 0U;
739 
740     switch ((CLKCTL0->SCTFCLKSEL) & CLKCTL0_SCTFCLKSEL_SEL_MASK)
741     {
742         case CLKCTL0_SCTFCLKSEL_SEL(0):
743             freq = CLOCK_GetMainClkFreq();
744             break;
745 
746         case CLKCTL0_SCTFCLKSEL_SEL(1):
747             freq = CLOCK_GetMainPllClkFreq();
748             break;
749 
750         case CLKCTL0_SCTFCLKSEL_SEL(2):
751             freq = CLOCK_GetAux0PllClkFreq();
752             break;
753 
754         case CLKCTL0_SCTFCLKSEL_SEL(3):
755             freq = CLOCK_GetFFroFreq();
756             break;
757 
758         case CLKCTL0_SCTFCLKSEL_SEL(4):
759             freq = CLOCK_GetAux1PllClkFreq();
760             break;
761 
762         case CLKCTL0_SCTFCLKSEL_SEL(5):
763             freq = CLOCK_GetAudioPllClkFreq();
764             break;
765 
766         default:
767             freq = 0U;
768             break;
769     }
770 
771     return freq / ((CLKCTL0->SCTFCLKDIV & CLKCTL0_SCTFCLKDIV_DIV_MASK) + 1U);
772 }
773 
774 /*! brief  Return Frequency of mclk Out
775  *  return Frequency of mclk Out clk
776  */
CLOCK_GetMclkClkFreq(void)777 uint32_t CLOCK_GetMclkClkFreq(void)
778 {
779     uint32_t freq = 0U;
780 
781     if (CLKCTL1->AUDIOMCLKSEL == 0U)
782     {
783         freq = CLOCK_GetFFroFreq();
784     }
785     else if (CLKCTL1->AUDIOMCLKSEL == 1U)
786     {
787         freq = CLOCK_GetAudioPllClkFreq();
788     }
789     else
790     {
791         /* Added comments to prevent the violation of MISRA C-2012 rule 15.7. */
792     }
793 
794     return freq / ((CLKCTL1->AUDIOMCLKDIV & CLKCTL1_AUDIOMCLKDIV_DIV_MASK) + 1U);
795 }
796 
797 /*! @brief  Return Frequency of WDT clk
798  *  @param  id : WDT index to get frequency.
799  *  @return Frequency of WDT clk
800  */
CLOCK_GetWdtClkFreq(uint32_t id)801 uint32_t CLOCK_GetWdtClkFreq(uint32_t id)
802 {
803     uint32_t freq = 0U;
804 
805     assert(id <= 1UL);
806 
807     if (id == 0UL)
808     {
809         if ((CLKCTL0->WDT0FCLKSEL & CLKCTL0_WDT0FCLKSEL_SEL_MASK) == CLKCTL0_WDT0FCLKSEL_SEL(0))
810         {
811             freq = CLOCK_GetLpOscFreq();
812         }
813         else
814         {
815             freq = CLOCK_GetMainClkFreq();
816         }
817     }
818     else
819     {
820         if ((CLKCTL1->WDT1FCLKSEL & CLKCTL1_WDT1FCLKSEL_SEL_MASK) == CLKCTL1_WDT1FCLKSEL_SEL(0))
821         {
822             freq = CLOCK_GetLpOscFreq();
823         }
824         else
825         {
826             freq = CLOCK_GetMainClkFreq();
827         }
828     }
829 
830     return freq;
831 }
832 
833 /*! brief  Return Frequency of systick clk
834  *  return Frequency of systick clk
835  */
CLOCK_GetSystickClkFreq(void)836 uint32_t CLOCK_GetSystickClkFreq(void)
837 {
838     uint32_t freq = 0U;
839 
840     switch (CLKCTL0->SYSTICKFCLKSEL)
841     {
842         case CLKCTL0_SYSTICKFCLKSEL_SEL(0):
843             freq = CLOCK_GetMainClkFreq() / ((CLKCTL0->SYSTICKFCLKDIV & CLKCTL0_SYSTICKFCLKDIV_DIV_MASK) + 1U);
844             break;
845 
846         case CLKCTL0_SYSTICKFCLKSEL_SEL(1):
847             freq = CLOCK_GetLpOscFreq();
848             break;
849 
850         case CLKCTL0_SYSTICKFCLKSEL_SEL(2):
851             freq = CLOCK_GetOsc32KFreq();
852             break;
853 
854         case CLKCTL0_SYSTICKFCLKSEL_SEL(3):
855             freq = CLOCK_GetSFroFreq();
856             break;
857 
858         default:
859             freq = 0U;
860             break;
861     }
862 
863     return freq;
864 }
865 
866 /*! brief  Return Frequency of SDIO clk
867  *  param id : SDIO index to get frequency.
868  *  return Frequency of SDIO clk
869  */
CLOCK_GetSdioClkFreq(uint32_t id)870 uint32_t CLOCK_GetSdioClkFreq(uint32_t id)
871 {
872     uint32_t freq = 0U;
873     volatile uint32_t *pClkSel;
874     volatile uint32_t *pClkDiv;
875 
876     assert(id <= 1U);
877 
878     if (id == 0UL)
879     {
880         pClkSel = &CLKCTL0->SDIO0FCLKSEL;
881         pClkDiv = &CLKCTL0->SDIO0FCLKDIV;
882     }
883     else
884     {
885         pClkSel = &CLKCTL0->SDIO1FCLKSEL;
886         pClkDiv = &CLKCTL0->SDIO1FCLKDIV;
887     }
888 
889     switch ((*pClkSel) & CLKCTL0_SDIO0FCLKSEL_SEL_MASK)
890     {
891         case CLKCTL0_SDIO0FCLKSEL_SEL(0):
892             freq = CLOCK_GetMainClkFreq();
893             break;
894 
895         case CLKCTL0_SDIO0FCLKSEL_SEL(1):
896             freq = CLOCK_GetMainPllClkFreq();
897             break;
898 
899         case CLKCTL0_SDIO0FCLKSEL_SEL(2):
900             freq = CLOCK_GetAux0PllClkFreq();
901             break;
902 
903         case CLKCTL0_SDIO0FCLKSEL_SEL(3):
904             freq = CLOCK_GetFFroFreq();
905             break;
906 
907         case CLKCTL0_SDIO0FCLKSEL_SEL(4):
908             freq = CLOCK_GetAux1PllClkFreq();
909             break;
910 
911         default:
912             freq = 0U;
913             break;
914     }
915 
916     return freq / (((*pClkDiv) & CLKCTL0_SDIO0FCLKDIV_DIV_MASK) + 1U);
917 }
918 
919 /*! @brief  Return Frequency of I3C clk
920  *  @return Frequency of I3C clk
921  */
CLOCK_GetI3cClkFreq(void)922 uint32_t CLOCK_GetI3cClkFreq(void)
923 {
924     uint32_t freq = 0U;
925 
926     switch ((CLKCTL1->I3C0FCLKSEL) & CLKCTL1_I3C0FCLKSEL_SEL_MASK)
927     {
928         case CLKCTL1_I3C0FCLKSEL_SEL(0):
929             freq = CLOCK_GetMainClkFreq();
930             break;
931 
932         case CLKCTL1_I3C0FCLKSEL_SEL(1):
933             freq = CLOCK_GetFFroFreq();
934             break;
935 
936         default:
937             freq = 0U;
938             break;
939     }
940 
941     return freq / ((CLKCTL1->I3C0FCLKDIV & CLKCTL1_I3C0FCLKDIV_DIV_MASK) + 1U);
942 }
943 
944 /*! brief  Return Frequency of USB clk
945  *  return Frequency of USB clk
946  */
CLOCK_GetUsbClkFreq(void)947 uint32_t CLOCK_GetUsbClkFreq(void)
948 {
949     uint32_t freq = 0U;
950 
951     if (CLKCTL0->USBHSFCLKSEL == 0U)
952     {
953         freq = CLOCK_GetXtalInClkFreq();
954     }
955     else if (CLKCTL0->USBHSFCLKSEL == 1U)
956     {
957         freq = CLOCK_GetMainClkFreq();
958     }
959     else
960     {
961         /* Add comments to prevent the violation of MISRA C-2012 rule 15.7 */
962     }
963 
964     return freq / ((CLKCTL0->USBHSFCLKDIV & 0xffU) + 1U);
965 }
966 
967 /*! brief  Return Frequency of DMIC clk
968  *  return Frequency of DMIC clk
969  */
CLOCK_GetDmicClkFreq(void)970 uint32_t CLOCK_GetDmicClkFreq(void)
971 {
972     uint32_t freq = 0U;
973 
974     switch ((CLKCTL1->DMIC0FCLKSEL) & CLKCTL1_DMIC0FCLKSEL_SEL_MASK)
975     {
976         case CLKCTL1_DMIC0FCLKSEL_SEL(0):
977             freq = CLOCK_GetSFroFreq();
978             break;
979 
980         case CLKCTL1_DMIC0FCLKSEL_SEL(1):
981             freq = CLOCK_GetFFroFreq();
982             break;
983 
984         case CLKCTL1_DMIC0FCLKSEL_SEL(2):
985             freq = CLOCK_GetAudioPllClkFreq();
986             break;
987 
988         case CLKCTL1_DMIC0FCLKSEL_SEL(3):
989             freq = CLOCK_GetMclkInClkFreq();
990             break;
991 
992         case CLKCTL1_DMIC0FCLKSEL_SEL(4):
993             freq = CLOCK_GetLpOscFreq();
994             break;
995 
996         case CLKCTL1_DMIC0FCLKSEL_SEL(5):
997             freq = CLOCK_GetWakeClk32KFreq();
998             break;
999 
1000         default:
1001             freq = 0U;
1002             break;
1003     }
1004 
1005     return freq / ((CLKCTL1->DMIC0FCLKDIV & 0xffU) + 1U);
1006 }
1007 
1008 /*! brief  Return Frequency of ACMP clk
1009  *  return Frequency of ACMP clk
1010  */
CLOCK_GetAcmpClkFreq(void)1011 uint32_t CLOCK_GetAcmpClkFreq(void)
1012 {
1013     uint32_t freq = 0U;
1014 
1015     switch ((CLKCTL1->ACMP0FCLKSEL) & CLKCTL1_ACMP0FCLKSEL_SEL_MASK)
1016     {
1017         case CLKCTL1_ACMP0FCLKSEL_SEL(0):
1018             freq = CLOCK_GetMainClkFreq();
1019             break;
1020 
1021         case CLKCTL1_ACMP0FCLKSEL_SEL(1):
1022             freq = CLOCK_GetSFroFreq();
1023             break;
1024 
1025         case CLKCTL1_ACMP0FCLKSEL_SEL(2):
1026             freq = CLOCK_GetFFroFreq();
1027             break;
1028 
1029         case CLKCTL1_ACMP0FCLKSEL_SEL(3):
1030             freq = CLOCK_GetAux0PllClkFreq();
1031             break;
1032 
1033         case CLKCTL1_ACMP0FCLKSEL_SEL(4):
1034             freq = CLOCK_GetAux1PllClkFreq();
1035             break;
1036 
1037         default:
1038             freq = 0U;
1039             break;
1040     }
1041 
1042     return freq / ((CLKCTL1->ACMP0FCLKDIV & CLKCTL1_ACMP0FCLKDIV_DIV_MASK) + 1U);
1043 }
1044 
1045 /* Get IP Clk */
1046 /*! brief  Return Frequency of selected clock
1047  *  return Frequency of selected clock
1048  */
CLOCK_GetFreq(clock_name_t clockName)1049 uint32_t CLOCK_GetFreq(clock_name_t clockName)
1050 {
1051     uint32_t freq = 0U;
1052 
1053     switch (clockName)
1054     {
1055         case kCLOCK_CoreSysClk:
1056         case kCLOCK_BusClk:
1057             freq = CLOCK_GetMainClkFreq() / ((CLKCTL0->SYSCPUAHBCLKDIV & CLKCTL0_SYSCPUAHBCLKDIV_DIV_MASK) + 1U);
1058             break;
1059         case kCLOCK_MclkClk:
1060             freq = CLOCK_GetMclkClkFreq();
1061             break;
1062         case kCLOCK_ClockOutClk:
1063             freq = CLOCK_GetClockOutClkFreq();
1064             break;
1065         case kCLOCK_AdcClk:
1066             freq = CLOCK_GetAdcClkFreq();
1067             break;
1068         case kCLOCK_FlexspiClk:
1069             freq = CLOCK_GetFlexspiClkFreq();
1070             break;
1071         case kCLOCK_SctClk:
1072             freq = CLOCK_GetSctClkFreq();
1073             break;
1074         case kCLOCK_Wdt0Clk:
1075             freq = CLOCK_GetWdtClkFreq(0U);
1076             break;
1077         case kCLOCK_Wdt1Clk:
1078             freq = CLOCK_GetWdtClkFreq(1U);
1079             break;
1080         case kCLOCK_SystickClk:
1081             freq = CLOCK_GetSystickClkFreq();
1082             break;
1083         case kCLOCK_Sdio0Clk:
1084             freq = CLOCK_GetSdioClkFreq(0U);
1085             break;
1086         case kCLOCK_Sdio1Clk:
1087             freq = CLOCK_GetSdioClkFreq(1U);
1088             break;
1089         case kCLOCK_I3cClk:
1090             freq = CLOCK_GetI3cClkFreq();
1091             break;
1092         case kCLOCK_UsbClk:
1093             freq = CLOCK_GetUsbClkFreq();
1094             break;
1095         case kCLOCK_DmicClk:
1096             freq = CLOCK_GetDmicClkFreq();
1097             break;
1098         case kCLOCK_DspCpuClk:
1099             freq = CLOCK_GetDspMainClkFreq() / ((CLKCTL1->DSPCPUCLKDIV & CLKCTL1_DSPCPUCLKDIV_DIV_MASK) + 1U);
1100             break;
1101         case kCLOCK_AcmpClk:
1102             freq = CLOCK_GetAcmpClkFreq();
1103             break;
1104         case kCLOCK_Flexcomm0Clk:
1105             freq = CLOCK_GetFlexCommClkFreq(0U);
1106             break;
1107         case kCLOCK_Flexcomm1Clk:
1108             freq = CLOCK_GetFlexCommClkFreq(1U);
1109             break;
1110         case kCLOCK_Flexcomm2Clk:
1111             freq = CLOCK_GetFlexCommClkFreq(2U);
1112             break;
1113         case kCLOCK_Flexcomm3Clk:
1114             freq = CLOCK_GetFlexCommClkFreq(3U);
1115             break;
1116         case kCLOCK_Flexcomm4Clk:
1117             freq = CLOCK_GetFlexCommClkFreq(4U);
1118             break;
1119         case kCLOCK_Flexcomm5Clk:
1120             freq = CLOCK_GetFlexCommClkFreq(5U);
1121             break;
1122         case kCLOCK_Flexcomm6Clk:
1123             freq = CLOCK_GetFlexCommClkFreq(6U);
1124             break;
1125         case kCLOCK_Flexcomm7Clk:
1126             freq = CLOCK_GetFlexCommClkFreq(7U);
1127             break;
1128         case kCLOCK_Flexcomm14Clk:
1129             freq = CLOCK_GetFlexCommClkFreq(14U);
1130             break;
1131         case kCLOCK_Flexcomm15Clk:
1132             freq = CLOCK_GetFlexCommClkFreq(15U);
1133             break;
1134         default:
1135             freq = 0U;
1136             break;
1137     }
1138 
1139     return freq;
1140 }
1141 
1142 /* Set FRG Clk */
1143 /*! brief  Set output of the Fractional baud rate generator
1144  * param   config    : Configuration to set to FRGn clock.
1145  */
CLOCK_SetFRGClock(const clock_frg_clk_config_t * config)1146 void CLOCK_SetFRGClock(const clock_frg_clk_config_t *config)
1147 {
1148     uint32_t i = config->num;
1149 
1150     assert(i <= 15U);
1151     assert(config->divider == 255U); /* Always set to 0xFF to use with the fractional baudrate generator.*/
1152 
1153     if (i <= 7UL)
1154     {
1155         CLKCTL1->FLEXCOMM[i].FRGCLKSEL = (uint32_t)config->sfg_clock_src;
1156         CLKCTL1->FLEXCOMM[i].FRGCTL    = (CLKCTL1_FRGCTL_MULT(config->mult) | CLKCTL1_FRGCTL_DIV(config->divider));
1157     }
1158     else if (i == 14UL)
1159     {
1160         CLKCTL1->FRG14CLKSEL = (uint32_t)config->sfg_clock_src;
1161         CLKCTL1->FRG14CTL    = (CLKCTL1_FRGCTL_MULT(config->mult) | CLKCTL1_FRGCTL_DIV(config->divider));
1162     }
1163     else if (i == 15UL)
1164     {
1165         CLKCTL1->FRG15CLKSEL = (uint32_t)config->sfg_clock_src;
1166         CLKCTL1->FRG15CTL    = (CLKCTL1_FRGCTL_MULT(config->mult) | CLKCTL1_FRGCTL_DIV(config->divider));
1167     }
1168     else
1169     {
1170         assert(false);
1171     }
1172 }
1173 
1174 #ifndef __XCC__
1175 /**
1176  * brief  Enable FFRO 48M/60M clock.
1177  * Note   Need to make sure FFRO and ROM has power(PDRUNCFG0[16] and PDRUNCFG1[28] = 0U) before calling this API
1178  *
1179  * param  ffroFreq : target fro frequency.
1180  * return Nothing
1181  */
CLOCK_EnableFfroClk(clock_ffro_freq_t ffroFreq)1182 void CLOCK_EnableFfroClk(clock_ffro_freq_t ffroFreq)
1183 {
1184     uint32_t tempco     = 0U;
1185     uint32_t coarse     = 0U;
1186     uint32_t fine       = 0U;
1187     uint32_t ffro_delay = 0U;
1188 
1189     assert(((SYSCTL0->PDRUNCFG0 & SYSCTL0_PDRUNCFG0_FFRO_PD_MASK) == 0UL) &&
1190            ((SYSCTL0->PDRUNCFG1 & SYSCTL0_PDRUNCFG1_ROM_PD_MASK) == 0UL));
1191 
1192     /* FFROCTL0, FFROCTL1 and the otp trim value should not be touched by application */
1193     CLKCTL0->FFROCTL1 |= CLKCTL0_FFROCTL1_UPDATE_MASK;
1194     OTP_INIT_API(CLOCK_GetMainClkFreq() / ((CLKCTL0->SYSCPUAHBCLKDIV & CLKCTL0_SYSCPUAHBCLKDIV_DIV_MASK) + 1U));
1195     if (ffroFreq == kCLOCK_Ffro48M)
1196     {
1197         /* Read 48M FFRO clock Trim settings from fuse. */
1198         OTP_FUSE_READ_API(FIRC_48MHZ_TRIM_TEMPCO, &tempco);
1199         OTP_FUSE_READ_API(FIRC_48MHZ_TRIM_COARSE, &coarse);
1200         OTP_FUSE_READ_API(FIRC_48MHZ_TRIM_FINE, &fine);
1201     }
1202     else
1203     {
1204         /* Read 60M FFRO clock Trim settings from fuse. */
1205         OTP_FUSE_READ_API(FIRC_60MHZ_TRIM_TEMPCO, &tempco);
1206         OTP_FUSE_READ_API(FIRC_60MHZ_TRIM_COARSE, &coarse);
1207         OTP_FUSE_READ_API(FIRC_60MHZ_TRIM_FINE, &fine);
1208     }
1209     /* Read FFRO stable time from fuse. */
1210     OTP_FUSE_READ_API(FFRO_STABLE_TIME, &ffro_delay);
1211     OTP_DEINIT_API();
1212     CLKCTL0->FFROCTL0 = CLKCTL0_FFROCTL0_TRIM_TEMPCO(tempco) | CLKCTL0_FFROCTL0_TRIM_COARSE(coarse) |
1213                         CLKCTL0_FFROCTL0_TRIM_FINE(fine) |
1214                         CLKCTL0_FFROCTL0_TRIM_RANGE((ffroFreq == kCLOCK_Ffro48M) ? 0 : 3);
1215     CLKCTL0->FFROCTL1 &= ~CLKCTL0_FFROCTL1_UPDATE_MASK;
1216     /* No FFRO enable/disable control in CLKCTL. Just wait FFRO stable in case FFRO just get powered on. */
1217     SDK_DelayAtLeastUs(ffro_delay, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1218 }
1219 /**
1220  * brief   Enable SFRO clock.
1221  * Note    Need to make sure SFRO and ROM has power(PDRUNCFG0[15] and PDRUNCFG1[28] = 0U) before calling this API
1222  *
1223  * param   Nothing
1224  * return  Nothing
1225  */
1226 
CLOCK_EnableSfroClk(void)1227 void CLOCK_EnableSfroClk(void)
1228 {
1229     uint32_t sfro_delay = 0U;
1230 
1231     assert(((SYSCTL0->PDRUNCFG0 & SYSCTL0_PDRUNCFG0_SFRO_PD_MASK) == 0UL) &&
1232            ((SYSCTL0->PDRUNCFG1 & SYSCTL0_PDRUNCFG1_ROM_PD_MASK) == 0UL));
1233     /* The otp trim value should not be touched by application */
1234     OTP_INIT_API(CLOCK_GetMainClkFreq() / ((CLKCTL0->SYSCPUAHBCLKDIV & CLKCTL0_SYSCPUAHBCLKDIV_DIV_MASK) + 1U));
1235     /* Read SFRO stable time from fuse. */
1236     OTP_FUSE_READ_API(SFRO_STABLE_TIME, &sfro_delay);
1237     OTP_DEINIT_API();
1238     /* No SFRO enable/disable control in CLKCTL. Just wait SFRO stable in case SFRO just get powered on. */
1239     SDK_DelayAtLeastUs(sfro_delay, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1240 }
1241 #endif /* __XCC__ */
1242 
1243 /* Initialize the SYSTEM PLL Clk */
1244 /*! brief  Initialize the System PLL.
1245  *  param  config    : Configuration to set to PLL.
1246  */
CLOCK_InitSysPll(const clock_sys_pll_config_t * config)1247 void CLOCK_InitSysPll(const clock_sys_pll_config_t *config)
1248 {
1249     /* Power down SYSPLL before change fractional settings */
1250     SYSCTL0->PDRUNCFG0_SET = SYSCTL0_PDRUNCFG0_SYSPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_SYSPLLANA_PD_MASK;
1251 
1252     CLKCTL0->SYSPLL0CLKSEL = (uint32_t)config->sys_pll_src;
1253     CLKCTL0->SYSPLL0NUM    = config->numerator;
1254     CLKCTL0->SYSPLL0DENOM  = config->denominator;
1255     switch (config->sys_pll_mult)
1256     {
1257         case kCLOCK_SysPllMult16:
1258             CLKCTL0->SYSPLL0CTL0 =
1259                 (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(16);
1260             break;
1261         case kCLOCK_SysPllMult17:
1262             CLKCTL0->SYSPLL0CTL0 =
1263                 (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(17);
1264             break;
1265         case kCLOCK_SysPllMult18:
1266             CLKCTL0->SYSPLL0CTL0 =
1267                 (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(18);
1268             break;
1269         case kCLOCK_SysPllMult19:
1270             CLKCTL0->SYSPLL0CTL0 =
1271                 (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(19);
1272             break;
1273         case kCLOCK_SysPllMult20:
1274             CLKCTL0->SYSPLL0CTL0 =
1275                 (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(20);
1276             break;
1277         case kCLOCK_SysPllMult21:
1278             CLKCTL0->SYSPLL0CTL0 =
1279                 (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(21);
1280             break;
1281         case kCLOCK_SysPllMult22:
1282             CLKCTL0->SYSPLL0CTL0 =
1283                 (CLKCTL0->SYSPLL0CTL0 & ~CLKCTL0_SYSPLL0CTL0_MULT_MASK) | CLKCTL0_SYSPLL0CTL0_MULT(22);
1284             break;
1285         default:
1286             /* Added comments to prevent the violation of MISRA rule. */
1287             break;
1288     }
1289     /* Clear System PLL reset*/
1290     CLKCTL0->SYSPLL0CTL0 &= ~CLKCTL0_SYSPLL0CTL0_RESET_MASK;
1291     /* Power up SYSPLL*/
1292     SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_SYSPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_SYSPLLANA_PD_MASK;
1293     SDK_DelayAtLeastUs((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 2UL,
1294                        SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1295     /* Set System PLL HOLDRINGOFF_ENA */
1296     CLKCTL0->SYSPLL0CTL0 |= CLKCTL0_SYSPLL0CTL0_HOLDRINGOFF_ENA_MASK;
1297     SDK_DelayAtLeastUs((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 6UL,
1298                        SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1299     /* Clear System PLL HOLDRINGOFF_ENA*/
1300     CLKCTL0->SYSPLL0CTL0 &= ~CLKCTL0_SYSPLL0CTL0_HOLDRINGOFF_ENA_MASK;
1301     SDK_DelayAtLeastUs((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 3UL,
1302                        SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1303 }
1304 /* Initialize the System PLL PFD */
1305 /*! brief Initialize the System PLL PFD.
1306  *  param pfd    : Which PFD clock to enable.
1307  *  param divider    : The PFD divider value.
1308  *  note It is recommended that PFD settings are kept between 12-35.
1309  */
CLOCK_InitSysPfd(clock_pfd_t pfd,uint8_t divider)1310 void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t divider)
1311 {
1312     uint32_t pfdIndex = (uint32_t)pfd;
1313     uint32_t syspfd;
1314 
1315     syspfd = CLKCTL0->SYSPLL0PFD &
1316              ~(((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_CLKGATE_MASK | (uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_MASK)
1317                << (8UL * pfdIndex));
1318 
1319     /* Disable the clock output first. */
1320     CLKCTL0->SYSPLL0PFD = syspfd | ((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_CLKGATE_MASK << (8UL * pfdIndex));
1321 
1322     /* Set the new value and enable output. */
1323     CLKCTL0->SYSPLL0PFD = syspfd | (CLKCTL0_SYSPLL0PFD_PFD0(divider) << (8UL * pfdIndex));
1324     /* Wait for output becomes stable. */
1325     while ((CLKCTL0->SYSPLL0PFD & ((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_CLKRDY_MASK << (8UL * pfdIndex))) == 0UL)
1326     {
1327     }
1328     /* Clear ready status flag. */
1329     CLKCTL0->SYSPLL0PFD |= ((uint32_t)CLKCTL0_SYSPLL0PFD_PFD0_CLKRDY_MASK << (8UL * pfdIndex));
1330 }
1331 /* Initialize the Audio PLL Clk */
1332 /*! brief  Initialize the audio PLL.
1333  *  param  config    : Configuration to set to PLL.
1334  */
CLOCK_InitAudioPll(const clock_audio_pll_config_t * config)1335 void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config)
1336 {
1337     /* Power down Audio PLL before change fractional settings */
1338     SYSCTL0->PDRUNCFG0_SET = SYSCTL0_PDRUNCFG0_AUDPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_AUDPLLANA_PD_MASK;
1339 
1340     CLKCTL1->AUDIOPLL0CLKSEL = (uint32_t)(config->audio_pll_src);
1341     CLKCTL1->AUDIOPLL0NUM    = config->numerator;
1342     CLKCTL1->AUDIOPLL0DENOM  = config->denominator;
1343     switch (config->audio_pll_mult)
1344     {
1345         case kCLOCK_AudioPllMult16:
1346             CLKCTL1->AUDIOPLL0CTL0 =
1347                 (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(16);
1348             break;
1349         case kCLOCK_AudioPllMult17:
1350             CLKCTL1->AUDIOPLL0CTL0 =
1351                 (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(17);
1352             break;
1353         case kCLOCK_AudioPllMult18:
1354             CLKCTL1->AUDIOPLL0CTL0 =
1355                 (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(18);
1356             break;
1357         case kCLOCK_AudioPllMult19:
1358             CLKCTL1->AUDIOPLL0CTL0 =
1359                 (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(19);
1360             break;
1361         case kCLOCK_AudioPllMult20:
1362             CLKCTL1->AUDIOPLL0CTL0 =
1363                 (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(20);
1364             break;
1365         case kCLOCK_AudioPllMult21:
1366             CLKCTL1->AUDIOPLL0CTL0 =
1367                 (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(21);
1368             break;
1369         case kCLOCK_AudioPllMult22:
1370             CLKCTL1->AUDIOPLL0CTL0 =
1371                 (CLKCTL1->AUDIOPLL0CTL0 & ~CLKCTL1_AUDIOPLL0CTL0_MULT_MASK) | CLKCTL1_AUDIOPLL0CTL0_MULT(22);
1372             break;
1373         default:
1374             /* Added comments to prevent the violation of MISRA C-2012 rule */
1375             break;
1376     }
1377 
1378     /* Clear Audio PLL reset*/
1379     CLKCTL1->AUDIOPLL0CTL0 &= ~CLKCTL1_AUDIOPLL0CTL0_RESET_MASK;
1380     /* Power up Audio PLL*/
1381     SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_AUDPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_AUDPLLANA_PD_MASK;
1382     SDK_DelayAtLeastUs((CLKCTL1->AUDIOPLL0LOCKTIMEDIV2 & CLKCTL1_AUDIOPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 2UL,
1383                        SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1384     /* Set Audio PLL HOLDRINGOFF_ENA */
1385     CLKCTL1->AUDIOPLL0CTL0 |= CLKCTL1_AUDIOPLL0CTL0_HOLDRINGOFF_ENA_MASK;
1386     SDK_DelayAtLeastUs((CLKCTL1->AUDIOPLL0LOCKTIMEDIV2 & CLKCTL1_AUDIOPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 6UL,
1387                        SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1388     /* Clear Audio PLL HOLDRINGOFF_ENA*/
1389     CLKCTL1->AUDIOPLL0CTL0 &= ~CLKCTL1_AUDIOPLL0CTL0_HOLDRINGOFF_ENA_MASK;
1390     SDK_DelayAtLeastUs((CLKCTL1->AUDIOPLL0LOCKTIMEDIV2 & CLKCTL1_AUDIOPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 3UL,
1391                        SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1392 }
1393 /* Initialize the Audio PLL PFD */
1394 /*! brief Initialize the audio PLL PFD.
1395  *  param pfd    : Which PFD clock to enable.
1396  *  param divider    : The PFD divider value.
1397  *  note It is recommended that PFD settings are kept between 12-35.
1398  */
CLOCK_InitAudioPfd(clock_pfd_t pfd,uint8_t divider)1399 void CLOCK_InitAudioPfd(clock_pfd_t pfd, uint8_t divider)
1400 {
1401     uint32_t pfdIndex = (uint32_t)pfd;
1402     uint32_t syspfd;
1403 
1404     syspfd = CLKCTL1->AUDIOPLL0PFD &
1405              ~(((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_CLKGATE_MASK | (uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_MASK)
1406                << (8UL * pfdIndex));
1407 
1408     /* Disable the clock output first. */
1409     CLKCTL1->AUDIOPLL0PFD = syspfd | ((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_CLKGATE_MASK << (8UL * pfdIndex));
1410 
1411     /* Set the new value and enable output. */
1412     CLKCTL1->AUDIOPLL0PFD = syspfd | (CLKCTL1_AUDIOPLL0PFD_PFD0(divider) << (8UL * pfdIndex));
1413     /* Wait for output becomes stable. */
1414     while ((CLKCTL1->AUDIOPLL0PFD & ((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_CLKRDY_MASK << (8UL * pfdIndex))) == 0UL)
1415     {
1416     }
1417     /* Clear ready status flag. */
1418     CLKCTL1->AUDIOPLL0PFD |= ((uint32_t)CLKCTL1_AUDIOPLL0PFD_PFD0_CLKRDY_MASK << (8UL * pfdIndex));
1419 }
1420 /*! @brief  Enable/Disable sys osc clock from external crystal clock.
1421  *  @param  enable : true to enable system osc clock, false to bypass system osc.
1422  *  @param  enableLowPower : true to enable low power mode, false to enable high gain mode.
1423  *  @param  delay_us : Delay time after OSC power up.
1424  */
CLOCK_EnableSysOscClk(bool enable,bool enableLowPower,uint32_t delay_us)1425 void CLOCK_EnableSysOscClk(bool enable, bool enableLowPower, uint32_t delay_us)
1426 {
1427     uint32_t ctrl = enableLowPower ? CLKCTL0_SYSOSCCTL0_LP_ENABLE_MASK : 0U;
1428 
1429     if (enable)
1430     {
1431         CLKCTL0->SYSOSCCTL0   = ctrl;
1432         CLKCTL0->SYSOSCBYPASS = 0;
1433         SDK_DelayAtLeastUs(delay_us, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1434     }
1435     else
1436     {
1437         CLKCTL0->SYSOSCCTL0 = ctrl | CLKCTL0_SYSOSCCTL0_BYPASS_ENABLE_MASK;
1438     }
1439 }
1440 /*! @brief Enable USB HS device clock.
1441  *
1442  * This function enables USB HS device clock.
1443  */
CLOCK_EnableUsbhsDeviceClock(void)1444 void CLOCK_EnableUsbhsDeviceClock(void)
1445 {
1446     CLOCK_EnableClock(kCLOCK_UsbhsPhy);
1447     /* Enable usbhs device and ram clock */
1448     CLOCK_EnableClock(kCLOCK_UsbhsDevice);
1449     CLOCK_EnableClock(kCLOCK_UsbhsSram);
1450 }
1451 
1452 /*! @brief Enable USB HS host clock.
1453  *
1454  * This function enables USB HS host clock.
1455  */
CLOCK_EnableUsbhsHostClock(void)1456 void CLOCK_EnableUsbhsHostClock(void)
1457 {
1458     CLOCK_EnableClock(kCLOCK_UsbhsPhy);
1459     /* Enable usbhs host and ram clock */
1460     CLOCK_EnableClock(kCLOCK_UsbhsHost);
1461     CLOCK_EnableClock(kCLOCK_UsbhsSram);
1462 }
1463 
1464 /*! brief Enable USB hs0PhyPll clock.
1465  *
1466  * param src  USB HS clock source.
1467  * param freq The frequency specified by src.
1468  * retval true The clock is set successfully.
1469  * retval false The clock source is invalid to get proper USB HS clock.
1470  */
CLOCK_EnableUsbHs0PhyPllClock(clock_attach_id_t src,uint32_t freq)1471 bool CLOCK_EnableUsbHs0PhyPllClock(clock_attach_id_t src, uint32_t freq)
1472 {
1473     uint32_t phyPllDiv  = 0U;
1474     uint32_t multiplier = 0U;
1475     bool retVal         = true;
1476 
1477     USBPHY->CTRL_CLR = USBPHY_CTRL_SFTRST_MASK;
1478 
1479     uint32_t delay = 100000;
1480     while ((delay--) != 0UL)
1481     {
1482         __NOP();
1483     }
1484 
1485     multiplier = 480000000UL / freq;
1486 
1487     switch (multiplier)
1488     {
1489         case 13:
1490         {
1491             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
1492             break;
1493         }
1494         case 15:
1495         {
1496             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
1497             break;
1498         }
1499         case 16:
1500         {
1501             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
1502             break;
1503         }
1504         case 20:
1505         {
1506             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(3U);
1507             break;
1508         }
1509         case 22:
1510         {
1511             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U);
1512             break;
1513         }
1514         case 25:
1515         {
1516             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U);
1517             break;
1518         }
1519         case 30:
1520         {
1521             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U);
1522             break;
1523         }
1524         case 240:
1525         {
1526             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(7U);
1527             break;
1528         }
1529         default:
1530         {
1531             retVal = false;
1532             break;
1533         }
1534     }
1535 
1536     if (retVal)
1537     {
1538         USBPHY->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_POWER(1) | USBPHY_PLL_SIC_PLL_REG_ENABLE_MASK);
1539         USBPHY->PLL_SIC     = (USBPHY->PLL_SIC & ~(USBPHY_PLL_SIC_PLL_DIV_SEL_MASK)) | phyPllDiv;
1540         USBPHY->PLL_SIC_CLR = USBPHY_PLL_SIC_PLL_BYPASS_MASK;
1541         USBPHY->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK);
1542 
1543         USBPHY->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK;
1544         USBPHY->PWD_SET  = 0x0;
1545 
1546         while (0UL == (USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK))
1547         {
1548         }
1549     }
1550 
1551     return retVal;
1552 }
1553