aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3/gadget.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r--drivers/usb/dwc3/gadget.c68
1 files changed, 42 insertions, 26 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 546ea5431b8c..f03b136ecfce 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1140,8 +1140,14 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
1140 if (!dep->endpoint.desc) { 1140 if (!dep->endpoint.desc) {
1141 dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", 1141 dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
1142 request, ep->name); 1142 request, ep->name);
1143 spin_unlock_irqrestore(&dwc->lock, flags); 1143 ret = -ESHUTDOWN;
1144 return -ESHUTDOWN; 1144 goto out;
1145 }
1146
1147 if (WARN(req->dep != dep, "request %p belongs to '%s'\n",
1148 request, req->dep->name)) {
1149 ret = -EINVAL;
1150 goto out;
1145 } 1151 }
1146 1152
1147 dev_vdbg(dwc->dev, "queing request %p to %s length %d\n", 1153 dev_vdbg(dwc->dev, "queing request %p to %s length %d\n",
@@ -1149,6 +1155,8 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
1149 trace_dwc3_ep_queue(req); 1155 trace_dwc3_ep_queue(req);
1150 1156
1151 ret = __dwc3_gadget_ep_queue(dep, req); 1157 ret = __dwc3_gadget_ep_queue(dep, req);
1158
1159out:
1152 spin_unlock_irqrestore(&dwc->lock, flags); 1160 spin_unlock_irqrestore(&dwc->lock, flags);
1153 1161
1154 return ret; 1162 return ret;
@@ -1622,8 +1630,7 @@ err0:
1622 return ret; 1630 return ret;
1623} 1631}
1624 1632
1625static int dwc3_gadget_stop(struct usb_gadget *g, 1633static int dwc3_gadget_stop(struct usb_gadget *g)
1626 struct usb_gadget_driver *driver)
1627{ 1634{
1628 struct dwc3 *dwc = gadget_to_dwc(g); 1635 struct dwc3 *dwc = gadget_to_dwc(g);
1629 unsigned long flags; 1636 unsigned long flags;
@@ -2034,6 +2041,17 @@ static void dwc3_resume_gadget(struct dwc3 *dwc)
2034 if (dwc->gadget_driver && dwc->gadget_driver->resume) { 2041 if (dwc->gadget_driver && dwc->gadget_driver->resume) {
2035 spin_unlock(&dwc->lock); 2042 spin_unlock(&dwc->lock);
2036 dwc->gadget_driver->resume(&dwc->gadget); 2043 dwc->gadget_driver->resume(&dwc->gadget);
2044 }
2045}
2046
2047static void dwc3_reset_gadget(struct dwc3 *dwc)
2048{
2049 if (!dwc->gadget_driver)
2050 return;
2051
2052 if (dwc->gadget.speed != USB_SPEED_UNKNOWN) {
2053 spin_unlock(&dwc->lock);
2054 usb_gadget_udc_reset(&dwc->gadget, dwc->gadget_driver);
2037 spin_lock(&dwc->lock); 2055 spin_lock(&dwc->lock);
2038 } 2056 }
2039} 2057}
@@ -2140,6 +2158,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
2140 2158
2141 dwc->gadget.speed = USB_SPEED_UNKNOWN; 2159 dwc->gadget.speed = USB_SPEED_UNKNOWN;
2142 dwc->setup_packet_pending = false; 2160 dwc->setup_packet_pending = false;
2161 usb_gadget_set_state(&dwc->gadget, USB_STATE_NOTATTACHED);
2143} 2162}
2144 2163
2145static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) 2164static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
@@ -2177,11 +2196,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
2177 dwc3_gadget_disconnect_interrupt(dwc); 2196 dwc3_gadget_disconnect_interrupt(dwc);
2178 } 2197 }
2179 2198
2180 /* after reset -> Default State */ 2199 dwc3_reset_gadget(dwc);
2181 usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
2182
2183 if (dwc->gadget.speed != USB_SPEED_UNKNOWN)
2184 dwc3_disconnect_gadget(dwc);
2185 2200
2186 reg = dwc3_readl(dwc->regs, DWC3_DCTL); 2201 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
2187 reg &= ~DWC3_DCTL_TSTCTRL_MASK; 2202 reg &= ~DWC3_DCTL_TSTCTRL_MASK;
@@ -2287,11 +2302,20 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
2287 reg = dwc3_readl(dwc->regs, DWC3_DCTL); 2302 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
2288 reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN); 2303 reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
2289 2304
2305 reg |= DWC3_DCTL_HIRD_THRES(dwc->hird_threshold);
2306
2290 /* 2307 /*
2291 * TODO: This should be configurable. For now using 2308 * When dwc3 revisions >= 2.40a, LPM Erratum is enabled and
2292 * maximum allowed HIRD threshold value of 0b1100 2309 * DCFG.LPMCap is set, core responses with an ACK and the
2310 * BESL value in the LPM token is less than or equal to LPM
2311 * NYET threshold.
2293 */ 2312 */
2294 reg |= DWC3_DCTL_HIRD_THRES(12); 2313 WARN_ONCE(dwc->revision < DWC3_REVISION_240A
2314 && dwc->has_lpm_erratum,
2315 "LPM Erratum not available on dwc3 revisisions < 2.40a\n");
2316
2317 if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
2318 reg |= DWC3_DCTL_LPM_ERRATA(dwc->lpm_nyet_threshold);
2295 2319
2296 dwc3_writel(dwc->regs, DWC3_DCTL, reg); 2320 dwc3_writel(dwc->regs, DWC3_DCTL, reg);
2297 } else { 2321 } else {
@@ -2744,26 +2768,13 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
2744 dwc->ctrl_req, dwc->ctrl_req_addr); 2768 dwc->ctrl_req, dwc->ctrl_req_addr);
2745} 2769}
2746 2770
2747int dwc3_gadget_prepare(struct dwc3 *dwc) 2771int dwc3_gadget_suspend(struct dwc3 *dwc)
2748{ 2772{
2749 if (dwc->pullups_connected) { 2773 if (dwc->pullups_connected) {
2750 dwc3_gadget_disable_irq(dwc); 2774 dwc3_gadget_disable_irq(dwc);
2751 dwc3_gadget_run_stop(dwc, true, true); 2775 dwc3_gadget_run_stop(dwc, true, true);
2752 } 2776 }
2753 2777
2754 return 0;
2755}
2756
2757void dwc3_gadget_complete(struct dwc3 *dwc)
2758{
2759 if (dwc->pullups_connected) {
2760 dwc3_gadget_enable_irq(dwc);
2761 dwc3_gadget_run_stop(dwc, true, false);
2762 }
2763}
2764
2765int dwc3_gadget_suspend(struct dwc3 *dwc)
2766{
2767 __dwc3_gadget_ep_disable(dwc->eps[0]); 2778 __dwc3_gadget_ep_disable(dwc->eps[0]);
2768 __dwc3_gadget_ep_disable(dwc->eps[1]); 2779 __dwc3_gadget_ep_disable(dwc->eps[1]);
2769 2780
@@ -2798,6 +2809,11 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
2798 2809
2799 dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg); 2810 dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
2800 2811
2812 if (dwc->pullups_connected) {
2813 dwc3_gadget_enable_irq(dwc);
2814 dwc3_gadget_run_stop(dwc, true, false);
2815 }
2816
2801 return 0; 2817 return 0;
2802 2818
2803err1: 2819err1: