summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorLi Jun <jun.li@nxp.com>2017-03-07 10:35:01 +0800
committerPeter Chen <peter.chen@nxp.com>2017-03-15 11:30:43 +0800
commit4f4555cfe704913ce4ce836ab2707825d784a7cc (patch)
tree6e6393d5f4bd3fa9c3f16c80d23caf620a1eb2e9 /drivers/usb
parent4495c08e84729385774601b5146d51d9e5849f81 (diff)
usb: chipidea: udc: update gadget state after bus resume
Gadget state is set to be suspended when bus suspened, but not updated after resume, this patch saves the gadget state before suspend and restores it after resume. Signed-off-by: Li Jun <jun.li@nxp.com> Signed-off-by: Peter Chen <peter.chen@nxp.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/chipidea/ci.h2
-rw-r--r--drivers/usb/chipidea/udc.c21
2 files changed, 15 insertions, 8 deletions
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 59e22389c10b..6743f85b1b7a 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -177,6 +177,7 @@ struct hw_bank {
* @td_pool: allocation pool for transfer descriptors
* @gadget: device side representation for peripheral controller
* @driver: gadget driver
+ * @resume_state: save the state of gadget suspend from
* @hw_ep_max: total number of endpoints supported by hardware
* @ci_hw_ep: array of endpoints
* @ep0_dir: ep0 direction
@@ -227,6 +228,7 @@ struct ci_hdrc {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
+ enum usb_device_state resume_state;
unsigned hw_ep_max;
struct ci_hw_ep ci_hw_ep[ENDPT_MAX];
u32 ep0_dir;
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index f88e9157fad0..be166c6ecb2d 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1845,27 +1845,32 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
if (USBi_PCI & intr) {
ci->gadget.speed = hw_port_is_high_speed(ci) ?
USB_SPEED_HIGH : USB_SPEED_FULL;
- if (ci->suspended && ci->driver->resume) {
- spin_unlock(&ci->lock);
- ci->driver->resume(&ci->gadget);
- spin_lock(&ci->lock);
+ if (ci->suspended) {
+ if (ci->driver->resume) {
+ spin_unlock(&ci->lock);
+ ci->driver->resume(&ci->gadget);
+ spin_lock(&ci->lock);
+ }
ci->suspended = 0;
+ usb_gadget_set_state(&ci->gadget,
+ ci->resume_state);
}
}
if (USBi_UI & intr)
isr_tr_complete_handler(ci);
- if (USBi_SLI & intr) {
+ if ((USBi_SLI & intr) && !(ci->suspended)) {
+ ci->suspended = 1;
+ ci->resume_state = ci->gadget.state;
if (ci->gadget.speed != USB_SPEED_UNKNOWN &&
ci->driver->suspend) {
- ci->suspended = 1;
spin_unlock(&ci->lock);
ci->driver->suspend(&ci->gadget);
- usb_gadget_set_state(&ci->gadget,
- USB_STATE_SUSPENDED);
spin_lock(&ci->lock);
}
+ usb_gadget_set_state(&ci->gadget,
+ USB_STATE_SUSPENDED);
}
retval = IRQ_HANDLED;
} else {