aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb
diff options
context:
space:
mode:
authorSergei Shtylyov <sshtylyov@ru.mvista.com>2009-03-26 21:27:47 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-17 13:50:25 -0400
commitb6e434a5404b9ce8c285ea081b6ea5c523b29db4 (patch)
tree8a1d0aac0692859aeb97931b86bf60314b663567 /drivers/usb/musb
parentc7bbc056a92476b3b3d70a8df7cc746ac5d56de7 (diff)
USB: musb: sanitize clearing TXCSR DMA bits (take 2)
The MUSB code clears TXCSR_DMAMODE incorrectly in several places, either asserting that TXCSR_DMAENAB is clear (when sometimes it isn't) or clearing both bits together. Recent versions of the programmer's guide require DMAENAB to be cleared first, although some older ones didn't. Fix this and while at it: - In musb_gadget::txstate(), stop clearing the AUTOSET and DMAMODE bits for the CPPI case since they never get set anyway (the former bit is reserved on DaVinci); but do clear the DMAENAB bit on the DMA error path. - In musb_host::musb_ep_program(), remove the duplicate DMA controller specific code code clearing the TXCSR previous state, add the code to clear TXCSR DMA bits on the Inventra DMA error path, to replace such code (executed late) on the PIO path. - In musbhsdma::dma_channel_abort()/dma_controller_irq(), add/use the 'offset' variable to avoid MUSB_EP_OFFSET() invocations on every RXCSR/TXCSR access. [dbrownell@users.sourceforge.net: don't introduce CamelCase, shrink diff] Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r--drivers/usb/musb/musb_gadget.c33
-rw-r--r--drivers/usb/musb/musb_host.c79
-rw-r--r--drivers/usb/musb/musbhsdma.c59
3 files changed, 90 insertions, 81 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index c7ebd0867fcc..f79440cdfe7e 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status)
165 if (is_dma_capable() && ep->dma) { 165 if (is_dma_capable() && ep->dma) {
166 struct dma_controller *c = ep->musb->dma_controller; 166 struct dma_controller *c = ep->musb->dma_controller;
167 int value; 167 int value;
168
168 if (ep->is_in) { 169 if (ep->is_in) {
170 /*
171 * The programming guide says that we must not clear
172 * the DMAMODE bit before DMAENAB, so we only
173 * clear it in the second write...
174 */
169 musb_writew(epio, MUSB_TXCSR, 175 musb_writew(epio, MUSB_TXCSR,
170 0 | MUSB_TXCSR_FLUSHFIFO); 176 MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO);
171 musb_writew(epio, MUSB_TXCSR, 177 musb_writew(epio, MUSB_TXCSR,
172 0 | MUSB_TXCSR_FLUSHFIFO); 178 0 | MUSB_TXCSR_FLUSHFIFO);
173 } else { 179 } else {
@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
230 | IN token(s) are recd from Host. 236 | IN token(s) are recd from Host.
231 | -> DMA interrupt on completion 237 | -> DMA interrupt on completion
232 | calls TxAvail. 238 | calls TxAvail.
233 | -> stop DMA, ~DmaEenab, 239 | -> stop DMA, ~DMAENAB,
234 | -> set TxPktRdy for last short pkt or zlp 240 | -> set TxPktRdy for last short pkt or zlp
235 | -> Complete Request 241 | -> Complete Request
236 | -> Continue next request (call txstate) 242 | -> Continue next request (call txstate)
@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req)
315 request->dma, request_size); 321 request->dma, request_size);
316 if (use_dma) { 322 if (use_dma) {
317 if (musb_ep->dma->desired_mode == 0) { 323 if (musb_ep->dma->desired_mode == 0) {
318 /* ASSERT: DMAENAB is clear */ 324 /*
319 csr &= ~(MUSB_TXCSR_AUTOSET | 325 * We must not clear the DMAMODE bit
320 MUSB_TXCSR_DMAMODE); 326 * before the DMAENAB bit -- and the
327 * latter doesn't always get cleared
328 * before we get here...
329 */
330 csr &= ~(MUSB_TXCSR_AUTOSET
331 | MUSB_TXCSR_DMAENAB);
332 musb_writew(epio, MUSB_TXCSR, csr
333 | MUSB_TXCSR_P_WZC_BITS);
334 csr &= ~MUSB_TXCSR_DMAMODE;
321 csr |= (MUSB_TXCSR_DMAENAB | 335 csr |= (MUSB_TXCSR_DMAENAB |
322 MUSB_TXCSR_MODE); 336 MUSB_TXCSR_MODE);
323 /* against programming guide */ 337 /* against programming guide */
@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
334 348
335#elif defined(CONFIG_USB_TI_CPPI_DMA) 349#elif defined(CONFIG_USB_TI_CPPI_DMA)
336 /* program endpoint CSR first, then setup DMA */ 350 /* program endpoint CSR first, then setup DMA */
337 csr &= ~(MUSB_TXCSR_AUTOSET 351 csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
338 | MUSB_TXCSR_DMAMODE
339 | MUSB_TXCSR_P_UNDERRUN
340 | MUSB_TXCSR_TXPKTRDY);
341 csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; 352 csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB;
342 musb_writew(epio, MUSB_TXCSR, 353 musb_writew(epio, MUSB_TXCSR,
343 (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) 354 (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
364 if (!use_dma) { 375 if (!use_dma) {
365 c->channel_release(musb_ep->dma); 376 c->channel_release(musb_ep->dma);
366 musb_ep->dma = NULL; 377 musb_ep->dma = NULL;
367 /* ASSERT: DMAENAB clear */ 378 csr &= ~MUSB_TXCSR_DMAENAB;
368 csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); 379 musb_writew(epio, MUSB_TXCSR, csr);
369 /* invariant: prequest->buf is non-null */ 380 /* invariant: prequest->buf is non-null */
370 } 381 }
371#elif defined(CONFIG_USB_TUSB_OMAP_DMA) 382#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 518abfca1243..1dfaaa6acfaf 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -593,10 +593,17 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
593 csr = musb_readw(ep->regs, MUSB_TXCSR); 593 csr = musb_readw(ep->regs, MUSB_TXCSR);
594 if (csr & MUSB_TXCSR_MODE) { 594 if (csr & MUSB_TXCSR_MODE) {
595 musb_h_tx_flush_fifo(ep); 595 musb_h_tx_flush_fifo(ep);
596 csr = musb_readw(ep->regs, MUSB_TXCSR);
596 musb_writew(ep->regs, MUSB_TXCSR, 597 musb_writew(ep->regs, MUSB_TXCSR,
597 MUSB_TXCSR_FRCDATATOG); 598 csr | MUSB_TXCSR_FRCDATATOG);
598 } 599 }
599 /* clear mode (and everything else) to enable Rx */ 600
601 /*
602 * Clear the MODE bit (and everything else) to enable Rx.
603 * NOTE: we mustn't clear the DMAMODE bit before DMAENAB.
604 */
605 if (csr & MUSB_TXCSR_DMAMODE)
606 musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
600 musb_writew(ep->regs, MUSB_TXCSR, 0); 607 musb_writew(ep->regs, MUSB_TXCSR, 0);
601 608
602 /* scrub all previous state, clearing toggle */ 609 /* scrub all previous state, clearing toggle */
@@ -693,12 +700,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
693 700
694 /* general endpoint setup */ 701 /* general endpoint setup */
695 if (epnum) { 702 if (epnum) {
696 /* ASSERT: TXCSR_DMAENAB was already cleared */
697
698 /* flush all old state, set default */ 703 /* flush all old state, set default */
699 musb_h_tx_flush_fifo(hw_ep); 704 musb_h_tx_flush_fifo(hw_ep);
705
706 /*
707 * We must not clear the DMAMODE bit before or in
708 * the same cycle with the DMAENAB bit, so we clear
709 * the latter first...
710 */
700 csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT 711 csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT
701 | MUSB_TXCSR_DMAMODE 712 | MUSB_TXCSR_AUTOSET
713 | MUSB_TXCSR_DMAENAB
702 | MUSB_TXCSR_FRCDATATOG 714 | MUSB_TXCSR_FRCDATATOG
703 | MUSB_TXCSR_H_RXSTALL 715 | MUSB_TXCSR_H_RXSTALL
704 | MUSB_TXCSR_H_ERROR 716 | MUSB_TXCSR_H_ERROR
@@ -706,16 +718,15 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
706 ); 718 );
707 csr |= MUSB_TXCSR_MODE; 719 csr |= MUSB_TXCSR_MODE;
708 720
709 if (usb_gettoggle(urb->dev, 721 if (usb_gettoggle(urb->dev, qh->epnum, 1))
710 qh->epnum, 1))
711 csr |= MUSB_TXCSR_H_WR_DATATOGGLE 722 csr |= MUSB_TXCSR_H_WR_DATATOGGLE
712 | MUSB_TXCSR_H_DATATOGGLE; 723 | MUSB_TXCSR_H_DATATOGGLE;
713 else 724 else
714 csr |= MUSB_TXCSR_CLRDATATOG; 725 csr |= MUSB_TXCSR_CLRDATATOG;
715 726
716 /* twice in case of double packet buffering */
717 musb_writew(epio, MUSB_TXCSR, csr); 727 musb_writew(epio, MUSB_TXCSR, csr);
718 /* REVISIT may need to clear FLUSHFIFO ... */ 728 /* REVISIT may need to clear FLUSHFIFO ... */
729 csr &= ~MUSB_TXCSR_DMAMODE;
719 musb_writew(epio, MUSB_TXCSR, csr); 730 musb_writew(epio, MUSB_TXCSR, csr);
720 csr = musb_readw(epio, MUSB_TXCSR); 731 csr = musb_readw(epio, MUSB_TXCSR);
721 } else { 732 } else {
@@ -759,34 +770,19 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
759 770
760#ifdef CONFIG_USB_INVENTRA_DMA 771#ifdef CONFIG_USB_INVENTRA_DMA
761 if (dma_channel) { 772 if (dma_channel) {
762
763 /* clear previous state */
764 csr = musb_readw(epio, MUSB_TXCSR);
765 csr &= ~(MUSB_TXCSR_AUTOSET
766 | MUSB_TXCSR_DMAMODE
767 | MUSB_TXCSR_DMAENAB);
768 csr |= MUSB_TXCSR_MODE;
769 musb_writew(epio, MUSB_TXCSR,
770 csr | MUSB_TXCSR_MODE);
771
772 qh->segsize = min(len, dma_channel->max_len); 773 qh->segsize = min(len, dma_channel->max_len);
773
774 if (qh->segsize <= packet_sz) 774 if (qh->segsize <= packet_sz)
775 dma_channel->desired_mode = 0; 775 dma_channel->desired_mode = 0;
776 else 776 else
777 dma_channel->desired_mode = 1; 777 dma_channel->desired_mode = 1;
778 778
779
780 if (dma_channel->desired_mode == 0) { 779 if (dma_channel->desired_mode == 0) {
781 csr &= ~(MUSB_TXCSR_AUTOSET 780 /* Against the programming guide */
782 | MUSB_TXCSR_DMAMODE);
783 csr |= (MUSB_TXCSR_DMAENAB); 781 csr |= (MUSB_TXCSR_DMAENAB);
784 /* against programming guide */
785 } else 782 } else
786 csr |= (MUSB_TXCSR_AUTOSET 783 csr |= (MUSB_TXCSR_AUTOSET
787 | MUSB_TXCSR_DMAENAB 784 | MUSB_TXCSR_DMAENAB
788 | MUSB_TXCSR_DMAMODE); 785 | MUSB_TXCSR_DMAMODE);
789
790 musb_writew(epio, MUSB_TXCSR, csr); 786 musb_writew(epio, MUSB_TXCSR, csr);
791 787
792 dma_ok = dma_controller->channel_program( 788 dma_ok = dma_controller->channel_program(
@@ -803,6 +799,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
803 else 799 else
804 hw_ep->rx_channel = NULL; 800 hw_ep->rx_channel = NULL;
805 dma_channel = NULL; 801 dma_channel = NULL;
802
803 /*
804 * The programming guide says that we must
805 * clear the DMAENAB bit before DMAMODE...
806 */
807 csr = musb_readw(epio, MUSB_TXCSR);
808 csr &= ~(MUSB_TXCSR_DMAENAB
809 | MUSB_TXCSR_AUTOSET);
810 musb_writew(epio, MUSB_TXCSR, csr);
811 csr &= ~MUSB_TXCSR_DMAMODE;
812 musb_writew(epio, MUSB_TXCSR, csr);
806 } 813 }
807 } 814 }
808#endif 815#endif
@@ -810,18 +817,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
810 /* candidate for DMA */ 817 /* candidate for DMA */
811 if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) { 818 if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
812 819
813 /* program endpoint CSRs first, then setup DMA. 820 /* Defer enabling DMA */
814 * assume CPPI setup succeeds.
815 * defer enabling dma.
816 */
817 csr = musb_readw(epio, MUSB_TXCSR);
818 csr &= ~(MUSB_TXCSR_AUTOSET
819 | MUSB_TXCSR_DMAMODE
820 | MUSB_TXCSR_DMAENAB);
821 csr |= MUSB_TXCSR_MODE;
822 musb_writew(epio, MUSB_TXCSR,
823 csr | MUSB_TXCSR_MODE);
824
825 dma_channel->actual_len = 0L; 821 dma_channel->actual_len = 0L;
826 qh->segsize = len; 822 qh->segsize = len;
827 823
@@ -850,20 +846,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
850 } 846 }
851 847
852 if (load_count) { 848 if (load_count) {
853 /* ASSERT: TXCSR_DMAENAB was already cleared */
854
855 /* PIO to load FIFO */ 849 /* PIO to load FIFO */
856 qh->segsize = load_count; 850 qh->segsize = load_count;
857 musb_write_fifo(hw_ep, load_count, buf); 851 musb_write_fifo(hw_ep, load_count, buf);
858 csr = musb_readw(epio, MUSB_TXCSR);
859 csr &= ~(MUSB_TXCSR_DMAENAB
860 | MUSB_TXCSR_DMAMODE
861 | MUSB_TXCSR_AUTOSET);
862 /* write CSR */
863 csr |= MUSB_TXCSR_MODE;
864
865 if (epnum)
866 musb_writew(epio, MUSB_TXCSR, csr);
867 } 852 }
868 853
869 /* re-enable interrupt */ 854 /* re-enable interrupt */
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index de0e24203673..5e83f96d6b77 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel)
195 void __iomem *mbase = musb_channel->controller->base; 195 void __iomem *mbase = musb_channel->controller->base;
196 196
197 u8 bchannel = musb_channel->idx; 197 u8 bchannel = musb_channel->idx;
198 int offset;
198 u16 csr; 199 u16 csr;
199 200
200 if (channel->status == MUSB_DMA_STATUS_BUSY) { 201 if (channel->status == MUSB_DMA_STATUS_BUSY) {
201 if (musb_channel->transmit) { 202 if (musb_channel->transmit) {
202 203 offset = MUSB_EP_OFFSET(musb_channel->epnum,
203 csr = musb_readw(mbase, 204 MUSB_TXCSR);
204 MUSB_EP_OFFSET(musb_channel->epnum, 205
205 MUSB_TXCSR)); 206 /*
206 csr &= ~(MUSB_TXCSR_AUTOSET | 207 * The programming guide says that we must clear
207 MUSB_TXCSR_DMAENAB | 208 * the DMAENAB bit before the DMAMODE bit...
208 MUSB_TXCSR_DMAMODE); 209 */
209 musb_writew(mbase, 210 csr = musb_readw(mbase, offset);
210 MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR), 211 csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
211 csr); 212 musb_writew(mbase, offset, csr);
213 csr &= ~MUSB_TXCSR_DMAMODE;
214 musb_writew(mbase, offset, csr);
212 } else { 215 } else {
213 csr = musb_readw(mbase, 216 offset = MUSB_EP_OFFSET(musb_channel->epnum,
214 MUSB_EP_OFFSET(musb_channel->epnum, 217 MUSB_RXCSR);
215 MUSB_RXCSR)); 218
219 csr = musb_readw(mbase, offset);
216 csr &= ~(MUSB_RXCSR_AUTOCLEAR | 220 csr &= ~(MUSB_RXCSR_AUTOCLEAR |
217 MUSB_RXCSR_DMAENAB | 221 MUSB_RXCSR_DMAENAB |
218 MUSB_RXCSR_DMAMODE); 222 MUSB_RXCSR_DMAMODE);
219 musb_writew(mbase, 223 musb_writew(mbase, offset, csr);
220 MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR),
221 csr);
222 } 224 }
223 225
224 musb_writew(mbase, 226 musb_writew(mbase,
@@ -296,14 +298,25 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
296 && ((channel->desired_mode == 0) 298 && ((channel->desired_mode == 0)
297 || (channel->actual_len & 299 || (channel->actual_len &
298 (musb_channel->max_packet_sz - 1))) 300 (musb_channel->max_packet_sz - 1)))
299 ) { 301 ) {
302 u8 epnum = musb_channel->epnum;
303 int offset = MUSB_EP_OFFSET(epnum,
304 MUSB_TXCSR);
305 u16 txcsr;
306
307 /*
308 * The programming guide says that we
309 * must clear DMAENAB before DMAMODE.
310 */
311 musb_ep_select(mbase, epnum);
312 txcsr = musb_readw(mbase, offset);
313 txcsr &= ~(MUSB_TXCSR_DMAENAB
314 | MUSB_TXCSR_AUTOSET);
315 musb_writew(mbase, offset, txcsr);
300 /* Send out the packet */ 316 /* Send out the packet */
301 musb_ep_select(mbase, 317 txcsr &= ~MUSB_TXCSR_DMAMODE;
302 musb_channel->epnum); 318 txcsr |= MUSB_TXCSR_TXPKTRDY;
303 musb_writew(mbase, MUSB_EP_OFFSET( 319 musb_writew(mbase, offset, txcsr);
304 musb_channel->epnum,
305 MUSB_TXCSR),
306 MUSB_TXCSR_TXPKTRDY);
307 } 320 }
308 musb_dma_completion(musb, musb_channel->epnum, 321 musb_dma_completion(musb, musb_channel->epnum,
309 musb_channel->transmit); 322 musb_channel->transmit);