]> git.gir.st - tmk_keyboard.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'
[tmk_keyboard.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
Imprint / Impressum