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