aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_host.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/musb_host.c')
-rw-r--r--drivers/usb/musb/musb_host.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 74c4c3698f1e..3421cf9858b5 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -605,8 +605,14 @@ 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, 608 /* Set RXMAXP with the FIFO size of the endpoint
609 qh->maxpacket | ((qh->hb_mult - 1) << 11)); 609 * to disable double buffer mode.
610 */
611 if (musb->hwvers < MUSB_HWVERS_2000)
612 musb_writew(ep->regs, MUSB_RXMAXP, ep->max_packet_sz_rx);
613 else
614 musb_writew(ep->regs, MUSB_RXMAXP,
615 qh->maxpacket | ((qh->hb_mult - 1) << 11));
610 616
611 ep->rx_reinit = 0; 617 ep->rx_reinit = 0;
612} 618}
@@ -1771,6 +1777,9 @@ static int musb_schedule(
1771 int best_end, epnum; 1777 int best_end, epnum;
1772 struct musb_hw_ep *hw_ep = NULL; 1778 struct musb_hw_ep *hw_ep = NULL;
1773 struct list_head *head = NULL; 1779 struct list_head *head = NULL;
1780 u8 toggle;
1781 u8 txtype;
1782 struct urb *urb = next_urb(qh);
1774 1783
1775 /* use fixed hardware for control and bulk */ 1784 /* use fixed hardware for control and bulk */
1776 if (qh->type == USB_ENDPOINT_XFER_CONTROL) { 1785 if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
@@ -1809,6 +1818,27 @@ static int musb_schedule(
1809 diff -= (qh->maxpacket * qh->hb_mult); 1818 diff -= (qh->maxpacket * qh->hb_mult);
1810 1819
1811 if (diff >= 0 && best_diff > diff) { 1820 if (diff >= 0 && best_diff > diff) {
1821
1822 /*
1823 * Mentor controller has a bug in that if we schedule
1824 * a BULK Tx transfer on an endpoint that had earlier
1825 * handled ISOC then the BULK transfer has to start on
1826 * a zero toggle. If the BULK transfer starts on a 1
1827 * toggle then this transfer will fail as the mentor
1828 * controller starts the Bulk transfer on a 0 toggle
1829 * irrespective of the programming of the toggle bits
1830 * in the TXCSR register. Check for this condition
1831 * while allocating the EP for a Tx Bulk transfer. If
1832 * so skip this EP.
1833 */
1834 hw_ep = musb->endpoints + epnum;
1835 toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in);
1836 txtype = (musb_readb(hw_ep->regs, MUSB_TXTYPE)
1837 >> 4) & 0x3;
1838 if (!is_in && (qh->type == USB_ENDPOINT_XFER_BULK) &&
1839 toggle && (txtype == USB_ENDPOINT_XFER_ISOC))
1840 continue;
1841
1812 best_diff = diff; 1842 best_diff = diff;
1813 best_end = epnum; 1843 best_end = epnum;
1814 } 1844 }