1 From c99f4a68268801a2e2ffbef9766c3ac89e4fb22c Mon Sep 17 00:00:00 2001
2 From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
3 Date: Thu, 26 Mar 2009 18:27:47 -0700
4 Subject: [PATCH] musb: sanitize clearing TXCSR DMA bits (take 2)
6 The MUSB code clears TXCSR_DMAMODE incorrectly in several
7 places, either asserting that TXCSR_DMAENAB is clear (when
8 sometimes it isn't) or clearing both bits together. Recent
9 versions of the programmer's guide require DMAENAB to be
10 cleared first, although some older ones didn't.
12 Fix this and while at it:
14 - In musb_gadget::txstate(), stop clearing the AUTOSET
15 and DMAMODE bits for the CPPI case since they never
16 get set anyway (the former bit is reserved on DaVinci);
17 but do clear the DMAENAB bit on the DMA error path.
19 - In musb_host::musb_ep_program(), remove the duplicate
20 DMA controller specific code code clearing the TXCSR
21 previous state, add the code to clear TXCSR DMA bits
22 on the Inventra DMA error path, to replace such code
23 (executed late) on the PIO path.
25 - In musbhsdma::dma_channel_abort()/dma_controller_irq(),
26 add/use the 'offset' variable to avoid MUSB_EP_OFFSET()
27 invocations on every RXCSR/TXCSR access.
29 [dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: don't introduce CamelCase,
32 Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
33 Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
35 drivers/usb/musb/musb_gadget.c | 33 +++++++++++------
36 drivers/usb/musb/musb_host.c | 79 ++++++++++++++++------------------------
37 drivers/usb/musb/musbhsdma.c | 59 ++++++++++++++++++------------
38 3 files changed, 90 insertions(+), 81 deletions(-)
40 diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
41 index c7ebd08..f79440c 100644
42 --- a/drivers/usb/musb/musb_gadget.c
43 +++ b/drivers/usb/musb/musb_gadget.c
44 @@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status)
45 if (is_dma_capable() && ep->dma) {
46 struct dma_controller *c = ep->musb->dma_controller;
51 + * The programming guide says that we must not clear
52 + * the DMAMODE bit before DMAENAB, so we only
53 + * clear it in the second write...
55 musb_writew(epio, MUSB_TXCSR,
56 - 0 | MUSB_TXCSR_FLUSHFIFO);
57 + MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO);
58 musb_writew(epio, MUSB_TXCSR,
59 0 | MUSB_TXCSR_FLUSHFIFO);
61 @@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
62 | IN token(s) are recd from Host.
63 | -> DMA interrupt on completion
65 - | -> stop DMA, ~DmaEenab,
66 + | -> stop DMA, ~DMAENAB,
67 | -> set TxPktRdy for last short pkt or zlp
69 | -> Continue next request (call txstate)
70 @@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req)
71 request->dma, request_size);
73 if (musb_ep->dma->desired_mode == 0) {
74 - /* ASSERT: DMAENAB is clear */
75 - csr &= ~(MUSB_TXCSR_AUTOSET |
76 - MUSB_TXCSR_DMAMODE);
78 + * We must not clear the DMAMODE bit
79 + * before the DMAENAB bit -- and the
80 + * latter doesn't always get cleared
81 + * before we get here...
83 + csr &= ~(MUSB_TXCSR_AUTOSET
84 + | MUSB_TXCSR_DMAENAB);
85 + musb_writew(epio, MUSB_TXCSR, csr
86 + | MUSB_TXCSR_P_WZC_BITS);
87 + csr &= ~MUSB_TXCSR_DMAMODE;
88 csr |= (MUSB_TXCSR_DMAENAB |
90 /* against programming guide */
91 @@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
93 #elif defined(CONFIG_USB_TI_CPPI_DMA)
94 /* program endpoint CSR first, then setup DMA */
95 - csr &= ~(MUSB_TXCSR_AUTOSET
96 - | MUSB_TXCSR_DMAMODE
97 - | MUSB_TXCSR_P_UNDERRUN
98 - | MUSB_TXCSR_TXPKTRDY);
99 + csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
100 csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB;
101 musb_writew(epio, MUSB_TXCSR,
102 (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
103 @@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
105 c->channel_release(musb_ep->dma);
107 - /* ASSERT: DMAENAB clear */
108 - csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
109 + csr &= ~MUSB_TXCSR_DMAENAB;
110 + musb_writew(epio, MUSB_TXCSR, csr);
111 /* invariant: prequest->buf is non-null */
113 #elif defined(CONFIG_USB_TUSB_OMAP_DMA)
114 diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
115 index a5d75aa..6591282 100644
116 --- a/drivers/usb/musb/musb_host.c
117 +++ b/drivers/usb/musb/musb_host.c
118 @@ -590,10 +590,17 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
119 csr = musb_readw(ep->regs, MUSB_TXCSR);
120 if (csr & MUSB_TXCSR_MODE) {
121 musb_h_tx_flush_fifo(ep);
122 + csr = musb_readw(ep->regs, MUSB_TXCSR);
123 musb_writew(ep->regs, MUSB_TXCSR,
124 - MUSB_TXCSR_FRCDATATOG);
125 + csr | MUSB_TXCSR_FRCDATATOG);
127 - /* clear mode (and everything else) to enable Rx */
130 + * Clear the MODE bit (and everything else) to enable Rx.
131 + * NOTE: we mustn't clear the DMAMODE bit before DMAENAB.
133 + if (csr & MUSB_TXCSR_DMAMODE)
134 + musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
135 musb_writew(ep->regs, MUSB_TXCSR, 0);
137 /* scrub all previous state, clearing toggle */
138 @@ -690,12 +697,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
140 /* general endpoint setup */
142 - /* ASSERT: TXCSR_DMAENAB was already cleared */
144 /* flush all old state, set default */
145 musb_h_tx_flush_fifo(hw_ep);
148 + * We must not clear the DMAMODE bit before or in
149 + * the same cycle with the DMAENAB bit, so we clear
150 + * the latter first...
152 csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT
153 - | MUSB_TXCSR_DMAMODE
154 + | MUSB_TXCSR_AUTOSET
155 + | MUSB_TXCSR_DMAENAB
156 | MUSB_TXCSR_FRCDATATOG
157 | MUSB_TXCSR_H_RXSTALL
159 @@ -703,16 +715,15 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
161 csr |= MUSB_TXCSR_MODE;
163 - if (usb_gettoggle(urb->dev,
165 + if (usb_gettoggle(urb->dev, qh->epnum, 1))
166 csr |= MUSB_TXCSR_H_WR_DATATOGGLE
167 | MUSB_TXCSR_H_DATATOGGLE;
169 csr |= MUSB_TXCSR_CLRDATATOG;
171 - /* twice in case of double packet buffering */
172 musb_writew(epio, MUSB_TXCSR, csr);
173 /* REVISIT may need to clear FLUSHFIFO ... */
174 + csr &= ~MUSB_TXCSR_DMAMODE;
175 musb_writew(epio, MUSB_TXCSR, csr);
176 csr = musb_readw(epio, MUSB_TXCSR);
178 @@ -755,34 +766,19 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
180 #ifdef CONFIG_USB_INVENTRA_DMA
183 - /* clear previous state */
184 - csr = musb_readw(epio, MUSB_TXCSR);
185 - csr &= ~(MUSB_TXCSR_AUTOSET
186 - | MUSB_TXCSR_DMAMODE
187 - | MUSB_TXCSR_DMAENAB);
188 - csr |= MUSB_TXCSR_MODE;
189 - musb_writew(epio, MUSB_TXCSR,
190 - csr | MUSB_TXCSR_MODE);
192 qh->segsize = min(len, dma_channel->max_len);
194 if (qh->segsize <= packet_sz)
195 dma_channel->desired_mode = 0;
197 dma_channel->desired_mode = 1;
200 if (dma_channel->desired_mode == 0) {
201 - csr &= ~(MUSB_TXCSR_AUTOSET
202 - | MUSB_TXCSR_DMAMODE);
203 + /* Against the programming guide */
204 csr |= (MUSB_TXCSR_DMAENAB);
205 - /* against programming guide */
207 csr |= (MUSB_TXCSR_AUTOSET
209 | MUSB_TXCSR_DMAMODE);
211 musb_writew(epio, MUSB_TXCSR, csr);
213 dma_ok = dma_controller->channel_program(
214 @@ -799,6 +795,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
216 hw_ep->rx_channel = NULL;
220 + * The programming guide says that we must
221 + * clear the DMAENAB bit before DMAMODE...
223 + csr = musb_readw(epio, MUSB_TXCSR);
224 + csr &= ~(MUSB_TXCSR_DMAENAB
225 + | MUSB_TXCSR_AUTOSET);
226 + musb_writew(epio, MUSB_TXCSR, csr);
227 + csr &= ~MUSB_TXCSR_DMAMODE;
228 + musb_writew(epio, MUSB_TXCSR, csr);
232 @@ -806,18 +813,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
233 /* candidate for DMA */
234 if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
236 - /* program endpoint CSRs first, then setup DMA.
237 - * assume CPPI setup succeeds.
238 - * defer enabling dma.
240 - csr = musb_readw(epio, MUSB_TXCSR);
241 - csr &= ~(MUSB_TXCSR_AUTOSET
242 - | MUSB_TXCSR_DMAMODE
243 - | MUSB_TXCSR_DMAENAB);
244 - csr |= MUSB_TXCSR_MODE;
245 - musb_writew(epio, MUSB_TXCSR,
246 - csr | MUSB_TXCSR_MODE);
248 + /* Defer enabling DMA */
249 dma_channel->actual_len = 0L;
252 @@ -846,20 +842,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
256 - /* ASSERT: TXCSR_DMAENAB was already cleared */
258 /* PIO to load FIFO */
259 qh->segsize = load_count;
260 musb_write_fifo(hw_ep, load_count, buf);
261 - csr = musb_readw(epio, MUSB_TXCSR);
262 - csr &= ~(MUSB_TXCSR_DMAENAB
263 - | MUSB_TXCSR_DMAMODE
264 - | MUSB_TXCSR_AUTOSET);
266 - csr |= MUSB_TXCSR_MODE;
269 - musb_writew(epio, MUSB_TXCSR, csr);
272 /* re-enable interrupt */
273 diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
274 index 8662e9e..40709c3 100644
275 --- a/drivers/usb/musb/musbhsdma.c
276 +++ b/drivers/usb/musb/musbhsdma.c
277 @@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel)
278 void __iomem *mbase = musb_channel->controller->base;
280 u8 bchannel = musb_channel->idx;
284 if (channel->status == MUSB_DMA_STATUS_BUSY) {
285 if (musb_channel->transmit) {
287 - csr = musb_readw(mbase,
288 - MUSB_EP_OFFSET(musb_channel->epnum,
290 - csr &= ~(MUSB_TXCSR_AUTOSET |
291 - MUSB_TXCSR_DMAENAB |
292 - MUSB_TXCSR_DMAMODE);
294 - MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR),
296 + offset = MUSB_EP_OFFSET(musb_channel->epnum,
300 + * The programming guide says that we must clear
301 + * the DMAENAB bit before the DMAMODE bit...
303 + csr = musb_readw(mbase, offset);
304 + csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
305 + musb_writew(mbase, offset, csr);
306 + csr &= ~MUSB_TXCSR_DMAMODE;
307 + musb_writew(mbase, offset, csr);
309 - csr = musb_readw(mbase,
310 - MUSB_EP_OFFSET(musb_channel->epnum,
312 + offset = MUSB_EP_OFFSET(musb_channel->epnum,
315 + csr = musb_readw(mbase, offset);
316 csr &= ~(MUSB_RXCSR_AUTOCLEAR |
320 - MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR),
322 + musb_writew(mbase, offset, csr);
326 @@ -296,14 +298,25 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
327 && ((channel->desired_mode == 0)
328 || (channel->actual_len &
329 (musb_channel->max_packet_sz - 1)))
332 + u8 epnum = musb_channel->epnum;
333 + int offset = MUSB_EP_OFFSET(epnum,
338 + * The programming guide says that we
339 + * must clear DMAENAB before DMAMODE.
341 + musb_ep_select(mbase, epnum);
342 + txcsr = musb_readw(mbase, offset);
343 + txcsr &= ~(MUSB_TXCSR_DMAENAB
344 + | MUSB_TXCSR_AUTOSET);
345 + musb_writew(mbase, offset, txcsr);
346 /* Send out the packet */
347 - musb_ep_select(mbase,
348 - musb_channel->epnum);
349 - musb_writew(mbase, MUSB_EP_OFFSET(
350 - musb_channel->epnum,
352 - MUSB_TXCSR_TXPKTRDY);
353 + txcsr &= ~MUSB_TXCSR_DMAMODE;
354 + txcsr |= MUSB_TXCSR_TXPKTRDY;
355 + musb_writew(mbase, offset, txcsr);