diff options
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 68 |
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 | |||
1159 | out: | ||
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 | ||
1625 | static int dwc3_gadget_stop(struct usb_gadget *g, | 1633 | static 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 | |||
2047 | static 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 | ||
2145 | static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) | 2164 | static 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 | ||
2747 | int dwc3_gadget_prepare(struct dwc3 *dwc) | 2771 | int 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 | |||
2757 | void 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 | |||
2765 | int 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 | ||
2803 | err1: | 2819 | err1: |