summaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/s3c-hsotg.c
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2014-02-28 13:06:11 +0100
committerFelipe Balbi <balbi@ti.com>2014-03-05 21:40:06 +0100
commitb83e333a4d03b73eb5ea7fc1cb86683c2575b237 (patch)
tree4346066f0dfd5b6fdaaeeb1fd257d6a311046e23 /drivers/usb/gadget/s3c-hsotg.c
parentusb: musb: musb_cppi41: Dont reprogram DMA if tear down is initiated (diff)
downloadlinux-b83e333a4d03b73eb5ea7fc1cb86683c2575b237.tar.xz
linux-b83e333a4d03b73eb5ea7fc1cb86683c2575b237.zip
usb: gadget: s3c-hsotg: add proper suspend/resume support
This patch adds suspend/resume support to s3c-hsotg driver. It makes UDC driver more power efficient. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Robert Baldyga <r.baldyga@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/s3c-hsotg.c')
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 99c8e3ca6a3c..2a9cb674926a 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -3774,10 +3774,55 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
return 0;
}
-#if 1
-#define s3c_hsotg_suspend NULL
-#define s3c_hsotg_resume NULL
-#endif
+static int s3c_hsotg_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
+ unsigned long flags;
+ int ret = 0;
+
+ if (hsotg->driver)
+ dev_info(hsotg->dev, "suspending usb gadget %s\n",
+ hsotg->driver->driver.name);
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+ s3c_hsotg_disconnect(hsotg);
+ s3c_hsotg_phy_disable(hsotg);
+ hsotg->gadget.speed = USB_SPEED_UNKNOWN;
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+
+ if (hsotg->driver) {
+ int ep;
+ for (ep = 0; ep < hsotg->num_of_eps; ep++)
+ s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+ }
+
+ return ret;
+}
+
+static int s3c_hsotg_resume(struct platform_device *pdev)
+{
+ struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
+ unsigned long flags;
+ int ret = 0;
+
+ if (hsotg->driver) {
+ dev_info(hsotg->dev, "resuming usb gadget %s\n",
+ hsotg->driver->driver.name);
+ ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+ }
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+ hsotg->last_rst = jiffies;
+ s3c_hsotg_phy_enable(hsotg);
+ s3c_hsotg_core_init(hsotg);
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+
+ return ret;
+}
#ifdef CONFIG_OF
static const struct of_device_id s3c_hsotg_of_ids[] = {