summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-02-06 04:23:37 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-02-06 04:23:37 -0800
commit50c69dd9ecbda29b60c0f7d81cf2718a0e44e51e (patch)
tree8be1c44ce8b407b8705cf94693037bfb1d7cee9b /drivers/usb
parentdd09cbba262e6a13856385e52bded069d78408bd (diff)
parentcdc3be303e42f1eb809218ae3ac2de1f3d7ed622 (diff)
Merge "usb: dwc3: Add support to LPM L1 remote wakeup for ep0 endpoints"
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/dwc3/core.h2
-rw-r--r--drivers/usb/dwc3/debugfs.c5
-rw-r--r--drivers/usb/dwc3/ep0.c14
-rw-r--r--drivers/usb/dwc3/gadget.c7
-rw-r--r--drivers/usb/dwc3/gadget.h8
5 files changed, 28 insertions, 8 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 0e73026711d6..9de5e06430e1 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1021,6 +1021,8 @@ struct dwc3 {
unsigned irq_event_count[MAX_INTR_STATS];
unsigned irq_dbg_index;
+ unsigned long l1_remote_wakeup_cnt;
+
wait_queue_head_t wait_linkstate;
};
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 4b4978043d50..068b03a35bd5 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -1180,9 +1180,12 @@ static int dwc3_gadget_int_events_show(struct seq_file *s, void *unused)
seq_printf(s, "%d\t", dwc->bh_completion_time[i]);
seq_putc(s, '\n');
- seq_printf(s, "t_pwr evt irq : %lld\t",
+ seq_printf(s, "t_pwr evt irq : %lld\n",
ktime_to_us(dwc->t_pwr_evt_irq));
+ seq_printf(s, "l1_remote_wakeup_cnt : %lu\n",
+ dwc->l1_remote_wakeup_cnt);
+
spin_unlock_irqrestore(&dwc->lock, flags);
return 0;
}
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2b910e09a80a..9cd87513619c 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -236,6 +236,8 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
unsigned long flags;
int ret;
+ enum dwc3_link_state link_state;
+ u32 reg;
spin_lock_irqsave(&dwc->lock, flags);
if (!dep->endpoint.desc) {
@@ -252,6 +254,18 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
goto out;
}
+ /* if link stats is in L1 initiate remote wakeup before queuing req */
+ if (dwc->speed != DWC3_DSTS_SUPERSPEED) {
+ link_state = dwc3_get_link_state(dwc);
+ /* in HS this link state is same as L1 */
+ if (link_state == DWC3_LINK_STATE_U2) {
+ dwc->l1_remote_wakeup_cnt++;
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg |= DWC3_DCTL_ULSTCHNG_RECOVERY;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+ }
+ }
+
dwc3_trace(trace_dwc3_ep0,
"queueing request %pK to %s length %d state '%s'",
request, dep->name, request->length,
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e2440b7efc58..88350e61f3bd 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1317,13 +1317,6 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
return 0;
}
-static inline enum dwc3_link_state dwc3_get_link_state(struct dwc3 *dwc)
-{
- u32 reg;
- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
- return DWC3_DSTS_USBLNKST(reg);
-}
-
static bool dwc3_gadget_is_suspended(struct dwc3 *dwc)
{
if (atomic_read(&dwc->in_lpm) ||
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index 3abd6379164e..a21962c8f513 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -84,6 +84,14 @@ static inline void dwc3_gadget_move_request_queued(struct dwc3_request *req)
list_move_tail(&req->list, &dep->req_queued);
}
+static inline enum dwc3_link_state dwc3_get_link_state(struct dwc3 *dwc)
+{
+ u32 reg;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+ return DWC3_DSTS_USBLNKST(reg);
+}
+
void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
int status);