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