]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/SilLabs_Code/emlib/em_cmu.c
Add files necessary to create a Pearl Gecko build configuration in the new EFM32...
[freertos] / FreeRTOS / Demo / CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio / Source / SilLabs_Code / emlib / em_cmu.c
1 /***************************************************************************//**\r
2  * @file em_cmu.c\r
3  * @brief Clock management unit (CMU) Peripheral API\r
4  * @version 4.2.1\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
8  *******************************************************************************\r
9  *\r
10  * Permission is granted to anyone to use this software for any purpose,\r
11  * including commercial applications, and to alter it and redistribute it\r
12  * freely, subject to the following restrictions:\r
13  *\r
14  * 1. The origin of this software must not be misrepresented; you must not\r
15  *    claim that you wrote the original software.\r
16  * 2. Altered source versions must be plainly marked as such, and must not be\r
17  *    misrepresented as being the original software.\r
18  * 3. This notice may not be removed or altered from any source distribution.\r
19  *\r
20  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
21  * obligation to support this Software. Silicon Labs is providing the\r
22  * Software "AS IS", with no express or implied warranties of any kind,\r
23  * including, but not limited to, any implied warranties of merchantability\r
24  * or fitness for any particular purpose or warranties against infringement\r
25  * of any proprietary rights of a third party.\r
26  *\r
27  * Silicon Labs will not be liable for any consequential, incidental, or\r
28  * special damages, or any other relief, or for any claim by any third party,\r
29  * arising from your use of this Software.\r
30  *\r
31  ******************************************************************************/\r
32 #include "em_cmu.h"\r
33 #if defined( CMU_PRESENT )\r
34 \r
35 #include <stddef.h>\r
36 #include <limits.h>\r
37 #include "em_assert.h"\r
38 #include "em_bus.h"\r
39 #include "em_emu.h"\r
40 #include "em_system.h"\r
41 \r
42 /***************************************************************************//**\r
43  * @addtogroup EM_Library\r
44  * @{\r
45  ******************************************************************************/\r
46 \r
47 /***************************************************************************//**\r
48  * @addtogroup CMU\r
49  * @brief Clock management unit (CMU) Peripheral API\r
50  * @{\r
51  ******************************************************************************/\r
52 \r
53 /*******************************************************************************\r
54  ******************************   DEFINES   ************************************\r
55  ******************************************************************************/\r
56 \r
57 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
58 \r
59 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
60 /** Maximum allowed core frequency when using 0 wait-states on flash access. */\r
61 #define CMU_MAX_FREQ_0WS    26000000\r
62 /** Maximum allowed core frequency when using 1 wait-states on flash access */\r
63 #define CMU_MAX_FREQ_1WS    40000000\r
64 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
65 /** Maximum allowed core frequency when using 0 wait-states on flash access. */\r
66 #define CMU_MAX_FREQ_0WS    16000000\r
67 /** Maximum allowed core frequency when using 1 wait-states on flash access */\r
68 #define CMU_MAX_FREQ_1WS    32000000\r
69 #else\r
70 #error "Unkown MCU platform."\r
71 #endif\r
72 \r
73 #if defined( CMU_CTRL_HFLE )\r
74 /** Maximum frequency for HFLE needs to be enabled on Giant, Leopard and\r
75     Wonder. */\r
76 #if defined( _EFM32_WONDER_FAMILY )     \\r
77     || defined( _EZR32_LEOPARD_FAMILY ) \\r
78     || defined( _EZR32_WONDER_FAMILY )\r
79 #define CMU_MAX_FREQ_HFLE() 24000000\r
80 #elif defined ( _EFM32_GIANT_FAMILY )\r
81 #define CMU_MAX_FREQ_HFLE() (maxFreqHfle())\r
82 #else\r
83 #error Invalid part/device.\r
84 #endif\r
85 #endif\r
86 \r
87 /*******************************************************************************\r
88  **************************   LOCAL VARIABLES   ********************************\r
89  ******************************************************************************/\r
90 \r
91 #if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
92 static CMU_AUXHFRCOFreq_TypeDef auxHfrcoFreq = cmuAUXHFRCOFreq_19M0Hz;\r
93 #endif\r
94 \r
95 /** @endcond */\r
96 \r
97 /*******************************************************************************\r
98  **************************   LOCAL FUNCTIONS   ********************************\r
99  ******************************************************************************/\r
100 \r
101 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
102 \r
103 /***************************************************************************//**\r
104  * @brief\r
105  *   Get the AUX clock frequency. Used by MSC flash programming and LESENSE,\r
106  *   by default also as debug clock.\r
107  *\r
108  * @return\r
109  *   AUX Frequency in Hz\r
110  ******************************************************************************/\r
111 static uint32_t auxClkGet(void)\r
112 {\r
113   uint32_t ret;\r
114 \r
115 #if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
116   ret = auxHfrcoFreq;\r
117 \r
118 #elif defined( _CMU_AUXHFRCOCTRL_BAND_MASK )\r
119   /* All Geckos from TG and newer */\r
120   switch(CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK)\r
121   {\r
122     case CMU_AUXHFRCOCTRL_BAND_1MHZ:\r
123       ret = 1000000;\r
124       break;\r
125 \r
126     case CMU_AUXHFRCOCTRL_BAND_7MHZ:\r
127       ret = 7000000;\r
128       break;\r
129 \r
130     case CMU_AUXHFRCOCTRL_BAND_11MHZ:\r
131       ret = 11000000;\r
132       break;\r
133 \r
134     case CMU_AUXHFRCOCTRL_BAND_14MHZ:\r
135       ret = 14000000;\r
136       break;\r
137 \r
138     case CMU_AUXHFRCOCTRL_BAND_21MHZ:\r
139       ret = 21000000;\r
140       break;\r
141 \r
142 #if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )\r
143     case CMU_AUXHFRCOCTRL_BAND_28MHZ:\r
144       ret = 28000000;\r
145       break;\r
146 #endif\r
147 \r
148     default:\r
149       EFM_ASSERT(0);\r
150       ret = 0;\r
151       break;\r
152   }\r
153 \r
154 #else\r
155   /* Gecko has a fixed 14Mhz AUXHFRCO clock */\r
156   ret = 14000000;\r
157 \r
158 #endif\r
159 \r
160   return ret;\r
161 }\r
162 \r
163 \r
164 /***************************************************************************//**\r
165  * @brief\r
166  *   Get the Debug Trace clock frequency\r
167  *\r
168  * @return\r
169  *   Debug Trace frequency in Hz\r
170  ******************************************************************************/\r
171 static uint32_t dbgClkGet(void)\r
172 {\r
173   uint32_t ret;\r
174   CMU_Select_TypeDef clk;\r
175 \r
176   /* Get selected clock source */\r
177   clk = CMU_ClockSelectGet(cmuClock_DBG);\r
178 \r
179   switch(clk)\r
180   {\r
181     case cmuSelect_HFCLK:\r
182       ret = SystemHFClockGet();\r
183 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
184       /* Family with an additional divider. */\r
185       ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)\r
186                         >> _CMU_CTRL_HFCLKDIV_SHIFT));\r
187 #endif\r
188       break;\r
189 \r
190     case cmuSelect_AUXHFRCO:\r
191       ret = auxClkGet();\r
192       break;\r
193 \r
194     default:\r
195       EFM_ASSERT(0);\r
196       ret = 0;\r
197       break;\r
198   }\r
199   return ret;\r
200 }\r
201 \r
202 \r
203 /***************************************************************************//**\r
204  * @brief\r
205  *   Configure flash access wait states in order to support given core clock\r
206  *   frequency.\r
207  *\r
208  * @param[in] coreFreq\r
209  *   Core clock frequency to configure flash wait-states for\r
210  ******************************************************************************/\r
211 static void flashWaitStateControl(uint32_t coreFreq)\r
212 {\r
213   uint32_t mode;\r
214   bool mscLocked;\r
215 #if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
216   bool scbtpEn;   /* Suppressed Conditional Branch Target Prefetch setting. */\r
217 #endif\r
218 \r
219   /* Make sure the MSC is unlocked */\r
220   mscLocked = MSC->LOCK;\r
221   MSC->LOCK = MSC_UNLOCK_CODE;\r
222 \r
223   /* Get mode and SCBTP enable */\r
224   mode = MSC->READCTRL & _MSC_READCTRL_MODE_MASK;\r
225 #if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
226   switch(mode)\r
227   {\r
228     case MSC_READCTRL_MODE_WS0:\r
229     case MSC_READCTRL_MODE_WS1:\r
230 #if defined( MSC_READCTRL_MODE_WS2 )\r
231     case MSC_READCTRL_MODE_WS2:\r
232 #endif\r
233       scbtpEn = false;\r
234       break;\r
235 \r
236     default: /* WSxSCBTP */\r
237       scbtpEn = true;\r
238     break;\r
239   }\r
240 #endif\r
241 \r
242 \r
243   /* Set mode based on the core clock frequency and SCBTP enable */\r
244 #if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
245   if (false)\r
246   {\r
247   }\r
248 #if defined( MSC_READCTRL_MODE_WS2 )\r
249   else if (coreFreq > CMU_MAX_FREQ_1WS)\r
250   {\r
251     mode = (scbtpEn ? MSC_READCTRL_MODE_WS2SCBTP : MSC_READCTRL_MODE_WS2);\r
252   }\r
253 #endif\r
254   else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS))\r
255   {\r
256     mode = (scbtpEn ? MSC_READCTRL_MODE_WS1SCBTP : MSC_READCTRL_MODE_WS1);\r
257   }\r
258   else\r
259   {\r
260     mode = (scbtpEn ? MSC_READCTRL_MODE_WS0SCBTP : MSC_READCTRL_MODE_WS0);\r
261   }\r
262 \r
263 #else /* If MODE and SCBTP is in separate register fields */\r
264 \r
265   if (false)\r
266   {\r
267   }\r
268 #if defined( MSC_READCTRL_MODE_WS2 )\r
269   else if (coreFreq > CMU_MAX_FREQ_1WS)\r
270   {\r
271     mode = MSC_READCTRL_MODE_WS2;\r
272   }\r
273 #endif\r
274   else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS))\r
275   {\r
276     mode = MSC_READCTRL_MODE_WS1;\r
277   }\r
278   else\r
279   {\r
280     mode = MSC_READCTRL_MODE_WS0;\r
281   }\r
282 #endif\r
283 \r
284   /* BUS_RegMaskedWrite cannot be used here as it would temporarely set the\r
285      mode field to WS0 */\r
286   MSC->READCTRL = (MSC->READCTRL &~_MSC_READCTRL_MODE_MASK) | mode;\r
287 \r
288   if (mscLocked)\r
289   {\r
290     MSC->LOCK = 0;\r
291   }\r
292 }\r
293 \r
294 \r
295 /***************************************************************************//**\r
296  * @brief\r
297  *   Configure flash access wait states to most conservative setting for\r
298  *   this target. Retain SCBTP (Suppressed Conditional Branch Target Prefetch)\r
299  *   setting.\r
300  ******************************************************************************/\r
301 static void flashWaitStateMax(void)\r
302 {\r
303   flashWaitStateControl(SystemMaxCoreClockGet());\r
304 }\r
305 \r
306 \r
307 /***************************************************************************//**\r
308  * @brief\r
309  *   Get the LFnCLK frequency based on current configuration.\r
310  *\r
311  * @param[in] lfClkBranch\r
312  *   Selected LF branch\r
313  *\r
314  * @return\r
315  *   The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is\r
316  *   returned.\r
317  ******************************************************************************/\r
318 static uint32_t lfClkGet(CMU_Clock_TypeDef lfClkBranch)\r
319 {\r
320   uint32_t sel;\r
321   uint32_t ret = 0;\r
322 \r
323   switch (lfClkBranch)\r
324   {\r
325     case cmuClock_LFA:\r
326     case cmuClock_LFB:\r
327 #if defined( _CMU_LFCCLKEN0_MASK )\r
328     case cmuClock_LFC:\r
329 #endif\r
330 #if defined( _CMU_LFECLKSEL_MASK )\r
331     case cmuClock_LFE:\r
332 #endif\r
333       break;\r
334 \r
335     default:\r
336       EFM_ASSERT(0);\r
337       break;\r
338   }\r
339 \r
340   sel = CMU_ClockSelectGet(lfClkBranch);\r
341 \r
342   /* Get clock select field */\r
343   switch (lfClkBranch)\r
344   {\r
345     case cmuClock_LFA:\r
346 #if defined( _CMU_LFCLKSEL_MASK )\r
347       sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK) >> _CMU_LFCLKSEL_LFA_SHIFT;\r
348 #elif defined( _CMU_LFACLKSEL_MASK )\r
349       sel = (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK) >> _CMU_LFACLKSEL_LFA_SHIFT;\r
350 #else\r
351       EFM_ASSERT(0);\r
352 #endif\r
353       break;\r
354 \r
355     case cmuClock_LFB:\r
356 #if defined( _CMU_LFCLKSEL_MASK )\r
357       sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK) >> _CMU_LFCLKSEL_LFB_SHIFT;\r
358 #elif defined( _CMU_LFBCLKSEL_MASK )\r
359       sel = (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK) >> _CMU_LFBCLKSEL_LFB_SHIFT;\r
360 #else\r
361       EFM_ASSERT(0);\r
362 #endif\r
363       break;\r
364 \r
365 #if defined( _CMU_LFCCLKEN0_MASK )\r
366     case cmuClock_LFC:\r
367       sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK) >> _CMU_LFCLKSEL_LFC_SHIFT;\r
368       break;\r
369 #endif\r
370 \r
371 #if defined( _CMU_LFECLKSEL_MASK )\r
372     case cmuClock_LFE:\r
373       sel = (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK) >> _CMU_LFECLKSEL_LFE_SHIFT;\r
374       break;\r
375 #endif\r
376 \r
377     default:\r
378       EFM_ASSERT(0);\r
379       break;\r
380   }\r
381 \r
382   /* Get clock frequency */\r
383 #if defined( _CMU_LFCLKSEL_MASK )\r
384   switch (sel)\r
385   {\r
386     case _CMU_LFCLKSEL_LFA_LFRCO:\r
387       ret = SystemLFRCOClockGet();\r
388       break;\r
389 \r
390     case _CMU_LFCLKSEL_LFA_LFXO:\r
391       ret = SystemLFXOClockGet();\r
392       break;\r
393 \r
394 #if defined( _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2 )\r
395     case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:\r
396 #if defined( CMU_CTRL_HFLE )\r
397       /* Family which can use an extra div 4 divider  */\r
398       /* (and must if >32MHz) or HFLE is set.         */\r
399       if(((CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK)\r
400            == CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4)\r
401          || (CMU->CTRL & CMU_CTRL_HFLE))\r
402       {\r
403         ret = SystemCoreClockGet() / 4U;\r
404       }\r
405       else\r
406       {\r
407         ret = SystemCoreClockGet() / 2U;\r
408       }\r
409 #else\r
410       ret = SystemCoreClockGet() / 2U;\r
411 #endif\r
412       break;\r
413 #endif\r
414 \r
415     case _CMU_LFCLKSEL_LFA_DISABLED:\r
416       ret = 0;\r
417 #if defined( CMU_LFCLKSEL_LFAE )\r
418       /* Check LF Extended bit setting for LFA or LFB ULFRCO clock */\r
419       if ((lfClkBranch == cmuClock_LFA) || (lfClkBranch == cmuClock_LFB))\r
420       {\r
421         if (CMU->LFCLKSEL >> (lfClkBranch == cmuClock_LFA\r
422                               ? _CMU_LFCLKSEL_LFAE_SHIFT\r
423                               : _CMU_LFCLKSEL_LFBE_SHIFT))\r
424         {\r
425           ret = SystemULFRCOClockGet();\r
426         }\r
427       }\r
428 #endif\r
429       break;\r
430 \r
431     default:\r
432       EFM_ASSERT(0);\r
433       ret = 0U;\r
434       break;\r
435   }\r
436 #endif /* _CMU_LFCLKSEL_MASK */\r
437 \r
438 #if defined( _CMU_LFACLKSEL_MASK )\r
439   switch (sel)\r
440   {\r
441     case _CMU_LFACLKSEL_LFA_LFRCO:\r
442       ret = SystemLFRCOClockGet();\r
443       break;\r
444 \r
445     case _CMU_LFACLKSEL_LFA_LFXO:\r
446       ret = SystemLFXOClockGet();\r
447       break;\r
448 \r
449     case _CMU_LFACLKSEL_LFA_ULFRCO:\r
450       ret = SystemULFRCOClockGet();\r
451       break;\r
452 \r
453 #if defined( _CMU_LFACLKSEL_LFA_HFCLKLE )\r
454     case _CMU_LFACLKSEL_LFA_HFCLKLE:\r
455       ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)\r
456              == CMU_HFPRESC_HFCLKLEPRESC_DIV4)\r
457             ? SystemCoreClockGet() / 4U\r
458             : SystemCoreClockGet() / 2U;\r
459       break;\r
460 #elif defined( _CMU_LFBCLKSEL_LFB_HFCLKLE )\r
461     case _CMU_LFBCLKSEL_LFB_HFCLKLE:\r
462       ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)\r
463              == CMU_HFPRESC_HFCLKLEPRESC_DIV4)\r
464             ? SystemCoreClockGet() / 4U\r
465             : SystemCoreClockGet() / 2U;\r
466       break;\r
467 #endif\r
468 \r
469     case _CMU_LFACLKSEL_LFA_DISABLED:\r
470       ret = 0;\r
471       break;\r
472   }\r
473 #endif\r
474 \r
475   return ret;\r
476 }\r
477 \r
478 \r
479 #if defined( CMU_CTRL_HFLE )              \\r
480     && !defined( _EFM32_WONDER_FAMILY )   \\r
481     && !defined( _EZR32_LEOPARD_FAMILY )  \\r
482     && !defined( _EZR32_WONDER_FAMILY )\r
483 /***************************************************************************//**\r
484  * @brief\r
485  *   Return max allowed frequency for low energy peripherals.\r
486  ******************************************************************************/\r
487 static uint32_t maxFreqHfle(void)\r
488 {\r
489   uint16_t majorMinorRev;\r
490 \r
491   switch (SYSTEM_GetFamily())\r
492   {\r
493     case systemPartFamilyEfm32Leopard:\r
494       /* CHIP MAJOR bit [5:0] */\r
495       majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)\r
496                         >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8);\r
497       /* CHIP MINOR bit [7:4] */\r
498       majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)\r
499                          >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);\r
500       /* CHIP MINOR bit [3:0] */\r
501       majorMinorRev |=  ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)\r
502                          >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);\r
503 \r
504       if (majorMinorRev >= 0x0204)\r
505         return 24000000;\r
506       else\r
507         return 32000000;\r
508 \r
509     case systemPartFamilyEfm32Giant:\r
510       return 32000000;\r
511 \r
512     default:\r
513       /* Invalid device family. */\r
514       EFM_ASSERT(false);\r
515       return 0;\r
516   }\r
517 }\r
518 #endif\r
519 \r
520 \r
521 /***************************************************************************//**\r
522  * @brief\r
523  *   Wait for ongoing sync of register(s) to low frequency domain to complete.\r
524  *\r
525  * @param[in] mask\r
526  *   Bitmask corresponding to SYNCBUSY register defined bits, indicating\r
527  *   registers that must complete any ongoing synchronization.\r
528  ******************************************************************************/\r
529 __STATIC_INLINE void syncReg(uint32_t mask)\r
530 {\r
531   /* Avoid deadlock if modifying the same register twice when freeze mode is */\r
532   /* activated. */\r
533   if (CMU->FREEZE & CMU_FREEZE_REGFREEZE)\r
534     return;\r
535 \r
536   /* Wait for any pending previous write operation to have been completed */\r
537   /* in low frequency domain */\r
538   while (CMU->SYNCBUSY & mask)\r
539   {\r
540   }\r
541 }\r
542 \r
543 \r
544 #if defined(USB_PRESENT)\r
545 /***************************************************************************//**\r
546  * @brief\r
547  *   Get the USBC frequency\r
548  *\r
549  * @return\r
550  *   USBC frequency in Hz\r
551  ******************************************************************************/\r
552 static uint32_t usbCClkGet(void)\r
553 {\r
554   uint32_t ret;\r
555   CMU_Select_TypeDef clk;\r
556 \r
557   /* Get selected clock source */\r
558   clk = CMU_ClockSelectGet(cmuClock_USBC);\r
559 \r
560   switch(clk)\r
561   {\r
562     case cmuSelect_LFXO:\r
563       ret = SystemLFXOClockGet();\r
564       break;\r
565     case cmuSelect_LFRCO:\r
566       ret = SystemLFRCOClockGet();\r
567       break;\r
568     case cmuSelect_HFCLK:\r
569       ret = SystemHFClockGet();\r
570       break;\r
571     default:\r
572       /* Clock is not enabled */\r
573       ret = 0;\r
574       break;\r
575   }\r
576   return ret;\r
577 }\r
578 #endif\r
579 \r
580 \r
581 /** @endcond */\r
582 \r
583 /*******************************************************************************\r
584  **************************   GLOBAL FUNCTIONS   *******************************\r
585  ******************************************************************************/\r
586 \r
587 #if defined( _CMU_AUXHFRCOCTRL_BAND_MASK )\r
588 /***************************************************************************//**\r
589  * @brief\r
590  *   Get AUXHFRCO band in use.\r
591  *\r
592  * @return\r
593  *   AUXHFRCO band in use.\r
594  ******************************************************************************/\r
595 CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void)\r
596 {\r
597   return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL\r
598                                      & _CMU_AUXHFRCOCTRL_BAND_MASK)\r
599                                     >> _CMU_AUXHFRCOCTRL_BAND_SHIFT);\r
600 }\r
601 #endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */\r
602 \r
603 \r
604 #if defined( _CMU_AUXHFRCOCTRL_BAND_MASK )\r
605 /***************************************************************************//**\r
606  * @brief\r
607  *   Set AUXHFRCO band and the tuning value based on the value in the\r
608  *   calibration table made during production.\r
609  *\r
610  * @param[in] band\r
611  *   AUXHFRCO band to activate.\r
612  ******************************************************************************/\r
613 void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)\r
614 {\r
615   uint32_t tuning;\r
616 \r
617   /* Read tuning value from calibration table */\r
618   switch (band)\r
619   {\r
620     case cmuAUXHFRCOBand_1MHz:\r
621       tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK)\r
622                >> _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT;\r
623       break;\r
624 \r
625     case cmuAUXHFRCOBand_7MHz:\r
626       tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK)\r
627                >> _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT;\r
628       break;\r
629 \r
630     case cmuAUXHFRCOBand_11MHz:\r
631       tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK)\r
632                >> _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT;\r
633       break;\r
634 \r
635     case cmuAUXHFRCOBand_14MHz:\r
636       tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK)\r
637                >> _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT;\r
638       break;\r
639 \r
640     case cmuAUXHFRCOBand_21MHz:\r
641       tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK)\r
642                >> _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT;\r
643       break;\r
644 \r
645 #if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )\r
646     case cmuAUXHFRCOBand_28MHz:\r
647       tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK)\r
648                >> _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT;\r
649       break;\r
650 #endif\r
651 \r
652     default:\r
653       EFM_ASSERT(0);\r
654       return;\r
655   }\r
656 \r
657   /* Set band/tuning */\r
658   CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL &\r
659                        ~(_CMU_AUXHFRCOCTRL_BAND_MASK\r
660                          | _CMU_AUXHFRCOCTRL_TUNING_MASK))\r
661                       | (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT)\r
662                       | (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);\r
663 \r
664 }\r
665 #endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */\r
666 \r
667 \r
668 #if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
669 /**************************************************************************//**\r
670  * @brief\r
671  *   Get a pointer to the AUXHFRCO frequency calibration word in DEVINFO\r
672  *\r
673  * @param[in] freq\r
674  *   Frequency in Hz\r
675  *\r
676  * @return\r
677  *   AUXHFRCO calibration word for a given frequency\r
678  *****************************************************************************/\r
679 static uint32_t CMU_AUXHFRCODevinfoGet(CMU_AUXHFRCOFreq_TypeDef freq)\r
680 {\r
681   switch (freq)\r
682   {\r
683   /* 1, 2 and 4MHz share the same calibration word */\r
684     case cmuAUXHFRCOFreq_1M0Hz:\r
685     case cmuAUXHFRCOFreq_2M0Hz:\r
686     case cmuAUXHFRCOFreq_4M0Hz:\r
687       return DEVINFO->AUXHFRCOCAL0;\r
688 \r
689     case cmuAUXHFRCOFreq_7M0Hz:\r
690       return DEVINFO->AUXHFRCOCAL3;\r
691 \r
692     case cmuAUXHFRCOFreq_13M0Hz:\r
693       return DEVINFO->AUXHFRCOCAL6;\r
694 \r
695     case cmuAUXHFRCOFreq_16M0Hz:\r
696       return DEVINFO->AUXHFRCOCAL7;\r
697 \r
698     case cmuAUXHFRCOFreq_19M0Hz:\r
699       return DEVINFO->AUXHFRCOCAL8;\r
700 \r
701     case cmuAUXHFRCOFreq_26M0Hz:\r
702       return DEVINFO->AUXHFRCOCAL10;\r
703 \r
704     case cmuAUXHFRCOFreq_32M0Hz:\r
705       return DEVINFO->AUXHFRCOCAL11;\r
706 \r
707     case cmuAUXHFRCOFreq_38M0Hz:\r
708       return DEVINFO->AUXHFRCOCAL12;\r
709 \r
710     default: /* cmuAUXHFRCOFreq_UserDefined */\r
711       return 0;\r
712   }\r
713 }\r
714 #endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */\r
715 \r
716 \r
717 #if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
718 /***************************************************************************//**\r
719  * @brief\r
720  *   Get AUXHFRCO frequency enumeration in use\r
721  *\r
722  * @return\r
723  *   AUXHFRCO frequency enumeration in use\r
724  ******************************************************************************/\r
725 CMU_AUXHFRCOFreq_TypeDef CMU_AUXHFRCOFreqGet(void)\r
726 {\r
727   return auxHfrcoFreq;\r
728 }\r
729 #endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */\r
730 \r
731 \r
732 #if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
733 /***************************************************************************//**\r
734  * @brief\r
735  *   Set AUXHFRCO calibration for the selected target frequency\r
736  *\r
737  * @param[in] frequency\r
738  *   AUXHFRCO frequency to set\r
739  ******************************************************************************/\r
740 void CMU_AUXHFRCOFreqSet(CMU_AUXHFRCOFreq_TypeDef freq)\r
741 {\r
742   uint32_t freqCal;\r
743 \r
744   /* Get DEVINFO index, set global auxHfrcoFreq */\r
745   freqCal = CMU_AUXHFRCODevinfoGet(freq);\r
746   EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX));\r
747   auxHfrcoFreq = freq;\r
748 \r
749   /* Wait for any previous sync to complete, and then set calibration data\r
750      for the selected frequency.  */\r
751   while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT));\r
752 \r
753   /* Set divider in AUXHFRCOCTRL for 1, 2 and 4MHz */\r
754   switch(freq)\r
755   {\r
756     case cmuAUXHFRCOFreq_1M0Hz:\r
757       freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)\r
758                 | CMU_AUXHFRCOCTRL_CLKDIV_DIV4;\r
759       break;\r
760 \r
761     case cmuAUXHFRCOFreq_2M0Hz:\r
762       freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)\r
763                 | CMU_AUXHFRCOCTRL_CLKDIV_DIV2;\r
764       break;\r
765 \r
766     case cmuAUXHFRCOFreq_4M0Hz:\r
767       freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)\r
768                 | CMU_AUXHFRCOCTRL_CLKDIV_DIV1;\r
769       break;\r
770 \r
771     default:\r
772       break;\r
773   }\r
774   CMU->AUXHFRCOCTRL = freqCal;\r
775 }\r
776 #endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */\r
777 \r
778 \r
779 /***************************************************************************//**\r
780  * @brief\r
781  *   Calibrate clock.\r
782  *\r
783  * @details\r
784  *   Run a calibration for HFCLK against a selectable reference clock. Please\r
785  *   refer to the reference manual, CMU chapter, for further details.\r
786  *\r
787  * @note\r
788  *   This function will not return until calibration measurement is completed.\r
789  *\r
790  * @param[in] HFCycles\r
791  *   The number of HFCLK cycles to run calibration. Increasing this number\r
792  *   increases precision, but the calibration will take more time.\r
793  *\r
794  * @param[in] ref\r
795  *   The reference clock used to compare HFCLK with.\r
796  *\r
797  * @return\r
798  *   The number of ticks the reference clock after HFCycles ticks on the HF\r
799  *   clock.\r
800  ******************************************************************************/\r
801 uint32_t CMU_Calibrate(uint32_t HFCycles, CMU_Osc_TypeDef ref)\r
802 {\r
803   EFM_ASSERT(HFCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));\r
804 \r
805   /* Set reference clock source */\r
806   switch (ref)\r
807   {\r
808     case cmuOsc_LFXO:\r
809       CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO;\r
810       break;\r
811 \r
812     case cmuOsc_LFRCO:\r
813       CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO;\r
814       break;\r
815 \r
816     case cmuOsc_HFXO:\r
817       CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO;\r
818       break;\r
819 \r
820     case cmuOsc_HFRCO:\r
821       CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO;\r
822       break;\r
823 \r
824     case cmuOsc_AUXHFRCO:\r
825       CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO;\r
826       break;\r
827 \r
828     default:\r
829       EFM_ASSERT(0);\r
830       return 0;\r
831   }\r
832 \r
833   /* Set top value */\r
834   CMU->CALCNT = HFCycles;\r
835 \r
836   /* Start calibration */\r
837   CMU->CMD = CMU_CMD_CALSTART;\r
838 \r
839 #if defined( CMU_STATUS_CALRDY )\r
840   /* Wait until calibration completes */\r
841   while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT))\r
842   {\r
843   }\r
844 #else\r
845   /* Wait until calibration completes */\r
846   while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))\r
847   {\r
848   }\r
849 #endif\r
850 \r
851   return CMU->CALCNT;\r
852 }\r
853 \r
854 \r
855 #if defined( _CMU_CALCTRL_UPSEL_MASK ) && defined( _CMU_CALCTRL_DOWNSEL_MASK )\r
856 /***************************************************************************//**\r
857  * @brief\r
858  *   Configure clock calibration\r
859  *\r
860  * @details\r
861  *   Configure a calibration for a selectable clock source against another\r
862  *   selectable reference clock.\r
863  *   Refer to the reference manual, CMU chapter, for further details.\r
864  *\r
865  * @note\r
866  *   After configuration, a call to CMU_CalibrateStart() is required, and\r
867  *   the resulting calibration value can be read out with the\r
868  *   CMU_CalibrateCountGet() function call.\r
869  *\r
870  * @param[in] downCycles\r
871  *   The number of downSel clock cycles to run calibration. Increasing this\r
872  *   number increases precision, but the calibration will take more time.\r
873  *\r
874  * @param[in] downSel\r
875  *   The clock which will be counted down downCycles\r
876  *\r
877  * @param[in] upSel\r
878  *   The reference clock, the number of cycles generated by this clock will\r
879  *   be counted and added up, the result can be given with the\r
880  *   CMU_CalibrateCountGet() function call.\r
881  ******************************************************************************/\r
882 void CMU_CalibrateConfig(uint32_t downCycles, CMU_Osc_TypeDef downSel,\r
883                          CMU_Osc_TypeDef upSel)\r
884 {\r
885   /* Keep untouched configuration settings */\r
886   uint32_t calCtrl = CMU->CALCTRL\r
887                      & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK);\r
888 \r
889   /* 20 bits of precision to calibration count register */\r
890   EFM_ASSERT(downCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));\r
891 \r
892   /* Set down counting clock source - down counter */\r
893   switch (downSel)\r
894   {\r
895     case cmuOsc_LFXO:\r
896       calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO;\r
897       break;\r
898 \r
899     case cmuOsc_LFRCO:\r
900       calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO;\r
901       break;\r
902 \r
903     case cmuOsc_HFXO:\r
904       calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO;\r
905       break;\r
906 \r
907     case cmuOsc_HFRCO:\r
908       calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO;\r
909       break;\r
910 \r
911     case cmuOsc_AUXHFRCO:\r
912       calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO;\r
913       break;\r
914 \r
915     default:\r
916       EFM_ASSERT(0);\r
917       break;\r
918   }\r
919 \r
920   /* Set top value to be counted down by the downSel clock */\r
921   CMU->CALCNT = downCycles;\r
922 \r
923   /* Set reference clock source - up counter */\r
924   switch (upSel)\r
925   {\r
926     case cmuOsc_LFXO:\r
927       calCtrl |= CMU_CALCTRL_UPSEL_LFXO;\r
928       break;\r
929 \r
930     case cmuOsc_LFRCO:\r
931       calCtrl |= CMU_CALCTRL_UPSEL_LFRCO;\r
932       break;\r
933 \r
934     case cmuOsc_HFXO:\r
935       calCtrl |= CMU_CALCTRL_UPSEL_HFXO;\r
936       break;\r
937 \r
938     case cmuOsc_HFRCO:\r
939       calCtrl |= CMU_CALCTRL_UPSEL_HFRCO;\r
940       break;\r
941 \r
942     case cmuOsc_AUXHFRCO:\r
943       calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO;\r
944       break;\r
945 \r
946     default:\r
947       EFM_ASSERT(0);\r
948       break;\r
949   }\r
950 \r
951   CMU->CALCTRL = calCtrl;\r
952 }\r
953 #endif\r
954 \r
955 \r
956 /***************************************************************************//**\r
957  * @brief\r
958  *    Get calibration count register\r
959  * @note\r
960  *    If continuous calibrartion mode is active, calibration busy will almost\r
961  *    always be off, and we just need to read the value, where the normal case\r
962  *    would be that this function call has been triggered by the CALRDY\r
963  *    interrupt flag.\r
964  * @return\r
965  *    Calibration count, the number of UPSEL clocks (see CMU_CalibrateConfig)\r
966  *    in the period of DOWNSEL oscillator clock cycles configured by a previous\r
967  *    write operation to CMU->CALCNT\r
968  ******************************************************************************/\r
969 uint32_t CMU_CalibrateCountGet(void)\r
970 {\r
971   /* Wait until calibration completes, UNLESS continuous calibration mode is  */\r
972   /* active */\r
973 #if defined( CMU_CALCTRL_CONT )\r
974   if (!BUS_RegBitRead(&CMU->CALCTRL, _CMU_CALCTRL_CONT_SHIFT))\r
975   {\r
976 #if defined( CMU_STATUS_CALRDY )\r
977     /* Wait until calibration completes */\r
978     while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT))\r
979     {\r
980     }\r
981 #else\r
982     /* Wait until calibration completes */\r
983     while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))\r
984     {\r
985     }\r
986 #endif\r
987   }\r
988 #else\r
989   while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))\r
990   {\r
991   }\r
992 #endif\r
993   return CMU->CALCNT;\r
994 }\r
995 \r
996 \r
997 /***************************************************************************//**\r
998  * @brief\r
999  *   Get clock divisor/prescaler.\r
1000  *\r
1001  * @param[in] clock\r
1002  *   Clock point to get divisor/prescaler for. Notice that not all clock points\r
1003  *   have a divisor/prescaler. Please refer to CMU overview in reference manual.\r
1004  *\r
1005  * @return\r
1006  *   The current clock point divisor/prescaler. 1 is returned\r
1007  *   if @p clock specifies a clock point without a divisor/prescaler.\r
1008  ******************************************************************************/\r
1009 CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock)\r
1010 {\r
1011 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1012   return 1 + (uint32_t)CMU_ClockPrescGet(clock);\r
1013 \r
1014 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
1015   uint32_t           divReg;\r
1016   CMU_ClkDiv_TypeDef ret;\r
1017 \r
1018   /* Get divisor reg id */\r
1019   divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;\r
1020 \r
1021   switch (divReg)\r
1022   {\r
1023 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
1024     case CMU_HFCLKDIV_REG:\r
1025       ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)\r
1026                  >> _CMU_CTRL_HFCLKDIV_SHIFT);\r
1027       break;\r
1028 #endif\r
1029 \r
1030     case CMU_HFPERCLKDIV_REG:\r
1031       ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV\r
1032                                   & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)\r
1033                                  >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);\r
1034       ret = CMU_Log2ToDiv(ret);\r
1035       break;\r
1036 \r
1037     case CMU_HFCORECLKDIV_REG:\r
1038       ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV\r
1039                                   & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK)\r
1040                                  >> _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);\r
1041       ret = CMU_Log2ToDiv(ret);\r
1042       break;\r
1043 \r
1044     case CMU_LFAPRESC0_REG:\r
1045       switch (clock)\r
1046       {\r
1047         case cmuClock_RTC:\r
1048           ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)\r
1049                                      >> _CMU_LFAPRESC0_RTC_SHIFT);\r
1050           ret = CMU_Log2ToDiv(ret);\r
1051           break;\r
1052 \r
1053 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)\r
1054         case cmuClock_LETIMER0:\r
1055           ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)\r
1056                                      >> _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
1057           ret = CMU_Log2ToDiv(ret);\r
1058           break;\r
1059 #endif\r
1060 \r
1061 #if defined(_CMU_LFAPRESC0_LCD_MASK)\r
1062         case cmuClock_LCDpre:\r
1063           ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)\r
1064                                       >> _CMU_LFAPRESC0_LCD_SHIFT)\r
1065                                      + CMU_DivToLog2(cmuClkDiv_16));\r
1066           ret = CMU_Log2ToDiv(ret);\r
1067           break;\r
1068 #endif\r
1069 \r
1070 #if defined(_CMU_LFAPRESC0_LESENSE_MASK)\r
1071         case cmuClock_LESENSE:\r
1072           ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)\r
1073                                      >> _CMU_LFAPRESC0_LESENSE_SHIFT);\r
1074           ret = CMU_Log2ToDiv(ret);\r
1075           break;\r
1076 #endif\r
1077 \r
1078         default:\r
1079           EFM_ASSERT(0);\r
1080           ret = cmuClkDiv_1;\r
1081           break;\r
1082       }\r
1083       break;\r
1084 \r
1085     case CMU_LFBPRESC0_REG:\r
1086       switch (clock)\r
1087       {\r
1088 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)\r
1089         case cmuClock_LEUART0:\r
1090           ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)\r
1091                                      >> _CMU_LFBPRESC0_LEUART0_SHIFT);\r
1092           ret = CMU_Log2ToDiv(ret);\r
1093           break;\r
1094 #endif\r
1095 \r
1096 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)\r
1097         case cmuClock_LEUART1:\r
1098           ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)\r
1099                                      >> _CMU_LFBPRESC0_LEUART1_SHIFT);\r
1100           ret = CMU_Log2ToDiv(ret);\r
1101           break;\r
1102 #endif\r
1103 \r
1104         default:\r
1105           EFM_ASSERT(0);\r
1106           ret = cmuClkDiv_1;\r
1107           break;\r
1108       }\r
1109       break;\r
1110 \r
1111     default:\r
1112       EFM_ASSERT(0);\r
1113       ret = cmuClkDiv_1;\r
1114       break;\r
1115   }\r
1116 \r
1117   return ret;\r
1118 #endif\r
1119 }\r
1120 \r
1121 \r
1122 /***************************************************************************//**\r
1123  * @brief\r
1124  *   Set clock divisor/prescaler.\r
1125  *\r
1126  * @note\r
1127  *   If setting a LF clock prescaler, synchronization into the low frequency\r
1128  *   domain is required. If the same register is modified before a previous\r
1129  *   update has completed, this function will stall until the previous\r
1130  *   synchronization has completed. Please refer to CMU_FreezeEnable() for\r
1131  *   a suggestion on how to reduce stalling time in some use cases.\r
1132  *\r
1133  * @param[in] clock\r
1134  *   Clock point to set divisor/prescaler for. Notice that not all clock points\r
1135  *   have a divisor/prescaler, please refer to CMU overview in the reference\r
1136  *   manual.\r
1137  *\r
1138  * @param[in] div\r
1139  *   The clock divisor to use (<= cmuClkDiv_512).\r
1140  ******************************************************************************/\r
1141 void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)\r
1142 {\r
1143 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1144   CMU_ClockPrescSet(clock, (CMU_ClkPresc_TypeDef)(div - 1));\r
1145 \r
1146 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
1147   uint32_t freq;\r
1148   uint32_t divReg;\r
1149 \r
1150   /* Get divisor reg id */\r
1151   divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;\r
1152 \r
1153   switch (divReg)\r
1154   {\r
1155 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
1156     case CMU_HFCLKDIV_REG:\r
1157       EFM_ASSERT((div>=cmuClkDiv_1) && (div<=cmuClkDiv_8));\r
1158 \r
1159       /* Configure worst case wait states for flash access before setting divisor */\r
1160       flashWaitStateMax();\r
1161 \r
1162       /* Set divider */\r
1163       CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK)\r
1164                   | ((div-1) << _CMU_CTRL_HFCLKDIV_SHIFT);\r
1165 \r
1166       /* Update CMSIS core clock variable */\r
1167       /* (The function will update the global variable) */\r
1168       freq = SystemCoreClockGet();\r
1169 \r
1170       /* Optimize flash access wait state setting for current core clk */\r
1171       flashWaitStateControl(freq);\r
1172       break;\r
1173 #endif\r
1174 \r
1175     case CMU_HFPERCLKDIV_REG:\r
1176       EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512));\r
1177       /* Convert to correct scale */\r
1178       div = CMU_DivToLog2(div);\r
1179       CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)\r
1180                          | (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);\r
1181       break;\r
1182 \r
1183     case CMU_HFCORECLKDIV_REG:\r
1184       EFM_ASSERT(div <= cmuClkDiv_512);\r
1185 \r
1186       /* Configure worst case wait states for flash access before setting divisor */\r
1187       flashWaitStateMax();\r
1188 \r
1189 #if defined( CMU_CTRL_HFLE )\r
1190       /* Clear HFLE and set DIV2 factor for peripheral clock\r
1191          when running at frequencies lower than or equal to CMU_MAX_FREQ_HFLE. */\r
1192       if ((CMU_ClockFreqGet(cmuClock_HF) / div) <= CMU_MAX_FREQ_HFLE())\r
1193       {\r
1194         /* Clear CMU HFLE */\r
1195         BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 0);\r
1196 \r
1197         /* Set DIV2 factor for peripheral clock */\r
1198         BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
1199                         _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 0);\r
1200       }\r
1201       else\r
1202       {\r
1203         /* Set CMU HFLE */\r
1204         BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);\r
1205 \r
1206         /* Set DIV4 factor for peripheral clock */\r
1207         BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
1208                         _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
1209       }\r
1210 #endif\r
1211 \r
1212       /* Convert to correct scale */\r
1213       div = CMU_DivToLog2(div);\r
1214 \r
1215       CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV\r
1216                            & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK)\r
1217                           | (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);\r
1218 \r
1219       /* Update CMSIS core clock variable */\r
1220       /* (The function will update the global variable) */\r
1221       freq = SystemCoreClockGet();\r
1222 \r
1223       /* Optimize flash access wait state setting for current core clk */\r
1224       flashWaitStateControl(freq);\r
1225       break;\r
1226 \r
1227     case CMU_LFAPRESC0_REG:\r
1228       switch (clock)\r
1229       {\r
1230         case cmuClock_RTC:\r
1231           EFM_ASSERT(div <= cmuClkDiv_32768);\r
1232 \r
1233           /* LF register about to be modified require sync. busy check */\r
1234           syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
1235 \r
1236           /* Convert to correct scale */\r
1237           div = CMU_DivToLog2(div);\r
1238 \r
1239           CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK)\r
1240                            | (div << _CMU_LFAPRESC0_RTC_SHIFT);\r
1241           break;\r
1242 \r
1243 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)\r
1244         case cmuClock_LETIMER0:\r
1245           EFM_ASSERT(div <= cmuClkDiv_32768);\r
1246 \r
1247           /* LF register about to be modified require sync. busy check */\r
1248           syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
1249 \r
1250           /* Convert to correct scale */\r
1251           div = CMU_DivToLog2(div);\r
1252 \r
1253           CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK)\r
1254                            | (div << _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
1255           break;\r
1256 #endif\r
1257 \r
1258 #if defined(LCD_PRESENT)\r
1259         case cmuClock_LCDpre:\r
1260           EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128));\r
1261 \r
1262           /* LF register about to be modified require sync. busy check */\r
1263           syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
1264 \r
1265           /* Convert to correct scale */\r
1266           div = CMU_DivToLog2(div);\r
1267 \r
1268           CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK)\r
1269                            | ((div - CMU_DivToLog2(cmuClkDiv_16))\r
1270                               << _CMU_LFAPRESC0_LCD_SHIFT);\r
1271           break;\r
1272 #endif /* defined(LCD_PRESENT) */\r
1273 \r
1274 #if defined(LESENSE_PRESENT)\r
1275         case cmuClock_LESENSE:\r
1276           EFM_ASSERT(div <= cmuClkDiv_8);\r
1277 \r
1278           /* LF register about to be modified require sync. busy check */\r
1279           syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
1280 \r
1281           /* Convert to correct scale */\r
1282           div = CMU_DivToLog2(div);\r
1283 \r
1284           CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK)\r
1285                            | (div << _CMU_LFAPRESC0_LESENSE_SHIFT);\r
1286           break;\r
1287 #endif /* defined(LESENSE_PRESENT) */\r
1288 \r
1289         default:\r
1290           EFM_ASSERT(0);\r
1291           break;\r
1292       }\r
1293       break;\r
1294 \r
1295     case CMU_LFBPRESC0_REG:\r
1296       switch (clock)\r
1297       {\r
1298 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)\r
1299         case cmuClock_LEUART0:\r
1300           EFM_ASSERT(div <= cmuClkDiv_8);\r
1301 \r
1302           /* LF register about to be modified require sync. busy check */\r
1303           syncReg(CMU_SYNCBUSY_LFBPRESC0);\r
1304 \r
1305           /* Convert to correct scale */\r
1306           div = CMU_DivToLog2(div);\r
1307 \r
1308           CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK)\r
1309                            | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT);\r
1310           break;\r
1311 #endif\r
1312 \r
1313 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)\r
1314         case cmuClock_LEUART1:\r
1315           EFM_ASSERT(div <= cmuClkDiv_8);\r
1316 \r
1317           /* LF register about to be modified require sync. busy check */\r
1318           syncReg(CMU_SYNCBUSY_LFBPRESC0);\r
1319 \r
1320           /* Convert to correct scale */\r
1321           div = CMU_DivToLog2(div);\r
1322 \r
1323           CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK)\r
1324                            | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT);\r
1325           break;\r
1326 #endif\r
1327 \r
1328         default:\r
1329           EFM_ASSERT(0);\r
1330           break;\r
1331       }\r
1332       break;\r
1333 \r
1334     default:\r
1335       EFM_ASSERT(0);\r
1336       break;\r
1337   }\r
1338 #endif\r
1339 }\r
1340 \r
1341 \r
1342 /***************************************************************************//**\r
1343  * @brief\r
1344  *   Enable/disable a clock.\r
1345  *\r
1346  * @details\r
1347  *   In general, module clocking is disabled after a reset. If a module\r
1348  *   clock is disabled, the registers of that module are not accessible and\r
1349  *   reading from such registers may return undefined values. Writing to\r
1350  *   registers of clock disabled modules have no effect. One should normally\r
1351  *   avoid accessing module registers of a module with a disabled clock.\r
1352  *\r
1353  * @note\r
1354  *   If enabling/disabling a LF clock, synchronization into the low frequency\r
1355  *   domain is required. If the same register is modified before a previous\r
1356  *   update has completed, this function will stall until the previous\r
1357  *   synchronization has completed. Please refer to CMU_FreezeEnable() for\r
1358  *   a suggestion on how to reduce stalling time in some use cases.\r
1359  *\r
1360  * @param[in] clock\r
1361  *   The clock to enable/disable. Notice that not all defined clock\r
1362  *   points have separate enable/disable control, please refer to CMU overview\r
1363  *   in reference manual.\r
1364  *\r
1365  * @param[in] enable\r
1366  *   @li true - enable specified clock.\r
1367  *   @li false - disable specified clock.\r
1368  ******************************************************************************/\r
1369 void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)\r
1370 {\r
1371   volatile uint32_t *reg;\r
1372   uint32_t          bit;\r
1373   uint32_t          sync = 0;\r
1374 \r
1375   /* Identify enable register */\r
1376   switch ((clock >> CMU_EN_REG_POS) & CMU_EN_REG_MASK)\r
1377   {\r
1378 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1379     case CMU_CTRL_EN_REG:\r
1380       reg = &CMU->CTRL;\r
1381       break;\r
1382 #endif\r
1383 \r
1384 #if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
1385     case CMU_HFCORECLKEN0_EN_REG:\r
1386       reg = &CMU->HFCORECLKEN0;\r
1387 #if defined( CMU_CTRL_HFLE )\r
1388       /* Set HFLE and DIV4 factor for peripheral clock when\r
1389          running at frequencies higher than or equal to CMU_MAX_FREQ_HFLE. */\r
1390       if ( CMU_ClockFreqGet(cmuClock_CORE) > CMU_MAX_FREQ_HFLE())\r
1391       {\r
1392         /* Enable CMU HFLE */\r
1393         BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);\r
1394 \r
1395         /* Set DIV4 factor for peripheral clock */\r
1396         BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
1397                         _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
1398       }\r
1399 #endif\r
1400       break;\r
1401 #endif\r
1402 \r
1403 #if defined( _CMU_HFBUSCLKEN0_MASK )\r
1404     case CMU_HFBUSCLKEN0_EN_REG:\r
1405       reg = &CMU->HFBUSCLKEN0;\r
1406       break;\r
1407 #endif\r
1408 \r
1409 #if defined( _CMU_HFRADIOCLKEN0_MASK )\r
1410     case CMU_HFRADIOCLKEN0_EN_REG:\r
1411       reg = &CMU->HFRADIOCLKEN0;\r
1412       break;\r
1413 #endif\r
1414 \r
1415 #if defined( _CMU_HFPERCLKDIV_MASK )\r
1416     case CMU_HFPERCLKDIV_EN_REG:\r
1417       reg = &CMU->HFPERCLKDIV;\r
1418       break;\r
1419 #endif\r
1420 \r
1421     case CMU_HFPERCLKEN0_EN_REG:\r
1422       reg = &CMU->HFPERCLKEN0;\r
1423       break;\r
1424 \r
1425     case CMU_LFACLKEN0_EN_REG:\r
1426       reg  = &CMU->LFACLKEN0;\r
1427       sync = CMU_SYNCBUSY_LFACLKEN0;\r
1428       break;\r
1429 \r
1430     case CMU_LFBCLKEN0_EN_REG:\r
1431       reg  = &CMU->LFBCLKEN0;\r
1432       sync = CMU_SYNCBUSY_LFBCLKEN0;\r
1433       break;\r
1434 \r
1435 #if defined( _CMU_LFCCLKEN0_MASK )\r
1436     case CMU_LFCCLKEN0_EN_REG:\r
1437       reg = &CMU->LFCCLKEN0;\r
1438       sync = CMU_SYNCBUSY_LFCCLKEN0;\r
1439       break;\r
1440 #endif\r
1441 \r
1442 #if defined( _CMU_LFECLKEN0_MASK )\r
1443     case CMU_LFECLKEN0_EN_REG:\r
1444       reg  = &CMU->LFECLKEN0;\r
1445       sync = CMU_SYNCBUSY_LFECLKEN0;\r
1446       break;\r
1447 #endif\r
1448 \r
1449     case CMU_PCNT_EN_REG:\r
1450       reg = &CMU->PCNTCTRL;\r
1451       break;\r
1452 \r
1453     default: /* Cannot enable/disable clock point */\r
1454       EFM_ASSERT(0);\r
1455       return;\r
1456   }\r
1457 \r
1458   /* Get bit position used to enable/disable */\r
1459   bit = (clock >> CMU_EN_BIT_POS) & CMU_EN_BIT_MASK;\r
1460 \r
1461   /* LF synchronization required? */\r
1462   if (sync)\r
1463   {\r
1464     syncReg(sync);\r
1465   }\r
1466 \r
1467   /* Set/clear bit as requested */\r
1468   BUS_RegBitWrite(reg, bit, enable);\r
1469 }\r
1470 \r
1471 \r
1472 /***************************************************************************//**\r
1473  * @brief\r
1474  *   Get clock frequency for a clock point.\r
1475  *\r
1476  * @param[in] clock\r
1477  *   Clock point to fetch frequency for.\r
1478  *\r
1479  * @return\r
1480  *   The current frequency in Hz.\r
1481  ******************************************************************************/\r
1482 uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)\r
1483 {\r
1484   uint32_t ret;\r
1485 \r
1486   switch(clock & (CMU_CLK_BRANCH_MASK << CMU_CLK_BRANCH_POS))\r
1487   {\r
1488     case (CMU_HF_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1489       ret = SystemHFClockGet();\r
1490 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
1491       /* Family with an additional divider. */\r
1492       ret = ret / (1U + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)\r
1493                          >> _CMU_CTRL_HFCLKDIV_SHIFT));\r
1494 #endif\r
1495 #if defined( _CMU_HFPRESC_MASK )\r
1496       ret = ret / (1U + ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)\r
1497                          >> _CMU_HFPRESC_PRESC_SHIFT));\r
1498 #endif\r
1499       break;\r
1500 \r
1501     case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1502       ret = SystemHFClockGet();\r
1503 #if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
1504 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
1505       /* Family with an additional divider. */\r
1506       ret = ret / (1U + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)\r
1507                          >> _CMU_CTRL_HFCLKDIV_SHIFT));\r
1508 #endif\r
1509       ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)\r
1510               >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT;\r
1511 #elif defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1512       ret /= 1U + ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK)\r
1513                    >> _CMU_HFPERPRESC_PRESC_SHIFT);\r
1514 #endif\r
1515       break;\r
1516 \r
1517 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1518 #if defined( _CMU_HFRADIOPRESC_PRESC_MASK )\r
1519     case (CMU_HFRADIO_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1520       ret = SystemHFClockGet();\r
1521       ret /= 1U + ((CMU->HFRADIOPRESC & _CMU_HFRADIOPRESC_PRESC_MASK)\r
1522                    >> _CMU_HFRADIOPRESC_PRESC_SHIFT);\r
1523       break;\r
1524 #endif\r
1525 \r
1526 #if defined( CRYPTO_PRESENT )   \\r
1527     || defined( LDMA_PRESENT )  \\r
1528     || defined( GPCRC_PRESENT ) \\r
1529     || defined( PRS_PRESENT )   \\r
1530     || defined( GPIO_PRESENT )\r
1531     case (CMU_HFBUS_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1532       ret = SystemHFClockGet();\r
1533       break;\r
1534 #endif\r
1535 \r
1536     case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1537       ret = SystemHFClockGet();\r
1538       ret /= 1U + ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK)\r
1539                    >> _CMU_HFCOREPRESC_PRESC_SHIFT);\r
1540       break;\r
1541 \r
1542     case (CMU_HFEXP_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1543       ret = SystemHFClockGet();\r
1544       ret /= 1U + ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK)\r
1545                    >> _CMU_HFEXPPRESC_PRESC_SHIFT);\r
1546       break;\r
1547 #endif\r
1548 \r
1549 #if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
1550 #if defined(AES_PRESENT)    \\r
1551     || defined(DMA_PRESENT) \\r
1552     || defined(EBI_PRESENT) \\r
1553     || defined(USB_PRESENT)\r
1554     case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1555     {\r
1556       ret = SystemCoreClockGet();\r
1557     } break;\r
1558 #endif\r
1559 #endif\r
1560 \r
1561     case (CMU_LFA_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1562       ret = lfClkGet(cmuClock_LFA);\r
1563       break;\r
1564 \r
1565 #if defined( _CMU_LFACLKEN0_RTC_MASK )\r
1566     case (CMU_RTC_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1567       ret = lfClkGet(cmuClock_LFA);\r
1568       ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)\r
1569               >> _CMU_LFAPRESC0_RTC_SHIFT;\r
1570       break;\r
1571 #endif\r
1572 \r
1573 #if defined( _CMU_LFECLKEN0_RTCC_MASK )\r
1574     case (CMU_RTCC_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1575       ret = lfClkGet(cmuClock_LFE);\r
1576       break;\r
1577 #endif\r
1578 \r
1579 #if defined( _CMU_LFACLKEN0_LETIMER0_MASK )\r
1580     case (CMU_LETIMER0_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1581       ret = lfClkGet(cmuClock_LFA);\r
1582 #if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
1583       ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)\r
1584               >> _CMU_LFAPRESC0_LETIMER0_SHIFT;\r
1585 #elif defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1586       ret /= CMU_Log2ToDiv((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)\r
1587                            >> _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
1588 #endif\r
1589       break;\r
1590 #endif\r
1591 \r
1592 #if defined(_CMU_LFACLKEN0_LCD_MASK)\r
1593     case (CMU_LCDPRE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1594       ret = lfClkGet(cmuClock_LFA);\r
1595       ret >>= ((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)\r
1596                >> _CMU_LFAPRESC0_LCD_SHIFT)\r
1597               + CMU_DivToLog2(cmuClkDiv_16);\r
1598       break;\r
1599 \r
1600     case (CMU_LCD_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1601       ret = lfClkGet(cmuClock_LFA);\r
1602       ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)\r
1603               >> _CMU_LFAPRESC0_LCD_SHIFT;\r
1604       ret /= 1U + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK)\r
1605                    >> _CMU_LCDCTRL_FDIV_SHIFT);\r
1606       break;\r
1607 #endif\r
1608 \r
1609 #if defined(_CMU_LFACLKEN0_LESENSE_MASK)\r
1610     case (CMU_LESENSE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1611       ret = lfClkGet(cmuClock_LFA);\r
1612       ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)\r
1613               >> _CMU_LFAPRESC0_LESENSE_SHIFT;\r
1614       break;\r
1615 #endif\r
1616 \r
1617     case (CMU_LFB_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1618       ret = lfClkGet(cmuClock_LFB);\r
1619       break;\r
1620 \r
1621 #if defined( _CMU_LFBCLKEN0_LEUART0_MASK )\r
1622     case (CMU_LEUART0_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1623       ret = lfClkGet(cmuClock_LFB);\r
1624 #if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
1625       ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)\r
1626               >> _CMU_LFBPRESC0_LEUART0_SHIFT;\r
1627 #elif defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1628       ret /= CMU_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)\r
1629                            >> _CMU_LFBPRESC0_LEUART0_SHIFT);\r
1630 #endif\r
1631       break;\r
1632 #endif\r
1633 \r
1634 #if defined( _CMU_LFBCLKEN0_LEUART1_MASK )\r
1635     case (CMU_LEUART1_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1636       ret = lfClkGet(cmuClock_LFB);\r
1637 #if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
1638       ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)\r
1639               >> _CMU_LFBPRESC0_LEUART1_SHIFT;\r
1640 #elif defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1641       ret /= CMU_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)\r
1642                            >> _CMU_LFBPRESC0_LEUART1_SHIFT);\r
1643 #endif\r
1644       break;\r
1645 #endif\r
1646 \r
1647 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1648     case (CMU_LFE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1649       ret = lfClkGet(cmuClock_LFE);\r
1650       break;\r
1651 #endif\r
1652 \r
1653     case (CMU_DBG_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1654       ret = dbgClkGet();\r
1655       break;\r
1656 \r
1657     case (CMU_AUX_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1658       ret = auxClkGet();\r
1659       break;\r
1660 \r
1661 #if defined(USB_PRESENT)\r
1662     case (CMU_USBC_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1663       ret = usbCClkGet();\r
1664       break;\r
1665 #endif\r
1666 \r
1667     default:\r
1668       EFM_ASSERT(0);\r
1669       ret = 0;\r
1670       break;\r
1671   }\r
1672 \r
1673   return ret;\r
1674 }\r
1675 \r
1676 \r
1677 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1678 /***************************************************************************//**\r
1679  * @brief\r
1680  *   Get clock prescaler.\r
1681  *\r
1682  * @param[in] clock\r
1683  *   Clock point to get the prescaler for. Notice that not all clock points\r
1684  *   have a prescaler. Please refer to CMU overview in reference manual.\r
1685  *\r
1686  * @return\r
1687  *   The prescaler value of the current clock point. 0 is returned\r
1688  *   if @p clock specifies a clock point without a prescaler.\r
1689  ******************************************************************************/\r
1690 uint32_t CMU_ClockPrescGet(CMU_Clock_TypeDef clock)\r
1691 {\r
1692   uint32_t  prescReg;\r
1693   uint32_t  ret;\r
1694 \r
1695   /* Get prescaler register id. */\r
1696   prescReg = (clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK;\r
1697 \r
1698   switch (prescReg)\r
1699   {\r
1700     case CMU_HFPRESC_REG:\r
1701       ret = ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)\r
1702              >> _CMU_HFPRESC_PRESC_SHIFT);\r
1703       break;\r
1704 \r
1705     case CMU_HFEXPPRESC_REG:\r
1706       ret = ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK)\r
1707              >> _CMU_HFEXPPRESC_PRESC_SHIFT);\r
1708       break;\r
1709 \r
1710     case CMU_HFCLKLEPRESC_REG:\r
1711       ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)\r
1712              >> _CMU_HFPRESC_HFCLKLEPRESC_SHIFT);\r
1713       break;\r
1714 \r
1715     case CMU_HFPERPRESC_REG:\r
1716       ret = ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK)\r
1717              >> _CMU_HFPERPRESC_PRESC_SHIFT);\r
1718       break;\r
1719 \r
1720 #if defined( _CMU_HFRADIOPRESC_PRESC_MASK )\r
1721     case CMU_HFRADIOPRESC_REG:\r
1722       ret = ((CMU->HFRADIOPRESC & _CMU_HFRADIOPRESC_PRESC_MASK)\r
1723              >> _CMU_HFRADIOPRESC_PRESC_SHIFT);\r
1724       break;\r
1725 #endif\r
1726 \r
1727     case CMU_HFCOREPRESC_REG:\r
1728       ret = ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK)\r
1729              >> _CMU_HFCOREPRESC_PRESC_SHIFT);\r
1730       break;\r
1731 \r
1732     case CMU_LFAPRESC0_REG:\r
1733       switch (clock)\r
1734       {\r
1735 #if defined( _CMU_LFAPRESC0_LETIMER0_MASK )\r
1736         case cmuClock_LETIMER0:\r
1737           ret = (((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)\r
1738                  >> _CMU_LFAPRESC0_LETIMER0_SHIFT));\r
1739           /* Convert the exponent to prescaler value. */\r
1740           ret = CMU_Log2ToDiv(ret) - 1U;\r
1741           break;\r
1742 #endif\r
1743 \r
1744         default:\r
1745           EFM_ASSERT(0);\r
1746           ret = 0U;\r
1747           break;\r
1748       }\r
1749       break;\r
1750 \r
1751     case CMU_LFBPRESC0_REG:\r
1752       switch (clock)\r
1753       {\r
1754 #if defined( _CMU_LFBPRESC0_LEUART0_MASK )\r
1755         case cmuClock_LEUART0:\r
1756           ret = (((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)\r
1757                  >> _CMU_LFBPRESC0_LEUART0_SHIFT));\r
1758           /* Convert the exponent to prescaler value. */\r
1759           ret = CMU_Log2ToDiv(ret) - 1U;\r
1760           break;\r
1761 #endif\r
1762 \r
1763 #if defined( _CMU_LFBPRESC0_LEUART1_MASK )\r
1764         case cmuClock_LEUART1:\r
1765           ret = (((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)\r
1766                  >> _CMU_LFBPRESC0_LEUART1_SHIFT));\r
1767           /* Convert the exponent to prescaler value. */\r
1768           ret = CMU_Log2ToDiv(ret) - 1U;\r
1769           break;\r
1770 #endif\r
1771 \r
1772         default:\r
1773           EFM_ASSERT(0);\r
1774           ret = 0U;\r
1775           break;\r
1776       }\r
1777       break;\r
1778 \r
1779     case CMU_LFEPRESC0_REG:\r
1780       switch (clock)\r
1781       {\r
1782 #if defined( RTCC_PRESENT )\r
1783         case cmuClock_RTCC:\r
1784           /* No need to compute with LFEPRESC0_RTCC - DIV1 is the only  */\r
1785           /* allowed value. Convert the exponent to prescaler value.    */\r
1786           ret = _CMU_LFEPRESC0_RTCC_DIV1;\r
1787           break;\r
1788 \r
1789         default:\r
1790           EFM_ASSERT(0);\r
1791           ret = 0U;\r
1792           break;\r
1793 #endif\r
1794       }\r
1795       break;\r
1796 \r
1797     default:\r
1798       EFM_ASSERT(0);\r
1799       ret = 0U;\r
1800       break;\r
1801   }\r
1802 \r
1803   return ret;\r
1804 }\r
1805 #endif\r
1806 \r
1807 \r
1808 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
1809 /***************************************************************************//**\r
1810  * @brief\r
1811  *   Set clock prescaler.\r
1812  *\r
1813  * @note\r
1814  *   If setting a LF clock prescaler, synchronization into the low frequency\r
1815  *   domain is required. If the same register is modified before a previous\r
1816  *   update has completed, this function will stall until the previous\r
1817  *   synchronization has completed. Please refer to CMU_FreezeEnable() for\r
1818  *   a suggestion on how to reduce stalling time in some use cases.\r
1819  *\r
1820  * @param[in] clock\r
1821  *   Clock point to set prescaler for. Notice that not all clock points\r
1822  *   have a prescaler, please refer to CMU overview in the reference manual.\r
1823  *\r
1824  * @param[in] presc\r
1825  *   The clock prescaler to use.\r
1826  ******************************************************************************/\r
1827 void CMU_ClockPrescSet(CMU_Clock_TypeDef clock, CMU_ClkPresc_TypeDef presc)\r
1828 {\r
1829   uint32_t freq;\r
1830   uint32_t prescReg;\r
1831 \r
1832   /* Get divisor reg id */\r
1833   prescReg = (clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK;\r
1834 \r
1835   switch (prescReg)\r
1836   {\r
1837     case CMU_HFPRESC_REG:\r
1838       EFM_ASSERT(presc < 32U);\r
1839 \r
1840       CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_PRESC_MASK)\r
1841                      | (presc << _CMU_HFPRESC_PRESC_SHIFT);\r
1842       break;\r
1843 \r
1844     case CMU_HFEXPPRESC_REG:\r
1845       EFM_ASSERT(presc < 32U);\r
1846 \r
1847       CMU->HFEXPPRESC = (CMU->HFEXPPRESC & ~_CMU_HFEXPPRESC_PRESC_MASK)\r
1848                         | (presc << _CMU_HFEXPPRESC_PRESC_SHIFT);\r
1849       break;\r
1850 \r
1851     case CMU_HFCLKLEPRESC_REG:\r
1852       EFM_ASSERT(presc < 2U);\r
1853 \r
1854       /* Specifies the clock divider for HFCLKLE. When running at frequencies\r
1855        * higher than 32 MHz, this must be set to DIV4. */\r
1856       CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_HFCLKLEPRESC_MASK)\r
1857                      | (presc << _CMU_HFPRESC_HFCLKLEPRESC_SHIFT);\r
1858       break;\r
1859 \r
1860     case CMU_HFPERPRESC_REG:\r
1861       EFM_ASSERT(presc < 512U);\r
1862 \r
1863       CMU->HFPERPRESC = (CMU->HFPERPRESC & ~_CMU_HFPERPRESC_PRESC_MASK)\r
1864                         | (presc << _CMU_HFPERPRESC_PRESC_SHIFT);\r
1865       break;\r
1866 \r
1867 #if defined( _CMU_HFRADIOPRESC_PRESC_MASK )\r
1868     case CMU_HFRADIOPRESC_REG:\r
1869       EFM_ASSERT(presc < 512U);\r
1870 \r
1871       CMU->HFRADIOPRESC = (CMU->HFRADIOPRESC & ~_CMU_HFRADIOPRESC_PRESC_MASK)\r
1872                           | (presc << _CMU_HFRADIOPRESC_PRESC_SHIFT);\r
1873       break;\r
1874 #endif\r
1875 \r
1876     case CMU_HFCOREPRESC_REG:\r
1877       EFM_ASSERT(presc < 512U);\r
1878 \r
1879       /* Configure worst case wait states for flash access before setting\r
1880        * the prescaler. */\r
1881       flashWaitStateControl(CMU_MAX_FREQ_0WS + 1);\r
1882 \r
1883       CMU->HFCOREPRESC = (CMU->HFCOREPRESC & ~_CMU_HFCOREPRESC_PRESC_MASK)\r
1884                          | (presc << _CMU_HFCOREPRESC_PRESC_SHIFT);\r
1885 \r
1886       /* Update CMSIS core clock variable */\r
1887       /* (The function will update the global variable) */\r
1888       freq = SystemCoreClockGet();\r
1889 \r
1890       /* Optimize flash access wait state setting for current core clk */\r
1891       flashWaitStateControl(freq);\r
1892       break;\r
1893 \r
1894     case CMU_LFAPRESC0_REG:\r
1895       switch (clock)\r
1896       {\r
1897 #if defined( RTC_PRESENT )\r
1898         case cmuClock_RTC:\r
1899           EFM_ASSERT(presc <= 32768U);\r
1900 \r
1901           /* Convert prescaler value to DIV exponent scale. */\r
1902           presc = CMU_PrescToLog2(presc);\r
1903 \r
1904           /* LF register about to be modified require sync. Busy check. */\r
1905           syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
1906 \r
1907           CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK)\r
1908                            | (presc << _CMU_LFAPRESC0_RTC_SHIFT);\r
1909           break;\r
1910 #endif\r
1911 \r
1912 #if defined( RTCC_PRESENT )\r
1913         case cmuClock_RTCC:\r
1914 #if defined( _CMU_LFEPRESC0_RTCC_MASK )\r
1915           /* DIV1 is the only accepted value. */\r
1916           EFM_ASSERT(presc <= 0U);\r
1917 \r
1918           /* LF register about to be modified require sync. Busy check.. */\r
1919           syncReg(CMU_SYNCBUSY_LFEPRESC0);\r
1920 \r
1921           CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK)\r
1922                            | (presc << _CMU_LFEPRESC0_RTCC_SHIFT);\r
1923 #else\r
1924           EFM_ASSERT(presc <= 32768U);\r
1925 \r
1926           /* Convert prescaler value to DIV exponent scale. */\r
1927           presc = CMU_PrescToLog2(presc);\r
1928 \r
1929           /* LF register about to be modified require sync. Busy check. */\r
1930           syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
1931 \r
1932           CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTCC_MASK)\r
1933                            | (presc << _CMU_LFAPRESC0_RTCC_SHIFT);\r
1934 #endif\r
1935           break;\r
1936 #endif\r
1937 \r
1938 #if defined( _CMU_LFAPRESC0_LETIMER0_MASK )\r
1939         case cmuClock_LETIMER0:\r
1940           EFM_ASSERT(presc <= 32768U);\r
1941 \r
1942           /* Convert prescaler value to DIV exponent scale. */\r
1943           presc = CMU_PrescToLog2(presc);\r
1944 \r
1945           /* LF register about to be modified require sync. Busy check. */\r
1946           syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
1947 \r
1948           CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK)\r
1949                            | (presc << _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
1950           break;\r
1951 #endif\r
1952 \r
1953         default:\r
1954           EFM_ASSERT(0);\r
1955           break;\r
1956       }\r
1957       break;\r
1958 \r
1959     case CMU_LFBPRESC0_REG:\r
1960       switch (clock)\r
1961       {\r
1962 #if defined( _CMU_LFBPRESC0_LEUART0_MASK )\r
1963         case cmuClock_LEUART0:\r
1964           EFM_ASSERT(presc <= 8U);\r
1965 \r
1966           /* Convert prescaler value to DIV exponent scale. */\r
1967           presc = CMU_PrescToLog2(presc);\r
1968 \r
1969           /* LF register about to be modified require sync. Busy check. */\r
1970           syncReg(CMU_SYNCBUSY_LFBPRESC0);\r
1971 \r
1972           CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK)\r
1973                            | (presc << _CMU_LFBPRESC0_LEUART0_SHIFT);\r
1974           break;\r
1975 #endif\r
1976 \r
1977 #if defined( _CMU_LFBPRESC0_LEUART1_MASK )\r
1978         case cmuClock_LEUART1:\r
1979           EFM_ASSERT(presc <= 8U);\r
1980 \r
1981           /* Convert prescaler value to DIV exponent scale. */\r
1982           presc = CMU_PrescToLog2(presc);\r
1983 \r
1984           /* LF register about to be modified require sync. Busy check. */\r
1985           syncReg(CMU_SYNCBUSY_LFBPRESC0);\r
1986 \r
1987           CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK)\r
1988                            | (presc << _CMU_LFBPRESC0_LEUART1_SHIFT);\r
1989           break;\r
1990 #endif\r
1991 \r
1992         default:\r
1993           EFM_ASSERT(0);\r
1994           break;\r
1995       }\r
1996       break;\r
1997 \r
1998     case CMU_LFEPRESC0_REG:\r
1999       switch (clock)\r
2000       {\r
2001 #if defined( _CMU_LFEPRESC0_RTCC_MASK )\r
2002         case cmuClock_RTCC:\r
2003           EFM_ASSERT(presc <= 0U);\r
2004 \r
2005           /* LF register about to be modified require sync. Busy check. */\r
2006           syncReg(CMU_SYNCBUSY_LFEPRESC0);\r
2007 \r
2008           CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK)\r
2009                            | (presc << _CMU_LFEPRESC0_RTCC_SHIFT);\r
2010           break;\r
2011 #endif\r
2012 \r
2013         default:\r
2014           EFM_ASSERT(0);\r
2015           break;\r
2016       }\r
2017       break;\r
2018 \r
2019     default:\r
2020       EFM_ASSERT(0);\r
2021       break;\r
2022   }\r
2023 }\r
2024 #endif\r
2025 \r
2026 \r
2027 /***************************************************************************//**\r
2028  * @brief\r
2029  *   Get currently selected reference clock used for a clock branch.\r
2030  *\r
2031  * @param[in] clock\r
2032  *   Clock branch to fetch selected ref. clock for. One of:\r
2033  *   @li #cmuClock_HF\r
2034  *   @li #cmuClock_LFA\r
2035  *   @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO\r
2036  *   @li #cmuClock_LFC\r
2037  *   @endif            @if _SILICON_LABS_32B_PLATFORM_2\r
2038  *   @li #cmuClock_LFE\r
2039  *   @endif\r
2040  *   @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT\r
2041  *   @li #cmuClock_USBC\r
2042  *   @endif\r
2043  *\r
2044  * @return\r
2045  *   Reference clock used for clocking selected branch, #cmuSelect_Error if\r
2046  *   invalid @p clock provided.\r
2047  ******************************************************************************/\r
2048 CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock)\r
2049 {\r
2050   CMU_Select_TypeDef ret = cmuSelect_Disabled;\r
2051   uint32_t selReg;\r
2052 \r
2053   selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;\r
2054 \r
2055   switch (selReg)\r
2056   {\r
2057     case CMU_HFCLKSEL_REG:\r
2058 #if defined( _CMU_HFCLKSEL_HF_MASK )\r
2059       switch (CMU->HFCLKSEL & _CMU_HFCLKSEL_HF_MASK)\r
2060       {\r
2061         case CMU_HFCLKSEL_HF_LFXO:\r
2062           ret = cmuSelect_LFXO;\r
2063           break;\r
2064 \r
2065         case CMU_HFCLKSEL_HF_LFRCO:\r
2066           ret = cmuSelect_LFRCO;\r
2067           break;\r
2068 \r
2069         case CMU_HFCLKSEL_HF_HFXO:\r
2070           ret = cmuSelect_HFXO;\r
2071           break;\r
2072 \r
2073         default:\r
2074           ret = cmuSelect_HFRCO;\r
2075           break;\r
2076       }\r
2077 #else\r
2078       switch (CMU->STATUS\r
2079               & (CMU_STATUS_HFRCOSEL\r
2080                  | CMU_STATUS_HFXOSEL\r
2081                  | CMU_STATUS_LFRCOSEL\r
2082 #if defined( CMU_STATUS_USHFRCODIV2SEL )\r
2083                  | CMU_STATUS_USHFRCODIV2SEL\r
2084 #endif\r
2085                  | CMU_STATUS_LFXOSEL))\r
2086       {\r
2087         case CMU_STATUS_LFXOSEL:\r
2088           ret = cmuSelect_LFXO;\r
2089           break;\r
2090 \r
2091         case CMU_STATUS_LFRCOSEL:\r
2092           ret = cmuSelect_LFRCO;\r
2093           break;\r
2094 \r
2095         case CMU_STATUS_HFXOSEL:\r
2096           ret = cmuSelect_HFXO;\r
2097           break;\r
2098 \r
2099 #if defined( CMU_STATUS_USHFRCODIV2SEL )\r
2100         case CMU_STATUS_USHFRCODIV2SEL:\r
2101           ret = cmuSelect_USHFRCODIV2;\r
2102           break;\r
2103 #endif\r
2104 \r
2105         default:\r
2106           ret = cmuSelect_HFRCO;\r
2107           break;\r
2108       }\r
2109 #endif\r
2110       break;\r
2111 \r
2112     case CMU_LFACLKSEL_REG:\r
2113 #if defined( _CMU_LFCLKSEL_MASK )\r
2114       switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK)\r
2115       {\r
2116         case CMU_LFCLKSEL_LFA_LFRCO:\r
2117           ret = cmuSelect_LFRCO;\r
2118           break;\r
2119 \r
2120         case CMU_LFCLKSEL_LFA_LFXO:\r
2121           ret = cmuSelect_LFXO;\r
2122           break;\r
2123 \r
2124 #if defined( CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2 )\r
2125         case CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:\r
2126           ret = cmuSelect_CORELEDIV2;\r
2127           break;\r
2128 #endif\r
2129 \r
2130         default:\r
2131 #if defined( CMU_LFCLKSEL_LFAE )\r
2132           if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK)\r
2133           {\r
2134             ret = cmuSelect_ULFRCO;\r
2135             break;\r
2136           }\r
2137 #else\r
2138           ret = cmuSelect_Disabled;\r
2139 #endif\r
2140           break;\r
2141       }\r
2142 #endif /* _CMU_LFCLKSEL_MASK */\r
2143 \r
2144 #if defined( _CMU_LFACLKSEL_MASK )\r
2145       switch (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK)\r
2146       {\r
2147         case CMU_LFACLKSEL_LFA_LFRCO:\r
2148           ret = cmuSelect_LFRCO;\r
2149           break;\r
2150 \r
2151         case CMU_LFACLKSEL_LFA_LFXO:\r
2152           ret = cmuSelect_LFXO;\r
2153           break;\r
2154 \r
2155         case CMU_LFACLKSEL_LFA_ULFRCO:\r
2156           ret = cmuSelect_ULFRCO;\r
2157           break;\r
2158 \r
2159 #if defined( _CMU_LFACLKSEL_LFA_HFCLKLE )\r
2160         case CMU_LFACLKSEL_LFA_HFCLKLE:\r
2161           ret = cmuSelect_HFCLKLE;\r
2162           break;\r
2163 #endif\r
2164 \r
2165         default:\r
2166           ret = cmuSelect_Disabled;\r
2167           break;\r
2168       }\r
2169 #endif\r
2170       break;\r
2171 \r
2172     case CMU_LFBCLKSEL_REG:\r
2173 #if defined( _CMU_LFCLKSEL_MASK )\r
2174       switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK)\r
2175       {\r
2176         case CMU_LFCLKSEL_LFB_LFRCO:\r
2177           ret = cmuSelect_LFRCO;\r
2178           break;\r
2179 \r
2180         case CMU_LFCLKSEL_LFB_LFXO:\r
2181           ret = cmuSelect_LFXO;\r
2182           break;\r
2183 \r
2184 #if defined( CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2 )\r
2185         case CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2:\r
2186           ret = cmuSelect_CORELEDIV2;\r
2187           break;\r
2188 #endif\r
2189 \r
2190 #if defined( CMU_LFCLKSEL_LFB_HFCLKLE )\r
2191         case CMU_LFCLKSEL_LFB_HFCLKLE:\r
2192           ret = cmuSelect_HFCLKLE;\r
2193           break;\r
2194 #endif\r
2195 \r
2196         default:\r
2197 #if defined( CMU_LFCLKSEL_LFBE )\r
2198           if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK)\r
2199           {\r
2200             ret = cmuSelect_ULFRCO;\r
2201             break;\r
2202           }\r
2203 #else\r
2204           ret = cmuSelect_Disabled;\r
2205 #endif\r
2206           break;\r
2207       }\r
2208 #endif /* _CMU_LFCLKSEL_MASK */\r
2209 \r
2210 #if defined( _CMU_LFBCLKSEL_MASK )\r
2211       switch (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK)\r
2212       {\r
2213         case CMU_LFBCLKSEL_LFB_LFRCO:\r
2214           ret = cmuSelect_LFRCO;\r
2215           break;\r
2216 \r
2217         case CMU_LFBCLKSEL_LFB_LFXO:\r
2218           ret = cmuSelect_LFXO;\r
2219           break;\r
2220 \r
2221         case CMU_LFBCLKSEL_LFB_ULFRCO:\r
2222           ret = cmuSelect_ULFRCO;\r
2223           break;\r
2224 \r
2225         case CMU_LFBCLKSEL_LFB_HFCLKLE:\r
2226           ret = cmuSelect_HFCLKLE;\r
2227           break;\r
2228 \r
2229         default:\r
2230           ret = cmuSelect_Disabled;\r
2231           break;\r
2232       }\r
2233 #endif\r
2234       break;\r
2235 \r
2236 #if defined( _CMU_LFCLKSEL_LFC_MASK )\r
2237     case CMU_LFCCLKSEL_REG:\r
2238       switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK)\r
2239       {\r
2240         case CMU_LFCLKSEL_LFC_LFRCO:\r
2241           ret = cmuSelect_LFRCO;\r
2242           break;\r
2243 \r
2244         case CMU_LFCLKSEL_LFC_LFXO:\r
2245           ret = cmuSelect_LFXO;\r
2246           break;\r
2247 \r
2248         default:\r
2249           ret = cmuSelect_Disabled;\r
2250           break;\r
2251       }\r
2252       break;\r
2253 #endif\r
2254 \r
2255 #if defined( _CMU_LFECLKSEL_LFE_MASK )\r
2256     case CMU_LFECLKSEL_REG:\r
2257       switch (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK)\r
2258       {\r
2259         case CMU_LFECLKSEL_LFE_LFRCO:\r
2260           ret = cmuSelect_LFRCO;\r
2261           break;\r
2262 \r
2263         case CMU_LFECLKSEL_LFE_LFXO:\r
2264           ret = cmuSelect_LFXO;\r
2265           break;\r
2266 \r
2267         case CMU_LFECLKSEL_LFE_ULFRCO:\r
2268           ret = cmuSelect_ULFRCO;\r
2269           break;\r
2270 \r
2271 #if defined ( _CMU_LFECLKSEL_LFE_HFCLKLE )\r
2272         case CMU_LFECLKSEL_LFE_HFCLKLE:\r
2273           ret = cmuSelect_HFCLKLE;\r
2274           break;\r
2275 #endif\r
2276 \r
2277         default:\r
2278           ret = cmuSelect_Disabled;\r
2279           break;\r
2280       }\r
2281       break;\r
2282 #endif /* CMU_LFECLKSEL_REG */\r
2283 \r
2284     case CMU_DBGCLKSEL_REG:\r
2285 #if defined( _CMU_DBGCLKSEL_DBG_MASK )\r
2286       switch (CMU->DBGCLKSEL & _CMU_DBGCLKSEL_DBG_MASK)\r
2287       {\r
2288         case CMU_DBGCLKSEL_DBG_HFCLK:\r
2289           ret = cmuSelect_HFCLK;\r
2290           break;\r
2291 \r
2292         case CMU_DBGCLKSEL_DBG_AUXHFRCO:\r
2293           ret = cmuSelect_AUXHFRCO;\r
2294           break;\r
2295       }\r
2296 #else\r
2297       ret = cmuSelect_AUXHFRCO;\r
2298 #endif /* CMU_DBGCLKSEL_DBG */\r
2299 \r
2300 #if defined( _CMU_CTRL_DBGCLK_MASK )\r
2301       switch(CMU->CTRL & _CMU_CTRL_DBGCLK_MASK)\r
2302       {\r
2303         case CMU_CTRL_DBGCLK_AUXHFRCO:\r
2304           ret = cmuSelect_AUXHFRCO;\r
2305           break;\r
2306 \r
2307         case CMU_CTRL_DBGCLK_HFCLK:\r
2308           ret = cmuSelect_HFCLK;\r
2309           break;\r
2310       }\r
2311 #else\r
2312       ret = cmuSelect_AUXHFRCO;\r
2313 #endif\r
2314       break;\r
2315 \r
2316 \r
2317 #if defined( USB_PRESENT )\r
2318     case CMU_USBCCLKSEL_REG:\r
2319       switch (CMU->STATUS\r
2320               & (CMU_STATUS_USBCLFXOSEL\r
2321 #if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)\r
2322                  | CMU_STATUS_USBCHFCLKSEL\r
2323 #endif\r
2324 #if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)\r
2325                  | CMU_STATUS_USBCUSHFRCOSEL\r
2326 #endif\r
2327                  | CMU_STATUS_USBCLFRCOSEL))\r
2328       {\r
2329 #if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)\r
2330         case CMU_STATUS_USBCHFCLKSEL:\r
2331           ret = cmuSelect_HFCLK;\r
2332           break;\r
2333 #endif\r
2334 \r
2335 #if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)\r
2336         case CMU_STATUS_USBCUSHFRCOSEL:\r
2337           ret = cmuSelect_USHFRCO;\r
2338           break;\r
2339 #endif\r
2340 \r
2341         case CMU_STATUS_USBCLFXOSEL:\r
2342           ret = cmuSelect_LFXO;\r
2343           break;\r
2344 \r
2345         case CMU_STATUS_USBCLFRCOSEL:\r
2346           ret = cmuSelect_LFRCO;\r
2347           break;\r
2348 \r
2349         default:\r
2350           ret = cmuSelect_Disabled;\r
2351           break;\r
2352       }\r
2353       break;\r
2354 #endif\r
2355 \r
2356     default:\r
2357       EFM_ASSERT(0);\r
2358       ret = cmuSelect_Error;\r
2359       break;\r
2360   }\r
2361 \r
2362   return ret;\r
2363 }\r
2364 \r
2365 \r
2366 /***************************************************************************//**\r
2367  * @brief\r
2368  *   Select reference clock/oscillator used for a clock branch.\r
2369  *\r
2370  * @details\r
2371  *   Notice that if a selected reference is not enabled prior to selecting its\r
2372  *   use, it will be enabled, and this function will wait for the selected\r
2373  *   oscillator to be stable. It will however NOT be disabled if another\r
2374  *   reference clock is selected later.\r
2375  *\r
2376  *   This feature is particularly important if selecting a new reference\r
2377  *   clock for the clock branch clocking the core, otherwise the system\r
2378  *   may halt.\r
2379  *\r
2380  * @param[in] clock\r
2381  *   Clock branch to select reference clock for. One of:\r
2382  *   @li #cmuClock_HF\r
2383  *   @li #cmuClock_LFA\r
2384  *   @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO\r
2385  *   @li #cmuClock_LFC\r
2386  *   @endif            @if _SILICON_LABS_32B_PLATFORM_2\r
2387  *   @li #cmuClock_LFE\r
2388  *   @endif\r
2389  *   @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT\r
2390  *   @li #cmuClock_USBC\r
2391  *   @endif\r
2392  *\r
2393  * @param[in] ref\r
2394  *   Reference selected for clocking, please refer to reference manual for\r
2395  *   for details on which reference is available for a specific clock branch.\r
2396  *   @li #cmuSelect_HFRCO\r
2397  *   @li #cmuSelect_LFRCO\r
2398  *   @li #cmuSelect_HFXO\r
2399  *   @li #cmuSelect_LFXO\r
2400  *   @li #cmuSelect_CORELEDIV2\r
2401  *   @li #cmuSelect_AUXHFRCO\r
2402  *   @li #cmuSelect_HFCLK @ifnot DOXYDOC_EFM32_GECKO_FAMILY\r
2403  *   @li #cmuSelect_ULFRCO\r
2404  *   @endif\r
2405  ******************************************************************************/\r
2406 void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)\r
2407 {\r
2408   uint32_t        select = cmuOsc_HFRCO;\r
2409   CMU_Osc_TypeDef osc    = cmuOsc_HFRCO;\r
2410   uint32_t        freq;\r
2411   uint32_t        tmp;\r
2412   uint32_t        selRegId;\r
2413 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
2414   volatile uint32_t *selReg = NULL;\r
2415 #endif\r
2416 #if defined( CMU_LFCLKSEL_LFAE_ULFRCO )\r
2417   uint32_t        lfExtended = 0;\r
2418 #endif\r
2419 \r
2420   selRegId = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;\r
2421 \r
2422   switch (selRegId)\r
2423   {\r
2424     case CMU_HFCLKSEL_REG:\r
2425       switch (ref)\r
2426       {\r
2427         case cmuSelect_LFXO:\r
2428 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
2429           select = CMU_HFCLKSEL_HF_LFXO;\r
2430 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
2431           select = CMU_CMD_HFCLKSEL_LFXO;\r
2432 #endif\r
2433           osc = cmuOsc_LFXO;\r
2434           break;\r
2435 \r
2436         case cmuSelect_LFRCO:\r
2437 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
2438           select = CMU_HFCLKSEL_HF_LFRCO;\r
2439 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
2440           select = CMU_CMD_HFCLKSEL_LFRCO;\r
2441 #endif\r
2442           osc = cmuOsc_LFRCO;\r
2443           break;\r
2444 \r
2445         case cmuSelect_HFXO:\r
2446           osc = cmuOsc_HFXO;\r
2447 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
2448           select = CMU_HFCLKSEL_HF_HFXO;\r
2449           /* Adjust HFXO buffer current for high frequencies, */\r
2450           /* enable WSHFLE for frequencies above 32MHz.       */\r
2451           if (SystemHFXOClockGet() > 32000000)\r
2452           {\r
2453             CMU->CTRL |= CMU_CTRL_WSHFLE;\r
2454           }\r
2455 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
2456           select = CMU_CMD_HFCLKSEL_HFXO;\r
2457 #if defined( CMU_CTRL_HFLE )\r
2458           /* Adjust HFXO buffer current for high frequencies,     */\r
2459           /* enable HFLE for frequencies above CMU_MAX_FREQ_HFLE. */\r
2460           if(SystemHFXOClockGet() > CMU_MAX_FREQ_HFLE())\r
2461           {\r
2462             CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)\r
2463                         | CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ\r
2464             /* Must have HFLE enabled to access some LE peripherals >=32MHz */\r
2465                         | CMU_CTRL_HFLE;\r
2466 \r
2467             /* Set HFLE and DIV4 factor for peripheral clock if HFCORE  */\r
2468             /* clock for LE is enabled.                                 */\r
2469             if (CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE)\r
2470             {\r
2471               BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
2472                               _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
2473             }\r
2474           }\r
2475           else\r
2476           {\r
2477             /* This can happen if the user configures the EFM32_HFXO_FREQ to */\r
2478             /* use another oscillator frequency */\r
2479             CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)\r
2480                         | CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ;\r
2481           }\r
2482 #endif\r
2483 #endif\r
2484           break;\r
2485 \r
2486         case cmuSelect_HFRCO:\r
2487 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
2488           select = CMU_HFCLKSEL_HF_HFRCO;\r
2489 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
2490           select = CMU_CMD_HFCLKSEL_HFRCO;\r
2491 #endif\r
2492           osc = cmuOsc_HFRCO;\r
2493           break;\r
2494 \r
2495 #if defined( CMU_CMD_HFCLKSEL_USHFRCODIV2 )\r
2496         case cmuSelect_USHFRCODIV2:\r
2497           select = CMU_CMD_HFCLKSEL_USHFRCODIV2;\r
2498           osc = cmuOsc_USHFRCO;\r
2499           break;\r
2500 #endif\r
2501 \r
2502 #if defined( CMU_LFCLKSEL_LFAE_ULFRCO ) || defined( CMU_LFACLKSEL_LFA_ULFRCO )\r
2503         case cmuSelect_ULFRCO:\r
2504           /* ULFRCO cannot be used as HFCLK  */\r
2505           EFM_ASSERT(0);\r
2506           return;\r
2507 #endif\r
2508 \r
2509         default:\r
2510           EFM_ASSERT(0);\r
2511           return;\r
2512       }\r
2513 \r
2514       /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2515       CMU_OscillatorEnable(osc, true, true);\r
2516 \r
2517       /* Configure worst case wait states for flash access before selecting */\r
2518       flashWaitStateMax();\r
2519 \r
2520       /* Switch to selected oscillator */\r
2521 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
2522       CMU->HFCLKSEL = select;\r
2523 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
2524       CMU->CMD = select;\r
2525 #endif\r
2526 \r
2527       /* Keep EMU module informed */\r
2528       EMU_UpdateOscConfig();\r
2529 \r
2530       /* Update CMSIS core clock variable */\r
2531       /* (The function will update the global variable) */\r
2532       freq = SystemCoreClockGet();\r
2533 \r
2534       /* Optimize flash access wait state setting for currently selected core clk */\r
2535       flashWaitStateControl(freq);\r
2536       break;\r
2537 \r
2538 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
2539     case CMU_LFACLKSEL_REG:\r
2540       selReg = (selReg == NULL) ? &CMU->LFACLKSEL : selReg;\r
2541 #if !defined( _CMU_LFACLKSEL_LFA_HFCLKLE )\r
2542       /* HFCLKCLE can not be used as LFACLK */\r
2543       EFM_ASSERT(ref != cmuSelect_HFCLKLE);\r
2544 #endif\r
2545     case CMU_LFECLKSEL_REG:\r
2546       selReg = (selReg == NULL) ? &CMU->LFECLKSEL : selReg;\r
2547 #if !defined( _CMU_LFECLKSEL_LFE_HFCLKLE )\r
2548       /* HFCLKCLE can not be used as LFECLK */\r
2549       EFM_ASSERT(ref != cmuSelect_HFCLKLE);\r
2550 #endif\r
2551     case CMU_LFBCLKSEL_REG:\r
2552       selReg = (selReg == NULL) ? &CMU->LFBCLKSEL : selReg;\r
2553       switch (ref)\r
2554       {\r
2555         case cmuSelect_Disabled:\r
2556           tmp = _CMU_LFACLKSEL_LFA_DISABLED;\r
2557           break;\r
2558 \r
2559         case cmuSelect_LFXO:\r
2560           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2561           CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
2562           tmp = _CMU_LFACLKSEL_LFA_LFXO;\r
2563           break;\r
2564 \r
2565         case cmuSelect_LFRCO:\r
2566           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2567           CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
2568           tmp = _CMU_LFACLKSEL_LFA_LFRCO;\r
2569           break;\r
2570 \r
2571         case cmuSelect_HFCLKLE:\r
2572           /* Ensure HFCORE to LE clocking is enabled */\r
2573           BUS_RegBitWrite(&CMU->HFBUSCLKEN0, _CMU_HFBUSCLKEN0_LE_SHIFT, 1);\r
2574           tmp = _CMU_LFBCLKSEL_LFB_HFCLKLE;\r
2575 \r
2576           /* If core frequency is > 32MHz enable WSHFLE */\r
2577           freq = SystemCoreClockGet();\r
2578           if (freq > 32000000U)\r
2579           {\r
2580             /* Enable CMU HFLE */\r
2581             BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_WSHFLE_SHIFT, 1);\r
2582 \r
2583             /* Enable DIV4 factor for peripheral clock */\r
2584             BUS_RegBitWrite(&CMU->HFPRESC, _CMU_HFPRESC_HFCLKLEPRESC_SHIFT, 1);\r
2585           }\r
2586           break;\r
2587 \r
2588         case cmuSelect_ULFRCO:\r
2589           /* ULFRCO is always on, there is no need to enable it. */\r
2590           tmp = _CMU_LFACLKSEL_LFA_ULFRCO;\r
2591           break;\r
2592 \r
2593         default:\r
2594           EFM_ASSERT(0);\r
2595           return;\r
2596       }\r
2597       *selReg = tmp;\r
2598       break;\r
2599 \r
2600 #elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
2601     case CMU_LFACLKSEL_REG:\r
2602     case CMU_LFBCLKSEL_REG:\r
2603       switch (ref)\r
2604       {\r
2605         case cmuSelect_Disabled:\r
2606           tmp = _CMU_LFCLKSEL_LFA_DISABLED;\r
2607           break;\r
2608 \r
2609         case cmuSelect_LFXO:\r
2610           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2611           CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
2612           tmp = _CMU_LFCLKSEL_LFA_LFXO;\r
2613           break;\r
2614 \r
2615         case cmuSelect_LFRCO:\r
2616           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2617           CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
2618           tmp = _CMU_LFCLKSEL_LFA_LFRCO;\r
2619           break;\r
2620 \r
2621         case cmuSelect_CORELEDIV2:\r
2622           /* Ensure HFCORE to LE clocking is enabled */\r
2623           BUS_RegBitWrite(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_LE_SHIFT, 1);\r
2624           tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2;\r
2625 #if defined( CMU_CTRL_HFLE )\r
2626           /* If core frequency is higher than CMU_MAX_FREQ_HFLE on\r
2627              Giant/Leopard/Wonder, enable HFLE and DIV4. */\r
2628           freq = SystemCoreClockGet();\r
2629           if(freq > CMU_MAX_FREQ_HFLE())\r
2630           {\r
2631             /* Enable CMU HFLE */\r
2632             BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);\r
2633 \r
2634             /* Enable DIV4 factor for peripheral clock */\r
2635             BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
2636                             _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
2637           }\r
2638 #endif\r
2639           break;\r
2640 \r
2641 #if defined( CMU_LFCLKSEL_LFAE_ULFRCO )\r
2642         case cmuSelect_ULFRCO:\r
2643           /* ULFRCO is always enabled */\r
2644           tmp = _CMU_LFCLKSEL_LFA_DISABLED;\r
2645           lfExtended = 1;\r
2646           break;\r
2647 #endif\r
2648 \r
2649         default:\r
2650           /* Illegal clock source for LFA/LFB selected */\r
2651           EFM_ASSERT(0);\r
2652           return;\r
2653       }\r
2654 \r
2655       /* Apply select */\r
2656       if (selRegId == CMU_LFACLKSEL_REG)\r
2657       {\r
2658 #if defined( _CMU_LFCLKSEL_LFAE_MASK )\r
2659         CMU->LFCLKSEL = (CMU->LFCLKSEL\r
2660                          & ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK))\r
2661                         | (tmp << _CMU_LFCLKSEL_LFA_SHIFT)\r
2662                         | (lfExtended << _CMU_LFCLKSEL_LFAE_SHIFT);\r
2663 #else\r
2664         CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFA_MASK)\r
2665                         | (tmp << _CMU_LFCLKSEL_LFA_SHIFT);\r
2666 #endif\r
2667       }\r
2668       else\r
2669       {\r
2670 #if defined( _CMU_LFCLKSEL_LFBE_MASK )\r
2671         CMU->LFCLKSEL = (CMU->LFCLKSEL\r
2672                          & ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK))\r
2673                         | (tmp << _CMU_LFCLKSEL_LFB_SHIFT)\r
2674                         | (lfExtended << _CMU_LFCLKSEL_LFBE_SHIFT);\r
2675 #else\r
2676         CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFB_MASK)\r
2677                         | (tmp << _CMU_LFCLKSEL_LFB_SHIFT);\r
2678 #endif\r
2679       }\r
2680       break;\r
2681 \r
2682 #if defined( _CMU_LFCLKSEL_LFC_MASK )\r
2683     case CMU_LFCCLKSEL_REG:\r
2684       switch(ref)\r
2685       {\r
2686         case cmuSelect_Disabled:\r
2687           tmp = _CMU_LFCLKSEL_LFA_DISABLED;\r
2688           break;\r
2689 \r
2690         case cmuSelect_LFXO:\r
2691           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2692           CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
2693           tmp = _CMU_LFCLKSEL_LFC_LFXO;\r
2694           break;\r
2695 \r
2696         case cmuSelect_LFRCO:\r
2697           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2698           CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
2699           tmp = _CMU_LFCLKSEL_LFC_LFRCO;\r
2700           break;\r
2701 \r
2702         default:\r
2703           /* Illegal clock source for LFC selected */\r
2704           EFM_ASSERT(0);\r
2705           return;\r
2706       }\r
2707 \r
2708       /* Apply select */\r
2709       CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFC_MASK)\r
2710                       | (tmp << _CMU_LFCLKSEL_LFC_SHIFT);\r
2711       break;\r
2712 #endif\r
2713 #endif\r
2714 \r
2715 #if defined( CMU_DBGCLKSEL_DBG ) || defined( CMU_CTRL_DBGCLK )\r
2716     case CMU_DBGCLKSEL_REG:\r
2717       switch(ref)\r
2718       {\r
2719 #if defined( CMU_DBGCLKSEL_DBG )\r
2720         case cmuSelect_AUXHFRCO:\r
2721           /* Select AUXHFRCO as debug clock */\r
2722           CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_AUXHFRCO;\r
2723           break;\r
2724 \r
2725         case cmuSelect_HFCLK:\r
2726           /* Select divided HFCLK as debug clock */\r
2727           CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_HFCLK;\r
2728           break;\r
2729 #endif\r
2730 \r
2731 #if defined( CMU_CTRL_DBGCLK )\r
2732         case cmuSelect_AUXHFRCO:\r
2733           /* Select AUXHFRCO as debug clock */\r
2734           CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))\r
2735                       | CMU_CTRL_DBGCLK_AUXHFRCO;\r
2736           break;\r
2737 \r
2738         case cmuSelect_HFCLK:\r
2739           /* Select divided HFCLK as debug clock */\r
2740           CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))\r
2741                       | CMU_CTRL_DBGCLK_HFCLK;\r
2742           break;\r
2743 #endif\r
2744 \r
2745         default:\r
2746           /* Illegal clock source for debug selected */\r
2747           EFM_ASSERT(0);\r
2748           return;\r
2749       }\r
2750       break;\r
2751 #endif\r
2752 \r
2753 #if defined(USB_PRESENT)\r
2754     case CMU_USBCCLKSEL_REG:\r
2755       switch(ref)\r
2756       {\r
2757         case cmuSelect_LFXO:\r
2758           /* Select LFXO as clock source for USB, can only be used in sleep mode */\r
2759           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2760           CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
2761 \r
2762           /* Switch oscillator */\r
2763           CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;\r
2764 \r
2765           /* Wait until clock is activated */\r
2766           while((CMU->STATUS & CMU_STATUS_USBCLFXOSEL)==0)\r
2767           {\r
2768           }\r
2769           break;\r
2770 \r
2771         case cmuSelect_LFRCO:\r
2772           /* Select LFRCO as clock source for USB, can only be used in sleep mode */\r
2773           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2774           CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
2775 \r
2776           /* Switch oscillator */\r
2777           CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;\r
2778 \r
2779           /* Wait until clock is activated */\r
2780           while((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL)==0)\r
2781           {\r
2782           }\r
2783           break;\r
2784 \r
2785 #if defined( CMU_STATUS_USBCHFCLKSEL )\r
2786         case cmuSelect_HFCLK:\r
2787           /* Select undivided HFCLK as clock source for USB */\r
2788           /* Oscillator must already be enabled to avoid a core lockup */\r
2789           CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;\r
2790           /* Wait until clock is activated */\r
2791           while((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL)==0)\r
2792           {\r
2793           }\r
2794           break;\r
2795 #endif\r
2796 \r
2797 #if defined( CMU_CMD_USBCCLKSEL_USHFRCO )\r
2798         case cmuSelect_USHFRCO:\r
2799           /* Select USHFRCO as clock source for USB */\r
2800           /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
2801           CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);\r
2802 \r
2803           /* Switch oscillator */\r
2804           CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;\r
2805 \r
2806           /* Wait until clock is activated */\r
2807           while((CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL)==0)\r
2808           {\r
2809           }\r
2810           break;\r
2811 #endif\r
2812 \r
2813         default:\r
2814           /* Illegal clock source for USB */\r
2815           EFM_ASSERT(0);\r
2816           return;\r
2817       }\r
2818       break;\r
2819 #endif\r
2820 \r
2821     default:\r
2822       EFM_ASSERT(0);\r
2823       break;\r
2824   }\r
2825 }\r
2826 \r
2827 \r
2828 /**************************************************************************//**\r
2829  * @brief\r
2830  *   CMU low frequency register synchronization freeze control.\r
2831  *\r
2832  * @details\r
2833  *   Some CMU registers requires synchronization into the low frequency (LF)\r
2834  *   domain. The freeze feature allows for several such registers to be\r
2835  *   modified before passing them to the LF domain simultaneously (which\r
2836  *   takes place when the freeze mode is disabled).\r
2837  *\r
2838  *   Another usage scenario of this feature, is when using an API (such\r
2839  *   as the CMU API) for modifying several bit fields consecutively in the\r
2840  *   same register. If freeze mode is enabled during this sequence, stalling\r
2841  *   can be avoided.\r
2842  *\r
2843  * @note\r
2844  *   When enabling freeze mode, this function will wait for all current\r
2845  *   ongoing CMU synchronization to LF domain to complete (Normally\r
2846  *   synchronization will not be in progress.) However for this reason, when\r
2847  *   using freeze mode, modifications of registers requiring LF synchronization\r
2848  *   should be done within one freeze enable/disable block to avoid unecessary\r
2849  *   stalling.\r
2850  *\r
2851  * @param[in] enable\r
2852  *   @li true - enable freeze, modified registers are not propagated to the\r
2853  *       LF domain\r
2854  *   @li false - disable freeze, modified registers are propagated to LF\r
2855  *       domain\r
2856  *****************************************************************************/\r
2857 void CMU_FreezeEnable(bool enable)\r
2858 {\r
2859   if (enable)\r
2860   {\r
2861     /* Wait for any ongoing LF synchronization to complete. This is just to */\r
2862     /* protect against the rare case when a user                            */\r
2863     /* - modifies a register requiring LF sync                              */\r
2864     /* - then enables freeze before LF sync completed                       */\r
2865     /* - then modifies the same register again                              */\r
2866     /* since modifying a register while it is in sync progress should be    */\r
2867     /* avoided.                                                             */\r
2868     while (CMU->SYNCBUSY)\r
2869     {\r
2870     }\r
2871 \r
2872     CMU->FREEZE = CMU_FREEZE_REGFREEZE;\r
2873   }\r
2874   else\r
2875   {\r
2876     CMU->FREEZE = 0;\r
2877   }\r
2878 }\r
2879 \r
2880 \r
2881 #if defined( _CMU_HFRCOCTRL_BAND_MASK )\r
2882 /***************************************************************************//**\r
2883  * @brief\r
2884  *   Get HFRCO band in use.\r
2885  *\r
2886  * @return\r
2887  *   HFRCO band in use.\r
2888  ******************************************************************************/\r
2889 CMU_HFRCOBand_TypeDef CMU_HFRCOBandGet(void)\r
2890 {\r
2891   return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK)\r
2892                                  >> _CMU_HFRCOCTRL_BAND_SHIFT);\r
2893 }\r
2894 #endif /* _CMU_HFRCOCTRL_BAND_MASK */\r
2895 \r
2896 \r
2897 #if defined( _CMU_HFRCOCTRL_BAND_MASK )\r
2898 /***************************************************************************//**\r
2899  * @brief\r
2900  *   Set HFRCO band and the tuning value based on the value in the calibration\r
2901  *   table made during production.\r
2902  *\r
2903  * @param[in] band\r
2904  *   HFRCO band to activate.\r
2905  ******************************************************************************/\r
2906 void CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)\r
2907 {\r
2908   uint32_t           tuning;\r
2909   uint32_t           freq;\r
2910   CMU_Select_TypeDef osc;\r
2911 \r
2912   /* Read tuning value from calibration table */\r
2913   switch (band)\r
2914   {\r
2915     case cmuHFRCOBand_1MHz:\r
2916       tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK)\r
2917                >> _DEVINFO_HFRCOCAL0_BAND1_SHIFT;\r
2918       break;\r
2919 \r
2920     case cmuHFRCOBand_7MHz:\r
2921       tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK)\r
2922                >> _DEVINFO_HFRCOCAL0_BAND7_SHIFT;\r
2923       break;\r
2924 \r
2925     case cmuHFRCOBand_11MHz:\r
2926       tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK)\r
2927                >> _DEVINFO_HFRCOCAL0_BAND11_SHIFT;\r
2928       break;\r
2929 \r
2930     case cmuHFRCOBand_14MHz:\r
2931       tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK)\r
2932                >> _DEVINFO_HFRCOCAL0_BAND14_SHIFT;\r
2933       break;\r
2934 \r
2935     case cmuHFRCOBand_21MHz:\r
2936       tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK)\r
2937                >> _DEVINFO_HFRCOCAL1_BAND21_SHIFT;\r
2938       break;\r
2939 \r
2940 #if defined( _CMU_HFRCOCTRL_BAND_28MHZ )\r
2941     case cmuHFRCOBand_28MHz:\r
2942       tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK)\r
2943                >> _DEVINFO_HFRCOCAL1_BAND28_SHIFT;\r
2944       break;\r
2945 #endif\r
2946 \r
2947     default:\r
2948       EFM_ASSERT(0);\r
2949       return;\r
2950   }\r
2951 \r
2952   /* If HFRCO is used for core clock, we have to consider flash access WS. */\r
2953   osc = CMU_ClockSelectGet(cmuClock_HF);\r
2954   if (osc == cmuSelect_HFRCO)\r
2955   {\r
2956     /* Configure worst case wait states for flash access before setting divider */\r
2957     flashWaitStateMax();\r
2958   }\r
2959 \r
2960   /* Set band/tuning */\r
2961   CMU->HFRCOCTRL = (CMU->HFRCOCTRL &\r
2962                     ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK))\r
2963                    | (band << _CMU_HFRCOCTRL_BAND_SHIFT)\r
2964                    | (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT);\r
2965 \r
2966   /* If HFRCO is used for core clock, optimize flash WS */\r
2967   if (osc == cmuSelect_HFRCO)\r
2968   {\r
2969     /* Update CMSIS core clock variable and get current core clock */\r
2970     /* (The function will update the global variable) */\r
2971     /* NOTE! We need at least 21 cycles before setting zero wait state to flash */\r
2972     /* (i.e. WS0) when going from the 28MHz to 1MHz in the HFRCO band */\r
2973     freq = SystemCoreClockGet();\r
2974 \r
2975     /* Optimize flash access wait state setting for current core clk */\r
2976     flashWaitStateControl(freq);\r
2977   }\r
2978 }\r
2979 #endif /* _CMU_HFRCOCTRL_BAND_MASK */\r
2980 \r
2981 \r
2982 #if defined( _CMU_HFRCOCTRL_FREQRANGE_MASK )\r
2983 /**************************************************************************//**\r
2984  * @brief\r
2985  *   Get a pointer to the HFRCO frequency calibration word in DEVINFO\r
2986  *\r
2987  * @param[in] freq\r
2988  *   Frequency in Hz\r
2989  *\r
2990  * @return\r
2991  *   HFRCO calibration word for a given frequency\r
2992  *****************************************************************************/\r
2993 static uint32_t CMU_HFRCODevinfoGet(CMU_HFRCOFreq_TypeDef freq)\r
2994 {\r
2995   switch (freq)\r
2996   {\r
2997     /* 1, 2 and 4MHz share the same calibration word */\r
2998     case cmuHFRCOFreq_1M0Hz:\r
2999     case cmuHFRCOFreq_2M0Hz:\r
3000     case cmuHFRCOFreq_4M0Hz:\r
3001       return DEVINFO->HFRCOCAL0;\r
3002 \r
3003     case cmuHFRCOFreq_7M0Hz:\r
3004       return DEVINFO->HFRCOCAL3;\r
3005 \r
3006     case cmuHFRCOFreq_13M0Hz:\r
3007       return DEVINFO->HFRCOCAL6;\r
3008 \r
3009     case cmuHFRCOFreq_16M0Hz:\r
3010       return DEVINFO->HFRCOCAL7;\r
3011 \r
3012     case cmuHFRCOFreq_19M0Hz:\r
3013       return DEVINFO->HFRCOCAL8;\r
3014 \r
3015     case cmuHFRCOFreq_26M0Hz:\r
3016       return DEVINFO->HFRCOCAL10;\r
3017 \r
3018     case cmuHFRCOFreq_32M0Hz:\r
3019       return DEVINFO->HFRCOCAL11;\r
3020 \r
3021     case cmuHFRCOFreq_38M0Hz:\r
3022       return DEVINFO->HFRCOCAL12;\r
3023 \r
3024     default: /* cmuHFRCOFreq_UserDefined */\r
3025       return 0;\r
3026   }\r
3027 }\r
3028 \r
3029 \r
3030 /***************************************************************************//**\r
3031  * @brief\r
3032  *   Get HFRCO frequency enumeration in use\r
3033  *\r
3034  * @return\r
3035  *   HFRCO frequency enumeration in use\r
3036  ******************************************************************************/\r
3037 CMU_HFRCOFreq_TypeDef CMU_HFRCOFreqGet(void)\r
3038 {\r
3039   return (CMU_HFRCOFreq_TypeDef)SystemHfrcoFreq;\r
3040 }\r
3041 \r
3042 \r
3043 /***************************************************************************//**\r
3044  * @brief\r
3045  *   Set HFRCO calibration for the selected target frequency\r
3046  *\r
3047  * @param[in] freq\r
3048  *   HFRCO frequency band to set\r
3049  ******************************************************************************/\r
3050 void CMU_HFRCOFreqSet(CMU_HFRCOFreq_TypeDef freq)\r
3051 {\r
3052   uint32_t freqCal;\r
3053 \r
3054   /* Get DEVINFO index, set CMSIS frequency SystemHfrcoFreq */\r
3055   freqCal = CMU_HFRCODevinfoGet(freq);\r
3056   EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX));\r
3057   SystemHfrcoFreq = (uint32_t)freq;\r
3058 \r
3059   /* Set max wait-states while changing core clock */\r
3060   if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO)\r
3061   {\r
3062     flashWaitStateMax();\r
3063   }\r
3064 \r
3065   /* Wait for any previous sync to complete, and then set calibration data\r
3066      for the selected frequency.  */\r
3067   while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT));\r
3068 \r
3069   /* Check for valid calibration data */\r
3070   EFM_ASSERT(freqCal != UINT_MAX);\r
3071 \r
3072   /* Set divider in HFRCOCTRL for 1, 2 and 4MHz */\r
3073   switch(freq)\r
3074   {\r
3075     case cmuHFRCOFreq_1M0Hz:\r
3076       freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)\r
3077                 | CMU_HFRCOCTRL_CLKDIV_DIV4;\r
3078       break;\r
3079 \r
3080     case cmuHFRCOFreq_2M0Hz:\r
3081       freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)\r
3082                 | CMU_HFRCOCTRL_CLKDIV_DIV2;\r
3083       break;\r
3084 \r
3085     case cmuHFRCOFreq_4M0Hz:\r
3086       freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)\r
3087                 | CMU_HFRCOCTRL_CLKDIV_DIV1;\r
3088       break;\r
3089 \r
3090     default:\r
3091       break;\r
3092   }\r
3093   CMU->HFRCOCTRL = freqCal;\r
3094 \r
3095   /* Optimize flash access wait-state configuration for this frequency, */\r
3096   /* if HFRCO is reference for core clock.                              */\r
3097   if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO)\r
3098   {\r
3099     flashWaitStateControl((uint32_t)freq);\r
3100   }\r
3101 }\r
3102 #endif /* _CMU_HFRCOCTRL_FREQRANGE_MASK */\r
3103 \r
3104 #if defined( _CMU_HFRCOCTRL_SUDELAY_MASK )\r
3105 /***************************************************************************//**\r
3106  * @brief\r
3107  *   Get the HFRCO startup delay.\r
3108  *\r
3109  * @details\r
3110  *   Please refer to the reference manual for further details.\r
3111  *\r
3112  * @return\r
3113  *   The startup delay in use.\r
3114  ******************************************************************************/\r
3115 uint32_t CMU_HFRCOStartupDelayGet(void)\r
3116 {\r
3117   return (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK)\r
3118          >> _CMU_HFRCOCTRL_SUDELAY_SHIFT;\r
3119 }\r
3120 \r
3121 \r
3122 /***************************************************************************//**\r
3123  * @brief\r
3124  *   Set the HFRCO startup delay.\r
3125  *\r
3126  * @details\r
3127  *   Please refer to the reference manual for further details.\r
3128  *\r
3129  * @param[in] delay\r
3130  *   The startup delay to set (<= 31).\r
3131  ******************************************************************************/\r
3132 void CMU_HFRCOStartupDelaySet(uint32_t delay)\r
3133 {\r
3134   EFM_ASSERT(delay <= 31);\r
3135 \r
3136   delay &= _CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT;\r
3137   CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK))\r
3138                    | (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT);\r
3139 }\r
3140 #endif\r
3141 \r
3142 \r
3143 #if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )\r
3144 /***************************************************************************//**\r
3145  * @brief\r
3146  *   Enable or disable HFXO autostart\r
3147  *\r
3148  * @param[in] enRACStartSel\r
3149  *   If true, HFXO is automatically started and selected upon RAC wakeup.\r
3150  *   If false, HFXO is not started or selected automatically upon RAC wakeup.\r
3151  *\r
3152  * @param[in] enEM0EM1Start\r
3153  *   If true, HFXO is automatically started upon entering EM0/EM1 entry from\r
3154  *   EM2/EM3. HFXO selection has to be handled by the user.\r
3155  *   If false, HFXO is not started automatically when entering EM0/EM1.\r
3156  *\r
3157  * @param[in] enEM0EM1StartSel\r
3158  *   If true, HFXO is automatically started and immediately selected upon\r
3159  *   entering EM0/EM1 entry from EM2/EM3. Note that this option stalls the use of\r
3160  *   HFSRCCLK until HFXO becomes ready.\r
3161  *   If false, HFXO is not started or selected automatically when entering\r
3162  *   EM0/EM1.\r
3163  ******************************************************************************/\r
3164 void CMU_HFXOAutostartEnable(bool enRACStartSel,\r
3165                              bool enEM0EM1Start,\r
3166                              bool enEM0EM1StartSel)\r
3167 {\r
3168   uint32_t hfxoCtrl;\r
3169   hfxoCtrl = CMU->HFXOCTRL & ~(_CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK\r
3170                               | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK\r
3171                               | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK);\r
3172 \r
3173   hfxoCtrl |= (enRACStartSel ? CMU_HFXOCTRL_AUTOSTARTRDYSELRAC : 0)\r
3174               | (enEM0EM1Start ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0)\r
3175               | (enEM0EM1StartSel ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0);\r
3176 \r
3177   CMU->HFXOCTRL = hfxoCtrl;\r
3178 }\r
3179 #endif /* _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK */\r
3180 \r
3181 \r
3182 #if defined( _CMU_HFXOCTRL_MASK )\r
3183 /**************************************************************************//**\r
3184  * @brief\r
3185  *   Set HFXO control registers\r
3186  *\r
3187  * @note\r
3188  *   HFXO configuration should be obtained from a configuration tool,\r
3189  *   app note or xtal datasheet. This function disables the HFXO to ensure\r
3190  *   a valid state before update.\r
3191  *\r
3192  * @param[in] hfxoInit\r
3193  *    HFXO setup parameters\r
3194  *****************************************************************************/\r
3195 void CMU_HFXOInit(CMU_HFXOInit_TypeDef *hfxoInit)\r
3196 {\r
3197   uint32_t ishReg;\r
3198   uint32_t ishMax;\r
3199 \r
3200   /* Do not disable HFXO if it is currently selected as HF/Core clock */\r
3201   EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_HFXO);\r
3202 \r
3203   /* HFXO must be disabled before reconfiguration */\r
3204   CMU_OscillatorEnable(cmuOsc_HFXO, false, false);\r
3205 \r
3206   /* Apply control settings */\r
3207   BUS_RegMaskedWrite(&CMU->HFXOCTRL,\r
3208                      _CMU_HFXOCTRL_LOWPOWER_MASK\r
3209 #if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )\r
3210                      | _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK\r
3211 #endif\r
3212                      | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK\r
3213                      | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK,\r
3214                      (hfxoInit->lowPowerMode\r
3215                       ? CMU_HFXOCTRL_LOWPOWER : 0)\r
3216 #if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )\r
3217                      | (hfxoInit->autoStartSelOnRacWakeup\r
3218                         ? CMU_HFXOCTRL_AUTOSTARTRDYSELRAC : 0)\r
3219 #endif\r
3220                      | (hfxoInit->autoStartEm01\r
3221                         ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0)\r
3222                      | (hfxoInit->autoSelEm01\r
3223                         ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0));\r
3224 \r
3225   /* Set XTAL tuning parameters */\r
3226 \r
3227   /* Set peak detection threshold in CMU_HFXOCTRL1_PEAKDETTHR[2:0] (hidden). */\r
3228   BUS_RegMaskedWrite((volatile uint32_t *)0x400E4028, 0x7, hfxoInit->thresholdPeakDetect);\r
3229 \r
3230   /* Set tuning for startup and steady state */\r
3231   BUS_RegMaskedWrite(&CMU->HFXOSTARTUPCTRL,\r
3232                      _CMU_HFXOSTARTUPCTRL_CTUNE_MASK\r
3233                      | _CMU_HFXOSTARTUPCTRL_REGISHWARM_MASK\r
3234                      | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK\r
3235                      | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCOREWARM_MASK,\r
3236                      (hfxoInit->ctuneStartup\r
3237                       << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT)\r
3238                      | (hfxoInit->regIshStartup\r
3239                         << _CMU_HFXOSTARTUPCTRL_REGISHWARM_SHIFT)\r
3240                      | (hfxoInit->xoCoreBiasTrimStartup\r
3241                         << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT)\r
3242                      | 0x4 /* Recommended tuning */\r
3243                         << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCOREWARM_SHIFT);\r
3244 \r
3245   /* Adjust CMU_HFXOSTEADYSTATECTRL_REGISHUPPER according to regIshSteadyState.\r
3246      Saturate at max value. Please see the reference manual page 433 and Section\r
3247      12.5.10 CMU_HFXOSTEADYSTATECTRL for more details. */\r
3248   ishReg = hfxoInit->regIshSteadyState + 3;\r
3249   ishMax = _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK\r
3250             >> _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT;\r
3251   ishReg = ishReg > ishMax ? ishMax : ishReg;\r
3252   ishReg <<= _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT;\r
3253 \r
3254   BUS_RegMaskedWrite(&CMU->HFXOSTEADYSTATECTRL,\r
3255                      _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK\r
3256                      | _CMU_HFXOSTEADYSTATECTRL_REGISH_MASK\r
3257                      | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK\r
3258                      | _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK,\r
3259                      (hfxoInit->ctuneSteadyState\r
3260                       << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT)\r
3261                      | (hfxoInit->regIshSteadyState\r
3262                         << _CMU_HFXOSTEADYSTATECTRL_REGISH_SHIFT)\r
3263                      | (hfxoInit->xoCoreBiasTrimSteadyState\r
3264                         << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT)\r
3265                      | ishReg);\r
3266 \r
3267   /* Set timeouts */\r
3268   BUS_RegMaskedWrite(&CMU->HFXOTIMEOUTCTRL,\r
3269                      _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_MASK\r
3270                      | _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_MASK\r
3271                      | _CMU_HFXOTIMEOUTCTRL_WARMSTEADYTIMEOUT_MASK\r
3272                      | _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_MASK\r
3273                      | _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_MASK,\r
3274                      (hfxoInit->timeoutShuntOptimization\r
3275                       << _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_SHIFT)\r
3276                      | (hfxoInit->timeoutPeakDetect\r
3277                         << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT)\r
3278                      | (hfxoInit->timeoutWarmSteady\r
3279                         << _CMU_HFXOTIMEOUTCTRL_WARMSTEADYTIMEOUT_SHIFT)\r
3280                      | (hfxoInit->timeoutSteady\r
3281                         << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT)\r
3282                      | (hfxoInit->timeoutStartup\r
3283                         << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT));\r
3284 }\r
3285 #endif\r
3286 \r
3287 \r
3288 /***************************************************************************//**\r
3289  * @brief\r
3290  *   Get the LCD framerate divisor (FDIV) setting.\r
3291  *\r
3292  * @return\r
3293  *   The LCD framerate divisor.\r
3294  ******************************************************************************/\r
3295 uint32_t CMU_LCDClkFDIVGet(void)\r
3296 {\r
3297 #if defined( LCD_PRESENT )\r
3298   return (CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT;\r
3299 #else\r
3300   return 0;\r
3301 #endif /* defined(LCD_PRESENT) */\r
3302 }\r
3303 \r
3304 \r
3305 /***************************************************************************//**\r
3306  * @brief\r
3307  *   Set the LCD framerate divisor (FDIV) setting.\r
3308  *\r
3309  * @note\r
3310  *   The FDIV field (CMU LCDCTRL register) should only be modified while the\r
3311  *   LCD module is clock disabled (CMU LFACLKEN0.LCD bit is 0). This function\r
3312  *   will NOT modify FDIV if the LCD module clock is enabled. Please refer to\r
3313  *   CMU_ClockEnable() for disabling/enabling LCD clock.\r
3314  *\r
3315  * @param[in] div\r
3316  *   The FDIV setting to use.\r
3317  ******************************************************************************/\r
3318 void CMU_LCDClkFDIVSet(uint32_t div)\r
3319 {\r
3320 #if defined( LCD_PRESENT )\r
3321   EFM_ASSERT(div <= cmuClkDiv_128);\r
3322 \r
3323   /* Do not allow modification if LCD clock enabled */\r
3324   if (CMU->LFACLKEN0 & CMU_LFACLKEN0_LCD)\r
3325   {\r
3326     return;\r
3327   }\r
3328 \r
3329   div        <<= _CMU_LCDCTRL_FDIV_SHIFT;\r
3330   div         &= _CMU_LCDCTRL_FDIV_MASK;\r
3331   CMU->LCDCTRL = (CMU->LCDCTRL & ~_CMU_LCDCTRL_FDIV_MASK) | div;\r
3332 #else\r
3333   (void)div;  /* Unused parameter */\r
3334 #endif /* defined(LCD_PRESENT) */\r
3335 }\r
3336 \r
3337 \r
3338 #if defined( _CMU_LFXOCTRL_MASK )\r
3339 /**************************************************************************//**\r
3340  * @brief\r
3341  *   Set LFXO control registers\r
3342  *\r
3343  * @note\r
3344  *   LFXO configuration should be obtained from a configuration tool,\r
3345  *   app note or xtal datasheet. This function disables the LFXO to ensure\r
3346  *   a valid state before update.\r
3347  *\r
3348  * @param[in] lfxoInit\r
3349  *    LFXO setup parameters\r
3350  *****************************************************************************/\r
3351 void CMU_LFXOInit(CMU_LFXOInit_TypeDef *lfxoInit)\r
3352 {\r
3353   /* Do not disable LFXO if it is currently selected as HF/Core clock */\r
3354   EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_LFXO);\r
3355 \r
3356   /* LFXO must be disabled before reconfiguration */\r
3357   CMU_OscillatorEnable(cmuOsc_LFXO, false, false);\r
3358 \r
3359   BUS_RegMaskedWrite(&CMU->LFXOCTRL,\r
3360                      _CMU_LFXOCTRL_TUNING_MASK\r
3361                      | _CMU_LFXOCTRL_GAIN_MASK\r
3362                      | _CMU_LFXOCTRL_TIMEOUT_MASK,\r
3363                      (lfxoInit->ctune << _CMU_LFXOCTRL_TUNING_SHIFT)\r
3364                      | (lfxoInit->gain << _CMU_LFXOCTRL_GAIN_SHIFT)\r
3365                      | (lfxoInit->timeout << _CMU_LFXOCTRL_TIMEOUT_SHIFT));\r
3366 }\r
3367 #endif\r
3368 \r
3369 \r
3370 /***************************************************************************//**\r
3371  * @brief\r
3372  *   Enable/disable oscillator.\r
3373  *\r
3374  * @note\r
3375  *   WARNING: When this function is called to disable either cmuOsc_LFXO or\r
3376  *   cmuOsc_HFXO the LFXOMODE or HFXOMODE fields of the CMU_CTRL register\r
3377  *   are reset to the reset value. I.e. if external clock sources are selected\r
3378  *   in either LFXOMODE or HFXOMODE fields, the configuration will be cleared\r
3379  *   and needs to be reconfigured if needed later.\r
3380  *\r
3381  * @param[in] osc\r
3382  *   The oscillator to enable/disable.\r
3383  *\r
3384  * @param[in] enable\r
3385  *   @li true - enable specified oscillator.\r
3386  *   @li false - disable specified oscillator.\r
3387  *\r
3388  * @param[in] wait\r
3389  *   Only used if @p enable is true.\r
3390  *   @li true - wait for oscillator start-up time to timeout before returning.\r
3391  *   @li false - do not wait for oscillator start-up time to timeout before\r
3392  *     returning.\r
3393  ******************************************************************************/\r
3394 void CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait)\r
3395 {\r
3396   uint32_t rdyBitPos;\r
3397 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3398   uint32_t ensBitPos;\r
3399 #endif\r
3400   uint32_t enBit;\r
3401   uint32_t disBit;\r
3402 \r
3403   switch (osc)\r
3404   {\r
3405     case cmuOsc_HFRCO:\r
3406       enBit  = CMU_OSCENCMD_HFRCOEN;\r
3407       disBit = CMU_OSCENCMD_HFRCODIS;\r
3408       rdyBitPos = _CMU_STATUS_HFRCORDY_SHIFT;\r
3409 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3410       ensBitPos = _CMU_STATUS_HFRCOENS_SHIFT;\r
3411 #endif\r
3412       break;\r
3413 \r
3414     case cmuOsc_HFXO:\r
3415       enBit  = CMU_OSCENCMD_HFXOEN;\r
3416       disBit = CMU_OSCENCMD_HFXODIS;\r
3417       rdyBitPos = _CMU_STATUS_HFXORDY_SHIFT;\r
3418 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3419       ensBitPos = _CMU_STATUS_HFXOENS_SHIFT;\r
3420 #endif\r
3421       break;\r
3422 \r
3423     case cmuOsc_AUXHFRCO:\r
3424       enBit  = CMU_OSCENCMD_AUXHFRCOEN;\r
3425       disBit = CMU_OSCENCMD_AUXHFRCODIS;\r
3426       rdyBitPos = _CMU_STATUS_AUXHFRCORDY_SHIFT;\r
3427 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3428       ensBitPos = _CMU_STATUS_AUXHFRCOENS_SHIFT;\r
3429 #endif\r
3430       break;\r
3431 \r
3432     case cmuOsc_LFRCO:\r
3433       enBit  = CMU_OSCENCMD_LFRCOEN;\r
3434       disBit = CMU_OSCENCMD_LFRCODIS;\r
3435       rdyBitPos = _CMU_STATUS_LFRCORDY_SHIFT;\r
3436 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3437       ensBitPos = _CMU_STATUS_LFRCOENS_SHIFT;\r
3438 #endif\r
3439       break;\r
3440 \r
3441     case cmuOsc_LFXO:\r
3442       enBit  = CMU_OSCENCMD_LFXOEN;\r
3443       disBit = CMU_OSCENCMD_LFXODIS;\r
3444       rdyBitPos = _CMU_STATUS_LFXORDY_SHIFT;\r
3445 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3446       ensBitPos = _CMU_STATUS_LFXOENS_SHIFT;\r
3447 #endif\r
3448       break;\r
3449 \r
3450 #if defined( _CMU_STATUS_USHFRCOENS_MASK )\r
3451     case cmuOsc_USHFRCO:\r
3452       enBit  = CMU_OSCENCMD_USHFRCOEN;\r
3453       disBit = CMU_OSCENCMD_USHFRCODIS;\r
3454       rdyBitPos = _CMU_STATUS_USHFRCORDY_SHIFT;\r
3455 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3456       ensBitPos = _CMU_STATUS_USHFRCOENS_SHIFT;\r
3457 #endif\r
3458       break;\r
3459 #endif\r
3460 \r
3461 #if defined( CMU_LFCLKSEL_LFAE_ULFRCO )\r
3462     case cmuOsc_ULFRCO:\r
3463       /* ULFRCO is always enabled, and cannot be turned off */\r
3464       return;\r
3465 #endif\r
3466 \r
3467     default:\r
3468       /* Undefined clock source */\r
3469       EFM_ASSERT(0);\r
3470       return;\r
3471   }\r
3472 \r
3473   if (enable)\r
3474   {\r
3475     CMU->OSCENCMD = enBit;\r
3476 \r
3477 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3478     /* Always wait for ENS to go high */\r
3479     while (!BUS_RegBitRead(&CMU->STATUS, ensBitPos))\r
3480     {\r
3481     }\r
3482 #endif\r
3483 \r
3484     /* Wait for clock to become ready after enable */\r
3485     if (wait)\r
3486     {\r
3487       while (!BUS_RegBitRead(&CMU->STATUS, rdyBitPos));\r
3488 #if defined( _CMU_STATUS_HFXOSHUNTOPTRDY_MASK )\r
3489       /* Wait for shunt current optimization to complete */\r
3490       if ((osc == cmuOsc_HFXO)\r
3491           && (BUS_RegMaskedRead(&CMU->HFXOCTRL,\r
3492                                 _CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)\r
3493               == CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_AUTOCMD))\r
3494       {\r
3495         while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_HFXOSHUNTOPTRDY_SHIFT))\r
3496         {\r
3497         }\r
3498         /* Assert on failed peak detection. Incorrect HFXO initialization parameters\r
3499            caused startup to fail. Please review parameters. */\r
3500         EFM_ASSERT(BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_HFXOPEAKDETRDY_SHIFT));\r
3501       }\r
3502 #endif\r
3503     }\r
3504   }\r
3505   else\r
3506   {\r
3507     CMU->OSCENCMD = disBit;\r
3508 \r
3509 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3510     /* Always wait for ENS to go low */\r
3511     while (BUS_RegBitRead(&CMU->STATUS, ensBitPos))\r
3512     {\r
3513     }\r
3514 #endif\r
3515   }\r
3516 \r
3517   /* Keep EMU module informed */\r
3518   EMU_UpdateOscConfig();\r
3519 }\r
3520 \r
3521 \r
3522 /***************************************************************************//**\r
3523  * @brief\r
3524  *   Get oscillator frequency tuning setting.\r
3525  *\r
3526  * @param[in] osc\r
3527  *   Oscillator to get tuning value for, one of:\r
3528  *   @li #cmuOsc_LFRCO\r
3529  *   @li #cmuOsc_HFRCO\r
3530  *   @li #cmuOsc_AUXHFRCO\r
3531  *\r
3532  * @return\r
3533  *   The oscillator frequency tuning setting in use.\r
3534  ******************************************************************************/\r
3535 uint32_t CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)\r
3536 {\r
3537   uint32_t ret;\r
3538 \r
3539   switch (osc)\r
3540   {\r
3541     case cmuOsc_LFRCO:\r
3542       ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK)\r
3543             >> _CMU_LFRCOCTRL_TUNING_SHIFT;\r
3544       break;\r
3545 \r
3546     case cmuOsc_HFRCO:\r
3547       ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK)\r
3548             >> _CMU_HFRCOCTRL_TUNING_SHIFT;\r
3549       break;\r
3550 \r
3551     case cmuOsc_AUXHFRCO:\r
3552       ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK)\r
3553             >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT;\r
3554       break;\r
3555 \r
3556     default:\r
3557       EFM_ASSERT(0);\r
3558       ret = 0;\r
3559       break;\r
3560   }\r
3561 \r
3562   return ret;\r
3563 }\r
3564 \r
3565 \r
3566 /***************************************************************************//**\r
3567  * @brief\r
3568  *   Set the oscillator frequency tuning control.\r
3569  *\r
3570  * @note\r
3571  *   Oscillator tuning is done during production, and the tuning value is\r
3572  *   automatically loaded after a reset. Changing the tuning value from the\r
3573  *   calibrated value is for more advanced use.\r
3574  *\r
3575  * @param[in] osc\r
3576  *   Oscillator to set tuning value for, one of:\r
3577  *   @li #cmuOsc_LFRCO\r
3578  *   @li #cmuOsc_HFRCO\r
3579  *   @li #cmuOsc_AUXHFRCO\r
3580  *\r
3581  * @param[in] val\r
3582  *   The oscillator frequency tuning setting to use.\r
3583  ******************************************************************************/\r
3584 void CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc, uint32_t val)\r
3585 {\r
3586   switch (osc)\r
3587   {\r
3588     case cmuOsc_LFRCO:\r
3589       EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK\r
3590                          >> _CMU_LFRCOCTRL_TUNING_SHIFT));\r
3591       val &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT);\r
3592 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3593       while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_LFRCOBSY_SHIFT));\r
3594 #endif\r
3595       CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK))\r
3596                        | (val << _CMU_LFRCOCTRL_TUNING_SHIFT);\r
3597       break;\r
3598 \r
3599     case cmuOsc_HFRCO:\r
3600       EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK\r
3601                          >> _CMU_HFRCOCTRL_TUNING_SHIFT));\r
3602       val &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT);\r
3603 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3604       while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT))\r
3605       {\r
3606       }\r
3607 #endif\r
3608       CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK))\r
3609                        | (val << _CMU_HFRCOCTRL_TUNING_SHIFT);\r
3610       break;\r
3611 \r
3612     case cmuOsc_AUXHFRCO:\r
3613       EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK\r
3614                          >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT));\r
3615       val &= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT);\r
3616 #if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
3617       while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT))\r
3618       {\r
3619       }\r
3620 #endif\r
3621       CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK))\r
3622                           | (val << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);\r
3623       break;\r
3624 \r
3625     default:\r
3626       EFM_ASSERT(0);\r
3627       break;\r
3628   }\r
3629 }\r
3630 \r
3631 \r
3632 /**************************************************************************//**\r
3633  * @brief\r
3634  *   Determine if currently selected PCNTn clock used is external or LFBCLK.\r
3635  *\r
3636  * @param[in] instance\r
3637  *   PCNT instance number to get currently selected clock source for.\r
3638  *\r
3639  * @return\r
3640  *   @li true - selected clock is external clock.\r
3641  *   @li false - selected clock is LFBCLK.\r
3642  *****************************************************************************/\r
3643 bool CMU_PCNTClockExternalGet(unsigned int instance)\r
3644 {\r
3645   uint32_t setting;\r
3646 \r
3647   switch (instance)\r
3648   {\r
3649 #if defined( _CMU_PCNTCTRL_PCNT0CLKEN_MASK )\r
3650     case 0:\r
3651       setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0;\r
3652       break;\r
3653 \r
3654 #if defined( _CMU_PCNTCTRL_PCNT1CLKEN_MASK )\r
3655     case 1:\r
3656       setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0;\r
3657       break;\r
3658 \r
3659 #if defined( _CMU_PCNTCTRL_PCNT2CLKEN_MASK )\r
3660     case 2:\r
3661       setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0;\r
3662       break;\r
3663 #endif\r
3664 #endif\r
3665 #endif\r
3666 \r
3667     default:\r
3668       setting = 0;\r
3669       break;\r
3670   }\r
3671   return (setting ? true : false);\r
3672 }\r
3673 \r
3674 \r
3675 /**************************************************************************//**\r
3676  * @brief\r
3677  *   Select PCNTn clock.\r
3678  *\r
3679  * @param[in] instance\r
3680  *   PCNT instance number to set selected clock source for.\r
3681  *\r
3682  * @param[in] external\r
3683  *   Set to true to select external clock, false to select LFBCLK.\r
3684  *****************************************************************************/\r
3685 void CMU_PCNTClockExternalSet(unsigned int instance, bool external)\r
3686 {\r
3687 #if defined( PCNT_PRESENT )\r
3688   uint32_t setting = 0;\r
3689 \r
3690   EFM_ASSERT(instance < PCNT_COUNT);\r
3691 \r
3692   if (external)\r
3693   {\r
3694     setting = 1;\r
3695   }\r
3696 \r
3697   BUS_RegBitWrite(&(CMU->PCNTCTRL), (instance * 2) + 1, setting);\r
3698 \r
3699 #else\r
3700   (void)instance;  /* Unused parameter */\r
3701   (void)external;  /* Unused parameter */\r
3702 #endif\r
3703 }\r
3704 \r
3705 \r
3706 #if defined( _CMU_USHFRCOCONF_BAND_MASK )\r
3707 /***************************************************************************//**\r
3708  * @brief\r
3709  *   Get USHFRCO band in use.\r
3710  *\r
3711  * @return\r
3712  *   USHFRCO band in use.\r
3713  ******************************************************************************/\r
3714 CMU_USHFRCOBand_TypeDef CMU_USHFRCOBandGet(void)\r
3715 {\r
3716   return (CMU_USHFRCOBand_TypeDef)((CMU->USHFRCOCONF\r
3717                                     & _CMU_USHFRCOCONF_BAND_MASK)\r
3718                                    >> _CMU_USHFRCOCONF_BAND_SHIFT);\r
3719 }\r
3720 #endif\r
3721 \r
3722 #if defined( _CMU_USHFRCOCONF_BAND_MASK )\r
3723 /***************************************************************************//**\r
3724  * @brief\r
3725  *   Set USHFRCO band to use.\r
3726  *\r
3727  * @param[in] band\r
3728  *   USHFRCO band to activate.\r
3729  ******************************************************************************/\r
3730 void CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band)\r
3731 {\r
3732   uint32_t           tuning;\r
3733   uint32_t           fineTuning;\r
3734   CMU_Select_TypeDef osc;\r
3735 \r
3736   /* Cannot switch band if USHFRCO is already selected as HF clock. */\r
3737   osc = CMU_ClockSelectGet(cmuClock_HF);\r
3738   EFM_ASSERT((CMU_USHFRCOBandGet() != band) && (osc != cmuSelect_USHFRCO));\r
3739 \r
3740   /* Read tuning value from calibration table */\r
3741   switch (band)\r
3742   {\r
3743     case cmuUSHFRCOBand_24MHz:\r
3744       tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_TUNING_MASK)\r
3745                >> _DEVINFO_USHFRCOCAL0_BAND24_TUNING_SHIFT;\r
3746       fineTuning = (DEVINFO->USHFRCOCAL0\r
3747                     & _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_MASK)\r
3748                    >> _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_SHIFT;\r
3749       break;\r
3750 \r
3751     case cmuUSHFRCOBand_48MHz:\r
3752       tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_TUNING_MASK)\r
3753                >> _DEVINFO_USHFRCOCAL0_BAND48_TUNING_SHIFT;\r
3754       fineTuning = (DEVINFO->USHFRCOCAL0\r
3755                     & _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_MASK)\r
3756                    >> _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_SHIFT;\r
3757       /* Enable the clock divider before switching the band from 24 to 48MHz */\r
3758       BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 0);\r
3759       break;\r
3760 \r
3761     default:\r
3762       EFM_ASSERT(0);\r
3763       return;\r
3764   }\r
3765 \r
3766   /* Set band and tuning */\r
3767   CMU->USHFRCOCONF = (CMU->USHFRCOCONF & ~_CMU_USHFRCOCONF_BAND_MASK)\r
3768                      | (band << _CMU_USHFRCOCONF_BAND_SHIFT);\r
3769   CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~_CMU_USHFRCOCTRL_TUNING_MASK)\r
3770                      | (tuning << _CMU_USHFRCOCTRL_TUNING_SHIFT);\r
3771   CMU->USHFRCOTUNE = (CMU->USHFRCOTUNE & ~_CMU_USHFRCOTUNE_FINETUNING_MASK)\r
3772                      | (fineTuning << _CMU_USHFRCOTUNE_FINETUNING_SHIFT);\r
3773 \r
3774   /* Disable the clock divider after switching the band from 48 to 24MHz */\r
3775   if (band == cmuUSHFRCOBand_24MHz)\r
3776   {\r
3777     BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 1);\r
3778   }\r
3779 }\r
3780 #endif\r
3781 \r
3782 \r
3783 \r
3784 /** @} (end addtogroup CMU) */\r
3785 /** @} (end addtogroup EM_Library) */\r
3786 #endif /* __EM_CMU_H */\r