SAML32: Update some DFLL logic

This commit is contained in:
Gregory Nutt
2015-05-20 12:26:49 -06:00
parent ea1adddbcd
commit 67a45b019d
2 changed files with 263 additions and 81 deletions
+226 -50
View File
@@ -107,12 +107,18 @@ static inline void sam_xosc32k_config(void);
static inline void sam_osc32k_config(void);
#endif
static inline void sam_osc16m_config(void);
#ifdef BOARD_DFLL_ENABLE
#ifdef BOARD_DFLL48M_ENABLE
static inline void sam_dfll48m_config(void);
static inline void sam_dfll48m_enable(void);
#endif
#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL_ENABLE) && \
!defined(BOARD_DFLL_OPENLOOP)
static inline void sam_dfll_reference(void);
#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL48M_ENABLE) && \
!defined(BOARD_DFLL48M_OPENLOOP)
static inline void sam_dfll48m_reference(void);
#endif
#ifdef BOARD_FDPLL96M_ENABLE
static inline void sam_fdpll96m_config(void);
static inline void sam_fdpll96m_enable(void);
static inline void sam_fdpll96m_reference(void);
#endif
static void sam_gclck_waitsyncbusy(void);
static void sam_gclk_config(FAR const struct sam_gclkconfig_s *config);
@@ -751,27 +757,30 @@ static inline void sam_osc16m_config(void)
* Name: sam_dfll48m_config
*
* Description:
* Configure the DFLL based on settings in the board.h header file.
* Configure the DFLL48M based on settings in the board.h header file.
* Depends on:
*
* BOARD_DFLL_OPENLOOP - Boolean (defined / not defined)
* BOARD_DFLL_TRACKAFTERFINELOCK - Boolean (defined / not defined)
* BOARD_DFLL_KEEPLOCKONWAKEUP - Boolean (defined / not defined)
* BOARD_DFLL_ENABLECHILLCYCLE - Boolean (defined / not defined)
* BOARD_DFLL_QUICKLOCK - Boolean (defined / not defined)
* BOARD_DFLL_ONDEMAND - Boolean (defined / not defined)
* BOARD_DFLL_COARSEVALUE - Value
* BOARD_DFLL_FINEVALUE - Value
* BOARD_DFLL48M_CLOSEDLOOP - Boolean (defined / not defined)
* BOARD_DFLL48M_OPENLOOP - Boolean (defined / not defined)
* BOARD_DFLL48M_RECOVERY - Boolean (defined / not defined)
* BOARD_DFLL48M_TRACKAFTERFINELOCK - Boolean (defined / not defined)
* BOARD_DFLL48M_KEEPLOCKONWAKEUP - Boolean (defined / not defined)
* BOARD_DFLL48M_ENABLECHILLCYCLE - Boolean (defined / not defined)
* BOARD_DFLL48M_QUICKLOCK - Boolean (defined / not defined)
* BOARD_DFLL48M_RUNINSTDBY - Boolean (defined / not defined)
* BOARD_DFLL48M_ONDEMAND - Boolean (defined / not defined)
* BOARD_DFLL48M_COARSEVALUE - Value
* BOARD_DFLL48M_FINEVALUE - Value
*
* Open Loop mode only:
* BOARD_DFLL_COARSEVALUE - Value
* BOARD_DFLL_FINEVALUE - Value
* BOARD_DFLL48M_COARSEVALUE - Value
* BOARD_DFLL48M_FINEVALUE - Value
*
* Closed loop mode only:
* BOARD_DFLL_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
* BOARD_DFLL_MULTIPLIER - Value
* BOARD_DFLL_MAXCOARSESTEP - Value
* BOARD_DFLL_MAXFINESTEP - Value
* BOARD_DFLL48M_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
* BOARD_DFLL48M_MULTIPLIER - Value
* BOARD_DFLL48M_MAXCOARSESTEP - Value
* BOARD_DFLL48M_MAXFINESTEP - Value
*
* Input Parameters:
* None
@@ -781,36 +790,66 @@ static inline void sam_osc16m_config(void)
*
****************************************************************************/
#ifdef BOARD_DFLL_ENABLE
#ifdef BOARD_DFLL48M_ENABLE
static inline void sam_dfll48m_config(void)
{
uint16_t control;
uint32_t regval;
/* Disable ONDEMAND mode while writing configurations (Errata 9905). This
* is probably not necessary on the first time configuration after reset.
*/
control = getreg16(SAM_OSCCTRL_DFLLCTRL);
control &= ~(OSCCTRL_DFLLCTRL_ENABLE | OSCCTRL_DFLLCTRL_ONDEMAND);
putreg16(control, SAM_OSCCTRL_DFLLCTRL);
/* Wait for the DFLL to synchronize */
while ((getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_DFLLRDY) == 0);
/* Set up the DFLL control register */
control = OSCCTRL_DFLLCTRL_ENABLE; /* Enable the DFLL */
control &= ~(OSCCTRL_DFLLCTRL_MODE | OSCCTRL_DFLLCTRL_STABLE |
OSCCTRL_DFLLCTRL_LLAW | OSCCTRL_DFLLCTRL_USBCRM |
OSCCTRL_DFLLCTRL_RUNSTDBY | OSCCTRL_DFLLCTRL_CCDIS |
OSCCTRL_DFLLCTRL_QLDIS | OSCCTRL_DFLLCTRL_BPLCKC |
OSCCTRL_DFLLCTRL_WAITLOCK);
#ifndef BOARD_DFLL_OPENLOOP
#if defined(BOARD_DFLL48M_CLOSELOOP
control |= OSCCTRL_DFLLCTRL_MODE; /* Closed loop mode */
#if defined(BOARD_DFLL48M_RECOVERY
control |= OSCCTRL_DFLLCTRL_USBCRM; /* USB clock recovery mode */
#endif
#ifndef BOARD_DFLL_TRACKAFTERFINELOCK
#ifndef BOARD_DFLL48M_TRACKAFTERFINELOCK
control |= OSCCTRL_DFLLCTRL_STABLE; /* FINE calibration fixed after a fine lock */
#endif
#ifndef BOARD_DFLL_KEEPLOCKONWAKEUP
#ifndef BOARD_DFLL48M_KEEPLOCKONWAKEUP
control |= OSCCTRL_DFLLCTRL_LLAW; /* Lose lock after wake */
#endif
#ifndef BOARD_DFLL_ENABLECHILLCYCLE
#ifndef BOARD_DFLL48M_RUNINSTDBY
control |= OSCCTRL_DFLLCTRL_RUNSTDBY; /* Chill cycle disable */
#endif
#ifndef BOARD_DFLL48M_ENABLECHILLCYCLE
control |= OSCCTRL_DFLLCTRL_CCDIS; /* Chill cycle disable */
#endif
#ifndef BOARD_DFLL_QUICKLOCK
#ifndef BOARD_DFLL48M_QUICKLOCK
control |= OSCCTRL_DFLLCTRL_QLDIS; /* Quick lock disable */
#endif
#ifndef BOARD_DFLL48M_BPLCKC
control |= OSCCTRL_DFLLCTRL_BPLCKC; /* Bypass coarse clock */
#endif
#ifndef BOARD_DFLL48M_WAITLOCK
control |= OSCCTRL_DFLLCTRL_WAITLOCK; /* Wait lock */
#endif
/* Then enable the DFLL (with ONDEMAND set to zero). */
putreg16(control, SAM_OSCCTRL_DFLLCTRL);
@@ -821,10 +860,10 @@ static inline void sam_dfll48m_config(void)
/* Set up the open loop mode multiplier register */
#ifndef BOARD_DFLL_OPENLOOP
regval = OSCCTRL_DFLLMUL_CSTEP(BOARD_DFLL_MAXCOARSESTEP) |
OSCCTRL_DFLLMUL_FSTEP(BOARD_DFLL_MAXFINESTEP) |
OSCCTRL_DFLLMUL_MUL(BOARD_DFLL_MULTIPLIER);
#ifndef BOARD_DFLL48M_OPENLOOP
regval = OSCCTRL_DFLLMUL_CSTEP(BOARD_DFLL48M_MAXCOARSESTEP) |
OSCCTRL_DFLLMUL_FSTEP(BOARD_DFLL48M_MAXFINESTEP) |
OSCCTRL_DFLLMUL_MUL(BOARD_DFLL48M_MULTIPLIER);
putreg32(regval, SAM_OSCCTRL_DFLLMUL);
#else
putreg32(0, SAM_OSCCTRL_DFLLMUL);
@@ -832,29 +871,19 @@ static inline void sam_dfll48m_config(void)
/* Set up the DFLL value register */
regval = OSCCTRL_DFLLVAL_COARSE(BOARD_DFLL_COARSEVALUE) |
OSCCTRL_DFLLVAL_FINE(BOARD_DFLL_FINEVALUE);
regval = OSCCTRL_DFLLVAL_COARSE(BOARD_DFLL48M_COARSEVALUE) |
OSCCTRL_DFLLVAL_FINE(BOARD_DFLL48M_FINEVALUE);
putreg32(regval, SAM_OSCCTRL_DFLLVAL);
/* Finally, set the state of the ONDEMAND bit if necessary */
#ifdef BOARD_DFLL_ONDEMAND
control |= OSCCTRL_DFLLCTRL_ONDEMAND; /* On demand control */
putreg16(control, SAM_OSCCTRL_DFLLCTRL);
#endif
}
#else
# define sam_dfll48m_config()
#endif
/****************************************************************************
* Name: sam_dfll_reference
* Name: sam_dfll48m_enable
*
* Description:
* Enable DFLL reference clock if in closed loop mode.
* Depends on:
*
* BOARD_DFLL_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
* Enable the DFLL48M.
*
* Input Parameters:
* None
@@ -864,9 +893,53 @@ static inline void sam_dfll48m_config(void)
*
****************************************************************************/
#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL_ENABLE) && \
!defined(BOARD_DFLL_OPENLOOP)
static inline void sam_dfll_reference(void)
#ifdef BOARD_DFLL48M_ENABLE
static inline void sam_dfll48m_enable(void)
{
uint16_t control;
uint32_t regval;
/* Enable the DFLL48M (with ONDEMAND still set to zero). */
control = getreg16(SAM_OSCCTRL_DFLLCTRL);
control |= OSCCTRL_DFLLCTRL_ENABLE; /* Enable the DFLL */
putreg16(control, SAM_OSCCTRL_DFLLCTRL);
/* Wait for the DFLL to synchronize */
while ((getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_DFLLRDY) == 0);
/* Finally, set the state of the ONDEMAND bit if necessary */
#ifdef BOARD_DFLL48M_ONDEMAND
control |= OSCCTRL_DFLLCTRL_ONDEMAND; /* On demand control */
putreg16(control, SAM_OSCCTRL_DFLLCTRL);
#endif
}
#else
# define sam_dfll48m_enable()
#endif
/****************************************************************************
* Name: sam_dfll48m_reference
*
* Description:
* Enable DFLL reference clock if in closed loop mode.
* Depends on:
*
* BOARD_DFLL48M_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL48M_ENABLE) && \
!defined(BOARD_DFLL48M_OPENLOOP)
static inline void sam_dfll48m_reference(void)
{
uint16_t regval;
@@ -885,7 +958,7 @@ static inline void sam_dfll_reference(void)
* NOTE: We could enable write lock here to prevent further modification
*/
regval = (BOARD_DFLL_SRCGCLKGEN | GCLK_CLKCTRL_ID_DFLL48M);
regval = (BOARD_DFLL48M_SRCGCLKGEN | GCLK_CLKCTRL_ID_DFLL48M);
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Enable the DFLL reference clock */
@@ -901,7 +974,98 @@ static inline void sam_dfll_reference(void)
while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) == 0);
}
#else
# define sam_dfll_reference()
# define sam_dfll48m_reference()
#endif
/****************************************************************************
* Name: sam_fdpll96m_config
*
* Description:
* Configure the DFLL based on settings in the board.h header file.
* Depends on:
*
* BOARD_FDPLL96M_OPENLOOP - Boolean (defined / not defined)
* BOARD_FDPLL96M_TRACKAFTERFINELOCK - Boolean (defined / not defined)
* BOARD_FDPLL96M_KEEPLOCKONWAKEUP - Boolean (defined / not defined)
* BOARD_FDPLL96M_ENABLECHILLCYCLE - Boolean (defined / not defined)
* BOARD_FDPLL96M_QUICKLOCK - Boolean (defined / not defined)
* BOARD_FDPLL96M_ONDEMAND - Boolean (defined / not defined)
* BOARD_FDPLL96M_COARSEVALUE - Value
* BOARD_FDPLL96M_FINEVALUE - Value
*
* Open Loop mode only:
* BOARD_FDPLL96M_COARSEVALUE - Value
* BOARD_FDPLL96M_FINEVALUE - Value
*
* Closed loop mode only:
* BOARD_FDPLL96M_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
* BOARD_FDPLL96M_MULTIPLIER - Value
* BOARD_FDPLL96M_MAXCOARSESTEP - Value
* BOARD_FDPLL96M_MAXFINESTEP - Value
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef BOARD_FDPLL96M_ENABLE
static inline void sam_fdpll96m_config(void)
{
#error Missing logic
}
#else
# define sam_fdpll96m_config()
#endif
/****************************************************************************
* Name: sam_fdpll96m_enable
*
* Description:
* Enable the FDPLL96M.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef BOARD_FDPLL96M_ENABLE
static inline void sam_fdpll96m_enable(void)
{
#error Missing logic
}
#else
# define sam_fdpll96m_enable()
#endif
/****************************************************************************
* Name: sam_fdpll96m_reference
*
* Description:
* Enable FDPLL96M reference clock.
* Depends on:
*
* BOARD_FDPLL96M_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_FDPLL96M_ENABLE)
static inline void sam_fdpll96m_reference(void)
{
}
#else
# define sam_fdpll96m_enable()
#endif
/****************************************************************************
@@ -1105,7 +1269,11 @@ static inline void sam_config_gclks(void)
/* Enable DFLL reference clock if the DFLL is enabled in closed loop mode */
sam_dfll_reference();
sam_dfll48m_reference();
/* Enable FDPLL reference clock if the DFLL is enabled */
sam_fdpll96m_reference();
/* Configure the GCLK_MAIN last as it may depend on the DFLL or other
* generators
@@ -1231,6 +1399,14 @@ void sam_clockconfig(void)
sam_config_gclks();
/* Enable DFLL48M */
sam_dfll48m_enable();
/* Enable FDPLL96M */
sam_fdpll96m_enable();
/* Set CPU and BUS clock dividers */
sam_dividers();
+37 -31
View File
@@ -175,50 +175,56 @@
* be determined by the values written to the DFLL Coarse Value bit group
* and the DFLL Fine Value bit group in the DFLL Value register.
*
* BOARD_DFLL_OPENLOOP - Boolean (defined / not defined)
* BOARD_DFLL_TRACKAFTERFINELOCK - Boolean (defined / not defined)
* BOARD_DFLL_KEEPLOCKONWAKEUP - Boolean (defined / not defined)
* BOARD_DFLL_ENABLECHILLCYCLE - Boolean (defined / not defined)
* BOARD_DFLL_QUICKLOCK - Boolean (defined / not defined)
* BOARD_DFLL_ONDEMAND - Boolean (defined / not defined)
* BOARD_DFLL_COARSEVALUE - Value
* BOARD_DFLL_FINEVALUE - Value
* BOARD_DFLL48M_CLOSEDLOOP - Boolean (defined / not defined)
* BOARD_DFLL48M_OPENLOOP - Boolean (defined / not defined)
* BOARD_DFLL48M_RECOVERY - Boolean (defined / not defined)
* BOARD_DFLL48M_TRACKAFTERFINELOCK - Boolean (defined / not defined)
* BOARD_DFLL48M_KEEPLOCKONWAKEUP - Boolean (defined / not defined)
* BOARD_DFLL48M_ENABLECHILLCYCLE - Boolean (defined / not defined)
* BOARD_DFLL48M_QUICKLOCK - Boolean (defined / not defined)
* BOARD_DFLL48M_RUNINSTDBY - Boolean (defined / not defined)
* BOARD_DFLL48M_ONDEMAND - Boolean (defined / not defined)
* BOARD_DFLL48M_COARSEVALUE - Value
* BOARD_DFLL48M_FINEVALUE - Value
*
* Open Loop mode only:
* BOARD_DFLL_COARSEVALUE - Value
* BOARD_DFLL_FINEVALUE - Value
* BOARD_DFLL48M_COARSEVALUE - Value
* BOARD_DFLL48M_FINEVALUE - Value
*
* Closed loop mode only:
* BOARD_DFLL_GCLKGEN - See GCLK_CLKCTRL_GEN* definitions
* BOARD_DFLL_MULTIPLIER - Value
* BOARD_DFLL_MAXCOARSESTEP - Value
* BOARD_DFLL_MAXFINESTEP - Value
* BOARD_DFLL48M_GCLKGEN - See GCLK_CLKCTRL_GEN* definitions
* BOARD_DFLL48M_MULTIPLIER - Value
* BOARD_DFLL48M_MAXCOARSESTEP - Value
* BOARD_DFLL48M_MAXFINESTEP - Value
*
* BOARD_DFLL_FREQUENCY - The resulting frequency
* BOARD_DFLL48M_FREQUENCY - The resulting frequency
*/
#define BOARD_DFLL_ENABLE 1
#undef BOARD_DFLL_OPENLOOP
#undef BOARD_DFLL_ONDEMAND
#undef BOARD_DFLL_RUNINSTANDBY
#define BOARD_DFLL48M_ENABLE 1 /* Use the DFLL48M */
#define BOARD_DFLL48M_CLOSEDLOOP 1 /* In closed loop mode */
#undef BOARD_DFLL48M_OPENLOOP
#undef BOARD_DFLL48M_RECOVERY
#undef BOARD_DFLL48M_RUNINSTDBY
#undef BOARD_DFLL48M_ONDEMAND
#undef BOARD_DFLL48M_RUNINSTANDBY
/* DFLL open loop mode configuration */
#define BOARD_DFLL_COARSEVALUE (0x1f / 4)
#define BOARD_DFLL_FINEVALUE (0xff / 4)
#define BOARD_DFLL48M_COARSEVALUE (0x1f / 4)
#define BOARD_DFLL48M_FINEVALUE (0xff / 4)
/* DFLL closed loop mode configuration */
#define BOARD_DFLL_SRCGCLKGEN GCLK_CLKCTRL_GEN1
#define BOARD_DFLL_MULTIPLIER 12
#define BOARD_DFLL_QUICKLOCK 1
#define BOARD_DFLL_TRACKAFTERFINELOCK 1
#define BOARD_DFLL_KEEPLOCKONWAKEUP 1
#define BOARD_DFLL_ENABLECHILLCYCLE 1
#define BOARD_DFLL_MAXCOARSESTEP (0x1f / 4)
#define BOARD_DFLL_MAXFINESTEP (0xff / 4)
#define BOARD_DFLL48M_SRCGCLKGEN GCLK_CLKCTRL_GEN1
#define BOARD_DFLL48M_MULTIPLIER 12
#define BOARD_DFLL48M_QUICKLOCK 1
#define BOARD_DFLL48M_TRACKAFTERFINELOCK 1
#define BOARD_DFLL48M_KEEPLOCKONWAKEUP 1
#define BOARD_DFLL48M_ENABLECHILLCYCLE 1
#define BOARD_DFLL48M_MAXCOARSESTEP (0x1f / 4)
#define BOARD_DFLL48M_MAXFINESTEP (0xff / 4)
#define BOARD_DFLL_FREQUENCY (48000000)
#define BOARD_DFLL48M_FREQUENCY (48000000)
/* GCLK Configuration
*
@@ -244,7 +250,7 @@
#define BOARD_GCLK0_CLOCK_SOURCE GCLK_GENCTRL_SRC_DFLL48M
#define BOARD_GCLK0_PRESCALER 1
#undef BOARD_GCLK0_OUTPUT_ENABLE
#define BOARD_GCLK0_FREQUENCY (BOARD_DFLL_FREQUENCY / BOARD_GCLK0_PRESCALER)
#define BOARD_GCLK0_FREQUENCY (BOARD_DFLL48M_FREQUENCY / BOARD_GCLK0_PRESCALER)
/* Configure GCLK generator 1 - Drives the DFLL */