diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2013-11-28 15:13:56 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2013-11-28 15:13:56 -0600 |
commit | 0b798a72734b25b356d3717cd4c49200f340c2a4 (patch) | |
tree | e93c06217951135c8bc0037be6953d34f10ba636 | |
parent | 1bcbded7141d063cc1732aff2ffe8730ad934820 (diff) | |
download | nuttx-0b798a72734b25b356d3717cd4c49200f340c2a4.tar.gz nuttx-0b798a72734b25b356d3717cd4c49200f340c2a4.tar.bz2 nuttx-0b798a72734b25b356d3717cd4c49200f340c2a4.zip |
LPC31 EHCI: Fixes so that high- and low-speed devices work with the EHCI host
-rwxr-xr-x | nuttx/arch/arm/src/lpc31xx/lpc31_ehci.c | 74 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc31xx/lpc31_usbotg.h | 5 |
2 files changed, 63 insertions, 16 deletions
diff --git a/nuttx/arch/arm/src/lpc31xx/lpc31_ehci.c b/nuttx/arch/arm/src/lpc31xx/lpc31_ehci.c index cae15166b..ff0c69715 100755 --- a/nuttx/arch/arm/src/lpc31xx/lpc31_ehci.c +++ b/nuttx/arch/arm/src/lpc31xx/lpc31_ehci.c @@ -3262,12 +3262,16 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) * 00b SE0 Not Low-speed device, perform EHCI reset * 10b J-state Not Low-speed device, perform EHCI reset * 01b K-state Low-speed device, release ownership of port + * + * NOTE: Low-speed devices could be detected by examining the PORTSC PSPD + * field after resetting the device. The more convential way here, however, + * also appears to work. */ regval = lpc31_getreg(&HCOR->portsc[rhpndx]); if ((regval & EHCI_PORTSC_LSTATUS_MASK) == EHCI_PORTSC_LSTATUS_KSTATE) { - /* Paragraph 2.3.9: + /* EHCI Paragraph 2.3.9: * * "Port Owner ... This bit unconditionally goes to a 0b when the * Configured bit in the CONFIGFLAG register makes a 0b to 1b @@ -3281,7 +3285,7 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) * device. A one in this bit means that a companion host * controller owns and controls the port. .... * - * Paragraph 4.2: + * EHCI Paragraph 4.2: * * "When a port is routed to a companion HC, it remains under the * control of the companion HC until the device is disconnected @@ -3296,6 +3300,8 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) */ rhport->ep0.speed = EHCI_LOW_SPEED; + +#if 0 /* The LPC31xx does not support a companion host controller */ regval |= EHCI_PORTSC_OWNER; lpc31_putreg(regval, &HCOR->portsc[rhpndx]); @@ -3303,6 +3309,7 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) rhport->connected = false; return -EPERM; +#endif } else { @@ -3322,7 +3329,7 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) DEBUGASSERT((lpc31_getreg(&HCOR->usbsts) & EHCI_USBSTS_HALTED) == 0); - /* paragraph 2.3.9: + /* EHCI paragraph 2.3.9: * * "When software writes a one to [the Port Reset] bit (from a zero), the * bus reset sequence as defined in the USB Specification Revision 2.0 is @@ -3351,7 +3358,7 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) /* Wait for the port reset to complete * - * Paragraph 2.3.9: + * EHCI Paragraph 2.3.9: * * "Note that when software writes a zero to this bit there may be a * delay before the bit status changes to a zero. The bit status will @@ -3366,7 +3373,7 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) while ((lpc31_getreg(regaddr) & EHCI_PORTSC_RESET) != 0); usleep(200*1000); - /* Paragraph 4.2.2: + /* EHCI Paragraph 4.2.2: * * "... The reset process is actually complete when software reads a zero * in the PortReset bit. The EHCI Driver checks the PortEnable bit in the @@ -3380,20 +3387,38 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) * indicate that a full-speed device is attached. In either case the EHCI * driver sets the PortOwner bit in the PORTSC register to a one to * release port ownership to a companion host controller." + * + * LPC31xx User Manual Paragraph 6.1.3: + * + * "In a standard EHCI controller design, the EHCI host controller driver + * detects a Full speed (FS) or Low speed (LS) device by noting if the + * port enable bit is set after the port reset operation. The port enable + * will only be set in a standard EHCI controller implementation after the + * port reset operation and when the host and device negotiate a High-Speed + * connection (i.e. Chirp completes successfully). Since this controller has + * an embedded Transaction Translator, the port enable will always be set + * after the port reset operation regardless of the result of the host device + * chirp result and the resulting port speed will be indicated by the PSPD + * field in PORTSC1. */ regval = lpc31_getreg(&HCOR->portsc[rhpndx]); + +#if 0 /* LPC31xx detects high- vs full-speed devices using the PSPD field */ if ((regval & EHCI_PORTSC_PE) != 0) +#else + if ((regval & USBDEV_PRTSC1_PSPD_MASK) == USBDEV_PRTSC1_PSPD_HS) +#endif { /* High speed device */ rhport->ep0.speed = EHCI_HIGH_SPEED; } - else + else if ((regval & USBDEV_PRTSC1_PSPD_MASK) == USBDEV_PRTSC1_PSPD_FS) { /* Low- or Full- speed device. Set the port ownership bit. * - * Paragraph 4.2: + * EHCI Paragraph 4.2: * * "When a port is routed to a companion HC, it remains under the * control of the companion HC until the device is disconnected @@ -3407,6 +3432,9 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) * repeat." */ + DEBUGASSERT(rhport->ep0.speed = EHCI_FULL_SPEED); + +#if 0 /* The LPC31xx does not support a companion host controller */ regval |= EHCI_PORTSC_OWNER; lpc31_putreg(regval, &HCOR->portsc[rhpndx]); @@ -3414,6 +3442,15 @@ static int lpc31_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx) rhport->connected = false; return -EPERM; +#endif + } + + /* Otherwise it must be a low speed device */ + + else + { + DEBUGASSERT(rhport->ep0.speed = EHCI_LOW_SPEED); + DEBUGASSERT((regval & USBDEV_PRTSC1_PSPD_MASK) == USBDEV_PRTSC1_PSPD_LS) } /* Let the common usbhost_enumerate do all of the real work. Note that the @@ -4302,16 +4339,25 @@ FAR struct usbhost_connection_s *lpc31_ehci_initialize(int controller) /* Program the controller to be the USB host controller * - * CM = Host mode - * ES = 0, Little endian mode. - * SLOM Not used in host mode. - * SDIS = 1, Stream disable mode. Eliminates overruns/underruns at - * the expense of some performance. - * VBPS = 1, off-chip power source + * Fixed selections: + * + * CM = Host mode + * ES = 0, Little endian mode. + * SLOM Not used in host mode. + * VBPS = 1, off-chip power source + * + * Configurable selections: + * + * SDIS = 1, Stream disable mode. Eliminates overruns/underruns at + * the expense of some performance. */ - putreg32(USBHOST_USBMODE_CMHOST /* | USBHOST_USBMODE_SDIS */ | USBHOST_USBMODE_VBPS, +#ifdef CONFIG_LPC31_EHCI_SDIS + putreg32(USBHOST_USBMODE_CMHOST | USBHOST_USBMODE_SDIS | USBHOST_USBMODE_VBPS, LPC31_USBDEV_USBMODE); +#else + putreg32(USBHOST_USBMODE_CMHOST | USBHOST_USBMODE_VBPS, LPC31_USBDEV_USBMODE); +#endif /* Host Controller Initialization. Paragraph 4.1 */ /* Reset the EHCI hardware */ diff --git a/nuttx/arch/arm/src/lpc31xx/lpc31_usbotg.h b/nuttx/arch/arm/src/lpc31xx/lpc31_usbotg.h index 27bd5e5ab..28a7fe7ee 100644 --- a/nuttx/arch/arm/src/lpc31xx/lpc31_usbotg.h +++ b/nuttx/arch/arm/src/lpc31xx/lpc31_usbotg.h @@ -422,10 +422,11 @@ /* Port Status and Control register PRTSC1 (address 0x19000184) -- Device Mode */ #define USBDEV_PRTSC1_PSPD_SHIFT (26) /* Bits 26-27: Port speed */ -# define USBDEV_PRTSC1_PSPD_MASK (3 << USBDEV_PRTSC1_PSPD_SHIFT) +#define USBDEV_PRTSC1_PSPD_MASK (3 << USBDEV_PRTSC1_PSPD_SHIFT) # define USBDEV_PRTSC1_PSPD_FS (0 << USBDEV_PRTSC1_PSPD_SHIFT) /* Full-speed */ +# define USBDEV_PRTSC1_PSPD_LS (1 << USBDEV_PRTSC1_PSPD_SHIFT) /* Low-speed */ # define USBDEV_PRTSC1_PSPD_HS (2 << USBDEV_PRTSC1_PSPD_SHIFT) /* High-speed */ -# define USBDEV_PRTSC1_PFSC (1 << 24) /* Bit 24: Port force full speed connect */ +#define USBDEV_PRTSC1_PFSC (1 << 24) /* Bit 24: Port force full speed connect */ #define USBDEV_PRTSC1_PHCD (1 << 23) /* Bit 23: PHY low power suspend - clock disable (PLPSCD) */ #define USBDEV_PRTSC1_PTC_SHIFT (16) /* Bits 16-19: 19: Port test control */ #define USBDEV_PRTSC1_PTC_MASK (15 << USBDEV_PRTSC1_PTC_SHIFT) |