dwc3: Add USB function suspend/resume related handling

Currently dwc3 driver doesn't hand over USB function suspend/resume
request to composite layer as those are supposed to be handle by
USB function driver. This change adds support for it. It also adds
function remote wakeup functionality which is needed by USB function
suspended interface to perform remote wakeup towards USB host for
resume interface related functionality.

Change-Id: I1f9ecc60346e16fad87439cc12c551e05b4f3491
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
This commit is contained in:
Mayank Rana 2020-07-13 18:23:25 -07:00
commit 2e537ca82a
2 changed files with 31 additions and 1 deletions

View file

@ -30,6 +30,8 @@
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep);
static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
struct dwc3_ep *dep, struct dwc3_request *req);
static int dwc3_ep0_delegate_req(struct dwc3 *dwc,
struct usb_ctrlrequest *ctrl);
static void dwc3_ep0_prepare_one_trb(struct dwc3_ep *dep,
dma_addr_t buf_dma, u32 len, u32 type, bool chain)
@ -352,7 +354,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
* Function Remote Wake Capable D0
* Function Remote Wakeup D1
*/
break;
return dwc3_ep0_delegate_req(dwc, ctrl);
case USB_RECIP_ENDPOINT:
dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex);
@ -507,6 +509,9 @@ static int dwc3_ep0_handle_intf(struct dwc3 *dwc,
* For now, we're not doing anything, just making sure we return
* 0 so USB Command Verifier tests pass without any errors.
*/
ret = dwc3_ep0_delegate_req(dwc, ctrl);
if (ret)
return ret;
break;
default:
ret = -EINVAL;

View file

@ -2116,6 +2116,28 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
return 0;
}
#ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED
static int dwc_gadget_func_wakeup(struct usb_gadget *g, int interface_id)
{
int ret = 0;
struct dwc3 *dwc = gadget_to_dwc(g);
if (dwc3_gadget_is_suspended(dwc)) {
dev_dbg(dwc->dev, "USB bus is suspended, scheduling wakeup\n");
dwc3_gadget_wakeup(&dwc->gadget);
return -EAGAIN;
}
ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_XMIT_DEV,
0x1 | (interface_id << 4));
if (ret)
dev_err(dwc->dev, "Function wakeup HW command failed, ret %d\n",
ret);
return ret;
}
#endif
static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
int is_selfpowered)
{
@ -2770,6 +2792,9 @@ static void __maybe_unused dwc3_gadget_set_speed(struct usb_gadget *g,
static const struct usb_gadget_ops dwc3_gadget_ops = {
.get_frame = dwc3_gadget_get_frame,
.wakeup = dwc3_gadget_wakeup,
#ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED
.func_wakeup = dwc_gadget_func_wakeup,
#endif
.set_selfpowered = dwc3_gadget_set_selfpowered,
.vbus_session = dwc3_gadget_vbus_session,
.vbus_draw = dwc3_gadget_vbus_draw,