diff options
author | Stefan Eichenberger <stefan.eichenberger@toradex.com> | 2023-05-24 17:59:09 +0200 |
---|---|---|
committer | Stefan Eichenberger <eichest@gmail.com> | 2023-05-24 18:24:44 +0200 |
commit | 4d948676c55ff543adcbd1b46714c9eae03a9052 (patch) | |
tree | c17963b5017f14eb4938efff31e887741e404251 | |
parent | a918eab4e464ddbdca90b4837ef9a3fc20ead058 (diff) |
usb: dwc3: imx8mp: add bus_early_clk
Add a bus_early_clk which is the same clock as for the usb controllers
child. This is necessary because the mentioned commit in fixes is
accessing registers which need the IMX8MP_CLK_HSI_AXI clock to be
enabled. Without this fix suspend/resume is not working properly if no
USB-devices are connected.
rtcwake -s 5 -m mem -d rtc1
It will try to wakeup after 5 seconds but hangs afterward.
Upstream-Status: Inappropriate [other]
This fix is only needed for the downstream kernel. In the upstream
kernel they added a power-domain for all hsio devices (usb, pcie, etc.)
and enable the clock there. However, backporting this solution would
probably cause more issues for now.
Fixes: cbd09f688623 ("usb: dwc3: imx8mp: Add support for setting SOC specific flags")
Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
-rw-r--r-- | drivers/usb/dwc3/dwc3-imx8mp.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c index cba3b79f7b40..1b3097eb0aed 100644 --- a/drivers/usb/dwc3/dwc3-imx8mp.c +++ b/drivers/usb/dwc3/dwc3-imx8mp.c @@ -55,6 +55,7 @@ struct dwc3_imx8mp { void __iomem *glue_base; struct clk *hsio_clk; struct clk *suspend_clk; + struct clk *bus_early_clk; int irq; bool pm_suspended; bool wakeup_pending; @@ -219,17 +220,31 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev) } request_bus_freq(BUS_FREQ_HIGH); + + dwc3_imx->bus_early_clk = devm_clk_get(dev, "bus_early_clk"); + if (IS_ERR(dwc3_imx->bus_early_clk)) { + err = PTR_ERR(dwc3_imx->bus_early_clk); + dev_err(dev, "Failed to get bus_early_clk clk, err=%d\n", err); + goto rel_high_bus; + } + + err = clk_prepare_enable(dwc3_imx->bus_early_clk); + if (err) { + dev_err(dev, "Failed to enable bus_early_clk clk, err=%d\n", err); + goto rel_high_bus; + } + dwc3_imx->hsio_clk = devm_clk_get(dev, "hsio"); if (IS_ERR(dwc3_imx->hsio_clk)) { err = PTR_ERR(dwc3_imx->hsio_clk); dev_err(dev, "Failed to get hsio clk, err=%d\n", err); - goto rel_high_bus; + goto disable_bus_early_clk_clk; } err = clk_prepare_enable(dwc3_imx->hsio_clk); if (err) { dev_err(dev, "Failed to enable hsio clk, err=%d\n", err); - return err; + goto disable_bus_early_clk_clk; } dwc3_imx->suspend_clk = devm_clk_get(dev, "suspend"); @@ -304,6 +319,8 @@ disable_clks: clk_disable_unprepare(dwc3_imx->suspend_clk); disable_hsio_clk: clk_disable_unprepare(dwc3_imx->hsio_clk); +disable_bus_early_clk_clk: + clk_disable_unprepare(dwc3_imx->bus_early_clk); rel_high_bus: release_bus_freq(BUS_FREQ_HIGH); @@ -320,6 +337,7 @@ static int dwc3_imx8mp_remove(struct platform_device *pdev) clk_disable_unprepare(dwc3_imx->suspend_clk); clk_disable_unprepare(dwc3_imx->hsio_clk); + clk_disable_unprepare(dwc3_imx->bus_early_clk); release_bus_freq(BUS_FREQ_HIGH); pm_runtime_disable(dev); pm_runtime_put_noidle(dev); @@ -392,6 +410,7 @@ static int __maybe_unused dwc3_imx8mp_pm_suspend(struct device *dev) clk_disable_unprepare(dwc3_imx->suspend_clk); clk_disable_unprepare(dwc3_imx->hsio_clk); + clk_disable_unprepare(dwc3_imx->bus_early_clk); dev_dbg(dev, "dwc3 imx8mp pm suspend.\n"); return ret; @@ -402,6 +421,10 @@ static int __maybe_unused dwc3_imx8mp_pm_resume(struct device *dev) struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); int ret; + ret = clk_prepare_enable(dwc3_imx->bus_early_clk); + if (ret) + return ret; + if (device_may_wakeup(dwc3_imx->dev)) { disable_irq_wake(dwc3_imx->irq); } else { |