dwc3: Add usb_get_remote_wakeup_status() API()

USB composite device updates to host about its wakeup capability
using bmAttribute, and USB host may support remote wakeup
functionality using SET_FEATURE. UDC gadget ops supports wakeup()
API which can be invoked by USB function driver to resume USB bus
by signaling remote wakeup. With HW accelerated path IPA will need
to know if host has enabled remote wakeup in order to decide whether
to suspend or disconnect the GSI channels. Add an API to allow USB
GSI driver to query the current remote wakeup enabled status.

Change-Id: I09eb62714f9df90d68cce5c478dc19096477709e
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
This commit is contained in:
Mayank Rana 2020-06-11 14:19:22 -07:00
commit af88d5f829
5 changed files with 35 additions and 0 deletions

View file

@ -1150,6 +1150,7 @@ struct dwc3_scratchpad_array {
* @bh_handled_evt_cnt: no. of events handled by tasklet per interrupt
* @bh_dbg_index: index for capturing bh_completion_time and bh_handled_evt_cnt
* @last_run_stop: timestamp denoting the last run_stop update
* @is_remote_wakeup_enabled: remote wakeup status from host perspective
*/
struct dwc3 {
struct work_struct drd_work;
@ -1395,6 +1396,7 @@ struct dwc3 {
u32 gen2_tx_de_emph2;
u32 gen2_tx_de_emph3;
ktime_t last_run_stop;
bool is_remote_wakeup_enabled;
};
#define INCRX_BURST_MODE 0

View file

@ -1838,6 +1838,21 @@ int usb_gsi_ep_op(struct usb_ep *ep, void *op_data, enum gsi_ep_op op)
}
EXPORT_SYMBOL(usb_gsi_ep_op);
/* Return true if host is supporting remote wakeup functionality. */
bool usb_get_remote_wakeup_status(struct usb_gadget *gadget)
{
struct dwc3 *dwc = gadget_to_dwc(gadget);
unsigned long flags;
bool rw = false;
spin_lock_irqsave(&dwc->lock, flags);
rw = dwc->is_remote_wakeup_enabled ? true : false;
spin_unlock_irqrestore(&dwc->lock, flags);
return rw;
}
EXPORT_SYMBOL(usb_get_remote_wakeup_status);
/**
* Configure a USB DBM ep to work in BAM mode.
*

View file

@ -340,6 +340,9 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
if (reg & DWC3_DCTL_INITU2ENA)
usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
} else {
usb_status |= dwc->is_remote_wakeup_enabled <<
USB_DEVICE_REMOTE_WAKEUP;
}
break;
@ -460,6 +463,9 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc,
switch (wValue) {
case USB_DEVICE_REMOTE_WAKEUP:
dbg_log_string("remote wakeup :%s",
(set ? "enabled" : "disabled"));
dwc->is_remote_wakeup_enabled = set;
break;
/*
* 9.4.1 says only only for SS, in AddressState only for

View file

@ -1993,6 +1993,12 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
int ret;
spin_lock_irqsave(&dwc->lock, flags);
if (!dwc->is_remote_wakeup_enabled) {
spin_unlock_irqrestore(&dwc->lock, flags);
dbg_log_string("remote wakeup not supported\n");
return -EINVAL;
}
ret = __dwc3_gadget_wakeup(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
@ -2508,6 +2514,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
}
dwc->gadget_driver = driver;
dwc->is_remote_wakeup_enabled = false;
/*
* For DRD, this might get called by gadget driver during bootup
@ -2539,6 +2546,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
spin_lock_irqsave(&dwc->lock, flags);
dwc->gadget_driver = NULL;
dwc->is_remote_wakeup_enabled = false;
spin_unlock_irqrestore(&dwc->lock, flags);
dbg_event(0xFF, "fwq_started", 0);
@ -3362,6 +3370,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->link_state = DWC3_LINK_STATE_U0;
dwc->is_remote_wakeup_enabled = false;
}
static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)

View file

@ -136,6 +136,7 @@ int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr, u32 size,
bool msm_dwc3_reset_ep_after_lpm(struct usb_gadget *gadget);
int msm_dwc3_reset_dbm_ep(struct usb_ep *ep);
int dwc3_msm_release_ss_lane(struct device *dev);
bool usb_get_remote_wakeup_status(struct usb_gadget *gadget);
#else
static inline struct usb_ep *usb_ep_autoconfig_by_name(
struct usb_gadget *gadget, struct usb_endpoint_descriptor *desc,
@ -163,6 +164,8 @@ static inline int msm_dwc3_reset_dbm_ep(struct usb_ep *ep)
{ return -ENODEV; }
static inline int dwc3_msm_release_ss_lane(struct device *dev)
{ return -ENODEV; }
static bool __maybe_unused usb_get_remote_wakeup_status(struct usb_gadget *gadget)
{ return false; }
#endif
#endif /* __LINUX_USB_DWC3_MSM_H */