aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_host.c
diff options
context:
space:
mode:
authorSwaminathan S <swami.iyer@ti.com>2009-12-28 06:40:37 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 17:53:45 -0500
commit5274dab6cb99c529b2e7f16bbc8ff9a79be46e7f (patch)
treed04a356d4ab42fa74438994e97492754ddd6014d /drivers/usb/musb/musb_host.c
parentf933a0c0fe0ea5f49a35bcd45e3e4850e0606cba (diff)
usb: musb: workaround toggle bug when doing bulk transfer after isoc
This patch implements the work around for a Mentor controller related bug where it's observed a BULK Tx toggle error on the bus when a BULK IO gets scheduled on an endpoint that was earlier used for handling ISOC transaction and needed to start on 1 toggle. When such a situation arises even if the TXCSR toggle bits are programmed correctly by the musb driver the data gets transmitted with 0 toggle which leads to toggle error on the bus and the BULK transaction fails. In case of MSC write, the device gets reset by the Host. This Mentor bug is observed on almost all Mentor versions (1.3, 1.5, 1.8). Confirmed on DM644x, DM355, DM365, OMAPL13x platforms. Signed-off-by: Swaminathan S <swami.iyer@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> 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.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 74c4c3698f1e..c3fdd6d69f5e 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1771,6 +1771,9 @@ static int musb_schedule(
1771 int best_end, epnum; 1771 int best_end, epnum;
1772 struct musb_hw_ep *hw_ep = NULL; 1772 struct musb_hw_ep *hw_ep = NULL;
1773 struct list_head *head = NULL; 1773 struct list_head *head = NULL;
1774 u8 toggle;
1775 u8 txtype;
1776 struct urb *urb = next_urb(qh);
1774 1777
1775 /* use fixed hardware for control and bulk */ 1778 /* use fixed hardware for control and bulk */
1776 if (qh->type == USB_ENDPOINT_XFER_CONTROL) { 1779 if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
@@ -1809,6 +1812,27 @@ static int musb_schedule(
1809 diff -= (qh->maxpacket * qh->hb_mult); 1812 diff -= (qh->maxpacket * qh->hb_mult);
1810 1813
1811 if (diff >= 0 && best_diff > diff) { 1814 if (diff >= 0 && best_diff > diff) {
1815
1816 /*
1817 * Mentor controller has a bug in that if we schedule
1818 * a BULK Tx transfer on an endpoint that had earlier
1819 * handled ISOC then the BULK transfer has to start on
1820 * a zero toggle. If the BULK transfer starts on a 1
1821 * toggle then this transfer will fail as the mentor
1822 * controller starts the Bulk transfer on a 0 toggle
1823 * irrespective of the programming of the toggle bits
1824 * in the TXCSR register. Check for this condition
1825 * while allocating the EP for a Tx Bulk transfer. If
1826 * so skip this EP.
1827 */
1828 hw_ep = musb->endpoints + epnum;
1829 toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in);
1830 txtype = (musb_readb(hw_ep->regs, MUSB_TXTYPE)
1831 >> 4) & 0x3;
1832 if (!is_in && (qh->type == USB_ENDPOINT_XFER_BULK) &&
1833 toggle && (txtype == USB_ENDPOINT_XFER_ISOC))
1834 continue;
1835
1812 best_diff = diff; 1836 best_diff = diff;
1813 best_end = epnum; 1837 best_end = epnum;
1814 } 1838 }