1 /***************************************************************************//**
2 * @file
3 * @brief Clock management unit (CMU) Peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30 #include "em_cmu.h"
31 #if defined(CMU_PRESENT)
32
33 #include <stddef.h>
34 #include <limits.h>
35 #include "sl_assert.h"
36 #include "em_bus.h"
37 #include "sl_common.h"
38 #include "em_emu.h"
39 #include "em_gpio.h"
40 #include "em_system.h"
41 #if defined(SYSCFG_PRESENT)
42 #include "em_syscfg.h"
43 #endif
44 #include "em_msc.h"
45
46 /***************************************************************************//**
47 * @addtogroup cmu CMU - Clock Management Unit
48 * @brief Clock management unit (CMU) Peripheral API
49 * @details
50 * This module contains functions for the CMU peripheral of Silicon Labs 32-bit
51 * MCUs and SoCs. The CMU module controls oscillators, clocks gates, clock
52 * multiplexers, pre-scalers, calibration modules and wait-states.
53 * @{
54 ******************************************************************************/
55 #if defined(_SILICON_LABS_32B_SERIES_2)
56
57 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
58
59 /*******************************************************************************
60 ****************************** DEFINES ************************************
61 ******************************************************************************/
62
63 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
64 // Maximum allowed core frequency vs. wait-states on flash accesses.
65 #define CMU_MAX_FREQ_0WS_1V1 40000000UL
66
67 #define CMU_MAX_FREQ_0WS_1V0 40000000UL
68
69 // Maximum allowed core frequency vs. wait-states on sram accesses.
70 #define CMU_MAX_SRAM_FREQ_0WS 50000000UL
71 #define CMU_MAX_SRAM_FREQ_1WS 80000000UL
72
73 #elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) \
74 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7)
75 #define CMU_MAX_FREQ_0WS_1V1 40000000UL
76
77 #define CMU_MAX_FREQ_0WS_1V0 40000000UL
78 #elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3) \
79 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
80 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)
81 // Maximum allowed core frequency vs. wait-states and vscale on flash accesses.
82 #define CMU_MAX_FREQ_0WS_1V1 40000000UL
83
84 #define CMU_MAX_FREQ_0WS_1V0 20000000UL
85 #elif (_SILICON_LABS_32B_SERIES_2_CONFIG == 5)
86 #define CMU_MAX_FREQ_0WS_1V1 25000000UL
87 #define CMU_MAX_FREQ_1WS_1V1 50000000UL
88 #define CMU_MAX_FREQ_2WS_1V1 75000000UL
89 #else
90 #warning "MCU flash wait states not supported"
91 #endif
92
93 // Maximum allowed PCLK frequency.
94 #define CMU_MAX_PCLK_FREQ 50000000UL
95
96 // Maximum allowed RHCLK frequency.
97 #define CMU_MAX_RHCLK_FREQ 40000000UL
98
99 #if defined(EMU_VSCALE_EM01_PRESENT)
100 // This macro is intended to be used as input to CMU_UpdateWaitStates()
101 #define VSCALE_DEFAULT (2 - (int)EMU_VScaleGet())
102 #else
103 #define VSCALE_DEFAULT VSCALE_EM01_HIGH_PERFORMANCE
104 #endif
105
106 #if defined(PLFRCO_PRESENT)
107 // Typical frequency for HFXO as recommanded in the datasheets.
108 // see AN0016: Oscillator Design Considerations
109 //
110 // Recommended for most wireless applications
111 // to meet transceiver electrical specifications
112 #define XTAL_38M4 38400000UL
113 // Recommended for implementing Z-Wave devices
114 #define XTAL_39M0 39000000UL
115 // High Precision mode calibration Counts for 38.4MHz
116 #define LFRCO_NOMCAL_XTAL_38M4 _LFRCO_NOMCAL_RESETVALUE
117 #define LFRCO_NOMCALINV_XTAL_38M4 _LFRCO_NOMCALINV_RESETVALUE
118 // High Precision mode calibration Counts for 39.0MHz.
119 #define LFRCO_NOMCAL_XTAL_39M0 0x0005CFBBUL
120 #define LFRCO_NOMCALINV_XTAL_39M0 0x0000581AUL
121 #endif
122
123 #define PLL0_USB_OUTPUT_FREQ 48000000UL
124
125 /*******************************************************************************
126 ************************** LOCAL VARIABLES ********************************
127 ******************************************************************************/
128
129 // Table of HFRCOCAL values and their associated min/max frequencies and
130 // optional band enumerator.
131 static const struct hfrcoCalTableElement{
132 uint32_t minFreq;
133 uint32_t maxFreq;
134 uint32_t value;
135 CMU_HFRCODPLLFreq_TypeDef band;
136 } hfrcoCalTable[] =
137 {
138 // minFreq maxFreq HFRCOCAL value band
139 { 900000UL, 1080000UL, 0x82401F00UL, cmuHFRCODPLLFreq_1M0Hz },
140 { 1080000UL, 1300000UL, 0xA2411F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
141 { 1300000UL, 1530000UL, 0xA2421F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
142 { 1530000UL, 1800000UL, 0xB6439F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
143 { 1800000UL, 2150000UL, 0x81401F00UL, cmuHFRCODPLLFreq_2M0Hz },
144 { 2150000UL, 2600000UL, 0xA1411F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
145 { 2600000UL, 3050000UL, 0xA1421F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
146 { 3050000UL, 3600000UL, 0xB5439F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
147 { 3600000UL, 4300000UL, 0x80401F00UL, cmuHFRCODPLLFreq_4M0Hz },
148 { 4300000UL, 5200000UL, 0xA0411F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
149 { 5200000UL, 6100000UL, 0xA0421F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
150 { 6100000UL, 7800000UL, 0xB4439F00UL, cmuHFRCODPLLFreq_7M0Hz },
151 { 7800000UL, 9800000UL, 0xB4449F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
152 { 9800000UL, 11800000UL, 0xB4459F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
153 { 11800000UL, 14400000UL, 0xB4669F00UL, cmuHFRCODPLLFreq_13M0Hz },
154 { 14400000UL, 17200000UL, 0xB4679F00UL, cmuHFRCODPLLFreq_16M0Hz },
155 { 17200000UL, 19700000UL, 0xA8689F00UL, cmuHFRCODPLLFreq_19M0Hz },
156 { 19700000UL, 23800000UL, 0xB8899F3AUL, (CMU_HFRCODPLLFreq_TypeDef)0 },
157 { 23800000UL, 28700000UL, 0xB88A9F00UL, cmuHFRCODPLLFreq_26M0Hz },
158 { 28700000UL, 34800000UL, 0xB8AB9F00UL, cmuHFRCODPLLFreq_32M0Hz },
159 { 34800000UL, 42800000UL, 0xA8CC9F00UL, cmuHFRCODPLLFreq_38M0Hz },
160 { 42800000UL, 51600000UL, 0xACED9F00UL, cmuHFRCODPLLFreq_48M0Hz },
161 { 51600000UL, 60500000UL, 0xBCEE9F00UL, cmuHFRCODPLLFreq_56M0Hz },
162 { 60500000UL, 72600000UL, 0xBCEF9F00UL, cmuHFRCODPLLFreq_64M0Hz },
163 { 72600000UL, 80000000UL, 0xCCF09F00UL, cmuHFRCODPLLFreq_80M0Hz },
164 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5)
165 { 80000000UL, 100000000UL, 0xCCF19F00UL, cmuHFRCODPLLFreq_100M0Hz }
166 #endif
167 };
168
169 static uint16_t lfxo_precision = 0xFFFF;
170
171 #define HFRCOCALTABLE_ENTRIES (sizeof(hfrcoCalTable) \
172 / sizeof(struct hfrcoCalTableElement))
173
174 // CTUNE delta needed for some series 2 chips. This delta is added to the tuning capacitance on XO.
175 // The inter-chip buffered crystal sharing feature added from the EFR32xG23 creates an imbalance
176 // between XI and XO capacitance load internally on the chip. The delta allows to compensate for
177 // the difference.
178 #if defined(_SILICON_LABS_32B_SERIES_2)
179 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3) \
180 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
181 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) \
182 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)
183 static int8_t ctuneDelta = 40; // Recommendation from analog team to counter the internal chip imbalance.
184 #else
185 static int8_t ctuneDelta = 0;
186 #endif
187 #endif
188
189 /*******************************************************************************
190 ************************** LOCAL PROTOTYPES *******************************
191 ******************************************************************************/
192 #if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
193 #if defined(PDM_PRESENT)
194 static void em01GrpbClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
195 #endif
196 #if defined(EUART_PRESENT)
197 static void euart0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
198 #endif
199 #if defined(EUSART_PRESENT)
200 static void eusart0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
201 #if defined(_CMU_EM01GRPCCLKCTRL_MASK)
202 static void em01GrpcClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
203 #endif
204 #endif
205 #if defined(LCD_PRESENT)
206 static void lcdClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
207 #endif
208 #if defined(VDAC_PRESENT)
209 static void vdac0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
210 #if (VDAC_COUNT > 1)
211 static void vdac1ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
212 #endif
213 #endif
214 #if defined(PCNT_PRESENT)
215 static void pcnt0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
216 #endif
217 #if defined(LESENSE_PRESENT)
218 static void lesenseHFClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
219 #endif
220 #if (defined(CMU_SYSCLKCTRL_RHCLKPRESC) \
221 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
222 static void rhclkPrescMax(void);
223 static void rhclkPrescOptimize(void);
224 #endif
225 #endif
226
227 #if defined(HFRCOEM23_PRESENT)
228 static uint32_t HFRCOEM23DevinfoGet(CMU_HFRCOEM23Freq_TypeDef freq);
229 #endif
230 static void traceClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
231 static void dpllRefClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
232 static void em01GrpaClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
233 static void em23GrpaClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
234 static void em4GrpaClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
235 __STATIC_INLINE uint32_t getWaitStatesByFrequencyAndVScale(uint32_t freq, int vscale);
236 static void flashWaitStateControl(uint32_t coreFreq, int vscale);
237 static uint32_t HFRCODPLLDevinfoGet(CMU_HFRCODPLLFreq_TypeDef freq);
238 #if defined(IADC_PRESENT)
239 static void iadcClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
240 #endif
241 static void pclkDivMax(void);
242 static void pclkDivOptimize(void);
243 #if defined(RTCC_PRESENT)
244 static void rtccClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
245 #elif defined(SYSRTC_PRESENT)
246 static void sysrtcClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
247 #endif
248 static void waitStateMax(void);
249 static void wdog0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
250 #if WDOG_COUNT > 1
251 static void wdog1ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
252 #endif
253 static void sysTickClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
254 #if defined(USB_PRESENT)
255 static void usbClkGet(uint32_t *freq, CMU_Select_TypeDef *sel);
256 #endif
257 /** @endcond */
258
259 // The following code is common for all SERIES_2 configurations.
260
261 /*******************************************************************************
262 ************************** GLOBAL FUNCTIONS *******************************
263 ******************************************************************************/
264
265 /***************************************************************************//**
266 * @brief
267 * Calibrate an oscillator.
268 *
269 * @details
270 * Run a calibration of a selectable reference clock againt HCLK. Please
271 * refer to the reference manual, CMU chapter, for further details.
272 *
273 * @note
274 * This function will not return until calibration measurement is completed.
275 *
276 * @param[in] cycles
277 * The number of HCLK cycles to run calibration. Increasing this number
278 * increases precision, but the calibration will take more time.
279 *
280 * @param[in] ref
281 * The reference clock used to compare against HCLK.
282 *
283 * @return
284 * The number of ticks the selected reference clock ticked while running
285 * cycles ticks of the HCLK clock.
286 ******************************************************************************/
CMU_Calibrate(uint32_t cycles,CMU_Select_TypeDef ref)287 uint32_t CMU_Calibrate(uint32_t cycles, CMU_Select_TypeDef ref)
288 {
289 // Check for cycle count overflow
290 #if defined(_CMU_CALCTRL_CALTOP_MASK)
291 EFM_ASSERT(cycles <= (_CMU_CALCTRL_CALTOP_MASK
292 >> _CMU_CALCTRL_CALTOP_SHIFT));
293 #elif defined(_CMU_CALTOP_CALTOP_MASK)
294 EFM_ASSERT(cycles <= (_CMU_CALTOP_CALTOP_MASK
295 >> _CMU_CALTOP_CALTOP_SHIFT));
296 #endif
297
298 CMU_CalibrateConfig(cycles, cmuSelect_HCLK, ref);
299 CMU_CalibrateStart();
300 return CMU_CalibrateCountGet();
301 }
302
303 /***************************************************************************//**
304 * @brief
305 * Configure clock calibration.
306 *
307 * @details
308 * Configure a calibration for a selectable clock source against another
309 * selectable reference clock.
310 * Refer to the reference manual, CMU chapter, for further details.
311 *
312 * @note
313 * After configuration, a call to @ref CMU_CalibrateStart() is required, and
314 * the resulting calibration value can be read with the
315 * @ref CMU_CalibrateCountGet() function call.
316 *
317 * @param[in] downCycles
318 * The number of downSel clock cycles to run calibration. Increasing this
319 * number increases precision, but the calibration will take more time.
320 *
321 * @param[in] downSel
322 * The clock which will be counted down downCycles cycles.
323 *
324 * @param[in] upSel
325 * The reference clock, the number of cycles generated by this clock will
326 * be counted and added up, the result can be given with the
327 * @ref CMU_CalibrateCountGet() function call.
328 ******************************************************************************/
CMU_CalibrateConfig(uint32_t downCycles,CMU_Select_TypeDef downSel,CMU_Select_TypeDef upSel)329 void CMU_CalibrateConfig(uint32_t downCycles, CMU_Select_TypeDef downSel,
330 CMU_Select_TypeDef upSel)
331 {
332 // Keep untouched configuration settings
333 uint32_t calCtrl = CMU->CALCTRL
334 & ~(_CMU_CALCTRL_UPSEL_MASK
335 | _CMU_CALCTRL_DOWNSEL_MASK
336 #if defined(_CMU_CALCTRL_CALTOP_MASK)
337 | _CMU_CALCTRL_CALTOP_MASK
338 #endif
339 );
340
341 // Check for cycle count overflow
342 #if defined(_CMU_CALCTRL_CALTOP_MASK)
343 EFM_ASSERT(downCycles <= (_CMU_CALCTRL_CALTOP_MASK
344 >> _CMU_CALCTRL_CALTOP_SHIFT));
345 calCtrl |= downCycles;
346 #elif defined(_CMU_CALTOP_CALTOP_MASK)
347 EFM_ASSERT(downCycles <= (_CMU_CALTOP_CALTOP_MASK >> _CMU_CALTOP_CALTOP_SHIFT));
348 CMU->CALTOP = downCycles << _CMU_CALTOP_CALTOP_SHIFT;
349 #endif
350
351 // Set down counting clock source selector
352 switch (downSel) {
353 case cmuSelect_HCLK:
354 calCtrl |= CMU_CALCTRL_DOWNSEL_HCLK;
355 break;
356
357 case cmuSelect_PRS:
358 calCtrl |= CMU_CALCTRL_DOWNSEL_PRS;
359 break;
360
361 case cmuSelect_HFXO:
362 calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO;
363 break;
364
365 case cmuSelect_LFXO:
366 calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO;
367 break;
368
369 case cmuSelect_HFRCODPLL:
370 calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCODPLL;
371 break;
372
373 #if defined(HFRCOEM23_PRESENT)
374 case cmuSelect_HFRCOEM23:
375 calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCOEM23;
376 break;
377 #endif
378
379 case cmuSelect_FSRCO:
380 calCtrl |= CMU_CALCTRL_DOWNSEL_FSRCO;
381 break;
382
383 case cmuSelect_LFRCO:
384 #if defined(PLFRCO_PRESENT)
385 case cmuSelect_PLFRCO:
386 #endif
387 calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO;
388 break;
389
390 case cmuSelect_ULFRCO:
391 calCtrl |= CMU_CALCTRL_DOWNSEL_ULFRCO;
392 break;
393
394 case cmuSelect_Disabled:
395 break;
396
397 default:
398 EFM_ASSERT(false);
399 break;
400 }
401
402 // Set up counting clock source selector
403 switch (upSel) {
404 case cmuSelect_PRS:
405 calCtrl |= CMU_CALCTRL_UPSEL_PRS;
406 break;
407
408 case cmuSelect_HFXO:
409 calCtrl |= CMU_CALCTRL_UPSEL_HFXO;
410 break;
411
412 case cmuSelect_LFXO:
413 calCtrl |= CMU_CALCTRL_UPSEL_LFXO;
414 break;
415
416 case cmuSelect_HFRCODPLL:
417 calCtrl |= CMU_CALCTRL_UPSEL_HFRCODPLL;
418 break;
419
420 #if defined(HFRCOEM23_PRESENT)
421 case cmuSelect_HFRCOEM23:
422 calCtrl |= CMU_CALCTRL_UPSEL_HFRCOEM23;
423 break;
424 #endif
425
426 case cmuSelect_FSRCO:
427 calCtrl |= CMU_CALCTRL_UPSEL_FSRCO;
428 break;
429
430 case cmuSelect_LFRCO:
431 #if defined(PLFRCO_PRESENT)
432 case cmuSelect_PLFRCO:
433 #endif
434 calCtrl |= CMU_CALCTRL_UPSEL_LFRCO;
435 break;
436
437 case cmuSelect_ULFRCO:
438 calCtrl |= CMU_CALCTRL_UPSEL_ULFRCO;
439 break;
440
441 case cmuSelect_Disabled:
442 break;
443
444 default:
445 EFM_ASSERT(false);
446 break;
447 }
448
449 CMU->CALCTRL = calCtrl;
450 }
451
452 /***************************************************************************//**
453 * @brief
454 * Get calibration count value.
455 *
456 * @note
457 * If continuous calibration mode is active, calibration busy will almost
458 * always be off, and reading the value will be just needed, where the normal
459 * case would be that this function call has been triggered by the CALRDY
460 * interrupt flag.
461 *
462 * @return
463 * Calibration count, the number of UPSEL clocks (see @ref CMU_CalibrateConfig())
464 * in the period of DOWNSEL oscillator clock cycles configured by a previous
465 * write operation to CMU->CALCNT.
466 ******************************************************************************/
CMU_CalibrateCountGet(void)467 uint32_t CMU_CalibrateCountGet(void)
468 {
469 // Wait until calibration completes, UNLESS continuous calibration mode is on
470 if ((CMU->CALCTRL & CMU_CALCTRL_CONT) == 0UL) {
471 // Wait until calibration completes
472 while ((CMU->STATUS & CMU_STATUS_CALRDY) == 0UL) {
473 }
474 }
475 return CMU->CALCNT;
476 }
477
478 /***************************************************************************//**
479 * @brief
480 * Direct a clock to a GPIO pin.
481 *
482 * @param[in] clkNo
483 * Selects between CLKOUT0, CLKOUT1 or CLKOUT2 outputs. Use values 0,1or 2.
484 *
485 * @param[in] sel
486 * Select clock source.
487 *
488 * @param[in] clkDiv
489 * Select a clock divisor (1..32). Only applicable when cmuSelect_EXPCLK is
490 * slexted as clock source.
491 *
492 * @param[in] port
493 * GPIO port.
494 *
495 * @param[in] pin
496 * GPIO pin.
497 *
498 * @note
499 * Refer to the reference manual and the datasheet for details on which
500 * GPIO port/pins that are available.
501 ******************************************************************************/
CMU_ClkOutPinConfig(uint32_t clkNo,CMU_Select_TypeDef sel,CMU_ClkDiv_TypeDef clkDiv,GPIO_Port_TypeDef port,unsigned int pin)502 void CMU_ClkOutPinConfig(uint32_t clkNo,
503 CMU_Select_TypeDef sel,
504 CMU_ClkDiv_TypeDef clkDiv,
505 GPIO_Port_TypeDef port,
506 unsigned int pin)
507 {
508 uint32_t tmp = 0U, mask;
509
510 EFM_ASSERT(clkNo <= 2U);
511 EFM_ASSERT(clkDiv <= 32U);
512 EFM_ASSERT(port <= 3U);
513 EFM_ASSERT(pin <= 15U);
514
515 switch (sel) {
516 case cmuSelect_Disabled:
517 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_DISABLED;
518 break;
519
520 case cmuSelect_FSRCO:
521 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_FSRCO;
522 break;
523
524 case cmuSelect_HFXO:
525 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_HFXO;
526 break;
527
528 case cmuSelect_HFRCODPLL:
529 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_HFRCODPLL;
530 break;
531
532 #if defined(HFRCOEM23_PRESENT)
533 case cmuSelect_HFRCOEM23:
534 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_HFRCOEM23;
535 break;
536 #endif
537
538 case cmuSelect_EXPCLK:
539 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_HFEXPCLK;
540 break;
541
542 case cmuSelect_LFXO:
543 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_LFXO;
544 break;
545
546 case cmuSelect_LFRCO:
547 #if defined(PLFRCO_PRESENT)
548 case cmuSelect_PLFRCO:
549 #endif
550 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_LFRCO;
551 break;
552
553 case cmuSelect_ULFRCO:
554 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_ULFRCO;
555 break;
556
557 case cmuSelect_HCLK:
558 tmp = CMU_EXPORTCLKCTRL_CLKOUTSEL0_HCLK;
559 break;
560
561 default:
562 EFM_ASSERT(false);
563 break;
564 }
565
566 mask = _CMU_EXPORTCLKCTRL_CLKOUTSEL0_MASK
567 << (clkNo * _CMU_EXPORTCLKCTRL_CLKOUTSEL1_SHIFT);
568 tmp <<= clkNo * _CMU_EXPORTCLKCTRL_CLKOUTSEL1_SHIFT;
569
570 if (sel == cmuSelect_EXPCLK) {
571 tmp |= (clkDiv - 1U) << _CMU_EXPORTCLKCTRL_PRESC_SHIFT;
572 mask |= _CMU_EXPORTCLKCTRL_PRESC_MASK;
573 }
574
575 CMU->EXPORTCLKCTRL = (CMU->EXPORTCLKCTRL & ~mask) | tmp;
576
577 if (sel == cmuSelect_Disabled) {
578 GPIO->CMUROUTE_CLR.ROUTEEN = GPIO_CMU_ROUTEEN_CLKOUT0PEN << clkNo;
579 GPIO_PinModeSet(port, pin, gpioModeDisabled, 0);
580 } else {
581 GPIO->CMUROUTE_SET.ROUTEEN = GPIO_CMU_ROUTEEN_CLKOUT0PEN << clkNo;
582 if (clkNo == 0U) {
583 GPIO->CMUROUTE.CLKOUT0ROUTE = (port << _GPIO_CMU_CLKOUT0ROUTE_PORT_SHIFT)
584 | (pin << _GPIO_CMU_CLKOUT0ROUTE_PIN_SHIFT);
585 } else if (clkNo == 1) {
586 GPIO->CMUROUTE.CLKOUT1ROUTE = (port << _GPIO_CMU_CLKOUT1ROUTE_PORT_SHIFT)
587 | (pin << _GPIO_CMU_CLKOUT1ROUTE_PIN_SHIFT);
588 } else {
589 GPIO->CMUROUTE.CLKOUT2ROUTE = (port << _GPIO_CMU_CLKOUT2ROUTE_PORT_SHIFT)
590 | (pin << _GPIO_CMU_CLKOUT2ROUTE_PIN_SHIFT);
591 }
592 GPIO_PinModeSet(port, pin, gpioModePushPull, 0);
593 }
594 }
595
596 /***************************************************************************//**
597 * @brief
598 * Get clock divisor.
599 *
600 * @param[in] clock
601 * Clock point to get divisor for. Notice that not all clock points
602 * have a divisors. Please refer to CMU overview in reference manual.
603 *
604 * @return
605 * The current clock point divisor. 1 is returned
606 * if @p clock specifies a clock point without divisor.
607 ******************************************************************************/
CMU_ClockDivGet(CMU_Clock_TypeDef clock)608 CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock)
609 {
610 uint32_t ret = 0U;
611
612 switch (clock) {
613 case cmuClock_HCLK:
614 case cmuClock_CORE:
615 ret = (CMU->SYSCLKCTRL & _CMU_SYSCLKCTRL_HCLKPRESC_MASK)
616 >> _CMU_SYSCLKCTRL_HCLKPRESC_SHIFT;
617 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
618 if (ret == 2U ) { // Unused value, illegal prescaler
619 EFM_ASSERT(false);
620 }
621 #elif (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
622 if (!((ret == _CMU_SYSCLKCTRL_HCLKPRESC_DIV1)
623 || (ret == _CMU_SYSCLKCTRL_HCLKPRESC_DIV2)
624 || (ret == _CMU_SYSCLKCTRL_HCLKPRESC_DIV4)
625 || (ret == _CMU_SYSCLKCTRL_HCLKPRESC_DIV8)
626 || (ret == _CMU_SYSCLKCTRL_HCLKPRESC_DIV16))) {
627 // Illegal prescaler
628 EFM_ASSERT(false);
629 }
630 #endif
631 break;
632
633 #if defined(_CMU_TRACECLKCTRL_PRESC_MASK)
634 case cmuClock_TRACECLK:
635 ret = (CMU->TRACECLKCTRL & _CMU_TRACECLKCTRL_PRESC_MASK)
636 >> _CMU_TRACECLKCTRL_PRESC_SHIFT;
637 if (!((ret == _CMU_TRACECLKCTRL_PRESC_DIV1)
638 || (ret == _CMU_TRACECLKCTRL_PRESC_DIV2)
639 #if defined(_CMU_TRACECLKCTRL_PRESC_DIV3)
640 || (ret == _CMU_TRACECLKCTRL_PRESC_DIV3)
641 #endif
642 || (ret == _CMU_TRACECLKCTRL_PRESC_DIV4))) {
643 // Illegal prescaler
644 EFM_ASSERT(false);
645 }
646 break;
647 #endif
648
649 case cmuClock_EXPCLK:
650 ret = (CMU->EXPORTCLKCTRL & _CMU_EXPORTCLKCTRL_PRESC_MASK)
651 >> _CMU_EXPORTCLKCTRL_PRESC_SHIFT;
652 break;
653
654 case cmuClock_PCLK:
655 ret = (CMU->SYSCLKCTRL & _CMU_SYSCLKCTRL_PCLKPRESC_MASK)
656 >> _CMU_SYSCLKCTRL_PCLKPRESC_SHIFT;
657 break;
658
659 default:
660 break;
661 }
662 return 1U + ret;
663 }
664
665 /***************************************************************************//**
666 * @brief
667 * Set clock divisor.
668 *
669 * @param[in] clock
670 * Clock point to set divisor for. Notice that not all clock points
671 * have a divisor, please refer to CMU overview in the reference
672 * manual.
673 *
674 * @param[in] div
675 * The clock divisor to use.
676 ******************************************************************************/
CMU_ClockDivSet(CMU_Clock_TypeDef clock,CMU_ClkDiv_TypeDef div)677 void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)
678 {
679 #if (defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
680 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) \
681 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
682 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)) \
683 && defined(CoreDebug_DEMCR_TRCENA_Msk)
684 bool restoreTrace;
685 #endif
686
687 switch (clock) {
688 case cmuClock_HCLK:
689 case cmuClock_CORE:
690 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
691 EFM_ASSERT((div == 1U) || (div == 2U) || (div == 4U));
692 #elif (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
693 EFM_ASSERT((div == 1U) || (div == 2U) || (div == 4U)
694 || (div == 8U) || (div == 16U));
695 #endif
696
697 // Set max wait-states and PCLK divisor while changing core clock
698 waitStateMax();
699 pclkDivMax();
700 #if ((defined(CMU_SYSCLKCTRL_RHCLKPRESC)) \
701 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
702 // Set largest prescaler for radio clock tree
703 rhclkPrescMax();
704 #endif
705
706 // Set new divisor
707 CMU->SYSCLKCTRL = (CMU->SYSCLKCTRL & ~_CMU_SYSCLKCTRL_HCLKPRESC_MASK)
708 | ((div - 1U) << _CMU_SYSCLKCTRL_HCLKPRESC_SHIFT);
709
710 // Update CMSIS core clock variable and set optimum wait-states
711 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
712
713 // Set optimal PCLK divisor
714 pclkDivOptimize();
715 #if (defined(CMU_SYSCLKCTRL_RHCLKPRESC) \
716 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
717 // Set optimal RHCLK prescaler
718 rhclkPrescOptimize();
719 #endif
720 break;
721
722 #if defined(_CMU_TRACECLKCTRL_PRESC_MASK)
723 case cmuClock_TRACECLK:
724 #if (defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
725 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) \
726 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
727 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)) \
728 && defined(CoreDebug_DEMCR_TRCENA_Msk)
729 restoreTrace = CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk;
730 if (restoreTrace) {
731 CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
732 }
733 #endif
734 #if defined(_CMU_TRACECLKCTRL_PRESC_DIV3)
735 EFM_ASSERT((div == 1U) || (div == 2U) || (div == 3U) || (div == 4U));
736 #else
737 EFM_ASSERT((div == 1U) || (div == 2U) || (div == 4U));
738 #endif
739 CMU->TRACECLKCTRL = (CMU->TRACECLKCTRL & ~_CMU_TRACECLKCTRL_PRESC_MASK)
740 | ((div - 1U) << _CMU_TRACECLKCTRL_PRESC_SHIFT);
741 #if (defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
742 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) \
743 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
744 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)) \
745 && defined(CoreDebug_DEMCR_TRCENA_Msk)
746 if (restoreTrace) {
747 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
748 }
749 #endif
750 break;
751 #endif
752
753 case cmuClock_EXPCLK:
754 EFM_ASSERT((div >= 1U) && (div <= 32U));
755 CMU->EXPORTCLKCTRL = (CMU->EXPORTCLKCTRL & ~_CMU_EXPORTCLKCTRL_PRESC_MASK)
756 | ((div - 1U) << _CMU_EXPORTCLKCTRL_PRESC_SHIFT);
757 break;
758
759 case cmuClock_PCLK:
760 EFM_ASSERT((div == 1U) || (div == 2U));
761 CMU->SYSCLKCTRL = (CMU->SYSCLKCTRL & ~_CMU_SYSCLKCTRL_PCLKPRESC_MASK)
762 | ((div - 1U) << _CMU_SYSCLKCTRL_PCLKPRESC_SHIFT);
763 break;
764
765 default:
766 EFM_ASSERT(false);
767 break;
768 }
769 }
770
771 #if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
772 /***************************************************************************//**
773 * @brief
774 * Enable/disable a clock.
775 *
776 * @details
777 * Module clocks sre disabled after reset. If a module clock is disabled, the
778 * registers of that module are not accessible and accessing such registers
779 * will hardfault the Cortex core.
780 *
781 * @param[in] clock
782 * The clock to enable/disable.
783 *
784 * @param[in] enable
785 * @li true - enable specified clock.
786 * @li false - disable specified clock.
787 ******************************************************************************/
CMU_ClockEnable(CMU_Clock_TypeDef clock,bool enable)788 void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
789 {
790 volatile uint32_t *reg = NULL;
791 uint32_t bit;
792
793 /* Identify the enable register. */
794 if (((unsigned)clock >> CMU_EN_REG_POS) == CMU_NO_EN_REG) {
795 EFM_ASSERT(false); /* No enable for this clock. */
796 } else if (((unsigned)clock >> CMU_EN_REG_POS) == CMU_CLKEN0_EN_REG) {
797 reg = &CMU->CLKEN0;
798 } else if (((unsigned)clock >> CMU_EN_REG_POS) == CMU_CLKEN1_EN_REG) {
799 reg = &CMU->CLKEN1;
800 } else {
801 #if defined(CRYPTOACC_PRESENT)
802 reg = &CMU->CRYPTOACCCLKCTRL;
803 #else
804 // No register to enable clock. Possible hard fault exception.
805 EFM_ASSERT(false);
806 #endif
807 }
808
809 /* Get the bit position used to enable/disable. */
810 bit = ((unsigned)clock >> CMU_EN_BIT_POS) & CMU_EN_BIT_MASK;
811
812 /* Set/clear bit as requested. */
813 BUS_RegBitWrite(reg, bit, (uint32_t)enable);
814 }
815 #endif // (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
816
817 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
818 /***************************************************************************//**
819 * @brief
820 * Get clock frequency for a clock point.
821 *
822 * @param[in] clock
823 * Clock point to fetch frequency for.
824 *
825 * @return
826 * The current frequency in Hz.
827 ******************************************************************************/
CMU_ClockFreqGet(CMU_Clock_TypeDef clock)828 uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
829 {
830 uint32_t ret = 0U;
831
832 switch (clock) {
833 case cmuClock_SYSCLK:
834 ret = SystemSYSCLKGet();
835 break;
836
837 case cmuClock_CORE:
838 case cmuClock_HCLK:
839 case cmuClock_LDMA:
840 case cmuClock_GPCRC:
841 ret = SystemHCLKGet();
842 break;
843
844 case cmuClock_EXPCLK:
845 ret = SystemSYSCLKGet() / CMU_ClockDivGet(cmuClock_EXPCLK);
846 break;
847
848 case cmuClock_I2C1:
849 case cmuClock_PRS:
850 case cmuClock_PCLK:
851 case cmuClock_GPIO:
852 case cmuClock_USART0:
853 case cmuClock_USART1:
854 case cmuClock_USART2:
855 ret = SystemHCLKGet() / CMU_ClockDivGet(cmuClock_PCLK);
856 break;
857
858 case cmuClock_I2C0:
859 case cmuClock_LSPCLK:
860 ret = SystemHCLKGet() / CMU_ClockDivGet(cmuClock_PCLK) / 2U;
861 break;
862
863 #if defined(IADC_PRESENT)
864 case cmuClock_IADC0:
865 case cmuClock_IADCCLK:
866 iadcClkGet(&ret, NULL);
867 break;
868 #endif
869
870 case cmuClock_TIMER0:
871 case cmuClock_TIMER1:
872 case cmuClock_TIMER2:
873 case cmuClock_TIMER3:
874 case cmuClock_EM01GRPACLK:
875 em01GrpaClkGet(&ret, NULL);
876 break;
877
878 case cmuClock_SYSTICK:
879 sysTickClkGet(&ret, NULL);
880 break;
881
882 case cmuClock_LETIMER0:
883 case cmuClock_EM23GRPACLK:
884 em23GrpaClkGet(&ret, NULL);
885 break;
886
887 case cmuClock_BURTC:
888 case cmuClock_EM4GRPACLK:
889 em4GrpaClkGet(&ret, NULL);
890 break;
891
892 case cmuClock_WDOG0:
893 case cmuClock_WDOG0CLK:
894 wdog0ClkGet(&ret, NULL);
895 break;
896
897 case cmuClock_WDOG1:
898 case cmuClock_WDOG1CLK:
899 wdog1ClkGet(&ret, NULL);
900 break;
901
902 case cmuClock_DPLLREFCLK:
903 dpllRefClkGet(&ret, NULL);
904 break;
905
906 case cmuClock_TRACECLK:
907 traceClkGet(&ret, NULL);
908 break;
909
910 case cmuClock_RTCC:
911 case cmuClock_RTCCCLK:
912 rtccClkGet(&ret, NULL);
913 break;
914
915 default:
916 EFM_ASSERT(false);
917 break;
918 }
919 return ret;
920 }
921 #endif // defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
922
923 #if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
924 /***************************************************************************//**
925 * @brief
926 * Get clock frequency for a clock point.
927 *
928 * @param[in] clock
929 * Clock point to fetch frequency for.
930 *
931 * @return
932 * The current frequency in Hz.
933 ******************************************************************************/
CMU_ClockFreqGet(CMU_Clock_TypeDef clock)934 uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
935 {
936 uint32_t ret = 0U;
937 uint32_t freq = 0U;
938
939 switch (clock) {
940 case cmuClock_SYSCLK:
941 ret = SystemSYSCLKGet();
942 break;
943
944 case cmuClock_HCLK:
945 case cmuClock_CORE:
946 case cmuClock_ICACHE:
947 case cmuClock_MSC:
948 case cmuClock_LDMA:
949 case cmuClock_SMU:
950 #if defined(RADIOAES_PRESENT)
951 case cmuClock_RADIOAES:
952 #endif
953 #if defined(CRYPTOACC_PRESENT)
954 case cmuClock_CRYPTOACC:
955 case cmuClock_CRYPTOAES:
956 case cmuClock_CRYPTOPK:
957 #endif
958 #if defined(MVP_PRESENT)
959 case cmuClock_MVP:
960 #endif
961 ret = SystemHCLKGet();
962 break;
963
964 case cmuClock_EXPCLK:
965 ret = SystemSYSCLKGet() / CMU_ClockDivGet(cmuClock_EXPCLK);
966 break;
967
968 case cmuClock_PCLK:
969 #if defined(USART_PRESENT)
970 case cmuClock_USART0:
971 #if USART_COUNT > 1
972 case cmuClock_USART1:
973 #endif
974 #endif
975 case cmuClock_I2C1:
976 case cmuClock_PRS:
977 case cmuClock_GPIO:
978 case cmuClock_GPCRC:
979 case cmuClock_LDMAXBAR:
980 case cmuClock_SYSCFG:
981 case cmuClock_DCDC:
982 case cmuClock_BURAM:
983 case cmuClock_DPLL0:
984 ret = SystemHCLKGet() / CMU_ClockDivGet(cmuClock_PCLK);
985 break;
986
987 case cmuClock_LSPCLK:
988 case cmuClock_I2C0:
989 case cmuClock_AMUXCP0:
990 #if defined(ACMP_PRESENT)
991 case cmuClock_ACMP0:
992 #if ACMP_COUNT > 1
993 case cmuClock_ACMP1:
994 #endif
995 #endif
996 ret = SystemHCLKGet() / CMU_ClockDivGet(cmuClock_PCLK) / 2U;
997 break;
998
999 case cmuClock_TRACECLK:
1000 traceClkGet(&freq, NULL);
1001 ret = freq / CMU_ClockDivGet(cmuClock_TRACECLK);
1002 break;
1003
1004 case cmuClock_TIMER0:
1005 case cmuClock_TIMER1:
1006 case cmuClock_TIMER2:
1007 case cmuClock_TIMER3:
1008 #if TIMER_COUNT > 4
1009 case cmuClock_TIMER4:
1010 #endif
1011 #if TIMER_COUNT > 7
1012 case cmuClock_TIMER5:
1013 case cmuClock_TIMER6:
1014 case cmuClock_TIMER7:
1015 #endif
1016 #if defined(KEYSCAN_PRESENT)
1017 case cmuClock_KEYSCAN:
1018 #endif
1019 case cmuClock_EM01GRPACLK:
1020 em01GrpaClkGet(&ret, NULL);
1021 break;
1022 #if defined(PDM_PRESENT)
1023 case cmuClock_PDM:
1024 case cmuClock_EM01GRPBCLK:
1025 em01GrpbClkGet(&ret, NULL);
1026 break;
1027 #endif
1028 #if defined(EUART_PRESENT)
1029 case cmuClock_EUART0:
1030 case cmuClock_EUART0CLK:
1031 euart0ClkGet(&ret, NULL);
1032 break;
1033 #endif
1034 #if defined(EUSART_PRESENT) && EUSART_COUNT > 0
1035 case cmuClock_EUSART0:
1036 case cmuClock_EUSART0CLK:
1037 eusart0ClkGet(&ret, NULL);
1038 break;
1039 #if defined(EUSART_PRESENT) && EUSART_COUNT > 1
1040 case cmuClock_EUSART1:
1041 #endif
1042 #if defined(EUSART_PRESENT) && EUSART_COUNT > 2
1043 case cmuClock_EUSART2:
1044 #endif
1045 #if defined(EUSART_PRESENT) && EUSART_COUNT > 3
1046 case cmuClock_EUSART3:
1047 #endif
1048 #if defined(EUSART_PRESENT) && EUSART_COUNT > 4
1049 case cmuClock_EUSART4:
1050 #endif
1051 #if defined(_CMU_EM01GRPCCLKCTRL_MASK)
1052 case cmuClock_EM01GRPCCLK:
1053 em01GrpcClkGet(&ret, NULL);
1054 break;
1055 #endif
1056 #endif
1057
1058 #if defined(IADC_PRESENT)
1059 case cmuClock_IADC0:
1060 case cmuClock_IADCCLK:
1061 iadcClkGet(&ret, NULL);
1062 break;
1063 #endif
1064
1065 case cmuClock_SYSTICK:
1066 sysTickClkGet(&ret, NULL);
1067 break;
1068
1069 case cmuClock_LETIMER0:
1070 case cmuClock_EM23GRPACLK:
1071 #if defined(LESENSE_PRESENT)
1072 case cmuClock_LESENSE:
1073 case cmuClock_LESENSECLK:
1074 #endif
1075 em23GrpaClkGet(&ret, NULL);
1076 break;
1077
1078 case cmuClock_WDOG0:
1079 case cmuClock_WDOG0CLK:
1080 wdog0ClkGet(&ret, NULL);
1081 break;
1082 #if WDOG_COUNT > 1
1083 case cmuClock_WDOG1:
1084 case cmuClock_WDOG1CLK:
1085 wdog1ClkGet(&ret, NULL);
1086 break;
1087 #endif
1088 #if defined(RTCC_PRESENT)
1089 case cmuClock_RTCC:
1090 case cmuClock_RTCCCLK:
1091 rtccClkGet(&ret, NULL);
1092 break;
1093 #endif
1094 #if defined(SYSRTC_PRESENT)
1095 case cmuClock_SYSRTC:
1096 case cmuClock_SYSRTCCLK:
1097 sysrtcClkGet(&ret, NULL);
1098 break;
1099 #endif
1100 #if defined(LCD_PRESENT)
1101 case cmuClock_LCD:
1102 case cmuClock_LCDCLK:
1103 lcdClkGet(&ret, NULL);
1104 break;
1105 #endif
1106 #if defined(VDAC_PRESENT)
1107 case cmuClock_VDAC0:
1108 case cmuClock_VDAC0CLK:
1109 vdac0ClkGet(&ret, NULL);
1110 break;
1111 #if (VDAC_COUNT > 1)
1112 case cmuClock_VDAC1:
1113 case cmuClock_VDAC1CLK:
1114 vdac1ClkGet(&ret, NULL);
1115 break;
1116 #endif
1117 #endif /* VDAC_PRESENT */
1118 #if defined(PCNT_PRESENT)
1119 case cmuClock_PCNT0:
1120 case cmuClock_PCNT0CLK:
1121 pcnt0ClkGet(&ret, NULL);
1122 break;
1123 #endif
1124 #if defined(LESENSE_PRESENT)
1125 case cmuClock_LESENSEHFCLK:
1126 lesenseHFClkGet(&ret, NULL);
1127 break;
1128 #endif
1129 case cmuClock_BURTC:
1130 case cmuClock_EM4GRPACLK:
1131 #if defined(ETAMPDET_PRESENT)
1132 case cmuClock_ETAMPDET:
1133 #endif
1134 em4GrpaClkGet(&ret, NULL);
1135 break;
1136
1137 #if defined(USB_PRESENT)
1138 case cmuClock_USB:
1139 usbClkGet(&ret, NULL);
1140 break;
1141 #endif
1142
1143 default:
1144 EFM_ASSERT(false);
1145 break;
1146 }
1147
1148 return ret;
1149 }
1150 #endif // (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
1151
1152 /***************************************************************************//**
1153 * @brief
1154 * Get currently selected reference clock used for a clock branch.
1155 *
1156 * @param[in] clock
1157 * Clock branch to fetch selected ref. clock for.
1158 *
1159 * @return
1160 * Reference clock used for clocking selected branch, #cmuSelect_Error if
1161 * invalid @p clock provided.
1162 ******************************************************************************/
CMU_ClockSelectGet(CMU_Clock_TypeDef clock)1163 CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock)
1164 {
1165 CMU_Select_TypeDef ret = cmuSelect_Error;
1166
1167 switch (clock) {
1168 // -----------------------------------------------------------------------------
1169 case cmuClock_SYSCLK:
1170 switch (CMU->SYSCLKCTRL & _CMU_SYSCLKCTRL_CLKSEL_MASK) {
1171 case CMU_SYSCLKCTRL_CLKSEL_HFRCODPLL:
1172 ret = cmuSelect_HFRCODPLL;
1173 break;
1174
1175 case CMU_SYSCLKCTRL_CLKSEL_HFXO:
1176 ret = cmuSelect_HFXO;
1177 break;
1178
1179 case CMU_SYSCLKCTRL_CLKSEL_CLKIN0:
1180 ret = cmuSelect_CLKIN0;
1181 break;
1182
1183 case CMU_SYSCLKCTRL_CLKSEL_FSRCO:
1184 ret = cmuSelect_FSRCO;
1185 break;
1186
1187 #if defined(RFFPLL_PRESENT)
1188 case CMU_SYSCLKCTRL_CLKSEL_RFFPLL0SYS:
1189 ret = cmuSelect_RFFPLLSYS;
1190 break;
1191 #endif
1192 default:
1193 ret = cmuSelect_Error;
1194 EFM_ASSERT(false);
1195 break;
1196 }
1197 break;
1198
1199 // -----------------------------------------------------------------------------
1200 #if defined(IADC_PRESENT)
1201 case cmuClock_IADC0:
1202 case cmuClock_IADCCLK:
1203 iadcClkGet(NULL, &ret);
1204 break;
1205 #endif
1206 // -----------------------------------------------------------------------------
1207 case cmuClock_TIMER0:
1208 case cmuClock_TIMER1:
1209 case cmuClock_TIMER2:
1210 case cmuClock_TIMER3:
1211 #if TIMER_COUNT > 4
1212 case cmuClock_TIMER4:
1213 #endif
1214 #if TIMER_COUNT > 7
1215 case cmuClock_TIMER5:
1216 case cmuClock_TIMER6:
1217 case cmuClock_TIMER7:
1218 #endif
1219 #if defined(KEYSCAN_PRESENT)
1220 case cmuClock_KEYSCAN:
1221 #endif
1222 case cmuClock_EM01GRPACLK:
1223 em01GrpaClkGet(NULL, &ret);
1224 break;
1225
1226 // -----------------------------------------------------------------------------
1227 case cmuClock_SYSTICK:
1228 sysTickClkGet(NULL, &ret);
1229 break;
1230
1231 case cmuClock_LETIMER0:
1232 case cmuClock_EM23GRPACLK:
1233 #if defined(LESENSE_PRESENT)
1234 case cmuClock_LESENSE:
1235 case cmuClock_LESENSECLK:
1236 #endif
1237 em23GrpaClkGet(NULL, &ret);
1238 break;
1239
1240 // -----------------------------------------------------------------------------
1241 case cmuClock_BURTC:
1242 case cmuClock_EM4GRPACLK:
1243 #if defined(ETAMPDET_PRESENT)
1244 case cmuClock_ETAMPDET:
1245 #endif
1246 em4GrpaClkGet(NULL, &ret);
1247 break;
1248
1249 // -----------------------------------------------------------------------------
1250 #if defined(_CMU_EM01GRPBCLKCTRL_CLKSEL_MASK)
1251 case cmuClock_PDMREF:
1252 case cmuClock_EM01GRPBCLK:
1253 em01GrpbClkGet(NULL, &ret);
1254 break;
1255 #endif
1256
1257 // -----------------------------------------------------------------------------
1258 case cmuClock_WDOG0:
1259 case cmuClock_WDOG0CLK:
1260 wdog0ClkGet(NULL, &ret);
1261 break;
1262
1263 // -----------------------------------------------------------------------------
1264 #if defined(_CMU_WDOG1CLKCTRL_CLKSEL_MASK)
1265 case cmuClock_WDOG1:
1266 case cmuClock_WDOG1CLK:
1267 wdog1ClkGet(NULL, &ret);
1268 break;
1269 #endif
1270
1271 // -----------------------------------------------------------------------------
1272 case cmuClock_DPLLREFCLK:
1273 dpllRefClkGet(NULL, &ret);
1274 break;
1275
1276 // -----------------------------------------------------------------------------
1277 #if defined(_CMU_TRACECLKCTRL_CLKSEL_MASK)
1278 case cmuClock_TRACECLK:
1279 traceClkGet(NULL, &ret);
1280 break;
1281 #endif
1282
1283 // -----------------------------------------------------------------------------
1284 #if defined(_CMU_EUART0CLKCTRL_CLKSEL_MASK)
1285 case cmuClock_EUART0:
1286 case cmuClock_EUART0CLK:
1287 euart0ClkGet(NULL, &ret);
1288 break;
1289 #elif defined(EUSART_PRESENT)
1290 case cmuClock_EUSART0:
1291 case cmuClock_EUSART0CLK:
1292 eusart0ClkGet(NULL, &ret);
1293 break;
1294
1295 #if defined(EUSART_PRESENT) && EUSART_COUNT > 1
1296 case cmuClock_EUSART1:
1297 #endif
1298 #if defined(EUSART_PRESENT) && EUSART_COUNT > 2
1299 case cmuClock_EUSART2:
1300 #endif
1301 #if defined(EUSART_PRESENT) && EUSART_COUNT > 3
1302 case cmuClock_EUSART3:
1303 #endif
1304 #if defined(EUSART_PRESENT) && EUSART_COUNT > 4
1305 case cmuClock_EUSART4:
1306 #endif
1307 #if defined(_CMU_EM01GRPCCLKCTRL_MASK)
1308 case cmuClock_EM01GRPCCLK:
1309 em01GrpcClkGet(NULL, &ret);
1310 break;
1311 #endif
1312 #endif
1313
1314 // -----------------------------------------------------------------------------
1315 #if defined(RTCC_PRESENT)
1316 case cmuClock_RTCC:
1317 case cmuClock_RTCCCLK:
1318 rtccClkGet(NULL, &ret);
1319 break;
1320 #endif
1321 // -----------------------------------------------------------------------------
1322 #if defined(SYSRTC_PRESENT)
1323 case cmuClock_SYSRTC:
1324 case cmuClock_SYSRTCCLK:
1325 sysrtcClkGet(NULL, &ret);
1326 break;
1327 #endif
1328 // -----------------------------------------------------------------------------
1329 #if defined(LCD_PRESENT)
1330 case cmuClock_LCD:
1331 case cmuClock_LCDCLK:
1332 lcdClkGet(NULL, &ret);
1333 break;
1334 #endif
1335 // -----------------------------------------------------------------------------
1336 #if defined(VDAC_PRESENT)
1337 case cmuClock_VDAC0:
1338 case cmuClock_VDAC0CLK:
1339 vdac0ClkGet(NULL, &ret);
1340 break;
1341 #if (VDAC_COUNT > 1)
1342 case cmuClock_VDAC1:
1343 case cmuClock_VDAC1CLK:
1344 vdac1ClkGet(NULL, &ret);
1345 break;
1346 #endif
1347 #endif
1348 // -----------------------------------------------------------------------------
1349 #if defined(PCNT_PRESENT)
1350 case cmuClock_PCNT0:
1351 case cmuClock_PCNT0CLK:
1352 pcnt0ClkGet(NULL, &ret);
1353 break;
1354 #endif
1355 // -----------------------------------------------------------------------------
1356 #if defined(LESENSE_PRESENT)
1357 case cmuClock_LESENSEHFCLK:
1358 lesenseHFClkGet(NULL, &ret);
1359 break;
1360 #endif
1361 // -----------------------------------------------------------------------------
1362 #if defined(USB_PRESENT)
1363 case cmuClock_USB:
1364 usbClkGet(NULL, &ret);
1365 break;
1366 #endif
1367 // -----------------------------------------------------------------------------
1368 default:
1369 EFM_ASSERT(false);
1370 break;
1371 }
1372 return ret;
1373 }
1374
1375 /***************************************************************************//**
1376 * @brief Performs pre-clock-selection operations to initialize the system clock.
1377 *
1378 * @note FOR INTERNAL USE ONLY.
1379 *
1380 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
1381 * the clock is SYSCLK.
1382 ******************************************************************************/
sli_em_cmu_SYSCLKInitPreClockSelect(void)1383 void sli_em_cmu_SYSCLKInitPreClockSelect(void)
1384 {
1385 #if defined(EMU_VSCALE_EM01_PRESENT)
1386 // VSCALE up before changing clock.
1387 EMU_VScaleEM01(emuVScaleEM01_HighPerformance, true);
1388 #endif
1389
1390 // Set max wait-states and PCLK divisor while changing core clock.
1391 waitStateMax();
1392 pclkDivMax();
1393 #if ((defined(CMU_SYSCLKCTRL_RHCLKPRESC)) \
1394 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
1395 // Set largest prescaler for radio clock tree
1396 rhclkPrescMax();
1397 #endif
1398 }
1399
1400 /***************************************************************************//**
1401 * @brief Performs post-clock-selection operations to initialize the system clock.
1402 *
1403 * @note FOR INTERNAL USE ONLY.
1404 *
1405 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
1406 * the clock is SYSCLK.
1407 ******************************************************************************/
sli_em_cmu_SYSCLKInitPostClockSelect(void)1408 void sli_em_cmu_SYSCLKInitPostClockSelect(void)
1409 {
1410 // Update CMSIS core clock variable and set optimum wait-states.
1411 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
1412
1413 #if defined(EMU_VSCALE_EM01_PRESENT)
1414 // Check if possible to downscale VSCALE setting.
1415 EMU_VScaleEM01ByClock(0, true);
1416 #endif
1417
1418 // Set optimal PCLK divisor
1419 pclkDivOptimize();
1420 #if (defined(CMU_SYSCLKCTRL_RHCLKPRESC) \
1421 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
1422 // Set optimal RHCLK prescaler
1423 rhclkPrescOptimize();
1424 #endif
1425 }
1426
1427 /***************************************************************************//**
1428 * @brief Sets the HFXO0 FORCEEN bit.
1429 *
1430 * @note FOR INTERNAL USE ONLY.
1431 *
1432 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
1433 * the clock is SYSCLK and the selected clock source is HFXO.
1434 ******************************************************************************/
sli_em_cmu_HFXOSetForceEnable(void)1435 void sli_em_cmu_HFXOSetForceEnable(void)
1436 {
1437 #if defined(_CMU_CLKEN0_MASK) && defined(CMU_CLKEN0_HFXO0)
1438 CMU->CLKEN0_SET = CMU_CLKEN0_HFXO0;
1439 #endif
1440 HFXO0->CTRL_SET = HFXO_CTRL_FORCEEN;
1441 }
1442
1443 /***************************************************************************//**
1444 * @brief This function will set the SYSCFG->CFGSYSTIC<SYSTICEXTCLKEN> bit.
1445 *
1446 * @note FOR INTERNAL USE ONLY.
1447 *
1448 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
1449 * the clock is SYSTICK.
1450 ******************************************************************************/
sli_em_cmu_SYSTICEXTCLKENSet(void)1451 void sli_em_cmu_SYSTICEXTCLKENSet(void)
1452 {
1453 #if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1454 bool syscfgClkIsOff = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) == 0);
1455 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
1456 #endif
1457
1458 SYSCFG_setSysTicExtClkEnCfgSysTic();
1459
1460 #if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1461 if (syscfgClkIsOff) {
1462 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
1463 }
1464 #endif
1465 }
1466
1467 /***************************************************************************//**
1468 * @brief This function will clear the SYSCFG->CFGSYSTIC<SYSTICEXTCLKEN> bit.
1469 *
1470 * @note FOR INTERNAL USE ONLY.
1471 *
1472 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
1473 * the clock is SYSTICK.
1474 ******************************************************************************/
sli_em_cmu_SYSTICEXTCLKENClear(void)1475 void sli_em_cmu_SYSTICEXTCLKENClear(void)
1476 {
1477 #if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1478 bool syscfgClkIsOff = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) == 0);
1479 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
1480 #endif
1481
1482 SYSCFG_clearSysTicExtClkEnCfgSysTic();
1483
1484 #if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1485 if (syscfgClkIsOff) {
1486 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
1487 }
1488 #endif
1489 }
1490
1491 /***************************************************************************//**
1492 * @brief
1493 * Select reference clock/oscillator used for a clock branch.
1494 *
1495 * @param[in] clock
1496 * Clock branch to select reference clock for.
1497 *
1498 * @param[in] ref
1499 * Reference selected for clocking, please refer to reference manual for
1500 * for details on which reference is available for a specific clock branch.
1501 ******************************************************************************/
CMU_ClockSelectSet(CMU_Clock_TypeDef clock,CMU_Select_TypeDef ref)1502 void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
1503 {
1504 uint32_t tmp = 0U;
1505 bool oscForceEnStatus = false;
1506 #if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
1507 bool syscfgClkIsOff = false;
1508 #endif
1509 #if (defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
1510 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) \
1511 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
1512 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)) \
1513 && defined(CoreDebug_DEMCR_TRCENA_Msk)
1514 bool restoreTrace;
1515 #endif
1516
1517 switch (clock) {
1518 // -----------------------------------------------------------------------------
1519 case cmuClock_SYSCLK:
1520 switch (ref) {
1521 case cmuSelect_HFRCODPLL:
1522 tmp = CMU_SYSCLKCTRL_CLKSEL_HFRCODPLL;
1523 break;
1524
1525 case cmuSelect_HFXO:
1526 tmp = CMU_SYSCLKCTRL_CLKSEL_HFXO;
1527 #if defined(_CMU_CLKEN0_MASK)
1528 #if defined(CMU_CLKEN0_HFXO0)
1529 CMU->CLKEN0_SET = CMU_CLKEN0_HFXO0;
1530 #endif
1531 #endif
1532 // Make sure HFXO is enabled.
1533 oscForceEnStatus = (HFXO0->CTRL & HFXO_CTRL_DISONDEMAND) != 0;
1534 HFXO0->CTRL_SET = HFXO_CTRL_FORCEEN;
1535 break;
1536
1537 case cmuSelect_CLKIN0:
1538 tmp = CMU_SYSCLKCTRL_CLKSEL_CLKIN0;
1539 break;
1540
1541 case cmuSelect_FSRCO:
1542 tmp = CMU_SYSCLKCTRL_CLKSEL_FSRCO;
1543 break;
1544
1545 #if defined(RFFPLL_PRESENT)
1546 case cmuSelect_RFFPLLSYS:
1547 tmp = CMU_SYSCLKCTRL_CLKSEL_RFFPLL0SYS;
1548 break;
1549 #endif
1550
1551 default:
1552 EFM_ASSERT(false);
1553 break;
1554 }
1555
1556 #if defined(EMU_VSCALE_EM01_PRESENT)
1557 // VSCALE up before changing clock.
1558 EMU_VScaleEM01(emuVScaleEM01_HighPerformance, true);
1559 #endif
1560
1561 // Set max wait-states and PCLK divisor while changing core clock.
1562 waitStateMax();
1563 pclkDivMax();
1564 #if ((defined(CMU_SYSCLKCTRL_RHCLKPRESC)) \
1565 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
1566 // Set largest prescaler for radio clock tree
1567 rhclkPrescMax();
1568 #endif
1569
1570 // Switch to selected oscillator.
1571 CMU->SYSCLKCTRL = (CMU->SYSCLKCTRL & ~_CMU_SYSCLKCTRL_CLKSEL_MASK) | tmp;
1572
1573 // Update CMSIS core clock variable and set optimum wait-states.
1574 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
1575
1576 #if defined(EMU_VSCALE_EM01_PRESENT)
1577 // Check if possible to downscale VSCALE setting.
1578 EMU_VScaleEM01ByClock(0, true);
1579 #endif
1580
1581 // Set optimal PCLK divisor
1582 pclkDivOptimize();
1583 #if (defined(CMU_SYSCLKCTRL_RHCLKPRESC) \
1584 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
1585 // Set optimal RHCLK prescaler
1586 rhclkPrescOptimize();
1587 #endif
1588
1589 if (oscForceEnStatus == false) {
1590 switch (ref) {
1591 case cmuSelect_HFXO:
1592 HFXO0->CTRL_CLR = HFXO_CTRL_FORCEEN;
1593 break;
1594
1595 default:
1596 break;
1597 }
1598 }
1599 break;
1600
1601 // -----------------------------------------------------------------------------
1602 #if defined(IADC_PRESENT)
1603 case cmuClock_IADC0:
1604 case cmuClock_IADCCLK:
1605 switch (ref) {
1606 case cmuSelect_EM01GRPACLK:
1607 tmp = CMU_IADCCLKCTRL_CLKSEL_EM01GRPACLK;
1608 break;
1609
1610 #if defined(HFRCOEM23_PRESENT)
1611 case cmuSelect_HFRCOEM23:
1612 tmp = CMU_IADCCLKCTRL_CLKSEL_HFRCOEM23;
1613 break;
1614 #endif
1615
1616 case cmuSelect_FSRCO:
1617 tmp = CMU_IADCCLKCTRL_CLKSEL_FSRCO;
1618 break;
1619
1620 default:
1621 EFM_ASSERT(false);
1622 break;
1623 }
1624 CMU->IADCCLKCTRL = (CMU->IADCCLKCTRL & ~_CMU_IADCCLKCTRL_CLKSEL_MASK)
1625 | tmp;
1626 break;
1627 #endif
1628
1629 // -----------------------------------------------------------------------------
1630 case cmuClock_TIMER0:
1631 case cmuClock_TIMER1:
1632 case cmuClock_TIMER2:
1633 case cmuClock_TIMER3:
1634 #if TIMER_COUNT > 4
1635 case cmuClock_TIMER4:
1636 #endif
1637 #if TIMER_COUNT > 7
1638 case cmuClock_TIMER5:
1639 case cmuClock_TIMER6:
1640 case cmuClock_TIMER7:
1641 #endif
1642 #if defined(KEYSCAN_PRESENT)
1643 case cmuClock_KEYSCAN:
1644 #endif
1645 case cmuClock_EM01GRPACLK:
1646 switch (ref) {
1647 case cmuSelect_HFRCODPLL:
1648 tmp = CMU_EM01GRPACLKCTRL_CLKSEL_HFRCODPLL;
1649 break;
1650
1651 case cmuSelect_HFXO:
1652 tmp = CMU_EM01GRPACLKCTRL_CLKSEL_HFXO;
1653 break;
1654
1655 #if defined(HFRCOEM23_PRESENT)
1656 case cmuSelect_HFRCOEM23:
1657 tmp = CMU_EM01GRPACLKCTRL_CLKSEL_HFRCOEM23;
1658 break;
1659 #endif
1660
1661 case cmuSelect_FSRCO:
1662 tmp = CMU_EM01GRPACLKCTRL_CLKSEL_FSRCO;
1663 break;
1664
1665 #if defined(CMU_EM01GRPACLKCTRL_CLKSEL_HFRCODPLLRT)
1666 case cmuSelect_HFRCODPLLRT:
1667 tmp = CMU_EM01GRPACLKCTRL_CLKSEL_HFRCODPLLRT;
1668 break;
1669 #endif
1670 #if defined(CMU_EM01GRPACLKCTRL_CLKSEL_HFXORT)
1671 case cmuSelect_HFXORT:
1672 tmp = CMU_EM01GRPACLKCTRL_CLKSEL_HFXORT;
1673 break;
1674 #endif
1675 default:
1676 EFM_ASSERT(false);
1677 break;
1678 }
1679 CMU->EM01GRPACLKCTRL = (CMU->EM01GRPACLKCTRL
1680 & ~_CMU_EM01GRPACLKCTRL_CLKSEL_MASK) | tmp;
1681 break;
1682
1683 // -----------------------------------------------------------------------------
1684 case cmuClock_SYSTICK:
1685 switch (ref) {
1686 case cmuSelect_EM23GRPACLK:
1687 case cmuSelect_LFXO:
1688 case cmuSelect_LFRCO:
1689 case cmuSelect_ULFRCO:
1690 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1691 SYSCFG_setSysTicExtClkEnCfgSysTic();
1692 #else
1693 syscfgClkIsOff = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) == 0);
1694 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
1695 SYSCFG_setSysTicExtClkEnCfgSysTic();
1696 if (syscfgClkIsOff) {
1697 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
1698 }
1699 #endif
1700 SysTick->CTRL = (SysTick->CTRL & ~SysTick_CTRL_CLKSOURCE_Msk);
1701 break;
1702 case cmuSelect_HCLK:
1703 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1704 SYSCFG_clearSysTicExtClkEnCfgSysTic();
1705 #else
1706 syscfgClkIsOff = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) == 0);
1707 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
1708 SYSCFG_clearSysTicExtClkEnCfgSysTic();
1709 if (syscfgClkIsOff) {
1710 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
1711 }
1712 #endif
1713 SysTick->CTRL = (SysTick->CTRL | SysTick_CTRL_CLKSOURCE_Msk);
1714 break;
1715 default:
1716 EFM_ASSERT(false);
1717 break;
1718 }
1719 break;
1720
1721 case cmuClock_LETIMER0:
1722 case cmuClock_EM23GRPACLK:
1723 #if defined(LESENSE_PRESENT)
1724 case cmuClock_LESENSE:
1725 case cmuClock_LESENSECLK:
1726 #endif
1727 switch (ref) {
1728 case cmuSelect_LFRCO:
1729 #if defined(PLFRCO_PRESENT)
1730 case cmuSelect_PLFRCO:
1731 #endif
1732 tmp = CMU_EM23GRPACLKCTRL_CLKSEL_LFRCO;
1733 break;
1734
1735 case cmuSelect_LFXO:
1736 tmp = CMU_EM23GRPACLKCTRL_CLKSEL_LFXO;
1737 break;
1738
1739 case cmuSelect_ULFRCO:
1740 tmp = CMU_EM23GRPACLKCTRL_CLKSEL_ULFRCO;
1741 break;
1742
1743 default:
1744 EFM_ASSERT(false);
1745 break;
1746 }
1747 CMU->EM23GRPACLKCTRL = (CMU->EM23GRPACLKCTRL
1748 & ~_CMU_EM23GRPACLKCTRL_CLKSEL_MASK) | tmp;
1749 break;
1750
1751 // -----------------------------------------------------------------------------
1752 case cmuClock_BURTC:
1753 #if defined(ETAMPDET_PRESENT)
1754 case cmuClock_ETAMPDET:
1755 #endif
1756 case cmuClock_EM4GRPACLK:
1757 switch (ref) {
1758 case cmuSelect_LFRCO:
1759 #if defined(PLFRCO_PRESENT)
1760 case cmuSelect_PLFRCO:
1761 #endif
1762 tmp = CMU_EM4GRPACLKCTRL_CLKSEL_LFRCO;
1763 break;
1764
1765 case cmuSelect_LFXO:
1766 tmp = CMU_EM4GRPACLKCTRL_CLKSEL_LFXO;
1767 break;
1768
1769 case cmuSelect_ULFRCO:
1770 tmp = CMU_EM4GRPACLKCTRL_CLKSEL_ULFRCO;
1771 break;
1772
1773 default:
1774 EFM_ASSERT(false);
1775 break;
1776 }
1777 CMU->EM4GRPACLKCTRL = (CMU->EM4GRPACLKCTRL
1778 & ~_CMU_EM4GRPACLKCTRL_CLKSEL_MASK) | tmp;
1779 break;
1780
1781 #if defined(_CMU_EM01GRPBCLKCTRL_CLKSEL_MASK)
1782 // -----------------------------------------------------------------------------
1783 case cmuClock_PDMREF:
1784 case cmuClock_EM01GRPBCLK:
1785 switch (ref) {
1786 case cmuSelect_HFRCODPLL:
1787 tmp = CMU_EM01GRPBCLKCTRL_CLKSEL_HFRCODPLL;
1788 break;
1789
1790 case cmuSelect_HFXO:
1791 tmp = CMU_EM01GRPBCLKCTRL_CLKSEL_HFXO;
1792 break;
1793
1794 case cmuSelect_FSRCO:
1795 tmp = CMU_EM01GRPBCLKCTRL_CLKSEL_FSRCO;
1796 break;
1797
1798 case cmuSelect_CLKIN0:
1799 tmp = CMU_EM01GRPBCLKCTRL_CLKSEL_CLKIN0;
1800 break;
1801
1802 case cmuSelect_HFRCODPLLRT:
1803 tmp = CMU_EM01GRPBCLKCTRL_CLKSEL_HFRCODPLLRT;
1804 break;
1805
1806 case cmuSelect_HFXORT:
1807 tmp = CMU_EM01GRPBCLKCTRL_CLKSEL_HFXORT;
1808 break;
1809
1810 default:
1811 EFM_ASSERT(false);
1812 break;
1813 }
1814 CMU->EM01GRPBCLKCTRL = (CMU->EM01GRPBCLKCTRL
1815 & ~_CMU_EM01GRPBCLKCTRL_CLKSEL_MASK) | tmp;
1816 break;
1817 #endif
1818
1819 // -----------------------------------------------------------------------------
1820 case cmuClock_WDOG0:
1821 case cmuClock_WDOG0CLK:
1822 switch (ref) {
1823 case cmuSelect_LFRCO:
1824 #if defined(PLFRCO_PRESENT)
1825 case cmuSelect_PLFRCO:
1826 #endif
1827 tmp = CMU_WDOG0CLKCTRL_CLKSEL_LFRCO;
1828 break;
1829
1830 case cmuSelect_LFXO:
1831 tmp = CMU_WDOG0CLKCTRL_CLKSEL_LFXO;
1832 break;
1833
1834 case cmuSelect_ULFRCO:
1835 tmp = CMU_WDOG0CLKCTRL_CLKSEL_ULFRCO;
1836 break;
1837
1838 case cmuSelect_HCLKDIV1024:
1839 tmp = CMU_WDOG0CLKCTRL_CLKSEL_HCLKDIV1024;
1840 break;
1841
1842 default:
1843 EFM_ASSERT(false);
1844 break;
1845 }
1846 CMU->WDOG0CLKCTRL = (CMU->WDOG0CLKCTRL & ~_CMU_WDOG0CLKCTRL_CLKSEL_MASK)
1847 | tmp;
1848 break;
1849
1850 #if defined(_CMU_WDOG1CLKCTRL_CLKSEL_MASK)
1851 // -----------------------------------------------------------------------------
1852 case cmuClock_WDOG1:
1853 case cmuClock_WDOG1CLK:
1854 switch (ref) {
1855 case cmuSelect_LFRCO:
1856 #if defined(PLFRCO_PRESENT)
1857 case cmuSelect_PLFRCO:
1858 #endif
1859 tmp = CMU_WDOG1CLKCTRL_CLKSEL_LFRCO;
1860 break;
1861
1862 case cmuSelect_LFXO:
1863 tmp = CMU_WDOG1CLKCTRL_CLKSEL_LFXO;
1864 break;
1865
1866 case cmuSelect_ULFRCO:
1867 tmp = CMU_WDOG1CLKCTRL_CLKSEL_ULFRCO;
1868 break;
1869
1870 case cmuSelect_HCLKDIV1024:
1871 tmp = CMU_WDOG1CLKCTRL_CLKSEL_HCLKDIV1024;
1872 break;
1873
1874 default:
1875 EFM_ASSERT(false);
1876 break;
1877 }
1878 CMU->WDOG1CLKCTRL = (CMU->WDOG1CLKCTRL & ~_CMU_WDOG1CLKCTRL_CLKSEL_MASK)
1879 | tmp;
1880 break;
1881 #endif
1882
1883 // -----------------------------------------------------------------------------
1884 case cmuClock_DPLLREFCLK:
1885 switch (ref) {
1886 case cmuSelect_HFXO:
1887 tmp = CMU_DPLLREFCLKCTRL_CLKSEL_HFXO;
1888 break;
1889
1890 case cmuSelect_LFXO:
1891 tmp = CMU_DPLLREFCLKCTRL_CLKSEL_LFXO;
1892 break;
1893
1894 case cmuSelect_CLKIN0:
1895 tmp = CMU_DPLLREFCLKCTRL_CLKSEL_CLKIN0;
1896 break;
1897
1898 case cmuSelect_Disabled:
1899 tmp = CMU_DPLLREFCLKCTRL_CLKSEL_DISABLED;
1900 break;
1901
1902 default:
1903 EFM_ASSERT(false);
1904 break;
1905 }
1906 CMU->DPLLREFCLKCTRL = (CMU->DPLLREFCLKCTRL
1907 & ~_CMU_DPLLREFCLKCTRL_CLKSEL_MASK) | tmp;
1908 break;
1909
1910 #if defined(_CMU_TRACECLKCTRL_CLKSEL_MASK)
1911 // -----------------------------------------------------------------------------
1912 case cmuClock_TRACECLK:
1913 #if (defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
1914 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) \
1915 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
1916 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)) \
1917 && defined(CoreDebug_DEMCR_TRCENA_Msk)
1918 restoreTrace = CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk;
1919 if (restoreTrace) {
1920 CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
1921 }
1922 #endif
1923 switch (ref) {
1924 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
1925 case cmuSelect_HCLK:
1926 tmp = CMU_TRACECLKCTRL_CLKSEL_HCLK;
1927 break;
1928 #endif
1929
1930 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
1931 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) \
1932 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
1933 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)
1934 case cmuSelect_SYSCLK:
1935 tmp = CMU_TRACECLKCTRL_CLKSEL_SYSCLK;
1936 break;
1937
1938 case cmuSelect_HFRCODPLLRT:
1939 tmp = CMU_TRACECLKCTRL_CLKSEL_HFRCODPLLRT;
1940 break;
1941 #endif
1942
1943 #if defined(CMU_TRACECLKCTRL_CLKSEL_HFRCOEM23)
1944 case cmuSelect_HFRCOEM23:
1945 tmp = CMU_TRACECLKCTRL_CLKSEL_HFRCOEM23;
1946 break;
1947 #endif
1948
1949 default:
1950 EFM_ASSERT(false);
1951 break;
1952 }
1953 CMU->TRACECLKCTRL = (CMU->TRACECLKCTRL & ~_CMU_TRACECLKCTRL_CLKSEL_MASK)
1954 | tmp;
1955 #if (defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
1956 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) \
1957 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) \
1958 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)) \
1959 && defined(CoreDebug_DEMCR_TRCENA_Msk)
1960 if (restoreTrace) {
1961 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
1962 }
1963 #endif
1964 break;
1965 #endif
1966
1967 #if defined(_CMU_EUART0CLKCTRL_CLKSEL_MASK)
1968 // -----------------------------------------------------------------------------
1969 case cmuClock_EUART0:
1970 case cmuClock_EUART0CLK:
1971 switch (ref) {
1972 case cmuSelect_EM01GRPACLK:
1973 tmp = _CMU_EUART0CLKCTRL_CLKSEL_EM01GRPACLK;
1974 break;
1975
1976 case cmuSelect_EM23GRPACLK:
1977 tmp = _CMU_EUART0CLKCTRL_CLKSEL_EM23GRPACLK;
1978 break;
1979
1980 default:
1981 EFM_ASSERT(false);
1982 break;
1983 }
1984 CMU->EUART0CLKCTRL = (CMU->EUART0CLKCTRL & ~_CMU_EUART0CLKCTRL_CLKSEL_MASK)
1985 | tmp;
1986 break;
1987 #elif defined(EUSART_PRESENT)
1988 case cmuClock_EUSART0:
1989 case cmuClock_EUSART0CLK:
1990 switch (ref) {
1991 #if defined(_CMU_EUSART0CLKCTRL_CLKSEL_EM01GRPACLK)
1992 case cmuSelect_EM01GRPACLK:
1993 tmp = _CMU_EUSART0CLKCTRL_CLKSEL_EM01GRPACLK;
1994 break;
1995 #endif
1996 #if defined(_CMU_EUSART0CLKCTRL_CLKSEL_EM01GRPCCLK)
1997 case cmuSelect_EM01GRPCCLK:
1998 tmp = _CMU_EUSART0CLKCTRL_CLKSEL_EM01GRPCCLK;
1999 break;
2000 #endif
2001 #if defined(_CMU_EUSART0CLKCTRL_CLKSEL_EM23GRPACLK)
2002 case cmuSelect_EM23GRPACLK:
2003 tmp = _CMU_EUSART0CLKCTRL_CLKSEL_EM23GRPACLK;
2004 break;
2005 #endif
2006 #if defined(_CMU_EUSART0CLKCTRL_CLKSEL_FSRCO)
2007 case cmuSelect_FSRCO:
2008 tmp = _CMU_EUSART0CLKCTRL_CLKSEL_FSRCO;
2009 break;
2010 #endif
2011 #if defined(_CMU_EUSART0CLKCTRL_CLKSEL_HFRCOEM23)
2012 case cmuSelect_HFRCOEM23:
2013 tmp = _CMU_EUSART0CLKCTRL_CLKSEL_HFRCOEM23;
2014 break;
2015 #endif
2016 #if defined(_CMU_EUSART0CLKCTRL_CLKSEL_LFRCO)
2017 case cmuSelect_LFRCO:
2018 #if defined(PLFRCO_PRESENT)
2019 case cmuSelect_PLFRCO:
2020 #endif
2021 tmp = _CMU_EUSART0CLKCTRL_CLKSEL_LFRCO;
2022 break;
2023 #endif
2024 #if defined(_CMU_EUSART0CLKCTRL_CLKSEL_LFXO)
2025 case cmuSelect_LFXO:
2026 tmp = _CMU_EUSART0CLKCTRL_CLKSEL_LFXO;
2027 break;
2028 #endif
2029
2030 default:
2031 EFM_ASSERT(false);
2032 break;
2033 }
2034 CMU->EUSART0CLKCTRL = (CMU->EUSART0CLKCTRL & ~_CMU_EUSART0CLKCTRL_CLKSEL_MASK)
2035 | tmp;
2036 break;
2037
2038 #if defined(EUSART_PRESENT) && EUSART_COUNT > 1
2039 case cmuClock_EUSART1:
2040 #endif
2041 #if defined(EUSART_PRESENT) && EUSART_COUNT > 2
2042 case cmuClock_EUSART2:
2043 #endif
2044 #if defined(EUSART_PRESENT) && EUSART_COUNT > 3
2045 case cmuClock_EUSART3:
2046 #endif
2047 #if defined(EUSART_PRESENT) && EUSART_COUNT > 4
2048 case cmuClock_EUSART4:
2049 #endif
2050 #if defined(_CMU_EM01GRPCCLKCTRL_MASK)
2051 case cmuClock_EM01GRPCCLK:
2052 switch (ref) {
2053 case cmuSelect_HFRCODPLL:
2054 tmp = _CMU_EM01GRPCCLKCTRL_CLKSEL_HFRCODPLL;
2055 break;
2056
2057 #if defined(CMU_EM01GRPCCLKCTRL_CLKSEL_HFRCODPLLRT)
2058 case cmuSelect_HFRCODPLLRT:
2059 tmp = CMU_EM01GRPCCLKCTRL_CLKSEL_HFRCODPLLRT;
2060 break;
2061 #endif
2062 case cmuSelect_HFRCOEM23:
2063 tmp = _CMU_EM01GRPCCLKCTRL_CLKSEL_HFRCOEM23;
2064 break;
2065
2066 case cmuSelect_FSRCO:
2067 tmp = _CMU_EM01GRPCCLKCTRL_CLKSEL_FSRCO;
2068 break;
2069
2070 case cmuSelect_HFXO:
2071 tmp = _CMU_EM01GRPCCLKCTRL_CLKSEL_HFXO;
2072 break;
2073
2074 #if defined(CMU_EM01GRPCCLKCTRL_CLKSEL_HFXORT)
2075 case cmuSelect_HFXORT:
2076 tmp = CMU_EM01GRPCCLKCTRL_CLKSEL_HFXORT;
2077 break;
2078 #endif
2079 default:
2080 EFM_ASSERT(false);
2081 break;
2082 }
2083 CMU->EM01GRPCCLKCTRL = (CMU->EM01GRPCCLKCTRL & ~_CMU_EM01GRPCCLKCTRL_CLKSEL_MASK)
2084 | tmp;
2085 break;
2086 #endif
2087 #endif
2088
2089 // -----------------------------------------------------------------------------
2090 #if defined (RTCC_PRESENT)
2091 case cmuClock_RTCC:
2092 case cmuClock_RTCCCLK:
2093 switch (ref) {
2094 case cmuSelect_LFRCO:
2095 #if defined(PLFRCO_PRESENT)
2096 case cmuSelect_PLFRCO:
2097 #endif
2098 tmp = CMU_RTCCCLKCTRL_CLKSEL_LFRCO;
2099 break;
2100
2101 case cmuSelect_LFXO:
2102 tmp = CMU_RTCCCLKCTRL_CLKSEL_LFXO;
2103 break;
2104
2105 case cmuSelect_ULFRCO:
2106 tmp = CMU_RTCCCLKCTRL_CLKSEL_ULFRCO;
2107 break;
2108
2109 default:
2110 EFM_ASSERT(false);
2111 break;
2112 }
2113 CMU->RTCCCLKCTRL = (CMU->RTCCCLKCTRL & ~_CMU_RTCCCLKCTRL_CLKSEL_MASK)
2114 | tmp;
2115 break;
2116 #endif
2117 // -----------------------------------------------------------------------------
2118 #if defined (SYSRTC_PRESENT)
2119 case cmuClock_SYSRTC:
2120 case cmuClock_SYSRTCCLK:
2121 switch (ref) {
2122 case cmuSelect_LFRCO:
2123 #if defined(PLFRCO_PRESENT)
2124 case cmuSelect_PLFRCO:
2125 #endif
2126 tmp = CMU_SYSRTC0CLKCTRL_CLKSEL_LFRCO;
2127 break;
2128
2129 case cmuSelect_LFXO:
2130 tmp = CMU_SYSRTC0CLKCTRL_CLKSEL_LFXO;
2131 break;
2132
2133 case cmuSelect_ULFRCO:
2134 tmp = CMU_SYSRTC0CLKCTRL_CLKSEL_ULFRCO;
2135 break;
2136
2137 default:
2138 EFM_ASSERT(false);
2139 break;
2140 }
2141 CMU->SYSRTC0CLKCTRL = (CMU->SYSRTC0CLKCTRL & ~_CMU_SYSRTC0CLKCTRL_CLKSEL_MASK)
2142 | tmp;
2143 break;
2144 #endif
2145 // -----------------------------------------------------------------------------
2146 #if defined(LCD_PRESENT)
2147 case cmuClock_LCD:
2148 case cmuClock_LCDCLK:
2149 switch (ref) {
2150 case cmuSelect_LFRCO:
2151 #if defined(PLFRCO_PRESENT)
2152 case cmuSelect_PLFRCO:
2153 #endif
2154 tmp = CMU_LCDCLKCTRL_CLKSEL_LFRCO;
2155 break;
2156
2157 case cmuSelect_LFXO:
2158 tmp = CMU_LCDCLKCTRL_CLKSEL_LFXO;
2159 break;
2160
2161 case cmuSelect_ULFRCO:
2162 tmp = CMU_LCDCLKCTRL_CLKSEL_ULFRCO;
2163 break;
2164
2165 default:
2166 EFM_ASSERT(false);
2167 break;
2168 }
2169 CMU->LCDCLKCTRL = (CMU->LCDCLKCTRL & ~_CMU_LCDCLKCTRL_CLKSEL_MASK)
2170 | tmp;
2171 break;
2172 #endif
2173 // -----------------------------------------------------------------------------
2174 #if defined(VDAC_PRESENT)
2175 case cmuClock_VDAC0:
2176 case cmuClock_VDAC0CLK:
2177 switch (ref) {
2178 case cmuSelect_FSRCO:
2179 tmp = CMU_VDAC0CLKCTRL_CLKSEL_FSRCO;
2180 break;
2181 case cmuSelect_HFRCOEM23:
2182 tmp = CMU_VDAC0CLKCTRL_CLKSEL_HFRCOEM23;
2183 break;
2184 case cmuSelect_EM01GRPACLK:
2185 tmp = CMU_VDAC0CLKCTRL_CLKSEL_EM01GRPACLK;
2186 break;
2187 case cmuSelect_EM23GRPACLK:
2188 tmp = CMU_VDAC0CLKCTRL_CLKSEL_EM23GRPACLK;
2189 break;
2190
2191 default:
2192 EFM_ASSERT(false);
2193 break;
2194 }
2195 CMU->VDAC0CLKCTRL = (CMU->VDAC0CLKCTRL & ~_CMU_VDAC0CLKCTRL_CLKSEL_MASK)
2196 | tmp;
2197 break;
2198 #if (VDAC_COUNT > 1)
2199 case cmuClock_VDAC1:
2200 case cmuClock_VDAC1CLK:
2201 switch (ref) {
2202 case cmuSelect_FSRCO:
2203 tmp = CMU_VDAC1CLKCTRL_CLKSEL_FSRCO;
2204 break;
2205 case cmuSelect_HFRCOEM23:
2206 tmp = CMU_VDAC1CLKCTRL_CLKSEL_HFRCOEM23;
2207 break;
2208 case cmuSelect_EM01GRPACLK:
2209 tmp = CMU_VDAC1CLKCTRL_CLKSEL_EM01GRPACLK;
2210 break;
2211 case cmuSelect_EM23GRPACLK:
2212 tmp = CMU_VDAC1CLKCTRL_CLKSEL_EM23GRPACLK;
2213 break;
2214
2215 default:
2216 EFM_ASSERT(false);
2217 break;
2218 }
2219 CMU->VDAC1CLKCTRL = (CMU->VDAC1CLKCTRL & ~_CMU_VDAC1CLKCTRL_CLKSEL_MASK)
2220 | tmp;
2221 break;
2222 #endif
2223 #endif /* VDAC_PRESENT */
2224 // -----------------------------------------------------------------------------
2225 #if defined(PCNT_PRESENT)
2226 case cmuClock_PCNT0:
2227 case cmuClock_PCNT0CLK:
2228 switch (ref) {
2229 case cmuSelect_EM23GRPACLK:
2230 tmp = CMU_PCNT0CLKCTRL_CLKSEL_EM23GRPACLK;
2231 break;
2232
2233 case cmuSelect_PCNTEXTCLK:
2234 tmp = CMU_PCNT0CLKCTRL_CLKSEL_PCNTS0;
2235 break;
2236
2237 default:
2238 EFM_ASSERT(false);
2239 break;
2240 }
2241 CMU->PCNT0CLKCTRL = (CMU->PCNT0CLKCTRL & ~_CMU_PCNT0CLKCTRL_CLKSEL_MASK)
2242 | tmp;
2243 break;
2244 #endif
2245 // -----------------------------------------------------------------------------
2246 #if defined(LESENSE_PRESENT)
2247 case cmuClock_LESENSEHFCLK:
2248 switch (ref) {
2249 case cmuSelect_FSRCO:
2250 tmp = CMU_LESENSEHFCLKCTRL_CLKSEL_FSRCO;
2251 break;
2252 case cmuSelect_HFRCOEM23:
2253 tmp = CMU_LESENSEHFCLKCTRL_CLKSEL_HFRCOEM23;
2254 break;
2255
2256 default:
2257 EFM_ASSERT(false);
2258 break;
2259 }
2260 CMU->LESENSEHFCLKCTRL = (CMU->LESENSEHFCLKCTRL & ~_CMU_LESENSEHFCLKCTRL_CLKSEL_MASK)
2261 | tmp;
2262 break;
2263 #endif
2264 // -----------------------------------------------------------------------------
2265 #if defined(USB_PRESENT)
2266 case cmuClock_USB:
2267 switch (ref) {
2268 case cmuSelect_USBPLL0:
2269 tmp = CMU_USB0CLKCTRL_CLKSEL_USBPLL0;
2270 break;
2271 case cmuSelect_LFXO:
2272 tmp = CMU_USB0CLKCTRL_CLKSEL_LFXO;
2273 break;
2274 case cmuSelect_LFRCO:
2275 tmp = CMU_USB0CLKCTRL_CLKSEL_LFRCO;
2276 break;
2277
2278 default:
2279 EFM_ASSERT(false);
2280 break;
2281 }
2282 CMU->USB0CLKCTRL = (CMU->USB0CLKCTRL & ~_CMU_USB0CLKCTRL_CLKSEL_MASK)
2283 | tmp;
2284 break;
2285 #endif
2286 // -----------------------------------------------------------------------------
2287 default:
2288 EFM_ASSERT(false);
2289 break;
2290 }
2291 }
2292
2293 /***************************************************************************//**
2294 * @brief
2295 * Gets the precision (in PPM) of the specified low frequency clock branch.
2296 *
2297 * @param[in] clock
2298 * Clock branch.
2299 *
2300 * @return
2301 * Precision, in PPM, of the specified clock branch.
2302 *
2303 * @note
2304 * This function is only for internal usage.
2305 *
2306 * @note
2307 * The current implementation of this function is used to determine if the
2308 * clock has a precision <= 500 ppm or not (which is the minimum required
2309 * for BLE). Future version of this function should provide more accurate
2310 * precision numbers to allow for further optimizations from the stacks.
2311 ******************************************************************************/
CMU_LF_ClockPrecisionGet(CMU_Clock_TypeDef clock)2312 uint16_t CMU_LF_ClockPrecisionGet(CMU_Clock_TypeDef clock)
2313 {
2314 CMU_Select_TypeDef src = CMU_ClockSelectGet(clock);
2315 uint16_t precision;
2316
2317 switch (src) {
2318 case cmuSelect_LFXO:
2319 precision = lfxo_precision;
2320 break;
2321
2322 #if defined(PLFRCO_PRESENT)
2323 #if defined(LFRCO_CFG_HIGHPRECEN)
2324 case cmuSelect_LFRCO:
2325 case cmuSelect_PLFRCO:
2326
2327 CMU->CLKEN0_SET = CMU_CLKEN0_LFRCO;
2328
2329 if (LFRCO->CFG & _LFRCO_CFG_HIGHPRECEN_MASK) {
2330 precision = 500;
2331 } else {
2332 precision = 0xFFFF;
2333 }
2334 break;
2335 #endif
2336 #endif
2337
2338 default:
2339 precision = 0xFFFF;
2340 break;
2341 }
2342
2343 return precision;
2344 }
2345
2346 /***************************************************************************//**
2347 * @brief
2348 * Get HFRCODPLL band in use.
2349 *
2350 * @return
2351 * HFRCODPLL band in use.
2352 ******************************************************************************/
CMU_HFRCODPLLBandGet(void)2353 CMU_HFRCODPLLFreq_TypeDef CMU_HFRCODPLLBandGet(void)
2354 {
2355 return (CMU_HFRCODPLLFreq_TypeDef)SystemHFRCODPLLClockGet();
2356 }
2357
2358 /***************************************************************************//**
2359 * @brief
2360 * Set HFRCODPLL band and the tuning value based on the value in the
2361 * calibration table made during production.
2362 *
2363 * @param[in] freq
2364 * HFRCODPLL frequency band to activate.
2365 ******************************************************************************/
CMU_HFRCODPLLBandSet(CMU_HFRCODPLLFreq_TypeDef freq)2366 void CMU_HFRCODPLLBandSet(CMU_HFRCODPLLFreq_TypeDef freq)
2367 {
2368 uint32_t hfrcoFreqRangeExpected;
2369 uint32_t hfrcoFreqRangeActual;
2370 uint32_t hfrcoCalCurrent;
2371 uint32_t freqCal, sysFreq;
2372 #if defined(EMU_VSCALE_EM01_PRESENT)
2373 uint32_t prevFreq;
2374 #endif
2375
2376 // Get calibration data from DEVINFO
2377 freqCal = HFRCODPLLDevinfoGet(freq);
2378 EFM_ASSERT((freqCal != 0UL) && (freqCal != UINT_MAX));
2379
2380 #if defined(CMU_CLKEN0_DPLL0)
2381 CMU->CLKEN0_SET = CMU_CLKEN0_DPLL0 | CMU_CLKEN0_HFRCO0;
2382 #endif
2383
2384 // Make sure DPLL is disabled before configuring
2385 if (DPLL0->EN == DPLL_EN_EN) {
2386 DPLL0->EN_CLR = DPLL_EN_EN;
2387 #if defined(DPLL_EN_DISABLING)
2388 while (DPLL0->EN & DPLL_EN_DISABLING) {
2389 }
2390 #else
2391 while ((DPLL0->STATUS & (DPLL_STATUS_ENS | DPLL_STATUS_RDY)) != 0UL) {
2392 }
2393 #endif
2394 }
2395
2396 // Set max wait-states and PCLK divisor while changing core clock
2397 if (CMU_ClockSelectGet(cmuClock_SYSCLK) == cmuSelect_HFRCODPLL) {
2398 waitStateMax();
2399 pclkDivMax();
2400 #if ((defined(CMU_SYSCLKCTRL_RHCLKPRESC)) \
2401 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
2402 // Set largest prescaler for radio clock tree
2403 rhclkPrescMax();
2404 #endif
2405 }
2406
2407 // Set divider for 1, 2 and 4MHz bands
2408 freqCal &= ~_HFRCO_CAL_CLKDIV_MASK;
2409 switch (freq) {
2410 case cmuHFRCODPLLFreq_1M0Hz:
2411 freqCal |= HFRCO_CAL_CLKDIV_DIV4;
2412 break;
2413
2414 case cmuHFRCODPLLFreq_2M0Hz:
2415 freqCal |= HFRCO_CAL_CLKDIV_DIV2;
2416 break;
2417
2418 default:
2419 break;
2420 }
2421
2422 #if defined(EMU_VSCALE_EM01_PRESENT)
2423 prevFreq = SystemHFRCODPLLClockGet();
2424
2425 if ((uint32_t)freq > prevFreq) {
2426 /* When increasing frequency voltage scale must be done before the change. */
2427 EMU_VScaleEM01ByClock((uint32_t)freq, true);
2428 }
2429 #endif
2430
2431 // updates to the CAL register are deferred if FREQBSY is high, so wait
2432 // until HFRCO is not busy to keep going
2433 while (HFRCO0->STATUS & (HFRCO_STATUS_SYNCBUSY | HFRCO_STATUS_FREQBSY)) {
2434 }
2435
2436 /*
2437 * Some devices have clamped frequency ranges, so instead of the usual [0:16]
2438 * interval, the upper limit is 12. Hardware takes care of clamping the value,
2439 * but a situation might occur where tuning and frequency range are not
2440 * in sync. So try to detect if the value has been clamped, and if it happened
2441 * revert back to the previous value.
2442 */
2443 hfrcoCalCurrent = HFRCO0->CAL;
2444 HFRCO0->CAL = freqCal;
2445
2446 // values are not shifted, not necessary for comparison
2447 hfrcoFreqRangeExpected = (freqCal & _HFRCO_CAL_FREQRANGE_MASK);
2448 hfrcoFreqRangeActual = (HFRCO0->CAL & _HFRCO_CAL_FREQRANGE_MASK);
2449
2450 EFM_ASSERT(hfrcoFreqRangeExpected == hfrcoFreqRangeActual);
2451 if (hfrcoFreqRangeExpected == hfrcoFreqRangeActual) {
2452 // Update CMSIS HFRCODPLL frequency.
2453 SystemHFRCODPLLClockSet(freq);
2454 } else {
2455 // revert back to previous value
2456 HFRCO0->CAL = hfrcoCalCurrent;
2457 #if defined(EMU_VSCALE_EM01_PRESENT)
2458 freq = (CMU_HFRCODPLLFreq_TypeDef)prevFreq;
2459 #endif
2460 }
2461
2462 // If HFRCODPLL is selected as SYSCLK (and HCLK), optimize flash access
2463 // wait-state configuration and PCLK divisor for this frequency.
2464 if (CMU_ClockSelectGet(cmuClock_SYSCLK) == cmuSelect_HFRCODPLL) {
2465 // Call @ref SystemCoreClockGet() to update CMSIS core clock variable.
2466 sysFreq = SystemCoreClockGet();
2467 EFM_ASSERT(sysFreq <= (uint32_t)freq);
2468 CMU_UpdateWaitStates(sysFreq, VSCALE_DEFAULT);
2469 pclkDivOptimize();
2470 #if (defined(CMU_SYSCLKCTRL_RHCLKPRESC) \
2471 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
2472 // Set optimal RHCLK prescaler
2473 rhclkPrescOptimize();
2474 #endif
2475 }
2476
2477 #if defined(EMU_VSCALE_EM01_PRESENT)
2478 if ((uint32_t)freq <= prevFreq) {
2479 /* When decreasing frequency voltage scale must be done after the change. */
2480 EMU_VScaleEM01ByClock(0, true);
2481 }
2482 #endif
2483 }
2484
2485 /**************************************************************************//**
2486 * @brief
2487 * Lock the DPLL to a given frequency.
2488 * The frequency is given by: Fout = Fref * (N+1) / (M+1).
2489 *
2490 * @note
2491 * This function does not check if the given N & M values will actually
2492 * produce the desired target frequency. @n
2493 * N & M limitations: @n
2494 * 300 < N <= 4095 @n
2495 * 0 <= M <= 4095 @n
2496 * Any peripheral running off HFRCODPLL should be switched to a lower
2497 * frequency clock (if possible) prior to calling this function to avoid
2498 * over-clocking.
2499 *
2500 * @param[in] init
2501 * DPLL setup parameter struct.
2502 *
2503 * @return
2504 * Returns false on invalid target frequency or DPLL locking error.
2505 *****************************************************************************/
CMU_DPLLLock(const CMU_DPLLInit_TypeDef * init)2506 bool CMU_DPLLLock(const CMU_DPLLInit_TypeDef *init)
2507 {
2508 int index = 0;
2509 unsigned int i;
2510 bool hclkDivIncreased = false;
2511 uint32_t hfrcoCalVal, lockStatus = 0, hclkDiv = 0, sysFreq;
2512 uint32_t hfrcoFreqRangeExpected;
2513 uint32_t hfrcoFreqRangeActual;
2514 uint32_t hfrcoCalCurrent;
2515 bool hfrcoClamped = false;
2516 bool restoreDpll;
2517
2518 #if defined(CMU_CLKEN0_DPLL0)
2519 CMU->CLKEN0_SET = CMU_CLKEN0_DPLL0 | CMU_CLKEN0_HFRCO0;
2520 #endif
2521
2522 restoreDpll = DPLL0->EN & _DPLL_EN_EN_MASK;
2523
2524 // Make sure DPLL is disabled before configuring
2525 DPLL0->EN_CLR = DPLL_EN_EN;
2526 #if defined(DPLL_EN_DISABLING)
2527 while (DPLL0->EN & DPLL_EN_DISABLING) {
2528 }
2529 #else
2530 while ((DPLL0->STATUS & (DPLL_STATUS_ENS | DPLL_STATUS_RDY)) != 0UL) {
2531 }
2532 #endif
2533 EFM_ASSERT(init->frequency >= hfrcoCalTable[0].minFreq);
2534 EFM_ASSERT(init->frequency
2535 <= hfrcoCalTable[HFRCOCALTABLE_ENTRIES - 1U].maxFreq);
2536
2537 EFM_ASSERT(init->n > 300U);
2538 EFM_ASSERT(init->n <= (_DPLL_CFG1_N_MASK >> _DPLL_CFG1_N_SHIFT));
2539 EFM_ASSERT(init->m <= (_DPLL_CFG1_M_MASK >> _DPLL_CFG1_M_SHIFT));
2540
2541 #if defined(EMU_VSCALE_EM01_PRESENT)
2542 if ((EMU_VScaleGet() == emuVScaleEM01_LowPower)
2543 && (init->frequency > CMU_VSCALEEM01_LOWPOWER_VOLTAGE_CLOCK_MAX)) {
2544 EFM_ASSERT(false);
2545 return false;
2546 }
2547 #endif
2548
2549 // Find correct HFRCODPLL band, and retrieve a HFRCOCAL value.
2550 for (i = 0; i < HFRCOCALTABLE_ENTRIES; i++) {
2551 if ((init->frequency >= hfrcoCalTable[i].minFreq)
2552 && (init->frequency <= hfrcoCalTable[i].maxFreq)) {
2553 index = (int)i; // Correct band found
2554 break;
2555 }
2556 }
2557 if ((uint32_t)index == HFRCOCALTABLE_ENTRIES) {
2558 EFM_ASSERT(false);
2559 return false; // Target frequency out of spec.
2560 }
2561 hfrcoCalVal = hfrcoCalTable[index].value;
2562
2563 // Check if a calibrated HFRCOCAL.TUNING value is present in device DI page.
2564 if (hfrcoCalTable[index].band != (CMU_HFRCODPLLFreq_TypeDef)0) {
2565 uint32_t tuning;
2566
2567 tuning = (HFRCODPLLDevinfoGet(hfrcoCalTable[index].band)
2568 & _HFRCO_CAL_TUNING_MASK)
2569 >> _HFRCO_CAL_TUNING_SHIFT;
2570 hfrcoCalVal |= tuning << _HFRCO_CAL_TUNING_SHIFT;
2571 }
2572
2573 if (CMU_ClockSelectGet(cmuClock_SYSCLK) == cmuSelect_HFRCODPLL) {
2574 // Set max wait-states and PCLK divisor while changing core clock
2575 waitStateMax();
2576 pclkDivMax();
2577 #if ((defined(CMU_SYSCLKCTRL_RHCLKPRESC)) \
2578 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
2579 // Set largest prescaler for radio clock tree
2580 rhclkPrescMax();
2581 #endif
2582
2583 // Increase HCLK divider value (if possible) while locking DPLL to
2584 // avoid over-clocking.
2585 hclkDiv = CMU_ClockDivGet(cmuClock_HCLK);
2586 hclkDivIncreased = true;
2587 if (hclkDiv == 1U) {
2588 CMU_ClockDivSet(cmuClock_HCLK, 2U);
2589 } else if (hclkDiv == 2U) {
2590 CMU_ClockDivSet(cmuClock_HCLK, 4U);
2591 } else {
2592 hclkDivIncreased = false;
2593 }
2594 }
2595
2596 // updates to the CAL register are deferred if FREQBSY is high, so wait
2597 // until HFRCO is not busy to keep going
2598 while (HFRCO0->STATUS & (HFRCO_STATUS_SYNCBUSY | HFRCO_STATUS_FREQBSY)) {
2599 }
2600
2601 /*
2602 * Some devices have clamped frequency ranges, so instead of the usual [0:16]
2603 * interval, the upper limit is 12. Hardware takes care of clamping the value,
2604 * but a situation might occur where tuning and frequency range are not
2605 * in sync. So try to detect if the value has been clamped, and if it happened
2606 * revert back to the previous value.
2607 */
2608 hfrcoCalCurrent = HFRCO0->CAL;
2609 HFRCO0->CAL = hfrcoCalVal;
2610
2611 // values are not shifted, not necessary for comparison
2612 hfrcoFreqRangeExpected = (hfrcoCalVal & _HFRCO_CAL_FREQRANGE_MASK);
2613 hfrcoFreqRangeActual = (HFRCO0->CAL & _HFRCO_CAL_FREQRANGE_MASK);
2614
2615 EFM_ASSERT(hfrcoFreqRangeExpected == hfrcoFreqRangeActual);
2616 if (hfrcoFreqRangeExpected == hfrcoFreqRangeActual) {
2617 DPLL0->CFG1 = ((uint32_t)init->n << _DPLL_CFG1_N_SHIFT)
2618 | ((uint32_t)init->m << _DPLL_CFG1_M_SHIFT);
2619
2620 /* For series 2 silicon, macro expansion is used to select clock
2621 * sources since it results in less code size when compared to the legacy
2622 * CMU_ClockSelectSet function.
2623 */
2624 if (init->refClk == cmuSelect_HFXO) {
2625 CMU_CLOCK_SELECT_SET(DPLLREFCLK, HFXO);
2626 } else if (init->refClk == cmuSelect_LFXO) {
2627 CMU_CLOCK_SELECT_SET(DPLLREFCLK, LFXO);
2628 } else if (init->refClk == cmuSelect_CLKIN0) {
2629 CMU_CLOCK_SELECT_SET(DPLLREFCLK, CLKIN0);
2630 }
2631
2632 DPLL0->CFG = ((init->autoRecover ? 1UL : 0UL) << _DPLL_CFG_AUTORECOVER_SHIFT)
2633 | ((init->ditherEn ? 1UL : 0UL) << _DPLL_CFG_DITHEN_SHIFT)
2634 | ((uint32_t)init->edgeSel << _DPLL_CFG_EDGESEL_SHIFT)
2635 | ((uint32_t)init->lockMode << _DPLL_CFG_MODE_SHIFT);
2636
2637 // Update CMSIS HFRCODPLL frequency.
2638 SystemHFRCODPLLClockSet(init->frequency);
2639 } else {
2640 hfrcoClamped = true;
2641 HFRCO0->CAL = hfrcoCalCurrent;
2642 }
2643
2644 /*
2645 * if HFRCO frequency range has been clamped, re-enable DPLL only if it was
2646 * previously enabled
2647 */
2648 if (!hfrcoClamped || restoreDpll) {
2649 DPLL0->IF_CLR = DPLL_IF_LOCK | DPLL_IF_LOCKFAILLOW | DPLL_IF_LOCKFAILHIGH;
2650
2651 // Lock DPLL
2652 DPLL0->EN_SET = DPLL_EN_EN;
2653 while ((lockStatus = (DPLL0->IF & (DPLL_IF_LOCK
2654 | DPLL_IF_LOCKFAILLOW
2655 | DPLL_IF_LOCKFAILHIGH))) == 0UL) {
2656 }
2657 }
2658
2659 if (CMU_ClockSelectGet(cmuClock_SYSCLK) == cmuSelect_HFRCODPLL) {
2660 if (hclkDivIncreased) {
2661 // Restore original HCLK divider
2662 CMU_ClockDivSet(cmuClock_HCLK, hclkDiv);
2663 }
2664
2665 // Call @ref SystemCoreClockGet() to update CMSIS core clock variable.
2666 sysFreq = SystemCoreClockGet();
2667 EFM_ASSERT(sysFreq <= init->frequency);
2668 EFM_ASSERT(sysFreq <= SystemHFRCODPLLClockGet());
2669 EFM_ASSERT(init->frequency == SystemHFRCODPLLClockGet());
2670
2671 // Set optimal wait-states and PCLK divisor
2672 CMU_UpdateWaitStates(sysFreq, VSCALE_DEFAULT);
2673 pclkDivOptimize();
2674 #if (defined(CMU_SYSCLKCTRL_RHCLKPRESC) \
2675 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
2676 // Set optimal RHCLK prescaler
2677 rhclkPrescOptimize();
2678 #endif
2679 }
2680
2681 if (hfrcoClamped) {
2682 return false;
2683 } else if (lockStatus == DPLL_IF_LOCK) {
2684 return true;
2685 }
2686 return false;
2687 }
2688
2689 #if defined(USBPLL_PRESENT)
2690 /***************************************************************************//**
2691 * @brief
2692 * Initialize the USB PLL control registers.
2693 *
2694 * @note
2695 * The HFXO reference frequency must be updated if crystal value is
2696 * different from default value.
2697 *
2698 * @param[in] pllInit
2699 * USB PLL parameters
2700 ******************************************************************************/
CMU_USBPLLInit(const CMU_USBPLL_Init_TypeDef * pllInit)2701 void CMU_USBPLLInit(const CMU_USBPLL_Init_TypeDef *pllInit)
2702 {
2703 CMU->CLKEN1_SET = CMU_CLKEN1_USB;
2704
2705 USBPLL0->LOCK = USBPLL_LOCK_LOCKKEY_UNLOCK;
2706
2707 // Stop the PLL for configuration purposes
2708 USBPLL0->CTRL_SET = USBPLL_CTRL_DISONDEMAND;
2709 USBPLL0->CTRL_CLR = USBPLL_CTRL_FORCEEN;
2710
2711 while (USBPLL0->STATUS & USBPLL_STATUS_PLLLOCK) ;
2712
2713 if (pllInit->hfxoRefFreq == cmuHFXORefFreq_39M0Hz) {
2714 // Set DCO in low frequency mode for 39 MHz crystal.
2715 USBPLL0->DCOCTRL_SET = _USBPLL_DCOCTRL_DCOBIASHALF_MASK;
2716 } else {
2717 USBPLL0->DCOCTRL_CLR = _USBPLL_DCOCTRL_DCOBIASHALF_MASK;
2718 }
2719
2720 while (USBPLL0->STATUS & USBPLL_STATUS_SYNCBUSY) ;
2721
2722 USBPLL0->CTRL = (USBPLL0->CTRL & ~(_USBPLL_CTRL_SHUNTREGLPEN_MASK
2723 | _USBPLL_CTRL_DIVR_MASK
2724 | _USBPLL_CTRL_DIVX_MASK
2725 | _USBPLL_CTRL_DIVN_MASK
2726 | _USBPLL_CTRL_DISONDEMAND_MASK
2727 | _USBPLL_CTRL_FORCEEN_MASK))
2728 | pllInit->hfxoRefFreq
2729 | pllInit->shuntRegEn << _USBPLL_CTRL_SHUNTREGLPEN_SHIFT
2730 | pllInit->disOnDemand << _USBPLL_CTRL_DISONDEMAND_SHIFT
2731 | pllInit->forceEn << _USBPLL_CTRL_FORCEEN_SHIFT;
2732
2733 while (USBPLL0->STATUS & USBPLL_STATUS_SYNCBUSY) ;
2734
2735 if (pllInit->forceEn) {
2736 CMU_WaitUSBPLLLock();
2737 }
2738
2739 if (pllInit->regLock) {
2740 USBPLL0->LOCK = ~USBPLL_LOCK_LOCKKEY_UNLOCK;
2741 }
2742 }
2743 #endif
2744
2745 #if defined(RFFPLL_PRESENT)
2746 /***************************************************************************//**
2747 * @brief
2748 * Initialize the RFFPLL control registers.
2749 *
2750 * @param[in] pllInit
2751 * RFF PLL parameters
2752 ******************************************************************************/
CMU_RFFPLLInit(const CMU_RFFPLL_Init_TypeDef * pllInit)2753 void CMU_RFFPLLInit(const CMU_RFFPLL_Init_TypeDef *pllInit)
2754 {
2755 EFM_ASSERT(CMU_ClockSelectGet(cmuClock_SYSCLK) != cmuSelect_RFFPLLSYS);
2756 EFM_ASSERT(pllInit->dividerY >= 8 && pllInit->dividerY <= 31);
2757 EFM_ASSERT(pllInit->dividerX >= 4 && pllInit->dividerX <= 15);
2758 EFM_ASSERT(pllInit->dividerN >= 32 && pllInit->dividerN <= 127);
2759
2760 CMU->CLKEN1_SET = CMU_CLKEN1_RFFPLL0;
2761
2762 RFFPLL0->LOCK = RFFPLL_LOCK_LOCKKEY_UNLOCK;
2763
2764 RFFPLL0->CTRL = (RFFPLL0->CTRL & ~(_RFFPLL_CTRL_DISONDEMAND_MASK | _RFFPLL_CTRL_FORCEEN_MASK))
2765 | (pllInit->disOnDemand << _RFFPLL_CTRL_DISONDEMAND_SHIFT)
2766 | (pllInit->forceEn << _RFFPLL_CTRL_FORCEEN_SHIFT);
2767
2768 RFFPLL0->RFFPLLCTRL1 = (RFFPLL0->RFFPLLCTRL1 & ~(_RFFPLL_RFFPLLCTRL1_DIVY_MASK | _RFFPLL_RFFPLLCTRL1_DIVX_MASK | _RFFPLL_RFFPLLCTRL1_DIVN_MASK))
2769 | (pllInit->dividerY << _RFFPLL_RFFPLLCTRL1_DIVY_SHIFT)
2770 | (pllInit->dividerX << _RFFPLL_RFFPLLCTRL1_DIVX_SHIFT)
2771 | (pllInit->dividerN << _RFFPLL_RFFPLLCTRL1_DIVN_SHIFT);
2772
2773 // Update CMSIS RFFPLL frequency.
2774 SystemRFFPLLClockSet(pllInit->frequency);
2775
2776 if (pllInit->forceEn) {
2777 CMU_WaitRFFPLLLock();
2778 }
2779
2780 if (pllInit->regLock) {
2781 RFFPLL0->LOCK = ~USBPLL_LOCK_LOCKKEY_UNLOCK;
2782 }
2783 }
2784 #endif
2785
2786 /**************************************************************************//**
2787 * @brief
2788 * Initialize all HFXO control registers.
2789 *
2790 * @note
2791 * HFXO configuration should be obtained from a configuration tool,
2792 * app note or crystal datasheet. This function returns early if HFXO is
2793 * already selected as SYSCLK.
2794 *
2795 * @param[in] hfxoInit
2796 * HFXO setup parameters.
2797 *****************************************************************************/
CMU_HFXOInit(const CMU_HFXOInit_TypeDef * hfxoInit)2798 void CMU_HFXOInit(const CMU_HFXOInit_TypeDef *hfxoInit)
2799 {
2800 // Check all initialization structure members which may overflow target
2801 // bitfield.
2802 EFM_ASSERT(hfxoInit->timeoutCbLsb
2803 <= (_HFXO_XTALCFG_TIMEOUTCBLSB_MASK
2804 >> _HFXO_XTALCFG_TIMEOUTCBLSB_SHIFT));
2805 EFM_ASSERT(hfxoInit->timeoutSteadyFirstLock
2806 <= (_HFXO_XTALCFG_TIMEOUTSTEADY_MASK
2807 >> _HFXO_XTALCFG_TIMEOUTSTEADY_SHIFT));
2808 EFM_ASSERT(hfxoInit->timeoutSteady
2809 <= (_HFXO_XTALCFG_TIMEOUTSTEADY_MASK
2810 >> _HFXO_XTALCFG_TIMEOUTSTEADY_SHIFT));
2811 EFM_ASSERT(hfxoInit->ctuneXoStartup
2812 <= (_HFXO_XTALCFG_CTUNEXOSTARTUP_MASK
2813 >> _HFXO_XTALCFG_CTUNEXOSTARTUP_SHIFT));
2814 EFM_ASSERT(hfxoInit->ctuneXiStartup
2815 <= (_HFXO_XTALCFG_CTUNEXISTARTUP_MASK
2816 >> _HFXO_XTALCFG_CTUNEXISTARTUP_SHIFT));
2817 EFM_ASSERT(hfxoInit->coreBiasStartup
2818 <= (_HFXO_XTALCFG_COREBIASSTARTUP_MASK
2819 >> _HFXO_XTALCFG_COREBIASSTARTUP_SHIFT));
2820 EFM_ASSERT(hfxoInit->imCoreBiasStartup
2821 <= (_HFXO_XTALCFG_COREBIASSTARTUPI_MASK
2822 >> _HFXO_XTALCFG_COREBIASSTARTUPI_SHIFT));
2823 EFM_ASSERT(hfxoInit->coreDegenAna
2824 <= (_HFXO_XTALCTRL_COREDGENANA_MASK
2825 >> _HFXO_XTALCTRL_COREDGENANA_SHIFT));
2826 EFM_ASSERT(hfxoInit->ctuneFixAna
2827 <= (_HFXO_XTALCTRL_CTUNEFIXANA_MASK
2828 >> _HFXO_XTALCTRL_CTUNEFIXANA_SHIFT));
2829 EFM_ASSERT(hfxoInit->mode
2830 <= (_HFXO_CFG_MODE_MASK >> _HFXO_CFG_MODE_SHIFT));
2831
2832 // Return early if HFXO is already selected as SYSCLK.
2833 if (CMU_ClockSelectGet(cmuClock_SYSCLK) == cmuSelect_HFXO) {
2834 return;
2835 }
2836
2837 #if defined(CMU_CLKEN0_HFXO0)
2838 // Enable HFXO module clock.
2839 CMU->CLKEN0_SET = CMU_CLKEN0_HFXO0;
2840 #endif
2841
2842 // Unlock register interface.
2843 HFXO0->LOCK = HFXO_LOCK_LOCKKEY_UNLOCK;
2844
2845 // Disable HFXO.
2846 HFXO0->CTRL_SET = HFXO_CTRL_DISONDEMAND
2847 #if defined(_HFXO_CTRL_DISONDEMANDBUFOUT_MASK)
2848 | HFXO_CTRL_DISONDEMANDBUFOUT
2849 #endif
2850 ;
2851 HFXO0->CTRL_CLR = HFXO_CTRL_FORCEEN;
2852 while ((HFXO0->STATUS & _HFXO_STATUS_ENS_MASK) != 0U) {
2853 }
2854
2855 #if defined(_DEVINFO_HFXOCAL_VTRTRIMANA_MASK) && defined(_HFXO_BUFOUTTRIM_MASK) && defined(_HFXO_SWRST_MASK)
2856 {
2857 uint32_t tmp;
2858
2859 tmp = BUS_RegMaskedRead(&DEVINFO->HFXOCAL,
2860 _DEVINFO_HFXOCAL_VTRTRIMANA_MASK);
2861 tmp >>= _DEVINFO_HFXOCAL_VTRTRIMANA_SHIFT;
2862 BUS_RegMaskedWrite(&HFXO0->BUFOUTTRIM,
2863 _HFXO_BUFOUTTRIM_VTRTRIMANA_MASK,
2864 tmp << _HFXO_BUFOUTTRIM_VTRTRIMANA_SHIFT);
2865 }
2866 #endif
2867
2868 #if defined(_DEVINFO_HFXOCAL_SHUNTBIASANA_MASK) && defined(_HFXO_LOWPWRCTRL_MASK) && defined(_HFXO_SWRST_MASK)
2869 {
2870 uint32_t tmp;
2871
2872 tmp = BUS_RegMaskedRead(&DEVINFO->HFXOCAL,
2873 _DEVINFO_HFXOCAL_SHUNTBIASANA_MASK);
2874 tmp >>= _DEVINFO_HFXOCAL_SHUNTBIASANA_SHIFT;
2875 BUS_RegMaskedWrite(&HFXO0->LOWPWRCTRL,
2876 _HFXO_LOWPWRCTRL_SHUNTBIASANA_MASK,
2877 tmp << _HFXO_LOWPWRCTRL_SHUNTBIASANA_SHIFT);
2878 }
2879 #endif
2880
2881 // Configure HFXO as specified in initialization struct, use
2882 // timeoutSteadyFirstLock as TIMEOUTSTEADY value.
2883 HFXO0->XTALCFG =
2884 (uint32_t)((hfxoInit->timeoutCbLsb << _HFXO_XTALCFG_TIMEOUTCBLSB_SHIFT)
2885 | (hfxoInit->timeoutSteadyFirstLock << _HFXO_XTALCFG_TIMEOUTSTEADY_SHIFT)
2886 | (hfxoInit->ctuneXoStartup << _HFXO_XTALCFG_CTUNEXOSTARTUP_SHIFT)
2887 | (hfxoInit->ctuneXiStartup << _HFXO_XTALCFG_CTUNEXISTARTUP_SHIFT)
2888 | (hfxoInit->coreBiasStartup << _HFXO_XTALCFG_COREBIASSTARTUP_SHIFT)
2889 | (hfxoInit->imCoreBiasStartup << _HFXO_XTALCFG_COREBIASSTARTUPI_SHIFT));
2890
2891 HFXO0->XTALCTRL = (HFXO0->XTALCTRL & _HFXO_XTALCTRL_SKIPCOREBIASOPT_MASK)
2892 | (hfxoInit->coreDegenAna << _HFXO_XTALCTRL_COREDGENANA_SHIFT)
2893 | (hfxoInit->ctuneFixAna << _HFXO_XTALCTRL_CTUNEFIXANA_SHIFT)
2894 | (hfxoInit->ctuneXoAna << _HFXO_XTALCTRL_CTUNEXOANA_SHIFT)
2895 | (hfxoInit->ctuneXiAna << _HFXO_XTALCTRL_CTUNEXIANA_SHIFT)
2896 | (hfxoInit->coreBiasAna << _HFXO_XTALCTRL_COREBIASANA_SHIFT);
2897
2898 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3) \
2899 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)
2900 // See [PM-2871] for details.
2901 BUS_RegMaskedWrite((volatile uint32_t*)(HFXO0_BASE + 0x38U),
2902 0x00000C00U,
2903 0x00000002U << 10);
2904 #endif
2905
2906 HFXO0->CFG = (HFXO0->CFG & ~(_HFXO_CFG_SQBUFSCHTRGANA_MASK
2907 | _HFXO_CFG_ENXIDCBIASANA_MASK
2908 | _HFXO_CFG_MODE_MASK))
2909 | ((hfxoInit->mode == cmuHfxoOscMode_Crystal)
2910 ? 0 : HFXO_CFG_SQBUFSCHTRGANA)
2911 | (hfxoInit->enXiDcBiasAna << _HFXO_CFG_ENXIDCBIASANA_SHIFT)
2912 | (hfxoInit->mode << _HFXO_CFG_MODE_SHIFT);
2913
2914 if (hfxoInit->mode == cmuHfxoOscMode_Crystal) {
2915 // Lock HFXO with FORCEEN bit set and DISONDEMAND bit cleared.
2916 HFXO0->CTRL = (HFXO0->CTRL & ~(_HFXO_CTRL_FORCEXO2GNDANA_MASK
2917 | _HFXO_CTRL_FORCEXI2GNDANA_MASK
2918 | _HFXO_CTRL_DISONDEMAND_MASK
2919 #if defined(HFXO_CTRL_EM23ONDEMAND)
2920 | _HFXO_CTRL_EM23ONDEMAND_MASK
2921 #endif
2922 | _HFXO_CTRL_FORCEEN_MASK))
2923 | (hfxoInit->forceXo2GndAna << _HFXO_CTRL_FORCEXO2GNDANA_SHIFT)
2924 | (hfxoInit->forceXi2GndAna << _HFXO_CTRL_FORCEXI2GNDANA_SHIFT)
2925 #if defined(HFXO_CTRL_EM23ONDEMAND)
2926 | (hfxoInit->em23OnDemand << _HFXO_CTRL_EM23ONDEMAND_SHIFT)
2927 #endif
2928 | HFXO_CTRL_FORCEEN;
2929
2930 // Wait for HFXO lock and core bias algorithm to complete.
2931 #if defined(HFXO_STATUS_FSMLOCK)
2932 while ((HFXO0->STATUS & (HFXO_STATUS_RDY | HFXO_STATUS_COREBIASOPTRDY
2933 | HFXO_STATUS_ENS | HFXO_STATUS_FSMLOCK))
2934 != (HFXO_STATUS_RDY | HFXO_STATUS_COREBIASOPTRDY | HFXO_STATUS_ENS
2935 | HFXO_STATUS_FSMLOCK)) {
2936 }
2937 #else
2938 while ((HFXO0->STATUS & (HFXO_STATUS_RDY | HFXO_STATUS_COREBIASOPTRDY
2939 | HFXO_STATUS_ENS))
2940 != (HFXO_STATUS_RDY | HFXO_STATUS_COREBIASOPTRDY | HFXO_STATUS_ENS)) {
2941 }
2942 #endif
2943 // Set DISONDEMAND to be able to enter new values for use on subsequent locks.
2944 HFXO0->CTRL_SET = HFXO_CTRL_DISONDEMAND;
2945 #if defined(HFXO_CMD_MANUALOVERRIDE)
2946 HFXO0->CMD = HFXO_CMD_MANUALOVERRIDE;
2947 #endif
2948 #if defined(HFXO_STATUS_FSMLOCK)
2949 while ((HFXO0->STATUS & HFXO_STATUS_FSMLOCK) != 0) {
2950 }
2951 #endif
2952 // Set new TIMEOUTSTEADY value for use on subsequent locks.
2953 HFXO0->XTALCFG = (HFXO0->XTALCFG & ~_HFXO_XTALCFG_TIMEOUTSTEADY_MASK)
2954 | (hfxoInit->timeoutSteady
2955 << _HFXO_XTALCFG_TIMEOUTSTEADY_SHIFT);
2956
2957 // Skip core bias algorithm on subsequent locks.
2958 HFXO0->XTALCTRL_SET = HFXO_XTALCTRL_SKIPCOREBIASOPT;
2959
2960 if (hfxoInit->disOnDemand == false) {
2961 HFXO0->CTRL_CLR = HFXO_CTRL_DISONDEMAND;
2962 }
2963
2964 if (hfxoInit->forceEn == false) {
2965 HFXO0->CTRL_CLR = HFXO_CTRL_FORCEEN;
2966 }
2967 } else {
2968 // Lock HFXO in EXTERNAL SINE mode.
2969
2970 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3) \
2971 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
2972 || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8)
2973 //See [PM-3665] for details.
2974 if (hfxoInit->mode == cmuHfxoOscMode_ExternalSinePkDet) {
2975 HFXO0->XTALCFG = 0;
2976 HFXO0->XTALCTRL = 0;
2977
2978 const uint32_t PKDETTHSTARTUP_PARAMETER_1 = 2UL;
2979 BUS_RegMaskedWrite((volatile uint32_t *)(HFXO0_BASE + 0x34U),
2980 0x0000F000U | 0x00000F00U,
2981 (PKDETTHSTARTUP_PARAMETER_1 << 12) | (PKDETTHSTARTUP_PARAMETER_1 << 8));
2982 }
2983 #endif
2984
2985 HFXO0->CTRL = (HFXO0->CTRL & ~(_HFXO_CTRL_FORCEXO2GNDANA_MASK
2986 | _HFXO_CTRL_FORCEXI2GNDANA_MASK
2987 | _HFXO_CTRL_DISONDEMAND_MASK
2988 #if defined(HFXO_CTRL_EM23ONDEMAND)
2989 | _HFXO_CTRL_EM23ONDEMAND_MASK
2990 #endif
2991 | _HFXO_CTRL_FORCEEN_MASK))
2992 | (hfxoInit->forceXo2GndAna << _HFXO_CTRL_FORCEXO2GNDANA_SHIFT)
2993 | (hfxoInit->disOnDemand << _HFXO_CTRL_DISONDEMAND_SHIFT)
2994 #if defined(HFXO_CTRL_EM23ONDEMAND)
2995 | (hfxoInit->em23OnDemand << _HFXO_CTRL_EM23ONDEMAND_SHIFT)
2996 #endif
2997 | (hfxoInit->forceEn << _HFXO_CTRL_FORCEEN_SHIFT);
2998 }
2999
3000 if (hfxoInit->regLock) {
3001 HFXO0->LOCK = ~HFXO_LOCK_LOCKKEY_UNLOCK;
3002 }
3003 }
3004
3005 #if defined(HFXO0_BUFOUT)
3006 /**************************************************************************//**
3007 * @brief
3008 * Initialize HFXO Bufout (Crystal sharing) leader control registers.
3009 * Configure the bufout request input GPIO as a clock request signal
3010 * to add the crystal sharing follower chip as a source of clock request.
3011 *
3012 * @warning
3013 * If EM2 capabilities are needed, a GPIO that fully retains its
3014 * capabilities while in EM2 must be selected.
3015 *
3016 * @param[in] bufoutInit
3017 * Bufout setup parameters.
3018 *
3019 * @param[in] port
3020 * Bufout request GPIO port.
3021 *
3022 * @param[in] pin
3023 * Bufout request GPIO pin.
3024 *****************************************************************************/
CMU_HFXOStartCrystalSharingLeader(const CMU_BUFOUTLeaderInit_TypeDef * bufoutInit,GPIO_Port_TypeDef port,unsigned int pin)3025 void CMU_HFXOStartCrystalSharingLeader(const CMU_BUFOUTLeaderInit_TypeDef *bufoutInit,
3026 GPIO_Port_TypeDef port,
3027 unsigned int pin)
3028 {
3029 EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
3030
3031 // Configure Bufout request GPIO.
3032 GPIO_PinModeSet(port, pin, gpioModeInput, 0U);
3033 GPIO->SYXOROUTE[0].BUFOUTREQINASYNCROUTE = pin << _GPIO_SYXO_BUFOUTREQINASYNCROUTE_PIN_SHIFT
3034 | port << _GPIO_SYXO_BUFOUTREQINASYNCROUTE_PORT_SHIFT;
3035
3036 bool wasLocked = HFXO0->STATUS & HFXO_STATUS_LOCK_LOCKED ? true : false;
3037
3038 // Unlock register interface.
3039 HFXO0->LOCK = HFXO_LOCK_LOCKKEY_UNLOCK;
3040
3041 HFXO0->CTRL_CLR = _HFXO_CTRL_BUFOUTFREEZE_MASK | _HFXO_CTRL_DISONDEMANDBUFOUT_MASK;
3042
3043 BUS_RegMaskedWrite(&HFXO0->BUFOUTCTRL,
3044 _HFXO_BUFOUTCTRL_MINIMUMSTARTUPDELAY_MASK
3045 | _HFXO_BUFOUTCTRL_TIMEOUTSTARTUP_MASK,
3046 bufoutInit->minimalStartupDelay << _HFXO_BUFOUTCTRL_MINIMUMSTARTUPDELAY_SHIFT
3047 | bufoutInit->timeoutStartup << _HFXO_BUFOUTCTRL_TIMEOUTSTARTUP_SHIFT);
3048
3049 if (wasLocked) {
3050 HFXO0->LOCK = ~HFXO_LOCK_LOCKKEY_UNLOCK;
3051 }
3052 }
3053 #endif
3054
3055 #if defined(_HFXO_CTRL_PRSSTATUSSEL0_MASK)
3056 /**************************************************************************//**
3057 * @brief
3058 * Initialize HFXO Bufout (Crystal sharing) follower control registers.
3059 * Configure the clock request signal to a specified GPIO to automatically
3060 * request the high frequency crystal oscillator sine wave clock.
3061 * This function must be used in conjunction with CMU_HFXOInit() configured
3062 * with EXTERNAL_SINE or EXTERNAL_SINEPKDET mode.
3063 *
3064 * @warning
3065 * If EM2 capabilities are needed, a GPIO that fully retains its
3066 * capabilities while in EM2 must be selected.
3067 *
3068 * @note
3069 * This function can be emulated on XG21/XG22 chips by controlling the clock
3070 * request GPIO to ask the crystal sharing leader clock when needed.
3071 *
3072 * @param[in] prsStatusSelectOutput
3073 * Selected HFXO PRS signal output.
3074 *
3075 * @param[in] prsAsyncCh
3076 * PRS producer asynchronous signal channel.
3077 *
3078 * @param[in] port
3079 * Bufout request GPIO port.
3080 *
3081 * @param[in] pin
3082 * Bufout request GPIO pin.
3083 *****************************************************************************/
CMU_HFXOCrystalSharingFollowerInit(CMU_PRS_Status_Output_Select_TypeDef prsStatusSelectOutput,unsigned int prsAsyncCh,GPIO_Port_TypeDef port,unsigned int pin)3084 void CMU_HFXOCrystalSharingFollowerInit(CMU_PRS_Status_Output_Select_TypeDef prsStatusSelectOutput,
3085 unsigned int prsAsyncCh,
3086 GPIO_Port_TypeDef port,
3087 unsigned int pin)
3088 {
3089 EFM_ASSERT(prsAsyncCh < PRS_ASYNC_CH_NUM);
3090 EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
3091
3092 uint32_t mask = 0U, prsSignal = 0U, value = 0U;
3093
3094 switch (prsStatusSelectOutput) {
3095 case PRS_Status_select_0:
3096 mask = _HFXO_CTRL_PRSSTATUSSEL0_MASK;
3097 value = _HFXO_CTRL_PRSSTATUSSEL0_ENS << _HFXO_CTRL_PRSSTATUSSEL0_SHIFT;
3098 prsSignal = _PRS_ASYNC_CH_CTRL_SIGSEL_HFXO0LSTATUS;
3099 break;
3100
3101 case PRS_Status_select_1:
3102 mask = _HFXO_CTRL_PRSSTATUSSEL1_MASK;
3103 value = _HFXO_CTRL_PRSSTATUSSEL1_ENS << _HFXO_CTRL_PRSSTATUSSEL1_SHIFT;
3104 prsSignal = _PRS_ASYNC_CH_CTRL_SIGSEL_HFXO0LSTATUS1;
3105 break;
3106
3107 default:
3108 EFM_ASSERT(false);
3109 break;
3110 }
3111
3112 bool wasLocked = HFXO0->STATUS & HFXO_STATUS_LOCK_LOCKED ? true : false;
3113
3114 // Unlock register interface.
3115 HFXO0->LOCK = HFXO_LOCK_LOCKKEY_UNLOCK;
3116
3117 BUS_RegMaskedWrite(&HFXO0->CTRL, mask, value);
3118
3119 if (wasLocked) {
3120 HFXO0->LOCK = ~HFXO_LOCK_LOCKKEY_UNLOCK;
3121 }
3122
3123 value = _PRS_ASYNC_CH_CTRL_AUXSEL_DEFAULT << _PRS_ASYNC_CH_CTRL_AUXSEL_SHIFT
3124 | _PRS_ASYNC_CH_CTRL_FNSEL_A << _PRS_ASYNC_CH_CTRL_FNSEL_SHIFT
3125 | _PRS_ASYNC_CH_CTRL_SOURCESEL_HFXO0L << _PRS_ASYNC_CH_CTRL_SOURCESEL_SHIFT
3126 | prsSignal << _PRS_ASYNC_CH_CTRL_SIGSEL_SHIFT;
3127
3128 mask = _PRS_ASYNC_CH_CTRL_AUXSEL_MASK
3129 | _PRS_ASYNC_CH_CTRL_FNSEL_MASK
3130 | _PRS_ASYNC_CH_CTRL_SOURCESEL_MASK
3131 | _PRS_ASYNC_CH_CTRL_SIGSEL_MASK;
3132
3133 BUS_RegMaskedWrite(&(PRS->ASYNC_CH[prsAsyncCh].CTRL), mask, value);
3134
3135 GPIO_PinModeSet(port, pin, gpioModeWiredOrPullDown, 0U);
3136
3137 (&(GPIO->PRSROUTE[0].ASYNCH0ROUTE))[prsAsyncCh] = pin << _GPIO_PRS_ASYNCH0ROUTE_PIN_SHIFT
3138 | port << _GPIO_PRS_ASYNCH0ROUTE_PORT_SHIFT;
3139 GPIO->PRSROUTE[0].ROUTEEN = 1U << (_GPIO_PRS_ROUTEEN_ASYNCH0PEN_SHIFT + prsAsyncCh);
3140 }
3141 #endif
3142
3143 /**************************************************************************//**
3144 * @brief
3145 * Set the HFXO crystal tuning capacitance.
3146 *
3147 * @param[in] ctune
3148 * The desired tuning capacitance value. Each step corresponds to
3149 * approximately 80fF. Min value is 0. Max value is 255.
3150 *
3151 * @note
3152 * While the oscillator is running in steady operation state, it may be
3153 * desirable to modify the tuning capacitance via CTUNEXIANA and CTUNEXOANA
3154 * fields in the HFXO_XTALCTRL register. When tuning, care should be taken to
3155 * make small changes to the CTUNE registers. Ideally, change the CTUNE
3156 * registers by one LSB at a time and alternate between the XI and XO
3157 * registers. Sufficient wait time for settling, on the order of
3158 * TIMEOUTSTEADY, should pass before new frequency measurement is taken.
3159 *****************************************************************************/
CMU_HFXOCTuneSet(uint32_t ctune)3160 void CMU_HFXOCTuneSet(uint32_t ctune)
3161 {
3162 uint32_t hfxoCtrlBkup;
3163
3164 // Make sure the given CTUNE value is within the allowable range
3165 EFM_ASSERT(ctune <= (_HFXO_XTALCTRL_CTUNEXIANA_MASK >> _HFXO_XTALCTRL_CTUNEXIANA_SHIFT));
3166
3167 hfxoCtrlBkup = HFXO0->CTRL;
3168
3169 // These two bits need to be set to allow writing the ctune register
3170 HFXO0->CTRL_SET = HFXO_CTRL_FORCEEN;
3171 while ((HFXO0->STATUS & HFXO_STATUS_COREBIASOPTRDY) == 0) {
3172 // Wait for crystal to startup
3173 }
3174
3175 HFXO0->CTRL_SET = HFXO_CTRL_DISONDEMAND;
3176
3177 #if defined(HFXO_CMD_MANUALOVERRIDE)
3178 HFXO0->CMD_SET = HFXO_CMD_MANUALOVERRIDE;
3179 #endif
3180
3181 #if defined(HFXO_STATUS_FSMLOCK)
3182 while ((HFXO0->STATUS & HFXO_STATUS_FSMLOCK) != 0) {
3183 // Wait for crystal to switch modes.
3184 }
3185 #endif
3186
3187 int32_t ctuneXoana = ctune + CMU_HFXOCTuneDeltaGet();
3188 if (ctuneXoana < 0) {
3189 ctuneXoana = 0;
3190 } else if (ctuneXoana > (int32_t)(_HFXO_XTALCTRL_CTUNEXOANA_MASK >> _HFXO_XTALCTRL_CTUNEXOANA_SHIFT)) {
3191 ctuneXoana = (int32_t)(_HFXO_XTALCTRL_CTUNEXOANA_MASK >> _HFXO_XTALCTRL_CTUNEXOANA_SHIFT); // Max value
3192 }
3193
3194 HFXO0->XTALCTRL = ((HFXO0->XTALCTRL & ~(_HFXO_XTALCTRL_CTUNEXOANA_MASK | _HFXO_XTALCTRL_CTUNEXIANA_MASK))
3195 | ((uint32_t)ctuneXoana << _HFXO_XTALCTRL_CTUNEXOANA_SHIFT)
3196 | ((ctune << _HFXO_XTALCTRL_CTUNEXIANA_SHIFT) & _HFXO_XTALCTRL_CTUNEXIANA_MASK));
3197
3198 HFXO0->CTRL = hfxoCtrlBkup;
3199 }
3200
3201 /**************************************************************************//**
3202 * @brief
3203 * Get the HFXO crystal tuning capacitance.
3204 *
3205 * @return
3206 * The HFXO crystal tuning capacitance.
3207 *
3208 * @note
3209 This function only returns the CTUNE XI value. The XO value can be
3210 different and can be found using the delta (difference between XI and XO).
3211 See @ref CMU_HFXOCTuneDeltaGet to retrieve the delta value.
3212 *****************************************************************************/
CMU_HFXOCTuneGet(void)3213 uint32_t CMU_HFXOCTuneGet(void)
3214 {
3215 return ((HFXO0->XTALCTRL & _HFXO_XTALCTRL_CTUNEXIANA_MASK)
3216 >> _HFXO_XTALCTRL_CTUNEXIANA_SHIFT);
3217 }
3218
3219 /**************************************************************************//**
3220 * @brief
3221 * Set the HFXO crystal tuning delta.
3222 *
3223 * @param[in] delta
3224 * Chip dependent crystal capacitor bank delta between HFXO XI and XO.
3225 *
3226 * @note
3227 * The delta between XI and XO is applicable for the series 2 EFR32xG2x
3228 * devices only.
3229 *****************************************************************************/
CMU_HFXOCTuneDeltaSet(int32_t delta)3230 void CMU_HFXOCTuneDeltaSet(int32_t delta)
3231 {
3232 ctuneDelta = (int8_t)delta;
3233 }
3234
3235 /**************************************************************************//**
3236 * @brief
3237 * Get the HFXO crystal tuning delta.
3238 *
3239 * @return
3240 * Chip dependent crystal capacitor bank tuning delta.
3241 *****************************************************************************/
CMU_HFXOCTuneDeltaGet(void)3242 int32_t CMU_HFXOCTuneDeltaGet(void)
3243 {
3244 return (int32_t)ctuneDelta;
3245 }
3246
3247 /**************************************************************************//**
3248 * @brief
3249 * Initialize LFXO control registers.
3250 *
3251 * @note
3252 * LFXO configuration should be obtained from a configuration tool,
3253 * app note or crystal datasheet. This function disables the LFXO to ensure
3254 * a valid state before update.
3255 *
3256 * @param[in] lfxoInit
3257 * LFXO setup parameters
3258 *****************************************************************************/
CMU_LFXOInit(const CMU_LFXOInit_TypeDef * lfxoInit)3259 void CMU_LFXOInit(const CMU_LFXOInit_TypeDef *lfxoInit)
3260 {
3261 EFM_ASSERT(lfxoInit->timeout
3262 <= (_LFXO_CFG_TIMEOUT_MASK >> _LFXO_CFG_TIMEOUT_SHIFT));
3263 EFM_ASSERT(lfxoInit->mode
3264 <= (_LFXO_CFG_MODE_MASK >> _LFXO_CFG_MODE_SHIFT));
3265 EFM_ASSERT(lfxoInit->gain
3266 <= (_LFXO_CAL_GAIN_MASK >> _LFXO_CAL_GAIN_SHIFT));
3267 EFM_ASSERT(lfxoInit->capTune
3268 <= (_LFXO_CAL_CAPTUNE_MASK >> _LFXO_CAL_CAPTUNE_SHIFT));
3269
3270 // Max internal capacitance tuning value is 0x4F (20 pF)
3271 uint8_t ctune = (uint8_t) SL_MIN(0x4FU, lfxoInit->capTune);
3272
3273 #if defined(CMU_CLKEN0_LFXO)
3274 // Enable LFXO module clock.
3275 CMU->CLKEN0_SET = CMU_CLKEN0_LFXO;
3276 #endif
3277
3278 // Unlock register interface
3279 LFXO->LOCK = LFXO_LOCK_LOCKKEY_UNLOCK;
3280
3281 // Disable LFXO
3282 LFXO->CTRL_SET = LFXO_CTRL_DISONDEMAND;
3283 LFXO->CTRL_CLR = LFXO_CTRL_FORCEEN;
3284 while ((LFXO->STATUS & _LFXO_STATUS_ENS_MASK) != 0U) {
3285 }
3286
3287 // Configure LFXO as specified
3288 LFXO->CAL = ((uint32_t)lfxoInit->gain << _LFXO_CAL_GAIN_SHIFT)
3289 | ((uint32_t)ctune << _LFXO_CAL_CAPTUNE_SHIFT);
3290
3291 LFXO->CFG = (uint32_t)((lfxoInit->timeout << _LFXO_CFG_TIMEOUT_SHIFT)
3292 | (lfxoInit->mode << _LFXO_CFG_MODE_SHIFT)
3293 | (lfxoInit->highAmplitudeEn << _LFXO_CFG_HIGHAMPL_SHIFT)
3294 | (lfxoInit->agcEn << _LFXO_CFG_AGC_SHIFT));
3295
3296 LFXO->CTRL = (uint32_t)((lfxoInit->failDetEM4WUEn << _LFXO_CTRL_FAILDETEM4WUEN_SHIFT)
3297 | (lfxoInit->failDetEn << _LFXO_CTRL_FAILDETEN_SHIFT)
3298 | (lfxoInit->disOnDemand << _LFXO_CTRL_DISONDEMAND_SHIFT)
3299 | (lfxoInit->forceEn << _LFXO_CTRL_FORCEEN_SHIFT));
3300
3301 if (lfxoInit->regLock) {
3302 LFXO->LOCK = ~LFXO_LOCK_LOCKKEY_UNLOCK;
3303 }
3304 }
3305
3306 /**************************************************************************//**
3307 * @brief
3308 * Sets LFXO's crystal precision, in PPM.
3309 *
3310 * @note
3311 * LFXO precision should be obtained from a crystal datasheet.
3312 *
3313 * @param[in] precision
3314 * LFXO's crystal precision, in PPM.
3315 *****************************************************************************/
CMU_LFXOPrecisionSet(uint16_t precision)3316 void CMU_LFXOPrecisionSet(uint16_t precision)
3317 {
3318 lfxo_precision = precision;
3319 }
3320
3321 /**************************************************************************//**
3322 * @brief
3323 * Gets LFXO's crystal precision, in PPM.
3324 *
3325 * @param[in] precision
3326 * LFXO's crystal precision, in PPM.
3327 *****************************************************************************/
CMU_LFXOPrecisionGet(void)3328 uint16_t CMU_LFXOPrecisionGet(void)
3329 {
3330 return lfxo_precision;
3331 }
3332
3333 #if defined(PLFRCO_PRESENT)
3334 /**************************************************************************//**
3335 * @brief
3336 * Configure the LFRCO precision.
3337 *
3338 * @details
3339 * When enabling high precision mode on the LFRCO the hardware will tune
3340 * the oscillator automatically using the HFXO as a reference.
3341 *
3342 * @note
3343 * Refer to the reference manual and the datasheet for details about
3344 * NOMCAL and NOMCALINV calibration count values.
3345 *
3346 * @param[in] precision
3347 * LFRCO precision, this can be either high or default.
3348 *****************************************************************************/
CMU_LFRCOSetPrecision(CMU_Precision_TypeDef precision)3349 void CMU_LFRCOSetPrecision(CMU_Precision_TypeDef precision)
3350 {
3351 uint32_t ref = 0;
3352 uint32_t nomcal = 0;
3353 uint32_t nomcalinv = 0;
3354
3355 CMU->CLKEN0_SET = CMU_CLKEN0_LFRCO;
3356
3357 LFRCO->CTRL = LFRCO_CTRL_DISONDEMAND; // Force disable
3358 while ((LFRCO->STATUS & LFRCO_STATUS_ENS) != 0U) {
3359 // Wait for LFRCO to stop
3360 }
3361
3362 if (precision == cmuPrecisionHigh) {
3363 ref = SystemHFXOClockGet();
3364 // Use precomputed value for HFXO typical frequencies
3365 if (ref == XTAL_38M4) {
3366 nomcal = LFRCO_NOMCAL_XTAL_38M4;
3367 nomcalinv = LFRCO_NOMCALINV_XTAL_38M4;
3368 } else if (ref == XTAL_39M0) {
3369 nomcal = LFRCO_NOMCAL_XTAL_39M0;
3370 nomcalinv = LFRCO_NOMCALINV_XTAL_39M0;
3371 } else {
3372 // Compute calibration count, based on HFXO frequency
3373 nomcal = (5 * ref) >> 9;
3374 nomcalinv = ((1UL << 31) / 5) << 2;
3375 nomcalinv /= (ref >> 9);
3376 }
3377
3378 LFRCO->NOMCAL = nomcal;
3379 LFRCO->NOMCALINV = nomcalinv;
3380
3381 LFRCO->CFG = LFRCO_CFG_HIGHPRECEN;
3382 } else {
3383 LFRCO->CFG = 0;
3384 }
3385 LFRCO->CTRL = _LFRCO_CTRL_RESETVALUE;
3386 }
3387 #endif
3388
3389 /***************************************************************************//**
3390 * @brief
3391 * Get oscillator frequency tuning setting.
3392 *
3393 * @param[in] osc
3394 * Oscillator to get tuning value for.
3395 *
3396 * @return
3397 * The oscillator frequency tuning setting in use.
3398 ******************************************************************************/
CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)3399 uint32_t CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)
3400 {
3401 uint32_t ret = 0U;
3402
3403 switch (osc) {
3404 #if defined(_LFRCO_CAL_FREQTRIM_MASK)
3405 case cmuOsc_LFRCO:
3406 #if defined(CMU_CLKEN0_LFRCO)
3407 CMU->CLKEN0_SET = CMU_CLKEN0_LFRCO;
3408 #endif
3409 ret = (LFRCO->CAL & _LFRCO_CAL_FREQTRIM_MASK) >> _LFRCO_CAL_FREQTRIM_SHIFT;
3410 break;
3411 #endif
3412
3413 case cmuOsc_HFRCODPLL:
3414 #if defined(CMU_CLKEN0_HFRCO0)
3415 CMU->CLKEN0_SET = CMU_CLKEN0_HFRCO0;
3416 #endif
3417 ret = (HFRCO0->CAL & _HFRCO_CAL_TUNING_MASK) >> _HFRCO_CAL_TUNING_SHIFT;
3418 break;
3419
3420 #if defined(HFRCOEM23_PRESENT)
3421 case cmuOsc_HFRCOEM23:
3422 ret = (HFRCOEM23->CAL & _HFRCO_CAL_TUNING_MASK) >> _HFRCO_CAL_TUNING_SHIFT;
3423 break;
3424 #endif
3425
3426 case cmuOsc_HFXO:
3427 #if defined(CMU_CLKEN0_HFXO0)
3428 CMU->CLKEN0_SET = CMU_CLKEN0_HFXO0;
3429 #endif
3430 ret = (HFXO0->XTALCTRL & _HFXO_XTALCTRL_COREBIASANA_MASK) >> _HFXO_XTALCTRL_COREBIASANA_SHIFT;
3431 break;
3432
3433 default:
3434 EFM_ASSERT(false);
3435 break;
3436 }
3437
3438 return ret;
3439 }
3440
3441 /***************************************************************************//**
3442 * @brief
3443 * Set the oscillator frequency tuning control.
3444 *
3445 * @note
3446 * Oscillator tuning is done during production, and the tuning value is
3447 * automatically loaded after a reset. Changing the tuning value from the
3448 * calibrated value is for more advanced use. Certain oscillators also have
3449 * build-in tuning optimization.
3450 *
3451 * @param[in] osc
3452 * Oscillator to set tuning value for.
3453 *
3454 * @param[in] val
3455 * The oscillator frequency tuning setting to use.
3456 ******************************************************************************/
CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc,uint32_t val)3457 void CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc, uint32_t val)
3458 {
3459 bool disondemand = false;
3460
3461 switch (osc) {
3462 #if defined(_LFRCO_CAL_FREQTRIM_MASK)
3463 case cmuOsc_LFRCO:
3464 #if defined(CMU_CLKEN0_LFRCO)
3465 CMU->CLKEN0_SET = CMU_CLKEN0_LFRCO;
3466 #endif
3467 EFM_ASSERT(val <= (_LFRCO_CAL_FREQTRIM_MASK
3468 >> _LFRCO_CAL_FREQTRIM_SHIFT));
3469 val &= _LFRCO_CAL_FREQTRIM_MASK >> _LFRCO_CAL_FREQTRIM_SHIFT;
3470 while (LFRCO->SYNCBUSY != 0U) {
3471 }
3472 LFRCO->CAL = (LFRCO->CAL & ~_LFRCO_CAL_FREQTRIM_MASK)
3473 | (val << _LFRCO_CAL_FREQTRIM_SHIFT);
3474 break;
3475 #endif
3476
3477 case cmuOsc_HFRCODPLL:
3478 #if defined(CMU_CLKEN0_HFRCO0)
3479 CMU->CLKEN0_SET = CMU_CLKEN0_HFRCO0;
3480 #endif
3481 EFM_ASSERT(val <= (_HFRCO_CAL_TUNING_MASK >> _HFRCO_CAL_TUNING_SHIFT));
3482 val &= _HFRCO_CAL_TUNING_MASK >> _HFRCO_CAL_TUNING_SHIFT;
3483 while ((HFRCO0->STATUS & HFRCO_STATUS_SYNCBUSY) != 0UL) {
3484 }
3485 HFRCO0->CAL = (HFRCO0->CAL & ~_HFRCO_CAL_TUNING_MASK)
3486 | (val << _HFRCO_CAL_TUNING_SHIFT);
3487 break;
3488
3489 #if defined(HFRCOEM23_PRESENT)
3490 case cmuOsc_HFRCOEM23:
3491 EFM_ASSERT(val <= (_HFRCO_CAL_TUNING_MASK >> _HFRCO_CAL_TUNING_SHIFT));
3492 val &= _HFRCO_CAL_TUNING_MASK >> _HFRCO_CAL_TUNING_SHIFT;
3493 while ((HFRCOEM23->STATUS & HFRCO_STATUS_SYNCBUSY) != 0UL) {
3494 }
3495 HFRCOEM23->CAL = (HFRCOEM23->CAL & ~_HFRCO_CAL_TUNING_MASK)
3496 | (val << _HFRCO_CAL_TUNING_SHIFT);
3497 break;
3498 #endif
3499
3500 case cmuOsc_HFXO:
3501 #if defined(CMU_CLKEN0_HFXO0)
3502 CMU->CLKEN0_SET = CMU_CLKEN0_HFXO0;
3503 #endif
3504 EFM_ASSERT(val <= (_HFXO_XTALCTRL_COREBIASANA_MASK >> _HFXO_XTALCTRL_COREBIASANA_SHIFT));
3505 // Make sure HFXO is disable
3506 EFM_ASSERT((HFXO0->STATUS & HFXO_STATUS_ENS) == 0);
3507
3508 // Set DISONDEMAND if not already set and wait for FSMLOCK to be clear so that
3509 // software can write to register
3510 disondemand = (HFXO0->CTRL & _HFXO_CTRL_DISONDEMAND_MASK) >> _HFXO_CTRL_DISONDEMAND_SHIFT;
3511 if (disondemand == false) {
3512 HFXO0->CTRL_SET = HFXO_CTRL_DISONDEMAND;
3513 }
3514 #if defined(HFXO_STATUS_FSMLOCK)
3515 while ((HFXO0->STATUS & HFXO_STATUS_FSMLOCK) != 0) {
3516 }
3517 #endif
3518 // Update Core Bias Ana setting and enable Optimization skip
3519 HFXO0->XTALCTRL = (HFXO0->XTALCTRL & ~_HFXO_XTALCTRL_COREBIASANA_MASK)
3520 | (val << _HFXO_XTALCTRL_COREBIASANA_SHIFT)
3521 | HFXO_XTALCTRL_SKIPCOREBIASOPT;
3522 // Clear back DISONDEMAND if needed
3523 if (disondemand == false) {
3524 HFXO0->CTRL_CLR = HFXO_CTRL_DISONDEMAND;
3525 }
3526 break;
3527
3528 default:
3529 EFM_ASSERT(false);
3530 break;
3531 }
3532 }
3533
3534 /***************************************************************************//**
3535 * @brief
3536 * Configure wait state settings necessary to switch to a given core clock
3537 * frequency at a certain voltage scale level.
3538 *
3539 * @details
3540 * This function will set up the necessary flash wait states. Updating the
3541 * wait state configuration must be done before increasing the clock
3542 * frequency and it must be done after decreasing the clock frequency.
3543 * Updating the wait state configuration must be done before core voltage is
3544 * decreased and it must be done after a core voltage is increased.
3545 *
3546 * @param[in] freq
3547 * The core clock frequency to configure wait-states.
3548 *
3549 * @param[in] vscale
3550 * The voltage scale to configure wait-states. Expected values are
3551 * 0 or 1, higher number is lower voltage.
3552 * @li 0 = 1.1 V (VSCALE2)
3553 * @li 1 = 1.0 V (VSCALE1)
3554 ******************************************************************************/
CMU_UpdateWaitStates(uint32_t freq,int vscale)3555 void CMU_UpdateWaitStates(uint32_t freq, int vscale)
3556 {
3557 if (vscale > 0) {
3558 flashWaitStateControl(freq, VSCALE_EM01_LOW_POWER);
3559 } else {
3560 flashWaitStateControl(freq, VSCALE_EM01_HIGH_PERFORMANCE);
3561 }
3562 }
3563
3564 /**************************************************************************//**
3565 * @brief
3566 * Select the PCNTn clock.
3567 *
3568 * @param[in] instance
3569 * PCNT instance number to set selected clock source for.
3570 *
3571 * @param[in] external
3572 * Set to true to select the external clock, false to select EM23GRPACLK.
3573 *****************************************************************************/
CMU_PCNTClockExternalSet(unsigned int instance,bool external)3574 void CMU_PCNTClockExternalSet(unsigned int instance, bool external)
3575 {
3576 (void)instance;
3577 #if defined(PCNT_PRESENT)
3578 if (external) {
3579 CMU->PCNT0CLKCTRL = CMU_PCNT0CLKCTRL_CLKSEL_PCNTS0;
3580 } else {
3581 CMU->PCNT0CLKCTRL = CMU_PCNT0CLKCTRL_CLKSEL_EM23GRPACLK;
3582 }
3583 #else
3584 (void)external;
3585 #endif
3586 }
3587
3588 #if defined(HFRCOEM23_PRESENT)
3589 /***************************************************************************//**
3590 * @brief
3591 * Get HFRCOEM23 band in use.
3592 *
3593 * @return
3594 * HFRCOEM23 band in use.
3595 ******************************************************************************/
CMU_HFRCOEM23BandGet(void)3596 CMU_HFRCOEM23Freq_TypeDef CMU_HFRCOEM23BandGet(void)
3597 {
3598 return (CMU_HFRCOEM23Freq_TypeDef)SystemHFRCOEM23ClockGet();
3599 }
3600
3601 /***************************************************************************//**
3602 * @brief
3603 * Set HFRCOEM23 band and the tuning value based on the value in the
3604 * calibration table made during production.
3605 *
3606 * @param[in] freq
3607 * HFRCOEM23 frequency band to activate.
3608 ******************************************************************************/
CMU_HFRCOEM23BandSet(CMU_HFRCOEM23Freq_TypeDef freq)3609 void CMU_HFRCOEM23BandSet(CMU_HFRCOEM23Freq_TypeDef freq)
3610 {
3611 uint32_t freqCal;
3612
3613 // Get calibration data from DEVINFO
3614 freqCal = HFRCOEM23DevinfoGet(freq);
3615 EFM_ASSERT((freqCal != 0UL) && (freqCal != UINT_MAX));
3616 #if defined(CMU_CLKEN0_HFRCOEM23)
3617 CMU->CLKEN0_SET = CMU_CLKEN0_HFRCOEM23;
3618 #endif
3619
3620 // Set divider for 1, 2 and 4MHz bands
3621 freqCal &= ~_HFRCO_CAL_CLKDIV_MASK;
3622 switch (freq) {
3623 case cmuHFRCOEM23Freq_1M0Hz:
3624 freqCal |= HFRCO_CAL_CLKDIV_DIV4;
3625 break;
3626
3627 case cmuHFRCOEM23Freq_2M0Hz:
3628 freqCal |= HFRCO_CAL_CLKDIV_DIV2;
3629 break;
3630
3631 default:
3632 break;
3633 }
3634
3635 // Activate new band selection
3636 HFRCOEM23->CAL = freqCal;
3637 }
3638 #endif // defined(HFRCOEM23_PRESENT)
3639
3640 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
3641
3642 /*******************************************************************************
3643 ************************** LOCAL FUNCTIONS ********************************
3644 ******************************************************************************/
3645
3646 #if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
3647 #if defined(PDM_PRESENT)
3648 /***************************************************************************//**
3649 * @brief
3650 * Get selected oscillator and frequency for @ref cmuClock_EM01GRPBCLK
3651 * clock tree.
3652 *
3653 * @param[out] freq
3654 * The frequency.
3655 *
3656 * @param[out] sel
3657 * The selected oscillator.
3658 ******************************************************************************/
em01GrpbClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)3659 static void em01GrpbClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
3660 {
3661 uint32_t f = 0U;
3662 CMU_Select_TypeDef s;
3663 switch (CMU->EM01GRPBCLKCTRL & _CMU_EM01GRPBCLKCTRL_CLKSEL_MASK) {
3664 case CMU_EM01GRPBCLKCTRL_CLKSEL_HFRCODPLL:
3665 f = SystemHFRCODPLLClockGet();
3666 s = cmuSelect_HFRCODPLL;
3667 break;
3668
3669 case CMU_EM01GRPBCLKCTRL_CLKSEL_HFRCODPLLRT:
3670 f = SystemHFRCODPLLClockGet();
3671 s = cmuSelect_HFRCODPLLRT;
3672 break;
3673
3674 case CMU_EM01GRPBCLKCTRL_CLKSEL_HFXO:
3675 f = SystemHFXOClockGet();
3676 s = cmuSelect_HFXO;
3677 break;
3678
3679 case CMU_EM01GRPBCLKCTRL_CLKSEL_HFXORT:
3680 f = SystemHFXOClockGet();
3681 s = cmuSelect_HFXORT;
3682 break;
3683
3684 case CMU_EM01GRPBCLKCTRL_CLKSEL_FSRCO:
3685 f = SystemFSRCOClockGet();
3686 s = cmuSelect_FSRCO;
3687 break;
3688
3689 case CMU_EM01GRPBCLKCTRL_CLKSEL_CLKIN0:
3690 f = SystemCLKIN0Get();
3691 s = cmuSelect_CLKIN0;
3692 break;
3693
3694 default:
3695 s = cmuSelect_Error;
3696 EFM_ASSERT(false);
3697 break;
3698 }
3699 if (freq != NULL) {
3700 *freq = f;
3701 }
3702 if (sel != NULL) {
3703 *sel = s;
3704 }
3705 }
3706 #endif
3707
3708 #if defined(EUART_PRESENT)
3709 /***************************************************************************//**
3710 * @brief
3711 * Get selected oscillator and frequency for @ref cmuClock_EUART0CLK
3712 * clock tree.
3713 *
3714 * @param[out] freq
3715 * The frequency.
3716 *
3717 * @param[out] sel
3718 * The selected oscillator.
3719 ******************************************************************************/
euart0ClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)3720 static void euart0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
3721 {
3722 switch (CMU->EUART0CLKCTRL & _CMU_EUART0CLKCTRL_CLKSEL_MASK) {
3723 case CMU_EUART0CLKCTRL_CLKSEL_EM01GRPACLK:
3724 em01GrpaClkGet(freq, sel);
3725 break;
3726
3727 case CMU_EUART0CLKCTRL_CLKSEL_EM23GRPACLK:
3728 em23GrpaClkGet(freq, sel);
3729 break;
3730
3731 default:
3732 if (freq != NULL) {
3733 *freq = 0U;
3734 }
3735 if (sel != NULL) {
3736 *sel = cmuSelect_Error;
3737 }
3738 EFM_ASSERT(false);
3739 break;
3740 }
3741 }
3742 #endif
3743
3744 #if defined(EUSART_PRESENT)
3745 /***************************************************************************//**
3746 * @brief
3747 * Get selected oscillator and frequency for @ref cmuClock_EUSART0CLK
3748 * clock tree.
3749 *
3750 * @param[out] freq
3751 * The frequency.
3752 *
3753 * @param[out] sel
3754 * The selected oscillator.
3755 ******************************************************************************/
eusart0ClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)3756 static void eusart0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
3757 {
3758 uint32_t f = 0U;
3759 CMU_Select_TypeDef s;
3760
3761 switch (CMU->EUSART0CLKCTRL & _CMU_EUSART0CLKCTRL_CLKSEL_MASK) {
3762 #if defined(CMU_EUSART0CLKCTRL_CLKSEL_EM01GRPACLK)
3763 case CMU_EUSART0CLKCTRL_CLKSEL_EM01GRPACLK:
3764 em01GrpaClkGet(&f, NULL);
3765 s = cmuSelect_EM01GRPACLK;
3766 break;
3767 #endif
3768
3769 #if defined(CMU_EUSART0CLKCTRL_CLKSEL_EM01GRPCCLK)
3770 case CMU_EUSART0CLKCTRL_CLKSEL_EM01GRPCCLK:
3771 em01GrpcClkGet(&f, NULL);
3772 s = cmuSelect_EM01GRPCCLK;
3773 break;
3774 #endif
3775
3776 #if defined(CMU_EUSART0CLKCTRL_CLKSEL_EM23GRPACLK)
3777 case CMU_EUSART0CLKCTRL_CLKSEL_EM23GRPACLK:
3778 em23GrpaClkGet(&f, NULL);
3779 s = cmuSelect_EM23GRPACLK;
3780 break;
3781 #endif
3782
3783 #if defined(CMU_EUSART0CLKCTRL_CLKSEL_FSRCO)
3784 case CMU_EUSART0CLKCTRL_CLKSEL_FSRCO:
3785 f = SystemFSRCOClockGet();
3786 s = cmuSelect_FSRCO;
3787 break;
3788 #endif
3789
3790 #if defined(CMU_EUSART0CLKCTRL_CLKSEL_HFRCOEM23)
3791 case CMU_EUSART0CLKCTRL_CLKSEL_HFRCOEM23:
3792 f = SystemHFRCOEM23ClockGet();
3793 s = cmuSelect_HFRCOEM23;
3794 break;
3795 #endif
3796
3797 #if defined(CMU_EUSART0CLKCTRL_CLKSEL_LFRCO)
3798 case CMU_EUSART0CLKCTRL_CLKSEL_LFRCO:
3799 f = SystemLFRCOClockGet();
3800 s = cmuSelect_LFRCO;
3801 break;
3802 #endif
3803
3804 #if defined(CMU_EUSART0CLKCTRL_CLKSEL_LFXO)
3805 case CMU_EUSART0CLKCTRL_CLKSEL_LFXO:
3806 f = SystemLFXOClockGet();
3807 s = cmuSelect_LFXO;
3808 break;
3809 #endif
3810
3811 default:
3812 s = cmuSelect_Error;
3813 EFM_ASSERT(false);
3814 break;
3815 }
3816 if (freq != NULL) {
3817 *freq = f;
3818 }
3819 if (sel != NULL) {
3820 *sel = s;
3821 }
3822 }
3823
3824 #if defined(_CMU_EM01GRPCCLKCTRL_MASK)
3825 /**************************************************************************//**
3826 * @brief
3827 * Get selected oscillator and frequency for @ref cmuClock_EM01GRPCCLK
3828 * clock tree.
3829 *
3830 * @param[out] freq
3831 * The frequency.
3832 *
3833 * @param[out] sel
3834 * The selected oscillator.
3835 ******************************************************************************/
em01GrpcClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)3836 static void em01GrpcClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
3837 {
3838 uint32_t f = 0U;
3839 CMU_Select_TypeDef s;
3840
3841 switch (CMU->EM01GRPCCLKCTRL & _CMU_EM01GRPCCLKCTRL_CLKSEL_MASK) {
3842 case CMU_EM01GRPCCLKCTRL_CLKSEL_HFRCODPLL:
3843 f = SystemHFRCODPLLClockGet();
3844 s = cmuSelect_HFRCODPLL;
3845 break;
3846
3847 #if defined(CMU_EM01GRPCCLKCTRL_CLKSEL_HFRCODPLLRT)
3848 case CMU_EM01GRPCCLKCTRL_CLKSEL_HFRCODPLLRT:
3849 f = SystemHFRCODPLLClockGet();
3850 s = cmuSelect_HFRCODPLLRT;
3851 break;
3852 #endif
3853
3854 case _CMU_EM01GRPCCLKCTRL_CLKSEL_HFRCOEM23:
3855 f = SystemHFRCOEM23ClockGet();
3856 s = cmuSelect_HFRCOEM23;
3857 break;
3858
3859 case CMU_EM01GRPCCLKCTRL_CLKSEL_HFXO:
3860 f = SystemHFXOClockGet();
3861 s = cmuSelect_HFXO;
3862 break;
3863
3864 #if defined(CMU_EM01GRPCCLKCTRL_CLKSEL_HFXORT)
3865 case CMU_EM01GRPCCLKCTRL_CLKSEL_HFXORT:
3866 f = SystemHFXOClockGet();
3867 s = cmuSelect_HFXORT;
3868 break;
3869 #endif
3870
3871 case _CMU_EM01GRPCCLKCTRL_CLKSEL_FSRCO:
3872 f = SystemFSRCOClockGet();
3873 s = cmuSelect_FSRCO;
3874 break;
3875
3876 default:
3877 s = cmuSelect_Error;
3878 EFM_ASSERT(false);
3879 break;
3880 }
3881 if (freq != NULL) {
3882 *freq = f;
3883 }
3884 if (sel != NULL) {
3885 *sel = s;
3886 }
3887 }
3888 #endif // defined(_CMU_EM01GRPCCLKCTRL_MASK)
3889 #endif // defined(EUSART_PRESENT)
3890
3891 #if defined(LCD_PRESENT)
3892 /***************************************************************************//**
3893 * @brief
3894 * Get selected oscillator and frequency for @ref cmuClock_LCDCLK
3895 * clock tree.
3896 *
3897 * @param[out] freq
3898 * The frequency.
3899 *
3900 * @param[out] sel
3901 * The selected oscillator.
3902 ******************************************************************************/
lcdClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)3903 static void lcdClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
3904 {
3905 uint32_t f = 0U;
3906 CMU_Select_TypeDef s;
3907
3908 switch (CMU->LCDCLKCTRL & _CMU_LCDCLKCTRL_CLKSEL_MASK) {
3909 case CMU_LCDCLKCTRL_CLKSEL_ULFRCO:
3910 f = SystemULFRCOClockGet();
3911 s = cmuSelect_ULFRCO;
3912 break;
3913
3914 case CMU_LCDCLKCTRL_CLKSEL_LFRCO:
3915 f = SystemLFRCOClockGet();
3916 s = cmuSelect_LFRCO;
3917 break;
3918
3919 case CMU_LCDCLKCTRL_CLKSEL_LFXO:
3920 f = SystemLFXOClockGet();
3921 s = cmuSelect_LFXO;
3922 break;
3923
3924 default:
3925 s = cmuSelect_Error;
3926 EFM_ASSERT(false);
3927 break;
3928 }
3929 if (freq != NULL) {
3930 *freq = f;
3931 }
3932 if (sel != NULL) {
3933 *sel = s;
3934 }
3935 }
3936 #endif // defined(LCD_PRESENT)
3937
3938 #if defined(VDAC_PRESENT)
3939 /***************************************************************************//**
3940 * @brief
3941 * Get selected oscillator and frequency for @ref cmuClock_VDAC0CLK
3942 * clock tree.
3943 *
3944 * @param[out] freq
3945 * The frequency.
3946 *
3947 * @param[out] sel
3948 * The selected oscillator.
3949 ******************************************************************************/
vdac0ClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)3950 static void vdac0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
3951 {
3952 uint32_t f = 0U;
3953 CMU_Select_TypeDef s;
3954
3955 switch (CMU->VDAC0CLKCTRL & _CMU_VDAC0CLKCTRL_CLKSEL_MASK) {
3956 case CMU_VDAC0CLKCTRL_CLKSEL_EM01GRPACLK:
3957 em01GrpaClkGet(&f, NULL);
3958 s = cmuSelect_EM01GRPACLK;
3959 break;
3960
3961 case CMU_VDAC0CLKCTRL_CLKSEL_EM23GRPACLK:
3962 em23GrpaClkGet(&f, NULL);
3963 s = cmuSelect_EM23GRPACLK;
3964 break;
3965
3966 case CMU_VDAC0CLKCTRL_CLKSEL_HFRCOEM23:
3967 f = SystemHFRCOEM23ClockGet();
3968 s = cmuSelect_HFRCOEM23;
3969 break;
3970
3971 case CMU_VDAC0CLKCTRL_CLKSEL_FSRCO:
3972 f = SystemFSRCOClockGet();
3973 s = cmuSelect_FSRCO;
3974 break;
3975
3976 default:
3977 s = cmuSelect_Error;
3978 EFM_ASSERT(false);
3979 break;
3980 }
3981 if (freq != NULL) {
3982 *freq = f;
3983 }
3984 if (sel != NULL) {
3985 *sel = s;
3986 }
3987 }
3988
3989 #if (VDAC_COUNT > 1)
3990 /***************************************************************************//**
3991 * @brief
3992 * Get selected oscillator and frequency for @ref cmuClock_VDAC1CLK
3993 * clock tree.
3994 *
3995 * @param[out] freq
3996 * The frequency.
3997 *
3998 * @param[out] sel
3999 * The selected oscillator.
4000 ******************************************************************************/
vdac1ClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4001 static void vdac1ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4002 {
4003 uint32_t f = 0U;
4004 CMU_Select_TypeDef s;
4005
4006 switch (CMU->VDAC1CLKCTRL & _CMU_VDAC1CLKCTRL_CLKSEL_MASK) {
4007 case CMU_VDAC1CLKCTRL_CLKSEL_EM01GRPACLK:
4008 em01GrpaClkGet(&f, NULL);
4009 s = cmuSelect_EM01GRPACLK;
4010 break;
4011
4012 case CMU_VDAC1CLKCTRL_CLKSEL_EM23GRPACLK:
4013 em23GrpaClkGet(&f, NULL);
4014 s = cmuSelect_EM23GRPACLK;
4015 break;
4016
4017 case CMU_VDAC1CLKCTRL_CLKSEL_HFRCOEM23:
4018 f = SystemHFRCOEM23ClockGet();
4019 s = cmuSelect_HFRCOEM23;
4020 break;
4021
4022 case CMU_VDAC1CLKCTRL_CLKSEL_FSRCO:
4023 f = SystemFSRCOClockGet();
4024 s = cmuSelect_FSRCO;
4025 break;
4026
4027 default:
4028 s = cmuSelect_Error;
4029 EFM_ASSERT(false);
4030 break;
4031 }
4032 if (freq != NULL) {
4033 *freq = f;
4034 }
4035 if (sel != NULL) {
4036 *sel = s;
4037 }
4038 }
4039 #endif
4040 #endif /* VDAC_PRESENT */
4041
4042 #if defined(PCNT_PRESENT)
4043 /***************************************************************************//**
4044 * @brief
4045 * Get selected oscillator and frequency for @ref cmuClock_PCNT0CLK
4046 * clock tree.
4047 *
4048 * @param[out] freq
4049 * The frequency.
4050 *
4051 * @param[out] sel
4052 * The selected oscillator.
4053 ******************************************************************************/
pcnt0ClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4054 static void pcnt0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4055 {
4056 uint32_t f = 0U;
4057 CMU_Select_TypeDef s;
4058
4059 switch (CMU->PCNT0CLKCTRL & _CMU_PCNT0CLKCTRL_CLKSEL_MASK) {
4060 case CMU_PCNT0CLKCTRL_CLKSEL_EM23GRPACLK:
4061 em23GrpaClkGet(&f, NULL);
4062 s = cmuSelect_EM23GRPACLK;
4063 break;
4064
4065 case CMU_PCNT0CLKCTRL_CLKSEL_PCNTS0:
4066 f = 0U; // external or PRS source so the frequency is undefined.
4067 s = cmuSelect_PCNTEXTCLK;
4068 break;
4069
4070 default:
4071 s = cmuSelect_Error;
4072 EFM_ASSERT(false);
4073 break;
4074 }
4075 if (freq != NULL) {
4076 *freq = f;
4077 }
4078 if (sel != NULL) {
4079 *sel = s;
4080 }
4081 }
4082 #endif
4083
4084 #if defined(LESENSE_PRESENT)
4085 /***************************************************************************//**
4086 * @brief
4087 * Get selected oscillator and frequency for @ref cmuClock_LESENSEHFCLK
4088 * clock tree.
4089 *
4090 * @param[out] freq
4091 * The frequency.
4092 *
4093 * @param[out] sel
4094 * The selected oscillator.
4095 ******************************************************************************/
lesenseHFClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4096 static void lesenseHFClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4097 {
4098 uint32_t f = 0U;
4099 CMU_Select_TypeDef s;
4100
4101 switch (CMU->LESENSEHFCLKCTRL & _CMU_LESENSEHFCLKCTRL_CLKSEL_MASK) {
4102 case CMU_LESENSEHFCLKCTRL_CLKSEL_HFRCOEM23:
4103 f = SystemHFRCOEM23ClockGet();
4104 s = cmuSelect_HFRCOEM23;
4105 break;
4106
4107 case CMU_LESENSEHFCLKCTRL_CLKSEL_FSRCO:
4108 f = SystemFSRCOClockGet();
4109 s = cmuSelect_FSRCO;
4110 break;
4111
4112 default:
4113 s = cmuSelect_Error;
4114 EFM_ASSERT(false);
4115 break;
4116 }
4117 if (freq != NULL) {
4118 *freq = f;
4119 }
4120 if (sel != NULL) {
4121 *sel = s;
4122 }
4123 }
4124 #endif
4125
4126 #if ((defined(CMU_SYSCLKCTRL_RHCLKPRESC)) \
4127 && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
4128 /***************************************************************************//**
4129 * @brief
4130 * Set maximum allowed prescaler for radio clock tree (RHCLK).
4131 ******************************************************************************/
rhclkPrescMax(void)4132 static void rhclkPrescMax(void)
4133 {
4134 // Set largest prescaler (DIV2).
4135 CMU->SYSCLKCTRL_SET = CMU_SYSCLKCTRL_RHCLKPRESC;
4136 }
4137
4138 /***************************************************************************//**
4139 * @brief
4140 * Set radio clock tree prescaler to achieve highest possible frequency
4141 * and still be within spec.
4142 ******************************************************************************/
rhclkPrescOptimize(void)4143 static void rhclkPrescOptimize(void)
4144 {
4145 if (CMU_ClockFreqGet(cmuClock_SYSCLK) <= CMU_MAX_RHCLK_FREQ) {
4146 // Set smallest prescaler (DIV1).
4147 CMU->SYSCLKCTRL_CLR = CMU_SYSCLKCTRL_RHCLKPRESC;
4148 }
4149 }
4150 #endif // ((defined(CMU_SYSCLKCTRL_RHCLKPRESC)) && (_SILICON_LABS_EFR32_RADIO_TYPE != _SILICON_LABS_EFR32_RADIO_NONE))
4151 #endif // #if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
4152
4153 #if defined(HFRCOEM23_PRESENT)
4154 /***************************************************************************//**
4155 * @brief
4156 * Get calibrated HFRCOEM23 tuning value from Device information (DI) page
4157 * for a given frequency. Calibration value is not available for all frequency
4158 * bands.
4159 *
4160 * @param[in] freq
4161 * HFRCOEM23 frequency band
4162 ******************************************************************************/
HFRCOEM23DevinfoGet(CMU_HFRCOEM23Freq_TypeDef freq)4163 static uint32_t HFRCOEM23DevinfoGet(CMU_HFRCOEM23Freq_TypeDef freq)
4164 {
4165 uint32_t ret = 0U;
4166
4167 switch (freq) {
4168 // 1, 2 and 4MHz share the same calibration word
4169 case cmuHFRCOEM23Freq_1M0Hz:
4170 case cmuHFRCOEM23Freq_2M0Hz:
4171 case cmuHFRCOEM23Freq_4M0Hz:
4172 ret = DEVINFO->HFRCOEM23CAL[0].HFRCOEM23CAL;
4173 break;
4174
4175 case cmuHFRCOEM23Freq_13M0Hz:
4176 ret = DEVINFO->HFRCOEM23CAL[6].HFRCOEM23CAL;
4177 break;
4178
4179 case cmuHFRCOEM23Freq_16M0Hz:
4180 ret = DEVINFO->HFRCOEM23CAL[7].HFRCOEM23CAL;
4181 break;
4182
4183 case cmuHFRCOEM23Freq_19M0Hz:
4184 ret = DEVINFO->HFRCOEM23CAL[8].HFRCOEM23CAL;
4185 break;
4186
4187 case cmuHFRCOEM23Freq_26M0Hz:
4188 ret = DEVINFO->HFRCOEM23CAL[10].HFRCOEM23CAL;
4189 break;
4190
4191 case cmuHFRCOEM23Freq_32M0Hz:
4192 ret = DEVINFO->HFRCOEM23CAL[11].HFRCOEM23CAL;
4193 break;
4194
4195 case cmuHFRCOEM23Freq_40M0Hz:
4196 ret = DEVINFO->HFRCOEM23CAL[12].HFRCOEM23CAL;
4197 break;
4198
4199 case cmuHFRCOEM23Freq_UserDefined:
4200 break;
4201
4202 default:
4203 EFM_ASSERT(false);
4204 break;
4205 }
4206 return ret;
4207 }
4208 #endif // defined(HFRCOEM23_PRESENT)
4209
4210 /***************************************************************************//**
4211 * @brief
4212 * Get selected oscillator and frequency for @ref cmuClock_TRACECLK
4213 * clock tree.
4214 *
4215 * @param[out] freq
4216 * The frequency.
4217 *
4218 * @param[out] sel
4219 * The selected oscillator.
4220 ******************************************************************************/
traceClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4221 static void traceClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4222 {
4223 uint32_t f = 0U;
4224 CMU_Select_TypeDef s;
4225
4226 #if defined(_CMU_TRACECLKCTRL_CLKSEL_MASK)
4227 switch (CMU->TRACECLKCTRL & _CMU_TRACECLKCTRL_CLKSEL_MASK) {
4228 #if defined(_CMU_TRACECLKCTRL_CLKSEL_HCLK)
4229 case CMU_TRACECLKCTRL_CLKSEL_HCLK:
4230 f = SystemHCLKGet();
4231 s = cmuSelect_HCLK;
4232 break;
4233 #endif
4234 #if defined(_CMU_TRACECLKCTRL_CLKSEL_SYSCLK)
4235 case CMU_TRACECLKCTRL_CLKSEL_SYSCLK:
4236 f = SystemSYSCLKGet();
4237 s = cmuSelect_SYSCLK;
4238 break;
4239 #endif
4240
4241 #if defined(CMU_TRACECLKCTRL_CLKSEL_HFRCOEM23)
4242 case CMU_TRACECLKCTRL_CLKSEL_HFRCOEM23:
4243 f = SystemHFRCOEM23ClockGet();
4244 s = cmuSelect_HFRCOEM23;
4245 break;
4246 #endif
4247
4248 #if defined(CMU_TRACECLKCTRL_CLKSEL_HFRCODPLLRT)
4249 case CMU_TRACECLKCTRL_CLKSEL_HFRCODPLLRT:
4250 f = SystemHFRCODPLLClockGet();
4251 s = cmuSelect_HFRCODPLLRT;
4252 break;
4253 #endif
4254
4255 default:
4256 s = cmuSelect_Error;
4257 EFM_ASSERT(false);
4258 break;
4259 }
4260 #else
4261 f = SystemSYSCLKGet();
4262 s = cmuSelect_SYSCLK;
4263 #endif
4264
4265 if (freq != NULL) {
4266 *freq = f;
4267 }
4268 if (sel != NULL) {
4269 *sel = s;
4270 }
4271 }
4272
4273 /***************************************************************************//**
4274 * @brief
4275 * Get selected oscillator and frequency for @ref cmuClock_DPLLREFCLK
4276 * clock tree.
4277 *
4278 * @param[out] freq
4279 * The frequency.
4280 *
4281 * @param[out] sel
4282 * The selected oscillator.
4283 ******************************************************************************/
dpllRefClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4284 static void dpllRefClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4285 {
4286 uint32_t f = 0U;
4287 CMU_Select_TypeDef s;
4288
4289 switch (CMU->DPLLREFCLKCTRL & _CMU_DPLLREFCLKCTRL_CLKSEL_MASK) {
4290 case CMU_DPLLREFCLKCTRL_CLKSEL_HFXO:
4291 f = SystemHFXOClockGet();
4292 s = cmuSelect_HFXO;
4293 break;
4294
4295 case CMU_DPLLREFCLKCTRL_CLKSEL_LFXO:
4296 f = SystemLFXOClockGet();
4297 s = cmuSelect_LFXO;
4298 break;
4299
4300 case CMU_DPLLREFCLKCTRL_CLKSEL_CLKIN0:
4301 f = SystemCLKIN0Get();
4302 s = cmuSelect_CLKIN0;
4303 break;
4304
4305 case CMU_DPLLREFCLKCTRL_CLKSEL_DISABLED:
4306 s = cmuSelect_Disabled;
4307 break;
4308
4309 default:
4310 s = cmuSelect_Error;
4311 EFM_ASSERT(false);
4312 break;
4313 }
4314
4315 if (freq != NULL) {
4316 *freq = f;
4317 }
4318 if (sel != NULL) {
4319 *sel = s;
4320 }
4321 }
4322
4323 /***************************************************************************//**
4324 * @brief
4325 * Get selected oscillator and frequency for @ref cmuClock_EM01GRPACLK
4326 * clock tree.
4327 *
4328 * @param[out] freq
4329 * The frequency.
4330 *
4331 * @param[out] sel
4332 * The selected oscillator.
4333 ******************************************************************************/
em01GrpaClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4334 static void em01GrpaClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4335 {
4336 uint32_t f = 0U;
4337 CMU_Select_TypeDef s;
4338
4339 switch (CMU->EM01GRPACLKCTRL & _CMU_EM01GRPACLKCTRL_CLKSEL_MASK) {
4340 case CMU_EM01GRPACLKCTRL_CLKSEL_HFRCODPLL:
4341 f = SystemHFRCODPLLClockGet();
4342 s = cmuSelect_HFRCODPLL;
4343 break;
4344
4345 case CMU_EM01GRPACLKCTRL_CLKSEL_HFXO:
4346 f = SystemHFXOClockGet();
4347 s = cmuSelect_HFXO;
4348 break;
4349
4350 #if defined(HFRCOEM23_PRESENT)
4351 case CMU_EM01GRPACLKCTRL_CLKSEL_HFRCOEM23:
4352 f = SystemHFRCOEM23ClockGet();
4353 s = cmuSelect_HFRCOEM23;
4354 break;
4355 #endif
4356
4357 case CMU_EM01GRPACLKCTRL_CLKSEL_FSRCO:
4358 f = SystemFSRCOClockGet();
4359 s = cmuSelect_FSRCO;
4360 break;
4361
4362 #if defined(CMU_EM01GRPACLKCTRL_CLKSEL_HFRCODPLLRT)
4363 case CMU_EM01GRPACLKCTRL_CLKSEL_HFRCODPLLRT:
4364 f = SystemHFRCODPLLClockGet();
4365 s = cmuSelect_HFRCODPLLRT;
4366 break;
4367 #endif
4368
4369 #if defined(CMU_EM01GRPACLKCTRL_CLKSEL_HFXORT)
4370 case CMU_EM01GRPACLKCTRL_CLKSEL_HFXORT:
4371 f = SystemHFXOClockGet();
4372 s = cmuSelect_HFXORT;
4373 break;
4374 #endif
4375
4376 default:
4377 s = cmuSelect_Error;
4378 EFM_ASSERT(false);
4379 break;
4380 }
4381
4382 if (freq != NULL) {
4383 *freq = f;
4384 }
4385 if (sel != NULL) {
4386 *sel = s;
4387 }
4388 }
4389
4390 /***************************************************************************//**
4391 * @brief
4392 * Get selected oscillator and frequency for @ref cmuClock_EM23GRPACLK
4393 * clock tree.
4394 *
4395 * @param[out] freq
4396 * The frequency.
4397 *
4398 * @param[out] sel
4399 * The selected oscillator.
4400 ******************************************************************************/
em23GrpaClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4401 static void em23GrpaClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4402 {
4403 uint32_t f = 0U;
4404 CMU_Select_TypeDef s;
4405
4406 switch (CMU->EM23GRPACLKCTRL & _CMU_EM23GRPACLKCTRL_CLKSEL_MASK) {
4407 case CMU_EM23GRPACLKCTRL_CLKSEL_LFRCO:
4408 f = SystemLFRCOClockGet();
4409 s = cmuSelect_LFRCO;
4410 break;
4411
4412 case CMU_EM23GRPACLKCTRL_CLKSEL_LFXO:
4413 f = SystemLFXOClockGet();
4414 s = cmuSelect_LFXO;
4415 break;
4416
4417 case CMU_EM23GRPACLKCTRL_CLKSEL_ULFRCO:
4418 f = SystemULFRCOClockGet();
4419 s = cmuSelect_ULFRCO;
4420 break;
4421
4422 default:
4423 s = cmuSelect_Error;
4424 EFM_ASSERT(false);
4425 break;
4426 }
4427
4428 if (freq != NULL) {
4429 *freq = f;
4430 }
4431 if (sel != NULL) {
4432 *sel = s;
4433 }
4434 }
4435
4436 /***************************************************************************//**
4437 * @brief
4438 * Get selected oscillator and frequency for @ref cmuClock_EM4GRPACLK
4439 * clock tree.
4440 *
4441 * @param[out] freq
4442 * The frequency.
4443 *
4444 * @param[out] sel
4445 * The selected oscillator.
4446 ******************************************************************************/
em4GrpaClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4447 static void em4GrpaClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4448 {
4449 uint32_t f = 0U;
4450 CMU_Select_TypeDef s;
4451
4452 switch (CMU->EM4GRPACLKCTRL & _CMU_EM4GRPACLKCTRL_CLKSEL_MASK) {
4453 case CMU_EM4GRPACLKCTRL_CLKSEL_LFRCO:
4454 f = SystemLFRCOClockGet();
4455 s = cmuSelect_LFRCO;
4456 break;
4457
4458 case CMU_EM4GRPACLKCTRL_CLKSEL_LFXO:
4459 f = SystemLFXOClockGet();
4460 s = cmuSelect_LFXO;
4461 break;
4462
4463 case CMU_EM4GRPACLKCTRL_CLKSEL_ULFRCO:
4464 f = SystemULFRCOClockGet();
4465 s = cmuSelect_ULFRCO;
4466 break;
4467
4468 default:
4469 s = cmuSelect_Error;
4470 EFM_ASSERT(false);
4471 break;
4472 }
4473
4474 if (freq != NULL) {
4475 *freq = f;
4476 }
4477 if (sel != NULL) {
4478 *sel = s;
4479 }
4480 }
4481
getWaitStatesByFrequencyAndVScale(uint32_t freq,int vscale)4482 __STATIC_INLINE uint32_t getWaitStatesByFrequencyAndVScale(uint32_t freq, int vscale)
4483 {
4484 uint32_t flashWs = MSC_READCTRL_MODE_WS3;
4485
4486 if (vscale == 0) {
4487 // VScale 1.1V core frequency ranges for wait-states configurations.
4488 if (0) {
4489 }
4490 #if defined(CMU_MAX_FREQ_2WS_1V1)
4491 else if (freq > CMU_MAX_FREQ_2WS_1V1) {
4492 flashWs = MSC_READCTRL_MODE_WS3;
4493 }
4494 #endif
4495 #if defined(CMU_MAX_FREQ_1WS_1V1)
4496 else if (freq > CMU_MAX_FREQ_1WS_1V1) {
4497 flashWs = MSC_READCTRL_MODE_WS2;
4498 }
4499 #endif
4500 #if defined(CMU_MAX_FREQ_0WS_1V1)
4501 else if (freq > CMU_MAX_FREQ_0WS_1V1) {
4502 flashWs = MSC_READCTRL_MODE_WS1;
4503 }
4504 #endif
4505 else {
4506 flashWs = MSC_READCTRL_MODE_WS0;
4507 }
4508 } else if (vscale >= 1) {
4509 // VScale 1.0V core frequency ranges for wait-states configurations.
4510 if (0) {
4511 }
4512 #if defined(CMU_MAX_FREQ_2WS_1V0)
4513 else if (freq > CMU_MAX_FREQ_2WS_1V0) {
4514 flashWs = MSC_READCTRL_MODE_WS3;
4515 }
4516 #endif
4517 #if defined(CMU_MAX_FREQ_1WS_1V0)
4518 else if (freq > CMU_MAX_FREQ_1WS_1V0) {
4519 flashWs = MSC_READCTRL_MODE_WS2;
4520 }
4521 #endif
4522 #if defined(CMU_MAX_FREQ_0WS_1V0)
4523 else if (freq > CMU_MAX_FREQ_0WS_1V0) {
4524 flashWs = MSC_READCTRL_MODE_WS1;
4525 }
4526 #endif
4527 else {
4528 flashWs = MSC_READCTRL_MODE_WS0;
4529 }
4530 }
4531 return flashWs;
4532 }
4533
4534 /***************************************************************************//**
4535 * @brief
4536 * Configure flash access wait states to support the given core clock
4537 * frequency and vscale level.
4538 *
4539 * @note Current implementation sets wait states depending on frequency only.
4540 * This assumes that applications running on Vscale enabled microcontrollers
4541 * never attemtps to set core frequency above 40MHz at VSCALE1 (1.0V).
4542 * Series 2 Config 1 devices does not support vscale.
4543 *
4544 * @param[in] coreFreq
4545 * The core clock frequency to configure flash wait-states.
4546 *
4547 * @param[in] vscale
4548 * Voltage Scale level. Supported levels are 0 and 1 where 0 is the default.
4549 * @li 0 = 1.1 V (VSCALE2)
4550 * @li 1 = 1.0 V (VSCALE1)
4551 ******************************************************************************/
flashWaitStateControl(uint32_t coreFreq,int vscale)4552 static void flashWaitStateControl(uint32_t coreFreq, int vscale)
4553 {
4554 (void)vscale;
4555
4556 uint32_t mode;
4557 bool mscLocked;
4558
4559 #if defined(CMU_CLKEN1_MSC)
4560 CMU->CLKEN1_SET = CMU_CLKEN1_MSC;
4561 #endif
4562
4563 #if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
4564 coreFreq *= CMU_ClockDivGet(cmuClock_CORE);
4565 #endif
4566
4567 // Make sure the MSC is unlocked
4568 mscLocked = MSC_LockGetLocked();
4569 MSC_LockSetUnlocked();
4570
4571 // Get current flash read setting
4572 mode = MSC_ReadCTRLGet() & ~_MSC_READCTRL_MODE_MASK;
4573
4574 // Set new mode based on the core clock frequency
4575 mode |= getWaitStatesByFrequencyAndVScale(coreFreq, vscale);
4576
4577 MSC_ReadCTRLSet(mode);
4578
4579 // Set sram wait states for config 1 mcu.
4580 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
4581 // Set new mode based on the core clock frequency
4582 if (coreFreq > CMU_MAX_SRAM_FREQ_0WS) {
4583 SYSCFG_setDmem0RamCtrlRamwsenBit();
4584 } else {
4585 SYSCFG_clearDmem0RamCtrlRamwsenBit();
4586 }
4587 #endif
4588 if (mscLocked) {
4589 MSC_LockSetLocked();
4590 }
4591 }
4592
4593 /***************************************************************************//**
4594 * @brief
4595 * Get calibrated HFRCODPLL tuning value from Device information (DI) page
4596 * for a given frequency. Calibration value is not available for all frequency
4597 * bands.
4598 *
4599 * @param[in] freq
4600 * HFRCODPLL frequency band
4601 ******************************************************************************/
HFRCODPLLDevinfoGet(CMU_HFRCODPLLFreq_TypeDef freq)4602 static uint32_t HFRCODPLLDevinfoGet(CMU_HFRCODPLLFreq_TypeDef freq)
4603 {
4604 uint32_t ret = 0U;
4605
4606 switch (freq) {
4607 // 1, 2 and 4MHz share the same calibration word
4608 case cmuHFRCODPLLFreq_1M0Hz:
4609 case cmuHFRCODPLLFreq_2M0Hz:
4610 case cmuHFRCODPLLFreq_4M0Hz:
4611 ret = DEVINFO->HFRCODPLLCAL[0].HFRCODPLLCAL;
4612 break;
4613
4614 case cmuHFRCODPLLFreq_7M0Hz:
4615 ret = DEVINFO->HFRCODPLLCAL[3].HFRCODPLLCAL;
4616 break;
4617
4618 case cmuHFRCODPLLFreq_13M0Hz:
4619 ret = DEVINFO->HFRCODPLLCAL[6].HFRCODPLLCAL;
4620 break;
4621
4622 case cmuHFRCODPLLFreq_16M0Hz:
4623 ret = DEVINFO->HFRCODPLLCAL[7].HFRCODPLLCAL;
4624 break;
4625
4626 case cmuHFRCODPLLFreq_19M0Hz:
4627 ret = DEVINFO->HFRCODPLLCAL[8].HFRCODPLLCAL;
4628 break;
4629
4630 case cmuHFRCODPLLFreq_26M0Hz:
4631 ret = DEVINFO->HFRCODPLLCAL[10].HFRCODPLLCAL;
4632 break;
4633
4634 case cmuHFRCODPLLFreq_32M0Hz:
4635 ret = DEVINFO->HFRCODPLLCAL[11].HFRCODPLLCAL;
4636 break;
4637
4638 case cmuHFRCODPLLFreq_38M0Hz:
4639 ret = DEVINFO->HFRCODPLLCAL[12].HFRCODPLLCAL;
4640 break;
4641
4642 case cmuHFRCODPLLFreq_48M0Hz:
4643 ret = DEVINFO->HFRCODPLLCAL[13].HFRCODPLLCAL;
4644 break;
4645
4646 case cmuHFRCODPLLFreq_56M0Hz:
4647 ret = DEVINFO->HFRCODPLLCAL[14].HFRCODPLLCAL;
4648 break;
4649
4650 case cmuHFRCODPLLFreq_64M0Hz:
4651 ret = DEVINFO->HFRCODPLLCAL[15].HFRCODPLLCAL;
4652 break;
4653
4654 case cmuHFRCODPLLFreq_80M0Hz:
4655 ret = DEVINFO->HFRCODPLLCAL[16].HFRCODPLLCAL;
4656 break;
4657
4658 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5)
4659 case cmuHFRCODPLLFreq_100M0Hz:
4660 ret = DEVINFO->HFRCODPLLCAL[17].HFRCODPLLCAL;
4661 break;
4662 #endif
4663
4664 case cmuHFRCODPLLFreq_UserDefined:
4665 break;
4666
4667 default:
4668 EFM_ASSERT(false);
4669 break;
4670 }
4671 return ret;
4672 }
4673
4674 #if defined(IADC_PRESENT)
4675 /***************************************************************************//**
4676 * @brief
4677 * Get selected oscillator and frequency for @ref cmuClock_IADCCLK
4678 * clock tree.
4679 *
4680 * @param[out] freq
4681 * The frequency.
4682 *
4683 * @param[out] sel
4684 * The selected oscillator.
4685 ******************************************************************************/
iadcClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4686 static void iadcClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4687 {
4688 uint32_t f = 0U;
4689 CMU_Select_TypeDef s;
4690
4691 switch (CMU->IADCCLKCTRL & _CMU_IADCCLKCTRL_CLKSEL_MASK) {
4692 case CMU_IADCCLKCTRL_CLKSEL_EM01GRPACLK:
4693 em01GrpaClkGet(&f, NULL);
4694 s = cmuSelect_EM01GRPACLK;
4695 break;
4696
4697 #if defined(HFRCOEM23_PRESENT)
4698 case CMU_IADCCLKCTRL_CLKSEL_HFRCOEM23:
4699 f = SystemHFRCOEM23ClockGet();
4700 s = cmuSelect_HFRCOEM23;
4701 break;
4702 #endif
4703
4704 case CMU_IADCCLKCTRL_CLKSEL_FSRCO:
4705 f = SystemFSRCOClockGet();
4706 s = cmuSelect_FSRCO;
4707 break;
4708
4709 default:
4710 s = cmuSelect_Error;
4711 EFM_ASSERT(false);
4712 break;
4713 }
4714
4715 if (freq != NULL) {
4716 *freq = f;
4717 }
4718 if (sel != NULL) {
4719 *sel = s;
4720 }
4721 }
4722 #endif
4723
4724 /***************************************************************************//**
4725 * @brief
4726 * Set maximum allowed divisor for @ref cmuClock_PCLK clock tree.
4727 ******************************************************************************/
pclkDivMax(void)4728 static void pclkDivMax(void)
4729 {
4730 // Set largest divisor for PCLK clock tree.
4731 CMU_ClockDivSet(cmuClock_PCLK, 2U);
4732 }
4733
4734 /***************************************************************************//**
4735 * @brief
4736 * Set @ref cmuClock_PCLK clock tree divisor to achieve highest possible
4737 * frequency and still be within spec.
4738 ******************************************************************************/
pclkDivOptimize(void)4739 static void pclkDivOptimize(void)
4740 {
4741 CMU_ClkDiv_TypeDef div = 2U;
4742
4743 if (CMU_ClockFreqGet(cmuClock_HCLK) <= CMU_MAX_PCLK_FREQ) {
4744 div = 1U;
4745 }
4746 CMU_ClockDivSet(cmuClock_PCLK, div);
4747 }
4748
4749 #if defined(RTCC_PRESENT)
4750 /***************************************************************************//**
4751 * @brief
4752 * Get selected oscillator and frequency for @ref cmuClock_RTCCCLK
4753 * clock tree.
4754 *
4755 * @param[out] freq
4756 * The frequency.
4757 *
4758 * @param[out] sel
4759 * The selected oscillator.
4760 ******************************************************************************/
rtccClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4761 static void rtccClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4762 {
4763 uint32_t f = 0U;
4764 CMU_Select_TypeDef s;
4765
4766 switch (CMU->RTCCCLKCTRL & _CMU_RTCCCLKCTRL_CLKSEL_MASK) {
4767 case CMU_RTCCCLKCTRL_CLKSEL_LFRCO:
4768 f = SystemLFRCOClockGet();
4769 s = cmuSelect_LFRCO;
4770 break;
4771
4772 case CMU_RTCCCLKCTRL_CLKSEL_LFXO:
4773 f = SystemLFXOClockGet();
4774 s = cmuSelect_LFXO;
4775 break;
4776
4777 case CMU_RTCCCLKCTRL_CLKSEL_ULFRCO:
4778 f = SystemULFRCOClockGet();
4779 s = cmuSelect_ULFRCO;
4780 break;
4781
4782 default:
4783 s = cmuSelect_Error;
4784 EFM_ASSERT(false);
4785 break;
4786 }
4787
4788 if (freq != NULL) {
4789 *freq = f;
4790 }
4791 if (sel != NULL) {
4792 *sel = s;
4793 }
4794 }
4795 #endif
4796
4797 #if defined(SYSRTC_PRESENT)
4798 /***************************************************************************//**
4799 * @brief
4800 * Get selected oscillator and frequency for @ref cmuClock_SYSRTCCLK
4801 * clock tree.
4802 *
4803 * @param[out] freq
4804 * The frequency.
4805 *
4806 * @param[out] sel
4807 * The selected oscillator.
4808 ******************************************************************************/
sysrtcClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4809 static void sysrtcClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4810 {
4811 uint32_t f = 0U;
4812 CMU_Select_TypeDef s;
4813
4814 switch (CMU->SYSRTC0CLKCTRL & _CMU_SYSRTC0CLKCTRL_CLKSEL_MASK) {
4815 case CMU_SYSRTC0CLKCTRL_CLKSEL_LFRCO:
4816 f = SystemLFRCOClockGet();
4817 s = cmuSelect_LFRCO;
4818 break;
4819
4820 case CMU_SYSRTC0CLKCTRL_CLKSEL_LFXO:
4821 f = SystemLFXOClockGet();
4822 s = cmuSelect_LFXO;
4823 break;
4824
4825 case CMU_SYSRTC0CLKCTRL_CLKSEL_ULFRCO:
4826 f = SystemULFRCOClockGet();
4827 s = cmuSelect_ULFRCO;
4828 break;
4829
4830 default:
4831 s = cmuSelect_Error;
4832 EFM_ASSERT(false);
4833 break;
4834 }
4835
4836 if (freq != NULL) {
4837 *freq = f;
4838 }
4839 if (sel != NULL) {
4840 *sel = s;
4841 }
4842 }
4843 #endif
4844
4845 /***************************************************************************//**
4846 * @brief
4847 * Set wait-states to values valid for maximum allowable core clock frequency.
4848 ******************************************************************************/
waitStateMax(void)4849 static void waitStateMax(void)
4850 {
4851 flashWaitStateControl(SystemMaxCoreClockGet(), 0);
4852 }
4853
4854 /***************************************************************************//**
4855 * @brief
4856 * Get selected oscillator and frequency for @ref cmuClock_WDOG0CLK
4857 * clock tree.
4858 *
4859 * @param[out] freq
4860 * The frequency.
4861 *
4862 * @param[out] sel
4863 * The selected oscillator.
4864 ******************************************************************************/
wdog0ClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4865 static void wdog0ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4866 {
4867 uint32_t f = 0U;
4868 CMU_Select_TypeDef s;
4869
4870 switch (CMU->WDOG0CLKCTRL & _CMU_WDOG0CLKCTRL_CLKSEL_MASK) {
4871 case CMU_WDOG0CLKCTRL_CLKSEL_LFRCO:
4872 f = SystemLFRCOClockGet();
4873 s = cmuSelect_LFRCO;
4874 break;
4875
4876 case CMU_WDOG0CLKCTRL_CLKSEL_LFXO:
4877 f = SystemLFXOClockGet();
4878 s = cmuSelect_LFXO;
4879 break;
4880
4881 case CMU_WDOG0CLKCTRL_CLKSEL_ULFRCO:
4882 f = SystemULFRCOClockGet();
4883 s = cmuSelect_ULFRCO;
4884 break;
4885
4886 case CMU_WDOG0CLKCTRL_CLKSEL_HCLKDIV1024:
4887 f = SystemHCLKGet() / 1024U;
4888 s = cmuSelect_HCLKDIV1024;
4889 break;
4890
4891 default:
4892 s = cmuSelect_Error;
4893 EFM_ASSERT(false);
4894 break;
4895 }
4896
4897 if (freq != NULL) {
4898 *freq = f;
4899 }
4900 if (sel != NULL) {
4901 *sel = s;
4902 }
4903 }
4904
4905 #if defined(_SILICON_LABS_32B_SERIES_2) && WDOG_COUNT > 1
4906 /***************************************************************************//**
4907 * @brief
4908 * Get selected oscillator and frequency for @ref cmuClock_WDOG1CLK
4909 * clock tree.
4910 *
4911 * @param[out] freq
4912 * The frequency.
4913 *
4914 * @param[out] sel
4915 * The selected oscillator.
4916 ******************************************************************************/
wdog1ClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4917 static void wdog1ClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4918 {
4919 uint32_t f = 0U;
4920 CMU_Select_TypeDef s;
4921
4922 switch (CMU->WDOG1CLKCTRL & _CMU_WDOG1CLKCTRL_CLKSEL_MASK) {
4923 case CMU_WDOG1CLKCTRL_CLKSEL_LFRCO:
4924 f = SystemLFRCOClockGet();
4925 s = cmuSelect_LFRCO;
4926 break;
4927
4928 case CMU_WDOG1CLKCTRL_CLKSEL_LFXO:
4929 f = SystemLFXOClockGet();
4930 s = cmuSelect_LFXO;
4931 break;
4932
4933 case CMU_WDOG1CLKCTRL_CLKSEL_ULFRCO:
4934 f = SystemULFRCOClockGet();
4935 s = cmuSelect_ULFRCO;
4936 break;
4937
4938 case CMU_WDOG1CLKCTRL_CLKSEL_HCLKDIV1024:
4939 f = SystemHCLKGet() / 1024U;
4940 s = cmuSelect_HCLKDIV1024;
4941 break;
4942
4943 default:
4944 s = cmuSelect_Error;
4945 EFM_ASSERT(false);
4946 break;
4947 }
4948
4949 if (freq != NULL) {
4950 *freq = f;
4951 }
4952 if (sel != NULL) {
4953 *sel = s;
4954 }
4955 }
4956 #endif // defined(_SILICON_LABS_32B_SERIES_2) && WDOG_COUNT > 1
4957
4958 /***************************************************************************//**
4959 * @brief
4960 * Get selected oscillator and frequency for @ref cmuClock_SYSTICK
4961 * clock tree.
4962 *
4963 * @param[out] freq
4964 * The frequency.
4965 *
4966 * @param[out] sel
4967 * The selected oscillator.
4968 ******************************************************************************/
sysTickClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)4969 static void sysTickClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
4970 {
4971 uint32_t f = 0U;
4972 CMU_Select_TypeDef s;
4973
4974 if (SysTick->CTRL & SysTick_CTRL_CLKSOURCE_Msk) {
4975 f = SystemHCLKGet();
4976 s = cmuSelect_HCLK;
4977 } else {
4978 em23GrpaClkGet(&f, &s);
4979 }
4980
4981 if (freq != NULL) {
4982 *freq = f;
4983 }
4984 if (sel != NULL) {
4985 *sel = s;
4986 }
4987 }
4988
4989 #if defined(USB_PRESENT)
4990 /***************************************************************************//**
4991 * @brief
4992 * Get selected oscillator and frequency for @ref cmuClock_USB clock tree.
4993 *
4994 * @param[out] freq
4995 * The frequency.
4996 *
4997 * @param[out] sel
4998 * The selected oscillator.
4999 ******************************************************************************/
usbClkGet(uint32_t * freq,CMU_Select_TypeDef * sel)5000 static void usbClkGet(uint32_t *freq, CMU_Select_TypeDef *sel)
5001 {
5002 uint32_t f = 0U;
5003 CMU_Select_TypeDef s;
5004
5005 switch (CMU->USB0CLKCTRL & _CMU_USB0CLKCTRL_CLKSEL_MASK) {
5006 case CMU_USB0CLKCTRL_CLKSEL_USBPLL0:
5007 f = PLL0_USB_OUTPUT_FREQ;
5008 s = cmuSelect_USBPLL0;
5009 break;
5010
5011 case CMU_USB0CLKCTRL_CLKSEL_LFXO:
5012 f = SystemLFXOClockGet();
5013 s = cmuSelect_LFXO;
5014 break;
5015
5016 case CMU_USB0CLKCTRL_CLKSEL_LFRCO:
5017 f = SystemLFRCOClockGet();
5018 s = cmuSelect_LFRCO;
5019 break;
5020
5021 default:
5022 s = cmuSelect_Error;
5023 EFM_ASSERT(false);
5024 break;
5025 }
5026
5027 if (freq != NULL) {
5028 *freq = f;
5029 }
5030 if (sel != NULL) {
5031 *sel = s;
5032 }
5033 }
5034 #endif
5035
5036 /** @endcond */
5037
5038 #else // defined(_SILICON_LABS_32B_SERIES_2)
5039
5040 /*******************************************************************************
5041 ****************************** DEFINES ************************************
5042 ******************************************************************************/
5043
5044 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
5045
5046 #if defined(_SILICON_LABS_32B_SERIES_0)
5047 /** The maximum allowed core frequency when using 0 wait-states on flash access. */
5048 #define CMU_MAX_FREQ_0WS 16000000
5049 /** The maximum allowed core frequency when using 1 wait-states on flash access */
5050 #define CMU_MAX_FREQ_1WS 32000000
5051
5052 #elif (_SILICON_LABS_GECKO_INTERNAL_SDID == 80)
5053 // EFR32xG1x and EFM32xG1x
5054 #define CMU_MAX_FREQ_0WS_1V2 25000000
5055 #define CMU_MAX_FREQ_1WS_1V2 40000000
5056
5057 #elif (_SILICON_LABS_GECKO_INTERNAL_SDID == 84)
5058 // EFR32xG12x and EFM32xG12x
5059 #define CMU_MAX_FREQ_0WS_1V2 25000000
5060 #define CMU_MAX_FREQ_1WS_1V2 40000000
5061 #define CMU_MAX_FREQ_0WS_1V1 21330000
5062 #define CMU_MAX_FREQ_1WS_1V1 32000000
5063 #define CMU_MAX_FREQ_0WS_1V0 7000000
5064 #define CMU_MAX_FREQ_1WS_1V0 14000000
5065 #define CMU_MAX_FREQ_2WS_1V0 20000000
5066
5067 #elif (_SILICON_LABS_GECKO_INTERNAL_SDID == 89)
5068 // EFR32xG13x and EFM32xG13x
5069 #define CMU_MAX_FREQ_0WS_1V2 25000000
5070 #define CMU_MAX_FREQ_1WS_1V2 40000000
5071 #define CMU_MAX_FREQ_0WS_1V0 7000000
5072 #define CMU_MAX_FREQ_1WS_1V0 14000000
5073 #define CMU_MAX_FREQ_2WS_1V0 20000000
5074
5075 #elif (_SILICON_LABS_GECKO_INTERNAL_SDID == 95)
5076 // EFR32xG14x and EFM32xG14x
5077 #define CMU_MAX_FREQ_0WS_1V2 25000000
5078 #define CMU_MAX_FREQ_1WS_1V2 40000000
5079 #define CMU_MAX_FREQ_0WS_1V0 7000000
5080 #define CMU_MAX_FREQ_1WS_1V0 14000000
5081 #define CMU_MAX_FREQ_2WS_1V0 20000000
5082
5083 #elif (_SILICON_LABS_GECKO_INTERNAL_SDID == 100)
5084 // EFM32GG11x
5085 #define CMU_MAX_FREQ_0WS_1V2 18000000
5086 #define CMU_MAX_FREQ_1WS_1V2 36000000
5087 #define CMU_MAX_FREQ_2WS_1V2 54000000
5088 #define CMU_MAX_FREQ_3WS_1V2 72000000
5089 #define CMU_MAX_FREQ_0WS_1V0 7000000
5090 #define CMU_MAX_FREQ_1WS_1V0 14000000
5091 #define CMU_MAX_FREQ_2WS_1V0 20000000
5092
5093 #elif (_SILICON_LABS_GECKO_INTERNAL_SDID == 103)
5094 // EFM32TG11x
5095 #define CMU_MAX_FREQ_0WS_1V2 25000000
5096 #define CMU_MAX_FREQ_1WS_1V2 48000000
5097 #define CMU_MAX_FREQ_0WS_1V0 10000000
5098 #define CMU_MAX_FREQ_1WS_1V0 21000000
5099 #define CMU_MAX_FREQ_2WS_1V0 20000000
5100
5101 #elif (_SILICON_LABS_GECKO_INTERNAL_SDID == 106)
5102 // EFM32GG12x
5103 #define CMU_MAX_FREQ_0WS_1V2 18000000
5104 #define CMU_MAX_FREQ_1WS_1V2 36000000
5105 #define CMU_MAX_FREQ_2WS_1V2 54000000
5106 #define CMU_MAX_FREQ_3WS_1V2 72000000
5107 #define CMU_MAX_FREQ_0WS_1V0 7000000
5108 #define CMU_MAX_FREQ_1WS_1V0 14000000
5109 #define CMU_MAX_FREQ_2WS_1V0 20000000
5110
5111 #else
5112 #error "Max Flash wait-state frequencies are not defined for this platform."
5113 #endif
5114
5115 /** The maximum frequency for the HFLE interface. */
5116 #if defined(CMU_CTRL_HFLE)
5117 /** The maximum HFLE frequency for series 0 EFM32 and EZR32 Wonder Gecko. */
5118 #if defined(_SILICON_LABS_32B_SERIES_0) \
5119 && (defined(_EFM32_WONDER_FAMILY) \
5120 || defined(_EZR32_WONDER_FAMILY))
5121 #define CMU_MAX_FREQ_HFLE 24000000UL
5122 /** The maximum HFLE frequency for other series 0 parts with maximum core clock
5123 higher than 32 MHz. */
5124 #elif defined(_SILICON_LABS_32B_SERIES_0) \
5125 && (defined(_EFM32_GIANT_FAMILY) \
5126 || defined(_EZR32_LEOPARD_FAMILY))
5127 #define CMU_MAX_FREQ_HFLE maxFreqHfle()
5128 #endif
5129 #elif defined(CMU_CTRL_WSHFLE)
5130 /** The maximum HFLE frequency for series 1 parts. */
5131 #define CMU_MAX_FREQ_HFLE 32000000UL
5132 #endif
5133
5134 #if defined(CMU_STATUS_HFXOSHUNTOPTRDY)
5135 #define HFXO_TUNING_READY_FLAGS (CMU_STATUS_HFXOPEAKDETRDY | CMU_STATUS_HFXOSHUNTOPTRDY)
5136 #define HFXO_TUNING_MODE_AUTO (_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_AUTOCMD)
5137 #define HFXO_TUNING_MODE_CMD (_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_CMD)
5138 #elif defined(CMU_STATUS_HFXOPEAKDETRDY)
5139 #define HFXO_TUNING_READY_FLAGS (CMU_STATUS_HFXOPEAKDETRDY)
5140 #define HFXO_TUNING_MODE_AUTO (_CMU_HFXOCTRL_PEAKDETMODE_AUTOCMD)
5141 #define HFXO_TUNING_MODE_CMD (_CMU_HFXOCTRL_PEAKDETMODE_CMD)
5142 #endif
5143
5144 #if defined(CMU_HFXOCTRL_MODE_EXTCLK)
5145 /** HFXO external clock mode is renamed from EXTCLK to DIGEXTCLK. */
5146 #define CMU_HFXOCTRL_MODE_DIGEXTCLK CMU_HFXOCTRL_MODE_EXTCLK
5147 #endif
5148
5149 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
5150 #define VSCALE_DEFAULT ((int)EMU_VScaleGet())
5151 #else
5152 #define VSCALE_DEFAULT VSCALE_EM01_HIGH_PERFORMANCE
5153 #endif
5154
5155 /*******************************************************************************
5156 ************************** LOCAL VARIABLES ********************************
5157 ******************************************************************************/
5158
5159 #if defined(_CMU_AUXHFRCOCTRL_FREQRANGE_MASK)
5160 static CMU_AUXHFRCOFreq_TypeDef auxHfrcoFreq = cmuAUXHFRCOFreq_19M0Hz;
5161 #endif
5162 #if defined(_CMU_STATUS_HFXOSHUNTOPTRDY_MASK)
5163 #define HFXO_INVALID_TRIM (~_CMU_HFXOTRIMSTATUS_MASK)
5164 #endif
5165
5166 #if defined(CMU_OSCENCMD_DPLLEN)
5167 /** A table of HFRCOCTRL values and their associated minimum/maximum frequencies and
5168 an optional band enumerator. */
5169 static const struct hfrcoCtrlTableElement{
5170 uint32_t minFreq;
5171 uint32_t maxFreq;
5172 uint32_t value;
5173 CMU_HFRCOFreq_TypeDef band;
5174 } hfrcoCtrlTable[] =
5175 {
5176 // minFreq maxFreq HFRCOCTRL value band
5177 { 860000UL, 1050000UL, 0xBC601F00UL, cmuHFRCOFreq_1M0Hz },
5178 { 1050000UL, 1280000UL, 0xBC611F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5179 { 1280000UL, 1480000UL, 0xBCA21F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5180 { 1480000UL, 1800000UL, 0xAD231F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5181 { 1800000UL, 2110000UL, 0xBA601F00UL, cmuHFRCOFreq_2M0Hz },
5182 { 2110000UL, 2560000UL, 0xBA611F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5183 { 2560000UL, 2970000UL, 0xBAA21F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5184 { 2970000UL, 3600000UL, 0xAB231F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5185 { 3600000UL, 4220000UL, 0xB8601F00UL, cmuHFRCOFreq_4M0Hz },
5186 { 4220000UL, 5120000UL, 0xB8611F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5187 { 5120000UL, 5930000UL, 0xB8A21F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5188 { 5930000UL, 7520000UL, 0xA9231F00UL, cmuHFRCOFreq_7M0Hz },
5189 { 7520000UL, 9520000UL, 0x99241F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5190 { 9520000UL, 11800000UL, 0x99251F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5191 { 11800000UL, 14400000UL, 0x99261F00UL, cmuHFRCOFreq_13M0Hz },
5192 { 14400000UL, 17200000UL, 0x99271F00UL, cmuHFRCOFreq_16M0Hz },
5193 { 17200000UL, 19700000UL, 0x99481F00UL, cmuHFRCOFreq_19M0Hz },
5194 { 19700000UL, 23800000UL, 0x99491F35UL, (CMU_HFRCOFreq_TypeDef)0 },
5195 { 23800000UL, 28700000UL, 0x994A1F00UL, cmuHFRCOFreq_26M0Hz },
5196 { 28700000UL, 34800000UL, 0x996B1F00UL, cmuHFRCOFreq_32M0Hz },
5197 #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_84) \
5198 || defined(_SILICON_LABS_GECKO_INTERNAL_SDID_89) \
5199 || defined(_SILICON_LABS_GECKO_INTERNAL_SDID_95)
5200 { 34800000UL, 40000000UL, 0x996C1F00UL, cmuHFRCOFreq_38M0Hz }
5201 #elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_100) \
5202 || defined(_SILICON_LABS_GECKO_INTERNAL_SDID_106)
5203 { 34800000UL, 42800000UL, 0x996C1F00UL, cmuHFRCOFreq_38M0Hz },
5204 { 42800000UL, 51600000UL, 0x996D1F00UL, cmuHFRCOFreq_48M0Hz },
5205 { 51600000UL, 60500000UL, 0x998E1F00UL, cmuHFRCOFreq_56M0Hz },
5206 { 60500000UL, 72000000UL, 0xA98F1F00UL, cmuHFRCOFreq_64M0Hz }
5207 #elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_103)
5208 { 34800000UL, 42800000UL, 0x996C1F00UL, cmuHFRCOFreq_38M0Hz },
5209 { 42800000UL, 48000000UL, 0x996D1F00UL, cmuHFRCOFreq_48M0Hz }
5210 #else
5211 #error "HFRCOCTRL values not set for this platform."
5212 #endif
5213 };
5214
5215 #define HFRCOCTRLTABLE_ENTRIES (sizeof(hfrcoCtrlTable) \
5216 / sizeof(struct hfrcoCtrlTableElement))
5217 #endif // CMU_OSCENCMD_DPLLEN
5218
5219 #if defined(_SILICON_LABS_32B_SERIES_1) && defined(_EMU_STATUS_VSCALE_MASK)
5220 /* Devices with Voltage Scaling needs extra handling of wait states. */
5221 static const struct flashWsTableElement{
5222 uint32_t maxFreq;
5223 uint8_t vscale;
5224 uint8_t ws;
5225 } flashWsTable[] =
5226 {
5227 #if (_SILICON_LABS_GECKO_INTERNAL_SDID == 100 || _SILICON_LABS_GECKO_INTERNAL_SDID == 106)
5228 { CMU_MAX_FREQ_0WS_1V2, 0, 0 }, /* 0 wait states at max frequency 18 MHz and 1.2V */
5229 { CMU_MAX_FREQ_1WS_1V2, 0, 1 }, /* 1 wait states at max frequency 36 MHz and 1.2V */
5230 { CMU_MAX_FREQ_2WS_1V2, 0, 2 }, /* 2 wait states at max frequency 54 MHz and 1.2V */
5231 { CMU_MAX_FREQ_3WS_1V2, 0, 3 }, /* 3 wait states at max frequency 72 MHz and 1.2V */
5232 { CMU_MAX_FREQ_0WS_1V0, 2, 0 }, /* 0 wait states at max frequency 7 MHz and 1.0V */
5233 { CMU_MAX_FREQ_1WS_1V0, 2, 1 }, /* 1 wait states at max frequency 14 MHz and 1.0V */
5234 { CMU_MAX_FREQ_2WS_1V0, 2, 2 }, /* 2 wait states at max frequency 21 MHz and 1.0V */
5235 #else
5236 { CMU_MAX_FREQ_0WS_1V2, 0, 0 }, /* 0 wait states at 1.2V */
5237 { CMU_MAX_FREQ_1WS_1V2, 0, 1 }, /* 1 wait states at 1.2V */
5238 { CMU_MAX_FREQ_0WS_1V0, 2, 0 }, /* 0 wait states at 1.0V */
5239 { CMU_MAX_FREQ_1WS_1V0, 2, 1 }, /* 1 wait states at 1.0V */
5240 { CMU_MAX_FREQ_2WS_1V0, 2, 2 }, /* 2 wait states at 1.0V */
5241 #endif
5242 };
5243
5244 #define FLASH_WS_TABLE_ENTRIES (sizeof(flashWsTable) / sizeof(flashWsTable[0]))
5245 #endif
5246
5247 #if defined(_CMU_USHFRCOCTRL_FREQRANGE_MASK) \
5248 || defined(_CMU_USHFRCOTUNE_MASK)
5249 #ifndef EFM32_USHFRCO_STARTUP_FREQ
5250 #define EFM32_USHFRCO_STARTUP_FREQ (48000000UL)
5251 #endif
5252
5253 static uint32_t ushfrcoFreq = EFM32_USHFRCO_STARTUP_FREQ;
5254 #endif
5255
5256 /*******************************************************************************
5257 ************************** LOCAL PROTOTYPES *******************************
5258 ******************************************************************************/
5259 #if defined(_CMU_HFRCOCTRL_FREQRANGE_MASK)
5260 static uint32_t CMU_HFRCODevinfoGet(CMU_HFRCOFreq_TypeDef freq);
5261 #endif
5262
5263 #if defined(_CMU_USHFRCOCTRL_FREQRANGE_MASK)
5264 static uint32_t CMU_USHFRCODevinfoGet(CMU_USHFRCOFreq_TypeDef freq);
5265 #endif
5266
5267 static void hfperClkSafePrescaler(void);
5268 static void hfperClkOptimizedPrescaler(void);
5269
5270 static uint16_t lfxo_precision = 0xFFFF;
5271
5272 /** @endcond */
5273
5274 /*******************************************************************************
5275 ************************** LOCAL FUNCTIONS ********************************
5276 ******************************************************************************/
5277
5278 #if defined(_SILICON_LABS_32B_SERIES_0) \
5279 && (defined(_EFM32_GIANT_FAMILY) \
5280 || defined(_EZR32_LEOPARD_FAMILY))
5281 /***************************************************************************//**
5282 * @brief
5283 * Return maximum allowed frequency for low energy peripherals.
5284 ******************************************************************************/
maxFreqHfle(void)5285 static uint32_t maxFreqHfle(void)
5286 {
5287 uint16_t majorMinorRev;
5288
5289 switch (SYSTEM_GetFamily()) {
5290 case systemPartFamilyEfm32Leopard:
5291 case systemPartFamilyEzr32Leopard:
5292 /* CHIP MAJOR bit [5:0] */
5293 majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)
5294 >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8);
5295 /* CHIP MINOR bit [7:4] */
5296 majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)
5297 >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);
5298 /* CHIP MINOR bit [3:0] */
5299 majorMinorRev |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)
5300 >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);
5301
5302 if (majorMinorRev >= 0x0204) {
5303 return 24000000;
5304 } else {
5305 return 32000000;
5306 }
5307
5308 case systemPartFamilyEfm32Giant:
5309 return 32000000;
5310
5311 default:
5312 /* Invalid device family. */
5313 EFM_ASSERT(false);
5314 return 0;
5315 }
5316 }
5317 #endif
5318
5319 #if defined(CMU_MAX_FREQ_HFLE)
5320
5321 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
5322 /* Unified definitions for the HFLE wait-state and prescaler fields. */
5323 #if defined(CMU_CTRL_HFLE)
5324 #define _GENERIC_HFLE_WS_MASK _CMU_CTRL_HFLE_MASK
5325 #define _GENERIC_HFLE_WS_SHIFT _CMU_CTRL_HFLE_SHIFT
5326 #define GENERIC_HFLE_PRESC_REG CMU->HFCORECLKDIV
5327 #define _GENERIC_HFLE_PRESC_MASK _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK
5328 #define _GENERIC_HFLE_PRESC_SHIFT _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT
5329 #elif defined(CMU_CTRL_WSHFLE)
5330 #define _GENERIC_HFLE_WS_MASK _CMU_CTRL_WSHFLE_MASK
5331 #define _GENERIC_HFLE_WS_SHIFT _CMU_CTRL_WSHFLE_SHIFT
5332 #define GENERIC_HFLE_PRESC_REG CMU->HFPRESC
5333 #define _GENERIC_HFLE_PRESC_MASK _CMU_HFPRESC_HFCLKLEPRESC_MASK
5334 #define _GENERIC_HFLE_PRESC_SHIFT _CMU_HFPRESC_HFCLKLEPRESC_SHIFT
5335 #endif
5336 /** @endcond */
5337
5338 /***************************************************************************//**
5339 * @brief
5340 * Set HFLE wait-states and HFCLKLE prescaler according to wanted HF clock.
5341 *
5342 * @param[in] hfFreq
5343 * The HF clock frequency to use.
5344 * This is:
5345 * CORE clock on Series0 devices.
5346 * HF clock on on Series1 devices.
5347 ******************************************************************************/
setHfLeConfig(uint32_t hfFreq)5348 static void setHfLeConfig(uint32_t hfFreq)
5349 {
5350 unsigned int hfleWs;
5351 uint32_t hflePresc;
5352
5353 /* Check for 1 bit fields. @ref BUS_RegBitWrite() below are going to fail if the
5354 fields are changed to more than 1 bit. */
5355 EFM_ASSERT((_GENERIC_HFLE_WS_MASK >> _GENERIC_HFLE_WS_SHIFT) == 0x1U);
5356
5357 /* - Enable HFLE wait-state to allow access to LE peripherals when HFBUSCLK is
5358 above maxLeFreq.
5359 - Set HFLE prescaler. Allowed HFLE clock frequency is maxLeFreq. */
5360
5361 hfleWs = 1;
5362 if (hfFreq <= CMU_MAX_FREQ_HFLE) {
5363 hfleWs = 0;
5364 hflePresc = 0;
5365 } else if (hfFreq <= (2UL * CMU_MAX_FREQ_HFLE)) {
5366 hflePresc = 1;
5367 } else {
5368 hflePresc = 2;
5369 }
5370 BUS_RegBitWrite(&CMU->CTRL, _GENERIC_HFLE_WS_SHIFT, hfleWs);
5371 GENERIC_HFLE_PRESC_REG = (GENERIC_HFLE_PRESC_REG & ~_GENERIC_HFLE_PRESC_MASK)
5372 | (hflePresc << _GENERIC_HFLE_PRESC_SHIFT);
5373 }
5374
5375 #if defined(_CMU_CTRL_HFLE_MASK)
5376 /***************************************************************************//**
5377 * @brief
5378 * Get HFLE wait-state configuration.
5379 *
5380 * @return
5381 * The current wait-state configuration.
5382 ******************************************************************************/
getHfLeConfig(void)5383 static uint32_t getHfLeConfig(void)
5384 {
5385 uint32_t ws = BUS_RegBitRead(&CMU->CTRL, _GENERIC_HFLE_WS_SHIFT);
5386 return ws;
5387 }
5388 #endif
5389 #endif
5390
5391 /***************************************************************************//**
5392 * @brief
5393 * Get the AUX clock frequency. Used by MSC flash programming and LESENSE,
5394 * by default also as a debug clock.
5395 *
5396 * @return
5397 * AUX Frequency in Hz.
5398 ******************************************************************************/
auxClkGet(void)5399 static uint32_t auxClkGet(void)
5400 {
5401 uint32_t ret;
5402
5403 #if defined(_CMU_AUXHFRCOCTRL_FREQRANGE_MASK)
5404 ret = (uint32_t)auxHfrcoFreq;
5405
5406 #elif defined(_CMU_AUXHFRCOCTRL_BAND_MASK)
5407 /* All series 0 families except EFM32G */
5408 switch (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK) {
5409 case CMU_AUXHFRCOCTRL_BAND_1MHZ:
5410 if ( SYSTEM_GetProdRev() >= 19 ) {
5411 ret = 1200000;
5412 } else {
5413 ret = 1000000;
5414 }
5415 break;
5416
5417 case CMU_AUXHFRCOCTRL_BAND_7MHZ:
5418 if ( SYSTEM_GetProdRev() >= 19 ) {
5419 ret = 6600000;
5420 } else {
5421 ret = 7000000;
5422 }
5423 break;
5424
5425 case CMU_AUXHFRCOCTRL_BAND_11MHZ:
5426 ret = 11000000;
5427 break;
5428
5429 case CMU_AUXHFRCOCTRL_BAND_14MHZ:
5430 ret = 14000000;
5431 break;
5432
5433 case CMU_AUXHFRCOCTRL_BAND_21MHZ:
5434 ret = 21000000;
5435 break;
5436
5437 #if defined(_CMU_AUXHFRCOCTRL_BAND_28MHZ)
5438 case CMU_AUXHFRCOCTRL_BAND_28MHZ:
5439 ret = 28000000;
5440 break;
5441 #endif
5442
5443 default:
5444 ret = 0;
5445 EFM_ASSERT(false);
5446 break;
5447 }
5448
5449 #else
5450 /* Gecko has a fixed 14 MHz AUXHFRCO clock. */
5451 ret = 14000000;
5452
5453 #endif
5454
5455 return ret;
5456 }
5457
5458 #if defined (_CMU_ADCCTRL_ADC0CLKSEL_HFSRCCLK) \
5459 || defined (_CMU_ADCCTRL_ADC1CLKSEL_HFSRCCLK)
5460 /***************************************************************************//**
5461 * @brief
5462 * Get the HFSRCCLK frequency.
5463 *
5464 * @return
5465 * HFSRCCLK Frequency in Hz.
5466 ******************************************************************************/
hfSrcClkGet(void)5467 static uint32_t hfSrcClkGet(void)
5468 {
5469 uint32_t ret;
5470
5471 ret = SystemHFClockGet();
5472 return ret * (1U + ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)
5473 >> _CMU_HFPRESC_PRESC_SHIFT));
5474 }
5475 #endif
5476
5477 /***************************************************************************//**
5478 * @brief
5479 * Get the Debug Trace clock frequency.
5480 *
5481 * @return
5482 * Debug Trace frequency in Hz.
5483 ******************************************************************************/
dbgClkGet(void)5484 static uint32_t dbgClkGet(void)
5485 {
5486 uint32_t ret;
5487 CMU_Select_TypeDef clk;
5488
5489 /* Get selected clock source */
5490 clk = CMU_ClockSelectGet(cmuClock_DBG);
5491
5492 switch (clk) {
5493 case cmuSelect_HFCLK:
5494 ret = SystemHFClockGet();
5495 break;
5496
5497 case cmuSelect_AUXHFRCO:
5498 ret = auxClkGet();
5499 break;
5500
5501 default:
5502 ret = 0;
5503 EFM_ASSERT(false);
5504 break;
5505 }
5506 return ret;
5507 }
5508
5509 #if defined(_CMU_ADCCTRL_ADC0CLKSEL_MASK)
5510 /***************************************************************************//**
5511 * @brief
5512 * Get the ADC n asynchronous clock frequency.
5513 *
5514 * @return
5515 * ADC n asynchronous frequency in Hz.
5516 ******************************************************************************/
adcAsyncClkGet(uint32_t adc)5517 static uint32_t adcAsyncClkGet(uint32_t adc)
5518 {
5519 uint32_t ret;
5520 CMU_Select_TypeDef clk;
5521
5522 /* Get the selected clock source. */
5523 switch (adc) {
5524 case 0:
5525 clk = CMU_ClockSelectGet(cmuClock_ADC0ASYNC);
5526 break;
5527
5528 #if defined(_CMU_ADCCTRL_ADC1CLKSEL_MASK)
5529 case 1:
5530 clk = CMU_ClockSelectGet(cmuClock_ADC1ASYNC);
5531 break;
5532 #endif
5533
5534 default:
5535 EFM_ASSERT(false);
5536 return 0;
5537 }
5538
5539 switch (clk) {
5540 case cmuSelect_Disabled:
5541 ret = 0;
5542 break;
5543
5544 case cmuSelect_AUXHFRCO:
5545 ret = auxClkGet();
5546 break;
5547
5548 case cmuSelect_HFXO:
5549 ret = SystemHFXOClockGet();
5550 break;
5551
5552 case cmuSelect_HFSRCCLK:
5553 ret = hfSrcClkGet();
5554 break;
5555
5556 default:
5557 ret = 0;
5558 EFM_ASSERT(false);
5559 break;
5560 }
5561 return ret;
5562 }
5563 #endif
5564
5565 #if defined(_CMU_SDIOCTRL_MASK)
5566 /***************************************************************************//**
5567 * @brief
5568 * Get the SDIO reference clock frequency.
5569 *
5570 * @return
5571 * SDIO reference clock frequency in Hz.
5572 ******************************************************************************/
sdioRefClkGet(void)5573 static uint32_t sdioRefClkGet(void)
5574 {
5575 uint32_t ret;
5576 CMU_Select_TypeDef clk;
5577
5578 /* Get the selected clock source. */
5579 clk = CMU_ClockSelectGet(cmuClock_SDIOREF);
5580
5581 switch (clk) {
5582 case cmuSelect_HFRCO:
5583 ret = SystemHfrcoFreq;
5584 break;
5585
5586 case cmuSelect_HFXO:
5587 ret = SystemHFXOClockGet();
5588 break;
5589
5590 case cmuSelect_AUXHFRCO:
5591 ret = auxClkGet();
5592 break;
5593
5594 case cmuSelect_USHFRCO:
5595 ret = ushfrcoFreq;
5596 break;
5597
5598 default:
5599 ret = 0;
5600 EFM_ASSERT(false);
5601 break;
5602 }
5603 return ret;
5604 }
5605 #endif
5606
5607 #if defined(_CMU_QSPICTRL_MASK)
5608 /***************************************************************************//**
5609 * @brief
5610 * Get the QSPI n reference clock frequency.
5611 *
5612 * @return
5613 * QSPI n reference clock frequency in Hz.
5614 ******************************************************************************/
qspiRefClkGet(uint32_t qspi)5615 static uint32_t qspiRefClkGet(uint32_t qspi)
5616 {
5617 uint32_t ret;
5618 CMU_Select_TypeDef clk;
5619
5620 /* Get the selected clock source. */
5621 switch (qspi) {
5622 case 0:
5623 clk = CMU_ClockSelectGet(cmuClock_QSPI0REF);
5624 break;
5625
5626 default:
5627 EFM_ASSERT(false);
5628 return 0;
5629 }
5630
5631 switch (clk) {
5632 case cmuSelect_HFRCO:
5633 ret = SystemHfrcoFreq;
5634 break;
5635
5636 case cmuSelect_HFXO:
5637 ret = SystemHFXOClockGet();
5638 break;
5639
5640 case cmuSelect_AUXHFRCO:
5641 ret = auxClkGet();
5642 break;
5643
5644 case cmuSelect_USHFRCO:
5645 ret = ushfrcoFreq;
5646 break;
5647
5648 default:
5649 ret = 0;
5650 EFM_ASSERT(false);
5651 break;
5652 }
5653 return ret;
5654 }
5655 #endif
5656
5657 #if defined(_CMU_PDMCTRL_MASK)
5658 /***************************************************************************//**
5659 * @brief
5660 * Get the PDM reference clock frequency.
5661 *
5662 * @return
5663 * PDM reference clock frequency in Hz.
5664 ******************************************************************************/
pdmRefClkGet(void)5665 static uint32_t pdmRefClkGet(void)
5666 {
5667 uint32_t ret;
5668 CMU_Select_TypeDef clk;
5669
5670 /* Get the selected clock source. */
5671 clk = CMU_ClockSelectGet(cmuClock_PDMREF);
5672
5673 switch (clk) {
5674 case cmuSelect_HFRCO:
5675 ret = SystemHfrcoFreq;
5676 break;
5677
5678 case cmuSelect_HFXO:
5679 ret = SystemHFXOClockGet();
5680 break;
5681
5682 case cmuSelect_USHFRCO:
5683 ret = ushfrcoFreq;
5684 break;
5685
5686 default:
5687 ret = 0;
5688 EFM_ASSERT(false);
5689 break;
5690 }
5691 return ret;
5692 }
5693 #endif
5694
5695 #if defined(USBR_CLOCK_PRESENT)
5696 /***************************************************************************//**
5697 * @brief
5698 * Get the USB rate clock frequency.
5699 *
5700 * @return
5701 * USB rate clock frequency in Hz.
5702 ******************************************************************************/
usbRateClkGet(void)5703 static uint32_t usbRateClkGet(void)
5704 {
5705 uint32_t ret;
5706 CMU_Select_TypeDef clk;
5707
5708 clk = CMU_ClockSelectGet(cmuClock_USBR);
5709
5710 switch (clk) {
5711 case cmuSelect_USHFRCO:
5712 ret = ushfrcoFreq;
5713 break;
5714
5715 case cmuSelect_HFXO:
5716 ret = SystemHFXOClockGet();
5717 break;
5718
5719 case cmuSelect_HFXOX2:
5720 ret = 2u * SystemHFXOClockGet();
5721 break;
5722
5723 case cmuSelect_HFRCO:
5724 ret = SystemHfrcoFreq;
5725 break;
5726
5727 case cmuSelect_LFXO:
5728 ret = SystemLFXOClockGet();
5729 break;
5730
5731 case cmuSelect_LFRCO:
5732 ret = SystemLFRCOClockGet();
5733 break;
5734
5735 default:
5736 ret = 0;
5737 EFM_ASSERT(false);
5738 break;
5739 }
5740 return ret;
5741 }
5742 #endif
5743
5744 /***************************************************************************//**
5745 * @brief
5746 * Configure flash access wait states to support the given core clock
5747 * frequency.
5748 *
5749 * @param[in] coreFreq
5750 * The core clock frequency to configure flash wait-states.
5751 *
5752 * @param[in] vscale
5753 * Voltage Scale level. Supported levels are 0 and 2 where 0 is the default.
5754 ******************************************************************************/
flashWaitStateControl(uint32_t coreFreq,int vscale)5755 static void flashWaitStateControl(uint32_t coreFreq, int vscale)
5756 {
5757 uint32_t mode;
5758 #if defined(MSC_READCTRL_MODE_WS0SCBTP)
5759 bool scbtpEn; /* Suppressed Conditional Branch Target Prefetch setting. */
5760 #endif
5761 (void) vscale; /* vscale parameter is only used on some devices. */
5762
5763 /* Get mode and SCBTP enable. */
5764 mode = MSC_ReadCTRLGet() & _MSC_READCTRL_MODE_MASK;
5765
5766 #if defined(_SILICON_LABS_32B_SERIES_0)
5767 #if defined(MSC_READCTRL_MODE_WS0SCBTP)
5768 /* Devices with MODE and SCBTP in the same register field. */
5769 switch (mode) {
5770 case MSC_READCTRL_MODE_WS0:
5771 case MSC_READCTRL_MODE_WS1:
5772 #if defined(MSC_READCTRL_MODE_WS2)
5773 case MSC_READCTRL_MODE_WS2:
5774 #endif
5775 scbtpEn = false;
5776 break;
5777
5778 default: /* WSxSCBTP */
5779 scbtpEn = true;
5780 break;
5781 }
5782
5783 /* Set mode based on the core clock frequency and SCBTP enable. */
5784 if (false) {
5785 }
5786 #if defined(MSC_READCTRL_MODE_WS2)
5787 else if (coreFreq > CMU_MAX_FREQ_1WS) {
5788 mode = (scbtpEn ? MSC_READCTRL_MODE_WS2SCBTP : MSC_READCTRL_MODE_WS2);
5789 }
5790 #endif
5791 else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS)) {
5792 mode = (scbtpEn ? MSC_READCTRL_MODE_WS1SCBTP : MSC_READCTRL_MODE_WS1);
5793 } else {
5794 mode = (scbtpEn ? MSC_READCTRL_MODE_WS0SCBTP : MSC_READCTRL_MODE_WS0);
5795 }
5796 #else /* defined(MSC_READCTRL_MODE_WS0SCBTP) */
5797
5798 if (coreFreq <= CMU_MAX_FREQ_0WS) {
5799 mode = 0;
5800 } else if (coreFreq <= CMU_MAX_FREQ_1WS) {
5801 mode = 1;
5802 }
5803 #endif /* defined(MSC_READCTRL_MODE_WS0SCBTP) */
5804 // End defined(_SILICON_LABS_32B_SERIES_0)
5805
5806 #elif defined(_SILICON_LABS_32B_SERIES_1)
5807 #if defined(_EMU_STATUS_VSCALE_MASK)
5808
5809 /* These devices have specific requirements on the supported flash wait state
5810 * depending on the frequency and voltage scale level. */
5811 uint32_t i;
5812 for (i = 0; i < FLASH_WS_TABLE_ENTRIES; i++) {
5813 if ((flashWsTable[i].vscale == (uint8_t)vscale)
5814 && (coreFreq <= flashWsTable[i].maxFreq)) {
5815 break; // Found a matching entry.
5816 }
5817 }
5818
5819 if (i == FLASH_WS_TABLE_ENTRIES) {
5820 mode = 3; // Worst case flash wait state for unsupported cases.
5821 EFM_ASSERT(false);
5822 } else {
5823 mode = flashWsTable[i].ws;
5824 }
5825 mode = mode << _MSC_READCTRL_MODE_SHIFT;
5826
5827 #else
5828 /* Devices where MODE and SCBTP are in separate fields and where the device
5829 * either does not support voltage scale or where the voltage scale does
5830 * not impact the flash wait state configuration. */
5831 if (coreFreq <= CMU_MAX_FREQ_0WS_1V2) {
5832 mode = 0;
5833 } else if (coreFreq <= CMU_MAX_FREQ_1WS_1V2) {
5834 mode = 1;
5835 }
5836 #if defined(MSC_READCTRL_MODE_WS2)
5837 else if (coreFreq <= CMU_MAX_FREQ_2WS) {
5838 mode = 2;
5839 }
5840 #endif
5841 #if defined(MSC_READCTRL_MODE_WS3)
5842 else if (coreFreq <= CMU_MAX_FREQ_3WS) {
5843 mode = 3;
5844 }
5845 #endif
5846 mode = mode << _MSC_READCTRL_MODE_SHIFT;
5847 #endif
5848 // End defined(_SILICON_LABS_32B_SERIES_1)
5849
5850 #else
5851 #error "Undefined 32B SERIES!"
5852 #endif
5853
5854 mode = (MSC_ReadCTRLGet() & ~_MSC_READCTRL_MODE_MASK) | mode;
5855 MSC_ReadCTRLSet(mode);
5856 }
5857
5858 /***************************************************************************//**
5859 * @brief
5860 * Configure flash access wait states to the most conservative setting for
5861 * this target. Retain SCBTP (Suppressed Conditional Branch Target Prefetch)
5862 * setting.
5863 ******************************************************************************/
flashWaitStateMax(void)5864 static void flashWaitStateMax(void)
5865 {
5866 /* Make sure the MSC is unlocked */
5867 bool mscLocked = MSC_LockGetLocked();
5868 MSC_LockSetUnlocked();
5869
5870 flashWaitStateControl(SystemMaxCoreClockGet(), 0);
5871
5872 if (mscLocked) {
5873 MSC_LockSetLocked();
5874 }
5875 }
5876
5877 #if defined(_MSC_RAMCTRL_RAMWSEN_MASK)
5878 /***************************************************************************//**
5879 * @brief
5880 * Configure RAM access wait states to support the given core clock
5881 * frequency.
5882 *
5883 * @param[in] coreFreq
5884 * The core clock frequency to configure RAM wait-states.
5885 *
5886 * @param[in] vscale
5887 * A voltage scale level. Supported levels are 0 and 2 where 0 is the default.
5888 ******************************************************************************/
setRamWaitState(uint32_t coreFreq,int vscale)5889 static void setRamWaitState(uint32_t coreFreq, int vscale)
5890 {
5891 uint32_t limit = 38000000;
5892 if (vscale == 2) {
5893 limit = 16000000;
5894 }
5895
5896 if (coreFreq > limit) {
5897 BUS_RegMaskedSet(&MSC->RAMCTRL, (MSC_RAMCTRL_RAMWSEN
5898 | MSC_RAMCTRL_RAM1WSEN
5899 | MSC_RAMCTRL_RAM2WSEN));
5900 } else {
5901 BUS_RegMaskedClear(&MSC->RAMCTRL, (MSC_RAMCTRL_RAMWSEN
5902 | MSC_RAMCTRL_RAM1WSEN
5903 | MSC_RAMCTRL_RAM2WSEN));
5904 }
5905 }
5906 #endif
5907
5908 #if defined(_MSC_CTRL_WAITMODE_MASK)
5909 /***************************************************************************//**
5910 * @brief
5911 * Configure the wait state for peripheral accesses over the bus to support
5912 * the given bus clock frequency.
5913 *
5914 * @param[in] busFreq
5915 * A peripheral bus clock frequency to configure wait-states.
5916 *
5917 * @param[in] vscale
5918 * The voltage scale to configure wait-states. Expected values are
5919 * 0 or 2.
5920 *
5921 * @li 0 = 1.2 V (VSCALE2)
5922 * @li 2 = 1.0 V (VSCALE0)
5923 * ******************************************************************************/
setBusWaitState(uint32_t busFreq,int vscale)5924 static void setBusWaitState(uint32_t busFreq, int vscale)
5925 {
5926 if ((busFreq > 50000000) && (vscale == 0)) {
5927 BUS_RegMaskedSet(&MSC->CTRL, MSC_CTRL_WAITMODE_WS1);
5928 } else {
5929 BUS_RegMaskedClear(&MSC->CTRL, MSC_CTRL_WAITMODE_WS1);
5930 }
5931 }
5932 #endif
5933
5934 #if defined(PLFRCO_PRESENT)
deviceHasPlfrco(void)5935 static bool deviceHasPlfrco(void)
5936 {
5937 SYSTEM_ChipRevision_TypeDef rev;
5938
5939 if (_SILICON_LABS_GECKO_INTERNAL_SDID == 89) {
5940 // check the xG13 rev and check if it's >= Rev A3
5941 SYSTEM_ChipRevisionGet(&rev);
5942 return (rev.major > 1) || (rev.minor >= 3);
5943 } else {
5944 return false;
5945 }
5946 }
5947 #endif
5948
5949 /***************************************************************************//**
5950 * @brief
5951 * Configure various wait states to switch to a certain frequency
5952 * and a certain voltage scale.
5953 *
5954 * @details
5955 * This function will set up the necessary flash, bus, and RAM wait states.
5956 * Updating the wait state configuration must be done before
5957 * increasing the clock frequency and it must be done after decreasing the
5958 * clock frequency. Updating the wait state configuration must be done before
5959 * core voltage is decreased and it must be done after a core voltage is
5960 * increased.
5961 *
5962 * @param[in] freq
5963 * The core clock frequency to configure wait-states.
5964 *
5965 * @param[in] vscale
5966 * The voltage scale to configure wait-states. Expected values are
5967 * 0 or 2, higher number is lower voltage.
5968 *
5969 * @li 0 = 1.2 V (VSCALE2)
5970 * @li 2 = 1.0 V (VSCALE0)
5971 *
5972 ******************************************************************************/
CMU_UpdateWaitStates(uint32_t freq,int vscale)5973 void CMU_UpdateWaitStates(uint32_t freq, int vscale)
5974 {
5975 /* Make sure the MSC is unlocked */
5976 bool mscLocked = MSC_LockGetLocked();
5977 MSC_LockSetUnlocked();
5978
5979 flashWaitStateControl(freq, vscale);
5980 #if defined(_MSC_RAMCTRL_RAMWSEN_MASK)
5981 setRamWaitState(freq, vscale);
5982 #endif
5983 #if defined(_MSC_CTRL_WAITMODE_MASK)
5984 setBusWaitState(freq, vscale);
5985 #endif
5986
5987 if (mscLocked) {
5988 MSC_LockSetLocked();
5989 }
5990 }
5991
5992 #if defined(_CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK)
5993 /***************************************************************************//**
5994 * @brief
5995 * Return the upper value for CMU_HFXOSTEADYSTATECTRL_REGISH.
5996 ******************************************************************************/
getRegIshUpperVal(uint32_t steadyStateRegIsh)5997 static uint32_t getRegIshUpperVal(uint32_t steadyStateRegIsh)
5998 {
5999 uint32_t regIshUpper;
6000 const uint32_t upperMax = _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK
6001 >> _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT;
6002 /* Add 3 as specified in the register description for CMU_HFXOSTEADYSTATECTRL_REGISHUPPER. */
6003 regIshUpper = SL_MIN(steadyStateRegIsh + 3UL, upperMax);
6004 regIshUpper <<= _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT;
6005 return regIshUpper;
6006 }
6007 #endif
6008
6009 #if defined(_CMU_HFXOCTRL_MASK)
6010 /***************************************************************************//**
6011 * @brief
6012 * Get the HFXO tuning mode.
6013 *
6014 * @return
6015 * The current HFXO tuning mode from the HFXOCTRL register.
6016 ******************************************************************************/
getHfxoTuningMode(void)6017 __STATIC_INLINE uint32_t getHfxoTuningMode(void)
6018 {
6019 #if defined(_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)
6020 return (CMU->HFXOCTRL & _CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)
6021 >> _CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_SHIFT;
6022 #else
6023 return (CMU->HFXOCTRL & _CMU_HFXOCTRL_PEAKDETMODE_MASK)
6024 >> _CMU_HFXOCTRL_PEAKDETMODE_SHIFT;
6025 #endif
6026 }
6027
6028 /***************************************************************************//**
6029 * @brief
6030 * Set the HFXO tuning mode.
6031 *
6032 * @param[in] mode
6033 * The new HFXO tuning mode. This can be HFXO_TUNING_MODE_AUTO or
6034 * HFXO_TUNING_MODE_CMD.
6035 ******************************************************************************/
setHfxoTuningMode(uint32_t mode)6036 __STATIC_INLINE void setHfxoTuningMode(uint32_t mode)
6037 {
6038 #if defined(_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)
6039 CMU->HFXOCTRL = (CMU->HFXOCTRL & ~_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)
6040 | (mode << _CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_SHIFT);
6041 #else
6042 CMU->HFXOCTRL = (CMU->HFXOCTRL & ~_CMU_HFXOCTRL_PEAKDETMODE_MASK)
6043 | (mode << _CMU_HFXOCTRL_PEAKDETMODE_SHIFT);
6044 #endif
6045 }
6046 #endif
6047
6048 /***************************************************************************//**
6049 * @brief
6050 * Get the LFnCLK frequency based on the current configuration.
6051 *
6052 * @param[in] lfClkBranch
6053 * Selected LF branch.
6054 *
6055 * @return
6056 * The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is
6057 * returned.
6058 ******************************************************************************/
lfClkGet(CMU_Clock_TypeDef lfClkBranch)6059 static uint32_t lfClkGet(CMU_Clock_TypeDef lfClkBranch)
6060 {
6061 uint32_t sel;
6062 uint32_t ret = 0;
6063
6064 switch (lfClkBranch) {
6065 case cmuClock_LFA:
6066 case cmuClock_LFB:
6067 #if defined(_CMU_LFCCLKEN0_MASK)
6068 case cmuClock_LFC:
6069 #endif
6070 #if defined(_CMU_LFECLKSEL_MASK)
6071 case cmuClock_LFE:
6072 #endif
6073 break;
6074
6075 default:
6076 EFM_ASSERT(false);
6077 break;
6078 }
6079
6080 sel = (uint32_t)CMU_ClockSelectGet(lfClkBranch);
6081
6082 /* Get clock select field */
6083 switch (lfClkBranch) {
6084 case cmuClock_LFA:
6085 #if defined(_CMU_LFCLKSEL_MASK)
6086 sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK) >> _CMU_LFCLKSEL_LFA_SHIFT;
6087 #elif defined(_CMU_LFACLKSEL_MASK)
6088 sel = (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK) >> _CMU_LFACLKSEL_LFA_SHIFT;
6089 #else
6090 EFM_ASSERT(false);
6091 #endif
6092 break;
6093
6094 case cmuClock_LFB:
6095 #if defined(_CMU_LFCLKSEL_MASK)
6096 sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK) >> _CMU_LFCLKSEL_LFB_SHIFT;
6097 #elif defined(_CMU_LFBCLKSEL_MASK)
6098 sel = (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK) >> _CMU_LFBCLKSEL_LFB_SHIFT;
6099 #else
6100 EFM_ASSERT(false);
6101 #endif
6102 break;
6103
6104 #if defined(_CMU_LFCCLKEN0_MASK)
6105 case cmuClock_LFC:
6106 #if defined(_CMU_LFCLKSEL_LFC_MASK)
6107 sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK) >> _CMU_LFCLKSEL_LFC_SHIFT;
6108 #elif defined(_CMU_LFCCLKSEL_LFC_MASK)
6109 sel = (CMU->LFCCLKSEL & _CMU_LFCCLKSEL_LFC_MASK) >> _CMU_LFCCLKSEL_LFC_SHIFT;
6110 #else
6111 EFM_ASSERT(false);
6112 #endif
6113 break;
6114 #endif
6115
6116 #if defined(_CMU_LFECLKSEL_MASK)
6117 case cmuClock_LFE:
6118 sel = (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK) >> _CMU_LFECLKSEL_LFE_SHIFT;
6119 break;
6120 #endif
6121
6122 default:
6123 EFM_ASSERT(false);
6124 break;
6125 }
6126
6127 /* Get the clock frequency. */
6128 #if defined(_CMU_LFCLKSEL_MASK)
6129 switch (sel) {
6130 case _CMU_LFCLKSEL_LFA_LFRCO:
6131 ret = SystemLFRCOClockGet();
6132 break;
6133
6134 case _CMU_LFCLKSEL_LFA_LFXO:
6135 ret = SystemLFXOClockGet();
6136 break;
6137
6138 #if defined(_CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2)
6139 case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
6140 #if defined(CMU_MAX_FREQ_HFLE)
6141 /* HFLE bit is or'ed by hardware with HFCORECLKLEDIV to reduce the
6142 * frequency of CMU_HFCORECLKLEDIV2. */
6143 ret = SystemCoreClockGet() / (1U << (getHfLeConfig() + 1));
6144 #else
6145 ret = SystemCoreClockGet() / 2U;
6146 #endif
6147 break;
6148 #endif
6149
6150 case _CMU_LFCLKSEL_LFA_DISABLED:
6151 ret = 0;
6152 #if defined(CMU_LFCLKSEL_LFAE)
6153 /* Check LF Extended bit setting for LFA or LFB ULFRCO clock. */
6154 if ((lfClkBranch == cmuClock_LFA) || (lfClkBranch == cmuClock_LFB)) {
6155 if (CMU->LFCLKSEL >> (lfClkBranch == cmuClock_LFA
6156 ? _CMU_LFCLKSEL_LFAE_SHIFT
6157 : _CMU_LFCLKSEL_LFBE_SHIFT)) {
6158 ret = SystemULFRCOClockGet();
6159 }
6160 }
6161 #endif
6162 break;
6163
6164 default:
6165 ret = 0U;
6166 EFM_ASSERT(false);
6167 break;
6168 }
6169 #endif /* _CMU_LFCLKSEL_MASK */
6170
6171 #if defined(_CMU_LFACLKSEL_MASK)
6172 switch (sel) {
6173 case _CMU_LFACLKSEL_LFA_LFRCO:
6174 ret = SystemLFRCOClockGet();
6175 break;
6176
6177 case _CMU_LFACLKSEL_LFA_LFXO:
6178 ret = SystemLFXOClockGet();
6179 break;
6180
6181 case _CMU_LFACLKSEL_LFA_ULFRCO:
6182 ret = SystemULFRCOClockGet();
6183 break;
6184
6185 #if defined(PLFRCO_PRESENT)
6186 case _CMU_LFACLKSEL_LFA_PLFRCO:
6187 ret = SystemLFRCOClockGet();
6188 break;
6189 #endif
6190
6191 #if defined(_CMU_LFBCLKSEL_LFB_HFCLKLE)
6192 case _CMU_LFBCLKSEL_LFB_HFCLKLE:
6193 ret = SystemHFClockGet()
6194 / SL_Log2ToDiv(((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)
6195 >> _CMU_HFPRESC_HFCLKLEPRESC_SHIFT) + 1UL);
6196 break;
6197 #endif
6198
6199 case _CMU_LFACLKSEL_LFA_DISABLED:
6200 ret = 0;
6201 break;
6202
6203 default:
6204 ret = 0U;
6205 EFM_ASSERT(false);
6206 break;
6207 }
6208 #endif
6209
6210 return ret;
6211 }
6212
6213 /***************************************************************************//**
6214 * @brief
6215 * Wait for an ongoing sync of register(s) to low-frequency domain to complete.
6216 *
6217 * @param[in] mask
6218 * A bitmask corresponding to SYNCBUSY register defined bits, indicating
6219 * registers that must complete any ongoing synchronization.
6220 ******************************************************************************/
syncReg(uint32_t mask)6221 __STATIC_INLINE void syncReg(uint32_t mask)
6222 {
6223 /* Avoid a deadlock if modifying the same register twice when freeze mode is */
6224 /* activated. */
6225 if ((CMU->FREEZE & CMU_FREEZE_REGFREEZE) != 0UL) {
6226 return;
6227 }
6228
6229 /* Wait for any pending previous write operation to complete */
6230 /* in low-frequency domain. */
6231 while ((CMU->SYNCBUSY & mask) != 0UL) {
6232 }
6233 }
6234
6235 #if defined(USBC_CLOCK_PRESENT)
6236 /***************************************************************************//**
6237 * @brief
6238 * Get the USBC frequency.
6239 *
6240 * @return
6241 * USBC frequency in Hz.
6242 ******************************************************************************/
usbCClkGet(void)6243 static uint32_t usbCClkGet(void)
6244 {
6245 uint32_t ret;
6246 CMU_Select_TypeDef clk;
6247
6248 /* Get the selected clock source. */
6249 clk = CMU_ClockSelectGet(cmuClock_USBC);
6250
6251 switch (clk) {
6252 case cmuSelect_LFXO:
6253 ret = SystemLFXOClockGet();
6254 break;
6255 case cmuSelect_LFRCO:
6256 ret = SystemLFRCOClockGet();
6257 break;
6258 #if defined (_CMU_USHFRCOCTRL_MASK)
6259 case cmuSelect_USHFRCO:
6260 ret = ushfrcoFreq;
6261 break;
6262 #endif
6263 case cmuSelect_HFCLK:
6264 ret = SystemHFClockGet();
6265 break;
6266 default:
6267 /* Clock is not enabled */
6268 ret = 0;
6269 break;
6270 }
6271 return ret;
6272 }
6273 #endif
6274
6275 /***************************************************************************//**
6276 * @brief
6277 * Set HFPER clock tree prescalers to safe values.
6278 *
6279 * @note
6280 * This function applies to EFM32GG11B. There are 3 HFPER clock trees with
6281 * these frequency limits:
6282 * HFPERCLK (A-tree): 20MHz in VSCALE0 mode, 50MHz in VSCALE2 mode.
6283 * HFPERBCLK (B-tree): 20MHz in VSCALE0 mode, 72MHz in VSCALE2 mode.
6284 * HFPERCCLK (C-tree): 20MHz in VSCALE0 mode, 50MHz in VSCALE2 mode.
6285 ******************************************************************************/
hfperClkSafePrescaler(void)6286 static void hfperClkSafePrescaler(void)
6287 {
6288 #if defined(_CMU_HFPERPRESC_MASK) && defined(_CMU_HFPERPRESCB_MASK) \
6289 && defined(_CMU_HFPERPRESCC_MASK)
6290 // Assuming a maximum HFCLK of 72MHz, set prescalers to DIV4.
6291 CMU_ClockPrescSet(cmuClock_HFPER, 3U);
6292 CMU_ClockPrescSet(cmuClock_HFPERB, 3U);
6293 CMU_ClockPrescSet(cmuClock_HFPERC, 3U);
6294 #endif
6295 }
6296
6297 /***************************************************************************//**
6298 * @brief
6299 * Set HFPER clock tree prescalers to give highest possible clock node
6300 * frequency while still beeing within spec.
6301 *
6302 * @note
6303 * This function applies to EFM32GG11B. There are 3 HFPER clock trees with
6304 * these frequency limits:
6305 * HFPERCLK (A-tree): 20MHz in VSCALE0 mode, 50MHz in VSCALE2 mode.
6306 * HFPERBCLK (B-tree): 20MHz in VSCALE0 mode, 72MHz in VSCALE2 mode.
6307 * HFPERCCLK (C-tree): 20MHz in VSCALE0 mode, 50MHz in VSCALE2 mode.
6308 ******************************************************************************/
hfperClkOptimizedPrescaler(void)6309 static void hfperClkOptimizedPrescaler(void)
6310 {
6311 #if defined(_CMU_HFPERPRESC_MASK) && defined(_CMU_HFPERPRESCB_MASK) \
6312 && defined(_CMU_HFPERPRESCC_MASK)
6313 uint32_t hfClkFreq, divisor;
6314
6315 hfClkFreq = SystemHFClockGet();
6316
6317 if ( EMU_VScaleGet() == emuVScaleEM01_LowPower) {
6318 divisor = (hfClkFreq + 20000000U - 1U) / 20000000U; // ceil(x)
6319 if (divisor > 0U) {
6320 divisor--; // Convert to prescaler
6321 }
6322 CMU_ClockPrescSet(cmuClock_HFPER, divisor);
6323 CMU_ClockPrescSet(cmuClock_HFPERB, divisor);
6324 CMU_ClockPrescSet(cmuClock_HFPERC, divisor);
6325 } else {
6326 divisor = (hfClkFreq + 50000000U - 1U) / 50000000U;
6327 if (divisor > 0U) {
6328 divisor--;
6329 }
6330 CMU_ClockPrescSet(cmuClock_HFPER, divisor);
6331 CMU_ClockPrescSet(cmuClock_HFPERC, divisor);
6332
6333 divisor = (hfClkFreq + 72000000U - 1U) / 72000000U;
6334 if (divisor > 0U) {
6335 divisor--;
6336 }
6337 CMU_ClockPrescSet(cmuClock_HFPERB, divisor);
6338 }
6339 #endif
6340 }
6341
6342 /*******************************************************************************
6343 ************************** GLOBAL FUNCTIONS *******************************
6344 ******************************************************************************/
6345
6346 #if defined(_CMU_AUXHFRCOCTRL_BAND_MASK)
6347 /***************************************************************************//**
6348 * @brief
6349 * Get the AUXHFRCO band in use.
6350 *
6351 * @return
6352 * AUXHFRCO band in use.
6353 ******************************************************************************/
CMU_AUXHFRCOBandGet(void)6354 CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void)
6355 {
6356 return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL
6357 & _CMU_AUXHFRCOCTRL_BAND_MASK)
6358 >> _CMU_AUXHFRCOCTRL_BAND_SHIFT);
6359 }
6360 #endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */
6361
6362 #if defined(_CMU_AUXHFRCOCTRL_BAND_MASK)
6363 /***************************************************************************//**
6364 * @brief
6365 * Set the AUXHFRCO band and the tuning value based on the value in the
6366 * calibration table made during production.
6367 *
6368 * @param[in] band
6369 * AUXHFRCO band to activate.
6370 ******************************************************************************/
CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)6371 void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)
6372 {
6373 uint32_t tuning;
6374
6375 /* Read a tuning value from the calibration table. */
6376 switch (band) {
6377 case cmuAUXHFRCOBand_1MHz:
6378 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK)
6379 >> _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT;
6380 break;
6381
6382 case cmuAUXHFRCOBand_7MHz:
6383 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK)
6384 >> _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT;
6385 break;
6386
6387 case cmuAUXHFRCOBand_11MHz:
6388 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK)
6389 >> _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT;
6390 break;
6391
6392 case cmuAUXHFRCOBand_14MHz:
6393 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK)
6394 >> _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT;
6395 break;
6396
6397 case cmuAUXHFRCOBand_21MHz:
6398 tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK)
6399 >> _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT;
6400 break;
6401
6402 #if defined(_CMU_AUXHFRCOCTRL_BAND_28MHZ)
6403 case cmuAUXHFRCOBand_28MHz:
6404 tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK)
6405 >> _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT;
6406 break;
6407 #endif
6408
6409 default:
6410 EFM_ASSERT(false);
6411 return;
6412 }
6413
6414 /* Set band/tuning. */
6415 CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL
6416 & ~(_CMU_AUXHFRCOCTRL_BAND_MASK
6417 | _CMU_AUXHFRCOCTRL_TUNING_MASK))
6418 | (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT)
6419 | (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);
6420 }
6421 #endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */
6422
6423 #if defined(_CMU_AUXHFRCOCTRL_FREQRANGE_MASK)
6424 /**************************************************************************//**
6425 * @brief
6426 * Get the AUXHFRCO frequency calibration word in DEVINFO.
6427 *
6428 * @param[in] freq
6429 * Frequency in Hz.
6430 *
6431 * @return
6432 * AUXHFRCO calibration word for a given frequency.
6433 *****************************************************************************/
CMU_AUXHFRCODevinfoGet(CMU_AUXHFRCOFreq_TypeDef freq)6434 static uint32_t CMU_AUXHFRCODevinfoGet(CMU_AUXHFRCOFreq_TypeDef freq)
6435 {
6436 switch (freq) {
6437 /* 1, 2, and 4 MHz share the same calibration word. */
6438 case cmuAUXHFRCOFreq_1M0Hz:
6439 case cmuAUXHFRCOFreq_2M0Hz:
6440 case cmuAUXHFRCOFreq_4M0Hz:
6441 return DEVINFO->AUXHFRCOCAL0;
6442
6443 case cmuAUXHFRCOFreq_7M0Hz:
6444 return DEVINFO->AUXHFRCOCAL3;
6445
6446 case cmuAUXHFRCOFreq_13M0Hz:
6447 return DEVINFO->AUXHFRCOCAL6;
6448
6449 case cmuAUXHFRCOFreq_16M0Hz:
6450 return DEVINFO->AUXHFRCOCAL7;
6451
6452 case cmuAUXHFRCOFreq_19M0Hz:
6453 return DEVINFO->AUXHFRCOCAL8;
6454
6455 case cmuAUXHFRCOFreq_26M0Hz:
6456 return DEVINFO->AUXHFRCOCAL10;
6457
6458 case cmuAUXHFRCOFreq_32M0Hz:
6459 return DEVINFO->AUXHFRCOCAL11;
6460
6461 case cmuAUXHFRCOFreq_38M0Hz:
6462 return DEVINFO->AUXHFRCOCAL12;
6463
6464 #if defined(_DEVINFO_AUXHFRCOCAL13_MASK)
6465 case cmuAUXHFRCOFreq_48M0Hz:
6466 return DEVINFO->AUXHFRCOCAL13;
6467 #endif
6468 #if defined(_DEVINFO_AUXHFRCOCAL14_MASK)
6469 case cmuAUXHFRCOFreq_50M0Hz:
6470 return DEVINFO->AUXHFRCOCAL14;
6471 #endif
6472
6473 default: /* cmuAUXHFRCOFreq_UserDefined */
6474 return 0;
6475 }
6476 }
6477 #endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */
6478
6479 #if defined(_CMU_AUXHFRCOCTRL_FREQRANGE_MASK)
6480 /***************************************************************************//**
6481 * @brief
6482 * Get the current AUXHFRCO frequency.
6483 *
6484 * @return
6485 * AUXHFRCO frequency.
6486 ******************************************************************************/
CMU_AUXHFRCOBandGet(void)6487 CMU_AUXHFRCOFreq_TypeDef CMU_AUXHFRCOBandGet(void)
6488 {
6489 return auxHfrcoFreq;
6490 }
6491 #endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */
6492
6493 #if defined(_CMU_AUXHFRCOCTRL_FREQRANGE_MASK)
6494 /***************************************************************************//**
6495 * @brief
6496 * Set AUXHFRCO calibration for the selected target frequency.
6497 *
6498 * @param[in] setFreq
6499 * AUXHFRCO frequency to set
6500 ******************************************************************************/
CMU_AUXHFRCOBandSet(CMU_AUXHFRCOFreq_TypeDef setFreq)6501 void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOFreq_TypeDef setFreq)
6502 {
6503 uint32_t freqCal;
6504
6505 /* Get DEVINFO index and set global auxHfrcoFreq. */
6506 freqCal = CMU_AUXHFRCODevinfoGet(setFreq);
6507 EFM_ASSERT((freqCal != 0UL) && (freqCal != UINT_MAX));
6508 auxHfrcoFreq = setFreq;
6509
6510 /* Wait for any previous sync to complete, then set calibration data
6511 for the selected frequency. */
6512 while (BUS_RegBitRead(&CMU->SYNCBUSY,
6513 _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT) != 0UL) {
6514 }
6515
6516 /* Set a divider in AUXHFRCOCTRL for 1, 2, and 4 MHz. */
6517 switch (setFreq) {
6518 case cmuAUXHFRCOFreq_1M0Hz:
6519 freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)
6520 | CMU_AUXHFRCOCTRL_CLKDIV_DIV4;
6521 break;
6522
6523 case cmuAUXHFRCOFreq_2M0Hz:
6524 freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)
6525 | CMU_AUXHFRCOCTRL_CLKDIV_DIV2;
6526 break;
6527
6528 case cmuAUXHFRCOFreq_4M0Hz:
6529 freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)
6530 | CMU_AUXHFRCOCTRL_CLKDIV_DIV1;
6531 break;
6532
6533 default:
6534 break;
6535 }
6536 CMU->AUXHFRCOCTRL = freqCal;
6537 }
6538 #endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */
6539
6540 /***************************************************************************//**
6541 * @brief
6542 * Calibrate the clock.
6543 *
6544 * @details
6545 * Run a calibration for HFCLK against a selectable reference clock.
6546 * See the reference manual, CMU chapter, for more details.
6547 *
6548 * @note
6549 * This function will not return until the calibration measurement is completed.
6550 *
6551 * @param[in] HFCycles
6552 * The number of HFCLK cycles to run the calibration. Increasing this number
6553 * increases precision but the calibration will take more time.
6554 *
6555 * @param[in] reference
6556 * The reference clock used to compare HFCLK.
6557 *
6558 * @return
6559 * The number of ticks the reference clock after HFCycles ticks on the HF
6560 * clock.
6561 ******************************************************************************/
CMU_Calibrate(uint32_t HFCycles,CMU_Osc_TypeDef reference)6562 uint32_t CMU_Calibrate(uint32_t HFCycles, CMU_Osc_TypeDef reference)
6563 {
6564 EFM_ASSERT(HFCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));
6565
6566 /* Set the reference clock source. */
6567 switch (reference) {
6568 case cmuOsc_LFXO:
6569 CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO;
6570 break;
6571
6572 case cmuOsc_LFRCO:
6573 CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO;
6574 break;
6575
6576 #if defined(PLFRCO_PRESENT)
6577 case cmuOsc_PLFRCO:
6578 CMU->CALCTRL = CMU_CALCTRL_UPSEL_PLFRCO;
6579 break;
6580 #endif
6581
6582 case cmuOsc_HFXO:
6583 CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO;
6584 break;
6585
6586 case cmuOsc_HFRCO:
6587 CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO;
6588 break;
6589
6590 case cmuOsc_AUXHFRCO:
6591 CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO;
6592 break;
6593
6594 #if defined (_CMU_USHFRCOCTRL_MASK)
6595 case cmuOsc_USHFRCO:
6596 CMU->CALCTRL = CMU_CALCTRL_UPSEL_USHFRCO;
6597 break;
6598 #endif
6599
6600 default:
6601 EFM_ASSERT(false);
6602 return 0;
6603 }
6604
6605 /* Set the top value. */
6606 CMU->CALCNT = HFCycles;
6607
6608 /* Start the calibration. */
6609 CMU->CMD = CMU_CMD_CALSTART;
6610
6611 #if defined(CMU_STATUS_CALRDY)
6612 /* Wait until calibration completes. */
6613 while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT) == 0UL) {
6614 }
6615 #else
6616 /* Wait until calibration completes. */
6617 while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT) != 0UL) {
6618 }
6619 #endif
6620
6621 return CMU->CALCNT;
6622 }
6623
6624 #if defined(_CMU_CALCTRL_UPSEL_MASK) && defined(_CMU_CALCTRL_DOWNSEL_MASK)
6625 /***************************************************************************//**
6626 * @brief
6627 * Configure the clock calibration.
6628 *
6629 * @details
6630 * Configure a calibration for a selectable clock source against another
6631 * selectable reference clock.
6632 * See the reference manual, CMU chapter, for more details.
6633 *
6634 * @note
6635 * After configuration, a call to @ref CMU_CalibrateStart() is required and
6636 * the resulting calibration value can be read out with the
6637 * @ref CMU_CalibrateCountGet() function call.
6638 *
6639 * @param[in] downCycles
6640 * The number of downSel clock cycles to run the calibration. Increasing this
6641 * number increases precision but the calibration will take more time.
6642 *
6643 * @param[in] downSel
6644 * The clock, which will be counted down downCycles.
6645 *
6646 * @param[in] upSel
6647 * The reference clock; the number of cycles generated by this clock will
6648 * be counted and added up and the result can be given with the
6649 * @ref CMU_CalibrateCountGet() function call.
6650 ******************************************************************************/
CMU_CalibrateConfig(uint32_t downCycles,CMU_Osc_TypeDef downSel,CMU_Osc_TypeDef upSel)6651 void CMU_CalibrateConfig(uint32_t downCycles, CMU_Osc_TypeDef downSel,
6652 CMU_Osc_TypeDef upSel)
6653 {
6654 /* Keep configuration settings untouched. */
6655 uint32_t calCtrl = CMU->CALCTRL
6656 & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK);
6657
6658 /* 20 bits of precision to calibration count register. */
6659 EFM_ASSERT(downCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));
6660
6661 /* Set down counting clock source - down counter. */
6662 switch (downSel) {
6663 case cmuOsc_LFXO:
6664 calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO;
6665 break;
6666
6667 case cmuOsc_LFRCO:
6668 calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO;
6669 break;
6670
6671 #if defined(PLFRCO_PRESENT)
6672 case cmuOsc_PLFRCO:
6673 calCtrl |= CMU_CALCTRL_DOWNSEL_PLFRCO;
6674 break;
6675 #endif
6676
6677 case cmuOsc_HFXO:
6678 calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO;
6679 break;
6680
6681 case cmuOsc_HFRCO:
6682 calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO;
6683 break;
6684
6685 case cmuOsc_AUXHFRCO:
6686 calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO;
6687 break;
6688
6689 #if defined (_CMU_USHFRCOCTRL_MASK)
6690 case cmuOsc_USHFRCO:
6691 calCtrl |= CMU_CALCTRL_DOWNSEL_USHFRCO;
6692 break;
6693 #endif
6694
6695 default:
6696 EFM_ASSERT(false);
6697 break;
6698 }
6699
6700 /* Set the top value to be counted down by the downSel clock. */
6701 CMU->CALCNT = downCycles;
6702
6703 /* Set the reference clock source - up counter. */
6704 switch (upSel) {
6705 case cmuOsc_LFXO:
6706 calCtrl |= CMU_CALCTRL_UPSEL_LFXO;
6707 break;
6708
6709 case cmuOsc_LFRCO:
6710 calCtrl |= CMU_CALCTRL_UPSEL_LFRCO;
6711 break;
6712
6713 #if defined(PLFRCO_PRESENT)
6714 case cmuOsc_PLFRCO:
6715 calCtrl |= CMU_CALCTRL_UPSEL_PLFRCO;
6716 break;
6717 #endif
6718
6719 case cmuOsc_HFXO:
6720 calCtrl |= CMU_CALCTRL_UPSEL_HFXO;
6721 break;
6722
6723 case cmuOsc_HFRCO:
6724 calCtrl |= CMU_CALCTRL_UPSEL_HFRCO;
6725 break;
6726
6727 case cmuOsc_AUXHFRCO:
6728 calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO;
6729 break;
6730
6731 #if defined (_CMU_USHFRCOCTRL_MASK)
6732 case cmuOsc_USHFRCO:
6733 calCtrl |= CMU_CALCTRL_UPSEL_USHFRCO;
6734 break;
6735 #endif
6736
6737 default:
6738 EFM_ASSERT(false);
6739 break;
6740 }
6741
6742 CMU->CALCTRL = calCtrl;
6743 }
6744 #endif
6745
6746 /***************************************************************************//**
6747 * @brief
6748 * Get the calibration count register.
6749 * @note
6750 * If continuous calibration mode is active, calibration busy will almost
6751 * always be off and only the value needs to be read. In a normal case,
6752 * this function call is triggered by the CALRDY
6753 * interrupt flag.
6754 * @return
6755 * The calibration count, the number of UPSEL clocks
6756 * in the period of DOWNSEL oscillator clock cycles configured by a previous
6757 * write operation to CMU->CALCNT.
6758 ******************************************************************************/
CMU_CalibrateCountGet(void)6759 uint32_t CMU_CalibrateCountGet(void)
6760 {
6761 /* Wait until calibration completes, UNLESS continuous calibration mode is */
6762 /* active. */
6763 #if defined(CMU_CALCTRL_CONT)
6764 if (BUS_RegBitRead(&CMU->CALCTRL, _CMU_CALCTRL_CONT_SHIFT) == 0UL) {
6765 #if defined(CMU_STATUS_CALRDY)
6766 /* Wait until calibration completes */
6767 while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT) == 0UL) {
6768 }
6769 #else
6770 /* Wait until calibration completes */
6771 while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT) != 0UL) {
6772 }
6773 #endif
6774 }
6775 #else
6776 while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT) != 0UL) {
6777 }
6778 #endif
6779 return CMU->CALCNT;
6780 }
6781
6782 /***************************************************************************//**
6783 * @brief
6784 * Get the clock divisor/prescaler.
6785 *
6786 * @param[in] clock
6787 * A clock point to get the divisor/prescaler for. Notice that not all clock points
6788 * have a divisor/prescaler. See the CMU overview in the reference manual.
6789 *
6790 * @return
6791 * The current clock point divisor/prescaler. 1 is returned
6792 * if @p clock specifies a clock point without a divisor/prescaler.
6793 ******************************************************************************/
CMU_ClockDivGet(CMU_Clock_TypeDef clock)6794 CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock)
6795 {
6796 #if defined(_SILICON_LABS_32B_SERIES_1)
6797 return 1UL + (uint32_t)CMU_ClockPrescGet(clock);
6798
6799 #elif defined(_SILICON_LABS_32B_SERIES_0)
6800 uint32_t divReg;
6801 CMU_ClkDiv_TypeDef ret;
6802
6803 /* Get divisor reg ID. */
6804 divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;
6805
6806 switch (divReg) {
6807 #if defined(_CMU_CTRL_HFCLKDIV_MASK)
6808 case CMU_HFCLKDIV_REG:
6809 ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)
6810 >> _CMU_CTRL_HFCLKDIV_SHIFT);
6811 break;
6812 #endif
6813
6814 case CMU_HFPERCLKDIV_REG:
6815 ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV
6816 & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)
6817 >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);
6818 ret = SL_Log2ToDiv(ret);
6819 break;
6820
6821 case CMU_HFCORECLKDIV_REG:
6822 ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV
6823 & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK)
6824 >> _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);
6825 ret = SL_Log2ToDiv(ret);
6826 break;
6827
6828 #if defined(_CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK)
6829 case CMU_HFCORECLKLEDIV_REG:
6830 ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV
6831 & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK)
6832 >> _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT);
6833 ret = SL_Log2ToDiv(ret + 1U);
6834 break;
6835 #endif
6836
6837 case CMU_LFAPRESC0_REG:
6838 switch (clock) {
6839 case cmuClock_RTC:
6840 ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)
6841 >> _CMU_LFAPRESC0_RTC_SHIFT);
6842 ret = SL_Log2ToDiv(ret);
6843 break;
6844
6845 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
6846 case cmuClock_LETIMER0:
6847 ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)
6848 >> _CMU_LFAPRESC0_LETIMER0_SHIFT);
6849 ret = SL_Log2ToDiv(ret);
6850 break;
6851 #endif
6852
6853 #if defined(_CMU_LFAPRESC0_LCD_MASK)
6854 case cmuClock_LCDpre:
6855 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)
6856 >> _CMU_LFAPRESC0_LCD_SHIFT)
6857 + CMU_DivToLog2(cmuClkDiv_16));
6858 ret = SL_Log2ToDiv(ret);
6859 break;
6860 #endif
6861
6862 #if defined(_CMU_LFAPRESC0_LESENSE_MASK)
6863 case cmuClock_LESENSE:
6864 ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)
6865 >> _CMU_LFAPRESC0_LESENSE_SHIFT);
6866 ret = SL_Log2ToDiv(ret);
6867 break;
6868 #endif
6869
6870 default:
6871 ret = cmuClkDiv_1;
6872 EFM_ASSERT(false);
6873 break;
6874 }
6875 break;
6876
6877 case CMU_LFBPRESC0_REG:
6878 switch (clock) {
6879 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)
6880 case cmuClock_LEUART0:
6881 ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)
6882 >> _CMU_LFBPRESC0_LEUART0_SHIFT);
6883 ret = SL_Log2ToDiv(ret);
6884 break;
6885 #endif
6886
6887 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)
6888 case cmuClock_LEUART1:
6889 ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)
6890 >> _CMU_LFBPRESC0_LEUART1_SHIFT);
6891 ret = SL_Log2ToDiv(ret);
6892 break;
6893 #endif
6894
6895 default:
6896 ret = cmuClkDiv_1;
6897 EFM_ASSERT(false);
6898 break;
6899 }
6900 break;
6901
6902 default:
6903 ret = cmuClkDiv_1;
6904 EFM_ASSERT(false);
6905 break;
6906 }
6907
6908 return ret;
6909 #endif
6910 }
6911
6912 /***************************************************************************//**
6913 * @brief
6914 * Set the clock divisor/prescaler.
6915 *
6916 * @note
6917 * If setting an LF clock prescaler, synchronization into the low-frequency
6918 * domain is required. If the same register is modified before a previous
6919 * update has completed, this function will stall until the previous
6920 * synchronization has completed. See @ref CMU_FreezeEnable() for
6921 * a suggestion on how to reduce the stalling time in some use cases.
6922 *
6923 * HFCLKLE prescaler is automatically modified when peripherals with clock
6924 * domain HFBUSCLK is chosen based on the maximum HFLE frequency allowed.
6925 *
6926 * @param[in] clock
6927 * Clock point to set divisor/prescaler for. Notice that not all clock points
6928 * have a divisor/prescaler. See the CMU overview in the reference
6929 * manual.
6930 *
6931 * @param[in] div
6932 * The clock divisor to use (<= cmuClkDiv_512).
6933 ******************************************************************************/
CMU_ClockDivSet(CMU_Clock_TypeDef clock,CMU_ClkDiv_TypeDef div)6934 void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)
6935 {
6936 #if defined(_SILICON_LABS_32B_SERIES_1)
6937 CMU_ClockPrescSet(clock, (CMU_ClkPresc_TypeDef)(div - 1U));
6938
6939 #elif defined(_SILICON_LABS_32B_SERIES_0)
6940 uint32_t freq;
6941 uint32_t divReg;
6942
6943 /* Get the divisor reg ID. */
6944 divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;
6945
6946 switch (divReg) {
6947 #if defined(_CMU_CTRL_HFCLKDIV_MASK)
6948 case CMU_HFCLKDIV_REG:
6949 EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_8));
6950
6951 /* Configure worst case wait states for flash access before setting divisor. */
6952 flashWaitStateMax();
6953
6954 /* Set the divider. */
6955 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK)
6956 | ((div - 1) << _CMU_CTRL_HFCLKDIV_SHIFT);
6957
6958 /* Update the CMSIS core clock variable. */
6959 /* (The function will update the global variable). */
6960 freq = SystemCoreClockGet();
6961
6962 /* Optimize flash access wait state setting for the current core clk. */
6963 CMU_UpdateWaitStates(freq, VSCALE_DEFAULT);
6964 break;
6965 #endif
6966
6967 case CMU_HFPERCLKDIV_REG:
6968 EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512));
6969 /* Convert to the correct scale. */
6970 div = CMU_DivToLog2(div);
6971 CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)
6972 | (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);
6973 break;
6974
6975 #if defined(_CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK)
6976 case CMU_HFCORECLKLEDIV_REG:
6977 /*
6978 This divisor is usually set when changing HF clock to keep HFLE clock
6979 within safe bounds. This code path ignore these constraints.
6980 */
6981 /* Convert to the correct scale. */
6982 div = CMU_DivToLog2(div) - 1U;
6983 CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV
6984 & ~_CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK)
6985 | (div << _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT);
6986 break;
6987 #endif
6988
6989 case CMU_HFCORECLKDIV_REG:
6990 EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512));
6991
6992 /* Configure worst case wait states for flash access before setting the divisor. */
6993 flashWaitStateMax();
6994
6995 #if defined(CMU_MAX_FREQ_HFLE)
6996 setHfLeConfig(SystemCoreClockGet() / div);
6997 #endif
6998
6999 /* Convert to the correct scale. */
7000 div = CMU_DivToLog2(div);
7001
7002 CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV
7003 & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK)
7004 | (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);
7005
7006 /* Update the CMSIS core clock variable. */
7007 /* (The function will update the global variable). */
7008 freq = SystemCoreClockGet();
7009
7010 /* Optimize wait state setting for the current core clk. */
7011 CMU_UpdateWaitStates(freq, VSCALE_DEFAULT);
7012 #if defined(CMU_MAX_FREQ_HFLE)
7013 setHfLeConfig(freq);
7014 #endif
7015 break;
7016
7017 case CMU_LFAPRESC0_REG:
7018 switch (clock) {
7019 case cmuClock_RTC:
7020 EFM_ASSERT(div <= cmuClkDiv_32768);
7021
7022 /* LF register about to be modified requires sync. busy check. */
7023 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7024
7025 /* Convert to the correct scale. */
7026 div = CMU_DivToLog2(div);
7027
7028 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK)
7029 | (div << _CMU_LFAPRESC0_RTC_SHIFT);
7030 break;
7031
7032 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
7033 case cmuClock_LETIMER0:
7034 EFM_ASSERT(div <= cmuClkDiv_32768);
7035
7036 /* LF register about to be modified requires sync. busy check. */
7037 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7038
7039 /* Convert to the correct scale. */
7040 div = CMU_DivToLog2(div);
7041
7042 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK)
7043 | (div << _CMU_LFAPRESC0_LETIMER0_SHIFT);
7044 break;
7045 #endif
7046
7047 #if defined(LCD_PRESENT)
7048 case cmuClock_LCDpre:
7049 EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128));
7050
7051 /* LF register about to be modified requires sync. busy check. */
7052 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7053
7054 /* Convert to the correct scale. */
7055 div = CMU_DivToLog2(div);
7056
7057 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK)
7058 | ((div - CMU_DivToLog2(cmuClkDiv_16))
7059 << _CMU_LFAPRESC0_LCD_SHIFT);
7060 break;
7061 #endif /* defined(LCD_PRESENT) */
7062
7063 #if defined(LESENSE_PRESENT)
7064 case cmuClock_LESENSE:
7065 EFM_ASSERT(div <= cmuClkDiv_8);
7066
7067 /* LF register about to be modified requires sync. busy check. */
7068 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7069
7070 /* Convert to the correct scale. */
7071 div = CMU_DivToLog2(div);
7072
7073 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK)
7074 | (div << _CMU_LFAPRESC0_LESENSE_SHIFT);
7075 break;
7076 #endif /* defined(LESENSE_PRESENT) */
7077
7078 default:
7079 EFM_ASSERT(false);
7080 break;
7081 }
7082 break;
7083
7084 case CMU_LFBPRESC0_REG:
7085 switch (clock) {
7086 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)
7087 case cmuClock_LEUART0:
7088 EFM_ASSERT(div <= cmuClkDiv_8);
7089
7090 /* LF register about to be modified requires sync. busy check. */
7091 syncReg(CMU_SYNCBUSY_LFBPRESC0);
7092
7093 /* Convert to the correct scale. */
7094 div = CMU_DivToLog2(div);
7095
7096 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK)
7097 | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT);
7098 break;
7099 #endif
7100
7101 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)
7102 case cmuClock_LEUART1:
7103 EFM_ASSERT(div <= cmuClkDiv_8);
7104
7105 /* LF register about to be modified requires sync. busy check. */
7106 syncReg(CMU_SYNCBUSY_LFBPRESC0);
7107
7108 /* Convert to the correct scale. */
7109 div = CMU_DivToLog2(div);
7110
7111 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK)
7112 | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT);
7113 break;
7114 #endif
7115
7116 default:
7117 EFM_ASSERT(false);
7118 break;
7119 }
7120 break;
7121
7122 default:
7123 EFM_ASSERT(false);
7124 break;
7125 }
7126 #endif
7127 }
7128
7129 /***************************************************************************//**
7130 * @brief
7131 * Enable/disable a clock.
7132 *
7133 * @details
7134 * In general, module clocking is disabled after a reset. If a module
7135 * clock is disabled, the registers of that module are not accessible and
7136 * reading from such registers may return undefined values. Writing to
7137 * registers of clock-disabled modules has no effect.
7138 * Avoid accessing module registers of a module with a disabled clock.
7139 *
7140 * @note
7141 * If enabling/disabling an LF clock, synchronization into the low-frequency
7142 * domain is required. If the same register is modified before a previous
7143 * update has completed, this function will stall until the previous
7144 * synchronization has completed. See @ref CMU_FreezeEnable() for
7145 * a suggestion on how to reduce the stalling time in some use cases.
7146 *
7147 * HFCLKLE prescaler is automatically modified when peripherals with clock
7148 * domain HFBUSCLK is chosen based on the maximum HFLE frequency allowed.
7149 *
7150 * @param[in] clock
7151 * The clock to enable/disable. Notice that not all defined clock
7152 * points have separate enable/disable control. See the CMU overview
7153 * in the reference manual.
7154 *
7155 * @param[in] enable
7156 * @li true - enable specified clock.
7157 * @li false - disable specified clock.
7158 ******************************************************************************/
CMU_ClockEnable(CMU_Clock_TypeDef clock,bool enable)7159 void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
7160 {
7161 volatile uint32_t *reg;
7162 uint32_t bit;
7163 uint32_t sync = 0;
7164
7165 /* Identify enable register */
7166 switch (((unsigned)clock >> CMU_EN_REG_POS) & CMU_EN_REG_MASK) {
7167 #if defined(_CMU_CTRL_HFPERCLKEN_MASK)
7168 case CMU_CTRL_EN_REG:
7169 reg = &CMU->CTRL;
7170 break;
7171 #endif
7172
7173 #if defined(_CMU_HFCORECLKEN0_MASK)
7174 case CMU_HFCORECLKEN0_EN_REG:
7175 reg = &CMU->HFCORECLKEN0;
7176 #if defined(CMU_MAX_FREQ_HFLE)
7177 setHfLeConfig(SystemCoreClockGet());
7178 #endif
7179 break;
7180 #endif
7181
7182 #if defined(_CMU_HFBUSCLKEN0_MASK)
7183 case CMU_HFBUSCLKEN0_EN_REG:
7184 reg = &CMU->HFBUSCLKEN0;
7185 break;
7186 #endif
7187
7188 #if defined(_CMU_HFPERCLKDIV_MASK)
7189 case CMU_HFPERCLKDIV_EN_REG:
7190 reg = &CMU->HFPERCLKDIV;
7191 break;
7192 #endif
7193
7194 case CMU_HFPERCLKEN0_EN_REG:
7195 reg = &CMU->HFPERCLKEN0;
7196 break;
7197
7198 #if defined(_CMU_HFPERCLKEN1_MASK)
7199 case CMU_HFPERCLKEN1_EN_REG:
7200 reg = &CMU->HFPERCLKEN1;
7201 break;
7202 #endif
7203
7204 case CMU_LFACLKEN0_EN_REG:
7205 reg = &CMU->LFACLKEN0;
7206 sync = CMU_SYNCBUSY_LFACLKEN0;
7207 break;
7208
7209 case CMU_LFBCLKEN0_EN_REG:
7210 reg = &CMU->LFBCLKEN0;
7211 sync = CMU_SYNCBUSY_LFBCLKEN0;
7212 break;
7213
7214 #if defined(_CMU_LFCCLKEN0_MASK)
7215 case CMU_LFCCLKEN0_EN_REG:
7216 reg = &CMU->LFCCLKEN0;
7217 sync = CMU_SYNCBUSY_LFCCLKEN0;
7218 break;
7219 #endif
7220
7221 #if defined(_CMU_LFECLKEN0_MASK)
7222 case CMU_LFECLKEN0_EN_REG:
7223 reg = &CMU->LFECLKEN0;
7224 sync = CMU_SYNCBUSY_LFECLKEN0;
7225 break;
7226 #endif
7227
7228 #if defined(_CMU_SDIOCTRL_MASK)
7229 case CMU_SDIOREF_EN_REG:
7230 reg = &CMU->SDIOCTRL;
7231 enable = !enable;
7232 break;
7233 #endif
7234
7235 #if defined(_CMU_QSPICTRL_MASK)
7236 case CMU_QSPI0REF_EN_REG:
7237 reg = &CMU->QSPICTRL;
7238 enable = !enable;
7239 break;
7240 #endif
7241 #if defined(_CMU_USBCTRL_MASK)
7242 case CMU_USBRCLK_EN_REG:
7243 reg = &CMU->USBCTRL;
7244 break;
7245 #endif
7246 #if defined(_CMU_PDMCTRL_MASK)
7247 case CMU_PDMREF_EN_REG:
7248 reg = &CMU->PDMCTRL;
7249 break;
7250 #endif
7251
7252 case CMU_PCNT_EN_REG:
7253 reg = &CMU->PCNTCTRL;
7254 break;
7255
7256 default: /* Cannot enable/disable a clock point. */
7257 EFM_ASSERT(false);
7258 return;
7259 }
7260
7261 /* Get the bit position used to enable/disable. */
7262 bit = ((unsigned)clock >> CMU_EN_BIT_POS) & CMU_EN_BIT_MASK;
7263
7264 /* LF synchronization required. */
7265 if (sync > 0UL) {
7266 syncReg(sync);
7267 }
7268
7269 /* Set/clear bit as requested. */
7270 BUS_RegBitWrite(reg, bit, (uint32_t)enable);
7271 }
7272
7273 /***************************************************************************//**
7274 * @brief
7275 * Get the clock frequency for a clock point.
7276 *
7277 * @param[in] clock
7278 * A clock point to fetch the frequency for.
7279 *
7280 * @return
7281 * The current frequency in Hz.
7282 ******************************************************************************/
CMU_ClockFreqGet(CMU_Clock_TypeDef clock)7283 uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
7284 {
7285 uint32_t ret;
7286
7287 switch ((unsigned)clock & (CMU_CLK_BRANCH_MASK << CMU_CLK_BRANCH_POS)) {
7288 case (CMU_HF_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7289 ret = SystemHFClockGet();
7290 break;
7291
7292 case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7293 ret = SystemHFClockGet();
7294 /* Calculate frequency after HFPER divider. */
7295 #if defined(_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)
7296 ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)
7297 >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT;
7298 #endif
7299 #if defined(_CMU_HFPERPRESC_PRESC_MASK)
7300 ret /= 1U + ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK)
7301 >> _CMU_HFPERPRESC_PRESC_SHIFT);
7302 #endif
7303 break;
7304
7305 #if defined(_CMU_HFPERPRESCB_MASK)
7306 case (CMU_HFPERB_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7307 ret = SystemHFClockGet();
7308 /* Calculate frequency after HFPERB prescaler. */
7309 ret /= 1U + ((CMU->HFPERPRESCB & _CMU_HFPERPRESCB_PRESC_MASK)
7310 >> _CMU_HFPERPRESCB_PRESC_SHIFT);
7311 break;
7312 #endif
7313
7314 #if defined(_CMU_HFPERPRESCC_MASK)
7315 case (CMU_HFPERC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7316 ret = SystemHFClockGet();
7317 /* Calculate frequency after HFPERC prescaler. */
7318 ret /= 1U + ((CMU->HFPERPRESCC & _CMU_HFPERPRESCC_PRESC_MASK)
7319 >> _CMU_HFPERPRESCC_PRESC_SHIFT);
7320 break;
7321 #endif
7322
7323 #if defined(_SILICON_LABS_32B_SERIES_1)
7324 #if defined(CRYPTO_PRESENT) \
7325 || defined(LDMA_PRESENT) \
7326 || defined(GPCRC_PRESENT) \
7327 || defined(PRS_PRESENT) \
7328 || defined(GPIO_PRESENT)
7329 case (CMU_HFBUS_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7330 ret = SystemHFClockGet();
7331 #if defined(_CMU_HFBUSPRESC_MASK)
7332 ret /= 1U + ((CMU->HFBUSPRESC & _CMU_HFBUSPRESC_MASK)
7333 >> _CMU_HFBUSPRESC_PRESC_SHIFT);
7334 #endif
7335 break;
7336 #endif
7337
7338 case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7339 ret = SystemHFClockGet();
7340 ret /= 1U + ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK)
7341 >> _CMU_HFCOREPRESC_PRESC_SHIFT);
7342 break;
7343
7344 case (CMU_HFEXP_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7345 ret = SystemHFClockGet();
7346 ret /= 1U + ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK)
7347 >> _CMU_HFEXPPRESC_PRESC_SHIFT);
7348 break;
7349 #endif
7350
7351 #if defined(_SILICON_LABS_32B_SERIES_0)
7352 #if defined(AES_PRESENT) \
7353 || defined(DMA_PRESENT) \
7354 || defined(EBI_PRESENT) \
7355 || defined(USB_PRESENT)
7356 case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7357 {
7358 ret = SystemCoreClockGet();
7359 } break;
7360 #endif
7361 #endif
7362
7363 case (CMU_LFA_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7364 ret = lfClkGet(cmuClock_LFA);
7365 break;
7366
7367 #if defined(_CMU_LFACLKEN0_RTC_MASK)
7368 case (CMU_RTC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7369 ret = lfClkGet(cmuClock_LFA);
7370 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)
7371 >> _CMU_LFAPRESC0_RTC_SHIFT;
7372 break;
7373 #endif
7374
7375 #if defined(_CMU_LFECLKEN0_RTCC_MASK)
7376 case (CMU_RTCC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7377 ret = lfClkGet(cmuClock_LFE);
7378 ret >>= (CMU->LFEPRESC0 & _CMU_LFEPRESC0_RTCC_MASK)
7379 >> _CMU_LFEPRESC0_RTCC_SHIFT;
7380 break;
7381 #endif
7382
7383 #if defined(_CMU_LFACLKEN0_LETIMER0_MASK)
7384 case (CMU_LETIMER0_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7385 ret = lfClkGet(cmuClock_LFA);
7386 #if defined(_SILICON_LABS_32B_SERIES_0)
7387 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)
7388 >> _CMU_LFAPRESC0_LETIMER0_SHIFT;
7389 #else
7390 ret /= SL_Log2ToDiv((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)
7391 >> _CMU_LFAPRESC0_LETIMER0_SHIFT);
7392 #endif
7393 break;
7394 #endif
7395
7396 #if defined(_CMU_LFACLKEN0_LETIMER1_MASK)
7397 case (CMU_LETIMER1_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7398 ret = lfClkGet(cmuClock_LFA);
7399 #if defined(_SILICON_LABS_32B_SERIES_0)
7400 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER1_MASK)
7401 >> _CMU_LFAPRESC0_LETIMER1_SHIFT;
7402 #else
7403 ret /= SL_Log2ToDiv((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER1_MASK)
7404 >> _CMU_LFAPRESC0_LETIMER1_SHIFT);
7405 #endif
7406 break;
7407 #endif
7408
7409 #if defined(_CMU_LFACLKEN0_LCD_MASK)
7410 case (CMU_LCDPRE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7411 ret = lfClkGet(cmuClock_LFA);
7412 #if defined(_SILICON_LABS_32B_SERIES_0)
7413 ret >>= ((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)
7414 >> _CMU_LFAPRESC0_LCD_SHIFT)
7415 + CMU_DivToLog2(cmuClkDiv_16);
7416 #else
7417 ret /= SL_Log2ToDiv((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)
7418 >> _CMU_LFAPRESC0_LCD_SHIFT);
7419 #endif
7420 break;
7421
7422 #if defined(_CMU_LCDCTRL_MASK)
7423 case (CMU_LCD_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7424 ret = lfClkGet(cmuClock_LFA);
7425 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)
7426 >> _CMU_LFAPRESC0_LCD_SHIFT;
7427 ret /= 1U + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK)
7428 >> _CMU_LCDCTRL_FDIV_SHIFT);
7429 break;
7430 #endif
7431 #endif
7432
7433 #if defined(_CMU_LFACLKEN0_LESENSE_MASK)
7434 case (CMU_LESENSE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7435 ret = lfClkGet(cmuClock_LFA);
7436 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)
7437 >> _CMU_LFAPRESC0_LESENSE_SHIFT;
7438 break;
7439 #endif
7440
7441 case (CMU_LFB_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7442 ret = lfClkGet(cmuClock_LFB);
7443 break;
7444
7445 #if defined(_CMU_LFBCLKEN0_LEUART0_MASK)
7446 case (CMU_LEUART0_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7447 ret = lfClkGet(cmuClock_LFB);
7448 #if defined(_SILICON_LABS_32B_SERIES_0)
7449 ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)
7450 >> _CMU_LFBPRESC0_LEUART0_SHIFT;
7451 #else
7452 ret /= SL_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)
7453 >> _CMU_LFBPRESC0_LEUART0_SHIFT);
7454 #endif
7455 break;
7456 #endif
7457
7458 #if defined(_CMU_LFBCLKEN0_LEUART1_MASK)
7459 case (CMU_LEUART1_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7460 ret = lfClkGet(cmuClock_LFB);
7461 #if defined(_SILICON_LABS_32B_SERIES_0)
7462 ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)
7463 >> _CMU_LFBPRESC0_LEUART1_SHIFT;
7464 #else
7465 ret /= SL_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)
7466 >> _CMU_LFBPRESC0_LEUART1_SHIFT);
7467 #endif
7468 break;
7469 #endif
7470
7471 #if defined(_CMU_LFBCLKEN0_CSEN_MASK)
7472 case (CMU_CSEN_LF_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7473 ret = lfClkGet(cmuClock_LFB);
7474 ret /= SL_Log2ToDiv(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_CSEN_MASK)
7475 >> _CMU_LFBPRESC0_CSEN_SHIFT) + 4UL);
7476 break;
7477 #endif
7478
7479 #if defined(CMU_LFCCLKEN0_USB)
7480 case (CMU_USBLE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7481 ret = lfClkGet(cmuClock_LFC);
7482 break;
7483 #endif
7484
7485 #if defined(_SILICON_LABS_32B_SERIES_1)
7486 case (CMU_LFE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7487 ret = lfClkGet(cmuClock_LFE);
7488 break;
7489 #endif
7490
7491 case (CMU_DBG_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7492 ret = dbgClkGet();
7493 break;
7494
7495 case (CMU_AUX_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7496 ret = auxClkGet();
7497 break;
7498
7499 #if defined(USBC_CLOCK_PRESENT)
7500 case (CMU_USBC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7501 ret = usbCClkGet();
7502 break;
7503 #endif
7504
7505 #if defined(_CMU_ADCCTRL_ADC0CLKSEL_MASK)
7506 case (CMU_ADC0ASYNC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7507 ret = adcAsyncClkGet(0);
7508 #if defined(_CMU_ADCCTRL_ADC0CLKDIV_MASK)
7509 ret /= 1U + ((CMU->ADCCTRL & _CMU_ADCCTRL_ADC0CLKDIV_MASK)
7510 >> _CMU_ADCCTRL_ADC0CLKDIV_SHIFT);
7511 #endif
7512 break;
7513 #endif
7514
7515 #if defined(_CMU_ADCCTRL_ADC1CLKSEL_MASK)
7516 case (CMU_ADC1ASYNC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7517 ret = adcAsyncClkGet(1);
7518 #if defined(_CMU_ADCCTRL_ADC1CLKDIV_MASK)
7519 ret /= 1U + ((CMU->ADCCTRL & _CMU_ADCCTRL_ADC1CLKDIV_MASK)
7520 >> _CMU_ADCCTRL_ADC1CLKDIV_SHIFT);
7521 #endif
7522 break;
7523 #endif
7524
7525 #if defined(_CMU_SDIOCTRL_SDIOCLKSEL_MASK)
7526 case (CMU_SDIOREF_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7527 ret = sdioRefClkGet();
7528 break;
7529 #endif
7530
7531 #if defined(_CMU_QSPICTRL_QSPI0CLKSEL_MASK)
7532 case (CMU_QSPI0REF_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7533 ret = qspiRefClkGet(0);
7534 break;
7535 #endif
7536
7537 #if defined(USBR_CLOCK_PRESENT)
7538 case (CMU_USBR_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7539 ret = usbRateClkGet();
7540 break;
7541 #endif
7542
7543 #if defined(_CMU_PDMCTRL_PDMCLKSEL_MASK)
7544 case (CMU_PDMREF_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7545 ret = pdmRefClkGet();
7546 break;
7547 #endif
7548
7549 case (CMU_HFLE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
7550 #if defined(_CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK)
7551 ret = SystemCoreClockGet() / CMU_ClockDivGet(clock);
7552 #elif defined(_CMU_HFPRESC_HFCLKLEPRESC_MASK)
7553 ret = SystemHFClockGet() / CMU_ClockDivGet(clock);
7554 #else
7555 ret = SystemCoreClockGet() / 2;
7556 #endif
7557 break;
7558
7559 default:
7560 ret = 0;
7561 EFM_ASSERT(false);
7562 break;
7563 }
7564
7565 return ret;
7566 }
7567
7568 #if defined(_SILICON_LABS_32B_SERIES_1)
7569 /***************************************************************************//**
7570 * @brief
7571 * Get the clock prescaler.
7572 *
7573 * @param[in] clock
7574 * A clock point to get the prescaler for. Notice that not all clock points
7575 * have a prescaler. See the CMU overview in the reference manual.
7576 *
7577 * @return
7578 * The prescaler value of the current clock point. 0 is returned
7579 * if @p clock specifies a clock point without a prescaler.
7580 ******************************************************************************/
CMU_ClockPrescGet(CMU_Clock_TypeDef clock)7581 uint32_t CMU_ClockPrescGet(CMU_Clock_TypeDef clock)
7582 {
7583 uint32_t prescReg;
7584 uint32_t ret;
7585
7586 /* Get the prescaler register ID. */
7587 prescReg = ((unsigned)clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK;
7588
7589 switch (prescReg) {
7590 case CMU_HFPRESC_REG:
7591 ret = (CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)
7592 >> _CMU_HFPRESC_PRESC_SHIFT;
7593 break;
7594
7595 case CMU_HFEXPPRESC_REG:
7596 ret = (CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK)
7597 >> _CMU_HFEXPPRESC_PRESC_SHIFT;
7598 break;
7599
7600 case CMU_HFCLKLEPRESC_REG:
7601 ret = (CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)
7602 >> _CMU_HFPRESC_HFCLKLEPRESC_SHIFT;
7603 ret = SL_Log2ToDiv(ret + 1U) - 1U;
7604 break;
7605
7606 case CMU_HFPERPRESC_REG:
7607 ret = (CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK)
7608 >> _CMU_HFPERPRESC_PRESC_SHIFT;
7609 break;
7610
7611 #if defined(_CMU_HFPERPRESCB_MASK)
7612 case CMU_HFPERPRESCB_REG:
7613 ret = (CMU->HFPERPRESCB & _CMU_HFPERPRESCB_PRESC_MASK)
7614 >> _CMU_HFPERPRESCB_PRESC_SHIFT;
7615 break;
7616 #endif
7617
7618 #if defined(_CMU_HFPERPRESCC_MASK)
7619 case CMU_HFPERPRESCC_REG:
7620 ret = (CMU->HFPERPRESCC & _CMU_HFPERPRESCC_PRESC_MASK)
7621 >> _CMU_HFPERPRESCC_PRESC_SHIFT;
7622 break;
7623 #endif
7624
7625 case CMU_HFCOREPRESC_REG:
7626 ret = (CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK)
7627 >> _CMU_HFCOREPRESC_PRESC_SHIFT;
7628 break;
7629
7630 case CMU_LFAPRESC0_REG:
7631 switch (clock) {
7632 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
7633 case cmuClock_LETIMER0:
7634 ret = (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)
7635 >> _CMU_LFAPRESC0_LETIMER0_SHIFT;
7636 /* Convert the exponent to a prescaler value. */
7637 ret = SL_Log2ToDiv(ret) - 1U;
7638 break;
7639 #endif
7640
7641 #if defined(_CMU_LFAPRESC0_LESENSE_MASK)
7642 case cmuClock_LESENSE:
7643 ret = (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)
7644 >> _CMU_LFAPRESC0_LESENSE_SHIFT;
7645 /* Convert the exponent to a prescaler value. */
7646 ret = SL_Log2ToDiv(ret) - 1U;
7647 break;
7648 #endif
7649
7650 #if defined(_CMU_LFAPRESC0_LETIMER1_MASK)
7651 case cmuClock_LETIMER1:
7652 ret = (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER1_MASK)
7653 >> _CMU_LFAPRESC0_LETIMER1_SHIFT;
7654 ret = SL_Log2ToDiv(ret) - 1U;
7655 break;
7656 #endif
7657
7658 #if defined(_CMU_LFAPRESC0_LCD_MASK)
7659 case cmuClock_LCD:
7660 case cmuClock_LCDpre:
7661 ret = (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)
7662 >> _CMU_LFAPRESC0_LCD_SHIFT;
7663 ret = SL_Log2ToDiv(ret) - 1U;
7664 break;
7665 #endif
7666
7667 #if defined(_CMU_LFAPRESC0_RTC_MASK)
7668 case cmuClock_RTC:
7669 ret = (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)
7670 >> _CMU_LFAPRESC0_RTC_SHIFT;
7671 ret = SL_Log2ToDiv(ret) - 1U;
7672 break;
7673 #endif
7674
7675 default:
7676 ret = 0U;
7677 EFM_ASSERT(false);
7678 break;
7679 }
7680 break;
7681
7682 case CMU_LFBPRESC0_REG:
7683 switch (clock) {
7684 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)
7685 case cmuClock_LEUART0:
7686 ret = (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)
7687 >> _CMU_LFBPRESC0_LEUART0_SHIFT;
7688 /* Convert the exponent to a prescaler value. */
7689 ret = SL_Log2ToDiv(ret) - 1U;
7690 break;
7691 #endif
7692
7693 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)
7694 case cmuClock_LEUART1:
7695 ret = (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)
7696 >> _CMU_LFBPRESC0_LEUART1_SHIFT;
7697 /* Convert the exponent to a prescaler value. */
7698 ret = SL_Log2ToDiv(ret) - 1U;
7699 break;
7700 #endif
7701
7702 #if defined(_CMU_LFBPRESC0_CSEN_MASK)
7703 case cmuClock_CSEN_LF:
7704 ret = (CMU->LFBPRESC0 & _CMU_LFBPRESC0_CSEN_MASK)
7705 >> _CMU_LFBPRESC0_CSEN_SHIFT;
7706 /* Convert the exponent to a prescaler value. */
7707 ret = SL_Log2ToDiv(ret + 4U) - 1U;
7708 break;
7709 #endif
7710
7711 default:
7712 ret = 0U;
7713 EFM_ASSERT(false);
7714 break;
7715 }
7716 break;
7717
7718 case CMU_LFEPRESC0_REG:
7719 switch (clock) {
7720 #if defined(RTCC_PRESENT)
7721 case cmuClock_RTCC:
7722 ret = (CMU->LFEPRESC0 & _CMU_LFEPRESC0_RTCC_MASK)
7723 >> _CMU_LFEPRESC0_RTCC_SHIFT;
7724 break;
7725
7726 default:
7727 ret = 0U;
7728 EFM_ASSERT(false);
7729 break;
7730 #endif
7731 }
7732 break;
7733
7734 #if defined(_CMU_ADCCTRL_ADC0CLKDIV_MASK) \
7735 || defined(_CMU_ADCCTRL_ADC1CLKDIV_MASK)
7736 case CMU_ADCASYNCDIV_REG:
7737 switch (clock) {
7738 #if defined(_CMU_ADCCTRL_ADC0CLKDIV_MASK)
7739 case cmuClock_ADC0ASYNC:
7740 ret = (CMU->ADCCTRL & _CMU_ADCCTRL_ADC0CLKDIV_MASK)
7741 >> _CMU_ADCCTRL_ADC0CLKDIV_SHIFT;
7742 break;
7743 #endif
7744 #if defined(_CMU_ADCCTRL_ADC1CLKDIV_MASK)
7745 case cmuClock_ADC1ASYNC:
7746 ret = (CMU->ADCCTRL & _CMU_ADCCTRL_ADC1CLKDIV_MASK)
7747 >> _CMU_ADCCTRL_ADC1CLKDIV_SHIFT;
7748 break;
7749 #endif
7750 default:
7751 ret = 0U;
7752 EFM_ASSERT(false);
7753 break;
7754 }
7755 break;
7756 #endif
7757 #if defined(_CMU_HFBUSPRESC_MASK)
7758 case CMU_HFBUSPRESC_REG:
7759 ret = (CMU->HFBUSPRESC & _CMU_HFBUSPRESC_MASK)
7760 >> _CMU_HFBUSPRESC_PRESC_SHIFT;
7761 break;
7762 #endif
7763 default:
7764 ret = 0U;
7765 EFM_ASSERT(false);
7766 break;
7767 }
7768
7769 return ret;
7770 }
7771 #endif
7772
7773 #if defined(_SILICON_LABS_32B_SERIES_1)
7774 /***************************************************************************//**
7775 * @brief
7776 * Set the clock prescaler.
7777 *
7778 * @note
7779 * If setting an LF clock prescaler, synchronization into the low-frequency
7780 * domain is required. If the same register is modified before a previous
7781 * update has completed, this function will stall until the previous
7782 * synchronization has completed. See @ref CMU_FreezeEnable() for
7783 * a suggestion on how to reduce the stalling time in some use cases.
7784 *
7785 * HFCLKLE prescaler is automatically modified when peripherals with clock
7786 * domain HFBUSCLK is chosen based on the maximum HFLE frequency allowed.
7787 *
7788 * @param[in] clock
7789 * A clock point to set the prescaler for. Notice that not all clock points
7790 * have a prescaler. See the CMU overview in the reference manual.
7791 *
7792 * @param[in] presc
7793 * The clock prescaler. The prescaler value is linked to the clock divider by:
7794 * divider = 'presc' + 1.
7795 ******************************************************************************/
CMU_ClockPrescSet(CMU_Clock_TypeDef clock,CMU_ClkPresc_TypeDef presc)7796 void CMU_ClockPrescSet(CMU_Clock_TypeDef clock, CMU_ClkPresc_TypeDef presc)
7797 {
7798 uint32_t freq;
7799 uint32_t prescReg;
7800
7801 /* Get the divisor reg ID. */
7802 prescReg = ((unsigned)clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK;
7803
7804 switch (prescReg) {
7805 case CMU_HFPRESC_REG:
7806 EFM_ASSERT(presc < 32U);
7807
7808 /* Configure worst case wait-states for flash and HFLE, set safe HFPER
7809 clock-tree prescalers. */
7810 flashWaitStateMax();
7811 setHfLeConfig(CMU_MAX_FREQ_HFLE + 1UL);
7812 hfperClkSafePrescaler();
7813
7814 CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_PRESC_MASK)
7815 | (presc << _CMU_HFPRESC_PRESC_SHIFT);
7816
7817 /* Update the CMSIS core clock variable (this function updates the global
7818 variable). */
7819 freq = SystemCoreClockGet();
7820 /* Optimize flash and HFLE wait states and set optimized HFPER clock-tree
7821 prescalers. */
7822 CMU_UpdateWaitStates(freq, VSCALE_DEFAULT);
7823 setHfLeConfig(SystemHFClockGet());
7824 hfperClkOptimizedPrescaler();
7825 break;
7826
7827 case CMU_HFEXPPRESC_REG:
7828 EFM_ASSERT(presc < 32U);
7829
7830 CMU->HFEXPPRESC = (CMU->HFEXPPRESC & ~_CMU_HFEXPPRESC_PRESC_MASK)
7831 | (presc << _CMU_HFEXPPRESC_PRESC_SHIFT);
7832 break;
7833
7834 case CMU_HFCLKLEPRESC_REG:
7835 presc = CMU_DivToLog2(presc);
7836 CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_HFCLKLEPRESC_MASK)
7837 | (presc << _CMU_HFPRESC_HFCLKLEPRESC_SHIFT);
7838 break;
7839
7840 case CMU_HFPERPRESC_REG:
7841 EFM_ASSERT(presc < 512U);
7842 CMU->HFPERPRESC = (CMU->HFPERPRESC & ~_CMU_HFPERPRESC_PRESC_MASK)
7843 | (presc << _CMU_HFPERPRESC_PRESC_SHIFT);
7844 break;
7845
7846 #if defined(_CMU_HFPERPRESCB_MASK)
7847 case CMU_HFPERPRESCB_REG:
7848 EFM_ASSERT(presc < 512U);
7849 CMU->HFPERPRESCB = (CMU->HFPERPRESCB & ~_CMU_HFPERPRESCB_PRESC_MASK)
7850 | (presc << _CMU_HFPERPRESCB_PRESC_SHIFT);
7851 break;
7852 #endif
7853
7854 #if defined(_CMU_HFPERPRESCC_MASK)
7855 case CMU_HFPERPRESCC_REG:
7856 EFM_ASSERT(presc < 512U);
7857 CMU->HFPERPRESCC = (CMU->HFPERPRESCC & ~_CMU_HFPERPRESCC_PRESC_MASK)
7858 | (presc << _CMU_HFPERPRESCC_PRESC_SHIFT);
7859 break;
7860 #endif
7861
7862 case CMU_HFCOREPRESC_REG:
7863 EFM_ASSERT(presc < 512U);
7864
7865 /* Configure worst case wait-states for flash. */
7866 flashWaitStateMax();
7867
7868 CMU->HFCOREPRESC = (CMU->HFCOREPRESC & ~_CMU_HFCOREPRESC_PRESC_MASK)
7869 | (presc << _CMU_HFCOREPRESC_PRESC_SHIFT);
7870
7871 /* Update the CMSIS core clock variable (this function updates the global variable).
7872 Optimize flash and HFLE wait states. */
7873 freq = SystemCoreClockGet();
7874 CMU_UpdateWaitStates(freq, VSCALE_DEFAULT);
7875 break;
7876
7877 case CMU_LFAPRESC0_REG:
7878 switch (clock) {
7879 #if defined(RTC_PRESENT)
7880 case cmuClock_RTC:
7881 EFM_ASSERT(presc <= 32768U);
7882
7883 /* Convert the prescaler value to a DIV exponent scale. */
7884 presc = CMU_PrescToLog2(presc);
7885
7886 /* LF register about to be modified requires sync. Busy check. */
7887 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7888
7889 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK)
7890 | (presc << _CMU_LFAPRESC0_RTC_SHIFT);
7891 break;
7892 #endif
7893
7894 #if defined(RTCC_PRESENT)
7895 case cmuClock_RTCC:
7896 #if defined(_CMU_LFEPRESC0_RTCC_MASK)
7897 #if defined(_CMU_LFEPRESC0_RTCC_DIV4)
7898 EFM_ASSERT(presc <= _CMU_LFEPRESC0_RTCC_DIV4);
7899 #elif defined(_CMU_LFEPRESC0_RTCC_DIV2)
7900 EFM_ASSERT(presc <= _CMU_LFEPRESC0_RTCC_DIV2);
7901 #else
7902 EFM_ASSERT(presc <= 0U);
7903 #endif
7904
7905 /* LF register about to be modified requires sync. Busy check. */
7906 syncReg(CMU_SYNCBUSY_LFEPRESC0);
7907
7908 CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK)
7909 | (presc << _CMU_LFEPRESC0_RTCC_SHIFT);
7910 #else
7911 EFM_ASSERT(presc <= 32768U);
7912
7913 /* Convert the prescaler value to a DIV exponent scale. */
7914 presc = CMU_PrescToLog2(presc);
7915
7916 /* LF register about to be modified requires sync. Busy check. */
7917 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7918
7919 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTCC_MASK)
7920 | (presc << _CMU_LFAPRESC0_RTCC_SHIFT);
7921 #endif
7922 break;
7923 #endif
7924
7925 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
7926 case cmuClock_LETIMER0:
7927 EFM_ASSERT(presc <= 32768U);
7928
7929 /* Convert the prescaler value to a DIV exponent scale. */
7930 presc = CMU_PrescToLog2(presc);
7931
7932 /* LF register about to be modified requires sync. Busy check. */
7933 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7934
7935 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK)
7936 | (presc << _CMU_LFAPRESC0_LETIMER0_SHIFT);
7937 break;
7938 #endif
7939
7940 #if defined(_CMU_LFAPRESC0_LETIMER1_MASK)
7941 case cmuClock_LETIMER1:
7942 EFM_ASSERT(presc <= 32768U);
7943
7944 /* Convert the prescaler value to a DIV exponent scale. */
7945 presc = CMU_PrescToLog2(presc);
7946
7947 /* LF register about to be modified requires sync. Busy check. */
7948 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7949
7950 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER1_MASK)
7951 | (presc << _CMU_LFAPRESC0_LETIMER1_SHIFT);
7952 break;
7953 #endif
7954
7955 #if defined(_CMU_LFAPRESC0_LESENSE_MASK)
7956 case cmuClock_LESENSE:
7957 EFM_ASSERT(presc <= 8U);
7958
7959 /* Convert the prescaler value to a DIV exponent scale. */
7960 presc = CMU_PrescToLog2(presc);
7961
7962 /* LF register about to be modified requires sync. Busy check. */
7963 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7964
7965 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK)
7966 | (presc << _CMU_LFAPRESC0_LESENSE_SHIFT);
7967 break;
7968 #endif
7969
7970 #if defined(_CMU_LFAPRESC0_LCD_MASK)
7971 case cmuClock_LCDpre:
7972 case cmuClock_LCD:
7973 EFM_ASSERT(presc <= 32768U);
7974
7975 /* Convert the prescaler value to a DIV exponent scale. */
7976 presc = CMU_PrescToLog2(presc);
7977
7978 /* LF register about to be modified requires sync. Busy check. */
7979 syncReg(CMU_SYNCBUSY_LFAPRESC0);
7980
7981 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK)
7982 | (presc << _CMU_LFAPRESC0_LCD_SHIFT);
7983 break;
7984 #endif
7985
7986 default:
7987 EFM_ASSERT(false);
7988 break;
7989 }
7990 break;
7991
7992 case CMU_LFBPRESC0_REG:
7993 switch (clock) {
7994 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)
7995 case cmuClock_LEUART0:
7996 EFM_ASSERT(presc <= 8U);
7997
7998 /* Convert the prescaler value to a DIV exponent scale. */
7999 presc = CMU_PrescToLog2(presc);
8000
8001 /* LF register about to be modified requires sync. Busy check. */
8002 syncReg(CMU_SYNCBUSY_LFBPRESC0);
8003
8004 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK)
8005 | (presc << _CMU_LFBPRESC0_LEUART0_SHIFT);
8006 break;
8007 #endif
8008
8009 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)
8010 case cmuClock_LEUART1:
8011 EFM_ASSERT(presc <= 8U);
8012
8013 /* Convert the prescaler value to a DIV exponent scale. */
8014 presc = CMU_PrescToLog2(presc);
8015
8016 /* LF register about to be modified requires sync. Busy check. */
8017 syncReg(CMU_SYNCBUSY_LFBPRESC0);
8018
8019 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK)
8020 | (presc << _CMU_LFBPRESC0_LEUART1_SHIFT);
8021 break;
8022 #endif
8023
8024 #if defined(_CMU_LFBPRESC0_CSEN_MASK)
8025 case cmuClock_CSEN_LF:
8026 EFM_ASSERT((presc <= 127U) && (presc >= 15U));
8027
8028 /* Convert the prescaler value to a DIV exponent scale.
8029 * DIV16 is the lowest supported prescaler. */
8030 presc = CMU_PrescToLog2(presc) - 4U;
8031
8032 /* LF register about to be modified requires sync. Busy check. */
8033 syncReg(CMU_SYNCBUSY_LFBPRESC0);
8034
8035 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_CSEN_MASK)
8036 | (presc << _CMU_LFBPRESC0_CSEN_SHIFT);
8037 break;
8038 #endif
8039
8040 default:
8041 EFM_ASSERT(false);
8042 break;
8043 }
8044 break;
8045
8046 case CMU_LFEPRESC0_REG:
8047 switch (clock) {
8048 #if defined(_CMU_LFEPRESC0_RTCC_MASK)
8049 case cmuClock_RTCC:
8050 #if defined(_CMU_LFEPRESC0_RTCC_DIV4)
8051 EFM_ASSERT(presc <= _CMU_LFEPRESC0_RTCC_DIV4);
8052 #elif defined(_CMU_LFEPRESC0_RTCC_DIV2)
8053 EFM_ASSERT(presc <= _CMU_LFEPRESC0_RTCC_DIV2);
8054 #else
8055 EFM_ASSERT(presc <= 0U);
8056 #endif
8057
8058 /* LF register about to be modified requires sync. Busy check. */
8059 syncReg(CMU_SYNCBUSY_LFEPRESC0);
8060
8061 CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK)
8062 | (presc << _CMU_LFEPRESC0_RTCC_SHIFT);
8063 break;
8064 #endif
8065
8066 default:
8067 EFM_ASSERT(false);
8068 break;
8069 }
8070 break;
8071
8072 #if defined(_CMU_ADCCTRL_ADC0CLKDIV_MASK) \
8073 || defined(_CMU_ADCCTRL_ADC1CLKDIV_MASK)
8074 case CMU_ADCASYNCDIV_REG:
8075 switch (clock) {
8076 #if defined(_CMU_ADCCTRL_ADC0CLKDIV_MASK)
8077 case cmuClock_ADC0ASYNC:
8078 EFM_ASSERT(presc <= 3);
8079 CMU->ADCCTRL = (CMU->ADCCTRL & ~_CMU_ADCCTRL_ADC0CLKDIV_MASK)
8080 | (presc << _CMU_ADCCTRL_ADC0CLKDIV_SHIFT);
8081 break;
8082 #endif
8083
8084 #if defined(_CMU_ADCCTRL_ADC1CLKDIV_MASK)
8085 case cmuClock_ADC1ASYNC:
8086 EFM_ASSERT(presc <= 3);
8087 CMU->ADCCTRL = (CMU->ADCCTRL & ~_CMU_ADCCTRL_ADC1CLKDIV_MASK)
8088 | (presc << _CMU_ADCCTRL_ADC1CLKDIV_SHIFT);
8089 break;
8090 #endif
8091 default:
8092 EFM_ASSERT(false);
8093 break;
8094 }
8095 break;
8096 #endif
8097
8098 #if defined(_CMU_HFBUSPRESC_MASK)
8099 case CMU_HFBUSPRESC_REG:
8100 EFM_ASSERT(presc <= _CMU_HFBUSPRESC_MASK >> _CMU_HFBUSPRESC_PRESC_SHIFT);
8101 CMU->HFBUSPRESC = (CMU->HFBUSPRESC & ~_CMU_HFBUSPRESC_MASK)
8102 | (presc << _CMU_HFBUSPRESC_PRESC_SHIFT);
8103 break;
8104 #endif
8105
8106 default:
8107 EFM_ASSERT(false);
8108 break;
8109 }
8110 }
8111 #endif
8112
8113 /***************************************************************************//**
8114 * @brief
8115 * Get the currently selected reference clock used for a clock branch.
8116 *
8117 * @param[in] clock
8118 * Clock branch to fetch selected ref. clock for. One of:
8119 * @li #cmuClock_HF
8120 * @li #cmuClock_LFA
8121 * @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO
8122 * @li #cmuClock_LFC
8123 * @endif @if _SILICON_LABS_32B_SERIES_1
8124 * @li #cmuClock_LFE
8125 * @endif
8126 * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT
8127 * @li #cmuClock_USBC
8128 * @endif
8129 *
8130 * @return
8131 * The reference clock used for clocking the selected branch, #cmuSelect_Error if
8132 * invalid @p clock provided.
8133 ******************************************************************************/
CMU_ClockSelectGet(CMU_Clock_TypeDef clock)8134 CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock)
8135 {
8136 CMU_Select_TypeDef ret = cmuSelect_Disabled;
8137 uint32_t selReg;
8138
8139 selReg = ((unsigned)clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;
8140
8141 switch (selReg) {
8142 case CMU_HFCLKSEL_REG:
8143 #if defined(_CMU_HFCLKSTATUS_MASK)
8144 switch (CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) {
8145 case CMU_HFCLKSTATUS_SELECTED_LFXO:
8146 ret = cmuSelect_LFXO;
8147 break;
8148
8149 case CMU_HFCLKSTATUS_SELECTED_LFRCO:
8150 ret = cmuSelect_LFRCO;
8151 break;
8152
8153 case CMU_HFCLKSTATUS_SELECTED_HFXO:
8154 ret = cmuSelect_HFXO;
8155 break;
8156
8157 #if defined(CMU_HFCLKSTATUS_SELECTED_HFRCODIV2)
8158 case CMU_HFCLKSTATUS_SELECTED_HFRCODIV2:
8159 ret = cmuSelect_HFRCODIV2;
8160 break;
8161 #endif
8162
8163 #if defined(CMU_HFCLKSTATUS_SELECTED_CLKIN0)
8164 case CMU_HFCLKSTATUS_SELECTED_CLKIN0:
8165 ret = cmuSelect_CLKIN0;
8166 break;
8167 #endif
8168
8169 #if defined(CMU_HFCLKSTATUS_SELECTED_USHFRCO)
8170 case CMU_HFCLKSTATUS_SELECTED_USHFRCO:
8171 ret = cmuSelect_USHFRCO;
8172 break;
8173 #endif
8174
8175 default:
8176 ret = cmuSelect_HFRCO;
8177 break;
8178 }
8179 #else
8180 switch (CMU->STATUS
8181 & (CMU_STATUS_HFRCOSEL
8182 | CMU_STATUS_HFXOSEL
8183 | CMU_STATUS_LFRCOSEL
8184 #if defined(CMU_STATUS_USHFRCODIV2SEL)
8185 | CMU_STATUS_USHFRCODIV2SEL
8186 #endif
8187 | CMU_STATUS_LFXOSEL)) {
8188 case CMU_STATUS_LFXOSEL:
8189 ret = cmuSelect_LFXO;
8190 break;
8191
8192 case CMU_STATUS_LFRCOSEL:
8193 ret = cmuSelect_LFRCO;
8194 break;
8195
8196 case CMU_STATUS_HFXOSEL:
8197 ret = cmuSelect_HFXO;
8198 break;
8199
8200 #if defined(CMU_STATUS_USHFRCODIV2SEL)
8201 case CMU_STATUS_USHFRCODIV2SEL:
8202 ret = cmuSelect_USHFRCODIV2;
8203 break;
8204 #endif
8205
8206 default:
8207 ret = cmuSelect_HFRCO;
8208 break;
8209 }
8210 #endif
8211 break;
8212
8213 #if defined(_CMU_LFCLKSEL_MASK) || defined(_CMU_LFACLKSEL_MASK)
8214 case CMU_LFACLKSEL_REG:
8215 #if defined(_CMU_LFCLKSEL_MASK)
8216 switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK) {
8217 case CMU_LFCLKSEL_LFA_LFRCO:
8218 ret = cmuSelect_LFRCO;
8219 break;
8220
8221 case CMU_LFCLKSEL_LFA_LFXO:
8222 ret = cmuSelect_LFXO;
8223 break;
8224
8225 #if defined(CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2)
8226 case CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
8227 ret = cmuSelect_HFCLKLE;
8228 break;
8229 #endif
8230
8231 default:
8232 #if defined(CMU_LFCLKSEL_LFAE)
8233 if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK) {
8234 ret = cmuSelect_ULFRCO;
8235 break;
8236 }
8237 #else
8238 ret = cmuSelect_Disabled;
8239 #endif
8240 break;
8241 }
8242
8243 #elif defined(_CMU_LFACLKSEL_MASK)
8244 switch (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK) {
8245 case CMU_LFACLKSEL_LFA_LFRCO:
8246 ret = cmuSelect_LFRCO;
8247 break;
8248
8249 case CMU_LFACLKSEL_LFA_LFXO:
8250 ret = cmuSelect_LFXO;
8251 break;
8252
8253 case CMU_LFACLKSEL_LFA_ULFRCO:
8254 ret = cmuSelect_ULFRCO;
8255 break;
8256
8257 #if defined(PLFRCO_PRESENT)
8258 case CMU_LFACLKSEL_LFA_PLFRCO:
8259 ret = cmuSelect_PLFRCO;
8260 break;
8261 #endif
8262
8263 default:
8264 ret = cmuSelect_Disabled;
8265 break;
8266 }
8267 #endif
8268 break;
8269 #endif /* _CMU_LFCLKSEL_MASK || _CMU_LFACLKSEL_MASK */
8270
8271 #if defined(_CMU_LFCLKSEL_MASK) || defined(_CMU_LFBCLKSEL_MASK)
8272 case CMU_LFBCLKSEL_REG:
8273 #if defined(_CMU_LFCLKSEL_MASK)
8274 switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK) {
8275 case CMU_LFCLKSEL_LFB_LFRCO:
8276 ret = cmuSelect_LFRCO;
8277 break;
8278
8279 case CMU_LFCLKSEL_LFB_LFXO:
8280 ret = cmuSelect_LFXO;
8281 break;
8282
8283 #if defined(CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2)
8284 case CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2:
8285 ret = cmuSelect_HFCLKLE;
8286 break;
8287 #endif
8288
8289 #if defined(CMU_LFCLKSEL_LFB_HFCLKLE)
8290 case CMU_LFCLKSEL_LFB_HFCLKLE:
8291 ret = cmuSelect_HFCLKLE;
8292 break;
8293 #endif
8294
8295 default:
8296 #if defined(CMU_LFCLKSEL_LFBE)
8297 if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK) {
8298 ret = cmuSelect_ULFRCO;
8299 break;
8300 }
8301 #else
8302 ret = cmuSelect_Disabled;
8303 #endif
8304 break;
8305 }
8306
8307 #elif defined(_CMU_LFBCLKSEL_MASK)
8308 switch (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK) {
8309 case CMU_LFBCLKSEL_LFB_LFRCO:
8310 ret = cmuSelect_LFRCO;
8311 break;
8312
8313 case CMU_LFBCLKSEL_LFB_LFXO:
8314 ret = cmuSelect_LFXO;
8315 break;
8316
8317 case CMU_LFBCLKSEL_LFB_ULFRCO:
8318 ret = cmuSelect_ULFRCO;
8319 break;
8320
8321 case CMU_LFBCLKSEL_LFB_HFCLKLE:
8322 ret = cmuSelect_HFCLKLE;
8323 break;
8324
8325 #if defined(PLFRCO_PRESENT)
8326 case CMU_LFBCLKSEL_LFB_PLFRCO:
8327 ret = cmuSelect_PLFRCO;
8328 break;
8329 #endif
8330
8331 default:
8332 ret = cmuSelect_Disabled;
8333 break;
8334 }
8335 #endif
8336 break;
8337 #endif /* _CMU_LFCLKSEL_MASK || _CMU_LFBCLKSEL_MASK */
8338
8339 #if defined(_CMU_LFCLKSEL_LFC_MASK)
8340 case CMU_LFCCLKSEL_REG:
8341 switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK) {
8342 case CMU_LFCLKSEL_LFC_LFRCO:
8343 ret = cmuSelect_LFRCO;
8344 break;
8345
8346 case CMU_LFCLKSEL_LFC_LFXO:
8347 ret = cmuSelect_LFXO;
8348 break;
8349
8350 default:
8351 ret = cmuSelect_Disabled;
8352 break;
8353 }
8354 break;
8355 #endif
8356
8357 #if defined(_CMU_LFECLKSEL_LFE_MASK)
8358 case CMU_LFECLKSEL_REG:
8359 switch (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK) {
8360 case CMU_LFECLKSEL_LFE_LFRCO:
8361 ret = cmuSelect_LFRCO;
8362 break;
8363
8364 case CMU_LFECLKSEL_LFE_LFXO:
8365 ret = cmuSelect_LFXO;
8366 break;
8367
8368 case CMU_LFECLKSEL_LFE_ULFRCO:
8369 ret = cmuSelect_ULFRCO;
8370 break;
8371
8372 #if defined(PLFRCO_PRESENT)
8373 case CMU_LFECLKSEL_LFE_PLFRCO:
8374 ret = cmuSelect_PLFRCO;
8375 break;
8376 #endif
8377
8378 default:
8379 ret = cmuSelect_Disabled;
8380 break;
8381 }
8382 break;
8383 #endif /* CMU_LFECLKSEL_REG */
8384
8385 #if defined(_CMU_LFCCLKSEL_LFC_MASK)
8386 case CMU_LFCCLKSEL_REG:
8387 switch (CMU->LFCCLKSEL & _CMU_LFCCLKSEL_LFC_MASK) {
8388 case CMU_LFCCLKSEL_LFC_LFRCO:
8389 ret = cmuSelect_LFRCO;
8390 break;
8391
8392 case CMU_LFCCLKSEL_LFC_LFXO:
8393 ret = cmuSelect_LFXO;
8394 break;
8395
8396 case CMU_LFCCLKSEL_LFC_ULFRCO:
8397 ret = cmuSelect_ULFRCO;
8398 break;
8399
8400 default:
8401 ret = cmuSelect_Disabled;
8402 break;
8403 }
8404 break;
8405 #endif /* CMU_LFCCLKSEL_REG */
8406
8407 case CMU_DBGCLKSEL_REG:
8408 #if defined(_CMU_DBGCLKSEL_DBG_MASK)
8409 switch (CMU->DBGCLKSEL & _CMU_DBGCLKSEL_DBG_MASK) {
8410 case CMU_DBGCLKSEL_DBG_HFCLK:
8411 ret = cmuSelect_HFCLK;
8412 break;
8413
8414 case CMU_DBGCLKSEL_DBG_AUXHFRCO:
8415 ret = cmuSelect_AUXHFRCO;
8416 break;
8417
8418 default:
8419 ret = cmuSelect_Disabled;
8420 break;
8421 }
8422
8423 #elif defined(_CMU_CTRL_DBGCLK_MASK)
8424 switch (CMU->CTRL & _CMU_CTRL_DBGCLK_MASK) {
8425 case CMU_CTRL_DBGCLK_AUXHFRCO:
8426 ret = cmuSelect_AUXHFRCO;
8427 break;
8428
8429 case CMU_CTRL_DBGCLK_HFCLK:
8430 ret = cmuSelect_HFCLK;
8431 break;
8432 }
8433 #else
8434 ret = cmuSelect_AUXHFRCO;
8435 #endif
8436 break;
8437
8438 #if defined(USBC_CLOCK_PRESENT)
8439 case CMU_USBCCLKSEL_REG:
8440 switch (CMU->STATUS
8441 & (CMU_STATUS_USBCLFXOSEL
8442 #if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)
8443 | CMU_STATUS_USBCHFCLKSEL
8444 #endif
8445 #if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)
8446 | CMU_STATUS_USBCUSHFRCOSEL
8447 #endif
8448 | CMU_STATUS_USBCLFRCOSEL)) {
8449 #if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)
8450 case CMU_STATUS_USBCHFCLKSEL:
8451 ret = cmuSelect_HFCLK;
8452 break;
8453 #endif
8454
8455 #if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)
8456 case CMU_STATUS_USBCUSHFRCOSEL:
8457 ret = cmuSelect_USHFRCO;
8458 break;
8459 #endif
8460
8461 case CMU_STATUS_USBCLFXOSEL:
8462 ret = cmuSelect_LFXO;
8463 break;
8464
8465 case CMU_STATUS_USBCLFRCOSEL:
8466 ret = cmuSelect_LFRCO;
8467 break;
8468
8469 default:
8470 ret = cmuSelect_Disabled;
8471 break;
8472 }
8473 break;
8474 #endif
8475
8476 #if defined(_CMU_ADCCTRL_ADC0CLKSEL_MASK)
8477 case CMU_ADC0ASYNCSEL_REG:
8478 switch (CMU->ADCCTRL & _CMU_ADCCTRL_ADC0CLKSEL_MASK) {
8479 case CMU_ADCCTRL_ADC0CLKSEL_DISABLED:
8480 ret = cmuSelect_Disabled;
8481 break;
8482
8483 case CMU_ADCCTRL_ADC0CLKSEL_AUXHFRCO:
8484 ret = cmuSelect_AUXHFRCO;
8485 break;
8486
8487 case CMU_ADCCTRL_ADC0CLKSEL_HFXO:
8488 ret = cmuSelect_HFXO;
8489 break;
8490
8491 case CMU_ADCCTRL_ADC0CLKSEL_HFSRCCLK:
8492 ret = cmuSelect_HFSRCCLK;
8493 break;
8494
8495 default:
8496 ret = cmuSelect_Disabled;
8497 break;
8498 }
8499 break;
8500 #endif
8501
8502 #if defined(_CMU_ADCCTRL_ADC1CLKSEL_MASK)
8503 case CMU_ADC1ASYNCSEL_REG:
8504 switch (CMU->ADCCTRL & _CMU_ADCCTRL_ADC1CLKSEL_MASK) {
8505 case CMU_ADCCTRL_ADC1CLKSEL_DISABLED:
8506 ret = cmuSelect_Disabled;
8507 break;
8508
8509 case CMU_ADCCTRL_ADC1CLKSEL_AUXHFRCO:
8510 ret = cmuSelect_AUXHFRCO;
8511 break;
8512
8513 case CMU_ADCCTRL_ADC1CLKSEL_HFXO:
8514 ret = cmuSelect_HFXO;
8515 break;
8516
8517 case CMU_ADCCTRL_ADC1CLKSEL_HFSRCCLK:
8518 ret = cmuSelect_HFSRCCLK;
8519 break;
8520 }
8521 break;
8522 #endif
8523
8524 #if defined(_CMU_SDIOCTRL_SDIOCLKSEL_MASK)
8525 case CMU_SDIOREFSEL_REG:
8526 switch (CMU->SDIOCTRL & _CMU_SDIOCTRL_SDIOCLKSEL_MASK) {
8527 case CMU_SDIOCTRL_SDIOCLKSEL_HFRCO:
8528 ret = cmuSelect_HFRCO;
8529 break;
8530
8531 case CMU_SDIOCTRL_SDIOCLKSEL_HFXO:
8532 ret = cmuSelect_HFXO;
8533 break;
8534
8535 case CMU_SDIOCTRL_SDIOCLKSEL_AUXHFRCO:
8536 ret = cmuSelect_AUXHFRCO;
8537 break;
8538
8539 case CMU_SDIOCTRL_SDIOCLKSEL_USHFRCO:
8540 ret = cmuSelect_USHFRCO;
8541 break;
8542 }
8543 break;
8544 #endif
8545
8546 #if defined(_CMU_QSPICTRL_QSPI0CLKSEL_MASK)
8547 case CMU_QSPI0REFSEL_REG:
8548 switch (CMU->QSPICTRL & _CMU_QSPICTRL_QSPI0CLKSEL_MASK) {
8549 case CMU_QSPICTRL_QSPI0CLKSEL_HFRCO:
8550 ret = cmuSelect_HFRCO;
8551 break;
8552
8553 case CMU_QSPICTRL_QSPI0CLKSEL_HFXO:
8554 ret = cmuSelect_HFXO;
8555 break;
8556
8557 case CMU_QSPICTRL_QSPI0CLKSEL_AUXHFRCO:
8558 ret = cmuSelect_AUXHFRCO;
8559 break;
8560
8561 case CMU_QSPICTRL_QSPI0CLKSEL_USHFRCO:
8562 ret = cmuSelect_USHFRCO;
8563 break;
8564 }
8565 break;
8566 #endif
8567
8568 #if defined(_CMU_USBCTRL_USBCLKSEL_MASK)
8569 case CMU_USBRCLKSEL_REG:
8570 switch (CMU->USBCTRL & _CMU_USBCTRL_USBCLKSEL_MASK) {
8571 case CMU_USBCTRL_USBCLKSEL_USHFRCO:
8572 ret = cmuSelect_USHFRCO;
8573 break;
8574
8575 case CMU_USBCTRL_USBCLKSEL_HFXO:
8576 ret = cmuSelect_HFXO;
8577 break;
8578
8579 case CMU_USBCTRL_USBCLKSEL_HFXOX2:
8580 ret = cmuSelect_HFXOX2;
8581 break;
8582
8583 case CMU_USBCTRL_USBCLKSEL_HFRCO:
8584 ret = cmuSelect_HFRCO;
8585 break;
8586
8587 case CMU_USBCTRL_USBCLKSEL_LFXO:
8588 ret = cmuSelect_LFXO;
8589 break;
8590
8591 case CMU_USBCTRL_USBCLKSEL_LFRCO:
8592 ret = cmuSelect_LFRCO;
8593 break;
8594 }
8595 break;
8596 #endif
8597
8598 #if defined(_CMU_PDMCTRL_PDMCLKSEL_MASK)
8599 case CMU_PDMREFSEL_REG:
8600 switch (CMU->PDMCTRL & _CMU_PDMCTRL_PDMCLKSEL_MASK) {
8601 case CMU_PDMCTRL_PDMCLKSEL_USHFRCO:
8602 ret = cmuSelect_USHFRCO;
8603 break;
8604
8605 case CMU_PDMCTRL_PDMCLKSEL_HFXO:
8606 ret = cmuSelect_HFXO;
8607 break;
8608
8609 case CMU_PDMCTRL_PDMCLKSEL_HFRCO:
8610 ret = cmuSelect_HFRCO;
8611 break;
8612 }
8613 break;
8614 #endif
8615
8616 default:
8617 ret = cmuSelect_Error;
8618 EFM_ASSERT(false);
8619 break;
8620 }
8621
8622 return ret;
8623 }
8624
8625 /***************************************************************************//**
8626 * @brief This function configures the HFLE wait-states and divider suitable
8627 * for the System Core Clock.
8628 *
8629 * @note FOR INTERNAL USE ONLY.
8630 *
8631 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8632 * the clock source is HFCLKLE.
8633 ******************************************************************************/
sli_em_cmu_SetHFLEConfigSystemCoreClock(void)8634 void sli_em_cmu_SetHFLEConfigSystemCoreClock(void)
8635 {
8636 #if defined(CMU_MAX_FREQ_HFLE)
8637 setHfLeConfig(SystemCoreClockGet());
8638 #endif
8639 }
8640
8641 /***************************************************************************//**
8642 * @brief This function configures the HFLE wait-states and divider suitable
8643 * for the HF Clock.
8644 *
8645 * @note FOR INTERNAL USE ONLY.
8646 *
8647 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8648 * the clock source is HFCLKLE.
8649 ******************************************************************************/
sli_em_cmu_SetHFLEConfigHFClock(void)8650 void sli_em_cmu_SetHFLEConfigHFClock(void)
8651 {
8652 #if defined(CMU_MAX_FREQ_HFLE)
8653 setHfLeConfig(SystemHFClockGet());
8654 #endif
8655 }
8656
8657 /***************************************************************************//**
8658 * @brief This function is used to initialize the HF clock and selecting
8659 * an LF clock source.
8660 *
8661 * @note FOR INTERNAL USE ONLY.
8662 *
8663 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8664 * the clock is HF and LFXO or LFRCO is selected as the clock source.
8665 ******************************************************************************/
sli_em_cmu_HFClockSelectLFOsc(uint8_t osc)8666 void sli_em_cmu_HFClockSelectLFOsc(uint8_t osc)
8667 {
8668 if (osc == (uint8_t)cmuOsc_LFXO) {
8669 // Enable LFXO oscillator
8670 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
8671 } else if (osc == (uint8_t)cmuOsc_LFRCO) {
8672 // Enable LFRCO oscillator
8673 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
8674 } else {
8675 EFM_ASSERT(false);
8676 }
8677
8678 // Configure worst case wait-states for flash and set safe HFPER
8679 // clock-tree prescalers.
8680 flashWaitStateMax();
8681 hfperClkSafePrescaler();
8682
8683 #if defined(_SILICON_LABS_32B_SERIES_1)
8684 // Select HF clock source.
8685 if (osc == (uint8_t)cmuOsc_LFXO) {
8686 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_LFXO;
8687 } else if (osc == (uint8_t)cmuOsc_LFRCO) {
8688 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_LFRCO;
8689 }
8690 #if defined(CMU_MAX_FREQ_HFLE)
8691 // Set HFLE clock.
8692 setHfLeConfig(SystemHFClockGet());
8693 #endif
8694 #elif defined(_SILICON_LABS_32B_SERIES_0)
8695 // Select HF clock source.
8696 if (osc == (uint8_t)cmuOsc_LFXO) {
8697 CMU->CMD = CMU_CMD_HFCLKSEL_LFXO;
8698 } else if (osc == (uint8_t)cmuOsc_LFRCO) {
8699 CMU->CMD = CMU_CMD_HFCLKSEL_LFRCO;
8700 }
8701 #if defined(CMU_MAX_FREQ_HFLE)
8702 // Set HFLE clock.
8703 setHfLeConfig(SystemCoreClockGet());
8704 #endif
8705 #endif
8706
8707 // Optimize flash access wait state setting for the currently selected core clk.
8708 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
8709 // Set optimized HFPER clock-tree prescalers.
8710 hfperClkOptimizedPrescaler();
8711 }
8712
8713 /***************************************************************************//**
8714 * @brief This function is used to initialize the HF clock and selecting
8715 * HFXO as the clock source.
8716 *
8717 * @note FOR INTERNAL USE ONLY.
8718 *
8719 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8720 * the clock is HF and HFXO is selected as the clock source.
8721 ******************************************************************************/
sli_em_cmu_HFClockSelectHFXO(void)8722 void sli_em_cmu_HFClockSelectHFXO(void)
8723 {
8724 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
8725 uint32_t vScaleFrequency = SystemHFXOClockGet();
8726 EMU_VScaleEM01ByClock(vScaleFrequency, false);
8727 #endif
8728
8729 #if defined(CMU_MAX_FREQ_HFLE)
8730 // Set 1 HFLE wait-state until the new HFCLKLE frequency is known.
8731 // This is known after 'select' is written below.
8732 setHfLeConfig(CMU_MAX_FREQ_HFLE + 1UL);
8733 #endif
8734 #if defined(CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ)
8735 // Adjust HFXO buffer current for frequencies above 32 MHz.
8736 if (SystemHFXOClockGet() > 32000000) {
8737 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)
8738 | CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ;
8739 } else {
8740 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)
8741 | CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ;
8742 }
8743 #endif
8744
8745 // Enable HFXO oscillator
8746 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
8747
8748 // Configure worst case wait-states for flash and set safe HFPER
8749 // clock-tree prescalers.
8750 flashWaitStateMax();
8751 hfperClkSafePrescaler();
8752
8753 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
8754 // Wait for voltage upscaling to complete before the clock is set.
8755 if (vScaleFrequency != 0UL) {
8756 EMU_VScaleWait();
8757 }
8758 #endif
8759
8760 #if defined(CMU_HFCLKSEL_HF_HFXO)
8761 // Select HF clock source.
8762 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFXO;
8763 #if defined(CMU_MAX_FREQ_HFLE)
8764 // Set HFLE clock.
8765 setHfLeConfig(SystemHFClockGet());
8766 #endif
8767 #elif defined(CMU_CMD_HFCLKSEL_HFXO)
8768 // Select HF clock source.
8769 CMU->CMD = CMU_CMD_HFCLKSEL_HFXO;
8770 #if defined(CMU_MAX_FREQ_HFLE)
8771 // Set HFLE clock.
8772 setHfLeConfig(SystemCoreClockGet());
8773 #endif
8774 #endif
8775
8776 // Optimize flash access wait state setting for the currently selected core clk.
8777 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
8778
8779 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
8780 // Keep EMU module informed on the source HF clock frequency. This will apply voltage
8781 // downscaling after clock is set if downscaling is configured.
8782 if (vScaleFrequency == 0UL) {
8783 EMU_VScaleEM01ByClock(0, true);
8784 }
8785 #endif
8786
8787 // Set optimized HFPER clock-tree prescalers.
8788 hfperClkOptimizedPrescaler();
8789 }
8790
8791 /***************************************************************************//**
8792 * @brief This function is used to initialize the HF clock and selecting
8793 * HFRCO as the clock source.
8794 *
8795 * @note FOR INTERNAL USE ONLY.
8796 *
8797 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8798 * the clock is HF and HFRCO is selected as the clock source.
8799 ******************************************************************************/
sli_em_cmu_HFClockSelectHFRCO(void)8800 void sli_em_cmu_HFClockSelectHFRCO(void)
8801 {
8802 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
8803 uint32_t vScaleFrequency = 0; /* Use default. */
8804 if (((uint32_t)CMU_HFRCOBandGet() > CMU_VSCALEEM01_LOWPOWER_VOLTAGE_CLOCK_MAX)) {
8805 vScaleFrequency = (uint32_t)CMU_HFRCOBandGet();
8806 }
8807 if (vScaleFrequency != 0UL) {
8808 EMU_VScaleEM01ByClock(vScaleFrequency, false);
8809 }
8810 #endif
8811
8812 #if defined(CMU_MAX_FREQ_HFLE)
8813 // Set 1 HFLE wait-state until the new HFCLKLE frequency is known.
8814 // This is known after 'select' is written below.
8815 setHfLeConfig(CMU_MAX_FREQ_HFLE + 1UL);
8816 #endif
8817
8818 // Enable HFRCO oscillator
8819 CMU_OscillatorEnable(cmuOsc_HFRCO, true, true);
8820
8821 // Configure worst case wait-states for flash and set safe HFPER
8822 // clock-tree prescalers.
8823 flashWaitStateMax();
8824 hfperClkSafePrescaler();
8825
8826 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
8827 // Wait for voltage upscaling to complete before the clock is set.
8828 if (vScaleFrequency != 0UL) {
8829 EMU_VScaleWait();
8830 }
8831 #endif
8832
8833 #if defined(_SILICON_LABS_32B_SERIES_1)
8834 // Select HF clock source.
8835 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFRCO;
8836 #if defined(CMU_MAX_FREQ_HFLE)
8837 // Set HFLE clock.
8838 setHfLeConfig(SystemHFClockGet());
8839 #endif
8840 #elif defined(_SILICON_LABS_32B_SERIES_0)
8841 // Select HF clock source.
8842 CMU->CMD = CMU_CMD_HFCLKSEL_HFRCO;
8843 #if defined(CMU_MAX_FREQ_HFLE)
8844 // Set HFLE clock.
8845 setHfLeConfig(SystemCoreClockGet());
8846 #endif
8847 #endif
8848
8849 // Optimize flash access wait state setting for the currently selected core clk.
8850 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
8851
8852 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
8853 // Keep EMU module informed on the source HF clock frequency. This will apply voltage
8854 // downscaling after clock is set if downscaling is configured.
8855 if (vScaleFrequency == 0UL) {
8856 EMU_VScaleEM01ByClock(0, true);
8857 }
8858 #endif
8859
8860 // Set optimized HFPER clock-tree prescalers.
8861 hfperClkOptimizedPrescaler();
8862 }
8863
8864 #if defined(CMU_CMD_HFCLKSEL_USHFRCODIV2)
8865 /***************************************************************************//**
8866 * @brief This function is used to initialize the HF clock and selecting
8867 * USHFRCODIV2 as the clock source.
8868 *
8869 * @note FOR INTERNAL USE ONLY.
8870 *
8871 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8872 * the clock is HF and USHFRCODIV2 is selected as the clock source.
8873 ******************************************************************************/
sli_em_cmu_HFClockSelectUSHFRCODIV2(void)8874 void sli_em_cmu_HFClockSelectUSHFRCODIV2(void)
8875 {
8876 // Enable USHFRCO oscillator
8877 CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
8878 // Configure worst case wait-states for flash and set safe HFPER
8879 // clock-tree prescalers.
8880 flashWaitStateMax();
8881 hfperClkSafePrescaler();
8882
8883 // Select HF clock source.
8884 CMU->CMD = CMU_CMD_HFCLKSEL_USHFRCODIV2;
8885 #if defined(CMU_MAX_FREQ_HFLE)
8886 setHfLeConfig(SystemCoreClockGet());
8887 #endif
8888
8889 // Optimize flash access wait state setting for the currently selected core clk.
8890 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
8891 // Set optimized HFPER clock-tree prescalers.
8892 hfperClkOptimizedPrescaler();
8893 }
8894 #endif
8895
8896 #if defined(CMU_HFCLKSTATUS_SELECTED_HFRCODIV2)
8897 /***************************************************************************//**
8898 * @brief This function is used to initialize the HF clock and selecting
8899 * HFRCODIV2 as the clock source.
8900 *
8901 * @note FOR INTERNAL USE ONLY.
8902 *
8903 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8904 * the clock is HF and HFRCODIV2 is selected as the clock source.
8905 ******************************************************************************/
sli_em_cmu_HFClockSelectHFRCODIV2(void)8906 void sli_em_cmu_HFClockSelectHFRCODIV2(void)
8907 {
8908 // Enable HFRCO oscillator
8909 CMU_OscillatorEnable(cmuOsc_HFRCO, true, true);
8910 // Configure worst case wait-states for flash and set safe HFPER
8911 // clock-tree prescalers.
8912 flashWaitStateMax();
8913 hfperClkSafePrescaler();
8914
8915 // Select HF clock source.
8916 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFRCODIV2;
8917 #if defined(CMU_MAX_FREQ_HFLE)
8918 setHfLeConfig(SystemHFClockGet());
8919 #endif
8920
8921 // Optimize flash access wait state setting for the currently selected core clk.
8922 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
8923 // Set optimized HFPER clock-tree prescalers.
8924 hfperClkOptimizedPrescaler();
8925 }
8926 #endif
8927
8928 #if defined(CMU_HFCLKSTATUS_SELECTED_CLKIN0)
8929 /***************************************************************************//**
8930 * @brief This function is used to initialize the HF clock and selecting
8931 * CLKIN0 as the clock source.
8932 *
8933 * @note FOR INTERNAL USE ONLY.
8934 *
8935 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8936 * the clock is HF and CLKIN0 is selected as the clock source.
8937 ******************************************************************************/
sli_em_cmu_HFClockSelectCLKIN0(void)8938 void sli_em_cmu_HFClockSelectCLKIN0(void)
8939 {
8940 // Configure worst case wait-states for flash and set safe HFPER
8941 // clock-tree prescalers.
8942 flashWaitStateMax();
8943 hfperClkSafePrescaler();
8944
8945 // Select HF clock source.
8946 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_CLKIN0;
8947 #if defined(CMU_MAX_FREQ_HFLE)
8948 setHfLeConfig(SystemHFClockGet());
8949 #endif
8950
8951 // Optimize flash access wait state setting for the currently selected core clk.
8952 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
8953 // Set optimized HFPER clock-tree prescalers.
8954 hfperClkOptimizedPrescaler();
8955 }
8956 #endif
8957
8958 #if defined(CMU_HFCLKSTATUS_SELECTED_USHFRCO)
8959 /***************************************************************************//**
8960 * @brief This function is used to initialize the HF clock and selecting
8961 * USHFRCO as the clock source.
8962 *
8963 * @note FOR INTERNAL USE ONLY.
8964 *
8965 * @note This function is needed for macro expansion of CMU_CLOCK_SELECT_SET when
8966 * the clock is HF and USHFRCO is selected as the clock source.
8967 ******************************************************************************/
sli_em_cmu_HFClockSelectUSHFRCO(void)8968 void sli_em_cmu_HFClockSelectUSHFRCO(void)
8969 {
8970 // Enable USHFRCO oscillator
8971 CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
8972 // Configure worst case wait-states for flash and set safe HFPER
8973 // clock-tree prescalers.
8974 flashWaitStateMax();
8975 hfperClkSafePrescaler();
8976
8977 // Select HF clock source.
8978 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_USHFRCO;
8979 #if defined(CMU_MAX_FREQ_HFLE)
8980 setHfLeConfig(SystemHFClockGet());
8981 #endif
8982
8983 // Optimize flash access wait state setting for the currently selected core clk.
8984 CMU_UpdateWaitStates(SystemCoreClockGet(), VSCALE_DEFAULT);
8985 // Set optimized HFPER clock-tree prescalers.
8986 hfperClkOptimizedPrescaler();
8987 }
8988 #endif
8989
8990 /***************************************************************************//**
8991 * @brief
8992 * Select the reference clock/oscillator used for a clock branch.
8993 *
8994 * @details
8995 * Notice that if a selected reference is not enabled prior to selecting its
8996 * use, it will be enabled and this function will wait for the selected
8997 * oscillator to be stable. It will however NOT be disabled if another
8998 * reference clock is selected later.
8999 *
9000 * This feature is particularly important if selecting a new reference
9001 * clock for the clock branch clocking the core. Otherwise, the system
9002 * may halt.
9003 *
9004 * @note
9005 * HFCLKLE prescaler is automatically modified when peripherals with clock
9006 * domain HFBUSCLK is chosen based on the maximum HFLE frequency allowed.
9007 *
9008 * @param[in] clock
9009 * A clock branch to select reference clock for. One of:
9010 * @li #cmuClock_HF
9011 * @li #cmuClock_LFA
9012 * @li #cmuClock_LFB
9013 * @if _CMU_LFCCLKEN0_MASK
9014 * @li #cmuClock_LFC
9015 * @endif
9016 * @if _CMU_LFECLKEN0_MASK
9017 * @li #cmuClock_LFE
9018 * @endif
9019 * @li #cmuClock_DBG
9020 * @if _CMU_CMD_USBCLKSEL_MASK
9021 * @li #cmuClock_USBC
9022 * @endif
9023 * @if _CMU_USBCTRL_MASK
9024 * @li #cmuClock_USBR
9025 * @endif
9026 *
9027 * @param[in] ref
9028 * A reference selected for clocking. See the reference manual
9029 * for details about references available for a specific clock branch.
9030 * @li #cmuSelect_HFRCO
9031 * @li #cmuSelect_LFRCO
9032 * @li #cmuSelect_HFXO
9033 * @if _CMU_HFXOCTRL_HFXOX2EN_MASK
9034 * @li #cmuSelect_HFXOX2
9035 * @endif
9036 * @li #cmuSelect_LFXO
9037 * @li #cmuSelect_HFCLKLE
9038 * @li #cmuSelect_AUXHFRCO
9039 * @if _CMU_USHFRCOCTRL_MASK
9040 * @li #cmuSelect_USHFRCO
9041 * @endif
9042 * @li #cmuSelect_HFCLK
9043 * @ifnot DOXYDOC_EFM32_GECKO_FAMILY
9044 * @li #cmuSelect_ULFRCO
9045 * @endif
9046 * @if CMU_OSCENCMD_PLFRCOEN
9047 * @li #cmuSelect_PLFRCO
9048 * @endif
9049 ******************************************************************************/
CMU_ClockSelectSet(CMU_Clock_TypeDef clock,CMU_Select_TypeDef ref)9050 void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
9051 {
9052 uint32_t select = (uint32_t)cmuOsc_HFRCO;
9053 CMU_Osc_TypeDef osc = cmuOsc_HFRCO;
9054 uint32_t freq;
9055 uint32_t tmp;
9056 uint32_t selRegId;
9057 #if defined(_SILICON_LABS_32B_SERIES_1)
9058 volatile uint32_t *selReg = NULL;
9059 #endif
9060 #if defined(CMU_LFCLKSEL_LFAE_ULFRCO)
9061 uint32_t lfExtended = 0;
9062 #endif
9063
9064 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
9065 uint32_t vScaleFrequency = 0; /* Use default. */
9066
9067 /* Start voltage upscaling before the clock is set. */
9068 if (clock == cmuClock_HF) {
9069 if (ref == cmuSelect_HFXO) {
9070 vScaleFrequency = SystemHFXOClockGet();
9071 } else if ((ref == cmuSelect_HFRCO)
9072 && ((uint32_t)CMU_HFRCOBandGet()
9073 > CMU_VSCALEEM01_LOWPOWER_VOLTAGE_CLOCK_MAX)) {
9074 vScaleFrequency = (uint32_t)CMU_HFRCOBandGet();
9075 } else {
9076 /* Use the default frequency. */
9077 }
9078 if (vScaleFrequency != 0UL) {
9079 EMU_VScaleEM01ByClock(vScaleFrequency, false);
9080 }
9081 }
9082 #endif
9083
9084 selRegId = ((unsigned)clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;
9085
9086 switch (selRegId) {
9087 case CMU_HFCLKSEL_REG:
9088 switch (ref) {
9089 case cmuSelect_LFXO:
9090 #if defined(_SILICON_LABS_32B_SERIES_1)
9091 select = CMU_HFCLKSEL_HF_LFXO;
9092 #elif defined(_SILICON_LABS_32B_SERIES_0)
9093 select = CMU_CMD_HFCLKSEL_LFXO;
9094 #endif
9095 osc = cmuOsc_LFXO;
9096 break;
9097
9098 case cmuSelect_LFRCO:
9099 #if defined(_SILICON_LABS_32B_SERIES_1)
9100 select = CMU_HFCLKSEL_HF_LFRCO;
9101 #elif defined(_SILICON_LABS_32B_SERIES_0)
9102 select = CMU_CMD_HFCLKSEL_LFRCO;
9103 #endif
9104 osc = cmuOsc_LFRCO;
9105 break;
9106
9107 case cmuSelect_HFXO:
9108 #if defined(CMU_HFCLKSEL_HF_HFXO)
9109 select = CMU_HFCLKSEL_HF_HFXO;
9110 #elif defined(CMU_CMD_HFCLKSEL_HFXO)
9111 select = CMU_CMD_HFCLKSEL_HFXO;
9112 #endif
9113 osc = cmuOsc_HFXO;
9114 #if defined(CMU_MAX_FREQ_HFLE)
9115 /* Set 1 HFLE wait-state until the new HFCLKLE frequency is known.
9116 This is known after 'select' is written below. */
9117 setHfLeConfig(CMU_MAX_FREQ_HFLE + 1UL);
9118 #endif
9119 #if defined(CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ)
9120 /* Adjust HFXO buffer current for frequencies above 32 MHz. */
9121 if (SystemHFXOClockGet() > 32000000) {
9122 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)
9123 | CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ;
9124 } else {
9125 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)
9126 | CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ;
9127 }
9128 #endif
9129 break;
9130
9131 case cmuSelect_HFRCO:
9132 #if defined(_SILICON_LABS_32B_SERIES_1)
9133 select = CMU_HFCLKSEL_HF_HFRCO;
9134 #elif defined(_SILICON_LABS_32B_SERIES_0)
9135 select = CMU_CMD_HFCLKSEL_HFRCO;
9136 #endif
9137 osc = cmuOsc_HFRCO;
9138 #if defined(CMU_MAX_FREQ_HFLE)
9139 /* Set 1 HFLE wait-state until the new HFCLKLE frequency is known.
9140 This is known after 'select' is written below. */
9141 setHfLeConfig(CMU_MAX_FREQ_HFLE + 1UL);
9142 #endif
9143 break;
9144
9145 #if defined(CMU_CMD_HFCLKSEL_USHFRCODIV2)
9146 case cmuSelect_USHFRCODIV2:
9147 select = CMU_CMD_HFCLKSEL_USHFRCODIV2;
9148 osc = cmuOsc_USHFRCO;
9149 break;
9150 #endif
9151
9152 #if defined(CMU_HFCLKSTATUS_SELECTED_HFRCODIV2)
9153 case cmuSelect_HFRCODIV2:
9154 select = CMU_HFCLKSEL_HF_HFRCODIV2;
9155 osc = cmuOsc_HFRCO;
9156 break;
9157 #endif
9158
9159 #if defined(CMU_HFCLKSTATUS_SELECTED_CLKIN0)
9160 case cmuSelect_CLKIN0:
9161 select = CMU_HFCLKSEL_HF_CLKIN0;
9162 osc = cmuOsc_CLKIN0;
9163 break;
9164 #endif
9165
9166 #if defined(CMU_HFCLKSTATUS_SELECTED_USHFRCO)
9167 case cmuSelect_USHFRCO:
9168 select = CMU_HFCLKSEL_HF_USHFRCO;
9169 osc = cmuOsc_USHFRCO;
9170 break;
9171 #endif
9172
9173 #if defined(CMU_LFCLKSEL_LFAE_ULFRCO) || defined(CMU_LFACLKSEL_LFA_ULFRCO)
9174 case cmuSelect_ULFRCO:
9175 /* ULFRCO cannot be used as HFCLK. */
9176 EFM_ASSERT(false);
9177 return;
9178 #endif
9179
9180 default:
9181 EFM_ASSERT(false);
9182 return;
9183 }
9184
9185 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9186 #if defined(CMU_HFCLKSTATUS_SELECTED_CLKIN0)
9187 if (osc != cmuOsc_CLKIN0) {
9188 CMU_OscillatorEnable(osc, true, true);
9189 }
9190 #else
9191 CMU_OscillatorEnable(osc, true, true);
9192 #endif
9193
9194 /* Configure worst case wait-states for flash and set safe HFPER
9195 clock-tree prescalers. */
9196 flashWaitStateMax();
9197 hfperClkSafePrescaler();
9198
9199 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
9200 /* Wait for voltage upscaling to complete before the clock is set. */
9201 if (vScaleFrequency != 0UL) {
9202 EMU_VScaleWait();
9203 }
9204 #endif
9205
9206 /* Switch to the selected oscillator. */
9207 #if defined(_CMU_HFCLKSEL_MASK)
9208 CMU->HFCLKSEL = select;
9209 #else
9210 CMU->CMD = select;
9211 #endif
9212 /* Update the CMSIS core clock variable. */
9213 /* (The function will update the global variable). */
9214 freq = SystemCoreClockGet();
9215
9216 #if defined(CMU_MAX_FREQ_HFLE)
9217 /* Update the HFLE configuration after 'select' is set.
9218 Note that the HFCLKLE clock is connected differently on platforms 1 and 2. */
9219 #if defined(_SILICON_LABS_32B_SERIES_0)
9220 setHfLeConfig(freq);
9221 #else
9222 setHfLeConfig(SystemHFClockGet());
9223 #endif
9224 #endif
9225
9226 /* Optimize flash access wait state setting for the currently selected core clk. */
9227 CMU_UpdateWaitStates(freq, VSCALE_DEFAULT);
9228
9229 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
9230 /* Keep EMU module informed on the source HF clock frequency. This will apply voltage
9231 downscaling after clock is set if downscaling is configured. */
9232 if (vScaleFrequency == 0UL) {
9233 EMU_VScaleEM01ByClock(0, true);
9234 }
9235 #endif
9236 /* Set optimized HFPER clock-tree prescalers. */
9237 hfperClkOptimizedPrescaler();
9238 break;
9239
9240 #if defined(_SILICON_LABS_32B_SERIES_1)
9241 case CMU_LFACLKSEL_REG:
9242 selReg = &CMU->LFACLKSEL;
9243 /* HFCLKCLE can't be used as LFACLK. */
9244 EFM_ASSERT(ref != cmuSelect_HFCLKLE);
9245 SL_FALLTHROUGH
9246 /* Fall through and select the clock source. */
9247
9248 #if defined(_CMU_LFCCLKSEL_MASK)
9249 case CMU_LFCCLKSEL_REG:
9250 selReg = (selReg == NULL) ? &CMU->LFCCLKSEL : selReg;
9251 /* HFCLKCLE can't be used as LFCCLK. */
9252 EFM_ASSERT(ref != cmuSelect_HFCLKLE);
9253 SL_FALLTHROUGH
9254 #endif
9255 /* Fall through and select the clock source. */
9256
9257 case CMU_LFECLKSEL_REG:
9258 selReg = (selReg == NULL) ? &CMU->LFECLKSEL : selReg;
9259 /* HFCLKCLE can't be used as LFECLK. */
9260 EFM_ASSERT(ref != cmuSelect_HFCLKLE);
9261 SL_FALLTHROUGH
9262 /* Fall through and select the clock source. */
9263
9264 case CMU_LFBCLKSEL_REG:
9265 selReg = (selReg == NULL) ? &CMU->LFBCLKSEL : selReg;
9266 switch (ref) {
9267 case cmuSelect_Disabled:
9268 tmp = _CMU_LFACLKSEL_LFA_DISABLED;
9269 break;
9270
9271 case cmuSelect_LFXO:
9272 /* Ensure that thes elected oscillator is enabled, waiting for it to stabilize. */
9273 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
9274 tmp = _CMU_LFACLKSEL_LFA_LFXO;
9275 break;
9276
9277 case cmuSelect_LFRCO:
9278 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9279 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
9280 tmp = _CMU_LFACLKSEL_LFA_LFRCO;
9281 break;
9282
9283 case cmuSelect_HFCLKLE:
9284 /* Ensure the correct HFLE wait-states and enable HFCLK to LE.*/
9285 setHfLeConfig(SystemHFClockGet());
9286 BUS_RegBitWrite(&CMU->HFBUSCLKEN0, _CMU_HFBUSCLKEN0_LE_SHIFT, 1);
9287 tmp = _CMU_LFBCLKSEL_LFB_HFCLKLE;
9288 break;
9289
9290 case cmuSelect_ULFRCO:
9291 /* ULFRCO is always on, there is no need to enable it. */
9292 tmp = _CMU_LFACLKSEL_LFA_ULFRCO;
9293 break;
9294
9295 #if defined(PLFRCO_PRESENT)
9296 case cmuSelect_PLFRCO:
9297 CMU_OscillatorEnable(cmuOsc_PLFRCO, true, true);
9298 tmp = _CMU_LFACLKSEL_LFA_PLFRCO;
9299 break;
9300 #endif
9301
9302 default:
9303 EFM_ASSERT(false);
9304 return;
9305 }
9306 *selReg = tmp;
9307 break;
9308
9309 #elif defined(_SILICON_LABS_32B_SERIES_0)
9310 case CMU_LFACLKSEL_REG:
9311 case CMU_LFBCLKSEL_REG:
9312 switch (ref) {
9313 case cmuSelect_Disabled:
9314 tmp = _CMU_LFCLKSEL_LFA_DISABLED;
9315 break;
9316
9317 case cmuSelect_LFXO:
9318 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9319 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
9320 tmp = _CMU_LFCLKSEL_LFA_LFXO;
9321 break;
9322
9323 case cmuSelect_LFRCO:
9324 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9325 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
9326 tmp = _CMU_LFCLKSEL_LFA_LFRCO;
9327 break;
9328
9329 case cmuSelect_HFCLKLE:
9330 #if defined(CMU_MAX_FREQ_HFLE)
9331 /* Set the HFLE wait-state and divider. */
9332 freq = SystemCoreClockGet();
9333 setHfLeConfig(freq);
9334 #endif
9335 /* Ensure HFCORE to LE clocking is enabled. */
9336 BUS_RegBitWrite(&CMU->HFCORECLKEN0, _CMU_HFCORECLKEN0_LE_SHIFT, 1);
9337 tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2;
9338 break;
9339
9340 #if defined(CMU_LFCLKSEL_LFAE_ULFRCO)
9341 case cmuSelect_ULFRCO:
9342 /* ULFRCO is always enabled. */
9343 tmp = _CMU_LFCLKSEL_LFA_DISABLED;
9344 lfExtended = 1;
9345 break;
9346 #endif
9347
9348 default:
9349 /* An illegal clock source for LFA/LFB selected. */
9350 EFM_ASSERT(false);
9351 return;
9352 }
9353
9354 /* Apply select. */
9355 if (selRegId == CMU_LFACLKSEL_REG) {
9356 #if defined(_CMU_LFCLKSEL_LFAE_MASK)
9357 CMU->LFCLKSEL = (CMU->LFCLKSEL
9358 & ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK))
9359 | (tmp << _CMU_LFCLKSEL_LFA_SHIFT)
9360 | (lfExtended << _CMU_LFCLKSEL_LFAE_SHIFT);
9361 #else
9362 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFA_MASK)
9363 | (tmp << _CMU_LFCLKSEL_LFA_SHIFT);
9364 #endif
9365 } else {
9366 #if defined(_CMU_LFCLKSEL_LFBE_MASK)
9367 CMU->LFCLKSEL = (CMU->LFCLKSEL
9368 & ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK))
9369 | (tmp << _CMU_LFCLKSEL_LFB_SHIFT)
9370 | (lfExtended << _CMU_LFCLKSEL_LFBE_SHIFT);
9371 #else
9372 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFB_MASK)
9373 | (tmp << _CMU_LFCLKSEL_LFB_SHIFT);
9374 #endif
9375 }
9376 break;
9377
9378 #if defined(_CMU_LFCLKSEL_LFC_MASK)
9379 case CMU_LFCCLKSEL_REG:
9380 switch (ref) {
9381 case cmuSelect_Disabled:
9382 tmp = _CMU_LFCLKSEL_LFA_DISABLED;
9383 break;
9384
9385 case cmuSelect_LFXO:
9386 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9387 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
9388 tmp = _CMU_LFCLKSEL_LFC_LFXO;
9389 break;
9390
9391 case cmuSelect_LFRCO:
9392 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9393 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
9394 tmp = _CMU_LFCLKSEL_LFC_LFRCO;
9395 break;
9396
9397 default:
9398 /* An illegal clock source for LFC selected. */
9399 EFM_ASSERT(false);
9400 return;
9401 }
9402
9403 /* Apply select. */
9404 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFC_MASK)
9405 | (tmp << _CMU_LFCLKSEL_LFC_SHIFT);
9406 break;
9407 #endif
9408 #endif
9409
9410 #if defined(_CMU_DBGCLKSEL_DBG_MASK) || defined(CMU_CTRL_DBGCLK)
9411 case CMU_DBGCLKSEL_REG:
9412 switch (ref) {
9413 #if defined(_CMU_DBGCLKSEL_DBG_MASK)
9414 case cmuSelect_AUXHFRCO:
9415 /* Select AUXHFRCO as a debug clock. */
9416 CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_AUXHFRCO;
9417 break;
9418
9419 case cmuSelect_HFCLK:
9420 /* Select divided HFCLK as a debug clock. */
9421 CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_HFCLK;
9422 break;
9423 #endif
9424
9425 #if defined(CMU_CTRL_DBGCLK)
9426 case cmuSelect_AUXHFRCO:
9427 /* Select AUXHFRCO as a debug clock. */
9428 CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))
9429 | CMU_CTRL_DBGCLK_AUXHFRCO;
9430 break;
9431
9432 case cmuSelect_HFCLK:
9433 /* Select divided HFCLK as a debug clock. */
9434 CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))
9435 | CMU_CTRL_DBGCLK_HFCLK;
9436 break;
9437 #endif
9438
9439 default:
9440 /* An illegal clock source for debug selected. */
9441 EFM_ASSERT(false);
9442 return;
9443 }
9444 break;
9445 #endif
9446
9447 #if defined(USBC_CLOCK_PRESENT)
9448 case CMU_USBCCLKSEL_REG:
9449 switch (ref) {
9450 case cmuSelect_LFXO:
9451 /* Select LFXO as a clock source for USB. It can only be used in sleep mode. */
9452 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9453 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
9454
9455 /* Switch the oscillator. */
9456 CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;
9457
9458 /* Wait until the clock is activated. */
9459 while ((CMU->STATUS & CMU_STATUS_USBCLFXOSEL) == 0) {
9460 }
9461 break;
9462
9463 case cmuSelect_LFRCO:
9464 /* Select LFRCO as a clock source for USB. It can only be used in sleep mode. */
9465 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9466 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
9467
9468 /* Switch the oscillator. */
9469 CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;
9470
9471 /* Wait until the clock is activated. */
9472 while ((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL) == 0) {
9473 }
9474 break;
9475
9476 #if defined(CMU_STATUS_USBCHFCLKSEL)
9477 case cmuSelect_HFCLK:
9478 /* Select undivided HFCLK as a clock source for USB. */
9479 /* The oscillator must already be enabled to avoid a core lockup. */
9480 CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
9481 /* Wait until the clock is activated. */
9482 while ((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL) == 0) {
9483 }
9484 break;
9485 #endif
9486
9487 #if defined(CMU_CMD_USBCCLKSEL_USHFRCO)
9488 case cmuSelect_USHFRCO:
9489 /* Select USHFRCO as a clock source for USB. */
9490 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9491 CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
9492
9493 /* Switch the oscillator. */
9494 CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;
9495
9496 /* Wait until the clock is activated. */
9497 while ((CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL) == 0) {
9498 }
9499 break;
9500 #endif
9501
9502 default:
9503 /* An illegal clock source for USB. */
9504 EFM_ASSERT(false);
9505 return;
9506 }
9507 break;
9508 #endif
9509
9510 #if defined(_CMU_ADCCTRL_ADC0CLKSEL_MASK)
9511 case CMU_ADC0ASYNCSEL_REG:
9512 switch (ref) {
9513 case cmuSelect_Disabled:
9514 tmp = _CMU_ADCCTRL_ADC0CLKSEL_DISABLED;
9515 break;
9516
9517 case cmuSelect_AUXHFRCO:
9518 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9519 CMU_OscillatorEnable(cmuOsc_AUXHFRCO, true, true);
9520 tmp = _CMU_ADCCTRL_ADC0CLKSEL_AUXHFRCO;
9521 break;
9522
9523 case cmuSelect_HFXO:
9524 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9525 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
9526 tmp = _CMU_ADCCTRL_ADC0CLKSEL_HFXO;
9527 break;
9528
9529 case cmuSelect_HFSRCCLK:
9530 tmp = _CMU_ADCCTRL_ADC0CLKSEL_HFSRCCLK;
9531 break;
9532
9533 default:
9534 /* An illegal clock source for ADC0ASYNC selected. */
9535 EFM_ASSERT(false);
9536 return;
9537 }
9538
9539 /* Apply select. */
9540 CMU->ADCCTRL = (CMU->ADCCTRL & ~_CMU_ADCCTRL_ADC0CLKSEL_MASK)
9541 | (tmp << _CMU_ADCCTRL_ADC0CLKSEL_SHIFT);
9542 break;
9543 #endif
9544
9545 #if defined(_CMU_ADCCTRL_ADC1CLKSEL_MASK)
9546 case CMU_ADC1ASYNCSEL_REG:
9547 switch (ref) {
9548 case cmuSelect_Disabled:
9549 tmp = _CMU_ADCCTRL_ADC1CLKSEL_DISABLED;
9550 break;
9551
9552 case cmuSelect_AUXHFRCO:
9553 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9554 CMU_OscillatorEnable(cmuOsc_AUXHFRCO, true, true);
9555 tmp = _CMU_ADCCTRL_ADC1CLKSEL_AUXHFRCO;
9556 break;
9557
9558 case cmuSelect_HFXO:
9559 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9560 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
9561 tmp = _CMU_ADCCTRL_ADC1CLKSEL_HFXO;
9562 break;
9563
9564 case cmuSelect_HFSRCCLK:
9565 tmp = _CMU_ADCCTRL_ADC1CLKSEL_HFSRCCLK;
9566 break;
9567
9568 default:
9569 /* An illegal clock source for ADC1ASYNC selected. */
9570 EFM_ASSERT(false);
9571 return;
9572 }
9573
9574 /* Apply select. */
9575 CMU->ADCCTRL = (CMU->ADCCTRL & ~_CMU_ADCCTRL_ADC1CLKSEL_MASK)
9576 | (tmp << _CMU_ADCCTRL_ADC1CLKSEL_SHIFT);
9577 break;
9578 #endif
9579
9580 #if defined(_CMU_SDIOCTRL_SDIOCLKSEL_MASK)
9581 case CMU_SDIOREFSEL_REG:
9582 switch (ref) {
9583 case cmuSelect_HFRCO:
9584 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9585 CMU_OscillatorEnable(cmuOsc_HFRCO, true, true);
9586 tmp = _CMU_SDIOCTRL_SDIOCLKSEL_HFRCO;
9587 break;
9588
9589 case cmuSelect_HFXO:
9590 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9591 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
9592 tmp = _CMU_SDIOCTRL_SDIOCLKSEL_HFXO;
9593 break;
9594
9595 case cmuSelect_AUXHFRCO:
9596 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9597 CMU_OscillatorEnable(cmuOsc_AUXHFRCO, true, true);
9598 tmp = _CMU_SDIOCTRL_SDIOCLKSEL_AUXHFRCO;
9599 break;
9600
9601 case cmuSelect_USHFRCO:
9602 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9603 CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
9604 tmp = _CMU_SDIOCTRL_SDIOCLKSEL_USHFRCO;
9605 break;
9606
9607 default:
9608 /* An illegal clock source for SDIOREF selected. */
9609 EFM_ASSERT(false);
9610 return;
9611 }
9612
9613 /* Apply select. */
9614 CMU->SDIOCTRL = (CMU->SDIOCTRL & ~_CMU_SDIOCTRL_SDIOCLKSEL_MASK)
9615 | (tmp << _CMU_SDIOCTRL_SDIOCLKSEL_SHIFT);
9616 break;
9617 #endif
9618
9619 #if defined(_CMU_QSPICTRL_QSPI0CLKSEL_MASK)
9620 case CMU_QSPI0REFSEL_REG:
9621 switch (ref) {
9622 case cmuSelect_HFRCO:
9623 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9624 CMU_OscillatorEnable(cmuOsc_HFRCO, true, true);
9625 tmp = _CMU_QSPICTRL_QSPI0CLKSEL_HFRCO;
9626 break;
9627
9628 case cmuSelect_HFXO:
9629 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9630 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
9631 tmp = _CMU_QSPICTRL_QSPI0CLKSEL_HFXO;
9632 break;
9633
9634 case cmuSelect_AUXHFRCO:
9635 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9636 CMU_OscillatorEnable(cmuOsc_AUXHFRCO, true, true);
9637 tmp = _CMU_QSPICTRL_QSPI0CLKSEL_AUXHFRCO;
9638 break;
9639
9640 case cmuSelect_USHFRCO:
9641 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9642 CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
9643 tmp = _CMU_QSPICTRL_QSPI0CLKSEL_USHFRCO;
9644 break;
9645
9646 default:
9647 /* An illegal clock source for QSPI0REF selected. */
9648 EFM_ASSERT(false);
9649 return;
9650 }
9651
9652 /* Apply select. */
9653 CMU->QSPICTRL = (CMU->QSPICTRL & ~_CMU_QSPICTRL_QSPI0CLKSEL_MASK)
9654 | (tmp << _CMU_QSPICTRL_QSPI0CLKSEL_SHIFT);
9655 break;
9656 #endif
9657
9658 #if defined(_CMU_USBCTRL_USBCLKSEL_MASK)
9659 case CMU_USBRCLKSEL_REG:
9660 switch (ref) {
9661 case cmuSelect_USHFRCO:
9662 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9663 CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
9664 tmp = _CMU_USBCTRL_USBCLKSEL_USHFRCO;
9665 break;
9666
9667 case cmuSelect_HFXO:
9668 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9669 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
9670 tmp = _CMU_USBCTRL_USBCLKSEL_HFXO;
9671 break;
9672
9673 case cmuSelect_HFXOX2:
9674 /* Only allowed for HFXO frequencies up to 25 MHz. */
9675 EFM_ASSERT(SystemHFXOClockGet() <= 25000000u);
9676
9677 /* Enable HFXO X2. */
9678 CMU->HFXOCTRL |= CMU_HFXOCTRL_HFXOX2EN;
9679
9680 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9681 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
9682
9683 tmp = _CMU_USBCTRL_USBCLKSEL_HFXOX2;
9684 break;
9685
9686 case cmuSelect_HFRCO:
9687 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9688 CMU_OscillatorEnable(cmuOsc_HFRCO, true, true);
9689 tmp = _CMU_USBCTRL_USBCLKSEL_HFRCO;
9690 break;
9691
9692 case cmuSelect_LFXO:
9693 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9694 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
9695 tmp = _CMU_USBCTRL_USBCLKSEL_LFXO;
9696 break;
9697
9698 case cmuSelect_LFRCO:
9699 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9700 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
9701 tmp = _CMU_USBCTRL_USBCLKSEL_LFRCO;
9702 break;
9703
9704 default:
9705 /* An illegal clock source for USBR selected. */
9706 EFM_ASSERT(false);
9707 return;
9708 }
9709
9710 /* Apply select. */
9711 CMU->USBCTRL = (CMU->USBCTRL & ~_CMU_USBCTRL_USBCLKSEL_MASK)
9712 | (tmp << _CMU_USBCTRL_USBCLKSEL_SHIFT);
9713 break;
9714 #endif
9715
9716 #if defined(_CMU_PDMCTRL_PDMCLKSEL_MASK)
9717 case CMU_PDMREFSEL_REG:
9718 switch (ref) {
9719 case cmuSelect_USHFRCO:
9720 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9721 CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
9722 tmp = _CMU_PDMCTRL_PDMCLKSEL_USHFRCO;
9723 break;
9724
9725 case cmuSelect_HFXO:
9726 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9727 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
9728 tmp = _CMU_PDMCTRL_PDMCLKSEL_HFXO;
9729 break;
9730
9731 case cmuSelect_HFRCO:
9732 /* Ensure that the selected oscillator is enabled, waiting for it to stabilize. */
9733 CMU_OscillatorEnable(cmuOsc_HFRCO, true, true);
9734 tmp = _CMU_PDMCTRL_PDMCLKSEL_HFRCO;
9735 break;
9736
9737 default:
9738 /* An illegal clock source for PDMREF selected. */
9739 EFM_ASSERT(false);
9740 return;
9741 }
9742
9743 /* Apply select. */
9744 CMU->PDMCTRL = (CMU->PDMCTRL & ~_CMU_PDMCTRL_PDMCLKSEL_MASK)
9745 | (tmp << _CMU_PDMCTRL_PDMCLKSEL_SHIFT);
9746 break;
9747 #endif
9748
9749 default:
9750 EFM_ASSERT(false);
9751 break;
9752 }
9753 }
9754
9755 /***************************************************************************//**
9756 * @brief
9757 * Gets the precision (in PPM) of the specified low frequency clock branch.
9758 *
9759 * @param[in] clock
9760 * Clock branch.
9761 *
9762 * @return
9763 * Precision, in PPM, of the specified clock branch.
9764 *
9765 * @note
9766 * This function is only for internal usage.
9767 *
9768 * @note
9769 * The current implementation of this function is used to determine if the
9770 * clock has a precision <= 500 ppm or not (which is the minimum required
9771 * for BLE). Future version of this function should provide more accurate
9772 * precision numbers to allow for further optimizations from the stacks.
9773 ******************************************************************************/
CMU_LF_ClockPrecisionGet(CMU_Clock_TypeDef clock)9774 uint16_t CMU_LF_ClockPrecisionGet(CMU_Clock_TypeDef clock)
9775 {
9776 CMU_Select_TypeDef src = CMU_ClockSelectGet(clock);
9777 uint16_t precision;
9778
9779 switch (src) {
9780 case cmuSelect_LFXO:
9781 precision = lfxo_precision;
9782 break;
9783
9784 #if defined(_SILICON_LABS_32B_SERIES_1) && defined(PLFRCO_PRESENT)
9785 case cmuSelect_PLFRCO:
9786 precision = 500;
9787 break;
9788 #endif
9789
9790 default:
9791 precision = 0xFFFF;
9792 break;
9793 }
9794
9795 return precision;
9796 }
9797
9798 #if defined(CMU_OSCENCMD_DPLLEN)
9799 /**************************************************************************//**
9800 * @brief
9801 * Lock the DPLL to a given frequency.
9802 *
9803 * The frequency is given by: Fout = Fref * (N+1) / (M+1).
9804 *
9805 * @note
9806 * This function does not check if the given N & M values will actually
9807 * produce the desired target frequency. @n
9808 * N & M limitations: @n
9809 * 300 < N <= 4095 @n
9810 * 0 <= M <= 4095 @n
9811 * Any peripheral running off HFRCO should be switched to HFRCODIV2 prior to
9812 * calling this function to avoid over-clocking.
9813 *
9814 * HFCLKLE prescaler is automatically modified before updating HFRCO
9815 * based on the maximum HFLE frequency allowed.
9816 *
9817 * @param[in] init
9818 * DPLL setup parameters.
9819 *
9820 * @return
9821 * Returns false on invalid target frequency or DPLL locking error.
9822 *****************************************************************************/
CMU_DPLLLock(const CMU_DPLLInit_TypeDef * init)9823 bool CMU_DPLLLock(const CMU_DPLLInit_TypeDef *init)
9824 {
9825 int index = 0;
9826 unsigned int i;
9827 bool hfrcoDiv2override = false;
9828 uint32_t hfrcoCtrlVal, lockStatus, sysFreq;
9829
9830 EFM_ASSERT(init->frequency >= hfrcoCtrlTable[0].minFreq);
9831 EFM_ASSERT(init->frequency
9832 <= hfrcoCtrlTable[HFRCOCTRLTABLE_ENTRIES - 1U].maxFreq);
9833 EFM_ASSERT(init->n > 300U);
9834 EFM_ASSERT(init->n <= (_CMU_DPLLCTRL1_N_MASK >> _CMU_DPLLCTRL1_N_SHIFT));
9835 EFM_ASSERT(init->m <= (_CMU_DPLLCTRL1_M_MASK >> _CMU_DPLLCTRL1_M_SHIFT));
9836 EFM_ASSERT(init->ssInterval <= (_CMU_HFRCOSS_SSINV_MASK
9837 >> _CMU_HFRCOSS_SSINV_SHIFT));
9838 EFM_ASSERT(init->ssAmplitude <= (_CMU_HFRCOSS_SSAMP_MASK
9839 >> _CMU_HFRCOSS_SSAMP_SHIFT));
9840
9841 #if defined(_EMU_STATUS_VSCALE_MASK)
9842 if ((EMU_VScaleGet() == emuVScaleEM01_LowPower)
9843 && (init->frequency > CMU_VSCALEEM01_LOWPOWER_VOLTAGE_CLOCK_MAX)) {
9844 EFM_ASSERT(false);
9845 return false;
9846 }
9847 #endif
9848
9849 // Find the correct HFRCO band and retrieve a HFRCOCTRL value.
9850 for (i = 0; i < HFRCOCTRLTABLE_ENTRIES; i++) {
9851 if ((init->frequency >= hfrcoCtrlTable[i].minFreq)
9852 && (init->frequency <= hfrcoCtrlTable[i].maxFreq)) {
9853 index = (int)i; // Correct band found
9854 break;
9855 }
9856 }
9857 if ((uint32_t)index == HFRCOCTRLTABLE_ENTRIES) {
9858 EFM_ASSERT(false);
9859 return false; // Target frequency out of spec.
9860 }
9861 hfrcoCtrlVal = hfrcoCtrlTable[index].value;
9862
9863 // Check if a calibrated HFRCOCTRL.TUNING value is in device DI page.
9864 if (hfrcoCtrlTable[index].band != (CMU_HFRCOFreq_TypeDef)0) {
9865 uint32_t tuning;
9866
9867 tuning = (CMU_HFRCODevinfoGet(hfrcoCtrlTable[index].band)
9868 & _CMU_HFRCOCTRL_TUNING_MASK)
9869 >> _CMU_HFRCOCTRL_TUNING_SHIFT;
9870
9871 // When HFRCOCTRL.FINETUNINGEN is enabled, the center frequency
9872 // of the band shifts down by 5.8%. 9 is subtracted to compensate.
9873 if (tuning > 9UL) {
9874 tuning -= 9UL;
9875 } else {
9876 tuning = 0UL;
9877 }
9878
9879 hfrcoCtrlVal |= tuning << _CMU_HFRCOCTRL_TUNING_SHIFT;
9880 }
9881
9882 // Update the CMSIS frequency SystemHfrcoFreq value.
9883 SystemHfrcoFreq = init->frequency;
9884
9885 // Set maximum wait-states while changing the core clock.
9886 if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) {
9887 flashWaitStateMax();
9888 }
9889
9890 // Update the HFLE configuration before updating HFRCO, use new DPLL frequency.
9891 if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) {
9892 setHfLeConfig(init->frequency);
9893
9894 // Switch to HFRCO/2 before setting DPLL to avoid over-clocking.
9895 hfrcoDiv2override = true;
9896 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFRCODIV2;
9897 }
9898
9899 CMU->OSCENCMD = CMU_OSCENCMD_DPLLDIS;
9900 while ((CMU->STATUS & (CMU_STATUS_DPLLENS | CMU_STATUS_DPLLRDY)) != 0UL) {
9901 }
9902 CMU->IFC = CMU_IFC_DPLLRDY | CMU_IFC_DPLLLOCKFAILLOW
9903 | CMU_IFC_DPLLLOCKFAILHIGH;
9904 CMU->DPLLCTRL1 = ((uint32_t)init->n << _CMU_DPLLCTRL1_N_SHIFT)
9905 | ((uint32_t)init->m << _CMU_DPLLCTRL1_M_SHIFT);
9906 CMU->HFRCOCTRL = hfrcoCtrlVal;
9907 CMU->DPLLCTRL = ((uint32_t)init->refClk << _CMU_DPLLCTRL_REFSEL_SHIFT)
9908 | ((init->autoRecover ? 1UL : 0UL)
9909 << _CMU_DPLLCTRL_AUTORECOVER_SHIFT)
9910 | ((uint32_t)init->edgeSel << _CMU_DPLLCTRL_EDGESEL_SHIFT)
9911 | ((uint32_t)init->lockMode << _CMU_DPLLCTRL_MODE_SHIFT);
9912 CMU->OSCENCMD = CMU_OSCENCMD_DPLLEN;
9913 while ((lockStatus = (CMU->IF & (CMU_IF_DPLLRDY
9914 | CMU_IF_DPLLLOCKFAILLOW
9915 | CMU_IF_DPLLLOCKFAILHIGH))) == 0UL) {
9916 }
9917
9918 // Restore to HFRCO
9919 if ((CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCODIV2)
9920 && (hfrcoDiv2override == true)) {
9921 CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFRCO;
9922 }
9923
9924 // If HFRCO is selected as an HF clock, optimize the flash access wait-state
9925 // configuration for this frequency and update the CMSIS core clock variable.
9926 if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) {
9927 // Call @ref SystemCoreClockGet() to update the CMSIS core clock variable.
9928 sysFreq = SystemCoreClockGet();
9929 EFM_ASSERT(sysFreq <= init->frequency);
9930 EFM_ASSERT(sysFreq <= SystemHfrcoFreq);
9931 EFM_ASSERT(init->frequency == SystemHfrcoFreq);
9932 CMU_UpdateWaitStates(sysFreq, VSCALE_DEFAULT);
9933 }
9934
9935 // Reduce HFLE frequency if possible.
9936 setHfLeConfig(SystemHFClockGet());
9937
9938 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
9939 // Update voltage scaling.
9940 EMU_VScaleEM01ByClock(0, true);
9941 #endif
9942
9943 if (lockStatus == CMU_IF_DPLLRDY) {
9944 return true;
9945 }
9946 return false;
9947 }
9948 #endif // CMU_OSCENCMD_DPLLEN
9949
9950 /**************************************************************************//**
9951 * @brief
9952 * CMU low frequency register synchronization freeze control.
9953 *
9954 * @details
9955 * Some CMU registers require synchronization into the low-frequency (LF)
9956 * domain. The freeze feature allows for several such registers to be
9957 * modified before passing them to the LF domain simultaneously (which
9958 * takes place when the freeze mode is disabled).
9959 *
9960 * Another use case for this feature is using an API (such
9961 * as the CMU API) for modifying several bit fields consecutively in the
9962 * same register. If freeze mode is enabled during this sequence, stalling
9963 * can be avoided.
9964 *
9965 * @note
9966 * When enabling freeze mode, this function will wait for all current
9967 * ongoing CMU synchronization to LF domain to complete (normally
9968 * synchronization will not be in progress.) However, for this reason, when
9969 * using freeze mode, modifications of registers requiring LF synchronization
9970 * should be done within one freeze enable/disable block to avoid unnecessary
9971 * stalling.
9972 *
9973 * @param[in] enable
9974 * @li true - enable freeze, modified registers are not propagated to the
9975 * LF domain
9976 * @li false - disable freeze, modified registers are propagated to the LF
9977 * domain
9978 *****************************************************************************/
CMU_FreezeEnable(bool enable)9979 void CMU_FreezeEnable(bool enable)
9980 {
9981 if (enable) {
9982 /* Wait for any ongoing LF synchronizations to complete. This */
9983 /* protects against the rare case when a user */
9984 /* - modifies a register requiring LF sync */
9985 /* - then enables freeze before LF sync completed */
9986 /* - then modifies the same register again */
9987 /* since modifying a register while it is in sync progress should be */
9988 /* avoided. */
9989 while (CMU->SYNCBUSY != 0UL) {
9990 }
9991
9992 CMU->FREEZE = CMU_FREEZE_REGFREEZE;
9993 } else {
9994 CMU->FREEZE = 0;
9995 }
9996 }
9997
9998 #if defined(_CMU_HFRCOCTRL_BAND_MASK)
9999 /***************************************************************************//**
10000 * @brief
10001 * Get HFRCO band in use.
10002 *
10003 * @return
10004 * HFRCO band in use.
10005 ******************************************************************************/
CMU_HFRCOBandGet(void)10006 CMU_HFRCOBand_TypeDef CMU_HFRCOBandGet(void)
10007 {
10008 return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK)
10009 >> _CMU_HFRCOCTRL_BAND_SHIFT);
10010 }
10011 #endif /* _CMU_HFRCOCTRL_BAND_MASK */
10012
10013 #if defined(_CMU_HFRCOCTRL_BAND_MASK)
10014 /***************************************************************************//**
10015 * @brief
10016 * Set HFRCO band and the tuning value based on the value in the calibration
10017 * table made during production.
10018 *
10019 * @note
10020 * HFCLKLE prescaler is automatically modified based on the maximum
10021 * HFLE frequency allowed.
10022 *
10023 * @param[in] band
10024 * HFRCO band to activate.
10025 ******************************************************************************/
CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)10026 void CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)
10027 {
10028 uint32_t tuning;
10029 uint32_t freq;
10030 CMU_Select_TypeDef osc;
10031
10032 /* Read the tuning value from the calibration table. */
10033 switch (band) {
10034 case cmuHFRCOBand_1MHz:
10035 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK)
10036 >> _DEVINFO_HFRCOCAL0_BAND1_SHIFT;
10037 break;
10038
10039 case cmuHFRCOBand_7MHz:
10040 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK)
10041 >> _DEVINFO_HFRCOCAL0_BAND7_SHIFT;
10042 break;
10043
10044 case cmuHFRCOBand_11MHz:
10045 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK)
10046 >> _DEVINFO_HFRCOCAL0_BAND11_SHIFT;
10047 break;
10048
10049 case cmuHFRCOBand_14MHz:
10050 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK)
10051 >> _DEVINFO_HFRCOCAL0_BAND14_SHIFT;
10052 break;
10053
10054 case cmuHFRCOBand_21MHz:
10055 tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK)
10056 >> _DEVINFO_HFRCOCAL1_BAND21_SHIFT;
10057 break;
10058
10059 #if defined(_CMU_HFRCOCTRL_BAND_28MHZ)
10060 case cmuHFRCOBand_28MHz:
10061 tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK)
10062 >> _DEVINFO_HFRCOCAL1_BAND28_SHIFT;
10063 break;
10064 #endif
10065
10066 default:
10067 EFM_ASSERT(false);
10068 return;
10069 }
10070
10071 /* If HFRCO is used for the core clock, flash access WS has to be considered. */
10072 osc = CMU_ClockSelectGet(cmuClock_HF);
10073 if (osc == cmuSelect_HFRCO) {
10074 /* Configure worst case wait states for flash access before setting the divider. */
10075 flashWaitStateMax();
10076 }
10077
10078 /* Set band/tuning. */
10079 CMU->HFRCOCTRL = (CMU->HFRCOCTRL
10080 & ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK))
10081 | (band << _CMU_HFRCOCTRL_BAND_SHIFT)
10082 | (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT);
10083
10084 /* If HFRCO is used for the core clock, optimize flash WS. */
10085 if (osc == cmuSelect_HFRCO) {
10086 /* Call @ref SystemCoreClockGet() to update the CMSIS core clock variable. */
10087 freq = SystemCoreClockGet();
10088 CMU_UpdateWaitStates(freq, VSCALE_DEFAULT);
10089 }
10090
10091 #if defined(CMU_MAX_FREQ_HFLE)
10092 /* Reduce HFLE frequency if possible. */
10093 setHfLeConfig(SystemCoreClockGet());
10094 #endif
10095 }
10096 #endif /* _CMU_HFRCOCTRL_BAND_MASK */
10097
10098 #if defined(_CMU_HFRCOCTRL_FREQRANGE_MASK)
10099 /**************************************************************************//**
10100 * @brief
10101 * Get the HFRCO frequency calibration word in DEVINFO.
10102 *
10103 * @param[in] freq
10104 * Frequency in Hz.
10105 *
10106 * @return
10107 * HFRCO calibration word for a given frequency.
10108 *****************************************************************************/
CMU_HFRCODevinfoGet(CMU_HFRCOFreq_TypeDef freq)10109 static uint32_t CMU_HFRCODevinfoGet(CMU_HFRCOFreq_TypeDef freq)
10110 {
10111 switch (freq) {
10112 /* 1, 2, and 4 MHz share the same calibration word. */
10113 case cmuHFRCOFreq_1M0Hz:
10114 case cmuHFRCOFreq_2M0Hz:
10115 case cmuHFRCOFreq_4M0Hz:
10116 return DEVINFO->HFRCOCAL0;
10117
10118 case cmuHFRCOFreq_7M0Hz:
10119 return DEVINFO->HFRCOCAL3;
10120
10121 case cmuHFRCOFreq_13M0Hz:
10122 return DEVINFO->HFRCOCAL6;
10123
10124 case cmuHFRCOFreq_16M0Hz:
10125 return DEVINFO->HFRCOCAL7;
10126
10127 case cmuHFRCOFreq_19M0Hz:
10128 return DEVINFO->HFRCOCAL8;
10129
10130 case cmuHFRCOFreq_26M0Hz:
10131 return DEVINFO->HFRCOCAL10;
10132
10133 case cmuHFRCOFreq_32M0Hz:
10134 return DEVINFO->HFRCOCAL11;
10135
10136 case cmuHFRCOFreq_38M0Hz:
10137 return DEVINFO->HFRCOCAL12;
10138
10139 #if defined(_DEVINFO_HFRCOCAL13_MASK)
10140 case cmuHFRCOFreq_48M0Hz:
10141 return DEVINFO->HFRCOCAL13;
10142 #endif
10143
10144 #if defined(_DEVINFO_HFRCOCAL14_MASK)
10145 case cmuHFRCOFreq_56M0Hz:
10146 return DEVINFO->HFRCOCAL14;
10147 #endif
10148
10149 #if defined(_DEVINFO_HFRCOCAL15_MASK)
10150 case cmuHFRCOFreq_64M0Hz:
10151 return DEVINFO->HFRCOCAL15;
10152 #endif
10153
10154 #if defined(_DEVINFO_HFRCOCAL16_MASK)
10155 case cmuHFRCOFreq_72M0Hz:
10156 return DEVINFO->HFRCOCAL16;
10157 #endif
10158
10159 default: /* cmuHFRCOFreq_UserDefined */
10160 return 0;
10161 }
10162 }
10163
10164 /***************************************************************************//**
10165 * @brief
10166 * Get the current HFRCO frequency.
10167 *
10168 * @return
10169 * HFRCO frequency.
10170 ******************************************************************************/
CMU_HFRCOBandGet(void)10171 CMU_HFRCOFreq_TypeDef CMU_HFRCOBandGet(void)
10172 {
10173 return (CMU_HFRCOFreq_TypeDef)SystemHfrcoFreq;
10174 }
10175
10176 /***************************************************************************//**
10177 * @brief
10178 * Set the HFRCO calibration for the selected target frequency.
10179 *
10180 * @note
10181 * HFCLKLE prescaler is automatically modified based on the maximum
10182 * HFLE frequency allowed.
10183 *
10184 * @param[in] setFreq
10185 * HFRCO frequency to set.
10186 ******************************************************************************/
CMU_HFRCOBandSet(CMU_HFRCOFreq_TypeDef setFreq)10187 void CMU_HFRCOBandSet(CMU_HFRCOFreq_TypeDef setFreq)
10188 {
10189 uint32_t freqCal;
10190 uint32_t sysFreq;
10191 uint32_t prevFreq;
10192
10193 /* Get the DEVINFO index and set the CMSIS frequency SystemHfrcoFreq. */
10194 freqCal = CMU_HFRCODevinfoGet(setFreq);
10195 EFM_ASSERT((freqCal != 0UL) && (freqCal != UINT_MAX));
10196 prevFreq = SystemHfrcoFreq;
10197 SystemHfrcoFreq = (uint32_t)setFreq;
10198
10199 /* Set maximum wait-states and set safe HFPER clock-tree prescalers while
10200 changing the core clock. */
10201 if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) {
10202 flashWaitStateMax();
10203 hfperClkSafePrescaler();
10204 }
10205
10206 /* Wait for any previous sync to complete and set calibration data
10207 for the selected frequency. */
10208 while (BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT) != 0UL) {
10209 }
10210
10211 /* Check for valid calibration data. */
10212 EFM_ASSERT(freqCal != UINT_MAX);
10213
10214 /* Set divider in HFRCOCTRL for 1, 2, and 4 MHz. */
10215 switch (setFreq) {
10216 case cmuHFRCOFreq_1M0Hz:
10217 freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)
10218 | CMU_HFRCOCTRL_CLKDIV_DIV4;
10219 break;
10220
10221 case cmuHFRCOFreq_2M0Hz:
10222 freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)
10223 | CMU_HFRCOCTRL_CLKDIV_DIV2;
10224 break;
10225
10226 case cmuHFRCOFreq_4M0Hz:
10227 freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)
10228 | CMU_HFRCOCTRL_CLKDIV_DIV1;
10229 break;
10230
10231 default:
10232 break;
10233 }
10234
10235 /* Update HFLE configuration before updating HFRCO.
10236 Use the new set frequency. */
10237 if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) {
10238 /* setFreq is worst-case as dividers may reduce the HFLE frequency. */
10239 setHfLeConfig((uint32_t)setFreq);
10240 }
10241
10242 if ((uint32_t)setFreq > prevFreq) {
10243 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
10244 /* When increasing frequency voltage scale must be done before the change. */
10245 EMU_VScaleEM01ByClock((uint32_t)setFreq, true);
10246 #endif
10247 }
10248
10249 CMU->HFRCOCTRL = freqCal;
10250
10251 /* If HFRCO is selected as an HF clock, optimize the flash access wait-state configuration
10252 for this frequency and update the CMSIS core clock variable. */
10253 if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) {
10254 /* Call @ref SystemCoreClockGet() to update the CMSIS core clock variable. */
10255 sysFreq = SystemCoreClockGet();
10256 EFM_ASSERT(sysFreq <= (uint32_t)setFreq);
10257 EFM_ASSERT(sysFreq <= SystemHfrcoFreq);
10258 EFM_ASSERT((uint32_t)setFreq == SystemHfrcoFreq);
10259 CMU_UpdateWaitStates(sysFreq, VSCALE_DEFAULT);
10260 }
10261
10262 /* Reduce HFLE frequency if possible. */
10263 setHfLeConfig(SystemHFClockGet());
10264
10265 if ((uint32_t)setFreq <= prevFreq) {
10266 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
10267 /* When decreasing frequency voltage scale must be done after the change */
10268 EMU_VScaleEM01ByClock(0, true);
10269 #endif
10270 }
10271 if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) {
10272 /* Set optimized HFPER clock-tree prescalers. */
10273 hfperClkOptimizedPrescaler();
10274 }
10275 }
10276 #endif /* _CMU_HFRCOCTRL_FREQRANGE_MASK */
10277
10278 #if defined(_CMU_HFRCOCTRL_SUDELAY_MASK)
10279 /***************************************************************************//**
10280 * @brief
10281 * Get the HFRCO startup delay.
10282 *
10283 * @details
10284 * See the reference manual for more details.
10285 *
10286 * @return
10287 * The startup delay in use.
10288 ******************************************************************************/
CMU_HFRCOStartupDelayGet(void)10289 uint32_t CMU_HFRCOStartupDelayGet(void)
10290 {
10291 return (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK)
10292 >> _CMU_HFRCOCTRL_SUDELAY_SHIFT;
10293 }
10294
10295 /***************************************************************************//**
10296 * @brief
10297 * Set the HFRCO startup delay.
10298 *
10299 * @details
10300 * See the reference manual for more details.
10301 *
10302 * @param[in] delay
10303 * The startup delay to set (<= 31).
10304 ******************************************************************************/
CMU_HFRCOStartupDelaySet(uint32_t delay)10305 void CMU_HFRCOStartupDelaySet(uint32_t delay)
10306 {
10307 EFM_ASSERT(delay <= 31);
10308
10309 delay &= _CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT;
10310 CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK))
10311 | (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT);
10312 }
10313 #endif
10314
10315 #if defined(_CMU_USHFRCOCTRL_FREQRANGE_MASK)
10316 /**************************************************************************//**
10317 * @brief
10318 * Get the USHFRCO frequency calibration word in DEVINFO.
10319 *
10320 * @param[in] freq
10321 * Frequency in Hz.
10322 *
10323 * @return
10324 * USHFRCO calibration word for a given frequency.
10325 *****************************************************************************/
CMU_USHFRCODevinfoGet(CMU_USHFRCOFreq_TypeDef freq)10326 static uint32_t CMU_USHFRCODevinfoGet(CMU_USHFRCOFreq_TypeDef freq)
10327 {
10328 switch (freq) {
10329 case cmuUSHFRCOFreq_16M0Hz:
10330 return DEVINFO->USHFRCOCAL7;
10331
10332 case cmuUSHFRCOFreq_32M0Hz:
10333 return DEVINFO->USHFRCOCAL11;
10334
10335 case cmuUSHFRCOFreq_48M0Hz:
10336 return DEVINFO->USHFRCOCAL13;
10337
10338 case cmuUSHFRCOFreq_50M0Hz:
10339 return DEVINFO->USHFRCOCAL14;
10340
10341 default: /* cmuUSHFRCOFreq_UserDefined */
10342 return 0;
10343 }
10344 }
10345
10346 /***************************************************************************//**
10347 * @brief
10348 * Get the current USHFRCO frequency.
10349 *
10350 * @return
10351 * HFRCO frequency.
10352 ******************************************************************************/
CMU_USHFRCOBandGet(void)10353 CMU_USHFRCOFreq_TypeDef CMU_USHFRCOBandGet(void)
10354 {
10355 return (CMU_USHFRCOFreq_TypeDef) ushfrcoFreq;
10356 }
10357
10358 /***************************************************************************//**
10359 * @brief
10360 * Get USHFRCO frequency.
10361 *
10362 * @return
10363 * USHFRCO frequency.
10364 ******************************************************************************/
CMU_USHFRCOFreqGet(void)10365 uint32_t CMU_USHFRCOFreqGet(void)
10366 {
10367 return ushfrcoFreq;
10368 }
10369
10370 /***************************************************************************//**
10371 * @brief
10372 * Set the USHFRCO calibration for the selected target frequency.
10373 *
10374 * @param[in] setFreq
10375 * USHFRCO frequency to set.
10376 ******************************************************************************/
CMU_USHFRCOBandSet(CMU_USHFRCOFreq_TypeDef setFreq)10377 void CMU_USHFRCOBandSet(CMU_USHFRCOFreq_TypeDef setFreq)
10378 {
10379 uint32_t freqCal;
10380
10381 /* Get DEVINFO calibration values. */
10382 freqCal = CMU_USHFRCODevinfoGet(setFreq);
10383 EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX));
10384 ushfrcoFreq = (uint32_t)setFreq;
10385
10386 /* Wait for any previous sync to complete and set calibration data
10387 for the selected frequency. */
10388 while (BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_USHFRCOBSY_SHIFT)) ;
10389
10390 CMU->USHFRCOCTRL = freqCal;
10391 }
10392 #endif /* _CMU_USHFRCOCTRL_FREQRANGE_MASK */
10393
10394 #if defined(_CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK)
10395 /***************************************************************************//**
10396 * @brief
10397 * Enable or disable HFXO autostart.
10398 *
10399 * @param[in] userSel
10400 * Additional user specified enable bit.
10401 *
10402 * @param[in] enEM0EM1Start
10403 * If true, HFXO is automatically started upon entering EM0/EM1 entry from
10404 * EM2/EM3. HFXO selection has to be handled by the user.
10405 * If false, HFXO is not started automatically when entering EM0/EM1.
10406 *
10407 * @param[in] enEM0EM1StartSel
10408 * If true, HFXO is automatically started and immediately selected upon
10409 * entering EM0/EM1 entry from EM2/EM3. Note that this option stalls the use of
10410 * HFSRCCLK until HFXO becomes ready. HFCLKLE prescaler is also automatically
10411 * modified if userSel is specified.
10412 * If false, HFXO is not started or selected automatically when entering
10413 * EM0/EM1.
10414 ******************************************************************************/
CMU_HFXOAutostartEnable(uint32_t userSel,bool enEM0EM1Start,bool enEM0EM1StartSel)10415 void CMU_HFXOAutostartEnable(uint32_t userSel,
10416 bool enEM0EM1Start,
10417 bool enEM0EM1StartSel)
10418 {
10419 uint32_t hfxoFreq;
10420 uint32_t hfxoCtrl;
10421
10422 #if defined(_EMU_CTRL_EM23VSCALE_MASK)
10423 if (enEM0EM1StartSel) {
10424 /* Voltage scaling is not compatible with HFXO auto start and select. */
10425 EFM_ASSERT((EMU->CTRL & _EMU_CTRL_EM23VSCALE_MASK) == EMU_CTRL_EM23VSCALE_VSCALE2);
10426 }
10427 #endif
10428
10429 /* Mask supported enable bits. */
10430 #if defined(_CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK)
10431 userSel &= _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK;
10432 #else
10433 userSel = 0;
10434 #endif
10435
10436 hfxoFreq = SystemHFXOClockGet();
10437 #if defined(_EMU_CMD_EM01VSCALE0_MASK)
10438 // Update voltage scaling.
10439 EMU_VScaleEM01ByClock(hfxoFreq, true);
10440 #endif
10441 /* Set wait-states for HFXO if automatic start and select is configured. */
10442 if ((userSel > 0UL) || enEM0EM1StartSel) {
10443 CMU_UpdateWaitStates(hfxoFreq, VSCALE_DEFAULT);
10444 setHfLeConfig(hfxoFreq / CMU_ClockDivGet(cmuClock_HF));
10445 }
10446
10447 if (enEM0EM1Start || enEM0EM1StartSel) {
10448 /* Enable the HFXO once in order to finish first time calibrations. */
10449 CMU_OscillatorEnable(cmuOsc_HFXO, true, true);
10450 }
10451
10452 /* Since call to CMU_OscillatorEnable() can change the CMU->HFXOCTRL register,
10453 * it's important to read the CMU->HFXOCTRL register after the call to CMU_OscillatorEnable(). */
10454 hfxoCtrl = CMU->HFXOCTRL & ~(userSel
10455 | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK
10456 | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK);
10457
10458 hfxoCtrl |= userSel
10459 | (enEM0EM1Start ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0UL)
10460 | (enEM0EM1StartSel ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0UL);
10461
10462 /* Update HFXOCTRL after wait-states are updated as HF may automatically switch
10463 to HFXO when automatic select is enabled . */
10464 CMU->HFXOCTRL = hfxoCtrl;
10465 }
10466 #endif
10467
10468 /**************************************************************************//**
10469 * @brief
10470 * Set HFXO control registers.
10471 *
10472 * @note
10473 * HFXO configuration should be obtained from a configuration tool,
10474 * app note, or crystal data sheet. This function disables the HFXO to
10475 * ensure a valid state before update.
10476 *
10477 * @param[in] hfxoInit
10478 * HFXO setup parameters.
10479 *****************************************************************************/
CMU_HFXOInit(const CMU_HFXOInit_TypeDef * hfxoInit)10480 void CMU_HFXOInit(const CMU_HFXOInit_TypeDef *hfxoInit)
10481 {
10482 /* Do not disable HFXO if it is currently selected as the HF/Core clock. */
10483 EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_HFXO);
10484
10485 /* HFXO must be disabled before reconfiguration. */
10486 CMU_OscillatorEnable(cmuOsc_HFXO, false, true);
10487
10488 #if defined(_SILICON_LABS_32B_SERIES_1) \
10489 && (_SILICON_LABS_GECKO_INTERNAL_SDID >= 100)
10490 uint32_t tmp = CMU_HFXOCTRL_MODE_XTAL;
10491
10492 switch (hfxoInit->mode) {
10493 case cmuOscMode_Crystal:
10494 tmp = CMU_HFXOCTRL_MODE_XTAL;
10495 break;
10496 case cmuOscMode_External:
10497 tmp = CMU_HFXOCTRL_MODE_DIGEXTCLK;
10498 break;
10499 case cmuOscMode_AcCoupled:
10500 tmp = CMU_HFXOCTRL_MODE_ACBUFEXTCLK;
10501 break;
10502 default:
10503 EFM_ASSERT(false); /* Unsupported configuration */
10504 break;
10505 }
10506 CMU->HFXOCTRL = (CMU->HFXOCTRL & ~_CMU_HFXOCTRL_MODE_MASK) | tmp;
10507
10508 #if defined(CMU_HFXOCTRL_HFXOX2EN)
10509 /* HFXO Doubler can only be enabled on crystals up to max 25 MHz. */
10510 tmp = 0;
10511 if (SystemHFXOClockGet() <= 25000000) {
10512 tmp |= CMU_HFXOCTRL_HFXOX2EN;
10513 }
10514
10515 CMU->HFXOCTRL = (CMU->HFXOCTRL & ~_CMU_HFXOCTRL_HFXOX2EN_MASK) | tmp;
10516 #endif
10517
10518 /* Set tuning for startup and steady state. */
10519 CMU->HFXOSTARTUPCTRL = (hfxoInit->ctuneStartup
10520 << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT)
10521 | (hfxoInit->xoCoreBiasTrimStartup
10522 << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT);
10523
10524 CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL
10525 & ~(_CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK
10526 | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK))
10527 | (hfxoInit->ctuneSteadyState
10528 << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT)
10529 | (hfxoInit->xoCoreBiasTrimSteadyState
10530 << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT);
10531
10532 /* Set timeouts */
10533 CMU->HFXOTIMEOUTCTRL = (hfxoInit->timeoutPeakDetect
10534 << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT)
10535 | (hfxoInit->timeoutSteady
10536 << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT)
10537 | (hfxoInit->timeoutStartup
10538 << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT);
10539
10540 #elif defined(_CMU_HFXOCTRL_MASK)
10541 /* Verify that the deprecated autostart fields are not used,
10542 * @ref CMU_HFXOAutostartEnable must be used instead. */
10543 EFM_ASSERT(!(hfxoInit->autoStartEm01
10544 || hfxoInit->autoSelEm01
10545 || hfxoInit->autoStartSelOnRacWakeup));
10546
10547 uint32_t tmp = CMU_HFXOCTRL_MODE_XTAL;
10548
10549 /* AC coupled external clock not supported. */
10550 EFM_ASSERT(hfxoInit->mode != cmuOscMode_AcCoupled);
10551 if (hfxoInit->mode == cmuOscMode_External) {
10552 tmp = CMU_HFXOCTRL_MODE_DIGEXTCLK;
10553 }
10554
10555 /* Apply control settings. */
10556 CMU->HFXOCTRL = (CMU->HFXOCTRL & ~_CMU_HFXOCTRL_MODE_MASK)
10557 | tmp;
10558 BUS_RegBitWrite(&CMU->HFXOCTRL,
10559 _CMU_HFXOCTRL_LOWPOWER_SHIFT,
10560 (unsigned)hfxoInit->lowPowerMode);
10561
10562 /* Set XTAL tuning parameters. */
10563
10564 #if defined(_CMU_HFXOCTRL1_PEAKDETTHR_MASK)
10565 /* Set peak detection threshold. */
10566 CMU->HFXOCTRL1 = (CMU->HFXOCTRL1 & ~_CMU_HFXOCTRL1_PEAKDETTHR_MASK)
10567 | (hfxoInit->thresholdPeakDetect
10568 << _CMU_HFXOCTRL1_PEAKDETTHR_SHIFT);
10569 #endif
10570 /* Set tuning for startup and steady state. */
10571 CMU->HFXOSTARTUPCTRL = ((uint32_t)hfxoInit->ctuneStartup
10572 << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT)
10573 | ((uint32_t)hfxoInit->xoCoreBiasTrimStartup
10574 << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT);
10575
10576 CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL
10577 & ~(_CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK
10578 | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK
10579 | _CMU_HFXOSTEADYSTATECTRL_REGISH_MASK
10580 | _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK))
10581 | ((uint32_t)hfxoInit->ctuneSteadyState
10582 << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT)
10583 | ((uint32_t)hfxoInit->xoCoreBiasTrimSteadyState
10584 << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT)
10585 | ((uint32_t)hfxoInit->regIshSteadyState
10586 << _CMU_HFXOSTEADYSTATECTRL_REGISH_SHIFT)
10587 | getRegIshUpperVal(hfxoInit->regIshSteadyState);
10588
10589 /* Set timeouts. */
10590 CMU->HFXOTIMEOUTCTRL = ((uint32_t)hfxoInit->timeoutPeakDetect
10591 << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT)
10592 | ((uint32_t)hfxoInit->timeoutSteady
10593 << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT)
10594 | ((uint32_t)hfxoInit->timeoutStartup
10595 << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT)
10596 | ((uint32_t)hfxoInit->timeoutShuntOptimization
10597 << _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_SHIFT);
10598
10599 #else
10600 CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_HFXOTIMEOUT_MASK
10601 | _CMU_CTRL_HFXOBOOST_MASK
10602 | _CMU_CTRL_HFXOMODE_MASK
10603 | _CMU_CTRL_HFXOGLITCHDETEN_MASK))
10604 | (hfxoInit->timeout << _CMU_CTRL_HFXOTIMEOUT_SHIFT)
10605 | (hfxoInit->boost << _CMU_CTRL_HFXOBOOST_SHIFT)
10606 | (hfxoInit->mode << _CMU_CTRL_HFXOMODE_SHIFT)
10607 | (hfxoInit->glitchDetector ? CMU_CTRL_HFXOGLITCHDETEN : 0);
10608 #endif
10609 }
10610
10611 /***************************************************************************//**
10612 * @brief
10613 * Get the LCD framerate divisor (FDIV) setting.
10614 *
10615 * @return
10616 * The LCD framerate divisor.
10617 ******************************************************************************/
CMU_LCDClkFDIVGet(void)10618 uint32_t CMU_LCDClkFDIVGet(void)
10619 {
10620 #if defined(LCD_PRESENT) && defined(_CMU_LCDCTRL_MASK)
10621 return (CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT;
10622 #else
10623 return 0;
10624 #endif /* defined(LCD_PRESENT) */
10625 }
10626
10627 /***************************************************************************//**
10628 * @brief
10629 * Set the LCD framerate divisor (FDIV) setting.
10630 *
10631 * @note
10632 * The FDIV field (CMU LCDCTRL register) should only be modified while the
10633 * LCD module is clock disabled (CMU LFACLKEN0.LCD bit is 0). This function
10634 * will NOT modify FDIV if the LCD module clock is enabled. See
10635 * @ref CMU_ClockEnable() for disabling/enabling LCD clock.
10636 *
10637 * @param[in] div
10638 * The FDIV setting to use.
10639 ******************************************************************************/
CMU_LCDClkFDIVSet(uint32_t div)10640 void CMU_LCDClkFDIVSet(uint32_t div)
10641 {
10642 #if defined(LCD_PRESENT) && defined(_CMU_LCDCTRL_MASK)
10643 EFM_ASSERT(div <= cmuClkDiv_128);
10644
10645 /* Do not allow modification if LCD clock enabled. */
10646 if (CMU->LFACLKEN0 & CMU_LFACLKEN0_LCD) {
10647 return;
10648 }
10649
10650 div <<= _CMU_LCDCTRL_FDIV_SHIFT;
10651 div &= _CMU_LCDCTRL_FDIV_MASK;
10652 CMU->LCDCTRL = (CMU->LCDCTRL & ~_CMU_LCDCTRL_FDIV_MASK) | div;
10653 #else
10654 (void)div; /* Unused parameter. */
10655 #endif /* defined(LCD_PRESENT) */
10656 }
10657
10658 /**************************************************************************//**
10659 * @brief
10660 * Set LFXO control registers.
10661 *
10662 * @note
10663 * LFXO configuration should be obtained from a configuration tool,
10664 * app note, or crystal data sheet. This function disables the LFXO when
10665 * necessary to ensure a valid state before update.
10666 *
10667 * @param[in] lfxoInit
10668 * LFXO setup parameters.
10669 *****************************************************************************/
CMU_LFXOInit(const CMU_LFXOInit_TypeDef * lfxoInit)10670 void CMU_LFXOInit(const CMU_LFXOInit_TypeDef *lfxoInit)
10671 {
10672 /* Do not disable LFXO if it is currently selected as the HF/Core clock. */
10673 EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_LFXO);
10674
10675 #if defined(_SILICON_LABS_32B_SERIES_1)
10676 uint32_t reg = (CMU->LFXOCTRL & ~(_CMU_LFXOCTRL_TUNING_MASK
10677 | _CMU_LFXOCTRL_GAIN_MASK
10678 | _CMU_LFXOCTRL_TIMEOUT_MASK
10679 | _CMU_LFXOCTRL_MODE_MASK))
10680 | ((uint32_t)lfxoInit->ctune << _CMU_LFXOCTRL_TUNING_SHIFT)
10681 | ((uint32_t)lfxoInit->gain << _CMU_LFXOCTRL_GAIN_SHIFT)
10682 | ((uint32_t)lfxoInit->timeout << _CMU_LFXOCTRL_TIMEOUT_SHIFT)
10683 | ((uint32_t)lfxoInit->mode << _CMU_LFXOCTRL_MODE_SHIFT);
10684
10685 /* If LFXO already contains the correct configuration then there is no need
10686 * to stop the oscillator and apply new settings. The LFXO can be running out
10687 * of reset, in which case there is no need to disable it unless necessary. */
10688 if (reg != CMU->LFXOCTRL) {
10689 CMU_OscillatorEnable(cmuOsc_LFXO, false, true);
10690 CMU->LFXOCTRL = reg;
10691 }
10692 #elif defined(_SILICON_LABS_32B_SERIES_0)
10693 /* LFXO must be disabled before reconfiguration. */
10694 CMU_OscillatorEnable(cmuOsc_LFXO, false, true);
10695
10696 bool cmuBoost = (lfxoInit->boost & 0x2);
10697 BUS_RegMaskedWrite(&CMU->CTRL,
10698 _CMU_CTRL_LFXOTIMEOUT_MASK
10699 | _CMU_CTRL_LFXOBOOST_MASK
10700 | _CMU_CTRL_LFXOMODE_MASK,
10701 ((uint32_t)lfxoInit->timeout
10702 << _CMU_CTRL_LFXOTIMEOUT_SHIFT)
10703 | ((cmuBoost ? 1 : 0) << _CMU_CTRL_LFXOBOOST_SHIFT)
10704 | ((uint32_t)lfxoInit->mode << _CMU_CTRL_LFXOMODE_SHIFT));
10705 #if defined(_EMU_AUXCTRL_REDLFXOBOOST_MASK)
10706 /* EFM32GG has a "reduce startup boost" field in the EMU */
10707 bool emuReduce = (lfxoInit->boost & 0x1);
10708 BUS_RegBitWrite(&EMU->AUXCTRL, _EMU_AUXCTRL_REDLFXOBOOST_SHIFT, emuReduce ? 1 : 0);
10709 #endif
10710 #endif
10711 }
10712
10713 /**************************************************************************//**
10714 * @brief
10715 * Sets LFXO's crystal precision, in PPM.
10716 *
10717 * @note
10718 * LFXO precision should be obtained from a crystal datasheet.
10719 *
10720 * @param[in] precision
10721 * LFXO's crystal precision, in PPM.
10722 *****************************************************************************/
CMU_LFXOPrecisionSet(uint16_t precision)10723 void CMU_LFXOPrecisionSet(uint16_t precision)
10724 {
10725 lfxo_precision = precision;
10726 }
10727
10728 /**************************************************************************//**
10729 * @brief
10730 * Gets LFXO's crystal precision, in PPM.
10731 *
10732 * @param[in] precision
10733 * LFXO's crystal precision, in PPM.
10734 *****************************************************************************/
CMU_LFXOPrecisionGet(void)10735 uint16_t CMU_LFXOPrecisionGet(void)
10736 {
10737 return lfxo_precision;
10738 }
10739
10740 /***************************************************************************//**
10741 * @brief
10742 * Enable/disable oscillator.
10743 *
10744 * @note
10745 * WARNING: When this function is called to disable either cmuOsc_LFXO or
10746 * cmuOsc_HFXO, the LFXOMODE or HFXOMODE fields of the CMU_CTRL register
10747 * are reset to the reset value. In other words, if external clock sources are selected
10748 * in either LFXOMODE or HFXOMODE fields, the configuration will be cleared
10749 * and needs to be reconfigured if needed later.
10750 *
10751 * @param[in] osc
10752 * The oscillator to enable/disable.
10753 *
10754 * @param[in] enable
10755 * @li true - enable specified oscillator.
10756 * @li false - disable specified oscillator.
10757 *
10758 * @param[in] wait
10759 * Only used if @p enable is true.
10760 * @li true - wait for oscillator start-up time to timeout before returning.
10761 * @li false - do not wait for oscillator start-up time to timeout before
10762 * returning.
10763 ******************************************************************************/
CMU_OscillatorEnable(CMU_Osc_TypeDef osc,bool enable,bool wait)10764 void CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait)
10765 {
10766 uint32_t rdyBitPos;
10767 #if defined(_SILICON_LABS_32B_SERIES_1)
10768 uint32_t ensBitPos;
10769 #endif
10770 #if defined(_CMU_STATUS_HFXOPEAKDETRDY_MASK)
10771 uint32_t hfxoTrimStatus;
10772 #endif
10773
10774 uint32_t enBit;
10775 uint32_t disBit;
10776
10777 switch (osc) {
10778 case cmuOsc_HFRCO:
10779 enBit = CMU_OSCENCMD_HFRCOEN;
10780 disBit = CMU_OSCENCMD_HFRCODIS;
10781 rdyBitPos = _CMU_STATUS_HFRCORDY_SHIFT;
10782 #if defined(_SILICON_LABS_32B_SERIES_1)
10783 ensBitPos = _CMU_STATUS_HFRCOENS_SHIFT;
10784 #endif
10785 break;
10786
10787 case cmuOsc_HFXO:
10788 enBit = CMU_OSCENCMD_HFXOEN;
10789 disBit = CMU_OSCENCMD_HFXODIS;
10790 rdyBitPos = _CMU_STATUS_HFXORDY_SHIFT;
10791 #if defined(_SILICON_LABS_32B_SERIES_1)
10792 ensBitPos = _CMU_STATUS_HFXOENS_SHIFT;
10793 #endif
10794 break;
10795
10796 case cmuOsc_AUXHFRCO:
10797 enBit = CMU_OSCENCMD_AUXHFRCOEN;
10798 disBit = CMU_OSCENCMD_AUXHFRCODIS;
10799 rdyBitPos = _CMU_STATUS_AUXHFRCORDY_SHIFT;
10800 #if defined(_SILICON_LABS_32B_SERIES_1)
10801 ensBitPos = _CMU_STATUS_AUXHFRCOENS_SHIFT;
10802 #endif
10803 break;
10804
10805 case cmuOsc_LFRCO:
10806 enBit = CMU_OSCENCMD_LFRCOEN;
10807 disBit = CMU_OSCENCMD_LFRCODIS;
10808 rdyBitPos = _CMU_STATUS_LFRCORDY_SHIFT;
10809 #if defined(_SILICON_LABS_32B_SERIES_1)
10810 ensBitPos = _CMU_STATUS_LFRCOENS_SHIFT;
10811 #endif
10812 break;
10813
10814 case cmuOsc_LFXO:
10815 enBit = CMU_OSCENCMD_LFXOEN;
10816 disBit = CMU_OSCENCMD_LFXODIS;
10817 rdyBitPos = _CMU_STATUS_LFXORDY_SHIFT;
10818 #if defined(_SILICON_LABS_32B_SERIES_1)
10819 ensBitPos = _CMU_STATUS_LFXOENS_SHIFT;
10820 #endif
10821 break;
10822
10823 #if defined(_CMU_STATUS_USHFRCOENS_MASK)
10824 case cmuOsc_USHFRCO:
10825 enBit = CMU_OSCENCMD_USHFRCOEN;
10826 disBit = CMU_OSCENCMD_USHFRCODIS;
10827 rdyBitPos = _CMU_STATUS_USHFRCORDY_SHIFT;
10828 #if defined(_SILICON_LABS_32B_SERIES_1)
10829 ensBitPos = _CMU_STATUS_USHFRCOENS_SHIFT;
10830 #endif
10831 break;
10832 #endif
10833
10834 #if defined(PLFRCO_PRESENT)
10835 case cmuOsc_PLFRCO:
10836 if (!deviceHasPlfrco()) {
10837 while (true) { // PLFRCO is not available
10838 EFM_ASSERT(false);
10839 }
10840 }
10841 enBit = CMU_OSCENCMD_PLFRCOEN;
10842 disBit = CMU_OSCENCMD_PLFRCODIS;
10843 rdyBitPos = _CMU_STATUS_PLFRCORDY_SHIFT;
10844 ensBitPos = _CMU_STATUS_PLFRCOENS_SHIFT;
10845 break;
10846 #endif
10847
10848 default:
10849 /* Undefined clock source, cmuOsc_CLKIN0 or cmuOsc_ULFRCO. ULFRCO is always enabled
10850 and cannot be disabled. In other words,the definition of cmuOsc_ULFRCO is primarily
10851 intended for information: the ULFRCO is always on. */
10852 EFM_ASSERT(false);
10853 return;
10854 }
10855
10856 if (enable) {
10857 #if defined(_CMU_HFXOCTRL_MASK)
10858 bool firstHfxoEnable = false;
10859
10860 /* Enabling the HFXO for the first time requires special handling.
10861 * PEAKDETSHUTOPTMODE field of the HFXOCTRL register is used to see if this is the
10862 * first time the HFXO is enabled. */
10863 if (osc == cmuOsc_HFXO) {
10864 if (getHfxoTuningMode() == HFXO_TUNING_MODE_AUTO) {
10865 /* REGPWRSEL must be set to DVDD before the HFXO can be enabled. */
10866 #if defined(_EMU_PWRCTRL_REGPWRSEL_MASK)
10867 EFM_ASSERT((EMU->PWRCTRL & EMU_PWRCTRL_REGPWRSEL_DVDD) != 0UL);
10868 #endif
10869
10870 firstHfxoEnable = true;
10871 /* The first time that an external clock is enabled, switch to CMD mode to make sure that
10872 * only SCO and not PDA tuning is performed. */
10873 if ((CMU->HFXOCTRL & (_CMU_HFXOCTRL_MODE_MASK)) == CMU_HFXOCTRL_MODE_DIGEXTCLK) {
10874 setHfxoTuningMode(HFXO_TUNING_MODE_CMD);
10875 }
10876 }
10877 }
10878 #endif
10879 CMU->OSCENCMD = enBit;
10880
10881 #if defined(_SILICON_LABS_32B_SERIES_1)
10882 /* Always wait for ENS to go high. */
10883 while (BUS_RegBitRead(&CMU->STATUS, ensBitPos) == 0UL) {
10884 }
10885 #endif
10886
10887 /* Wait for the clock to become ready after enable. */
10888 if (wait) {
10889 while (BUS_RegBitRead(&CMU->STATUS, rdyBitPos) == 0UL) {
10890 }
10891 #if defined(_SILICON_LABS_32B_SERIES_1)
10892 if ((osc == cmuOsc_HFXO) && firstHfxoEnable) {
10893 if ((CMU->HFXOCTRL & _CMU_HFXOCTRL_MODE_MASK)
10894 == CMU_HFXOCTRL_MODE_DIGEXTCLK) {
10895 #if defined(CMU_CMD_HFXOSHUNTOPTSTART)
10896 /* External clock mode should only do shunt current optimization. */
10897 (void)CMU_OscillatorTuningOptimize(cmuOsc_HFXO,
10898 cmuHFXOTuningMode_ShuntCommand,
10899 true);
10900 #endif
10901 } else {
10902 /* Wait for the peak detection and shunt current optimization
10903 to complete. */
10904 (void)CMU_OscillatorTuningWait(cmuOsc_HFXO, cmuHFXOTuningMode_Auto);
10905 }
10906
10907 /* Disable the HFXO again to apply the trims. Apply trim from
10908 HFXOTRIMSTATUS when disabled. */
10909 hfxoTrimStatus = CMU_OscillatorTuningGet(cmuOsc_HFXO);
10910 CMU_OscillatorEnable(cmuOsc_HFXO, false, true);
10911 CMU_OscillatorTuningSet(cmuOsc_HFXO, hfxoTrimStatus);
10912
10913 /* Restart in CMD mode. */
10914 CMU->OSCENCMD = enBit;
10915 while (BUS_RegBitRead(&CMU->STATUS, rdyBitPos) == 0UL) {
10916 }
10917 }
10918 #endif
10919 }
10920 } else {
10921 CMU->OSCENCMD = disBit;
10922
10923 #if defined(_SILICON_LABS_32B_SERIES_1)
10924 /* Always wait for ENS to go low. */
10925 while ((CMU->STATUS & (0x1 << ensBitPos)) != 0U) {
10926 }
10927
10928 if (wait) {
10929 /* Wait for RDY to go low as well. */
10930 while ((CMU->STATUS & (0x1 << rdyBitPos)) != 0U) {
10931 }
10932 }
10933 #endif
10934 }
10935 }
10936
10937 /***************************************************************************//**
10938 * @brief
10939 * Get the oscillator frequency tuning setting.
10940 *
10941 * @param[in] osc
10942 * An oscillator to get tuning value for, one of the following:
10943 * @li #cmuOsc_LFRCO
10944 * @li #cmuOsc_HFRCO @if _CMU_USHFRCOCTRL_TUNING_MASK
10945 * @li #cmuOsc_USHFRCO
10946 * @endif
10947 * @li #cmuOsc_AUXHFRCO
10948 * @li #cmuOsc_HFXO if CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE is defined
10949 *
10950 * @return
10951 * The oscillator frequency tuning setting in use.
10952 ******************************************************************************/
CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)10953 uint32_t CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)
10954 {
10955 uint32_t ret;
10956
10957 switch (osc) {
10958 case cmuOsc_LFRCO:
10959 ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK)
10960 >> _CMU_LFRCOCTRL_TUNING_SHIFT;
10961 break;
10962
10963 case cmuOsc_HFRCO:
10964 ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK)
10965 >> _CMU_HFRCOCTRL_TUNING_SHIFT;
10966 break;
10967
10968 #if defined (_CMU_USHFRCOCTRL_TUNING_MASK)
10969 case cmuOsc_USHFRCO:
10970 ret = (CMU->USHFRCOCTRL & _CMU_USHFRCOCTRL_TUNING_MASK)
10971 >> _CMU_USHFRCOCTRL_TUNING_SHIFT;
10972 break;
10973 #endif
10974
10975 case cmuOsc_AUXHFRCO:
10976 ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK)
10977 >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT;
10978 break;
10979
10980 #if defined(_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)
10981 case cmuOsc_HFXO:
10982 ret = CMU->HFXOTRIMSTATUS & (_CMU_HFXOTRIMSTATUS_IBTRIMXOCORE_MASK
10983 #if defined(_CMU_HFXOTRIMSTATUS_REGISH_MASK)
10984 | _CMU_HFXOTRIMSTATUS_REGISH_MASK
10985 #endif
10986 );
10987 break;
10988 #endif
10989
10990 default:
10991 ret = 0;
10992 EFM_ASSERT(false);
10993 break;
10994 }
10995
10996 return ret;
10997 }
10998
10999 /***************************************************************************//**
11000 * @brief
11001 * Set the oscillator frequency tuning control.
11002 *
11003 * @note
11004 * Oscillator tuning is done during production and the tuning value is
11005 * automatically loaded after reset. Changing the tuning value from the
11006 * calibrated value is for more advanced use. Certain oscillators also have
11007 * build-in tuning optimization.
11008 *
11009 * @param[in] osc
11010 * An oscillator to set tuning value for, one of the following:
11011 * @li #cmuOsc_LFRCO
11012 * @li #cmuOsc_HFRCO @if _CMU_USHFRCOCTRL_TUNING_MASK
11013 * @li #cmuOsc_USHFRCO
11014 * @endif
11015 * @li #cmuOsc_AUXHFRCO
11016 * @li #cmuOsc_HFXO if PEAKDETSHUNTOPTMODE is available. Note that CMD mode is set.
11017 *
11018 * @param[in] val
11019 * The oscillator frequency tuning setting to use.
11020 ******************************************************************************/
CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc,uint32_t val)11021 void CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc, uint32_t val)
11022 {
11023 #if defined(_CMU_HFXOSTEADYSTATECTRL_REGISH_MASK)
11024 uint32_t regIshUpper;
11025 #endif
11026
11027 switch (osc) {
11028 case cmuOsc_LFRCO:
11029 EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK
11030 >> _CMU_LFRCOCTRL_TUNING_SHIFT));
11031 val &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT);
11032 #if defined(_SILICON_LABS_32B_SERIES_1)
11033 while (BUS_RegBitRead(&CMU->SYNCBUSY,
11034 _CMU_SYNCBUSY_LFRCOBSY_SHIFT) != 0UL) {
11035 }
11036 #endif
11037 CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK))
11038 | (val << _CMU_LFRCOCTRL_TUNING_SHIFT);
11039 break;
11040
11041 case cmuOsc_HFRCO:
11042 EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK
11043 >> _CMU_HFRCOCTRL_TUNING_SHIFT));
11044 val &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT);
11045 #if defined(_SILICON_LABS_32B_SERIES_1)
11046 while (BUS_RegBitRead(&CMU->SYNCBUSY,
11047 _CMU_SYNCBUSY_HFRCOBSY_SHIFT) != 0UL) {
11048 }
11049 #endif
11050 CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK))
11051 | (val << _CMU_HFRCOCTRL_TUNING_SHIFT);
11052 break;
11053
11054 #if defined (_CMU_USHFRCOCTRL_TUNING_MASK)
11055 case cmuOsc_USHFRCO:
11056 EFM_ASSERT(val <= (_CMU_USHFRCOCTRL_TUNING_MASK
11057 >> _CMU_USHFRCOCTRL_TUNING_SHIFT));
11058 val &= (_CMU_USHFRCOCTRL_TUNING_MASK >> _CMU_USHFRCOCTRL_TUNING_SHIFT);
11059 #if defined(_SILICON_LABS_32B_SERIES_1)
11060 while (BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_USHFRCOBSY_SHIFT)) {
11061 }
11062 #endif
11063 CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~(_CMU_USHFRCOCTRL_TUNING_MASK))
11064 | (val << _CMU_USHFRCOCTRL_TUNING_SHIFT);
11065 break;
11066 #endif
11067
11068 case cmuOsc_AUXHFRCO:
11069 EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK
11070 >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT));
11071 val &= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT);
11072 #if defined(_SILICON_LABS_32B_SERIES_1)
11073 while (BUS_RegBitRead(&CMU->SYNCBUSY,
11074 _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT) != 0UL) {
11075 }
11076 #endif
11077 CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK))
11078 | (val << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);
11079 break;
11080
11081 #if defined(_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)
11082 case cmuOsc_HFXO:
11083
11084 /* Do set PEAKDETSHUNTOPTMODE or HFXOSTEADYSTATECTRL if HFXO is enabled. */
11085 EFM_ASSERT((CMU->STATUS & CMU_STATUS_HFXOENS) == 0UL);
11086
11087 /* Switch to command mode. Automatic SCO and PDA calibration is not done
11088 at the next enable. Set user REGISH, REGISHUPPER, and IBTRIMXOCORE. */
11089 CMU->HFXOCTRL = (CMU->HFXOCTRL & ~_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)
11090 | CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_CMD;
11091
11092 #if defined(_CMU_HFXOSTEADYSTATECTRL_REGISH_MASK)
11093 regIshUpper = getRegIshUpperVal((val & _CMU_HFXOSTEADYSTATECTRL_REGISH_MASK)
11094 >> _CMU_HFXOSTEADYSTATECTRL_REGISH_SHIFT);
11095 CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL
11096 & ~(_CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK
11097 | _CMU_HFXOSTEADYSTATECTRL_REGISH_MASK
11098 | _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK))
11099 | val
11100 | regIshUpper;
11101 #else
11102 CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL
11103 & ~_CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK)
11104 | val;
11105 #endif
11106
11107 break;
11108 #endif
11109
11110 default:
11111 EFM_ASSERT(false);
11112 break;
11113 }
11114 }
11115
11116 #if defined(_CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK) || defined(_CMU_HFXOCTRL_PEAKDETMODE_MASK)
11117 /***************************************************************************//**
11118 * @brief
11119 * Wait for the oscillator tuning optimization.
11120 *
11121 * @param[in] osc
11122 * An oscillator to set tuning value for, one of the following:
11123 * @li #cmuOsc_HFXO
11124 *
11125 * @param[in] mode
11126 * Tuning optimization mode.
11127 *
11128 * @return
11129 * Returns false on invalid parameters or oscillator error status.
11130 ******************************************************************************/
CMU_OscillatorTuningWait(CMU_Osc_TypeDef osc,CMU_HFXOTuningMode_TypeDef mode)11131 bool CMU_OscillatorTuningWait(CMU_Osc_TypeDef osc,
11132 CMU_HFXOTuningMode_TypeDef mode)
11133 {
11134 uint32_t waitFlags;
11135 EFM_ASSERT(osc == cmuOsc_HFXO);
11136
11137 /* Currently implemented for HFXO with PEAKDETSHUNTOPTMODE only. */
11138 (void)osc;
11139
11140 if (getHfxoTuningMode() == HFXO_TUNING_MODE_AUTO) {
11141 waitFlags = HFXO_TUNING_READY_FLAGS;
11142 } else {
11143 /* Set wait flags for each command and wait. */
11144 switch (mode) {
11145 #if defined(_CMU_STATUS_HFXOSHUNTOPTRDY_MASK)
11146 case cmuHFXOTuningMode_ShuntCommand:
11147 waitFlags = CMU_STATUS_HFXOSHUNTOPTRDY;
11148 break;
11149 #endif
11150 case cmuHFXOTuningMode_Auto:
11151 waitFlags = HFXO_TUNING_READY_FLAGS;
11152 break;
11153
11154 #if defined(CMU_CMD_HFXOSHUNTOPTSTART)
11155 case cmuHFXOTuningMode_PeakShuntCommand:
11156 waitFlags = HFXO_TUNING_READY_FLAGS;
11157 break;
11158 #endif
11159
11160 default:
11161 waitFlags = _CMU_STATUS_MASK;
11162 EFM_ASSERT(false);
11163 break;
11164 }
11165 }
11166 while ((CMU->STATUS & waitFlags) != waitFlags) {
11167 }
11168
11169 #if defined(CMU_IF_HFXOPEAKDETERR)
11170 /* Check error flags. */
11171 if ((waitFlags & CMU_STATUS_HFXOPEAKDETRDY) != 0UL) {
11172 return (CMU->IF & CMU_IF_HFXOPEAKDETERR) != 0UL ? true : false;
11173 }
11174 #endif
11175 return true;
11176 }
11177
11178 /***************************************************************************//**
11179 * @brief
11180 * Start and optionally wait for the oscillator tuning optimization.
11181 *
11182 * @param[in] osc
11183 * An oscillator to set tuning value for, one of the following:
11184 * @li #cmuOsc_HFXO
11185 *
11186 * @param[in] mode
11187 * Tuning optimization mode.
11188 *
11189 * @param[in] wait
11190 * Wait for tuning optimization to complete.
11191 * true - wait for tuning optimization to complete.
11192 * false - return without waiting.
11193 *
11194 * @return
11195 * Returns false on invalid parameters or oscillator error status.
11196 ******************************************************************************/
CMU_OscillatorTuningOptimize(CMU_Osc_TypeDef osc,CMU_HFXOTuningMode_TypeDef mode,bool wait)11197 bool CMU_OscillatorTuningOptimize(CMU_Osc_TypeDef osc,
11198 CMU_HFXOTuningMode_TypeDef mode,
11199 bool wait)
11200 {
11201 switch (osc) {
11202 case cmuOsc_HFXO:
11203 if ((unsigned)mode != 0U) {
11204 #if defined(CMU_IF_HFXOPEAKDETERR)
11205 /* Clear the error flag before command write. */
11206 CMU->IFC = CMU_IFC_HFXOPEAKDETERR;
11207 #endif
11208 CMU->CMD = (uint32_t)mode;
11209 }
11210 if (wait) {
11211 return CMU_OscillatorTuningWait(osc, mode);
11212 }
11213 break;
11214
11215 default:
11216 EFM_ASSERT(false);
11217 break;
11218 }
11219 return true;
11220 }
11221 #endif
11222
11223 /**************************************************************************//**
11224 * @brief
11225 * Determine if the currently selected PCNTn clock used is external or LFBCLK.
11226 *
11227 * @param[in] instance
11228 * PCNT instance number to get currently selected clock source for.
11229 *
11230 * @return
11231 * @li true - selected clock is external clock.
11232 * @li false - selected clock is LFBCLK.
11233 *****************************************************************************/
CMU_PCNTClockExternalGet(unsigned int instance)11234 bool CMU_PCNTClockExternalGet(unsigned int instance)
11235 {
11236 uint32_t setting;
11237
11238 switch (instance) {
11239 #if defined(_CMU_PCNTCTRL_PCNT0CLKEN_MASK)
11240 case 0:
11241 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0;
11242 break;
11243
11244 #if defined(_CMU_PCNTCTRL_PCNT1CLKEN_MASK)
11245 case 1:
11246 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0;
11247 break;
11248
11249 #if defined(_CMU_PCNTCTRL_PCNT2CLKEN_MASK)
11250 case 2:
11251 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0;
11252 break;
11253 #endif
11254 #endif
11255 #endif
11256
11257 default:
11258 setting = 0;
11259 break;
11260 }
11261 return setting > 0UL ? true : false;
11262 }
11263
11264 /**************************************************************************//**
11265 * @brief
11266 * Select the PCNTn clock.
11267 *
11268 * @param[in] instance
11269 * PCNT instance number to set selected clock source for.
11270 *
11271 * @param[in] external
11272 * Set to true to select the external clock, false to select LFBCLK.
11273 *****************************************************************************/
CMU_PCNTClockExternalSet(unsigned int instance,bool external)11274 void CMU_PCNTClockExternalSet(unsigned int instance, bool external)
11275 {
11276 #if defined(PCNT_PRESENT)
11277 uint32_t setting = 0;
11278
11279 EFM_ASSERT(instance < (unsigned)PCNT_COUNT);
11280
11281 if (external) {
11282 setting = 1;
11283 }
11284
11285 BUS_RegBitWrite(&(CMU->PCNTCTRL), (instance * 2U) + 1U, setting);
11286
11287 #else
11288 (void)instance; /* An unused parameter */
11289 (void)external; /* An unused parameter */
11290 #endif
11291 }
11292
11293 #if defined(_CMU_USHFRCOCONF_BAND_MASK)
11294 /***************************************************************************//**
11295 * @brief
11296 * Get USHFRCO band in use.
11297 *
11298 * @return
11299 * USHFRCO band in use.
11300 ******************************************************************************/
CMU_USHFRCOBandGet(void)11301 CMU_USHFRCOBand_TypeDef CMU_USHFRCOBandGet(void)
11302 {
11303 return (CMU_USHFRCOBand_TypeDef)((CMU->USHFRCOCONF
11304 & _CMU_USHFRCOCONF_BAND_MASK)
11305 >> _CMU_USHFRCOCONF_BAND_SHIFT);
11306 }
11307
11308 /***************************************************************************//**
11309 * @brief
11310 * Get USHFRCO frequency.
11311 *
11312 * @return
11313 * USHFRCO frequency.
11314 ******************************************************************************/
CMU_USHFRCOFreqGet(void)11315 uint32_t CMU_USHFRCOFreqGet(void)
11316 {
11317 return ushfrcoFreq;
11318 }
11319 #endif
11320
11321 #if defined(_CMU_USHFRCOCONF_BAND_MASK)
11322 /***************************************************************************//**
11323 * @brief
11324 * Set the USHFRCO band to use.
11325 *
11326 * @param[in] band
11327 * USHFRCO band to activate.
11328 ******************************************************************************/
CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band)11329 void CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band)
11330 {
11331 uint32_t tuning;
11332 uint32_t fineTuning;
11333
11334 /* Cannot switch band if USHFRCO is already selected as HF clock. */
11335 EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_USHFRCODIV2);
11336
11337 /* Read tuning value from calibration table. */
11338 switch (band) {
11339 case cmuUSHFRCOBand_24MHz:
11340 tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_TUNING_MASK)
11341 >> _DEVINFO_USHFRCOCAL0_BAND24_TUNING_SHIFT;
11342 fineTuning = (DEVINFO->USHFRCOCAL0
11343 & _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_MASK)
11344 >> _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_SHIFT;
11345 ushfrcoFreq = 24000000UL;
11346 break;
11347
11348 case cmuUSHFRCOBand_48MHz:
11349 tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_TUNING_MASK)
11350 >> _DEVINFO_USHFRCOCAL0_BAND48_TUNING_SHIFT;
11351 fineTuning = (DEVINFO->USHFRCOCAL0
11352 & _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_MASK)
11353 >> _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_SHIFT;
11354 /* Enable the clock divider before switching the band from 24 to 48 MHz */
11355 BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 0);
11356 ushfrcoFreq = 48000000UL;
11357 break;
11358
11359 default:
11360 EFM_ASSERT(false);
11361 return;
11362 }
11363
11364 /* Set band and tuning. */
11365 CMU->USHFRCOCONF = (CMU->USHFRCOCONF & ~_CMU_USHFRCOCONF_BAND_MASK)
11366 | (band << _CMU_USHFRCOCONF_BAND_SHIFT);
11367 CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~_CMU_USHFRCOCTRL_TUNING_MASK)
11368 | (tuning << _CMU_USHFRCOCTRL_TUNING_SHIFT);
11369 CMU->USHFRCOTUNE = (CMU->USHFRCOTUNE & ~_CMU_USHFRCOTUNE_FINETUNING_MASK)
11370 | (fineTuning << _CMU_USHFRCOTUNE_FINETUNING_SHIFT);
11371
11372 /* Disable the clock divider after switching the band from 48 to 24 MHz. */
11373 if (band == cmuUSHFRCOBand_24MHz) {
11374 BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 1);
11375 }
11376 }
11377 #endif
11378
11379 #endif // defined(_SILICON_LABS_32B_SERIES_2)
11380 /** @} (end addtogroup cmu) */
11381 #endif /* defined(CMU_PRESENT) */
11382