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