aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/usb/musb/musb_core.c19
-rw-r--r--drivers/usb/musb/musb_core.h3
-rw-r--r--drivers/usb/musb/musb_host.c47
-rw-r--r--drivers/usb/musb/musb_host.h1
4 files changed, 48 insertions, 22 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index b49859623f8d..554a414f65d1 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1084,14 +1084,13 @@ static struct fifo_cfg __initdata mode_4_cfg[] = {
1084{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, }, 1084{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, },
1085{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, }, 1085{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, },
1086{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, }, 1086{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, },
1087{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 512, }, 1087{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, },
1088{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 512, }, 1088{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, },
1089{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 512, }, 1089{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, },
1090{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 512, }, 1090{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, },
1091{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 512, }, 1091{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, },
1092{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 512, }, 1092{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, },
1093{ .hw_ep_num = 13, .style = FIFO_TX, .maxpacket = 512, }, 1093{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, },
1094{ .hw_ep_num = 13, .style = FIFO_RX, .maxpacket = 512, },
1095{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, 1094{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
1096{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, 1095{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
1097}; 1096};
@@ -1351,11 +1350,11 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
1351 } 1350 }
1352 if (reg & MUSB_CONFIGDATA_HBRXE) { 1351 if (reg & MUSB_CONFIGDATA_HBRXE) {
1353 strcat(aInfo, ", HB-ISO Rx"); 1352 strcat(aInfo, ", HB-ISO Rx");
1354 strcat(aInfo, " (X)"); /* no driver support */ 1353 musb->hb_iso_rx = true;
1355 } 1354 }
1356 if (reg & MUSB_CONFIGDATA_HBTXE) { 1355 if (reg & MUSB_CONFIGDATA_HBTXE) {
1357 strcat(aInfo, ", HB-ISO Tx"); 1356 strcat(aInfo, ", HB-ISO Tx");
1358 strcat(aInfo, " (X)"); /* no driver support */ 1357 musb->hb_iso_tx = true;
1359 } 1358 }
1360 if (reg & MUSB_CONFIGDATA_SOFTCONE) 1359 if (reg & MUSB_CONFIGDATA_SOFTCONE)
1361 strcat(aInfo, ", SoftConn"); 1360 strcat(aInfo, ", SoftConn");
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 78116fdb5781..f3772ca3b2cf 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -395,6 +395,9 @@ struct musb {
395 unsigned is_multipoint:1; 395 unsigned is_multipoint:1;
396 unsigned ignore_disconnect:1; /* during bus resets */ 396 unsigned ignore_disconnect:1; /* during bus resets */
397 397
398 unsigned hb_iso_rx:1; /* high bandwidth iso rx? */
399 unsigned hb_iso_tx:1; /* high bandwidth iso tx? */
400
398#ifdef C_MP_TX 401#ifdef C_MP_TX
399 unsigned bulk_split:1; 402 unsigned bulk_split:1;
400#define can_bulk_split(musb,type) \ 403#define can_bulk_split(musb,type) \
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);
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
index 0b7fbcd21963..14b00776638d 100644
--- a/drivers/usb/musb/musb_host.h
+++ b/drivers/usb/musb/musb_host.h
@@ -67,6 +67,7 @@ struct musb_qh {
67 u8 is_ready; /* safe to modify hw_ep */ 67 u8 is_ready; /* safe to modify hw_ep */
68 u8 type; /* XFERTYPE_* */ 68 u8 type; /* XFERTYPE_* */
69 u8 epnum; 69 u8 epnum;
70 u8 hb_mult; /* high bandwidth pkts per uf */
70 u16 maxpacket; 71 u16 maxpacket;
71 u16 frame; /* for periodic schedule */ 72 u16 frame; /* for periodic schedule */
72 unsigned iso_idx; /* in urb->iso_frame_desc[] */ 73 unsigned iso_idx; /* in urb->iso_frame_desc[] */