From 7b2a0368bbc9bc4a7936d8587eaff4b8c35b2247 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Dec 2013 13:43:19 -0600 Subject: [PATCH] usb: dwc3: gadget: set KEEP_CONNECT in case of hibernation 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 --- 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 87b09bd6266e..3934d0afc185 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1409,7 +1409,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; @@ -1424,9 +1424,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; } @@ -1464,7 +1472,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; @@ -2715,8 +2723,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; } @@ -2725,7 +2735,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); } }