summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-10-21 10:45:33 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-10-21 10:45:33 -0600
commitb52689da1021481b1d2b809fbadc9e9c6334d67e (patch)
tree3d21bbcd0c9b9225954bdc222de3524a3f1e333a
parent8a56f7e3aa30f4812ca9d7e2cee27abe2fdbd28f (diff)
downloadpx4-nuttx-b52689da1021481b1d2b809fbadc9e9c6334d67e.tar.gz
px4-nuttx-b52689da1021481b1d2b809fbadc9e9c6334d67e.tar.bz2
px4-nuttx-b52689da1021481b1d2b809fbadc9e9c6334d67e.zip
EFM32: Add LFA and LFB clock support
-rw-r--r--nuttx/arch/arm/src/efm32/efm32_clockconfig.c247
-rw-r--r--nuttx/configs/efm32-g8xx-stk/include/board.h10
-rw-r--r--nuttx/configs/olimex-efm32g880f128-stk/include/board.h10
3 files changed, 251 insertions, 16 deletions
diff --git a/nuttx/arch/arm/src/efm32/efm32_clockconfig.c b/nuttx/arch/arm/src/efm32/efm32_clockconfig.c
index 8c2ec0d99..9edbb0641 100644
--- a/nuttx/arch/arm/src/efm32/efm32_clockconfig.c
+++ b/nuttx/arch/arm/src/efm32/efm32_clockconfig.c
@@ -71,6 +71,18 @@
# error HFPERCLK divisor not yet supported
#endif
+#ifdef BOARD_LFACLK_ULFRCO
+# define BOARD_LFA_ULFCO_ENABLE true
+#else
+# define BOARD_LFA_ULFCO_ENABLE false
+#endif
+
+#ifdef BOARD_LFBCLK_ULFRCO
+# define BOARD_LFB_ULFCO_ENABLE true
+#else
+# define BOARD_LFB_ULFCO_ENABLE false
+#endif
+
/****************************************************************************
* Public Data
****************************************************************************/
@@ -140,7 +152,7 @@ static inline void efm32_statuswait(uint32_t bitset)
*
****************************************************************************/
-static inline void efm32_enable_lfrco(void)
+static void efm32_enable_lfrco(void)
{
/* Enable the LFRCO */
@@ -148,8 +160,7 @@ static inline void efm32_enable_lfrco(void)
efm32_statuswait(CMU_STATUS_LFRCORDY);
}
-
-static inline void efm32_enable_lfxo(void)
+static void efm32_enable_lfxo(void)
{
/* Enable the LFXO */
@@ -165,7 +176,7 @@ static inline void efm32_enable_hfrco(void)
efm32_statuswait(CMU_STATUS_HFRCORDY);
}
-static inline void efm32_enable_hfxo(void)
+static void efm32_enable_hfxo(void)
{
/* Enable the HFXO */
@@ -182,6 +193,58 @@ static inline void efm32_enable_auxhfrco(void)
}
/****************************************************************************
+ * Name: efm32_enable_leclocking
+ *
+ * Description:
+ * Enable HFCORE clocking to the LE
+ *
+ ****************************************************************************/
+
+static void efm32_enable_leclocking(void)
+{
+ uint32_t regval;
+
+ regval = getreg32(EFM32_CMU_HFCORECLKEN0);
+ regval |= CMU_HFCORECLKEN0_LE;
+ putreg32(regval, EFM32_CMU_HFCORECLKEN0);
+}
+
+/****************************************************************************
+ * Name: efm32_enable_leclocking
+ *
+ * Description:
+ * If the core frequency is higher than CMU_MAX_FREQ_HFLE on
+ * Giant/Leopard/Wonder, enable HFLE and DIV4.
+ *
+ ****************************************************************************/
+
+#ifdef CMU_CTRL_HFLE
+static void efm32_enable_hfle(uint32_t frequency)
+{
+ uint32_t regval;
+
+ /* Check if the core frequency is higher than CMU_MAX_FREQ_HFLE */
+
+ if (frequency > CMU_MAX_FREQ_HFLE)
+ {
+ /* Enable HFLE */
+
+ regval = getreg32(EFM32_CMU_CTRL);
+ regval |= CMU_CTRL_HFLE;
+ putreg32(regval, EFM32_CMU_CTRL);
+
+ /* Enable DIV4 factor for peripheral clock */
+
+ regval = getreg32(EFM32_CMU_HFCORECLKDIV);
+ regval |= CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4;
+ putreg32(regval, EFM32_CMU_HFCORECLKDIV);
+ }
+}
+#else
+# define efm32_enable_hfle(f)
+#endif
+
+/****************************************************************************
* Name: efm32_maxwaitstates
*
* Description:
@@ -326,7 +389,7 @@ static void efm32_setwaitstates(uint32_t hfcoreclk)
*
****************************************************************************/
-static inline void efm32_hfclk_config(uint32_t hfclksel, uint32_t hfclkdiv)
+static inline uint32_t efm32_hfclk_config(uint32_t hfclksel, uint32_t hfclkdiv)
{
uint32_t frequency;
#ifdef CMU_CTRL_HFLE
@@ -427,6 +490,7 @@ static inline void efm32_hfclk_config(uint32_t hfclksel, uint32_t hfclkdiv)
/* Now select the optimal number of FLASH wait states */
efm32_setwaitstates(frequency);
+ return frequency;
}
/****************************************************************************
@@ -458,9 +522,11 @@ static inline void efm32_hfclk_config(uint32_t hfclksel, uint32_t hfclkdiv)
*
****************************************************************************/
-static inline void efm32_hfcoreclk_config(uint32_t hfcoreclkdiv)
+static inline uint32_t efm32_hfcoreclk_config(uint32_t hfcoreclkdiv,
+ uint32_t hfclk)
{
/* REVISIT: Divider not currently used */
+ return hfclk;
}
/****************************************************************************
@@ -479,9 +545,11 @@ static inline void efm32_hfcoreclk_config(uint32_t hfcoreclkdiv)
*
****************************************************************************/
-static inline void efm32_hfperclk_config(uint32_t hfperclkdiv)
+static inline uint32_t efm32_hfperclk_config(uint32_t hfperclkdiv,
+ uint32_t hfclk)
{
/* REVISIT: Divider not currently used */
+ return hfclk;
}
/****************************************************************************
@@ -509,9 +577,77 @@ static inline void efm32_hfperclk_config(uint32_t hfperclkdiv)
*
****************************************************************************/
-static inline void efm32_lfaclk_config(uint32_t lfaclksel)
+static inline uint32_t efm32_lfaclk_config(uint32_t lfaclksel, bool ulfrco,
+ uint32_t hfcoreclk)
{
- /* REVISIT: Not yet implemented */
+ uint32_t lfaclk;
+ uint32_t regval;
+
+ /* ULFRCO is a special case */
+
+ if (ulfrco)
+ {
+ /* ULFRCO is always enabled */
+
+ lfaclksel = _CMU_LFCLKSEL_LFA_DISABLED;
+ lfaclk = BOARD_ULFRCO_FREQUNCY;
+ }
+ else
+ {
+ /* Enable the oscillator source */
+
+ switch (lfaclksel)
+ {
+ default:
+ case _CMU_LFCLKSEL_LFA_DISABLED:
+ {
+ lfaclk = 0;
+ }
+ break;
+
+ case CMU_LFCLKSEL_LFA_LFRCO:
+ {
+ efm32_enable_lfrco();
+ }
+ break;
+
+ case _CMU_LFCLKSEL_LFA_LFXO:
+ {
+ efm32_enable_lfxo();
+ lfaclk = BOARD_LFXO_FREQUENCY;
+ }
+ break;
+
+ case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
+ {
+ /* Enable core clocking to the LE */
+
+ efm32_enable_leclocking();
+
+ /* Enable HFLE, if appropriate */
+
+ efm32_enable_hfle(hfcoreclk);
+
+ /* And, finally, enable the HFXO */
+
+ efm32_enable_hfxo();
+ lfaclk = hfcoreclk >> 1;
+ }
+ break;
+ }
+ }
+
+ /* Enable the LFA clock in the LFCLKSEL register */
+
+ regval = getreg32(EFM32_CMU_LFCLKSEL);
+ regval &= ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK);
+ regval |= (lfaclksel << _CMU_LFCLKSEL_LFA_SHIFT);
+#ifdef CMU_LFCLKSEL_LFAE_ULFRCO
+ regval |= ((uint32_t)ulfrco << _CMU_LFCLKSEL_LFAE_SHIFT);
+#endif
+ putreg32(regval, EFM32_CMU_LFCLKSEL);
+
+ return lfaclk;
}
/****************************************************************************
@@ -535,9 +671,77 @@ static inline void efm32_lfaclk_config(uint32_t lfaclksel)
*
****************************************************************************/
-static inline void efm32_lfbclk_config(uint32_t lfbclksel)
+static inline uint32_t efm32_lfbclk_config(uint32_t lfbclksel, bool ulfrco,
+ uint32_t hfcoreclk)
{
- /* REVISIT: Not yet implemented */
+ uint32_t lfbclk;
+ uint32_t regval;
+
+ /* ULFRCO is a special case */
+
+ if (ulfrco)
+ {
+ /* ULFRCO is always enabled */
+
+ lfbclksel = _CMU_LFCLKSEL_LFB_DISABLED;
+ lfbclk = BOARD_ULFRCO_FREQUNCY;
+ }
+ else
+ {
+ /* Enable the oscillator source */
+
+ switch (lfbclksel)
+ {
+ default:
+ case _CMU_LFCLKSEL_LFB_DISABLED:
+ {
+ lfbclk = 0;
+ }
+ break;
+
+ case CMU_LFCLKSEL_LFB_LFRCO:
+ {
+ efm32_enable_lfrco();
+ }
+ break;
+
+ case _CMU_LFCLKSEL_LFB_LFXO:
+ {
+ efm32_enable_lfxo();
+ lfbclk = BOARD_LFXO_FREQUENCY;
+ }
+ break;
+
+ case _CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2:
+ {
+ /* Enable core clocking to the LE */
+
+ efm32_enable_leclocking();
+
+ /* Enable HFLE, if appropriate */
+
+ efm32_enable_hfle(hfcoreclk);
+
+ /* And, finally, enable the HFXO */
+
+ efm32_enable_hfxo();
+ lfbclk = hfcoreclk >> 1;
+ }
+ break;
+ }
+ }
+
+ /* Enable the LFB clock in the LFCLKSEL register */
+
+ regval = getreg32(EFM32_CMU_LFCLKSEL);
+ regval &= ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK);
+ regval |= (lfbclksel << _CMU_LFCLKSEL_LFB_SHIFT);
+#ifdef CMU_LFCLKSEL_LFBE_ULFRCO
+ regval |= ((uint32_t)ulfrco << _CMU_LFCLKSEL_LFBE_SHIFT);
+#endif
+ putreg32(regval, EFM32_CMU_LFCLKSEL);
+
+ return lfbclk;
}
/****************************************************************************
@@ -634,17 +838,28 @@ static inline void efm32_gpioclock(void)
void efm32_clockconfig(void)
{
+ uint32_t hfclk;
+ uint32_t hfcoreclk;
+ uint32_t hfperclk;
+ uint32_t lfaclk;
+ uint32_t lfbclk;
+
/* Enable clocks and set dividers as determined by the board.h header file */
- efm32_hfclk_config(BOARD_HFCLKSEL, BOARD_HFCLKDIV);
- efm32_hfcoreclk_config(BOARD_HFCORECLKDIV);
- efm32_hfperclk_config(BOARD_HFPERCLKDIV);
- efm32_lfaclk_config(BOARD_LFACLKSEL);
- efm32_lfbclk_config(BOARD_LFBCLKSEL);
+ hfclk = efm32_hfclk_config(BOARD_HFCLKSEL, BOARD_HFCLKDIV);
+ hfcoreclk = efm32_hfcoreclk_config(BOARD_HFCORECLKDIV, hfclk);
+ hfperclk = efm32_hfperclk_config(BOARD_HFPERCLKDIV, hfclk);
+ lfaclk = efm32_lfaclk_config(BOARD_LFACLKSEL, BOARD_LFA_ULFCO_ENABLE, hfcoreclk);
+ lfbclk = efm32_lfbclk_config(BOARD_LFBCLKSEL, BOARD_LFB_ULFCO_ENABLE, hfcoreclk);
+
efm32_pcntclk_config();
efm32_wdogclk_config();
efm32_auxclk_config();
+ UNUSED(hfperclk);
+ UNUSED(lfaclk);
+ UNUSED(lfbclk);
+
/* Enable clocking of the GPIO ports */
efm32_gpioclock();
diff --git a/nuttx/configs/efm32-g8xx-stk/include/board.h b/nuttx/configs/efm32-g8xx-stk/include/board.h
index 2bcddbb71..62035cc82 100644
--- a/nuttx/configs/efm32-g8xx-stk/include/board.h
+++ b/nuttx/configs/efm32-g8xx-stk/include/board.h
@@ -56,6 +56,7 @@
* - 4-32 MHz High Frequency Crystal Oscillator (HFXO)
* - 32.768 kHz Low Frequency RC Oscillator (LFRCO)
* - 32.768 kHz Low Frequency Crystal Oscillator (LFXO)
+ * - 1KHz Ultra Low Frequency RC Oscillator (ULFRCO)
*
* The device boots with 14 MHz HFRCO as the HFCLK source.
*/
@@ -67,6 +68,7 @@
#define BOARD_HFXO_FREQUENCY 32000000 /* 32MHz crystal on board */
#define BOARD_LFRCO_FREQUENCY 32768 /* Low frequency oscillator */
#define BOARD_LFXO_FREQUENCY 32768 /* 32MHz crystal on board */
+#define BOARD_ULFRCO_FREQUNCY 1000 /* Ultra low frequency oscillator */
/* HFCLK - High Frequency Clock
*
@@ -110,9 +112,13 @@
* LFRCO is disabled from reset. The selection is configured using the LFA
* field in CMU_LFCLKSEL. The HFCORECLK/2 setting allows the Low Energy A
* Peripherals to be used as high-frequency peripherals.
+ *
+ * Use _CMU_LFCLKSEL_LFA_DISABLED to disable.
+ * ULFRCO is a special case.
*/
#define BOARD_LFACLKSEL _CMU_LFCLKSEL_LFA_LFXO
+#undef BOARD_LFACLK_ULFRCO
#define BOARD_LFACLK_FREQUENCY BOARD_LFXO_FREQUENCY
/* LFBCLK - Low Frequency B Clock
@@ -123,9 +129,13 @@
* LFRCO is disabled from reset. The selection is configured using the LFB
* field in CMU_LFCLKSEL. The HFCORECLK/2 setting allows the Low Energy B
* Peripherals to be used as high-frequency peripherals.
+ *
+ * Use _CMU_LFCLKSEL_LFA_DISABLED to disable
+ * ULFRCO is a special case.
*/
#define BOARD_LFBCLKSEL _CMU_LFCLKSEL_LFB_LFXO
+#undef BOARD_LFBCLK_ULFRCO
#define BOARD_LFBCLK_FREQUENCY BOARD_LFXO_FREQUENCY
/* PCNTnCLK - Pulse Counter n Clock
diff --git a/nuttx/configs/olimex-efm32g880f128-stk/include/board.h b/nuttx/configs/olimex-efm32g880f128-stk/include/board.h
index 96b11a40f..e1f1f68b2 100644
--- a/nuttx/configs/olimex-efm32g880f128-stk/include/board.h
+++ b/nuttx/configs/olimex-efm32g880f128-stk/include/board.h
@@ -56,6 +56,7 @@
* - 4-32 MHz High Frequency Crystal Oscillator (HFXO)
* - 32.768 kHz Low Frequency RC Oscillator (LFRCO)
* - 32.768 kHz Low Frequency Crystal Oscillator (LFXO)
+ * - 1KHz Ultra Low Frequency RC Oscillator (ULFRCO)
*
* The device boots with 14 MHz HFRCO as the HFCLK source.
*/
@@ -67,6 +68,7 @@
#define BOARD_HFXO_FREQUENCY 32000000 /* 32MHz crystal on board */
#define BOARD_LFRCO_FREQUENCY 32768 /* Low frequency oscillator */
#define BOARD_LFXO_FREQUENCY 32768 /* 32MHz crystal on board */
+#define BOARD_ULFRCO_FREQUNCY 1000 /* Ultra low frequency oscillator */
/* HFCLK - High Frequency Clock
*
@@ -110,9 +112,13 @@
* LFRCO is disabled from reset. The selection is configured using the LFA
* field in CMU_LFCLKSEL. The HFCORECLK/2 setting allows the Low Energy A
* Peripherals to be used as high-frequency peripherals.
+ *
+ * Use _CMU_LFCLKSEL_LFA_DISABLED to disable
+ * ULFRCO is a special case.
*/
#define BOARD_LFACLKSEL _CMU_LFCLKSEL_LFA_LFXO
+#undef BOARD_LFACLK_ULFRCO
#define BOARD_LFACLK_FREQUENCY BOARD_LFXO_FREQUENCY
/* LFBCLK - Low Frequency B Clock
@@ -123,9 +129,13 @@
* LFRCO is disabled from reset. The selection is configured using the LFB
* field in CMU_LFCLKSEL. The HFCORECLK/2 setting allows the Low Energy B
* Peripherals to be used as high-frequency peripherals.
+ *
+ * Use _CMU_LFCLKSEL_LFB_DISABLED to disable
+ * ULFRCO is a special case.
*/
#define BOARD_LFBCLKSEL _CMU_LFCLKSEL_LFB_LFXO
+#undef BOARD_LFBCLK_ULFRCO
#define BOARD_LFBCLK_FREQUENCY BOARD_LFXO_FREQUENCY
/* PCNTnCLK - Pulse Counter n Clock