SAMV7 USB: USB must be enabled before PMC 480MHz clock is enabled

This commit is contained in:
Gregory Nutt 2015-08-11 15:48:26 -06:00
parent f3d1c19965
commit 2264c1fa64
3 changed files with 82 additions and 25 deletions

View File

@ -224,30 +224,26 @@ static inline void sam_pmcsetup(void)
putreg32(BOARD_CKGR_PLLAR, SAM_PMC_CKGR_PLLAR);
sam_pmcwait(PMC_INT_LOCKA);
#ifdef CONFIG_USBDEV
#ifdef CONFIG_SAMV7_USBDEVHS
/* UTMI configuration: Enable port0, select 12/16 MHz MAINOSC crystal source */
#if 0 /* REVISIT: Does this apply only to OHCI? */
putreg32(UTMI_OHCIICR_RES0, SAM_UTMI_OHCIICR);
#endif
#if BOARD_MAINOSC_FREQUENCY == 12000000
putreg32(UTMI_CKTRIM_FREQ_XTAL12, SAM_UTMI_CKTRIM);
#elif BOARD_MAINOSC_FREQUENCY == 12000000
#elif BOARD_MAINOSC_FREQUENCY == 16000000
putreg32(UTMI_CKTRIM_FREQ_XTAL16, SAM_UTMI_CKTRIM);
#else
# error ERROR: Unrecognized MAINSOSC frequency
#endif
#ifdef CONFIG_SAMV7_USBDEVHS_LOWPOWER
/* Enable UTMI Clocking. The USBHS can work in two modes:
*
* - Normal mode where High speed, Full speed and Low speed are available.
* - Low-power mode where only Full speed and Low speed are available.
*
* Only the normal mode is supported by this logic.
* Only the Low-power mode is mode is supported by this logic.
*/
#ifdef CONFIG_SAMV7_USBDEVHS_LOWPOWER
/* UTMI Low-power mode, Full/Low Speed mode
*
* Enable the 48MHz FS Clock.
@ -255,15 +251,6 @@ static inline void sam_pmcsetup(void)
putreg32(PMC_USBCLK, SAM_PMC_SCER);
#else
/* UTMI normal mode, High/Full/Low Speed
*
* Disable the 48MHz USB FS Clock. It is not used in this configuration
*/
putreg32(PMC_USBCLK, SAM_PMC_SCDR);
#endif
/* Select the UTMI PLL as the USB PLL clock input (480MHz) with divider
* to get to 48MHz. UPLL output frequency is determined only by the
* 12/16MHz crystal selection above.
@ -271,7 +258,6 @@ static inline void sam_pmcsetup(void)
regval = PMC_USB_USBS_UPLL;
#ifdef CONFIG_SAMV7_USBDEVHS_LOWPOWER
if ((getreg32(SAM_PMC_MCKR) & PMC_MCKR_PLLADIV2) != 0)
{
/* Divider = 480 Mhz / 2 / 48 Mhz = 5 */
@ -284,7 +270,6 @@ static inline void sam_pmcsetup(void)
regval |= PMC_USB_USBDIV(9);
}
#endif
putreg32(regval, SAM_PMC_USB);
@ -296,7 +281,9 @@ static inline void sam_pmcsetup(void)
/* Wait for LOCKU */
sam_pmcwait(PMC_INT_LOCKU);
#endif
#endif /* CONFIG_SAMV7_USBDEVHS_LOWPOWER */
#endif /* CONFIG_SAMV7_USBDEVHS */
/* Switch to the fast clock and wait for MCKRDY */
@ -405,3 +392,50 @@ void sam_clockconfig(void)
sam_enabledefaultmaster();
}
/****************************************************************************
* Name: sam_usbclock
*
* Description:
* Enable USBHS clocking.
*
****************************************************************************/
#if defined(CONFIG_SAMV7_USBDEVHS) && !defined(CONFIG_SAMV7_USBDEVHS_LOWPOWER)
void sam_usbclock(void)
{
uint32_t regval;
/* Enable UTMI Clocking. The USBHS can work in two modes:
*
* - Normal mode where High speed, Full speed and Low speed are available.
* - Low-power mode where only Full speed and Low speed are available.
*
* Only the normal mode is supported by this logic.
*/
/* UTMI normal mode, High/Full/Low Speed
*
* Disable the 48MHz USB FS Clock. It is not used in this configuration
*/
putreg32(PMC_USBCLK, SAM_PMC_SCDR);
/* Select the UTMI PLL as the USB PLL clock input (480MHz) with a divider
* of 1. UPLL output frequency is determined only by the 12/16MHz crystal
* selection set in sam_clockconfig().
*/
putreg32(PMC_USB_USBS_UPLL, SAM_PMC_USB);
/* Enable the UTMI PLL with the maximum start-up time */
regval = PMC_CKGR_UCKR_UPLLEN | PMC_CKGR_UCKR_UPLLCOUNT_MAX;
putreg32(regval, SAM_PMC_CKGR_UCKR);
/* Wait for LOCKU */
sam_pmcwait(PMC_INT_LOCKU);
}
#endif /* CONFIG_SAMV7_USBDEVHS && !CONFIG_SAMV7_USBDEVHS_LOWPOWER */

