diff options
Diffstat (limited to 'drivers/usb/chipidea/ci_hdrc_tegra.c')
| -rw-r--r-- | drivers/usb/chipidea/ci_hdrc_tegra.c | 53 | 
1 files 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..a72a9474afea 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,14 @@ 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_tegra_core_dev_init_opp_table_common(&pdev->dev); +	if (err) +		return err; + +	pm_runtime_enable(&pdev->dev); +	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 +328,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 +356,9 @@ 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_sync_suspend(&pdev->dev); +	pm_runtime_force_suspend(&pdev->dev); +  	return err;  } @@ -360,15 +368,46 @@ static int tegra_usb_remove(struct platform_device *pdev)  	ci_hdrc_remove_device(usb->dev);  	usb_phy_shutdown(usb->phy); + +	pm_runtime_put_sync_suspend(&pdev->dev); +	pm_runtime_force_suspend(&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, |