UPSTREAM: usb: dwc3: gadget: put link to U0 before Start Transfer
authorFelipe Balbi <felipe.balbi@linux.intel.com>
Mon, 4 Apr 2016 09:46:33 +0000 (12:46 +0300)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 16 Aug 2016 12:48:19 +0000 (20:48 +0800)
Synopsys Databook says we should move link to U0
before issuing a Start Transfer command. We could
require the gadget driver to call
usb_gadget_wakeup() however I feel that changing all
gadget drivers to keep track of Link State and
conditionally call usb_gadget_wakeup() would be far
too much work. For now we will handle this at the
UDC level, but at some point composite.c should be
one handling this.

Change-Id: I3a124898f642d909c3b705f12dcb95c6af1a7825
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: Wu Liang feng <wulf@rock-chips.com>
(cherry picked from commit c36d8e947a56a6e6478fc48152c5f4626462db55)

drivers/usb/dwc3/gadget.c

index 83a97cac395257c1813e4ceff0497cb7cffb7ac1..32a9a940bebb66fe76c6ad3df6ae59442fe70583 100644 (file)
@@ -221,6 +221,8 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
        } while (1);
 }
 
+static int __dwc3_gadget_wakeup(struct dwc3 *dwc);
+
 int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
                unsigned cmd, struct dwc3_gadget_ep_cmd_params *params)
 {
@@ -248,6 +250,20 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
                dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
        }
 
+       if (cmd == DWC3_DEPCMD_STARTTRANSFER) {
+               int             needs_wakeup;
+
+               needs_wakeup = (dwc->link_state == DWC3_LINK_STATE_U1 ||
+                               dwc->link_state == DWC3_LINK_STATE_U2 ||
+                               dwc->link_state == DWC3_LINK_STATE_U3);
+
+               if (unlikely(needs_wakeup)) {
+                       ret = __dwc3_gadget_wakeup(dwc);
+                       dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n",
+                                       ret);
+               }
+       }
+
        dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0);
        dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1);
        dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2);