diff options
author | Ajay Kumar Gupta <ajay.gupta@ti.com> | 2009-04-03 19:16:17 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:41 -0400 |
commit | a483d7068f661213e9586d4d132fc0e0287118b4 (patch) | |
tree | ff575463eacee555e070a2d2a049f7ac37d9fb38 /drivers/usb/musb/musb_host.c | |
parent | d1043a2697effee3054451a9293a376bfb013e4b (diff) |
musb: add high bandwidth ISO support
Tested on OMAP3 host side with Creative (Live! Cam Optia) USB camera
which uses high bandwidth isochronous IN endpoints. FIFO mode 4 is
updated to provide the needed 4K endpoint buffer without breaking
the g_nokia composite gadget configuration. (This is the only
gadget driver known to use enough endpoints to notice the change.)
Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'drivers/usb/musb/musb_host.c')
-rw-r--r-- | drivers/usb/musb/musb_host.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 0d1f15336a9c..94a2a350a414 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
@@ -605,7 +605,8 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) | |||
605 | musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg); | 605 | musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg); |
606 | musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg); | 606 | musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg); |
607 | /* NOTE: bulk combining rewrites high bits of maxpacket */ | 607 | /* NOTE: bulk combining rewrites high bits of maxpacket */ |
608 | musb_writew(ep->regs, MUSB_RXMAXP, qh->maxpacket); | 608 | musb_writew(ep->regs, MUSB_RXMAXP, |
609 | qh->maxpacket | ((qh->hb_mult - 1) << 11)); | ||
609 | 610 | ||
610 | ep->rx_reinit = 0; | 611 | ep->rx_reinit = 0; |
611 | } | 612 | } |
@@ -627,9 +628,10 @@ static bool musb_tx_dma_program(struct dma_controller *dma, | |||
627 | csr = musb_readw(epio, MUSB_TXCSR); | 628 | csr = musb_readw(epio, MUSB_TXCSR); |
628 | if (length > pkt_size) { | 629 | if (length > pkt_size) { |
629 | mode = 1; | 630 | mode = 1; |
630 | csr |= MUSB_TXCSR_AUTOSET | 631 | csr |= MUSB_TXCSR_DMAMODE | MUSB_TXCSR_DMAENAB; |
631 | | MUSB_TXCSR_DMAMODE | 632 | /* autoset shouldn't be set in high bandwidth */ |
632 | | MUSB_TXCSR_DMAENAB; | 633 | if (qh->hb_mult == 1) |
634 | csr |= MUSB_TXCSR_AUTOSET; | ||
633 | } else { | 635 | } else { |
634 | mode = 0; | 636 | mode = 0; |
635 | csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); | 637 | csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); |
@@ -1497,6 +1499,10 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1497 | /* packet error reported later */ | 1499 | /* packet error reported later */ |
1498 | iso_err = true; | 1500 | iso_err = true; |
1499 | } | 1501 | } |
1502 | } else if (rx_csr & MUSB_RXCSR_INCOMPRX) { | ||
1503 | DBG(3, "end %d high bandwidth incomplete ISO packet RX\n", | ||
1504 | epnum); | ||
1505 | status = -EPROTO; | ||
1500 | } | 1506 | } |
1501 | 1507 | ||
1502 | /* faults abort the transfer */ | 1508 | /* faults abort the transfer */ |
@@ -1704,7 +1710,11 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1704 | val &= ~MUSB_RXCSR_H_AUTOREQ; | 1710 | val &= ~MUSB_RXCSR_H_AUTOREQ; |
1705 | else | 1711 | else |
1706 | val |= MUSB_RXCSR_H_AUTOREQ; | 1712 | val |= MUSB_RXCSR_H_AUTOREQ; |
1707 | val |= MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB; | 1713 | val |= MUSB_RXCSR_DMAENAB; |
1714 | |||
1715 | /* autoclear shouldn't be set in high bandwidth */ | ||
1716 | if (qh->hb_mult == 1) | ||
1717 | val |= MUSB_RXCSR_AUTOCLEAR; | ||
1708 | 1718 | ||
1709 | musb_writew(epio, MUSB_RXCSR, | 1719 | musb_writew(epio, MUSB_RXCSR, |
1710 | MUSB_RXCSR_H_WZC_BITS | val); | 1720 | MUSB_RXCSR_H_WZC_BITS | val); |
@@ -1790,9 +1800,10 @@ static int musb_schedule( | |||
1790 | continue; | 1800 | continue; |
1791 | 1801 | ||
1792 | if (is_in) | 1802 | if (is_in) |
1793 | diff = hw_ep->max_packet_sz_rx - qh->maxpacket; | 1803 | diff = hw_ep->max_packet_sz_rx; |
1794 | else | 1804 | else |
1795 | diff = hw_ep->max_packet_sz_tx - qh->maxpacket; | 1805 | diff = hw_ep->max_packet_sz_tx; |
1806 | diff -= (qh->maxpacket * qh->hb_mult); | ||
1796 | 1807 | ||
1797 | if (diff >= 0 && best_diff > diff) { | 1808 | if (diff >= 0 && best_diff > diff) { |
1798 | best_diff = diff; | 1809 | best_diff = diff; |
@@ -1895,15 +1906,27 @@ static int musb_urb_enqueue( | |||
1895 | qh->is_ready = 1; | 1906 | qh->is_ready = 1; |
1896 | 1907 | ||
1897 | qh->maxpacket = le16_to_cpu(epd->wMaxPacketSize); | 1908 | qh->maxpacket = le16_to_cpu(epd->wMaxPacketSize); |
1909 | qh->type = usb_endpoint_type(epd); | ||
1898 | 1910 | ||
1899 | /* no high bandwidth support yet */ | 1911 | /* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier. |
1900 | if (qh->maxpacket & ~0x7ff) { | 1912 | * Some musb cores don't support high bandwidth ISO transfers; and |
1901 | ret = -EMSGSIZE; | 1913 | * we don't (yet!) support high bandwidth interrupt transfers. |
1902 | goto done; | 1914 | */ |
1915 | qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03); | ||
1916 | if (qh->hb_mult > 1) { | ||
1917 | int ok = (qh->type == USB_ENDPOINT_XFER_ISOC); | ||
1918 | |||
1919 | if (ok) | ||
1920 | ok = (usb_pipein(urb->pipe) && musb->hb_iso_rx) | ||
1921 | || (usb_pipeout(urb->pipe) && musb->hb_iso_tx); | ||
1922 | if (!ok) { | ||
1923 | ret = -EMSGSIZE; | ||
1924 | goto done; | ||
1925 | } | ||
1926 | qh->maxpacket &= 0x7ff; | ||
1903 | } | 1927 | } |
1904 | 1928 | ||
1905 | qh->epnum = usb_endpoint_num(epd); | 1929 | qh->epnum = usb_endpoint_num(epd); |
1906 | qh->type = usb_endpoint_type(epd); | ||
1907 | 1930 | ||
1908 | /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */ | 1931 | /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */ |
1909 | qh->addr_reg = (u8) usb_pipedevice(urb->pipe); | 1932 | qh->addr_reg = (u8) usb_pipedevice(urb->pipe); |