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