aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_host.c
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/musb_host.c
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/musb_host.c')
-rw-r--r--drivers/usb/musb/musb_host.c79
1 files changed, 32 insertions, 47 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 518abfca124..1dfaaa6acfa 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 */