View File

@ -85,6 +85,20 @@ extern "C"
void sam_clockconfig(void);
/****************************************************************************
* Name: sam_usbclock
*
* Description:
* Enable USBHS clocking.
*
****************************************************************************/
#if defined(CONFIG_SAMV7_USBDEVHS) && !defined(CONFIG_SAMV7_USBDEVHS_LOWPOWER)
void sam_usbclock(void);
#else
# define sam_usbclock()
#endif
#undef EXTERN
#if defined(__cplusplus)
}

View File

@ -74,6 +74,7 @@
#include "sam_periphclks.h"
#include "chip/sam_usbhs.h"
#include "sam_clockconfig.h"
#include "sam_usbdev.h"
#if defined(CONFIG_USBDEV) && defined(CONFIG_SAMV7_USBDEVHS)
@ -2832,14 +2833,14 @@ static int sam_usbhs_interrupt(int irq, void *context)
sam_putreg(USBHS_DEVINT_SUSPD | USBHS_DEVINT_WAKEUP, SAM_USBHS_DEVICR);
/* Inform board logic that USB is suspended */
sam_suspend(priv);
/* Re-freeze the clock */
regval |= USBHS_CTRL_FRZCLK;
sam_putreg(regval, SAM_USBHS_CTRL);
/* Inform board logic that USB is suspended */
sam_suspend(priv);
}
/* SOF interrupt */
@ -4325,6 +4326,10 @@ static void sam_hw_setup(struct sam_usbdev_s *priv)
regval &= ~USBHS_CTRL_USBE;
sam_putreg(regval, SAM_USBHS_CTRL);
/* Configure USBHS pins. Nothing needs to be done: HDM and HDP are the
* primary pin functions and there are not alternatives.
*/
/* Enable clocking to the USBHS peripheral.
*
* The clock for the USBHS bus interface is generated by the Power
@ -4346,7 +4351,7 @@ static void sam_hw_setup(struct sam_usbdev_s *priv)
* 3. Enable the UPLL 480 MHz.
* 4. Wait for the UPLL 480 MHz to be considered as locked by the PMC.
*
* Steps 1,3, and 4 were performed in sam_clockconfig.c.
* Steps 3 and 4 are performed in sam_usbclock.c.
*/
/* Enable the USBHS peripheral clock (PMC_PCER) */
@ -4366,6 +4371,10 @@ static void sam_hw_setup(struct sam_usbdev_s *priv)
regval &= ~USBHS_CTRL_FRZCLK;
sam_putreg(regval, SAM_USBHS_CTRL);
/* Enable the UPLL */
sam_usbclock();
/* Select High Speed or force Full Speed */
regval = sam_getreg(SAM_USBHS_DEVCTRL);