mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
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:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user