diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2014-11-21 15:14:49 +0100 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2014-11-21 09:07:42 -0600 |
commit | dc6e69e603e58200df806afcfb9b71ef94e58847 (patch) | |
tree | 7309381e4303518d5e5636c639fcf667aab5aa90 /drivers/usb/dwc2 | |
parent | 7ad8096edfe0529eabb3ad466184c8fbd6134e1a (diff) | |
download | lwn-dc6e69e603e58200df806afcfb9b71ef94e58847.tar.gz lwn-dc6e69e603e58200df806afcfb9b71ef94e58847.zip |
usb: dwc2: gadget: rework suspend/resume code to correctly restore gadget state
Suspend/resume code assumed that the gadget was always started and
enabled to connect to usb bus. This means that the actual state of the
gadget (started/stopped or connected/disconnected) was not correctly
preserved on suspend/resume cycle. This patch fixes this issue.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r-- | drivers/usb/dwc2/core.h | 3 | ||||
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 39 |
2 files changed, 24 insertions, 18 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 6b197550c133..7a70a1349334 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -688,8 +688,9 @@ struct dwc2_hsotg { u8 ctrl_buff[8]; struct usb_gadget gadget; + unsigned int enabled:1; unsigned int connected:1; - unsigned int setup; + unsigned int setup:1; unsigned long last_rst; struct s3c_hsotg_ep *eps; #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */ diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 651733413c0e..05b05221d677 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2889,6 +2889,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, spin_lock_irqsave(&hsotg->lock, flags); s3c_hsotg_init(hsotg); s3c_hsotg_core_init_disconnected(hsotg); + hsotg->enabled = 0; spin_unlock_irqrestore(&hsotg->lock, flags); dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); @@ -2929,6 +2930,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget) hsotg->driver = NULL; hsotg->gadget.speed = USB_SPEED_UNKNOWN; + hsotg->enabled = 0; spin_unlock_irqrestore(&hsotg->lock, flags); @@ -2972,9 +2974,11 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on) spin_lock_irqsave(&hsotg->lock, flags); if (is_on) { clk_enable(hsotg->clk); + hsotg->enabled = 1; s3c_hsotg_core_connect(hsotg); } else { s3c_hsotg_core_disconnect(hsotg); + hsotg->enabled = 0; clk_disable(hsotg->clk); } @@ -3585,20 +3589,21 @@ int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg) mutex_lock(&hsotg->init_mutex); - if (hsotg->driver) + if (hsotg->driver) { + int ep; + dev_info(hsotg->dev, "suspending usb gadget %s\n", hsotg->driver->driver.name); - spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_core_disconnect(hsotg); - s3c_hsotg_disconnect(hsotg); - hsotg->gadget.speed = USB_SPEED_UNKNOWN; - spin_unlock_irqrestore(&hsotg->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); + if (hsotg->enabled) + s3c_hsotg_core_disconnect(hsotg); + s3c_hsotg_disconnect(hsotg); + hsotg->gadget.speed = USB_SPEED_UNKNOWN; + spin_unlock_irqrestore(&hsotg->lock, flags); - s3c_hsotg_phy_disable(hsotg); + s3c_hsotg_phy_disable(hsotg); - if (hsotg->driver) { - int ep; for (ep = 0; ep < hsotg->num_of_eps; ep++) s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); @@ -3626,16 +3631,16 @@ int s3c_hsotg_resume(struct dwc2_hsotg *hsotg) clk_enable(hsotg->clk); ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), - hsotg->supplies); - } - - s3c_hsotg_phy_enable(hsotg); + hsotg->supplies); - spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_core_init_disconnected(hsotg); - s3c_hsotg_core_connect(hsotg); - spin_unlock_irqrestore(&hsotg->lock, flags); + s3c_hsotg_phy_enable(hsotg); + spin_lock_irqsave(&hsotg->lock, flags); + s3c_hsotg_core_init_disconnected(hsotg); + if (hsotg->enabled) + s3c_hsotg_core_connect(hsotg); + spin_unlock_irqrestore(&hsotg->lock, flags); + } mutex_unlock(&hsotg->init_mutex); return ret; |