On 21-09-27 01:40:39, Dmitry Osipenko wrote: > The Tegra USB controller belongs to the core power domain and we're going > to enable GENPD support for the core domain. Now USB controller must be > resumed using runtime PM API in order to initialize the USB power state. > We already support runtime PM for the CI device, but CI's PM is separated > from the RPM managed by tegra-usb driver. Add runtime PM and OPP support > to the driver. > > Signed-off-by: Dmitry Osipenko <digetx@xxxxxxxxx> > --- > drivers/usb/chipidea/ci_hdrc_tegra.c | 53 ++++++++++++++++++++++++---- > 1 file changed, 46 insertions(+), 7 deletions(-) > > diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c > index 60361141ac04..3142ef7ebe42 100644 > --- a/drivers/usb/chipidea/ci_hdrc_tegra.c > +++ b/drivers/usb/chipidea/ci_hdrc_tegra.c > @@ -7,6 +7,7 @@ > #include <linux/io.h> > #include <linux/module.h> > #include <linux/of_device.h> > +#include <linux/pm_runtime.h> > #include <linux/reset.h> > > #include <linux/usb.h> > @@ -15,6 +16,8 @@ > #include <linux/usb/of.h> > #include <linux/usb/phy.h> > > +#include <soc/tegra/common.h> > + > #include "../host/ehci.h" > > #include "ci.h" > @@ -278,6 +281,8 @@ static int tegra_usb_probe(struct platform_device *pdev) > if (!usb) > return -ENOMEM; > > + platform_set_drvdata(pdev, usb); > + > soc = of_device_get_match_data(&pdev->dev); > if (!soc) { > dev_err(&pdev->dev, "failed to match OF data\n"); > @@ -296,11 +301,17 @@ static int tegra_usb_probe(struct platform_device *pdev) > return err; > } > > - err = clk_prepare_enable(usb->clk); > - if (err < 0) { > - dev_err(&pdev->dev, "failed to enable clock: %d\n", err); > + err = devm_pm_runtime_enable(&pdev->dev); > + if (err) > + return err; > + > + err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); > + if (err) > + return err; > + > + err = pm_runtime_resume_and_get(&pdev->dev); > + if (err) > return err; > - } > > if (device_property_present(&pdev->dev, "nvidia,needs-double-reset")) > usb->needs_double_reset = true; > @@ -320,8 +331,6 @@ static int tegra_usb_probe(struct platform_device *pdev) > if (err) > goto fail_power_off; > > - platform_set_drvdata(pdev, usb); > - > /* setup and register ChipIdea HDRC device */ > usb->soc = soc; > usb->data.name = "tegra-usb"; > @@ -350,7 +359,8 @@ static int tegra_usb_probe(struct platform_device *pdev) > phy_shutdown: > usb_phy_shutdown(usb->phy); > fail_power_off: > - clk_disable_unprepare(usb->clk); > + pm_runtime_put(&pdev->dev); > + > return err; > } > > @@ -360,15 +370,44 @@ static int tegra_usb_remove(struct platform_device *pdev) > > ci_hdrc_remove_device(usb->dev); > usb_phy_shutdown(usb->phy); > + pm_runtime_put(&pdev->dev); > + > + return 0; > +} > + > +static int __maybe_unused tegra_usb_runtime_resume(struct device *dev) > +{ > + struct tegra_usb *usb = dev_get_drvdata(dev); > + int err; > + > + err = clk_prepare_enable(usb->clk); > + if (err < 0) { > + dev_err(dev, "failed to enable clock: %d\n", err); > + return err; > + } > + > + return 0; > +} > + > +static int __maybe_unused tegra_usb_runtime_suspend(struct device *dev) > +{ > + struct tegra_usb *usb = dev_get_drvdata(dev); > + > clk_disable_unprepare(usb->clk); > > return 0; > } > > +static const struct dev_pm_ops tegra_usb_pm = { > + SET_RUNTIME_PM_OPS(tegra_usb_runtime_suspend, tegra_usb_runtime_resume, > + NULL) > +}; > + > static struct platform_driver tegra_usb_driver = { > .driver = { > .name = "tegra-usb", > .of_match_table = tegra_usb_of_match, > + .pm = &tegra_usb_pm, > }, > .probe = tegra_usb_probe, > .remove = tegra_usb_remove, > -- > 2.32.0 > I got below compile error if only compile this file, I think previous patches should include the definition, if that, feel free to add my ack to this patch. Acked-by: Peter Chen <peter.chen@xxxxxxxxxx> drivers/usb/chipidea/ci_hdrc_tegra.c:308:8: error: implicit declaration of function ‘devm_tegra_core_dev_init_opp_table_common’; did you mean ‘devm_tegra_core_dev_init_opp_table’? [-Werror=implicit-function-declaration] 308 | err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | devm_tegra_core_dev_init_opp_table -- Thanks, Peter Chen