aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/cdns3/cdns3-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/cdns3/cdns3-imx.c')
-rw-r--r--drivers/usb/cdns3/cdns3-imx.c60
1 files changed, 47 insertions, 13 deletions
diff --git a/drivers/usb/cdns3/cdns3-imx.c b/drivers/usb/cdns3/cdns3-imx.c
index 54a2d70a9c73..74e758dc0895 100644
--- a/drivers/usb/cdns3/cdns3-imx.c
+++ b/drivers/usb/cdns3/cdns3-imx.c
@@ -151,6 +151,7 @@ static int cdns_imx_platform_suspend(struct device *dev,
bool suspend, bool wakeup);
static struct cdns3_platform_data cdns_imx_pdata = {
.platform_suspend = cdns_imx_platform_suspend,
+ .quirks = CDNS3_DEFAULT_PM_RUNTIME_ALLOW,
};
static const struct of_dev_auxdata cdns_imx_auxdata[] = {
@@ -184,7 +185,11 @@ static int cdns_imx_probe(struct platform_device *pdev)
}
data->num_clks = ARRAY_SIZE(imx_cdns3_core_clks);
- data->clks = (struct clk_bulk_data *)imx_cdns3_core_clks;
+ data->clks = devm_kmemdup(dev, imx_cdns3_core_clks,
+ sizeof(imx_cdns3_core_clks), GFP_KERNEL);
+ if (!data->clks)
+ return -ENOMEM;
+
ret = devm_clk_bulk_get(dev, data->num_clks, data->clks);
if (ret)
return ret;
@@ -206,7 +211,6 @@ static int cdns_imx_probe(struct platform_device *pdev)
device_set_wakeup_capable(dev, true);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
- pm_runtime_forbid(dev);
return ret;
err:
@@ -214,20 +218,16 @@ err:
return ret;
}
-static int cdns_imx_remove_core(struct device *dev, void *data)
-{
- struct platform_device *pdev = to_platform_device(dev);
-
- platform_device_unregister(pdev);
-
- return 0;
-}
-
static int cdns_imx_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct cdns_imx *data = dev_get_drvdata(dev);
- device_for_each_child(dev, NULL, cdns_imx_remove_core);
+ pm_runtime_get_sync(dev);
+ of_platform_depopulate(dev);
+ clk_bulk_disable_unprepare(data->num_clks, data->clks);
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
platform_set_drvdata(pdev, NULL);
return 0;
@@ -250,7 +250,7 @@ static void cdns3_set_wakeup(struct cdns_imx *data, bool enable)
static int cdns_imx_platform_suspend(struct device *dev,
bool suspend, bool wakeup)
{
- struct cdns3 *cdns = dev_get_drvdata(dev);
+ struct cdns *cdns = dev_get_drvdata(dev);
struct device *parent = dev->parent;
struct cdns_imx *data = dev_get_drvdata(parent);
void __iomem *otg_regs = (void __iomem *)(cdns->otg_regs);
@@ -361,6 +361,39 @@ static int cdns_imx_suspend(struct device *dev)
return 0;
}
+
+
+/* Indicate if the controller was power lost before */
+static inline bool cdns_imx_is_power_lost(struct cdns_imx *data)
+{
+ u32 value;
+
+ value = cdns_imx_readl(data, USB3_CORE_CTRL1);
+ if ((value & SW_RESET_MASK) == ALL_SW_RESET)
+ return true;
+ else
+ return false;
+}
+
+static int __maybe_unused cdns_imx_system_resume(struct device *dev)
+{
+ struct cdns_imx *data = dev_get_drvdata(dev);
+ int ret;
+
+ ret = cdns_imx_resume(dev);
+ if (ret)
+ return ret;
+
+ if (cdns_imx_is_power_lost(data)) {
+ dev_dbg(dev, "resume from power lost\n");
+ ret = cdns_imx_noncore_init(data);
+ if (ret)
+ cdns_imx_suspend(dev);
+ }
+
+ return ret;
+}
+
#else
static int cdns_imx_platform_suspend(struct device *dev,
bool suspend, bool wakeup)
@@ -372,6 +405,7 @@ static int cdns_imx_platform_suspend(struct device *dev,
static const struct dev_pm_ops cdns_imx_pm_ops = {
SET_RUNTIME_PM_OPS(cdns_imx_suspend, cdns_imx_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(cdns_imx_suspend, cdns_imx_system_resume)
};
static const struct of_device_id cdns_imx_of_match[] = {