aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_host.c
diff options
context:
space:
mode:
authorAjay Kumar Gupta <ajay.gupta@ti.com>2009-04-03 19:16:17 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:41 -0400
commita483d7068f661213e9586d4d132fc0e0287118b4 (patch)
treeff575463eacee555e070a2d2a049f7ac37d9fb38 /drivers/usb/musb/musb_host.c
parentd1043a2697effee3054451a9293a376bfb013e4b (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.c47
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);