if we have hibernation configured, Databook
instructs us to set KEEP_CONNECT bit together
with RUN_STOP bit, in step 9 of section 12.3.6.1
Initialization for Hibernation Support.

Signed-off-by: Felipe Balbi <ba...@ti.com>
---
 drivers/usb/dwc3/gadget.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e9f2cbc..3eee96a 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1429,7 +1429,7 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget 
*g,
        return 0;
 }
 
-static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
+static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 {
        u32                     reg;
        u32                     timeout = 500;
@@ -1444,9 +1444,17 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on)
                if (dwc->revision >= DWC3_REVISION_194A)
                        reg &= ~DWC3_DCTL_KEEP_CONNECT;
                reg |= DWC3_DCTL_RUN_STOP;
+
+               if (dwc->has_hibernation)
+                       reg |= DWC3_DCTL_KEEP_CONNECT;
+
                dwc->pullups_connected = true;
        } else {
                reg &= ~DWC3_DCTL_RUN_STOP;
+
+               if (dwc->has_hibernation && !suspend)
+                       reg &= ~DWC3_DCTL_KEEP_CONNECT;
+
                dwc->pullups_connected = false;
        }
 
@@ -1484,7 +1492,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
        is_on = !!is_on;
 
        spin_lock_irqsave(&dwc->lock, flags);
-       ret = dwc3_gadget_run_stop(dwc, is_on);
+       ret = dwc3_gadget_run_stop(dwc, is_on, false);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return ret;
@@ -2726,8 +2734,10 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
 int dwc3_gadget_prepare(struct dwc3 *dwc)
 {
-       if (dwc->pullups_connected)
+       if (dwc->pullups_connected) {
                dwc3_gadget_disable_irq(dwc);
+               dwc3_gadget_run_stop(dwc, true, true);
+       }
 
        return 0;
 }
@@ -2736,7 +2746,7 @@ void dwc3_gadget_complete(struct dwc3 *dwc)
 {
        if (dwc->pullups_connected) {
                dwc3_gadget_enable_irq(dwc);
-               dwc3_gadget_run_stop(dwc, true);
+               dwc3_gadget_run_stop(dwc, true, false);
        }
 }
 
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to