Skip to content

Commit

Permalink
USB: musb_host, fix ep0 fifo flushing
Browse files Browse the repository at this point in the history
The MUSB host side can't share generic TX FIFO flush logic
with EP0; the EP0 TX status register bits are different
from those for other entpoints.

Resolve this issue by providing a new EP0-specific routine
to flush and reset the FIFO, which pays careful attention to
restrictions listed in the latest programmer's guide.  This
gets rid of an open issue whereby the usbtest control write
test (#14) failed.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
David Brownell authored and Greg Kroah-Hartman committed Apr 17, 2009
1 parent e4813ee commit 78322c1
Showing 1 changed file with 29 additions and 14 deletions.
43 changes: 29 additions & 14 deletions drivers/usb/musb/musb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,29 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
}
}

static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep)
{
void __iomem *epio = ep->regs;
u16 csr;
int retries = 5;

/* scrub any data left in the fifo */
do {
csr = musb_readw(epio, MUSB_TXCSR);
if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY)))
break;
musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO);
csr = musb_readw(epio, MUSB_TXCSR);
udelay(10);
} while (--retries);

WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n",
ep->epnum, csr);

/* and reset for the next transfer */
musb_writew(epio, MUSB_TXCSR, 0);
}

/*
* Start transmit. Caller is responsible for locking shared resources.
* musb must be locked.
Expand Down Expand Up @@ -694,10 +717,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
csr = musb_readw(epio, MUSB_TXCSR);
} else {
/* endpoint 0: just flush */
musb_writew(epio, MUSB_CSR0,
csr | MUSB_CSR0_FLUSHFIFO);
musb_writew(epio, MUSB_CSR0,
csr | MUSB_CSR0_FLUSHFIFO);
musb_h_ep0_flush_fifo(hw_ep);
}

/* target addr and (for multipoint) hub addr/port */
Expand Down Expand Up @@ -1063,11 +1083,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
musb_writew(epio, MUSB_CSR0, csr);
} else {
csr |= MUSB_CSR0_FLUSHFIFO;
musb_writew(epio, MUSB_CSR0, csr);
musb_writew(epio, MUSB_CSR0, csr);
csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
musb_writew(epio, MUSB_CSR0, csr);
musb_h_ep0_flush_fifo(hw_ep);
}

musb_writeb(epio, MUSB_NAKLIMIT0, 0);
Expand All @@ -1081,10 +1097,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
* SHOULD NEVER HAPPEN! */
ERR("no URB for end 0\n");

musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
musb_writew(epio, MUSB_CSR0, 0);

musb_h_ep0_flush_fifo(hw_ep);
goto done;
}

Expand Down Expand Up @@ -2043,7 +2056,7 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
* endpoint's irq status here to avoid bogus irqs.
* clearing that status is platform-specific...
*/
} else {
} else if (ep->epnum) {
musb_h_tx_flush_fifo(ep);
csr = musb_readw(epio, MUSB_TXCSR);
csr &= ~(MUSB_TXCSR_AUTOSET
Expand All @@ -2057,6 +2070,8 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
musb_writew(epio, MUSB_TXCSR, csr);
/* flush cpu writebuffer */
csr = musb_readw(epio, MUSB_TXCSR);
} else {
musb_h_ep0_flush_fifo(ep);
}
if (status == 0)
musb_advance_schedule(ep->musb, urb, ep, is_in);
Expand Down

0 comments on commit 78322c1

Please sign in to comment.