aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Anderson <dianders@chromium.org>2015-11-11 13:33:52 -0500
committerFelipe Balbi <balbi@ti.com>2015-12-15 10:12:41 -0500
commit69b76cdff592058ea445cd40e18c75dffaba4cb9 (patch)
tree2f6b280c1c4ee89f93376f0ccd666f51adcd6786
parent6a6595318ac2dd169d2931a1d9431a64f4ada75c (diff)
usb: dwc2: host: Support immediate retries for split transactions
In some cases, like when you've got a "Microsoft Wireless Keyboard 2000" connected to dwc2 with a hub, expected that we'll get some transfer errors sometimes. The controller is expected to try at least 3 times before giving up. See figure "Figure A-67. Normal HS CSPLIT 3 Strikes Smash" in the USB spec. The dwc2 controller has a way to support this by using the "EC_MC" field. The Raspberry Pi driver has logic for setting this right. See fiq_fsm_queue_split_transaction() in their "dwc_otg_hcd.c". Let's use the same logic. After making this change, we no longer get dropped characters from the above mentioned keyboard. Other devices on the same bus as the keyboard also behave more properly. Thanks for Julius Werner for the expert analysis and suggestions. Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/dwc2/core.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 97de85521eb6..0a9ebe00fbcc 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -1707,6 +1707,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
1707 u32 hcchar; 1707 u32 hcchar;
1708 u32 hctsiz = 0; 1708 u32 hctsiz = 0;
1709 u16 num_packets; 1709 u16 num_packets;
1710 u32 ec_mc;
1710 1711
1711 if (dbg_hc(chan)) 1712 if (dbg_hc(chan))
1712 dev_vdbg(hsotg->dev, "%s()\n", __func__); 1713 dev_vdbg(hsotg->dev, "%s()\n", __func__);
@@ -1743,6 +1744,13 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
1743 1744
1744 hctsiz |= chan->xfer_len << TSIZ_XFERSIZE_SHIFT & 1745 hctsiz |= chan->xfer_len << TSIZ_XFERSIZE_SHIFT &
1745 TSIZ_XFERSIZE_MASK; 1746 TSIZ_XFERSIZE_MASK;
1747
1748 /* For split set ec_mc for immediate retries */
1749 if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
1750 chan->ep_type == USB_ENDPOINT_XFER_ISOC)
1751 ec_mc = 3;
1752 else
1753 ec_mc = 1;
1746 } else { 1754 } else {
1747 if (dbg_hc(chan)) 1755 if (dbg_hc(chan))
1748 dev_vdbg(hsotg->dev, "no split\n"); 1756 dev_vdbg(hsotg->dev, "no split\n");
@@ -1805,6 +1813,9 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
1805 1813
1806 hctsiz |= chan->xfer_len << TSIZ_XFERSIZE_SHIFT & 1814 hctsiz |= chan->xfer_len << TSIZ_XFERSIZE_SHIFT &
1807 TSIZ_XFERSIZE_MASK; 1815 TSIZ_XFERSIZE_MASK;
1816
1817 /* The ec_mc gets the multi_count for non-split */
1818 ec_mc = chan->multi_count;
1808 } 1819 }
1809 1820
1810 chan->start_pkt_count = num_packets; 1821 chan->start_pkt_count = num_packets;
@@ -1855,8 +1866,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
1855 1866
1856 hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); 1867 hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
1857 hcchar &= ~HCCHAR_MULTICNT_MASK; 1868 hcchar &= ~HCCHAR_MULTICNT_MASK;
1858 hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT & 1869 hcchar |= (ec_mc << HCCHAR_MULTICNT_SHIFT) & HCCHAR_MULTICNT_MASK;
1859 HCCHAR_MULTICNT_MASK;
1860 dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar); 1870 dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar);
1861 1871
1862 if (hcchar & HCCHAR_CHDIS) 1872 if (hcchar & HCCHAR_CHDIS)