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; static struct usbhost_connection_s *g_ehciconn;
#endif #endif
/* Overcurrent interrupt handler */
#if defined(HAVE_USBHOST) && defined(CONFIG_SAMA5_PIOD_IRQ)
static xcpt_t g_ochandler;
#endif
/************************************************************************************ /************************************************************************************
* Private Functions * Private Functions
************************************************************************************/ ************************************************************************************/
@ -229,7 +235,7 @@ static int ehci_waiter(int argc, char *argv[])
void weak_function sam_usbinitialize(void) void weak_function sam_usbinitialize(void)
{ {
#if 0 #ifdef HAVE_USBDEV
/* Configure Port A to support the USB device function */ /* Configure Port A to support the USB device function */
sam_configpio(PIO_USBA_VBUS_SENSE); /* VBUS sense */ 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 */ /* TODO: Configure an interrupt on VBUS sense */
#endif #endif
#ifdef CONFIG_SAMA5_OHCI #ifdef HAVE_USBHOST
/* Configure Port C to support the USB OHCI function */ #ifndef HAVE_USBDEV
/* Configure Port A to support the USB OHCI/EHCI function only if USB
sam_configpio(PIO_USBC_VBUS_ENABLE); /* VBUS enable, initially OFF */ * device is not also supported.
*/
sam_configpio(PIO_USBA_VBUS_ENABLE); /* VBUS enable, initially OFF */
#endif #endif
#ifdef CONFIG_SAMA5_EHCI /* Configure Ports B and C to support the USB OHCI/EHCI function */
/* Configure Port B to support the USB OHCI 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
#if defined(CONFIG_SAMA5_OHCI) || defined(CONFIG_SAMA5_EHCI)
/* 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 */
@ -271,7 +276,7 @@ void weak_function sam_usbinitialize(void)
#if HAVE_USBHOST #if HAVE_USBHOST
int sam_usbhost_initialize(void) int sam_usbhost_initialize(void)
{ {
int pid; pid_t pid;
int ret; int ret;
/* First, register all of the class drivers needed to support the drivers /* 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 * each platform that implements the OHCI or EHCI host interface
* *
* Input Parameters: * Input Parameters:
* iface - Selects USB host interface: * rhport - Selects root hub port to be powered host interface. See SAM_RHPORT_*
* 0 = EHCI (Port B) * definitions above.
* 1 = OHCI (Port C)
* enable - true: enable VBUS power; false: disable VBUS power * enable - true: enable VBUS power; false: disable VBUS power
* *
* Returned Value: * Returned Value:
@ -349,32 +353,35 @@ int sam_usbhost_initialize(void)
***********************************************************************************/ ***********************************************************************************/
#if HAVE_USBHOST #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 /* Pick the PIO configuration associated with the selected root hub port */
if (iface == SAM_OHCI_IFACE)
switch (rhport)
{ {
uvdbg("OHCI: iface %d enable %d\n", iface, enable); case SAM_RHPORT1:
pinset = PIO_USBC_VBUS_ENABLE; #ifdef HAVE_USBDEV
} udbg("ERROR: RHPort1 is not available in this configuration\n");
else return;
#else
pinset = PIO_USBA_VBUS_ENABLE;
break;
#endif #endif
#ifdef CONFIG_SAMA5_EHCI case SAM_RHPORT2:
if (iface == SAM_EHCI_IFACE)
{
uvdbg("EHCI: iface %d enable %d\n", iface, enable);
pinset = PIO_USBB_VBUS_ENABLE; pinset = PIO_USBB_VBUS_ENABLE;
} break;
else
#endif
{ case SAM_RHPORT3:
udbg("ERROR: Unsupported iface %d\n", iface); pinset = PIO_USBC_VBUS_ENABLE;
break;
default:
udbg("ERROR: RHPort%d is not supported\n", rhport+1);
return; return;
} }
@ -390,7 +397,7 @@ void sam_usbhost_vbusdrive(int iface, bool enable)
{ {
/* Disable the Power Switch by driving the enable pin high */ /* Disable the Power Switch by driving the enable pin high */
sam_piowrite(pinset, false); sam_piowrite(pinset, true);
} }
} }
#endif #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 * Setup to receive an interrupt-level callback if an overcurrent condition is
* detected. * 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: * Input paramter:
* handler - New overcurrent interrupt handler * handler - New overcurrent interrupt handler
* *
@ -413,12 +423,33 @@ void sam_usbhost_vbusdrive(int iface, bool enable)
#if HAVE_USBHOST #if HAVE_USBHOST
xcpt_t sam_setup_overcurrent(xcpt_t handler) 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 #if defined(CONFIG_SAMA5_PIOD_IRQ)
* both EHCI and OHCI drivers when this error occurs. 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; return NULL;
#endif
} }
#endif #endif

View File

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