SAML32: Update some DFLL logic

This commit is contained in:
Gregory Nutt 2015-05-20 12:26:49 -06:00
parent 7000cf8193
commit 8075f8ab84

View File

@ -107,12 +107,18 @@ static inline void sam_xosc32k_config(void);
static inline void sam_osc32k_config(void); static inline void sam_osc32k_config(void);
#endif #endif
static inline void sam_osc16m_config(void); 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_config(void);
static inline void sam_dfll48m_enable(void);
#endif #endif
#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL_ENABLE) && \ #if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL48M_ENABLE) && \
!defined(BOARD_DFLL_OPENLOOP) !defined(BOARD_DFLL48M_OPENLOOP)
static inline void sam_dfll_reference(void); 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 #endif
static void sam_gclck_waitsyncbusy(void); static void sam_gclck_waitsyncbusy(void);
static void sam_gclk_config(FAR const struct sam_gclkconfig_s *config); 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 * Name: sam_dfll48m_config
* *
* Description: * 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: * Depends on:
* *
* BOARD_DFLL_OPENLOOP - Boolean (defined / not defined) * BOARD_DFLL48M_CLOSEDLOOP - Boolean (defined / not defined)
* BOARD_DFLL_TRACKAFTERFINELOCK - Boolean (defined / not defined) * BOARD_DFLL48M_OPENLOOP - Boolean (defined / not defined)
* BOARD_DFLL_KEEPLOCKONWAKEUP - Boolean (defined / not defined) * BOARD_DFLL48M_RECOVERY - Boolean (defined / not defined)
* BOARD_DFLL_ENABLECHILLCYCLE - Boolean (defined / not defined) * BOARD_DFLL48M_TRACKAFTERFINELOCK - Boolean (defined / not defined)
* BOARD_DFLL_QUICKLOCK - Boolean (defined / not defined) * BOARD_DFLL48M_KEEPLOCKONWAKEUP - Boolean (defined / not defined)
* BOARD_DFLL_ONDEMAND - Boolean (defined / not defined) * BOARD_DFLL48M_ENABLECHILLCYCLE - Boolean (defined / not defined)
* BOARD_DFLL_COARSEVALUE - Value * BOARD_DFLL48M_QUICKLOCK - Boolean (defined / not defined)
* BOARD_DFLL_FINEVALUE - Value * 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: * Open Loop mode only:
* BOARD_DFLL_COARSEVALUE - Value * BOARD_DFLL48M_COARSEVALUE - Value
* BOARD_DFLL_FINEVALUE - Value * BOARD_DFLL48M_FINEVALUE - Value
* *
* Closed loop mode only: * Closed loop mode only:
* BOARD_DFLL_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions * BOARD_DFLL48M_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
* BOARD_DFLL_MULTIPLIER - Value * BOARD_DFLL48M_MULTIPLIER - Value
* BOARD_DFLL_MAXCOARSESTEP - Value * BOARD_DFLL48M_MAXCOARSESTEP - Value
* BOARD_DFLL_MAXFINESTEP - Value * BOARD_DFLL48M_MAXFINESTEP - Value
* *
* Input Parameters: * Input Parameters:
* None * 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) static inline void sam_dfll48m_config(void)
{ {
uint16_t control; uint16_t control;
uint32_t regval; 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 */ /* 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 */ control |= OSCCTRL_DFLLCTRL_MODE; /* Closed loop mode */
#if defined(BOARD_DFLL48M_RECOVERY
control |= OSCCTRL_DFLLCTRL_USBCRM; /* USB clock recovery mode */
#endif #endif
#ifndef BOARD_DFLL_TRACKAFTERFINELOCK #ifndef BOARD_DFLL48M_TRACKAFTERFINELOCK
control |= OSCCTRL_DFLLCTRL_STABLE; /* FINE calibration fixed after a fine lock */ control |= OSCCTRL_DFLLCTRL_STABLE; /* FINE calibration fixed after a fine lock */
#endif #endif
#ifndef BOARD_DFLL_KEEPLOCKONWAKEUP #ifndef BOARD_DFLL48M_KEEPLOCKONWAKEUP
control |= OSCCTRL_DFLLCTRL_LLAW; /* Lose lock after wake */ control |= OSCCTRL_DFLLCTRL_LLAW; /* Lose lock after wake */
#endif #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 */ control |= OSCCTRL_DFLLCTRL_CCDIS; /* Chill cycle disable */
#endif #endif
#ifndef BOARD_DFLL_QUICKLOCK #ifndef BOARD_DFLL48M_QUICKLOCK
control |= OSCCTRL_DFLLCTRL_QLDIS; /* Quick lock disable */ control |= OSCCTRL_DFLLCTRL_QLDIS; /* Quick lock disable */
#endif #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). */ /* Then enable the DFLL (with ONDEMAND set to zero). */
putreg16(control, SAM_OSCCTRL_DFLLCTRL); putreg16(control, SAM_OSCCTRL_DFLLCTRL);
@ -821,10 +860,10 @@ static inline void sam_dfll48m_config(void)
/* Set up the open loop mode multiplier register */ /* Set up the open loop mode multiplier register */
#ifndef BOARD_DFLL_OPENLOOP #ifndef BOARD_DFLL48M_OPENLOOP
regval = OSCCTRL_DFLLMUL_CSTEP(BOARD_DFLL_MAXCOARSESTEP) | regval = OSCCTRL_DFLLMUL_CSTEP(BOARD_DFLL48M_MAXCOARSESTEP) |
OSCCTRL_DFLLMUL_FSTEP(BOARD_DFLL_MAXFINESTEP) | OSCCTRL_DFLLMUL_FSTEP(BOARD_DFLL48M_MAXFINESTEP) |
OSCCTRL_DFLLMUL_MUL(BOARD_DFLL_MULTIPLIER); OSCCTRL_DFLLMUL_MUL(BOARD_DFLL48M_MULTIPLIER);
putreg32(regval, SAM_OSCCTRL_DFLLMUL); putreg32(regval, SAM_OSCCTRL_DFLLMUL);
#else #else
putreg32(0, SAM_OSCCTRL_DFLLMUL); putreg32(0, SAM_OSCCTRL_DFLLMUL);
@ -832,29 +871,19 @@ static inline void sam_dfll48m_config(void)
/* Set up the DFLL value register */ /* Set up the DFLL value register */
regval = OSCCTRL_DFLLVAL_COARSE(BOARD_DFLL_COARSEVALUE) | regval = OSCCTRL_DFLLVAL_COARSE(BOARD_DFLL48M_COARSEVALUE) |
OSCCTRL_DFLLVAL_FINE(BOARD_DFLL_FINEVALUE); OSCCTRL_DFLLVAL_FINE(BOARD_DFLL48M_FINEVALUE);
putreg32(regval, SAM_OSCCTRL_DFLLVAL); 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 #else
# define sam_dfll48m_config() # define sam_dfll48m_config()
#endif #endif
/**************************************************************************** /****************************************************************************
* Name: sam_dfll_reference * Name: sam_dfll48m_enable
* *
* Description: * Description:
* Enable DFLL reference clock if in closed loop mode. * Enable the DFLL48M.
* Depends on:
*
* BOARD_DFLL_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
* *
* Input Parameters: * Input Parameters:
* None * None
@ -864,9 +893,53 @@ static inline void sam_dfll48m_config(void)
* *
****************************************************************************/ ****************************************************************************/
#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL_ENABLE) && \ #ifdef BOARD_DFLL48M_ENABLE
!defined(BOARD_DFLL_OPENLOOP) static inline void sam_dfll48m_enable(void)
static inline void sam_dfll_reference(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; 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 * 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); putreg16(regval, SAM_GCLK_CLKCTRL);
/* Enable the DFLL reference clock */ /* 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); while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) == 0);
} }
#else #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 #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 */ /* 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 /* Configure the GCLK_MAIN last as it may depend on the DFLL or other
* generators * generators
@ -1231,6 +1399,14 @@ void sam_clockconfig(void)
sam_config_gclks(); sam_config_gclks();
/* Enable DFLL48M */
sam_dfll48m_enable();
/* Enable FDPLL96M */
sam_fdpll96m_enable();
/* Set CPU and BUS clock dividers */ /* Set CPU and BUS clock dividers */
sam_dividers(); sam_dividers();