diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/musb/musb_host.c | 43 |
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 | ||
128 | static 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); |