SAMA5: Add support for sharing ports when both OHCI and EHCI are enabled

This commit is contained in:
Gregory Nutt 2013-08-23 10:58:30 -06:00
parent 3d59f1f61c
commit cd21e6886e
2 changed files with 74 additions and 46 deletions

View File

@ -83,6 +83,12 @@ static struct usbhost_connection_s *g_ohciconn;
static struct usbhost_connection_s *g_ehciconn;
#endif
/* Overcurrent interrupt handler */
#if defined(HAVE_USBHOST) && defined(CONFIG_SAMA5_PIOD_IRQ)
static xcpt_t g_ochandler;
#endif
/************************************************************************************
* Private Functions
************************************************************************************/
@ -229,7 +235,7 @@ static int ehci_waiter(int argc, char *argv[])
void weak_function sam_usbinitialize(void)
{
#if 0
#ifdef HAVE_USBDEV
/* Configure Port A to support the USB device function */
sam_configpio(PIO_USBA_VBUS_SENSE); /* VBUS sense */
@ -237,21 +243,20 @@ void weak_function sam_usbinitialize(void)
/* TODO: Configure an interrupt on VBUS sense */
#endif
#ifdef CONFIG_SAMA5_OHCI
/* Configure Port C to support the USB OHCI function */
sam_configpio(PIO_USBC_VBUS_ENABLE); /* VBUS enable, initially OFF */
#ifdef HAVE_USBHOST
#ifndef HAVE_USBDEV
/* Configure Port A to support the USB OHCI/EHCI function only if USB
* device is not also supported.
*/
sam_configpio(PIO_USBA_VBUS_ENABLE); /* VBUS enable, initially OFF */
#endif
#ifdef CONFIG_SAMA5_EHCI
/* Configure Port B to support the USB OHCI function */
/* Configure Ports B and C to support the USB OHCI/EHCI function */
sam_configpio(PIO_USBB_VBUS_ENABLE); /* VBUS enable, initially OFF */
sam_configpio(PIO_USBC_VBUS_ENABLE); /* VBUS enable, initially OFF */
#endif
#if defined(CONFIG_SAMA5_OHCI) || defined(CONFIG_SAMA5_EHCI)
/* Configure Port B/C VBUS overrcurrent detection */
sam_configpio(PIO_USBBC_VBUS_OVERCURRENT); /* VBUS overcurrent */
@ -271,7 +276,7 @@ void weak_function sam_usbinitialize(void)
#if HAVE_USBHOST
int sam_usbhost_initialize(void)
{
int pid;
pid_t pid;
int ret;
/* First, register all of the class drivers needed to support the drivers
@ -338,9 +343,8 @@ int sam_usbhost_initialize(void)
* each platform that implements the OHCI or EHCI host interface
*
* Input Parameters:
* iface - Selects USB host interface:
* 0 = EHCI (Port B)
* 1 = OHCI (Port C)
* rhport - Selects root hub port to be powered host interface. See SAM_RHPORT_*
* definitions above.
* enable - true: enable VBUS power; false: disable VBUS power
*
* Returned Value:
@ -349,34 +353,37 @@ int sam_usbhost_initialize(void)
***********************************************************************************/
#if HAVE_USBHOST
void sam_usbhost_vbusdrive(int iface, bool enable)
void sam_usbhost_vbusdrive(int rhport, bool enable)
{
pio_pinset_t pinset;
pio_pinset_t pinset = 0;
/* Pick the PIO associated with the OHCI or EHCI interface */
uvdbg("RHPort%d: enable=%d\n", rhport+1, enable);
#ifdef CONFIG_SAMA5_OHCI
if (iface == SAM_OHCI_IFACE)
/* Pick the PIO configuration associated with the selected root hub port */
switch (rhport)
{
uvdbg("OHCI: iface %d enable %d\n", iface, enable);
pinset = PIO_USBC_VBUS_ENABLE;
}
else
case SAM_RHPORT1:
#ifdef HAVE_USBDEV
udbg("ERROR: RHPort1 is not available in this configuration\n");
return;
#else
pinset = PIO_USBA_VBUS_ENABLE;
break;
#endif
#ifdef CONFIG_SAMA5_EHCI
if (iface == SAM_EHCI_IFACE)
{
uvdbg("EHCI: iface %d enable %d\n", iface, enable);
case SAM_RHPORT2:
pinset = PIO_USBB_VBUS_ENABLE;
}
else
#endif
break;
{
udbg("ERROR: Unsupported iface %d\n", iface);
return;
}
case SAM_RHPORT3:
pinset = PIO_USBC_VBUS_ENABLE;
break;
default:
udbg("ERROR: RHPort%d is not supported\n", rhport+1);
return;
}
/* Then enable or disable VBUS power */
@ -384,13 +391,13 @@ void sam_usbhost_vbusdrive(int iface, bool enable)
{
/* Enable the Power Switch by driving the enable pin low */
sam_piowrite(pinset, false);
sam_piowrite(pinset, false);
}
else
{
/* Disable the Power Switch by driving the enable pin high */
sam_piowrite(pinset, false);
sam_piowrite(pinset, true);
}
}
#endif
@ -402,6 +409,9 @@ void sam_usbhost_vbusdrive(int iface, bool enable)
* Setup to receive an interrupt-level callback if an overcurrent condition is
* detected.
*
* 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.
*
* Input paramter:
* handler - New overcurrent interrupt handler
*
@ -413,12 +423,33 @@ void sam_usbhost_vbusdrive(int iface, bool enable)
#if HAVE_USBHOST
xcpt_t sam_setup_overcurrent(xcpt_t handler)
{
/* 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.
#if defined(CONFIG_SAMA5_PIOD_IRQ)
xcpt_t oldhandler;
irqstate_t flags;
/* Disable interrupts until we are done. This guarantees that the
* following operations are atomic.
*/
# warning Missing logic
flags = irqsave();
/* Get the old button interrupt handler and save the new one */
oldhandler = *g_ochandler;
*g_ochandler = handler;
/* Configure the interrupt */
sam_pioirq(IRQ_USBBC_VBUS_OVERCURRENT);
(void)irq_attach(IRQ_USBBC_VBUS_OVERCURRENT, handler);
sam_pioirqenable(IRQ_USBBC_VBUS_OVERCURRENT);
/* Return the old button handler (so that it can be restored) */
return oldhandler;
#else
return NULL;
#endif
}
#endif

View File

@ -58,6 +58,7 @@
#define HAVE_HSMCI_MTD 1
#define HAVE_AT25_MTD 1
#define HAVE_USBHOST 1
#define HAVE_USBDEV 1
/* HSMCI */
/* Can't support MMC/SD if the card interface(s) are not enable */
@ -120,12 +121,13 @@
#endif
#if !defined(CONFIG_SAMA5_UDPHS)
# undef HAVE_USBDEV
#endif
/* CONFIG_USBDEV and CONFIG_USBHOST must also be defined */
#if defined(CONFIG_USBDEV)
#else
#if !defined(CONFIG_USBDEV)
# undef HAVE_USBDEV
#endif
#if defined(CONFIG_USBHOST)
@ -137,11 +139,6 @@
# undef CONFIG_SAMA5_EHCI
#endif
#if defined(CONFIG_SAMA5_OHCI) && defined(CONFIG_SAMA5_EHCI)
# warning Both CONFIG_SAMA5_OHCI and CONFIG_SAMA5_EHCI are defined
# undef CONFIG_SAMA5_EHCI
#endif
#if !defined(CONFIG_SAMA5_OHCI) && !defined(CONFIG_SAMA5_EHCI)
# undef HAVE_USBHOST
#endif