]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/mcg/fsl_mcg_hal.c
Merge commit '1fe4406f374291ab2e86e95a97341fd9c475fcb8'
[qmk_firmware.git] / tmk_core / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_Freescale / TARGET_KPSDK_MCUS / TARGET_KPSDK_CODE / hal / mcg / fsl_mcg_hal.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.h"
32
33 /*******************************************************************************
34  * Definitions
35  ******************************************************************************/
36
37
38 /*******************************************************************************
39  * Code
40  ******************************************************************************/
41
42 /*FUNCTION**********************************************************************
43  *
44  * Function Name : CLOCK_HAL_GetFllRefclk
45  * Description   : Internal function to find the fll reference clock
46  * This is an internal function to get the fll reference clock. The returned
47  * value will be used for other APIs to calculate teh fll and other clock value.
48  *
49  *END**************************************************************************/
50 uint32_t CLOCK_HAL_GetFllRefClk(uint32_t baseAddr)
51 {
52     uint32_t mcgffclk;
53     uint8_t  divider;
54
55     if (CLOCK_HAL_GetInternalRefSelMode(baseAddr) == kMcgInternalRefClkSrcExternal)
56     {
57         /* External reference clock is selected */
58 #if FSL_FEATURE_MCG_USE_OSCSEL          /* case 1: use oscsel for ffclk      */
59
60         int32_t oscsel = CLOCK_HAL_GetOscselMode(baseAddr);
61         if (oscsel == kMcgOscselOsc)
62         {
63 #if FSL_FEATURE_MCG_HAS_OSC1
64             /* System oscillator 0 drives MCG clock */
65             mcgffclk = CPU_XTAL0_CLK_HZ;
66 #else
67             /* System oscillator 0 drives MCG clock */
68             mcgffclk = CPU_XTAL_CLK_HZ;
69 #endif
70         }
71         else if (oscsel == kMcgOscselRtc)
72         {
73             /* RTC 32 kHz oscillator drives MCG clock */
74             mcgffclk = CPU_XTAL32k_CLK_HZ;
75         }
76 #if FSL_FEATURE_MCG_HAS_IRC_48M         /* case 1.1: if IRC 48M exists*/
77         else if (oscsel == kMcgOscselIrc)
78         {
79             /* IRC 48Mhz oscillator drives MCG clock */
80             mcgffclk = CPU_INT_IRC_CLK_HZ;
81         }
82 #endif
83         else
84         {
85             mcgffclk = 0;
86         }
87
88 #else                                   /* case 2: use default osc0*/
89
90         /* System oscillator 0 drives MCG clock */
91         mcgffclk = CPU_XTAL_CLK_HZ;
92
93 #endif
94
95         divider = (uint8_t)(1u << CLOCK_HAL_GetFllExternalRefDivider(baseAddr));
96
97         /* Calculate the divided FLL reference clock*/
98         mcgffclk = (mcgffclk / divider);
99
100         if ((CLOCK_HAL_GetRange0Mode(baseAddr) != kMcgFreqRangeSelLow) 
101 #if FSL_FEATURE_MCG_USE_OSCSEL          /* case 1: use oscsel for ffclk      */
102             && (CLOCK_HAL_GetOscselMode(baseAddr) != kMcgOscselRtc))
103 #else
104             )
105 #endif
106         {
107             /* If high range is enabled, additional 32 divider is active*/
108             mcgffclk = (mcgffclk >> kMcgConstant5);
109         }
110     }
111     else
112     {
113         /* The slow internal reference clock is selected */
114         mcgffclk = CPU_INT_SLOW_CLK_HZ;
115     }
116     return mcgffclk;
117 }
118
119 /*FUNCTION**********************************************************************
120  *
121  * Function Name : CLOCK_HAL_GetFllclk
122  * Description   : Get the current mcg fll clock
123  * This function will return the mcgfllclk value in frequency(hz) based on
124  * current mcg configurations and settings. Fll should be properly configured
125  * in order to get the valid value.
126  *
127  *END**************************************************************************/
128 uint32_t CLOCK_HAL_GetFllClk(uint32_t baseAddr)
129 {
130     uint32_t mcgfllclk;
131     mcg_dmx32_select_t dmx32;
132     mcg_digital_controlled_osc_range_select_t drstDrs;
133
134     mcgfllclk = CLOCK_HAL_GetFllRefClk(baseAddr);
135
136     /* Select correct multiplier to calculate the MCG output clock  */
137     dmx32 = CLOCK_HAL_GetDmx32(baseAddr);
138     drstDrs = CLOCK_HAL_GetDigitalControlledOscRangeMode(baseAddr);
139
140     switch (drstDrs)
141     {
142     case kMcgDigitalControlledOscRangeSelLow:         /* Low frequency range */
143         switch (dmx32)
144         {
145         case kMcgDmx32Default:          /* DCO has a default range of 25% */
146             mcgfllclk *= kMcgConstant640;
147             break;
148         case kMcgDmx32Fine:             /* DCO is fine-tuned for max freq 32.768 kHz */
149             mcgfllclk *= kMcgConstant732;
150             break;
151         default:
152             break;
153         }
154         break;
155     case kMcgDigitalControlledOscRangeSelMid:         /* Mid frequency range*/
156         switch (dmx32)
157         {
158         case kMcgDmx32Default:          /* DCO has a default range of 25% */
159             mcgfllclk *= kMcgConstant1280;
160             break;
161         case kMcgDmx32Fine:             /* DCO is fine-tuned for max freq 32.768 kHz */
162             mcgfllclk *= kMcgConstant1464;
163             break;
164         default:
165             break;
166         }
167         break;
168     case kMcgDigitalControlledOscRangeSelMidHigh:      /* Mid-High frequency range */
169         switch (dmx32)
170         {
171         case kMcgDmx32Default:          /* DCO has a default range of 25% */
172             mcgfllclk *= kMcgConstant1920;
173             break;
174         case kMcgDmx32Fine:             /* DCO is fine-tuned for max freq 32.768 kHz */
175             mcgfllclk *= kMcgConstant2197;
176             break;
177         default:
178             break;
179         }
180         break;
181     case kMcgDigitalControlledOscRangeSelHigh:        /* High frequency range */
182         switch (dmx32)
183         {
184         case kMcgDmx32Default:          /* DCO has a default range of 25% */
185             mcgfllclk *= kMcgConstant2560;
186             break;
187         case kMcgDmx32Fine:             /* DCO is fine-tuned for max freq 32.768 kHz */
188             mcgfllclk *= kMcgConstant2929;
189             break;
190         default:
191             break;
192         }
193         break;
194     default:
195         break;
196     }
197
198     return mcgfllclk;
199 }
200 #if FSL_FEATURE_MCG_HAS_PLL
201 /*FUNCTION**********************************************************************
202  *
203  * Function Name : CLOCK_HAL_GetPll0clk
204  * Description   : Get the current mcg pll/pll0 clock
205  * This function will return the mcgpllclk/mcgpll0 value in frequency(hz) based
206  * on current mcg configurations and settings. PLL/PLL0 should be properly
207  * configured in order to get the valid value.
208  *
209  *END**************************************************************************/
210 uint32_t CLOCK_HAL_GetPll0Clk(uint32_t baseAddr)
211 {
212     uint32_t mcgpll0clk;
213     uint8_t  divider;
214
215     /* PLL(0) output is selected*/
216 #if FSL_FEATURE_MCG_USE_PLLREFSEL /* case 1 use pllrefsel to select pll*/
217
218     if (CLOCK_HAL_GetPllRefSel0Mode(baseAddr) != kMcgPllExternalRefClkSelOsc0)
219     {
220         /* OSC1 clock source used as an external reference clock */
221         mcgpll0clk = CPU_XTAL1_CLK_HZ;
222     }
223     else
224     {
225         /* OSC0 clock source used as an external reference clock*/
226         mcgpll0clk = CPU_XTAL0_CLK_HZ;
227     }
228 #else
229 #if FSL_FEATURE_MCG_USE_OSCSEL              /* case 2: use oscsel for pll      */
230     mcg_oscsel_select_t oscsel = CLOCK_HAL_GetOscselMode(baseAddr);
231     if (oscsel == kMcgOscselOsc)        /* case 2.1: OSC0 */
232     {
233         /* System oscillator drives MCG clock*/
234         mcgpll0clk = CPU_XTAL_CLK_HZ;
235     }
236     else if (oscsel == kMcgOscselRtc)   /* case 2.2: RTC */
237     {
238         /* RTC 32 kHz oscillator drives MCG clock*/
239         mcgpll0clk = CPU_XTAL32k_CLK_HZ;
240     }
241 #if FSL_FEATURE_MCG_HAS_IRC_48M
242     else if (oscsel == kMcgOscselIrc)   /* case 2.3: IRC 48M */
243     {
244         /* IRC 48Mhz oscillator drives MCG clock*/
245         mcgpll0clk = CPU_INT_IRC_CLK_HZ;
246     }
247     else
248     {
249         mcgpll0clk = 0;
250     }
251 #endif
252 #else                                       /* case 3: use default osc0*/
253     /* System oscillator drives MCG clock*/
254     mcgpll0clk = CPU_XTAL_CLK_HZ;
255 #endif
256 #endif
257
258     divider = (kMcgConstant1 + CLOCK_HAL_GetPllExternalRefDivider0(baseAddr));
259
260     /* Calculate the PLL reference clock*/
261     mcgpll0clk /= divider;
262     divider = (CLOCK_HAL_GetVoltCtrlOscDivider0(baseAddr) + FSL_FEATURE_MCG_PLL_VDIV_BASE);
263
264     /* Calculate the MCG output clock*/
265     mcgpll0clk = (mcgpll0clk * divider);
266
267     return mcgpll0clk;
268 }
269 #endif
270
271 #if FSL_FEATURE_MCG_HAS_PLL1
272 /*FUNCTION**********************************************************************
273  *
274  * Function Name : CLOCK_HAL_GetPll1Clk
275  * Description   : Get the current mcg pll1 clock
276  * This function will return the mcgpll1clk value in frequency(hz) based
277  * on current mcg configurations and settings. PLL1 should be properly configured
278  * in order to get the valid value.
279  *
280  *END**************************************************************************/
281 uint32_t CLOCK_HAL_GetPll1Clk(uint32_t baseAddr)
282 {
283     uint32_t mcgpll1clk;
284     uint8_t  divider;
285
286     if (CLOCK_HAL_GetPllRefSel1Mode(baseAddr) != kMcgPllExternalRefClkSelOsc0)
287     {
288         /* OSC1 clock source used as an external reference clock*/
289         mcgpll1clk = CPU_XTAL1_CLK_HZ;
290     }
291     else
292     {
293         /* OSC0 clock source used as an external reference clock*/
294         mcgpll1clk = CPU_XTAL0_CLK_HZ;
295     }
296
297     divider = (kMcgConstant1 + CLOCK_HAL_GetPllExternalRefDivider1(baseAddr));
298
299     /* Calculate the PLL reference clock*/
300     mcgpll1clk /= divider;
301     divider = (CLOCK_HAL_GetVoltCtrlOscDivider1(baseAddr) + FSL_FEATURE_MCG_PLL_VDIV_BASE);
302
303     /* Calculate the MCG output clock*/
304     mcgpll1clk = ((mcgpll1clk * divider) >> kMcgConstant1); /* divided by 2*/
305     return mcgpll1clk;
306 }
307 #endif
308
309 /*FUNCTION**********************************************************************
310  *
311  * Function Name : CLOCK_HAL_GetIrclk
312  * Description   : Get the current mcg ir clock
313  * This function will return the mcgirclk value in frequency(hz) based
314  * on current mcg configurations and settings. It will not check if the
315  * mcgirclk is enabled or not, just calculate and return the value.
316  *
317  *END**************************************************************************/
318 uint32_t CLOCK_HAL_GetInternalRefClk(uint32_t baseAddr)
319 {
320     int32_t mcgirclk;
321     if (CLOCK_HAL_GetInternalRefClkSelMode(baseAddr) == kMcgInternalRefClkSelSlow)
322     {
323         /* Slow internal reference clock selected*/
324         mcgirclk = CPU_INT_SLOW_CLK_HZ;
325     }
326     else
327     {
328         mcgirclk = CPU_INT_FAST_CLK_HZ / (1 << CLOCK_HAL_GetFastClkInternalRefDivider(baseAddr));
329     }
330     return mcgirclk;
331 }
332
333 /*FUNCTION**********************************************************************
334  *
335  * Function Name : CLOCK_HAL_GetOutclk
336  * Description   : Get the current mcg out clock
337  * This function will return the mcgoutclk value in frequency(hz) based on
338  * current mcg configurations and settings. The configuration should be
339  * properly done in order to get the valid value.
340  *
341  *END**************************************************************************/
342 uint32_t CLOCK_HAL_GetOutClk(uint32_t baseAddr)
343 {
344     /* Variable to store output clock frequency of the MCG module*/
345     uint32_t mcgoutclk = 0;
346
347     if (CLOCK_HAL_GetClkSrcMode(baseAddr) == kMcgClkSelOut)
348     {
349 #if FSL_FEATURE_MCG_HAS_PLL
350         /* Output of FLL or PLL is selected*/
351         if (CLOCK_HAL_GetPllSelMode(baseAddr) == kMcgPllSelFll)
352         {
353             /* FLL is selected*/
354             mcgoutclk = CLOCK_HAL_GetFllClk(baseAddr);
355         }
356         else
357         {
358             /* PLL is selected*/
359 #if FSL_FEATURE_MCG_HAS_PLL1
360             if (CLOCK_HAL_GetPllClkSelMode(baseAddr) != kMcgPllClkSelPll0)
361             {
362                 /* PLL1 output is selected*/
363                 mcgoutclk = CLOCK_HAL_GetPll1Clk(baseAddr);
364             }
365             else
366             {
367                 mcgoutclk = CLOCK_HAL_GetPll0Clk(baseAddr);
368             }
369 #else
370             mcgoutclk = CLOCK_HAL_GetPll0Clk(baseAddr);
371 #endif // FSL_FEATURE_MCG_HAS_PLL1
372         }
373 #else
374         mcgoutclk = CLOCK_HAL_GetFllClk(baseAddr);
375 #endif // FSL_FEATURE_MCG_HAS_PLL
376     }
377     else if (CLOCK_HAL_GetClkSrcMode(baseAddr) == kMcgClkSelInternal)
378     {
379         /* Internal reference clock is selected*/
380         mcgoutclk = CLOCK_HAL_GetInternalRefClk(baseAddr);
381     }
382     else if (CLOCK_HAL_GetClkSrcMode(baseAddr) == kMcgClkSelExternal)
383     {
384         /* External reference clock is selected*/
385
386 #if FSL_FEATURE_MCG_USE_OSCSEL              /* case 1: use oscsel for outclock      */
387
388         uint32_t oscsel = CLOCK_HAL_GetOscselMode(baseAddr);
389         if (oscsel == kMcgOscselOsc)
390         {
391 #if FSL_FEATURE_MCG_HAS_OSC1
392             /* System oscillator drives MCG clock*/
393             mcgoutclk = CPU_XTAL0_CLK_HZ;
394 #else
395             /* System oscillator drives MCG clock*/
396             mcgoutclk = CPU_XTAL_CLK_HZ;
397 #endif
398         }
399         else if (oscsel == kMcgOscselRtc)
400         {
401             /* RTC 32 kHz oscillator drives MCG clock*/
402             mcgoutclk = CPU_XTAL32k_CLK_HZ;
403         }
404 #if FSL_FEATURE_MCG_HAS_IRC_48M             /* case 1.1: IRC 48M exists*/
405         else if (oscsel == kMcgOscselIrc)
406         {
407             /* IRC 48Mhz oscillator drives MCG clock*/
408             mcgoutclk = CPU_INT_IRC_CLK_HZ;
409         }
410         else
411         {
412             mcgoutclk = 0;
413         }
414 #endif
415
416 #else                                       /* case 2: use default osc0*/
417         /* System oscillator drives MCG clock*/
418         mcgoutclk = CPU_XTAL_CLK_HZ;
419 #endif
420     }
421     else
422     {
423         /* Reserved value*/
424         return mcgoutclk;
425     }
426     return mcgoutclk;
427 }
428
429 /*******************************************************************************
430  * EOF
431  ******************************************************************************/
432