From c61a482621db18deb24cd5c3e1ec1be5531a4c65 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 2 Jan 2012 18:55:57 +0200 Subject: [PATCH] --- yaml --- r: 289611 b: refs/heads/master c: 8598bde7fa125e85bc97decd6513d37dcf1e7bd9 h: refs/heads/master i: 289609: 44f60834e88a0409bd5a5adddd4a0662b1e873c0 289607: 87bef96b4c090caefbb2fd0f49cb67a1e41dc94a v: v3 --- [refs] | 2 +- trunk/drivers/usb/dwc3/gadget.c | 52 ++++++++++++++++++++++++++------- trunk/drivers/usb/dwc3/gadget.h | 1 + 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/[refs] b/[refs] index dfe3684e5679..e5a2198ad1fa 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 080d921fe7a8d27c07eba7723fe53a3bea100327 +refs/heads/master: 8598bde7fa125e85bc97decd6513d37dcf1e7bd9 diff --git a/trunk/drivers/usb/dwc3/gadget.c b/trunk/drivers/usb/dwc3/gadget.c index 1dee17e7b778..80003952547e 100644 --- a/trunk/drivers/usb/dwc3/gadget.c +++ b/trunk/drivers/usb/dwc3/gadget.c @@ -89,6 +89,42 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) return 0; } +/** + * dwc3_gadget_set_link_state - Sets USB Link to a particular State + * @dwc: pointer to our context structure + * @state: the state to put link into + * + * Caller should take care of locking. This function will + * return 0 on success or -EINVAL. + */ +int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) +{ + int retries = 100; + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; + + /* set requested state */ + reg |= DWC3_DCTL_ULSTCHNGREQ(state); + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + + /* wait for a change in DSTS */ + while (--retries) { + reg = dwc3_readl(dwc->regs, DWC3_DSTS); + + /* in HS, means ON */ + if (DWC3_DSTS_USBLNKST(reg) == state) + return 0; + + usleep_range(500, 1500); + } + + dev_vdbg(dwc->dev, "link state change request timed out\n"); + + return -ETIMEDOUT; +} + void dwc3_map_buffer_to_dma(struct dwc3_request *req) { struct dwc3 *dwc = req->dep->dwc; @@ -1155,17 +1191,11 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) goto out; } - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - - /* - * Switch link state to Recovery. In HS/FS/LS this means - * RemoteWakeup Request - */ - reg |= DWC3_DCTL_ULSTCHNG_RECOVERY; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - /* wait for at least 2000us */ - usleep_range(2000, 2500); + ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV); + if (ret < 0) { + dev_err(dwc->dev, "failed to put link in Recovery\n"); + goto out; + } /* write zeroes to Link Change Request */ reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; diff --git a/trunk/drivers/usb/dwc3/gadget.h b/trunk/drivers/usb/dwc3/gadget.h index 2cf6f2989f73..152b6de0649d 100644 --- a/trunk/drivers/usb/dwc3/gadget.h +++ b/trunk/drivers/usb/dwc3/gadget.h @@ -101,6 +101,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status); int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode); +int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state); void dwc3_ep0_interrupt(struct dwc3 *dwc, const struct dwc3_event_depevt *event);