From 4d948676c55ff543adcbd1b46714c9eae03a9052 Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Wed, 24 May 2023 17:59:09 +0200 Subject: 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 --- drivers/usb/dwc3/dwc3-imx8mp.c | 27 +++++++++++++++++++++++++-- 1 file 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 { -- cgit v1.2.3