]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/SilLabs_Code/emlib/em_cmu.c
Add EFM32 Giant Gecko Starter Kit demo - still a work in progress as the low power...
[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.0.0\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2014 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 \r
33 \r
34 #include "em_cmu.h"\r
35 #if defined( CMU_PRESENT )\r
36 \r
37 #include "em_assert.h"\r
38 #include "em_bitband.h"\r
39 #include "em_emu.h"\r
40 \r
41 /***************************************************************************//**\r
42  * @addtogroup EM_Library\r
43  * @{\r
44  ******************************************************************************/\r
45 \r
46 /***************************************************************************//**\r
47  * @addtogroup CMU\r
48  * @brief Clock management unit (CMU) Peripheral API\r
49  * @{\r
50  ******************************************************************************/\r
51 \r
52 /*******************************************************************************\r
53  ******************************   DEFINES   ************************************\r
54  ******************************************************************************/\r
55 \r
56 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
57 \r
58 /** Maximum allowed core frequency when using 0 wait states on flash access. */\r
59 #define CMU_MAX_FREQ_0WS    16000000\r
60 /** Maximum allowed core frequency when using 1 wait states on flash access */\r
61 #define CMU_MAX_FREQ_1WS    32000000\r
62 \r
63 #if defined( CMU_CTRL_HFLE )\r
64 /** Maximum frequency for HFLE needs to be enabled on Giant, Leopard and\r
65     Wonder. */\r
66 #if defined ( _EFM32_WONDER_FAMILY ) ||  \\r
67     defined ( _EZR32_LEOPARD_FAMILY ) || \\r
68     defined ( _EZR32_WONDER_FAMILY )\r
69 #define CMU_MAX_FREQ_HFLE   24000000\r
70 #elif defined ( _EFM32_GIANT_FAMILY )\r
71 #define CMU_MAX_FREQ_HFLE   (CMU_MaxFreqHfle())\r
72 #else\r
73 #error Invalid part/device.\r
74 #endif\r
75 #endif\r
76 \r
77 /** Low frequency A group identifier */\r
78 #define CMU_LFA             0\r
79 \r
80 /** Low frequency B group identifier */\r
81 #define CMU_LFB             1\r
82 \r
83 /** @endcond */\r
84 \r
85 /*******************************************************************************\r
86  **************************   LOCAL FUNCTIONS   ********************************\r
87  ******************************************************************************/\r
88 \r
89 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
90 \r
91 #if defined( CMU_CTRL_HFLE ) &&         \\r
92   !defined ( _EFM32_WONDER_FAMILY ) &&  \\r
93   !defined ( _EZR32_LEOPARD_FAMILY ) && \\r
94   !defined ( _EZR32_WONDER_FAMILY )\r
95 \r
96 /***************************************************************************//**\r
97  * @brief\r
98  *   Return max allowed frequency for low energy peripherals.\r
99  ******************************************************************************/\r
100 static uint32_t CMU_MaxFreqHfle(void)\r
101 {\r
102   /* SYSTEM_GetFamily and SYSTEM_ChipRevisionGet could have been used here\r
103      but we want to minimize dependencies in em_cmu.c. */\r
104   uint16_t majorMinorRev;\r
105   uint8_t  deviceFamily = ((DEVINFO->PART & _DEVINFO_PART_DEVICE_FAMILY_MASK)\r
106                            >> _DEVINFO_PART_DEVICE_FAMILY_SHIFT);\r
107   switch (deviceFamily)\r
108   {\r
109   case _DEVINFO_PART_DEVICE_FAMILY_LG:\r
110     /* CHIP MAJOR bit [3:0] */\r
111     majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)\r
112                       >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8);\r
113     /* CHIP MINOR bit [7:4] */\r
114     majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)\r
115                        >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);\r
116     /* CHIP MINOR bit [3:0] */\r
117     majorMinorRev |=  ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)\r
118                        >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);\r
119 \r
120     if (majorMinorRev >= 0x0204)\r
121       return 24000000;\r
122     else\r
123       return 32000000;\r
124   case _DEVINFO_PART_DEVICE_FAMILY_GG:\r
125     return 32000000;\r
126   case _DEVINFO_PART_DEVICE_FAMILY_WG:\r
127     return 24000000;\r
128   default:\r
129     /* Invalid device family. */\r
130     EFM_ASSERT(false);\r
131     return 0;\r
132   }\r
133 }\r
134 #endif\r
135 \r
136 \r
137 /***************************************************************************//**\r
138  * @brief\r
139  *   Configure flash access wait states in order to support given core clock\r
140  *   frequency.\r
141  *\r
142  * @param[in] hfcoreclk\r
143  *   Core clock frequency to configure flash wait-states for\r
144  ******************************************************************************/\r
145 static void CMU_FlashWaitStateControl(uint32_t hfcoreclk)\r
146 {\r
147   uint32_t mode;\r
148   bool mscLocked;\r
149 #if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
150   bool scbtpEn;\r
151 #endif\r
152 \r
153   /* Make sure the MSC is unlocked */\r
154   mscLocked = MSC->LOCK;\r
155   MSC->LOCK = MSC_UNLOCK_CODE;\r
156 \r
157   /* Get mode and SCBTP enable */\r
158   mode = MSC->READCTRL & _MSC_READCTRL_MODE_MASK;\r
159 #if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
160   switch(mode)\r
161   {\r
162     case MSC_READCTRL_MODE_WS0:\r
163     case MSC_READCTRL_MODE_WS1:\r
164 #if defined( MSC_READCTRL_MODE_WS2 )\r
165     case MSC_READCTRL_MODE_WS2:\r
166 #endif\r
167       scbtpEn = false;\r
168       break;\r
169 \r
170     default: /* WSxSCBTP */\r
171       scbtpEn = true;\r
172     break;\r
173   }\r
174 #endif\r
175 \r
176 \r
177   /* Set mode based on the core clock frequency and SCBTP enable */\r
178 #if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
179   if (false)\r
180   {\r
181   }\r
182 #if defined( MSC_READCTRL_MODE_WS2 )\r
183   else if (hfcoreclk > CMU_MAX_FREQ_1WS)\r
184   {\r
185     mode = (scbtpEn ? MSC_READCTRL_MODE_WS2SCBTP : MSC_READCTRL_MODE_WS2);\r
186   }\r
187 #endif\r
188   else if ((hfcoreclk <= CMU_MAX_FREQ_1WS) && (hfcoreclk > CMU_MAX_FREQ_0WS))\r
189   {\r
190     mode = (scbtpEn ? MSC_READCTRL_MODE_WS1SCBTP : MSC_READCTRL_MODE_WS1);\r
191   }\r
192   else\r
193   {\r
194     mode = (scbtpEn ? MSC_READCTRL_MODE_WS0SCBTP : MSC_READCTRL_MODE_WS0);\r
195   }\r
196 \r
197 #else /* If MODE and SCBTP is in separate register fields */\r
198 \r
199   if (false)\r
200   {\r
201   }\r
202 #if defined( MSC_READCTRL_MODE_WS2 )\r
203   else if (hfcoreclk > CMU_MAX_FREQ_1WS)\r
204   {\r
205     mode = MSC_READCTRL_MODE_WS2;\r
206   }\r
207 #endif\r
208   else if ((hfcoreclk <= CMU_MAX_FREQ_1WS) && (hfcoreclk > CMU_MAX_FREQ_0WS))\r
209   {\r
210     mode = MSC_READCTRL_MODE_WS1;\r
211   }\r
212   else\r
213   {\r
214     mode = MSC_READCTRL_MODE_WS0;\r
215   }\r
216 #endif\r
217 \r
218   /* BUS_RegMaskedWrite cannot be used here as it would temporarely set the\r
219      mode field to WS0 */\r
220   MSC->READCTRL = (MSC->READCTRL &~_MSC_READCTRL_MODE_MASK) | mode;\r
221 \r
222   if (mscLocked)\r
223   {\r
224     MSC->LOCK = 0;\r
225   }\r
226 }\r
227 \r
228 \r
229 /***************************************************************************//**\r
230  * @brief\r
231  *   Configure flash access wait states to most conservative setting for\r
232  *   this target. Retain SCBTP setting.\r
233  ******************************************************************************/\r
234 static void CMU_FlashWaitStateMax(void)\r
235 {\r
236   uint32_t maxCoreClock;\r
237 #if defined   (_EFM32_GECKO_FAMILY)\r
238   maxCoreClock = 32000000;\r
239 #elif defined (_EFM32_GIANT_FAMILY)\r
240   maxCoreClock = 48000000;\r
241 #elif defined (_EFM32_TINY_FAMILY)\r
242   maxCoreClock = 32000000;\r
243 #elif defined (_EFM32_LEOPARD_FAMILY)\r
244   maxCoreClock = 48000000;\r
245 #elif defined (_EFM32_WONDER_FAMILY)\r
246   maxCoreClock = 48000000;\r
247 #elif defined (_EFM32_ZERO_FAMILY)\r
248   maxCoreClock = 24000000;\r
249 #elif defined (_EFM32_HAPPY_FAMILY)\r
250   maxCoreClock = 25000000;\r
251 #else\r
252 #error "Max core clock frequency is not defined for this family"\r
253 #endif\r
254 \r
255   /* Use SystemMaxCoreClockGet() when available in CMSIS */\r
256   CMU_FlashWaitStateControl(maxCoreClock);\r
257 }\r
258 \r
259 \r
260 /***************************************************************************//**\r
261  * @brief Convert dividend to prescaler logarithmic value. Only works for even\r
262  *        numbers equal to 2^n\r
263  * @param[in] div Unscaled dividend,\r
264  * @return Base 2 logarithm of input, as used by fixed prescalers\r
265  ******************************************************************************/\r
266 __STATIC_INLINE uint32_t CMU_DivToLog2(CMU_ClkDiv_TypeDef div)\r
267 {\r
268   uint32_t log2;\r
269 \r
270   /* Prescalers take argument of 32768 or less */\r
271   EFM_ASSERT((div>0) && (div <= 32768));\r
272 \r
273   /* Count leading zeroes and "reverse" result, Cortex-M3 intrinsic */\r
274   log2 = (31 - __CLZ(div));\r
275 \r
276   return log2;\r
277 }\r
278 \r
279 \r
280 /***************************************************************************//**\r
281  * @brief Convert logarithm of 2 prescaler to division factor\r
282  * @param[in] log2\r
283  * @return Dividend\r
284  ******************************************************************************/\r
285 __STATIC_INLINE uint32_t CMU_Log2ToDiv(uint32_t log2)\r
286 {\r
287   return 1<<log2;\r
288 }\r
289 \r
290 \r
291 #if defined(USB_PRESENT)\r
292 /***************************************************************************//**\r
293  * @brief\r
294  *   Get the USBC frequency\r
295  *\r
296  * @return\r
297  *   USBC frequency in Hz\r
298  ******************************************************************************/\r
299 static uint32_t CMU_USBCClkGet(void)\r
300 {\r
301   uint32_t ret;\r
302   CMU_Select_TypeDef clk;\r
303 \r
304   /* Get selected clock source */\r
305   clk = CMU_ClockSelectGet(cmuClock_USBC);\r
306 \r
307   switch(clk)\r
308   {\r
309   case cmuSelect_LFXO:\r
310     ret = SystemLFXOClockGet();\r
311     break;\r
312   case cmuSelect_LFRCO:\r
313     ret = SystemLFRCOClockGet();\r
314     break;\r
315   case cmuSelect_HFCLK:\r
316     ret = SystemHFClockGet();\r
317     break;\r
318   default:\r
319     /* Clock is not enabled */\r
320     ret = 0;\r
321     break;\r
322   }\r
323   return ret;\r
324 }\r
325 #endif\r
326 \r
327 \r
328 /***************************************************************************//**\r
329  * @brief\r
330  *   Get the AUX clock frequency. Used by MSC flash programming and LESENSE,\r
331  *   by default also as debug clock.\r
332  *\r
333  * @return\r
334  *   AUX Frequency in Hz\r
335  ******************************************************************************/\r
336 static uint32_t CMU_AUXClkGet(void)\r
337 {\r
338   uint32_t ret;\r
339 \r
340 #if defined(_EFM32_GECKO_FAMILY)\r
341   /* Gecko has a fixed 14Mhz AUXHFRCO clock */\r
342   ret = 14000000;\r
343 #else\r
344   switch(CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK)\r
345   {\r
346   case CMU_AUXHFRCOCTRL_BAND_1MHZ:\r
347     ret = 1000000;\r
348     break;\r
349   case CMU_AUXHFRCOCTRL_BAND_7MHZ:\r
350     ret = 7000000;\r
351     break;\r
352   case CMU_AUXHFRCOCTRL_BAND_11MHZ:\r
353     ret = 11000000;\r
354     break;\r
355   case CMU_AUXHFRCOCTRL_BAND_14MHZ:\r
356     ret = 14000000;\r
357     break;\r
358   case CMU_AUXHFRCOCTRL_BAND_21MHZ:\r
359     ret = 21000000;\r
360     break;\r
361 #if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )\r
362   case CMU_AUXHFRCOCTRL_BAND_28MHZ:\r
363     ret = 28000000;\r
364     break;\r
365 #endif\r
366   default:\r
367     ret = 0;\r
368     break;\r
369   }\r
370 #endif\r
371   return ret;\r
372 }\r
373 \r
374 \r
375 /***************************************************************************//**\r
376  * @brief\r
377  *   Get the Debug Trace clock frequency\r
378  *\r
379  * @return\r
380  *   Debug Trace frequency in Hz\r
381  ******************************************************************************/\r
382 static uint32_t CMU_DBGClkGet(void)\r
383 {\r
384   uint32_t ret;\r
385   CMU_Select_TypeDef clk;\r
386 \r
387   /* Get selected clock source */\r
388   clk = CMU_ClockSelectGet(cmuClock_DBG);\r
389 \r
390   switch(clk)\r
391   {\r
392   case cmuSelect_HFCLK:\r
393     ret = SystemHFClockGet();\r
394 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
395     /* Giant Gecko has an additional divider, not used by USBC */\r
396     ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>\r
397                       _CMU_CTRL_HFCLKDIV_SHIFT));\r
398 #endif\r
399     break;\r
400 \r
401   case cmuSelect_AUXHFRCO:\r
402     ret = CMU_AUXClkGet();\r
403     break;\r
404 \r
405   default:\r
406     EFM_ASSERT(0);\r
407     ret = 0;\r
408     break;\r
409   }\r
410   return ret;\r
411 }\r
412 \r
413 \r
414 /***************************************************************************//**\r
415  * @brief\r
416  *   Get the LFnCLK frequency based on current configuration.\r
417  *\r
418  * @param[in] lfClkBranch\r
419  *   LF branch, 0 = LFA, 1 = LFB, ...\r
420  *\r
421  * @return\r
422  *   The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is\r
423  *   returned.\r
424  ******************************************************************************/\r
425 static uint32_t CMU_LFClkGet(unsigned int lfClkBranch)\r
426 {\r
427   uint32_t ret;\r
428 \r
429   EFM_ASSERT(lfClkBranch == CMU_LFA || lfClkBranch == CMU_LFB);\r
430 \r
431   switch ((CMU->LFCLKSEL >> (lfClkBranch * 2)) & 0x3)\r
432   {\r
433   case _CMU_LFCLKSEL_LFA_LFRCO:\r
434     ret = SystemLFRCOClockGet();\r
435     break;\r
436 \r
437   case _CMU_LFCLKSEL_LFA_LFXO:\r
438     ret = SystemLFXOClockGet();\r
439     break;\r
440 \r
441   case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:\r
442 #if defined( CMU_CTRL_HFLE )\r
443     /* Giant Gecko can use a /4 divider (and must if >32MHz) or HFLE is set */\r
444     if(((CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK) == CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4)||\r
445        (CMU->CTRL & CMU_CTRL_HFLE))\r
446     {\r
447       ret = SystemCoreClockGet() / 4;\r
448     }\r
449     else\r
450     {\r
451       ret = SystemCoreClockGet() / 2;\r
452     }\r
453 #else\r
454     ret = SystemCoreClockGet() / 2;\r
455 #endif\r
456     break;\r
457 \r
458   case _CMU_LFCLKSEL_LFA_DISABLED:\r
459 #if defined( CMU_LFCLKSEL_LFAE )\r
460     /* Check LF Extended bit setting for ULFRCO clock */\r
461     if(CMU->LFCLKSEL >> (_CMU_LFCLKSEL_LFAE_SHIFT + lfClkBranch * 4))\r
462     {\r
463       ret = SystemULFRCOClockGet();\r
464     }\r
465     else\r
466     {\r
467       ret = 0;\r
468     }\r
469 #else\r
470     ret = 0;\r
471 #endif\r
472     break;\r
473 \r
474   default:\r
475     ret = 0;\r
476     break;\r
477   }\r
478 \r
479   return ret;\r
480 }\r
481 \r
482 \r
483 /***************************************************************************//**\r
484  * @brief\r
485  *   Wait for ongoing sync of register(s) to low frequency domain to complete.\r
486  *\r
487  * @param[in] mask\r
488  *   Bitmask corresponding to SYNCBUSY register defined bits, indicating\r
489  *   registers that must complete any ongoing synchronization.\r
490  ******************************************************************************/\r
491 __STATIC_INLINE void CMU_Sync(uint32_t mask)\r
492 {\r
493   /* Avoid deadlock if modifying the same register twice when freeze mode is */\r
494   /* activated. */\r
495   if (CMU->FREEZE & CMU_FREEZE_REGFREEZE)\r
496     return;\r
497 \r
498   /* Wait for any pending previous write operation to have been completed */\r
499   /* in low frequency domain */\r
500   while (CMU->SYNCBUSY & mask)\r
501     ;\r
502 }\r
503 \r
504 \r
505 /** @endcond */\r
506 \r
507 /*******************************************************************************\r
508  **************************   GLOBAL FUNCTIONS   *******************************\r
509  ******************************************************************************/\r
510 \r
511 /***************************************************************************//**\r
512  * @brief\r
513  *   Calibrate clock.\r
514  *\r
515  * @details\r
516  *   Run a calibration for HFCLK against a selectable reference clock. Please\r
517  *   refer to the EFM32 reference manual, CMU chapter, for further details.\r
518  *\r
519  * @note\r
520  *   This function will not return until calibration measurement is completed.\r
521  *\r
522  * @param[in] HFCycles\r
523  *   The number of HFCLK cycles to run calibration. Increasing this number\r
524  *   increases precision, but the calibration will take more time.\r
525  *\r
526  * @param[in] ref\r
527  *   The reference clock used to compare HFCLK with.\r
528  *\r
529  * @return\r
530  *   The number of ticks the reference clock after HFCycles ticks on the HF\r
531  *   clock.\r
532  ******************************************************************************/\r
533 uint32_t CMU_Calibrate(uint32_t HFCycles, CMU_Osc_TypeDef ref)\r
534 {\r
535   EFM_ASSERT(HFCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));\r
536 \r
537   /* Set reference clock source */\r
538   switch (ref)\r
539   {\r
540   case cmuOsc_LFXO:\r
541     CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO;\r
542     break;\r
543 \r
544   case cmuOsc_LFRCO:\r
545     CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO;\r
546     break;\r
547 \r
548   case cmuOsc_HFXO:\r
549     CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO;\r
550     break;\r
551 \r
552   case cmuOsc_HFRCO:\r
553     CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO;\r
554     break;\r
555 \r
556   case cmuOsc_AUXHFRCO:\r
557     CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO;\r
558     break;\r
559 \r
560   default:\r
561     EFM_ASSERT(0);\r
562     return 0;\r
563   }\r
564 \r
565   /* Set top value */\r
566   CMU->CALCNT = HFCycles;\r
567 \r
568   /* Start calibration */\r
569   CMU->CMD = CMU_CMD_CALSTART;\r
570 \r
571   /* Wait until calibration completes */\r
572   while (CMU->STATUS & CMU_STATUS_CALBSY)\r
573     ;\r
574 \r
575   return CMU->CALCNT;\r
576 }\r
577 \r
578 \r
579 #if defined( _CMU_CALCTRL_UPSEL_MASK ) && defined( _CMU_CALCTRL_DOWNSEL_MASK )\r
580 /***************************************************************************//**\r
581  * @brief\r
582  *   Configure clock calibration\r
583  *\r
584  * @details\r
585  *   Configure a calibration for a selectable clock source against another\r
586  *   selectable reference clock.\r
587  *   Refer to the EFM32 reference manual, CMU chapter, for further details.\r
588  *\r
589  * @note\r
590  *   After configuration, a call to CMU_CalibrateStart() is required, and\r
591  *   the resulting calibration value can be read out with the\r
592  *   CMU_CalibrateCountGet() function call.\r
593  *\r
594  * @param[in] downCycles\r
595  *   The number of downSel clock cycles to run calibration. Increasing this\r
596  *   number increases precision, but the calibration will take more time.\r
597  *\r
598  * @param[in] downSel\r
599  *   The clock which will be counted down downCycles\r
600  *\r
601  * @param[in] upSel\r
602  *   The reference clock, the number of cycles generated by this clock will\r
603  *   be counted and added up, the result can be given with the\r
604  *   CMU_CalibrateCountGet() function call.\r
605  ******************************************************************************/\r
606 void CMU_CalibrateConfig(uint32_t downCycles, CMU_Osc_TypeDef downSel,\r
607                          CMU_Osc_TypeDef upSel)\r
608 {\r
609   /* Keep untouched configuration settings */\r
610   uint32_t calCtrl = CMU->CALCTRL & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK);\r
611 \r
612   /* 20 bits of precision to calibration count register */\r
613   EFM_ASSERT(downCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));\r
614 \r
615   /* Set down counting clock source - down counter */\r
616   switch (downSel)\r
617   {\r
618   case cmuOsc_LFXO:\r
619     calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO;\r
620     break;\r
621 \r
622   case cmuOsc_LFRCO:\r
623     calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO;\r
624     break;\r
625 \r
626   case cmuOsc_HFXO:\r
627     calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO;\r
628     break;\r
629 \r
630   case cmuOsc_HFRCO:\r
631     calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO;\r
632     break;\r
633 \r
634   case cmuOsc_AUXHFRCO:\r
635     calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO;\r
636     break;\r
637 \r
638   default:\r
639     EFM_ASSERT(0);\r
640     break;\r
641   }\r
642 \r
643   /* Set top value to be counted down by the downSel clock */\r
644   CMU->CALCNT = downCycles;\r
645 \r
646   /* Set reference clock source - up counter */\r
647   switch (upSel)\r
648   {\r
649   case cmuOsc_LFXO:\r
650     calCtrl |= CMU_CALCTRL_UPSEL_LFXO;\r
651     break;\r
652 \r
653   case cmuOsc_LFRCO:\r
654     calCtrl |= CMU_CALCTRL_UPSEL_LFRCO;\r
655     break;\r
656 \r
657   case cmuOsc_HFXO:\r
658     calCtrl |= CMU_CALCTRL_UPSEL_HFXO;\r
659     break;\r
660 \r
661   case cmuOsc_HFRCO:\r
662     calCtrl |= CMU_CALCTRL_UPSEL_HFRCO;\r
663     break;\r
664 \r
665   case cmuOsc_AUXHFRCO:\r
666     calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO;\r
667     break;\r
668 \r
669   default:\r
670     EFM_ASSERT(0);\r
671     break;\r
672   }\r
673 \r
674   CMU->CALCTRL = calCtrl;\r
675 }\r
676 #endif\r
677 \r
678 \r
679 /***************************************************************************//**\r
680  * @brief\r
681  *   Get clock divisor/prescaler.\r
682  *\r
683  * @param[in] clock\r
684  *   Clock point to get divisor/prescaler for. Notice that not all clock points\r
685  *   have a divisor/prescaler. Please refer to CMU overview in reference manual.\r
686  *\r
687  * @return\r
688  *   The current clock point divisor/prescaler. 1 is returned\r
689  *   if @p clock specifies a clock point without a divisor/prescaler.\r
690  ******************************************************************************/\r
691 CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock)\r
692 {\r
693   uint32_t           divReg;\r
694   CMU_ClkDiv_TypeDef ret;\r
695 \r
696   /* Get divisor reg id */\r
697   divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;\r
698 \r
699   switch (divReg)\r
700   {\r
701 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
702   case CMU_HFCLKDIV_REG:\r
703     ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>\r
704                _CMU_CTRL_HFCLKDIV_SHIFT);\r
705     break;\r
706 #endif\r
707 \r
708   case CMU_HFPERCLKDIV_REG:\r
709     ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV &\r
710                                 _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >>\r
711                                _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);\r
712     ret = CMU_Log2ToDiv(ret);\r
713     break;\r
714 \r
715   case CMU_HFCORECLKDIV_REG:\r
716     ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV &\r
717                                 _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >>\r
718                                _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);\r
719     ret = CMU_Log2ToDiv(ret);\r
720     break;\r
721 \r
722   case CMU_LFAPRESC0_REG:\r
723     switch (clock)\r
724     {\r
725     case cmuClock_RTC:\r
726       ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) >>\r
727                                   _CMU_LFAPRESC0_RTC_SHIFT));\r
728       ret = CMU_Log2ToDiv(ret);\r
729       break;\r
730 \r
731 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)\r
732     case cmuClock_LETIMER0:\r
733       ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) >>\r
734                                   _CMU_LFAPRESC0_LETIMER0_SHIFT));\r
735       ret = CMU_Log2ToDiv(ret);\r
736       break;\r
737 #endif\r
738 \r
739 #if defined(_CMU_LFAPRESC0_LCD_MASK)\r
740     case cmuClock_LCDpre:\r
741       ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>\r
742                                   _CMU_LFAPRESC0_LCD_SHIFT) + CMU_DivToLog2(cmuClkDiv_16));\r
743       ret = CMU_Log2ToDiv(ret);\r
744       break;\r
745 #endif\r
746 \r
747 #if defined(_CMU_LFAPRESC0_LESENSE_MASK)\r
748     case cmuClock_LESENSE:\r
749       ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) >>\r
750                                   _CMU_LFAPRESC0_LESENSE_SHIFT));\r
751       ret = CMU_Log2ToDiv(ret);\r
752       break;\r
753 #endif\r
754 \r
755     default:\r
756       EFM_ASSERT(0);\r
757       ret = cmuClkDiv_1;\r
758       break;\r
759     }\r
760     break;\r
761 \r
762   case CMU_LFBPRESC0_REG:\r
763     switch (clock)\r
764     {\r
765 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)\r
766     case cmuClock_LEUART0:\r
767       ret = (CMU_ClkDiv_TypeDef)(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) >>\r
768                                   _CMU_LFBPRESC0_LEUART0_SHIFT));\r
769       ret = CMU_Log2ToDiv(ret);\r
770       break;\r
771 #endif\r
772 \r
773 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)\r
774     case cmuClock_LEUART1:\r
775       ret = (CMU_ClkDiv_TypeDef)(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) >>\r
776                                   _CMU_LFBPRESC0_LEUART1_SHIFT));\r
777       ret = CMU_Log2ToDiv(ret);\r
778       break;\r
779 #endif\r
780 \r
781     default:\r
782       EFM_ASSERT(0);\r
783       ret = cmuClkDiv_1;\r
784       break;\r
785     }\r
786     break;\r
787 \r
788   default:\r
789     EFM_ASSERT(0);\r
790     ret = cmuClkDiv_1;\r
791     break;\r
792   }\r
793 \r
794   return(ret);\r
795 }\r
796 \r
797 \r
798 /***************************************************************************//**\r
799  * @brief\r
800  *   Set clock divisor/prescaler.\r
801  *\r
802  * @note\r
803  *   If setting a LF clock prescaler, synchronization into the low frequency\r
804  *   domain is required. If the same register is modified before a previous\r
805  *   update has completed, this function will stall until the previous\r
806  *   synchronization has completed. Please refer to CMU_FreezeEnable() for\r
807  *   a suggestion on how to reduce stalling time in some use cases.\r
808  *\r
809  * @param[in] clock\r
810  *   Clock point to set divisor/prescaler for. Notice that not all clock points\r
811  *   have a divisor/prescaler, please refer to CMU overview in the reference\r
812  *   manual.\r
813  *\r
814  * @param[in] div\r
815  *   The clock divisor to use (<= cmuClkDiv_512).\r
816  ******************************************************************************/\r
817 void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)\r
818 {\r
819   uint32_t freq;\r
820   uint32_t divReg;\r
821 \r
822   /* Get divisor reg id */\r
823   divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;\r
824 \r
825   switch (divReg)\r
826   {\r
827 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
828   case CMU_HFCLKDIV_REG:\r
829     EFM_ASSERT((div>=cmuClkDiv_1) && (div<=cmuClkDiv_8));\r
830 \r
831     /* Configure worst case wait states for flash access before setting divisor */\r
832     CMU_FlashWaitStateMax();\r
833 \r
834     /* Set divider */\r
835     CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK) |\r
836       ((div-1) << _CMU_CTRL_HFCLKDIV_SHIFT);\r
837 \r
838     /* Update CMSIS core clock variable */\r
839     /* (The function will update the global variable) */\r
840     freq = SystemCoreClockGet();\r
841 \r
842     /* Optimize flash access wait state setting for current core clk */\r
843     CMU_FlashWaitStateControl(freq);\r
844     break;\r
845 #endif\r
846 \r
847   case CMU_HFPERCLKDIV_REG:\r
848     EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512));\r
849     /* Convert to correct scale */\r
850     div = CMU_DivToLog2(div);\r
851     CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) |\r
852                        (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);\r
853     break;\r
854 \r
855   case CMU_HFCORECLKDIV_REG:\r
856     EFM_ASSERT(div <= cmuClkDiv_512);\r
857 \r
858     /* Configure worst case wait states for flash access before setting divisor */\r
859     CMU_FlashWaitStateMax();\r
860 \r
861 #if defined( CMU_CTRL_HFLE )\r
862     /* Clear HFLE and set DIV2 factor for peripheral clock\r
863        when running at frequencies lower than or equal to CMU_MAX_FREQ_HFLE. */\r
864     if ((CMU_ClockFreqGet(cmuClock_HF) / div) <= CMU_MAX_FREQ_HFLE)\r
865     {\r
866       /* Clear CMU HFLE */\r
867       BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 0);\r
868 \r
869       /* Set DIV2 factor for peripheral clock */\r
870       BITBAND_Peripheral(&(CMU->HFCORECLKDIV),\r
871                          _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 0);\r
872     }\r
873     else\r
874     {\r
875       /* Set CMU HFLE */\r
876       BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1);\r
877 \r
878       /* Set DIV4 factor for peripheral clock */\r
879       BITBAND_Peripheral(&(CMU->HFCORECLKDIV),\r
880                          _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
881     }\r
882 #endif\r
883 \r
884     /* Convert to correct scale */\r
885     div = CMU_DivToLog2(div);\r
886 \r
887     CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) |\r
888                         (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);\r
889 \r
890     /* Update CMSIS core clock variable */\r
891     /* (The function will update the global variable) */\r
892     freq = SystemCoreClockGet();\r
893 \r
894     /* Optimize flash access wait state setting for current core clk */\r
895     CMU_FlashWaitStateControl(freq);\r
896     break;\r
897 \r
898   case CMU_LFAPRESC0_REG:\r
899     switch (clock)\r
900     {\r
901     case cmuClock_RTC:\r
902       EFM_ASSERT(div <= cmuClkDiv_32768);\r
903 \r
904       /* LF register about to be modified require sync. busy check */\r
905       CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);\r
906 \r
907       /* Convert to correct scale */\r
908       div = CMU_DivToLog2(div);\r
909 \r
910       CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK) |\r
911                        (div << _CMU_LFAPRESC0_RTC_SHIFT);\r
912       break;\r
913 \r
914 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)\r
915     case cmuClock_LETIMER0:\r
916       EFM_ASSERT(div <= cmuClkDiv_32768);\r
917 \r
918       /* LF register about to be modified require sync. busy check */\r
919       CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);\r
920 \r
921       /* Convert to correct scale */\r
922       div = CMU_DivToLog2(div);\r
923 \r
924       CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK) |\r
925                        (div << _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
926       break;\r
927 #endif\r
928 \r
929 #if defined(LCD_PRESENT)\r
930     case cmuClock_LCDpre:\r
931       EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128));\r
932 \r
933       /* LF register about to be modified require sync. busy check */\r
934       CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);\r
935 \r
936       /* Convert to correct scale */\r
937       div = CMU_DivToLog2(div);\r
938 \r
939       CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK) |\r
940                        ((div - CMU_DivToLog2(cmuClkDiv_16)) << _CMU_LFAPRESC0_LCD_SHIFT);\r
941       break;\r
942 #endif /* defined(LCD_PRESENT) */\r
943 \r
944 #if defined(LESENSE_PRESENT)\r
945     case cmuClock_LESENSE:\r
946       EFM_ASSERT(div <= cmuClkDiv_8);\r
947 \r
948       /* LF register about to be modified require sync. busy check */\r
949       CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);\r
950 \r
951       /* Convert to correct scale */\r
952       div = CMU_DivToLog2(div);\r
953 \r
954       CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK) |\r
955                        (div << _CMU_LFAPRESC0_LESENSE_SHIFT);\r
956       break;\r
957 #endif /* defined(LESENSE_PRESENT) */\r
958 \r
959     default:\r
960       EFM_ASSERT(0);\r
961       break;\r
962     }\r
963     break;\r
964 \r
965   case CMU_LFBPRESC0_REG:\r
966     switch (clock)\r
967     {\r
968 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)\r
969     case cmuClock_LEUART0:\r
970       EFM_ASSERT(div <= cmuClkDiv_8);\r
971 \r
972       /* LF register about to be modified require sync. busy check */\r
973       CMU_Sync(CMU_SYNCBUSY_LFBPRESC0);\r
974 \r
975       /* Convert to correct scale */\r
976       div = CMU_DivToLog2(div);\r
977 \r
978       CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK) |\r
979                        (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT);\r
980       break;\r
981 #endif\r
982 \r
983 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)\r
984     case cmuClock_LEUART1:\r
985       EFM_ASSERT(div <= cmuClkDiv_8);\r
986 \r
987       /* LF register about to be modified require sync. busy check */\r
988       CMU_Sync(CMU_SYNCBUSY_LFBPRESC0);\r
989 \r
990       /* Convert to correct scale */\r
991       div = CMU_DivToLog2(div);\r
992 \r
993       CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK) |\r
994                        (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT);\r
995       break;\r
996 #endif\r
997 \r
998     default:\r
999       EFM_ASSERT(0);\r
1000       break;\r
1001     }\r
1002     break;\r
1003 \r
1004   default:\r
1005     EFM_ASSERT(0);\r
1006     break;\r
1007   }\r
1008 }\r
1009 \r
1010 \r
1011 /***************************************************************************//**\r
1012  * @brief\r
1013  *   Enable/disable a clock.\r
1014  *\r
1015  * @details\r
1016  *   In general, module clocking is disabled after a reset. If a module\r
1017  *   clock is disabled, the registers of that module are not accessible and\r
1018  *   reading from such registers may return undefined values. Writing to\r
1019  *   registers of clock disabled modules have no effect. One should normally\r
1020  *   avoid accessing module registers of a module with a disabled clock.\r
1021  *\r
1022  * @note\r
1023  *   If enabling/disabling a LF clock, synchronization into the low frequency\r
1024  *   domain is required. If the same register is modified before a previous\r
1025  *   update has completed, this function will stall until the previous\r
1026  *   synchronization has completed. Please refer to CMU_FreezeEnable() for\r
1027  *   a suggestion on how to reduce stalling time in some use cases.\r
1028  *\r
1029  * @param[in] clock\r
1030  *   The clock to enable/disable. Notice that not all defined clock\r
1031  *   points have separate enable/disable control, please refer to CMU overview\r
1032  *   in reference manual.\r
1033  *\r
1034  * @param[in] enable\r
1035  *   @li true - enable specified clock.\r
1036  *   @li false - disable specified clock.\r
1037  ******************************************************************************/\r
1038 void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)\r
1039 {\r
1040   volatile uint32_t *reg;\r
1041   uint32_t          bit;\r
1042   uint32_t          sync = 0;\r
1043 \r
1044   /* Identify enable register */\r
1045   switch ((clock >> CMU_EN_REG_POS) & CMU_EN_REG_MASK)\r
1046   {\r
1047   case CMU_HFPERCLKDIV_EN_REG:\r
1048     reg = &(CMU->HFPERCLKDIV);\r
1049     break;\r
1050 \r
1051   case CMU_HFPERCLKEN0_EN_REG:\r
1052     reg = &(CMU->HFPERCLKEN0);\r
1053     break;\r
1054 \r
1055   case CMU_HFCORECLKEN0_EN_REG:\r
1056     reg = &(CMU->HFCORECLKEN0);\r
1057 \r
1058 #if defined( CMU_CTRL_HFLE )\r
1059     /* Set HFLE and DIV4 factor for peripheral clock when\r
1060        running at frequencies higher than or equal to CMU_MAX_FREQ_HFLE. */\r
1061     if ( CMU_ClockFreqGet(cmuClock_CORE) > CMU_MAX_FREQ_HFLE )\r
1062     {\r
1063       /* Enable CMU HFLE */\r
1064       BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1);\r
1065 \r
1066       /* Set DIV4 factor for peripheral clock */\r
1067       BITBAND_Peripheral(&(CMU->HFCORECLKDIV),\r
1068                          _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
1069     }\r
1070 #endif\r
1071     break;\r
1072 \r
1073   case CMU_LFACLKEN0_EN_REG:\r
1074     reg  = &(CMU->LFACLKEN0);\r
1075     sync = CMU_SYNCBUSY_LFACLKEN0;\r
1076     break;\r
1077 \r
1078   case CMU_LFBCLKEN0_EN_REG:\r
1079     reg  = &(CMU->LFBCLKEN0);\r
1080     sync = CMU_SYNCBUSY_LFBCLKEN0;\r
1081     break;\r
1082 \r
1083   case CMU_PCNT_EN_REG:\r
1084     reg = &(CMU->PCNTCTRL);\r
1085     break;\r
1086 \r
1087 #if defined( _CMU_LFCCLKEN0_MASK )\r
1088   case CMU_LFCCLKEN0_EN_REG:\r
1089     reg = &(CMU->LFCCLKEN0);\r
1090     sync = CMU_SYNCBUSY_LFCCLKEN0;\r
1091     break;\r
1092 #endif\r
1093 \r
1094   default: /* Cannot enable/disable clock point */\r
1095     EFM_ASSERT(0);\r
1096     return;\r
1097   }\r
1098 \r
1099   /* Get bit position used to enable/disable */\r
1100   bit = (clock >> CMU_EN_BIT_POS) & CMU_EN_BIT_MASK;\r
1101 \r
1102   /* LF synchronization required? */\r
1103   if (sync)\r
1104   {\r
1105     CMU_Sync(sync);\r
1106   }\r
1107 \r
1108   /* Set/clear bit as requested */\r
1109   BITBAND_Peripheral(reg, bit, (unsigned int)enable);\r
1110 }\r
1111 \r
1112 \r
1113 /***************************************************************************//**\r
1114  * @brief\r
1115  *   Get clock frequency for a clock point.\r
1116  *\r
1117  * @param[in] clock\r
1118  *   Clock point to fetch frequency for.\r
1119  *\r
1120  * @return\r
1121  *   The current frequency in Hz.\r
1122  ******************************************************************************/\r
1123 uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)\r
1124 {\r
1125   uint32_t ret;\r
1126 \r
1127   switch(clock & (CMU_CLK_BRANCH_MASK << CMU_CLK_BRANCH_POS))\r
1128   {\r
1129     case (CMU_HF_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1130     {\r
1131       ret = SystemHFClockGet();\r
1132 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
1133       /* Giant Gecko has an additional divider, not used by USBC */\r
1134       ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>\r
1135                    _CMU_CTRL_HFCLKDIV_SHIFT));\r
1136 #endif\r
1137     } break;\r
1138 \r
1139 #if defined(_CMU_HFPERCLKEN0_USART0_MASK) || \\r
1140     defined(_CMU_HFPERCLKEN0_USART1_MASK) || \\r
1141     defined(_CMU_HFPERCLKEN0_USART2_MASK) || \\r
1142     defined(_CMU_HFPERCLKEN0_UART0_MASK) || \\r
1143     defined(_CMU_HFPERCLKEN0_UART1_MASK) || \\r
1144     defined(_CMU_HFPERCLKEN0_TIMER0_MASK) || \\r
1145     defined(_CMU_HFPERCLKEN0_TIMER1_MASK) || \\r
1146     defined(_CMU_HFPERCLKEN0_TIMER2_MASK) || \\r
1147     defined(_CMU_HFPERCLKEN0_TIMER3_MASK) || \\r
1148     defined(_CMU_HFPERCLKEN0_ACMP0_MASK) || \\r
1149     defined(_CMU_HFPERCLKEN0_ACMP1_MASK) || \\r
1150     defined(_CMU_HFPERCLKEN0_DAC0_MASK) || \\r
1151     defined(_CMU_HFPERCLKEN0_IDAC0_MASK) || \\r
1152     defined(_CMU_HFPERCLKEN0_ADC0_MASK) || \\r
1153     defined(_CMU_HFPERCLKEN0_I2C0_MASK) || \\r
1154     defined(_CMU_HFPERCLKEN0_I2C1_MASK) || \\r
1155     defined(PRS_PRESENT) || \\r
1156     defined(VCMP_PRESENT)|| \\r
1157     defined(GPIO_PRESENT)\r
1158     case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1159     {\r
1160       ret   = SystemHFClockGet();\r
1161 #if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
1162       /* Leopard/Giant Gecko has an additional divider */\r
1163       ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>\r
1164                         _CMU_CTRL_HFCLKDIV_SHIFT));\r
1165 #endif\r
1166       ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >>\r
1167               _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT;\r
1168     } break;\r
1169 #endif\r
1170 \r
1171 #if defined(AES_PRESENT) || \\r
1172     defined(DMA_PRESENT) || \\r
1173     defined(EBI_PRESENT) || \\r
1174     defined(USB_PRESENT)\r
1175     case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1176     {\r
1177       ret = SystemCoreClockGet();\r
1178     } break;\r
1179 #endif\r
1180 \r
1181     case (CMU_LFA_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1182     {\r
1183       ret = CMU_LFClkGet(CMU_LFA);\r
1184     } break;\r
1185 #if defined(_CMU_LFACLKEN0_RTC_MASK)\r
1186     case (CMU_RTC_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1187     {\r
1188       ret   = CMU_LFClkGet(CMU_LFA);\r
1189       ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) >>\r
1190               _CMU_LFAPRESC0_RTC_SHIFT;\r
1191     } break;\r
1192 #endif\r
1193 #if defined(_CMU_LFACLKEN0_LETIMER0_MASK)\r
1194     case (CMU_LETIMER_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1195     {\r
1196       ret   = CMU_LFClkGet(CMU_LFA);\r
1197       ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) >>\r
1198               _CMU_LFAPRESC0_LETIMER0_SHIFT;\r
1199     } break;\r
1200 #endif\r
1201 #if defined(_CMU_LFACLKEN0_LCD_MASK)\r
1202     case (CMU_LCDPRE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1203     {\r
1204       ret   = CMU_LFClkGet(CMU_LFA);\r
1205       ret >>= ((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>\r
1206               _CMU_LFAPRESC0_LCD_SHIFT) + CMU_DivToLog2(cmuClkDiv_16);\r
1207     } break;\r
1208 \r
1209     case (CMU_LCD_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1210     {\r
1211       ret   = CMU_LFClkGet(CMU_LFA);\r
1212       ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>\r
1213               _CMU_LFAPRESC0_LCD_SHIFT;\r
1214       ret /= (1 + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >>\r
1215                    _CMU_LCDCTRL_FDIV_SHIFT));\r
1216     } break;\r
1217 #endif\r
1218 #if defined(_CMU_LFACLKEN0_LESENSE_MASK)\r
1219     case (CMU_LESENSE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1220     {\r
1221       ret   = CMU_LFClkGet(CMU_LFA);\r
1222       ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) >>\r
1223               _CMU_LFAPRESC0_LESENSE_SHIFT;\r
1224     } break;\r
1225 #endif\r
1226     case (CMU_LFB_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1227     {\r
1228       ret = CMU_LFClkGet(CMU_LFB);\r
1229     } break;\r
1230 #if defined(_CMU_LFBCLKEN0_LEUART0_MASK)\r
1231     case (CMU_LEUART0_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1232     {\r
1233       ret   = CMU_LFClkGet(CMU_LFB);\r
1234       ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) >>\r
1235               _CMU_LFBPRESC0_LEUART0_SHIFT;\r
1236     } break;\r
1237 #endif\r
1238 #if defined(_CMU_LFBCLKEN0_LEUART1_MASK)\r
1239     case (CMU_LEUART1_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1240     {\r
1241       ret   = CMU_LFClkGet(CMU_LFB);\r
1242       ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) >>\r
1243         _CMU_LFBPRESC0_LEUART1_SHIFT;\r
1244     } break;\r
1245 #endif\r
1246 \r
1247     case (CMU_DBG_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1248     {\r
1249       ret  = CMU_DBGClkGet();\r
1250     } break;\r
1251 \r
1252     case (CMU_AUX_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1253     {\r
1254       ret  = CMU_AUXClkGet();\r
1255     } break;\r
1256 \r
1257 #if defined(USB_PRESENT)\r
1258     case (CMU_USBC_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
1259     {\r
1260       ret = CMU_USBCClkGet();\r
1261     } break;\r
1262 #endif\r
1263     default:\r
1264     {\r
1265       EFM_ASSERT(0);\r
1266       ret = 0;\r
1267     } break;\r
1268   }\r
1269   return ret;\r
1270 }\r
1271 \r
1272 \r
1273 /**************************************************************************//**\r
1274  * @brief\r
1275  *   Get currently selected reference clock used for a clock branch.\r
1276  *\r
1277  * @param[in] clock\r
1278  *   Clock branch to fetch selected ref. clock for. One of:\r
1279  *   @li #cmuClock_HF\r
1280  *   @li #cmuClock_LFA\r
1281  *   @li #cmuClock_LFB\r
1282  *   @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT\r
1283  *   @li #cmuClock_USBC\r
1284  *   @endif\r
1285  *\r
1286  * @return\r
1287  *   Reference clock used for clocking selected branch, #cmuSelect_Error if\r
1288  *   invalid @p clock provided.\r
1289  *****************************************************************************/\r
1290 CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock)\r
1291 {\r
1292   CMU_Select_TypeDef ret = cmuSelect_Disabled;\r
1293   uint32_t           selReg;\r
1294   uint32_t           statusClkSelMask;\r
1295 \r
1296   statusClkSelMask =\r
1297     (CMU_STATUS_HFRCOSEL |\r
1298      CMU_STATUS_HFXOSEL |\r
1299      CMU_STATUS_LFRCOSEL |\r
1300 #if defined( CMU_STATUS_USHFRCODIV2SEL )\r
1301      CMU_STATUS_USHFRCODIV2SEL |\r
1302 #endif\r
1303      CMU_STATUS_LFXOSEL);\r
1304 \r
1305   selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;\r
1306 \r
1307   switch (selReg)\r
1308   {\r
1309   case CMU_HFCLKSEL_REG:\r
1310     switch (CMU->STATUS & statusClkSelMask)\r
1311     {\r
1312     case CMU_STATUS_LFXOSEL:\r
1313       ret = cmuSelect_LFXO;\r
1314       break;\r
1315 \r
1316     case CMU_STATUS_LFRCOSEL:\r
1317       ret = cmuSelect_LFRCO;\r
1318       break;\r
1319 \r
1320     case CMU_STATUS_HFXOSEL:\r
1321       ret = cmuSelect_HFXO;\r
1322       break;\r
1323 \r
1324 #if defined( CMU_STATUS_USHFRCODIV2SEL )\r
1325     case CMU_STATUS_USHFRCODIV2SEL:\r
1326       ret = cmuSelect_USHFRCODIV2;\r
1327       break;\r
1328 #endif\r
1329 \r
1330     default:\r
1331       ret = cmuSelect_HFRCO;\r
1332       break;\r
1333     }\r
1334     break;\r
1335 \r
1336   case CMU_LFACLKSEL_REG:\r
1337     switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK)\r
1338     {\r
1339     case CMU_LFCLKSEL_LFA_LFRCO:\r
1340       ret = cmuSelect_LFRCO;\r
1341       break;\r
1342 \r
1343     case CMU_LFCLKSEL_LFA_LFXO:\r
1344       ret = cmuSelect_LFXO;\r
1345       break;\r
1346 \r
1347     case CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:\r
1348       ret = cmuSelect_CORELEDIV2;\r
1349       break;\r
1350 \r
1351     default:\r
1352 #if defined( CMU_LFCLKSEL_LFAE )\r
1353       if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK)\r
1354       {\r
1355         ret = cmuSelect_ULFRCO;\r
1356         break;\r
1357       }\r
1358 #else\r
1359       ret = cmuSelect_Disabled;\r
1360 #endif\r
1361       break;\r
1362     }\r
1363     break;\r
1364 \r
1365   case CMU_LFBCLKSEL_REG:\r
1366     switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK)\r
1367     {\r
1368     case CMU_LFCLKSEL_LFB_LFRCO:\r
1369       ret = cmuSelect_LFRCO;\r
1370       break;\r
1371 \r
1372     case CMU_LFCLKSEL_LFB_LFXO:\r
1373       ret = cmuSelect_LFXO;\r
1374       break;\r
1375 \r
1376     case CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2:\r
1377       ret = cmuSelect_CORELEDIV2;\r
1378       break;\r
1379 \r
1380     default:\r
1381 #if defined( CMU_LFCLKSEL_LFBE )\r
1382       if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK)\r
1383       {\r
1384         ret = cmuSelect_ULFRCO;\r
1385         break;\r
1386       }\r
1387 #else\r
1388       ret = cmuSelect_Disabled;\r
1389 #endif\r
1390       break;\r
1391     }\r
1392     break;\r
1393 \r
1394 #if defined( _CMU_LFCLKSEL_LFC_MASK )\r
1395   case CMU_LFCCLKSEL_REG:\r
1396     switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK)\r
1397     {\r
1398     case CMU_LFCLKSEL_LFC_LFRCO:\r
1399       ret = cmuSelect_LFRCO;\r
1400       break;\r
1401 \r
1402     case CMU_LFCLKSEL_LFC_LFXO:\r
1403       ret = cmuSelect_LFXO;\r
1404       break;\r
1405 \r
1406     default:\r
1407       ret = cmuSelect_Disabled;\r
1408       break;\r
1409     }\r
1410     break;\r
1411 #endif\r
1412 \r
1413   case CMU_DBGCLKSEL_REG:\r
1414 \r
1415 #if defined( _CMU_DBGCLKSEL_DBG_MASK )\r
1416     switch (CMU->DBGCLKSEL & _CMU_DBGCLKSEL_DBG_MASK)\r
1417     {\r
1418     case CMU_DBGCLKSEL_DBG_HFCLK:\r
1419       ret = cmuSelect_HFCLK;\r
1420       break;\r
1421 \r
1422     case CMU_DBGCLKSEL_DBG_AUXHFRCO:\r
1423       ret = cmuSelect_AUXHFRCO;\r
1424       break;\r
1425     }\r
1426 #else\r
1427     ret = cmuSelect_AUXHFRCO;\r
1428 #endif /* CMU_DBGCLKSEL_DBG */\r
1429 \r
1430 #if defined( _CMU_CTRL_DBGCLK_MASK )\r
1431     switch(CMU->CTRL & _CMU_CTRL_DBGCLK_MASK)\r
1432     {\r
1433     case CMU_CTRL_DBGCLK_AUXHFRCO:\r
1434       ret = cmuSelect_AUXHFRCO;\r
1435       break;\r
1436 \r
1437     case CMU_CTRL_DBGCLK_HFCLK:\r
1438       ret = cmuSelect_HFCLK;\r
1439       break;\r
1440     }\r
1441 #else\r
1442     ret = cmuSelect_AUXHFRCO;\r
1443 #endif\r
1444     break;\r
1445 \r
1446 \r
1447 #if defined(USB_PRESENT)\r
1448 \r
1449   case CMU_USBCCLKSEL_REG:\r
1450     switch(CMU->STATUS &\r
1451            (CMU_STATUS_USBCLFXOSEL |\r
1452 #if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)\r
1453             CMU_STATUS_USBCHFCLKSEL |\r
1454 #endif\r
1455 #if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)\r
1456             CMU_STATUS_USBCUSHFRCOSEL |\r
1457 #endif\r
1458             CMU_STATUS_USBCLFRCOSEL))\r
1459     {\r
1460 \r
1461     case CMU_STATUS_USBCLFXOSEL:\r
1462       ret = cmuSelect_LFXO;\r
1463       break;\r
1464 \r
1465     case CMU_STATUS_USBCLFRCOSEL:\r
1466       ret = cmuSelect_LFRCO;\r
1467       break;\r
1468 \r
1469 #if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)\r
1470     case CMU_STATUS_USBCHFCLKSEL:\r
1471       ret = cmuSelect_HFCLK;\r
1472       break;\r
1473 #endif\r
1474 \r
1475 #if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)\r
1476     case CMU_STATUS_USBCUSHFRCOSEL:\r
1477       ret = cmuSelect_USHFRCO;\r
1478       break;\r
1479 #endif\r
1480 \r
1481     default:\r
1482       ret = cmuSelect_Disabled;\r
1483       break;\r
1484     }\r
1485     break;\r
1486 #endif\r
1487 \r
1488   default:\r
1489     EFM_ASSERT(0);\r
1490     ret = cmuSelect_Error;\r
1491     break;\r
1492   }\r
1493 \r
1494   return ret;\r
1495 }\r
1496 \r
1497 \r
1498 /**************************************************************************//**\r
1499  * @brief\r
1500  *   Select reference clock/oscillator used for a clock branch.\r
1501  *\r
1502  * @details\r
1503  *   Notice that if a selected reference is not enabled prior to selecting its\r
1504  *   use, it will be enabled, and this function will wait for the selected\r
1505  *   oscillator to be stable. It will however NOT be disabled if another\r
1506  *   reference clock is selected later.\r
1507  *\r
1508  *   This feature is particularly important if selecting a new reference\r
1509  *   clock for the clock branch clocking the core, otherwise the system\r
1510  *   may halt.\r
1511  *\r
1512  * @param[in] clock\r
1513  *   Clock branch to select reference clock for. One of:\r
1514  *   @li #cmuClock_HF\r
1515  *   @li #cmuClock_LFA\r
1516  *   @li #cmuClock_LFB\r
1517  *   @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT\r
1518  *   @li #cmuClock_USBC\r
1519  *   @endif\r
1520  *\r
1521  * @param[in] ref\r
1522  *   Reference selected for clocking, please refer to reference manual for\r
1523  *   for details on which reference is available for a specific clock branch.\r
1524  *   @li #cmuSelect_HFRCO\r
1525  *   @li #cmuSelect_LFRCO\r
1526  *   @li #cmuSelect_HFXO\r
1527  *   @li #cmuSelect_LFXO\r
1528  *   @li #cmuSelect_CORELEDIV2\r
1529  *   @li #cmuSelect_AUXHFRCO\r
1530  *   @li #cmuSelect_HFCLK @ifnot DOXYDOC_EFM32_GECKO_FAMILY\r
1531  *   @li #cmuSelect_ULFRCO\r
1532  *   @endif\r
1533  *****************************************************************************/\r
1534 void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)\r
1535 {\r
1536   uint32_t        select = cmuOsc_HFRCO;\r
1537   CMU_Osc_TypeDef osc    = cmuOsc_HFRCO;\r
1538   uint32_t        freq;\r
1539   uint32_t        selReg;\r
1540 #if !defined(_EFM32_GECKO_FAMILY)\r
1541   uint32_t        lfExtended = 0;\r
1542 #endif\r
1543   uint32_t        tmp;\r
1544 \r
1545   selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;\r
1546 \r
1547   switch (selReg)\r
1548   {\r
1549   case CMU_HFCLKSEL_REG:\r
1550     switch (ref)\r
1551     {\r
1552     case cmuSelect_LFXO:\r
1553       select = CMU_CMD_HFCLKSEL_LFXO;\r
1554       osc    = cmuOsc_LFXO;\r
1555       break;\r
1556 \r
1557     case cmuSelect_LFRCO:\r
1558       select = CMU_CMD_HFCLKSEL_LFRCO;\r
1559       osc    = cmuOsc_LFRCO;\r
1560       break;\r
1561 \r
1562     case cmuSelect_HFXO:\r
1563       select = CMU_CMD_HFCLKSEL_HFXO;\r
1564       osc    = cmuOsc_HFXO;\r
1565 #if defined( CMU_CTRL_HFLE )\r
1566       /* Adjust HFXO buffer current for high frequencies, enable HFLE for */\r
1567       /* frequencies above CMU_MAX_FREQ_HFLE. */\r
1568       if(SystemHFXOClockGet() > CMU_MAX_FREQ_HFLE)\r
1569       {\r
1570         CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) |\r
1571           CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ |\r
1572           /* Must have HFLE enabled to access some LE peripherals >=32MHz */\r
1573           CMU_CTRL_HFLE;\r
1574 \r
1575         /* Set HFLE and DIV4 factor for peripheral clock if HFCORE clock for\r
1576            LE is enabled. */\r
1577         if (CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE)\r
1578         {\r
1579           BITBAND_Peripheral(&(CMU->HFCORECLKDIV),\r
1580                              _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
1581         }\r
1582       } else {\r
1583         /* This can happen if the user configures the EFM32_HFXO_FREQ to */\r
1584         /* use another oscillator frequency */\r
1585         CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) |\r
1586           CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ;\r
1587       }\r
1588 #endif\r
1589       break;\r
1590 \r
1591     case cmuSelect_HFRCO:\r
1592       select = CMU_CMD_HFCLKSEL_HFRCO;\r
1593       osc    = cmuOsc_HFRCO;\r
1594       break;\r
1595 \r
1596 #if defined( CMU_CMD_HFCLKSEL_USHFRCODIV2 )\r
1597     case cmuSelect_USHFRCODIV2:\r
1598       select = CMU_CMD_HFCLKSEL_USHFRCODIV2;\r
1599       osc    = cmuOsc_USHFRCO;\r
1600       break;\r
1601 #endif\r
1602 \r
1603 #if !defined( _EFM32_GECKO_FAMILY )\r
1604     case cmuSelect_ULFRCO:\r
1605       /* ULFRCO cannot be used as HFCLK  */\r
1606       EFM_ASSERT(0);\r
1607       break;\r
1608 #endif\r
1609 \r
1610     default:\r
1611       EFM_ASSERT(0);\r
1612       return;\r
1613     }\r
1614 \r
1615     /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
1616     CMU_OscillatorEnable(osc, true, true);\r
1617 \r
1618     /* Configure worst case wait states for flash access before selecting */\r
1619     CMU_FlashWaitStateMax();\r
1620 \r
1621     /* Switch to selected oscillator */\r
1622     CMU->CMD = select;\r
1623 \r
1624     /* Keep EMU module informed */\r
1625     EMU_UpdateOscConfig();\r
1626 \r
1627     /* Update CMSIS core clock variable */\r
1628     /* (The function will update the global variable) */\r
1629     freq = SystemCoreClockGet();\r
1630 \r
1631     /* Optimize flash access wait state setting for currently selected core clk */\r
1632     CMU_FlashWaitStateControl(freq);\r
1633     break;\r
1634 \r
1635   case CMU_LFACLKSEL_REG:\r
1636   case CMU_LFBCLKSEL_REG:\r
1637 \r
1638     switch (ref)\r
1639     {\r
1640     case cmuSelect_Disabled:\r
1641       tmp = _CMU_LFCLKSEL_LFA_DISABLED;\r
1642       break;\r
1643 \r
1644     case cmuSelect_LFXO:\r
1645       /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
1646       CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
1647       tmp = _CMU_LFCLKSEL_LFA_LFXO;\r
1648       break;\r
1649 \r
1650     case cmuSelect_LFRCO:\r
1651       /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
1652       CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
1653       tmp = _CMU_LFCLKSEL_LFA_LFRCO;\r
1654       break;\r
1655 \r
1656     case cmuSelect_CORELEDIV2:\r
1657       /* Ensure HFCORE to LE clocking is enabled */\r
1658       BITBAND_Peripheral(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_LE_SHIFT, 1);\r
1659       tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2;\r
1660 #if defined( CMU_CTRL_HFLE )\r
1661       /* If core frequency is higher than CMU_MAX_FREQ_HFLE on\r
1662          Giant/Leopard/Wonder, enable HFLE and DIV4. */\r
1663       freq = SystemCoreClockGet();\r
1664       if(freq > CMU_MAX_FREQ_HFLE)\r
1665       {\r
1666         /* Enable CMU HFLE */\r
1667         BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1);\r
1668 \r
1669         /* Enable DIV4 factor for peripheral clock */\r
1670         BITBAND_Peripheral(&(CMU->HFCORECLKDIV),\r
1671                            _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
1672       }\r
1673 #endif\r
1674       break;\r
1675 \r
1676 #if !defined(_EFM32_GECKO_FAMILY)\r
1677     case cmuSelect_ULFRCO:\r
1678       /* ULFRCO is always enabled */\r
1679       tmp        = _CMU_LFCLKSEL_LFA_DISABLED;\r
1680       lfExtended = 1;\r
1681       break;\r
1682 #endif\r
1683 \r
1684     default:\r
1685       /* Illegal clock source for LFA/LFB selected */\r
1686       EFM_ASSERT(0);\r
1687       return;\r
1688     }\r
1689 \r
1690     /* Apply select */\r
1691     if (selReg == CMU_LFACLKSEL_REG)\r
1692     {\r
1693 #if !defined( _EFM32_GECKO_FAMILY )\r
1694       CMU->LFCLKSEL = (CMU->LFCLKSEL & ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK) ) |\r
1695                     (tmp << _CMU_LFCLKSEL_LFA_SHIFT) | (lfExtended << _CMU_LFCLKSEL_LFAE_SHIFT);\r
1696 #else\r
1697       CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFA_MASK) |\r
1698                     (tmp << _CMU_LFCLKSEL_LFA_SHIFT);\r
1699 #endif\r
1700     }\r
1701     else\r
1702     {\r
1703 #if !defined( _EFM32_GECKO_FAMILY )\r
1704       CMU->LFCLKSEL = (CMU->LFCLKSEL & ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK) ) |\r
1705                     (tmp << _CMU_LFCLKSEL_LFB_SHIFT) | (lfExtended << _CMU_LFCLKSEL_LFBE_SHIFT);\r
1706 #else\r
1707       CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFB_MASK) |\r
1708                     (tmp << _CMU_LFCLKSEL_LFB_SHIFT);\r
1709 #endif\r
1710     }\r
1711     break;\r
1712 \r
1713 #if defined( _CMU_LFCLKSEL_LFC_MASK )\r
1714   case CMU_LFCCLKSEL_REG:\r
1715     switch(ref)\r
1716     {\r
1717     case cmuSelect_Disabled:\r
1718       tmp = _CMU_LFCLKSEL_LFA_DISABLED;\r
1719       break;\r
1720 \r
1721     case cmuSelect_LFXO:\r
1722       /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
1723       CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
1724       tmp = _CMU_LFCLKSEL_LFC_LFXO;\r
1725       break;\r
1726 \r
1727     case cmuSelect_LFRCO:\r
1728       /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
1729       CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
1730       tmp = _CMU_LFCLKSEL_LFC_LFRCO;\r
1731       break;\r
1732 \r
1733     default:\r
1734       /* Illegal clock source for LFC selected */\r
1735       EFM_ASSERT(0);\r
1736       return;\r
1737     }\r
1738 \r
1739     /* Apply select */\r
1740     CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFC_MASK) |\r
1741                     (tmp << _CMU_LFCLKSEL_LFC_SHIFT);\r
1742     break;\r
1743 #endif\r
1744 \r
1745 #if defined( CMU_CTRL_DBGCLK )\r
1746   case CMU_DBGCLKSEL_REG:\r
1747     switch(ref)\r
1748     {\r
1749     case cmuSelect_AUXHFRCO:\r
1750       /* Select AUXHFRCO as debug clock */\r
1751       CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))| CMU_CTRL_DBGCLK_AUXHFRCO;\r
1752       break;\r
1753 \r
1754     case cmuSelect_HFCLK:\r
1755       /* Select divided HFCLK as debug clock */\r
1756       CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))| CMU_CTRL_DBGCLK_HFCLK;\r
1757       break;\r
1758 \r
1759     default:\r
1760       /* Illegal clock source for debug selected */\r
1761       EFM_ASSERT(0);\r
1762       return;\r
1763     }\r
1764     break;\r
1765 #endif\r
1766 \r
1767 #if defined(USB_PRESENT)\r
1768   case CMU_USBCCLKSEL_REG:\r
1769     switch(ref)\r
1770     {\r
1771     case cmuSelect_LFXO:\r
1772       /* Select LFXO as clock source for USB, can only be used in sleep mode */\r
1773 \r
1774       /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
1775       CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
1776 \r
1777       /* Switch oscillator */\r
1778       CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;\r
1779 \r
1780       /* Wait until clock is activated */\r
1781       while((CMU->STATUS & CMU_STATUS_USBCLFXOSEL)==0);\r
1782       break;\r
1783 \r
1784     case cmuSelect_LFRCO:\r
1785       /* Select LFRCO as clock source for USB, can only be used in sleep mode */\r
1786 \r
1787       /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
1788       CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
1789 \r
1790       /* Switch oscillator */\r
1791       CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;\r
1792 \r
1793       /* Wait until clock is activated */\r
1794       while((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL)==0);\r
1795       break;\r
1796 \r
1797 #if defined( CMU_STATUS_USBCHFCLKSEL )\r
1798     case cmuSelect_HFCLK:\r
1799       /* Select undivided HFCLK as clock source for USB */\r
1800 \r
1801       /* Oscillator must already be enabled to avoid a core lockup */\r
1802       CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;\r
1803       /* Wait until clock is activated */\r
1804       while((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL)==0);\r
1805       break;\r
1806 #endif\r
1807 \r
1808 #if defined( CMU_CMD_USBCCLKSEL_USHFRCO )\r
1809     case cmuSelect_USHFRCO:\r
1810       /* Select USHFRCO as clock source for USB */\r
1811 \r
1812       /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
1813       CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);\r
1814 \r
1815       /* Switch oscillator */\r
1816       CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;\r
1817 \r
1818       /* Wait until clock is activated */\r
1819       while((CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL)==0);\r
1820       break;\r
1821 #endif\r
1822 \r
1823     default:\r
1824       /* Illegal clock source for USB */\r
1825       EFM_ASSERT(0);\r
1826       return;\r
1827     }\r
1828     /* Wait until clock has been activated */\r
1829     break;\r
1830 #endif\r
1831 \r
1832   default:\r
1833     EFM_ASSERT(0);\r
1834     break;\r
1835   }\r
1836 }\r
1837 \r
1838 \r
1839 /**************************************************************************//**\r
1840  * @brief\r
1841  *   CMU low frequency register synchronization freeze control.\r
1842  *\r
1843  * @details\r
1844  *   Some CMU registers requires synchronization into the low frequency (LF)\r
1845  *   domain. The freeze feature allows for several such registers to be\r
1846  *   modified before passing them to the LF domain simultaneously (which\r
1847  *   takes place when the freeze mode is disabled).\r
1848  *\r
1849  *   Another usage scenario of this feature, is when using an API (such\r
1850  *   as the CMU API) for modifying several bit fields consecutively in the\r
1851  *   same register. If freeze mode is enabled during this sequence, stalling\r
1852  *   can be avoided.\r
1853  *\r
1854  * @note\r
1855  *   When enabling freeze mode, this function will wait for all current\r
1856  *   ongoing CMU synchronization to LF domain to complete (Normally\r
1857  *   synchronization will not be in progress.) However for this reason, when\r
1858  *   using freeze mode, modifications of registers requiring LF synchronization\r
1859  *   should be done within one freeze enable/disable block to avoid unecessary\r
1860  *   stalling.\r
1861  *\r
1862  * @param[in] enable\r
1863  *   @li true - enable freeze, modified registers are not propagated to the\r
1864  *       LF domain\r
1865  *   @li false - disable freeze, modified registers are propagated to LF\r
1866  *       domain\r
1867  *****************************************************************************/\r
1868 void CMU_FreezeEnable(bool enable)\r
1869 {\r
1870   if (enable)\r
1871   {\r
1872     /* Wait for any ongoing LF synchronization to complete. This is just to */\r
1873     /* protect against the rare case when a user                            */\r
1874     /* - modifies a register requiring LF sync                              */\r
1875     /* - then enables freeze before LF sync completed                       */\r
1876     /* - then modifies the same register again                              */\r
1877     /* since modifying a register while it is in sync progress should be    */\r
1878     /* avoided.                                                             */\r
1879     while (CMU->SYNCBUSY)\r
1880       ;\r
1881 \r
1882     CMU->FREEZE = CMU_FREEZE_REGFREEZE;\r
1883   }\r
1884   else\r
1885   {\r
1886     CMU->FREEZE = 0;\r
1887   }\r
1888 }\r
1889 \r
1890 \r
1891 #if defined( _CMU_AUXHFRCOCTRL_BAND_MASK )\r
1892 /***************************************************************************//**\r
1893  * @brief\r
1894  *   Get AUXHFRCO band in use.\r
1895  *\r
1896  * @return\r
1897  *   AUXHFRCO band in use.\r
1898  ******************************************************************************/\r
1899 CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void)\r
1900 {\r
1901   return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK) >>\r
1902                                  _CMU_AUXHFRCOCTRL_BAND_SHIFT);\r
1903 }\r
1904 \r
1905 /***************************************************************************//**\r
1906  * @brief\r
1907  *   Set AUIXHFRCO band and the tuning value based on the value in the\r
1908  *   calibration table made during production.\r
1909  *\r
1910  * @param[in] band\r
1911  *   AUXHFRCO band to activate.\r
1912  ******************************************************************************/\r
1913 void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)\r
1914 {\r
1915   uint32_t tuning;\r
1916 \r
1917   /* Read tuning value from calibration table */\r
1918   switch (band)\r
1919   {\r
1920   case cmuAUXHFRCOBand_1MHz:\r
1921     tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK) >>\r
1922              _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT;\r
1923     break;\r
1924 \r
1925   case cmuAUXHFRCOBand_7MHz:\r
1926     tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK) >>\r
1927              _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT;\r
1928     break;\r
1929 \r
1930   case cmuAUXHFRCOBand_11MHz:\r
1931     tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK) >>\r
1932              _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT;\r
1933     break;\r
1934 \r
1935   case cmuAUXHFRCOBand_14MHz:\r
1936     tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK) >>\r
1937              _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT;\r
1938     break;\r
1939 \r
1940   case cmuAUXHFRCOBand_21MHz:\r
1941     tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK) >>\r
1942              _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT;\r
1943     break;\r
1944 \r
1945 #if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )\r
1946   case cmuAUXHFRCOBand_28MHz:\r
1947     tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK) >>\r
1948              _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT;\r
1949     break;\r
1950 #endif\r
1951 \r
1952   default:\r
1953     EFM_ASSERT(0);\r
1954     return;\r
1955   }\r
1956 \r
1957   /* Set band/tuning */\r
1958   CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL &\r
1959                     ~(_CMU_AUXHFRCOCTRL_BAND_MASK | _CMU_AUXHFRCOCTRL_TUNING_MASK)) |\r
1960                    (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT) |\r
1961                    (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);\r
1962 \r
1963 }\r
1964 #endif\r
1965 \r
1966 \r
1967 #if defined( _CMU_USHFRCOCONF_BAND_MASK )\r
1968 /***************************************************************************//**\r
1969  * @brief\r
1970  *   Get USHFRCO band in use.\r
1971  *\r
1972  * @return\r
1973  *   USHFRCO band in use.\r
1974  ******************************************************************************/\r
1975 CMU_USHFRCOBand_TypeDef CMU_USHFRCOBandGet(void)\r
1976 {\r
1977   return (CMU_USHFRCOBand_TypeDef)((CMU->USHFRCOCONF & _CMU_USHFRCOCONF_BAND_MASK) >>\r
1978                                      _CMU_USHFRCOCONF_BAND_SHIFT);\r
1979 }\r
1980 \r
1981 void CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band)\r
1982 {\r
1983   uint32_t           tuning;\r
1984   uint32_t           fineTuning;\r
1985   CMU_Select_TypeDef osc;\r
1986 \r
1987   /* Cannot switch band if USHFRCO is already selected as HF clock. */\r
1988   osc = CMU_ClockSelectGet(cmuClock_HF);\r
1989   EFM_ASSERT((CMU_USHFRCOBandGet() != band) && (osc != cmuSelect_USHFRCO));\r
1990 \r
1991   /* Read tuning value from calibration table */\r
1992   switch (band)\r
1993   {\r
1994   case cmuUSHFRCOBand_24MHz:\r
1995     tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_TUNING_MASK) >>\r
1996          _DEVINFO_USHFRCOCAL0_BAND24_TUNING_SHIFT;\r
1997     fineTuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_MASK) >>\r
1998          _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_SHIFT;\r
1999     break;\r
2000 \r
2001   case cmuUSHFRCOBand_48MHz:\r
2002     tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_TUNING_MASK) >>\r
2003          _DEVINFO_USHFRCOCAL0_BAND48_TUNING_SHIFT;\r
2004     fineTuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_MASK) >>\r
2005          _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_SHIFT;\r
2006     /* Enable the clock divider before switching the band from 24 to 48MHz */\r
2007     BITBAND_Peripheral(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 0);\r
2008     break;\r
2009 \r
2010   default:\r
2011     EFM_ASSERT(0);\r
2012     return;\r
2013   }\r
2014 \r
2015   /* Set band and tuning */\r
2016   CMU->USHFRCOCONF = (CMU->USHFRCOCONF & ~_CMU_USHFRCOCONF_BAND_MASK) |\r
2017                      (band << _CMU_USHFRCOCONF_BAND_SHIFT);\r
2018   CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~_CMU_USHFRCOCTRL_TUNING_MASK) |\r
2019                      (tuning << _CMU_USHFRCOCTRL_TUNING_SHIFT);\r
2020   CMU->USHFRCOTUNE = (CMU->USHFRCOTUNE & ~_CMU_USHFRCOTUNE_FINETUNING_MASK) |\r
2021                      (fineTuning << _CMU_USHFRCOTUNE_FINETUNING_SHIFT);\r
2022 \r
2023   /* Disable the clock divider after switching the band from 48 to 24MHz */\r
2024   if (band == cmuUSHFRCOBand_24MHz)\r
2025   {\r
2026     BITBAND_Peripheral(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 1);\r
2027   }\r
2028 }\r
2029 #endif\r
2030 \r
2031 \r
2032 /***************************************************************************//**\r
2033  * @brief\r
2034  *   Get HFRCO band in use.\r
2035  *\r
2036  * @return\r
2037  *   HFRCO band in use.\r
2038  ******************************************************************************/\r
2039 CMU_HFRCOBand_TypeDef CMU_HFRCOBandGet(void)\r
2040 {\r
2041   return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK) >>\r
2042                                  _CMU_HFRCOCTRL_BAND_SHIFT);\r
2043 }\r
2044 \r
2045 \r
2046 /***************************************************************************//**\r
2047  * @brief\r
2048  *   Set HFRCO band and the tuning value based on the value in the calibration\r
2049  *   table made during production.\r
2050  *\r
2051  * @param[in] band\r
2052  *   HFRCO band to activate.\r
2053  ******************************************************************************/\r
2054 void CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)\r
2055 {\r
2056   uint32_t           tuning;\r
2057   uint32_t           freq;\r
2058   CMU_Select_TypeDef osc;\r
2059 \r
2060   /* Read tuning value from calibration table */\r
2061   switch (band)\r
2062   {\r
2063   case cmuHFRCOBand_1MHz:\r
2064     tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK) >>\r
2065              _DEVINFO_HFRCOCAL0_BAND1_SHIFT;\r
2066     break;\r
2067 \r
2068   case cmuHFRCOBand_7MHz:\r
2069     tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK) >>\r
2070              _DEVINFO_HFRCOCAL0_BAND7_SHIFT;\r
2071     break;\r
2072 \r
2073   case cmuHFRCOBand_11MHz:\r
2074     tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK) >>\r
2075              _DEVINFO_HFRCOCAL0_BAND11_SHIFT;\r
2076     break;\r
2077 \r
2078   case cmuHFRCOBand_14MHz:\r
2079     tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK) >>\r
2080              _DEVINFO_HFRCOCAL0_BAND14_SHIFT;\r
2081     break;\r
2082 \r
2083   case cmuHFRCOBand_21MHz:\r
2084     tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK) >>\r
2085              _DEVINFO_HFRCOCAL1_BAND21_SHIFT;\r
2086     break;\r
2087 \r
2088 #if defined( _CMU_HFRCOCTRL_BAND_28MHZ )\r
2089   case cmuHFRCOBand_28MHz:\r
2090     tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK) >>\r
2091              _DEVINFO_HFRCOCAL1_BAND28_SHIFT;\r
2092     break;\r
2093 #endif\r
2094 \r
2095   default:\r
2096     EFM_ASSERT(0);\r
2097     return;\r
2098   }\r
2099 \r
2100   /* If HFRCO is used for core clock, we have to consider flash access WS. */\r
2101   osc = CMU_ClockSelectGet(cmuClock_HF);\r
2102   if (osc == cmuSelect_HFRCO)\r
2103   {\r
2104     /* Configure worst case wait states for flash access before setting divider */\r
2105     CMU_FlashWaitStateMax();\r
2106   }\r
2107 \r
2108   /* Set band/tuning */\r
2109   CMU->HFRCOCTRL = (CMU->HFRCOCTRL &\r
2110                     ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK)) |\r
2111                    (band << _CMU_HFRCOCTRL_BAND_SHIFT) |\r
2112                    (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT);\r
2113 \r
2114   /* If HFRCO is used for core clock, optimize flash WS */\r
2115   if (osc == cmuSelect_HFRCO)\r
2116   {\r
2117     /* Update CMSIS core clock variable and get current core clock */\r
2118     /* (The function will update the global variable) */\r
2119     /* NOTE! We need at least 21 cycles before setting zero wait state to flash */\r
2120     /* (i.e. WS0) when going from the 28MHz to 1MHz in the HFRCO band */\r
2121     freq = SystemCoreClockGet();\r
2122 \r
2123     /* Optimize flash access wait state setting for current core clk */\r
2124     CMU_FlashWaitStateControl(freq);\r
2125   }\r
2126 }\r
2127 \r
2128 \r
2129 /***************************************************************************//**\r
2130  * @brief\r
2131  *   Get the HFRCO startup delay.\r
2132  *\r
2133  * @details\r
2134  *   Please refer to the reference manual for further details.\r
2135  *\r
2136  * @return\r
2137  *   The startup delay in use.\r
2138  ******************************************************************************/\r
2139 uint32_t CMU_HFRCOStartupDelayGet(void)\r
2140 {\r
2141   return((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK) >>\r
2142          _CMU_HFRCOCTRL_SUDELAY_SHIFT);\r
2143 }\r
2144 \r
2145 \r
2146 /***************************************************************************//**\r
2147  * @brief\r
2148  *   Set the HFRCO startup delay.\r
2149  *\r
2150  * @details\r
2151  *   Please refer to the reference manual for further details.\r
2152  *\r
2153  * @param[in] delay\r
2154  *   The startup delay to set (<= 31).\r
2155  ******************************************************************************/\r
2156 void CMU_HFRCOStartupDelaySet(uint32_t delay)\r
2157 {\r
2158   EFM_ASSERT(delay <= 31);\r
2159 \r
2160   delay         &= (_CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT);\r
2161   CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK)) |\r
2162                    (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT);\r
2163 }\r
2164 \r
2165 \r
2166 /***************************************************************************//**\r
2167  * @brief\r
2168  *   Get the LCD framerate divisor (FDIV) setting.\r
2169  *\r
2170  * @return\r
2171  *   The LCD framerate divisor.\r
2172  ******************************************************************************/\r
2173 uint32_t CMU_LCDClkFDIVGet(void)\r
2174 {\r
2175 #if defined(LCD_PRESENT)\r
2176   return((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT);\r
2177 #else\r
2178   return 0;\r
2179 #endif /* defined(LCD_PRESENT) */\r
2180 }\r
2181 \r
2182 \r
2183 /***************************************************************************//**\r
2184  * @brief\r
2185  *   Set the LCD framerate divisor (FDIV) setting.\r
2186  *\r
2187  * @note\r
2188  *   The FDIV field (CMU LCDCTRL register) should only be modified while the\r
2189  *   LCD module is clock disabled (CMU LFACLKEN0.LCD bit is 0). This function\r
2190  *   will NOT modify FDIV if the LCD module clock is enabled. Please refer to\r
2191  *   CMU_ClockEnable() for disabling/enabling LCD clock.\r
2192  *\r
2193  * @param[in] div\r
2194  *   The FDIV setting to use.\r
2195  ******************************************************************************/\r
2196 void CMU_LCDClkFDIVSet(uint32_t div)\r
2197 {\r
2198 #if defined(LCD_PRESENT)\r
2199   EFM_ASSERT(div <= cmuClkDiv_128);\r
2200 \r
2201   /* Do not allow modification if LCD clock enabled */\r
2202   if (CMU->LFACLKEN0 & CMU_LFACLKEN0_LCD)\r
2203   {\r
2204     return;\r
2205   }\r
2206 \r
2207   div        <<= _CMU_LCDCTRL_FDIV_SHIFT;\r
2208   div         &= _CMU_LCDCTRL_FDIV_MASK;\r
2209   CMU->LCDCTRL = (CMU->LCDCTRL & ~_CMU_LCDCTRL_FDIV_MASK) | div;\r
2210 #else\r
2211   (void)div;  /* Unused parameter */\r
2212 #endif /* defined(LCD_PRESENT) */\r
2213 }\r
2214 \r
2215 \r
2216 /***************************************************************************//**\r
2217  * @brief\r
2218  *   Enable/disable oscillator.\r
2219  *\r
2220  * @note\r
2221  *   WARNING: When this function is called to disable either cmuOsc_LFXO or\r
2222  *   cmuOsc_HFXO the LFXOMODE or HFXOMODE fields of the CMU_CTRL register\r
2223  *   are reset to the reset value. I.e. if external clock sources are selected\r
2224  *   in either LFXOMODE or HFXOMODE fields, the configuration will be cleared\r
2225  *   and needs to be reconfigured if needed later.\r
2226  *\r
2227  * @param[in] osc\r
2228  *   The oscillator to enable/disable.\r
2229  *\r
2230  * @param[in] enable\r
2231  *   @li true - enable specified oscillator.\r
2232  *   @li false - disable specified oscillator.\r
2233  *\r
2234  * @param[in] wait\r
2235  *   Only used if @p enable is true.\r
2236  *   @li true - wait for oscillator start-up time to timeout before returning.\r
2237  *   @li false - do not wait for oscillator start-up time to timeout before\r
2238  *     returning.\r
2239  ******************************************************************************/\r
2240 void CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait)\r
2241 {\r
2242   uint32_t status;\r
2243   uint32_t enBit;\r
2244   uint32_t disBit;\r
2245 \r
2246   switch (osc)\r
2247   {\r
2248   case cmuOsc_HFRCO:\r
2249     enBit  = CMU_OSCENCMD_HFRCOEN;\r
2250     disBit = CMU_OSCENCMD_HFRCODIS;\r
2251     status = CMU_STATUS_HFRCORDY;\r
2252     break;\r
2253 \r
2254   case cmuOsc_HFXO:\r
2255     enBit  = CMU_OSCENCMD_HFXOEN;\r
2256     disBit = CMU_OSCENCMD_HFXODIS;\r
2257     status = CMU_STATUS_HFXORDY;\r
2258     break;\r
2259 \r
2260   case cmuOsc_AUXHFRCO:\r
2261     enBit  = CMU_OSCENCMD_AUXHFRCOEN;\r
2262     disBit = CMU_OSCENCMD_AUXHFRCODIS;\r
2263     status = CMU_STATUS_AUXHFRCORDY;\r
2264     break;\r
2265 \r
2266   case cmuOsc_LFRCO:\r
2267     enBit  = CMU_OSCENCMD_LFRCOEN;\r
2268     disBit = CMU_OSCENCMD_LFRCODIS;\r
2269     status = CMU_STATUS_LFRCORDY;\r
2270     break;\r
2271 \r
2272   case cmuOsc_LFXO:\r
2273     enBit  = CMU_OSCENCMD_LFXOEN;\r
2274     disBit = CMU_OSCENCMD_LFXODIS;\r
2275     status = CMU_STATUS_LFXORDY;\r
2276     break;\r
2277 \r
2278 #if defined( _CMU_STATUS_USHFRCOENS_MASK )\r
2279   case cmuOsc_USHFRCO:\r
2280     enBit  = CMU_OSCENCMD_USHFRCOEN;\r
2281     disBit = CMU_OSCENCMD_USHFRCODIS;\r
2282     status = CMU_STATUS_USHFRCORDY;\r
2283     break;\r
2284 #endif\r
2285 \r
2286 #if defined( _CMU_LFCLKSEL_LFAE_ULFRCO )\r
2287   case cmuOsc_ULFRCO:\r
2288     /* ULFRCO is always enabled, and cannot be turned off */\r
2289     return;\r
2290 #endif\r
2291 \r
2292   default:\r
2293     /* Undefined clock source */\r
2294     EFM_ASSERT(0);\r
2295     return;\r
2296   }\r
2297 \r
2298   if (enable)\r
2299   {\r
2300     CMU->OSCENCMD = enBit;\r
2301 \r
2302     /* Wait for clock to stabilize if requested */\r
2303     if (wait)\r
2304     {\r
2305       while (!(CMU->STATUS & status))\r
2306         ;\r
2307     }\r
2308   }\r
2309   else\r
2310   {\r
2311     CMU->OSCENCMD = disBit;\r
2312   }\r
2313 \r
2314   /* Keep EMU module informed */\r
2315   EMU_UpdateOscConfig();\r
2316 }\r
2317 \r
2318 \r
2319 /***************************************************************************//**\r
2320  * @brief\r
2321  *   Get oscillator frequency tuning setting.\r
2322  *\r
2323  * @param[in] osc\r
2324  *   Oscillator to get tuning value for, one of:\r
2325  *   @li #cmuOsc_LFRCO\r
2326  *   @li #cmuOsc_HFRCO\r
2327  *   @li #cmuOsc_AUXHFRCO\r
2328  *\r
2329  * @return\r
2330  *   The oscillator frequency tuning setting in use.\r
2331  ******************************************************************************/\r
2332 uint32_t CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)\r
2333 {\r
2334   uint32_t ret;\r
2335 \r
2336   switch (osc)\r
2337   {\r
2338   case cmuOsc_LFRCO:\r
2339     ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK) >>\r
2340           _CMU_LFRCOCTRL_TUNING_SHIFT;\r
2341     break;\r
2342 \r
2343   case cmuOsc_HFRCO:\r
2344     ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK) >>\r
2345           _CMU_HFRCOCTRL_TUNING_SHIFT;\r
2346     break;\r
2347 \r
2348   case cmuOsc_AUXHFRCO:\r
2349     ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK) >>\r
2350           _CMU_AUXHFRCOCTRL_TUNING_SHIFT;\r
2351     break;\r
2352 \r
2353   default:\r
2354     EFM_ASSERT(0);\r
2355     ret = 0;\r
2356     break;\r
2357   }\r
2358 \r
2359   return(ret);\r
2360 }\r
2361 \r
2362 \r
2363 /***************************************************************************//**\r
2364  * @brief\r
2365  *   Set the oscillator frequency tuning control.\r
2366  *\r
2367  * @note\r
2368  *   Oscillator tuning is done during production, and the tuning value is\r
2369  *   automatically loaded after a reset. Changing the tuning value from the\r
2370  *   calibrated value is for more advanced use.\r
2371  *\r
2372  * @param[in] osc\r
2373  *   Oscillator to set tuning value for, one of:\r
2374  *   @li #cmuOsc_LFRCO\r
2375  *   @li #cmuOsc_HFRCO\r
2376  *   @li #cmuOsc_AUXHFRCO\r
2377  *\r
2378  * @param[in] val\r
2379  *   The oscillator frequency tuning setting to use.\r
2380  ******************************************************************************/\r
2381 void CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc, uint32_t val)\r
2382 {\r
2383   switch (osc)\r
2384   {\r
2385   case cmuOsc_LFRCO:\r
2386     EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT));\r
2387 \r
2388     val           &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT);\r
2389     CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK)) |\r
2390                      (val << _CMU_LFRCOCTRL_TUNING_SHIFT);\r
2391     break;\r
2392 \r
2393   case cmuOsc_HFRCO:\r
2394     EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT));\r
2395 \r
2396     val           &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT);\r
2397     CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK)) |\r
2398                      (val << _CMU_HFRCOCTRL_TUNING_SHIFT);\r
2399     break;\r
2400 \r
2401   case cmuOsc_AUXHFRCO:\r
2402     EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT));\r
2403 \r
2404     val             <<= _CMU_AUXHFRCOCTRL_TUNING_SHIFT;\r
2405     val              &= _CMU_AUXHFRCOCTRL_TUNING_MASK;\r
2406     CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK)) | val;\r
2407     break;\r
2408 \r
2409   default:\r
2410     EFM_ASSERT(0);\r
2411     break;\r
2412   }\r
2413 }\r
2414 \r
2415 \r
2416 /**************************************************************************//**\r
2417  * @brief\r
2418  *   Determine if currently selected PCNTn clock used is external or LFBCLK.\r
2419  *\r
2420  * @param[in] inst\r
2421  *   PCNT instance number to get currently selected clock source for.\r
2422  *\r
2423  * @return\r
2424  *   @li true - selected clock is external clock.\r
2425  *   @li false - selected clock is LFBCLK.\r
2426  *****************************************************************************/\r
2427 bool CMU_PCNTClockExternalGet(unsigned int inst)\r
2428 {\r
2429   bool     ret;\r
2430   uint32_t setting;\r
2431 \r
2432   switch (inst)\r
2433   {\r
2434 #if defined(_CMU_PCNTCTRL_PCNT0CLKEN_MASK)\r
2435   case 0:\r
2436     setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0;\r
2437     break;\r
2438 \r
2439 #if defined(_CMU_PCNTCTRL_PCNT1CLKEN_MASK)\r
2440   case 1:\r
2441     setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0;\r
2442     break;\r
2443 \r
2444 #if defined(_CMU_PCNTCTRL_PCNT2CLKEN_MASK)\r
2445   case 2:\r
2446     setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0;\r
2447     break;\r
2448 #endif\r
2449 #endif\r
2450 #endif\r
2451 \r
2452   default:\r
2453     setting = 0;\r
2454     break;\r
2455   }\r
2456 \r
2457   if (setting)\r
2458   {\r
2459     ret = true;\r
2460   }\r
2461   else\r
2462   {\r
2463     ret = false;\r
2464   }\r
2465   return ret;\r
2466 }\r
2467 \r
2468 \r
2469 /**************************************************************************//**\r
2470  * @brief\r
2471  *   Select PCNTn clock.\r
2472  *\r
2473  * @param[in] inst\r
2474  *   PCNT instance number to set selected clock source for.\r
2475  *\r
2476  * @param[in] external\r
2477  *   Set to true to select external clock, false to select LFBCLK.\r
2478  *****************************************************************************/\r
2479 void CMU_PCNTClockExternalSet(unsigned int inst, bool external)\r
2480 {\r
2481 #if defined(PCNT_PRESENT)\r
2482   uint32_t setting = 0;\r
2483 \r
2484   EFM_ASSERT(inst < PCNT_COUNT);\r
2485 \r
2486   if (external)\r
2487   {\r
2488     setting = 1;\r
2489   }\r
2490 \r
2491   BITBAND_Peripheral(&(CMU->PCNTCTRL), (inst * 2) + 1, setting);\r
2492 \r
2493 #else\r
2494   (void)inst;      /* Unused parameter */\r
2495   (void)external;  /* Unused parameter */\r
2496 #endif\r
2497 }\r
2498 \r
2499 \r
2500 /** @} (end addtogroup CMU) */\r
2501 /** @} (end addtogroup EM_Library) */\r
2502 #endif /* __EM_CMU_H */\r