SAMA5: EHCI now handles low- and full-speed connections by giving them to OHCI; OHCI now uses the work queue to defer interrupt processing; If both OHCI and EHCI are enabled, EHCI is the master of the UHPHS interrupt

This commit is contained in:
Gregory Nutt
2013-08-24 11:34:24 -06:00
parent cd21e6886e
commit 39052e0ae7
3 changed files with 72 additions and 23 deletions
+7 -4
View File
@@ -1166,14 +1166,14 @@ Configurations
volume when it is removed. But those callbacks are not used in volume when it is removed. But those callbacks are not used in
this configuration. this configuration.
10) Support the USB full-speed OHCI host driver can be enabled by changing 10) Support the USB low/full-speed OHCI host driver can be enabled by changing
the NuttX configuration file as follows: the NuttX configuration file as follows:
System Type -> ATSAMA5 Peripheral Support System Type -> ATSAMA5 Peripheral Support
CONFIG_SAMA5_UHPHS=y : USB Host High Speed CONFIG_SAMA5_UHPHS=y : USB Host High Speed
System Type -> USB High Speed Host driver options System Type -> USB High Speed Host driver options
CONFIG_SAMA5_OHCI=y : Full-speed OHCI support CONFIG_SAMA5_OHCI=y : Low/full-speed OHCI support
: Defaults for values probably OK : Defaults for values probably OK
Device Drivers Device Drivers
CONFIG_USBHOST=y : Enable USB host support CONFIG_USBHOST=y : Enable USB host support
@@ -1194,14 +1194,17 @@ Configurations
values that are used will be off slightly because of this. values that are used will be off slightly because of this.
10) Support the USB high-speed EHCI host driver can be enabled by changing 10) Support the USB high-speed EHCI host driver can be enabled by changing
the NuttX configuration file as follows: the NuttX configuration file as follows. If EHCI is enabled by itself,
then only high-speed devices can be supported. If OHCI is also enabled,
then all low-, full-, and high speed devices should work.
System Type -> ATSAMA5 Peripheral Support System Type -> ATSAMA5 Peripheral Support
CONFIG_SAMA5_UHPHS=y : USB Host High Speed CONFIG_SAMA5_UHPHS=y : USB Host High Speed
System Type -> USB High Speed Host driver options System Type -> USB High Speed Host driver options
CONFIG_SAMA5_EHCI=y : High-speed EHCI support CONFIG_SAMA5_EHCI=y : High-speed EHCI support
: Defaults for values probably OK CONFIG_SAMA5_OHCI=y : Low/full-speed OHCI support
: Defaults for values probably OK for both
Device Drivers Device Drivers
CONFIG_USBHOST=y : Enable USB host support CONFIG_USBHOST=y : Enable USB host support
+8 -5
View File
@@ -51,17 +51,20 @@
* definitions will configure operational clocking. * definitions will configure operational clocking.
*/ */
#ifndef CONFIG_SAMA5_OHCI #if !defined(CONFIG_SAMA5_OHCI) || defined(CONFIG_SAMA5_EHCI)
/* This is the configuration provided in the Atmel example code. This setup results /* This is the configuration provided in the Atmel example code. This setup results
* in a CPU clock of 396MHz * in a CPU clock of 396MHz.
*
* In this configuration, UPLL is the source of the UHPHS clock (if enabled).
*/ */
# include <arch/board/board_396MHz.h> # include <arch/board/board_396MHz.h>
#else #else
/* This is an alternative slower configuration that will produce a 48MHz USB clock /* OHCI Only. This is an alternative slower configuration that will produce a 48MHz
* with the required accuracy. When used with OHCI, an additional requirement is * USB clock with the required accuracy using only PLLA. When PPLA is used to clock
* the PLLACK be a multiple of 48MHz. This setup results in a CPU clock of 384MHz. * OHCI, an additional requirement is the PLLACK be a multiple of 48MHz. This setup
* results in a CPU clock of 384MHz.
*/ */
# include <arch/board/board_384MHz.h> # include <arch/board/board_384MHz.h>
+57 -14
View File
@@ -71,6 +71,10 @@
# define CONFIG_USBHOST_STACKSIZE 1024 # define CONFIG_USBHOST_STACKSIZE 1024
#endif #endif
#ifdef HAVE_USBDEV
# undef CONFIG_SAMA5_UHPHS_RHPORT1
#endif
/************************************************************************************ /************************************************************************************
* Private Data * Private Data
************************************************************************************/ ************************************************************************************/
@@ -102,12 +106,17 @@ static xcpt_t g_ochandler;
************************************************************************************/ ************************************************************************************/
#if HAVE_USBHOST #if HAVE_USBHOST
#ifdef CONFIG_DEBUG_USB
static int usbhost_waiter(struct usbhost_connection_s *dev, const char *hcistr)
#else
static int usbhost_waiter(struct usbhost_connection_s *dev) static int usbhost_waiter(struct usbhost_connection_s *dev)
#endif
{ {
bool connected[SAM_OHCI_NRHPORT] = {false, false, false}; bool connected[SAM_OHCI_NRHPORT] = {false, false, false};
int rhpndx; int rhpndx;
int ret;
uvdbg("Running\n"); uvdbg("%s Waiter Running\n", hcistr);
for (;;) for (;;)
{ {
/* Wait for the device to change state */ /* Wait for the device to change state */
@@ -117,8 +126,8 @@ static int usbhost_waiter(struct usbhost_connection_s *dev)
connected[rhpndx] = !connected[rhpndx]; connected[rhpndx] = !connected[rhpndx];
uvdbg("RHport%d %s\n", uvdbg("%s RHport%d %s\n",
rhpndx + 1, connected[rhpndx] ? "connected" : "disconnected"); hcistr, rhpndx + 1, connected[rhpndx] ? "connected" : "disconnected");
/* Did we just become connected? */ /* Did we just become connected? */
@@ -126,7 +135,12 @@ static int usbhost_waiter(struct usbhost_connection_s *dev)
{ {
/* Yes.. enumerate the newly connected device */ /* Yes.. enumerate the newly connected device */
(void)CONN_ENUMERATE(dev, rhpndx); ret = CONN_ENUMERATE(dev, rhpndx);
if (ret < 0)
{
uvdbg("%s RHport%d CONN_ENUMERATE failed: %d\n", hcistr, rhpndx+1, ret);
connected[rhpndx] = false;
}
} }
} }
@@ -147,7 +161,11 @@ static int usbhost_waiter(struct usbhost_connection_s *dev)
#ifdef CONFIG_SAMA5_OHCI #ifdef CONFIG_SAMA5_OHCI
static int ohci_waiter(int argc, char *argv[]) static int ohci_waiter(int argc, char *argv[])
{ {
#ifdef CONFIG_DEBUG_USB
return usbhost_waiter(g_ohciconn, "OHCI");
#else
return usbhost_waiter(g_ohciconn); return usbhost_waiter(g_ohciconn);
#endif
} }
#endif #endif
@@ -162,7 +180,11 @@ static int ohci_waiter(int argc, char *argv[])
#ifdef CONFIG_SAMA5_EHCI #ifdef CONFIG_SAMA5_EHCI
static int ehci_waiter(int argc, char *argv[]) static int ehci_waiter(int argc, char *argv[])
{ {
#ifdef CONFIG_DEBUG_USB
return usbhost_waiter(g_ehciconn, "EHCI");
#else
return usbhost_waiter(g_ehciconn); return usbhost_waiter(g_ehciconn);
#endif
} }
#endif #endif
@@ -244,23 +266,30 @@ void weak_function sam_usbinitialize(void)
#endif #endif
#ifdef HAVE_USBHOST #ifdef HAVE_USBHOST
#ifndef HAVE_USBDEV #ifdef CONFIG_SAMA5_UHPHS_RHPORT1
/* Configure Port A to support the USB OHCI/EHCI function only if USB /* Configure Port A to support the USB OHCI/EHCI function */
* device is not also supported.
*/
sam_configpio(PIO_USBA_VBUS_ENABLE); /* VBUS enable, initially OFF */ sam_configpio(PIO_USBA_VBUS_ENABLE); /* VBUS enable, initially OFF */
#endif #endif
/* Configure Ports B and C to support the USB OHCI/EHCI function */ #ifdef CONFIG_SAMA5_UHPHS_RHPORT2
/* Configure Port B to support the USB OHCI/EHCI function */
sam_configpio(PIO_USBB_VBUS_ENABLE); /* VBUS enable, initially OFF */ sam_configpio(PIO_USBB_VBUS_ENABLE); /* VBUS enable, initially OFF */
sam_configpio(PIO_USBC_VBUS_ENABLE); /* VBUS enable, initially OFF */ #endif
#ifdef CONFIG_SAMA5_UHPHS_RHPORT3
/* Configure Port C to support the USB OHCI/EHCI function */
sam_configpio(PIO_USBC_VBUS_ENABLE); /* VBUS enable, initially OFF */
#endif
#if defined(CONFIG_SAMA5_UHPHS_RHPORT2) || defined(CONFIG_SAMA5_UHPHS_RHPORT3)
/* Configure Port B/C VBUS overrcurrent detection */ /* Configure Port B/C VBUS overrcurrent detection */
sam_configpio(PIO_USBBC_VBUS_OVERCURRENT); /* VBUS overcurrent */ sam_configpio(PIO_USBBC_VBUS_OVERCURRENT); /* VBUS overcurrent */
#endif #endif
#endif /* HAVE_USBHOST */
} }
/*********************************************************************************** /***********************************************************************************
@@ -364,7 +393,7 @@ void sam_usbhost_vbusdrive(int rhport, bool enable)
switch (rhport) switch (rhport)
{ {
case SAM_RHPORT1: case SAM_RHPORT1:
#ifdef HAVE_USBDEV #ifdef CONFIG_SAMA5_UHPHS_RHPORT1
udbg("ERROR: RHPort1 is not available in this configuration\n"); udbg("ERROR: RHPort1 is not available in this configuration\n");
return; return;
#else #else
@@ -373,12 +402,22 @@ void sam_usbhost_vbusdrive(int rhport, bool enable)
#endif #endif
case SAM_RHPORT2: case SAM_RHPORT2:
#ifdef CONFIG_SAMA5_UHPHS_RHPORT2
udbg("ERROR: RHPort2 is not available in this configuration\n");
return;
#else
pinset = PIO_USBB_VBUS_ENABLE; pinset = PIO_USBB_VBUS_ENABLE;
break; break;
#endif
case SAM_RHPORT3: case SAM_RHPORT3:
#ifdef CONFIG_SAMA5_UHPHS_RHPORT3
udbg("ERROR: RHPort3 is not available in this configuration\n");
return;
#else
pinset = PIO_USBC_VBUS_ENABLE; pinset = PIO_USBC_VBUS_ENABLE;
break; break;
#endif
default: default:
udbg("ERROR: RHPort%d is not supported\n", rhport+1); udbg("ERROR: RHPort%d is not supported\n", rhport+1);
@@ -407,7 +446,7 @@ void sam_usbhost_vbusdrive(int rhport, bool enable)
* *
* Description: * Description:
* Setup to receive an interrupt-level callback if an overcurrent condition is * Setup to receive an interrupt-level callback if an overcurrent condition is
* detected. * detected on port B or C.
* *
* REVISIT: Since this is a common signal, we will need to come up with some way * REVISIT: Since this is a common signal, we will need to come up with some way
* to inform both EHCI and OHCI drivers when this error occurs. * to inform both EHCI and OHCI drivers when this error occurs.
@@ -423,7 +462,9 @@ void sam_usbhost_vbusdrive(int rhport, bool enable)
#if HAVE_USBHOST #if HAVE_USBHOST
xcpt_t sam_setup_overcurrent(xcpt_t handler) xcpt_t sam_setup_overcurrent(xcpt_t handler)
{ {
#if defined(CONFIG_SAMA5_PIOD_IRQ) #if defined(CONFIG_SAMA5_PIOD_IRQ) && (defined(CONFIG_SAMA5_UHPHS_RHPORT2) || \
defined(CONFIG_SAMA5_UHPHS_RHPORT3))
xcpt_t oldhandler; xcpt_t oldhandler;
irqstate_t flags; irqstate_t flags;
@@ -447,11 +488,13 @@ xcpt_t sam_setup_overcurrent(xcpt_t handler)
/* Return the old button handler (so that it can be restored) */ /* Return the old button handler (so that it can be restored) */
return oldhandler; return oldhandler;
#else #else
return NULL; return NULL;
#endif #endif
} }
#endif #endif /* CONFIG_SAMA5_PIOD_IRQ ... */
/************************************************************************************ /************************************************************************************
* Name: sam_usbsuspend * Name: sam_usbsuspend