Commit 0de97425 authored by Al Cooper's avatar Al Cooper Committed by Felipe Balbi

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: default avatarAl Cooper <alcooperx@gmail.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 8ac1685b
...@@ -454,6 +454,7 @@ struct bdc { ...@@ -454,6 +454,7 @@ struct bdc {
* Func Wake packet every 2.5 secs. Refer to USB3 spec section 8.5.6.4 * Func Wake packet every 2.5 secs. Refer to USB3 spec section 8.5.6.4
*/ */
struct delayed_work func_wake_notify; struct delayed_work func_wake_notify;
struct clk *clk;
}; };
static inline u32 bdc_readl(void __iomem *base, u32 offset) static inline u32 bdc_readl(void __iomem *base, u32 offset)
......
...@@ -473,6 +473,8 @@ static int bdc_probe(struct platform_device *pdev) ...@@ -473,6 +473,8 @@ static int bdc_probe(struct platform_device *pdev)
if (!bdc) if (!bdc)
return -ENOMEM; return -ENOMEM;
bdc->clk = clk;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bdc->regs = devm_ioremap_resource(dev, res); bdc->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(bdc->regs)) { if (IS_ERR(bdc->regs)) {
...@@ -529,10 +531,43 @@ static int bdc_remove(struct platform_device *pdev) ...@@ -529,10 +531,43 @@ static int bdc_remove(struct platform_device *pdev)
dev_dbg(bdc->dev, "%s ()\n", __func__); dev_dbg(bdc->dev, "%s ()\n", __func__);
bdc_udc_exit(bdc); bdc_udc_exit(bdc);
bdc_hw_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; 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[] = { static const struct of_device_id bdc_of_match[] = {
{ .compatible = "brcm,bdc-v0.16" }, { .compatible = "brcm,bdc-v0.16" },
{ .compatible = "brcm,bdc" }, { .compatible = "brcm,bdc" },
...@@ -543,6 +578,7 @@ static struct platform_driver bdc_driver = { ...@@ -543,6 +578,7 @@ static struct platform_driver bdc_driver = {
.driver = { .driver = {
.name = BRCM_BDC_NAME, .name = BRCM_BDC_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &bdc_pm_ops,
.of_match_table = bdc_of_match, .of_match_table = bdc_of_match,
}, },
.probe = bdc_probe, .probe = bdc_probe,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment