aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-03-26 20:38:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-17 13:50:25 -0400
commit78322c1a64387673f46afb8b5e31edec94e9603d (patch)
tree811809247734b7bac96e7dbea5f82693c3be1078
parente4813eec8d47c8299d968bd5349dc881fa481c26 (diff)
USB: musb_host, fix ep0 fifo flushing
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>
-rw-r--r--drivers/usb/musb/musb_host.c43
1 files changed, 29 insertions, 14 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index ff095956ca96..521fd83f5b9d 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -125,6 +125,29 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
125 } 125 }
126} 126}
127 127
128static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep)
129{
130 void __iomem *epio = ep->regs;
131 u16 csr;
132 int retries = 5;
133
134 /* scrub any data left in the fifo */
135 do {
136 csr = musb_readw(epio, MUSB_TXCSR);
137 if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY)))
138 break;
139 musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO);
140 csr = musb_readw(epio, MUSB_TXCSR);
141 udelay(10);
142 } while (--retries);
143
144 WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n",
145 ep->epnum, csr);
146
147 /* and reset for the next transfer */
148 musb_writew(epio, MUSB_TXCSR, 0);
149}
150
128/* 151/*
129 * Start transmit. Caller is responsible for locking shared resources. 152 * Start transmit. Caller is responsible for locking shared resources.
130 * musb must be locked. 153 * musb must be locked.
@@ -694,10 +717,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
694 csr = musb_readw(epio, MUSB_TXCSR); 717 csr = musb_readw(epio, MUSB_TXCSR);
695 } else { 718 } else {
696 /* endpoint 0: just flush */ 719 /* endpoint 0: just flush */
697 musb_writew(epio, MUSB_CSR0, 720 musb_h_ep0_flush_fifo(hw_ep);
698 csr | MUSB_CSR0_FLUSHFIFO);
699 musb_writew(epio, MUSB_CSR0,
700 csr | MUSB_CSR0_FLUSHFIFO);
701 } 721 }
702 722
703 /* target addr and (for multipoint) hub addr/port */ 723 /* target addr and (for multipoint) hub addr/port */
@@ -1063,11 +1083,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
1063 csr &= ~MUSB_CSR0_H_NAKTIMEOUT; 1083 csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
1064 musb_writew(epio, MUSB_CSR0, csr); 1084 musb_writew(epio, MUSB_CSR0, csr);
1065 } else { 1085 } else {
1066 csr |= MUSB_CSR0_FLUSHFIFO; 1086 musb_h_ep0_flush_fifo(hw_ep);
1067 musb_writew(epio, MUSB_CSR0, csr);
1068 musb_writew(epio, MUSB_CSR0, csr);
1069 csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
1070 musb_writew(epio, MUSB_CSR0, csr);
1071 } 1087 }
1072 1088
1073 musb_writeb(epio, MUSB_NAKLIMIT0, 0); 1089 musb_writeb(epio, MUSB_NAKLIMIT0, 0);
@@ -1081,10 +1097,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
1081 * SHOULD NEVER HAPPEN! */ 1097 * SHOULD NEVER HAPPEN! */
1082 ERR("no URB for end 0\n"); 1098 ERR("no URB for end 0\n");
1083 1099
1084 musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO); 1100 musb_h_ep0_flush_fifo(hw_ep);
1085 musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
1086 musb_writew(epio, MUSB_CSR0, 0);
1087
1088 goto done; 1101 goto done;
1089 } 1102 }
1090 1103
@@ -2043,7 +2056,7 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
2043 * endpoint's irq status here to avoid bogus irqs. 2056 * endpoint's irq status here to avoid bogus irqs.
2044 * clearing that status is platform-specific... 2057 * clearing that status is platform-specific...
2045 */ 2058 */
2046 } else { 2059 } else if (ep->epnum) {
2047 musb_h_tx_flush_fifo(ep); 2060 musb_h_tx_flush_fifo(ep);
2048 csr = musb_readw(epio, MUSB_TXCSR); 2061 csr = musb_readw(epio, MUSB_TXCSR);
2049 csr &= ~(MUSB_TXCSR_AUTOSET 2062 csr &= ~(MUSB_TXCSR_AUTOSET
@@ -2057,6 +2070,8 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
2057 musb_writew(epio, MUSB_TXCSR, csr); 2070 musb_writew(epio, MUSB_TXCSR, csr);
2058 /* flush cpu writebuffer */ 2071 /* flush cpu writebuffer */
2059 csr = musb_readw(epio, MUSB_TXCSR); 2072 csr = musb_readw(epio, MUSB_TXCSR);
2073 } else {
2074 musb_h_ep0_flush_fifo(ep);
2060 } 2075 }
2061 if (status == 0) 2076 if (status == 0)
2062 musb_advance_schedule(ep->musb, urb, ep, is_in); 2077 musb_advance_schedule(ep->musb, urb, ep, is_in);