[09/11] usb: dwc3: gadget: set KEEP_CONNECT in case of hibernation

Message ID 1393357243-2958-10-git-send-email-balbi@ti.com
State Accepted
Commit 7b2a0368bbc9bc4a7936d8587eaff4b8c35b2247
Headers show

Commit Message

Felipe Balbi Feb. 25, 2014, 7:40 p.m.
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 <balbi@ti.com>
---
 drivers/usb/dwc3/gadget.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

Patch

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);
 	}
 }