Commit f65d1c40 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: net2280 patch

Don't clear ep0 status phase handshake during endpoint reset ... at least
one driver emits so much debug output before resetting endpoints that the
reset happens late enough to make the chip break protocol.

Also handle resets IRQs a bit differently:  they can happen twice during
enumeration, which can worsen the other problem.

From:          Alex Sanks <alex@netchip.com>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent ea945ce1
...@@ -307,7 +307,6 @@ static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep) ...@@ -307,7 +307,6 @@ static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
| (1 << SET_NAK_OUT_PACKETS) | (1 << SET_NAK_OUT_PACKETS)
| (1 << CLEAR_EP_HIDE_STATUS_PHASE) | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
| (1 << CLEAR_INTERRUPT_MODE) | (1 << CLEAR_INTERRUPT_MODE)
| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
| (1 << CLEAR_ENDPOINT_TOGGLE) | (1 << CLEAR_ENDPOINT_TOGGLE)
| (1 << CLEAR_ENDPOINT_HALT) | (1 << CLEAR_ENDPOINT_HALT)
, &ep->regs->ep_rsp); , &ep->regs->ep_rsp);
...@@ -2511,15 +2510,23 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) ...@@ -2511,15 +2510,23 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
static void handle_stat1_irqs (struct net2280 *dev, u32 stat) static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
{ {
struct net2280_ep *ep; struct net2280_ep *ep;
u32 tmp, num, scratch; u32 tmp, num, mask, scratch;
/* after disconnect there's nothing else to do! */ /* after disconnect there's nothing else to do! */
tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT); tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED);
/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
* Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
* both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
* only indicates a change in the reset state).
*/
if (stat & tmp) { if (stat & tmp) {
writel (tmp, &dev->regs->irqstat1); writel (tmp, &dev->regs->irqstat1);
if (((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) != 0 if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) &&
|| (readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0 ((readl (&dev->usb->usbstat) & mask) == 0))
) && dev->gadget.speed != USB_SPEED_UNKNOWN) { || ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0)
) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
DEBUG (dev, "disconnect %s\n", DEBUG (dev, "disconnect %s\n",
dev->driver->driver.name); dev->driver->driver.name);
stop_activity (dev, dev->driver); stop_activity (dev, dev->driver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment