summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Cooper <alcooperx@gmail.com>2017-07-19 15:11:45 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2017-08-15 14:18:58 +0300
commit0de9742514a05e5d9a06479bd98b9f894f85328e (patch)
tree11c463e88339ddb43596e4bbc12752173363873d
parent8ac1685bf911f70aea6de67b3db5674c3ea112f1 (diff)
downloadlinux-stable-0de9742514a05e5d9a06479bd98b9f894f85328e.tar.gz
linux-stable-0de9742514a05e5d9a06479bd98b9f894f85328e.tar.bz2
linux-stable-0de9742514a05e5d9a06479bd98b9f894f85328e.zip
usb: bdc: Add support for suspend/resume
Based on a previous commit by Danesh Petigara <dpetigara@broadcom.com> that added resume to solve the following problem: "The BDC driver will fail after resuming from S3 suspend and this will cause any upper layer gadget driver to fail." This commit also adds support for suspend and manages the clock during suspend/resume. Signed-off-by: Al Cooper <alcooperx@gmail.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc.h1
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c36
2 files changed, 37 insertions, 0 deletions
diff --git a/drivers/usb/gadget/udc/bdc/bdc.h b/drivers/usb/gadget/udc/bdc/bdc.h
index f657a4e81d05..67c5f23a2720 100644
--- a/drivers/usb/gadget/udc/bdc/bdc.h
+++ b/drivers/usb/gadget/udc/bdc/bdc.h
@@ -454,6 +454,7 @@ struct bdc {
* Func Wake packet every 2.5 secs. Refer to USB3 spec section 8.5.6.4
*/
struct delayed_work func_wake_notify;
+ struct clk *clk;
};
static inline u32 bdc_readl(void __iomem *base, u32 offset)
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c
index bc0729b84948..2690b6fc4f6f 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -473,6 +473,8 @@ static int bdc_probe(struct platform_device *pdev)
if (!bdc)
return -ENOMEM;
+ bdc->clk = clk;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bdc->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(bdc->regs)) {
@@ -529,10 +531,43 @@ static int bdc_remove(struct platform_device *pdev)
dev_dbg(bdc->dev, "%s ()\n", __func__);
bdc_udc_exit(bdc);
bdc_hw_exit(bdc);
+ clk_disable_unprepare(bdc->clk);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int bdc_suspend(struct device *dev)
+{
+ struct bdc *bdc = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(bdc->clk);
+ return 0;
+}
+
+static int bdc_resume(struct device *dev)
+{
+ struct bdc *bdc = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(bdc->clk);
+ if (ret) {
+ dev_err(bdc->dev, "err enabling the clock\n");
+ return ret;
+ }
+ ret = bdc_reinit(bdc);
+ if (ret) {
+ dev_err(bdc->dev, "err in bdc reinit\n");
+ return ret;
+ }
return 0;
}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(bdc_pm_ops, bdc_suspend,
+ bdc_resume);
+
static const struct of_device_id bdc_of_match[] = {
{ .compatible = "brcm,bdc-v0.16" },
{ .compatible = "brcm,bdc" },
@@ -543,6 +578,7 @@ static struct platform_driver bdc_driver = {
.driver = {
.name = BRCM_BDC_NAME,
.owner = THIS_MODULE,
+ .pm = &bdc_pm_ops,
.of_match_table = bdc_of_match,
},
.probe = bdc_probe,