diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/K32L2B21A/drivers/fsl_clock.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/devices/K32L2B21A/drivers/fsl_clock.c | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/K32L2B21A/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/K32L2B21A/drivers/fsl_clock.c new file mode 100644 index 000000000..92ea36ef4 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/K32L2B21A/drivers/fsl_clock.c | |||
@@ -0,0 +1,506 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. | ||
3 | * Copyright 2016 - 2019, NXP | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * SPDX-License-Identifier: BSD-3-Clause | ||
7 | */ | ||
8 | |||
9 | #include "fsl_clock.h" | ||
10 | |||
11 | /******************************************************************************* | ||
12 | * Definitions | ||
13 | ******************************************************************************/ | ||
14 | |||
15 | /* Component ID definition, used by tools. */ | ||
16 | #ifndef FSL_COMPONENT_ID | ||
17 | #define FSL_COMPONENT_ID "platform.drivers.clock" | ||
18 | #endif | ||
19 | |||
20 | #if (defined(OSC) && !(defined(OSC0))) | ||
21 | #define OSC0 OSC | ||
22 | #endif | ||
23 | |||
24 | #define MCG_HIRC_FREQ (48000000U) | ||
25 | #define MCG_LIRC_FREQ1 (2000000U) | ||
26 | #define MCG_LIRC_FREQ2 (8000000U) | ||
27 | |||
28 | #define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) | ||
29 | #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) | ||
30 | #define MCG_MC_LIRC_DIV2_VAL ((MCG->MC & MCG_MC_LIRC_DIV2_MASK) >> MCG_MC_LIRC_DIV2_SHIFT) | ||
31 | #define MCG_C2_IRCS_VAL ((MCG->C2 & MCG_C2_IRCS_MASK) >> MCG_C2_IRCS_SHIFT) | ||
32 | |||
33 | #define SIM_CLKDIV1_OUTDIV1_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT) | ||
34 | #define SIM_CLKDIV1_OUTDIV4_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) | ||
35 | #define SIM_SOPT1_OSC32KSEL_VAL ((SIM->SOPT1 & SIM_SOPT1_OSC32KSEL_MASK) >> SIM_SOPT1_OSC32KSEL_SHIFT) | ||
36 | |||
37 | /******************************************************************************* | ||
38 | * Variables | ||
39 | ******************************************************************************/ | ||
40 | |||
41 | /* External XTAL0 (OSC0) clock frequency. */ | ||
42 | volatile uint32_t g_xtal0Freq; | ||
43 | /* External XTAL32K clock frequency. */ | ||
44 | volatile uint32_t g_xtal32Freq; | ||
45 | |||
46 | /******************************************************************************* | ||
47 | * Prototypes | ||
48 | ******************************************************************************/ | ||
49 | |||
50 | /*! | ||
51 | * @brief Get the current MCG_Lite LIRC_CLK frequency in Hz. | ||
52 | * | ||
53 | * This function will return the LIRC_CLK value in frequency(Hz) based | ||
54 | * on current MCG_Lite configurations and settings. It is an internal function. | ||
55 | * | ||
56 | * @return MCG_Lite LIRC_CLK frequency. | ||
57 | */ | ||
58 | static uint32_t CLOCK_GetLircClkFreq(void); | ||
59 | |||
60 | /*! | ||
61 | * @brief Get RANGE value based on OSC frequency. | ||
62 | * | ||
63 | * To setup external crystal oscillator, must set the register bits RANGE base | ||
64 | * on the crystal frequency. This function returns the RANGE base on the input | ||
65 | * frequency. This is an internal function. | ||
66 | * | ||
67 | * @return RANGE value. | ||
68 | */ | ||
69 | static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); | ||
70 | |||
71 | /******************************************************************************* | ||
72 | * Code | ||
73 | ******************************************************************************/ | ||
74 | |||
75 | static uint32_t CLOCK_GetLircClkFreq(void) | ||
76 | { | ||
77 | static const uint32_t lircFreqs[] = {MCG_LIRC_FREQ1, MCG_LIRC_FREQ2}; | ||
78 | uint32_t freq; | ||
79 | |||
80 | /* Check whether the LIRC is enabled. */ | ||
81 | if (((MCG->C1 & MCG_C1_IRCLKEN_MASK) != 0U) || ((uint8_t)kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL)) | ||
82 | { | ||
83 | freq = lircFreqs[MCG_C2_IRCS_VAL]; | ||
84 | } | ||
85 | else | ||
86 | { | ||
87 | freq = 0U; | ||
88 | } | ||
89 | |||
90 | return freq; | ||
91 | } | ||
92 | |||
93 | static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) | ||
94 | { | ||
95 | uint8_t range; | ||
96 | |||
97 | if (freq <= 39063U) | ||
98 | { | ||
99 | range = 0U; | ||
100 | } | ||
101 | else if (freq <= 8000000U) | ||
102 | { | ||
103 | range = 1U; | ||
104 | } | ||
105 | else | ||
106 | { | ||
107 | range = 2U; | ||
108 | } | ||
109 | |||
110 | return range; | ||
111 | } | ||
112 | |||
113 | /*! | ||
114 | * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). | ||
115 | * | ||
116 | * return Clock frequency in Hz. | ||
117 | */ | ||
118 | uint32_t CLOCK_GetOsc0ErClkFreq(void) | ||
119 | { | ||
120 | uint32_t freq; | ||
121 | |||
122 | if ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U) | ||
123 | { | ||
124 | /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ | ||
125 | assert(g_xtal0Freq); | ||
126 | freq = g_xtal0Freq; | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | freq = 0U; | ||
131 | } | ||
132 | |||
133 | return freq; | ||
134 | } | ||
135 | |||
136 | /*! | ||
137 | * brief Get the external reference 32K clock frequency (ERCLK32K). | ||
138 | * | ||
139 | * return Clock frequency in Hz. | ||
140 | */ | ||
141 | uint32_t CLOCK_GetEr32kClkFreq(void) | ||
142 | { | ||
143 | uint32_t freq; | ||
144 | |||
145 | switch (SIM_SOPT1_OSC32KSEL_VAL) | ||
146 | { | ||
147 | case 0U: /* OSC 32k clock */ | ||
148 | freq = (CLOCK_GetOsc0ErClkFreq() == 32768U) ? 32768U : 0U; | ||
149 | break; | ||
150 | case 2U: /* RTC 32k clock */ | ||
151 | /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ | ||
152 | assert(g_xtal32Freq); | ||
153 | freq = g_xtal32Freq; | ||
154 | break; | ||
155 | case 3U: /* LPO clock */ | ||
156 | freq = LPO_CLK_FREQ; | ||
157 | break; | ||
158 | default: | ||
159 | freq = 0U; | ||
160 | break; | ||
161 | } | ||
162 | return freq; | ||
163 | } | ||
164 | |||
165 | /*! | ||
166 | * brief Get the platform clock frequency. | ||
167 | * | ||
168 | * return Clock frequency in Hz. | ||
169 | */ | ||
170 | uint32_t CLOCK_GetPlatClkFreq(void) | ||
171 | { | ||
172 | return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); | ||
173 | } | ||
174 | |||
175 | /*! | ||
176 | * brief Get the flash clock frequency. | ||
177 | * | ||
178 | * return Clock frequency in Hz. | ||
179 | */ | ||
180 | uint32_t CLOCK_GetFlashClkFreq(void) | ||
181 | { | ||
182 | uint32_t freq; | ||
183 | |||
184 | freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); | ||
185 | freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1U); | ||
186 | |||
187 | return freq; | ||
188 | } | ||
189 | |||
190 | /*! | ||
191 | * brief Get the bus clock frequency. | ||
192 | * | ||
193 | * return Clock frequency in Hz. | ||
194 | */ | ||
195 | uint32_t CLOCK_GetBusClkFreq(void) | ||
196 | { | ||
197 | uint32_t freq; | ||
198 | |||
199 | freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); | ||
200 | freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1U); | ||
201 | |||
202 | return freq; | ||
203 | } | ||
204 | |||
205 | /*! | ||
206 | * brief Get the core clock or system clock frequency. | ||
207 | * | ||
208 | * return Clock frequency in Hz. | ||
209 | */ | ||
210 | uint32_t CLOCK_GetCoreSysClkFreq(void) | ||
211 | { | ||
212 | return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); | ||
213 | } | ||
214 | |||
215 | /*! | ||
216 | * brief Gets the clock frequency for a specific clock name. | ||
217 | * | ||
218 | * This function checks the current clock configurations and then calculates | ||
219 | * the clock frequency for a specific clock name defined in clock_name_t. | ||
220 | * The MCG must be properly configured before using this function. | ||
221 | * | ||
222 | * param clockName Clock names defined in clock_name_t | ||
223 | * return Clock frequency value in Hertz | ||
224 | */ | ||
225 | uint32_t CLOCK_GetFreq(clock_name_t clockName) | ||
226 | { | ||
227 | uint32_t freq; | ||
228 | |||
229 | switch (clockName) | ||
230 | { | ||
231 | case kCLOCK_CoreSysClk: | ||
232 | case kCLOCK_PlatClk: | ||
233 | freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); | ||
234 | break; | ||
235 | case kCLOCK_BusClk: | ||
236 | case kCLOCK_FlashClk: | ||
237 | freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1U); | ||
238 | freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1U); | ||
239 | break; | ||
240 | case kCLOCK_Er32kClk: | ||
241 | freq = CLOCK_GetEr32kClkFreq(); | ||
242 | break; | ||
243 | case kCLOCK_Osc0ErClk: | ||
244 | freq = CLOCK_GetOsc0ErClkFreq(); | ||
245 | break; | ||
246 | case kCLOCK_McgInternalRefClk: | ||
247 | freq = CLOCK_GetInternalRefClkFreq(); | ||
248 | break; | ||
249 | case kCLOCK_McgPeriphClk: | ||
250 | case kCLOCK_McgIrc48MClk: | ||
251 | freq = CLOCK_GetPeriphClkFreq(); | ||
252 | break; | ||
253 | case kCLOCK_LpoClk: | ||
254 | freq = LPO_CLK_FREQ; | ||
255 | break; | ||
256 | default: | ||
257 | freq = 0U; | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | return freq; | ||
262 | } | ||
263 | |||
264 | /*! | ||
265 | * brief Set the clock configure in SIM module. | ||
266 | * | ||
267 | * This function sets system layer clock settings in SIM module. | ||
268 | * | ||
269 | * param config Pointer to the configure structure. | ||
270 | */ | ||
271 | void CLOCK_SetSimConfig(sim_clock_config_t const *config) | ||
272 | { | ||
273 | SIM->CLKDIV1 = config->clkdiv1; | ||
274 | CLOCK_SetEr32kClock(config->er32kSrc); | ||
275 | } | ||
276 | |||
277 | /*! brief Enable USB FS clock. | ||
278 | * | ||
279 | * param src USB FS clock source. | ||
280 | * param freq The frequency specified by src. | ||
281 | * retval true The clock is set successfully. | ||
282 | * retval false The clock source is invalid to get proper USB FS clock. | ||
283 | */ | ||
284 | bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) | ||
285 | { | ||
286 | bool ret = true; | ||
287 | |||
288 | CLOCK_DisableClock(kCLOCK_Usbfs0); | ||
289 | |||
290 | if (kCLOCK_UsbSrcExt == src) | ||
291 | { | ||
292 | SIM->SOPT2 &= ~SIM_SOPT2_USBSRC_MASK; | ||
293 | } | ||
294 | else | ||
295 | { | ||
296 | SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK; | ||
297 | } | ||
298 | |||
299 | CLOCK_EnableClock(kCLOCK_Usbfs0); | ||
300 | |||
301 | if (kCLOCK_UsbSrcIrc48M == src) | ||
302 | { | ||
303 | USB0->CLK_RECOVER_IRC_EN = 0x03U; | ||
304 | USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK; | ||
305 | } | ||
306 | |||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | /*! | ||
311 | * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. | ||
312 | * | ||
313 | * This function gets the MCG_Lite internal reference clock frequency in Hz based | ||
314 | * on the current MCG register value. | ||
315 | * | ||
316 | * return The frequency of MCGIRCLK. | ||
317 | */ | ||
318 | uint32_t CLOCK_GetInternalRefClkFreq(void) | ||
319 | { | ||
320 | uint8_t divider1 = MCG_SC_FCRDIV_VAL; | ||
321 | uint8_t divider2 = MCG_MC_LIRC_DIV2_VAL; | ||
322 | /* LIRC internal reference clock is selected*/ | ||
323 | return CLOCK_GetLircClkFreq() >> (divider1 + divider2); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * brief Gets the current MCGPCLK frequency. | ||
328 | * | ||
329 | * This function gets the MCGPCLK frequency in Hz based on the current MCG_Lite | ||
330 | * register settings. | ||
331 | * | ||
332 | * return The frequency of MCGPCLK. | ||
333 | */ | ||
334 | uint32_t CLOCK_GetPeriphClkFreq(void) | ||
335 | { | ||
336 | uint32_t freq; | ||
337 | |||
338 | /* Check whether the HIRC is enabled. */ | ||
339 | if (((MCG->MC & MCG_MC_HIRCEN_MASK) != 0U) || ((uint8_t)kMCGLITE_ClkSrcHirc == MCG_S_CLKST_VAL)) | ||
340 | { | ||
341 | freq = MCG_HIRC_FREQ; | ||
342 | } | ||
343 | else | ||
344 | { | ||
345 | freq = 0U; | ||
346 | } | ||
347 | |||
348 | return freq; | ||
349 | } | ||
350 | |||
351 | /*! | ||
352 | * brief Gets the MCG_Lite output clock (MCGOUTCLK) frequency. | ||
353 | * | ||
354 | * This function gets the MCG_Lite output clock frequency in Hz based on the current | ||
355 | * MCG_Lite register value. | ||
356 | * | ||
357 | * return The frequency of MCGOUTCLK. | ||
358 | */ | ||
359 | uint32_t CLOCK_GetOutClkFreq(void) | ||
360 | { | ||
361 | uint32_t freq; | ||
362 | |||
363 | switch (MCG_S_CLKST_VAL) | ||
364 | { | ||
365 | case (uint8_t)kMCGLITE_ClkSrcHirc: | ||
366 | freq = MCG_HIRC_FREQ; | ||
367 | break; | ||
368 | case (uint8_t)kMCGLITE_ClkSrcLirc: | ||
369 | freq = CLOCK_GetLircClkFreq() >> MCG_SC_FCRDIV_VAL; | ||
370 | break; | ||
371 | case (uint8_t)kMCGLITE_ClkSrcExt: | ||
372 | /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ | ||
373 | assert(g_xtal0Freq); | ||
374 | freq = g_xtal0Freq; | ||
375 | break; | ||
376 | default: | ||
377 | freq = 0U; | ||
378 | break; | ||
379 | } | ||
380 | |||
381 | return freq; | ||
382 | } | ||
383 | |||
384 | /*! | ||
385 | * brief Gets the current MCG_Lite mode. | ||
386 | * | ||
387 | * This function checks the MCG_Lite registers and determines the current MCG_Lite mode. | ||
388 | * | ||
389 | * return The current MCG_Lite mode or error code. | ||
390 | */ | ||
391 | mcglite_mode_t CLOCK_GetMode(void) | ||
392 | { | ||
393 | mcglite_mode_t mode; | ||
394 | |||
395 | switch (MCG_S_CLKST_VAL) | ||
396 | { | ||
397 | case (uint8_t)kMCGLITE_ClkSrcHirc: /* HIRC */ | ||
398 | mode = kMCGLITE_ModeHirc48M; | ||
399 | break; | ||
400 | case (uint8_t)kMCGLITE_ClkSrcLirc: /* LIRC */ | ||
401 | if ((uint8_t)kMCGLITE_Lirc2M == MCG_C2_IRCS_VAL) | ||
402 | { | ||
403 | mode = kMCGLITE_ModeLirc2M; | ||
404 | } | ||
405 | else | ||
406 | { | ||
407 | mode = kMCGLITE_ModeLirc8M; | ||
408 | } | ||
409 | break; | ||
410 | case (uint8_t)kMCGLITE_ClkSrcExt: /* EXT */ | ||
411 | mode = kMCGLITE_ModeExt; | ||
412 | break; | ||
413 | default: | ||
414 | mode = kMCGLITE_ModeError; | ||
415 | break; | ||
416 | } | ||
417 | |||
418 | return mode; | ||
419 | } | ||
420 | |||
421 | /*! | ||
422 | * brief Sets the MCG_Lite configuration. | ||
423 | * | ||
424 | * This function configures the MCG_Lite, includes the output clock source, MCGIRCLK | ||
425 | * settings, HIRC settings, and so on. See ref mcglite_config_t for details. | ||
426 | * | ||
427 | * param targetConfig Pointer to the target MCG_Lite mode configuration structure. | ||
428 | * return Error code. | ||
429 | */ | ||
430 | status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig) | ||
431 | { | ||
432 | assert(targetConfig); | ||
433 | |||
434 | /* | ||
435 | * If switch between LIRC8M and LIRC2M, need to switch to HIRC mode first, | ||
436 | * because could not switch directly. | ||
437 | */ | ||
438 | if (((uint8_t)kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL) && (kMCGLITE_ClkSrcLirc == targetConfig->outSrc) && | ||
439 | (MCG_C2_IRCS_VAL != (uint8_t)(targetConfig->ircs))) | ||
440 | { | ||
441 | MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCGLITE_ClkSrcHirc)); | ||
442 | while ((uint8_t)kMCGLITE_ClkSrcHirc != MCG_S_CLKST_VAL) | ||
443 | { | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /* Set configuration now. */ | ||
448 | MCG->SC = MCG_SC_FCRDIV(targetConfig->fcrdiv); | ||
449 | MCG->MC = MCG_MC_HIRCEN(targetConfig->hircEnableInNotHircMode) | MCG_MC_LIRC_DIV2(targetConfig->lircDiv2); | ||
450 | MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | MCG_C2_IRCS(targetConfig->ircs)); | ||
451 | MCG->C1 = MCG_C1_CLKS(targetConfig->outSrc) | targetConfig->irclkEnableMode; | ||
452 | |||
453 | /* | ||
454 | * If external oscillator used and MCG_Lite is set to EXT mode, need to | ||
455 | * wait for the OSC stable. | ||
456 | */ | ||
457 | if (((MCG->C2 & MCG_C2_EREFS0_MASK) != 0U) && (kMCGLITE_ClkSrcExt == targetConfig->outSrc)) | ||
458 | { | ||
459 | while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) | ||
460 | { | ||
461 | } | ||
462 | } | ||
463 | |||
464 | /* Wait for clock source change completed. */ | ||
465 | while ((uint8_t)targetConfig->outSrc != MCG_S_CLKST_VAL) | ||
466 | { | ||
467 | } | ||
468 | |||
469 | return kStatus_Success; | ||
470 | } | ||
471 | |||
472 | /*! | ||
473 | * brief Initializes the OSC0. | ||
474 | * | ||
475 | * This function initializes the OSC0 according to the board configuration. | ||
476 | * | ||
477 | * param config Pointer to the OSC0 configuration structure. | ||
478 | */ | ||
479 | void CLOCK_InitOsc0(osc_config_t const *config) | ||
480 | { | ||
481 | uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); | ||
482 | |||
483 | OSC_SetCapLoad(OSC0, config->capLoad); | ||
484 | OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); | ||
485 | |||
486 | MCG->C2 = ((MCG->C2 & MCG_C2_IRCS_MASK) | MCG_C2_RANGE0(range) | (uint8_t)config->workMode); | ||
487 | |||
488 | if ((kOSC_ModeExt != config->workMode) && ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U)) | ||
489 | { | ||
490 | /* Wait for stable. */ | ||
491 | while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) | ||
492 | { | ||
493 | } | ||
494 | } | ||
495 | } | ||
496 | |||
497 | /*! | ||
498 | * brief Deinitializes the OSC0. | ||
499 | * | ||
500 | * This function deinitializes the OSC0. | ||
501 | */ | ||
502 | void CLOCK_DeinitOsc0(void) | ||
503 | { | ||
504 | OSC0->CR = 0U; | ||
505 | MCG->C2 &= MCG_C2_IRCS_MASK; | ||
506 | } | ||