Skip to content

Commit

Permalink
usb: dwc3: gadget: re-factor Link state change to a function
Browse files Browse the repository at this point in the history
Most link changes will, of course, happen with
the help of a matching host HW, but in some cases
we might want to debug very low level details about
the link and exposing this to debugfs sounds like
a good plan.

This is a preparation for such setup.

Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Felipe Balbi committed Feb 6, 2012
1 parent 080d921 commit 8598bde
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
52 changes: 41 additions & 11 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/dwc3/gadget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 8598bde

Please sign in to comment.