On 20-06-09 19:12:42, Li Jun wrote: > + > + pm_runtime_set_active(dev); > + pm_runtime_enable(dev); > + err = pm_runtime_get_sync(dev); > + if (err < 0) > + goto disable_rpm; > + > + dwc3_np = of_get_child_by_name(node, "dwc3"); > + if (!dwc3_np) { > + dev_err(dev, "failed to find dwc3 core child\n"); > + goto disable_rpm; > + } You may call of_node_put() for dwc3_np after using. > + > + err = of_platform_populate(node, NULL, NULL, dev); > + if (err) { > + dev_err(&pdev->dev, "failed to create dwc3 core\n"); > + goto disable_rpm; > + } > + > + dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np); > + if (!dwc3_imx->dwc3) { > + dev_err(dev, "failed to get dwc3 platform device\n"); > + err = -ENODEV; > + goto depopulate; > + } > + > + device_set_wakeup_capable(dev, true); > + pm_runtime_put(dev); > + > + return 0; > + > +depopulate: > + of_platform_depopulate(dev); > +disable_rpm: > + pm_runtime_disable(dev); > + pm_runtime_put_noidle(dev); > +disable_clks: > + clk_disable_unprepare(dwc3_imx->clks[dwc3_imx->num_clks-1].clk); > +disable_bulk_clk: > + clk_bulk_disable_unprepare(dwc3_imx->num_clks, dwc3_imx->clks); > + > + return err; > +} > + > +static int dwc3_imx8mp_remove(struct platform_device *pdev) > +{ > + struct dwc3_imx8mp *dwc3_imx = platform_get_drvdata(pdev); > + struct device *dev = &pdev->dev; > + > + pm_runtime_get_sync(dev); > + of_platform_depopulate(dev); > + > + clk_bulk_disable_unprepare(dwc3_imx->num_clks, dwc3_imx->clks); > + clk_disable_unprepare(dwc3_imx->clks[dwc3_imx->num_clks-1].clk); > + > + pm_runtime_disable(dev); > + pm_runtime_put_noidle(dev); > + platform_set_drvdata(pdev, NULL); > + > + return 0; > +} > + > +static int dwc3_imx8mp_suspend(struct dwc3_imx8mp *dwc3_imx, pm_message_t msg) > +{ > + if (dwc3_imx->pm_suspended) > + return 0; > + > + /* Wakeup enable */ > + if (PMSG_IS_AUTO(msg) || device_may_wakeup(dwc3_imx->dev)) > + dwc3_imx8mp_wakeup_enable(dwc3_imx); > + > + clk_bulk_disable_unprepare(dwc3_imx->num_clks, dwc3_imx->clks); > + dwc3_imx->pm_suspended = true; > + > + return 0; > +} > + > +static int dwc3_imx8mp_resume(struct dwc3_imx8mp *dwc3_imx, pm_message_t msg) > +{ > + struct dwc3 *dwc = platform_get_drvdata(dwc3_imx->dwc3); > + int ret = 0; > + > + if (!dwc3_imx->pm_suspended) > + return 0; > + > + ret = clk_bulk_prepare_enable(dwc3_imx->num_clks, dwc3_imx->clks); > + if (ret) > + return ret; > + > + /* Wakeup disable */ > + dwc3_imx8mp_wakeup_disable(dwc3_imx); > + dwc3_imx->pm_suspended = false; > + > + if (dwc3_imx->wakeup_pending) { > + dwc3_imx->wakeup_pending = false; > + if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE) { > + pm_runtime_mark_last_busy(dwc->dev); > + pm_runtime_put_autosuspend(dwc->dev); > + } else { > + /* > + * Add wait for xhci switch from suspend > + * clock to normal clock to detect connection. > + */ > + usleep_range(9000, 10000); > + } > + enable_irq(dwc3_imx->irq); > + } > + > + return ret; > +} > + You may need to add __maybe_unused for above two functions. Peter > +static int __maybe_unused dwc3_imx8mp_pm_suspend(struct device *dev) > +{ > + struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); > + int ret; > + > + ret = dwc3_imx8mp_suspend(dwc3_imx, PMSG_SUSPEND); > + > + if (device_may_wakeup(dwc3_imx->dev)) > + enable_irq_wake(dwc3_imx->irq); > + > + dev_dbg(dev, "dwc3 imx8mp pm suspend.\n"); > + > + return ret; > +} > + > +static int __maybe_unused dwc3_imx8mp_pm_resume(struct device *dev) > +{ > + struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); > + int ret; > + > + if (device_may_wakeup(dwc3_imx->dev)) > + disable_irq_wake(dwc3_imx->irq); > + > + ret = dwc3_imx8mp_resume(dwc3_imx, PMSG_RESUME); > + > + pm_runtime_disable(dev); > + pm_runtime_set_active(dev); > + pm_runtime_enable(dev); > + > + dev_dbg(dev, "dwc3 imx8mp pm resume.\n"); > + > + return ret; > +} > + > +static int __maybe_unused dwc3_imx8mp_runtime_suspend(struct device *dev) > +{ > + struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); > + > + dev_dbg(dev, "dwc3 imx8mp runtime suspend.\n"); > + > + return dwc3_imx8mp_suspend(dwc3_imx, PMSG_AUTO_SUSPEND); > +} > + > +static int __maybe_unused dwc3_imx8mp_runtime_resume(struct device *dev) > +{ > + struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); > + > + dev_dbg(dev, "dwc3 imx8mp runtime resume.\n"); > + > + return dwc3_imx8mp_resume(dwc3_imx, PMSG_AUTO_RESUME); > +} > + > +static const struct dev_pm_ops dwc3_imx8mp_dev_pm_ops = { > + SET_SYSTEM_SLEEP_PM_OPS(dwc3_imx8mp_pm_suspend, dwc3_imx8mp_pm_resume) > + SET_RUNTIME_PM_OPS(dwc3_imx8mp_runtime_suspend, > + dwc3_imx8mp_runtime_resume, NULL) > +}; > + > +static const struct of_device_id dwc3_imx8mp_of_match[] = { > + { .compatible = "fsl,imx8mp-dwc3", }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, dwc3_imx8mp_of_match); > + > +static struct platform_driver dwc3_imx8mp_driver = { > + .probe = dwc3_imx8mp_probe, > + .remove = dwc3_imx8mp_remove, > + .driver = { > + .name = "imx8mp-dwc3", > + .pm = &dwc3_imx8mp_dev_pm_ops, > + .of_match_table = dwc3_imx8mp_of_match, > + }, > +}; > + > +module_platform_driver(dwc3_imx8mp_driver); > + > +MODULE_ALIAS("platform:imx8mp-dwc3"); > +MODULE_AUTHOR("jun.li@xxxxxxx"); > +MODULE_LICENSE("GPL v2"); > +MODULE_DESCRIPTION("DesignWare USB3 imx8mp Glue Layer"); > -- > 2.7.4 > -- Thanks, Peter Chen