From 39052e0ae7e1f640a4f17ed08a36751a61a84c92 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 24 Aug 2013 11:34:24 -0600 Subject: [PATCH] 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 --- configs/sama5d3x-ek/README.txt | 11 +++-- configs/sama5d3x-ek/include/board.h | 13 ++++-- configs/sama5d3x-ek/src/sam_usb.c | 71 +++++++++++++++++++++++------ 3 files changed, 72 insertions(+), 23 deletions(-) diff --git a/configs/sama5d3x-ek/README.txt b/configs/sama5d3x-ek/README.txt index d7eadc4cd6..e89d1d9ee1 100644 --- a/configs/sama5d3x-ek/README.txt +++ b/configs/sama5d3x-ek/README.txt @@ -1166,14 +1166,14 @@ Configurations volume when it is removed. But those callbacks are not used in 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: System Type -> ATSAMA5 Peripheral Support CONFIG_SAMA5_UHPHS=y : USB Host High Speed 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 Device Drivers CONFIG_USBHOST=y : Enable USB host support @@ -1194,14 +1194,17 @@ Configurations 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 - 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 CONFIG_SAMA5_UHPHS=y : USB Host High Speed System Type -> USB High Speed Host driver options 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 CONFIG_USBHOST=y : Enable USB host support diff --git a/configs/sama5d3x-ek/include/board.h b/configs/sama5d3x-ek/include/board.h index 321a237e57..29e56028e9 100644 --- a/configs/sama5d3x-ek/include/board.h +++ b/configs/sama5d3x-ek/include/board.h @@ -51,17 +51,20 @@ * 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 - * 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 #else -/* This is an alternative slower configuration that will produce a 48MHz USB clock - * with the required accuracy. When used with OHCI, an additional requirement is - * the PLLACK be a multiple of 48MHz. This setup results in a CPU clock of 384MHz. +/* OHCI Only. This is an alternative slower configuration that will produce a 48MHz + * USB clock with the required accuracy using only PLLA. When PPLA is used to clock + * OHCI, an additional requirement is the PLLACK be a multiple of 48MHz. This setup + * results in a CPU clock of 384MHz. */ # include diff --git a/configs/sama5d3x-ek/src/sam_usb.c b/configs/sama5d3x-ek/src/sam_usb.c index d6b41c2b0c..b8cc73d21e 100644 --- a/configs/sama5d3x-ek/src/sam_usb.c +++ b/configs/sama5d3x-ek/src/sam_usb.c @@ -71,6 +71,10 @@ # define CONFIG_USBHOST_STACKSIZE 1024 #endif +#ifdef HAVE_USBDEV +# undef CONFIG_SAMA5_UHPHS_RHPORT1 +#endif + /************************************************************************************ * Private Data ************************************************************************************/ @@ -102,12 +106,17 @@ static xcpt_t g_ochandler; ************************************************************************************/ #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) +#endif { bool connected[SAM_OHCI_NRHPORT] = {false, false, false}; int rhpndx; + int ret; - uvdbg("Running\n"); + uvdbg("%s Waiter Running\n", hcistr); for (;;) { /* Wait for the device to change state */ @@ -117,8 +126,8 @@ static int usbhost_waiter(struct usbhost_connection_s *dev) connected[rhpndx] = !connected[rhpndx]; - uvdbg("RHport%d %s\n", - rhpndx + 1, connected[rhpndx] ? "connected" : "disconnected"); + uvdbg("%s RHport%d %s\n", + hcistr, rhpndx + 1, connected[rhpndx] ? "connected" : "disconnected"); /* Did we just become connected? */ @@ -126,7 +135,12 @@ static int usbhost_waiter(struct usbhost_connection_s *dev) { /* 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 static int ohci_waiter(int argc, char *argv[]) { +#ifdef CONFIG_DEBUG_USB + return usbhost_waiter(g_ohciconn, "OHCI"); +#else return usbhost_waiter(g_ohciconn); +#endif } #endif @@ -162,7 +180,11 @@ static int ohci_waiter(int argc, char *argv[]) #ifdef CONFIG_SAMA5_EHCI static int ehci_waiter(int argc, char *argv[]) { +#ifdef CONFIG_DEBUG_USB + return usbhost_waiter(g_ehciconn, "EHCI"); +#else return usbhost_waiter(g_ehciconn); +#endif } #endif @@ -244,23 +266,30 @@ void weak_function sam_usbinitialize(void) #endif #ifdef HAVE_USBHOST -#ifndef HAVE_USBDEV - /* Configure Port A to support the USB OHCI/EHCI function only if USB - * device is not also supported. - */ +#ifdef CONFIG_SAMA5_UHPHS_RHPORT1 + /* Configure Port A to support the USB OHCI/EHCI function */ sam_configpio(PIO_USBA_VBUS_ENABLE); /* VBUS enable, initially OFF */ #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_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 */ sam_configpio(PIO_USBBC_VBUS_OVERCURRENT); /* VBUS overcurrent */ #endif +#endif /* HAVE_USBHOST */ } /*********************************************************************************** @@ -364,7 +393,7 @@ void sam_usbhost_vbusdrive(int rhport, bool enable) switch (rhport) { case SAM_RHPORT1: -#ifdef HAVE_USBDEV +#ifdef CONFIG_SAMA5_UHPHS_RHPORT1 udbg("ERROR: RHPort1 is not available in this configuration\n"); return; #else @@ -373,12 +402,22 @@ void sam_usbhost_vbusdrive(int rhport, bool enable) #endif 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; break; +#endif 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; break; +#endif default: udbg("ERROR: RHPort%d is not supported\n", rhport+1); @@ -407,7 +446,7 @@ void sam_usbhost_vbusdrive(int rhport, bool enable) * * Description: * 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 * 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 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; 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 oldhandler; + #else return NULL; + #endif } -#endif +#endif /* CONFIG_SAMA5_PIOD_IRQ ... */ /************************************************************************************ * Name: sam_usbsuspend