For devices which have 'assigned-performance-states' specified in DT, set the specified performance state during probe and drop it on remove. Also drop/set as part of runtime suspend/resume callbacks. Signed-off-by: Roja Rani Yarubandi <rojay@xxxxxxxxxxxxxx> --- drivers/i2c/busses/i2c-qcom-geni.c | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 046d241183c5..250773784631 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <linux/qcom-geni-se.h> #include <linux/spinlock.h> @@ -86,6 +87,7 @@ struct geni_i2c_dev { u32 clk_freq_out; const struct geni_i2c_clk_fld *clk_fld; int suspended; + unsigned int assigned_pstate; }; struct geni_i2c_err_log { @@ -497,6 +499,7 @@ static int geni_i2c_probe(struct platform_device *pdev) u32 proto, tx_depth; int ret; struct device *dev = &pdev->dev; + unsigned int assigned_pstate; gi2c = devm_kzalloc(dev, sizeof(*gi2c), GFP_KERNEL); if (!gi2c) @@ -520,6 +523,20 @@ static int geni_i2c_probe(struct platform_device *pdev) gi2c->clk_freq_out = KHZ(100); } + /* Set the assigned performance state */ + if (!of_property_read_u32(pdev->dev.of_node, "assigned-performance-states", + &assigned_pstate)) { + if (assigned_pstate) { + ret = dev_pm_genpd_set_performance_state(dev, + assigned_pstate); + if (ret) { + dev_err(dev, "Failed to set performance state\n"); + return ret; + } + gi2c->assigned_pstate = assigned_pstate; + } + } + if (has_acpi_companion(dev)) ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(dev)); @@ -616,10 +633,22 @@ static int geni_i2c_probe(struct platform_device *pdev) static int geni_i2c_remove(struct platform_device *pdev) { + int ret; + struct device *dev = &pdev->dev; struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev); i2c_del_adapter(&gi2c->adap); pm_runtime_disable(gi2c->se.dev); + + /* Drop the assigned performance state */ + if (gi2c->assigned_pstate) { + ret = dev_pm_genpd_set_performance_state(dev, 0); + if (ret) { + dev_err(dev, "Failed to set performance state\n"); + return ret; + } + } + return 0; } @@ -629,6 +658,16 @@ static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev) struct geni_i2c_dev *gi2c = dev_get_drvdata(dev); disable_irq(gi2c->irq); + + /* Drop the assigned performance state */ + if (gi2c->assigned_pstate) { + ret = dev_pm_genpd_set_performance_state(dev, 0); + if (ret) { + dev_err(dev, "Failed to set performance state\n"); + return ret; + } + } + ret = geni_se_resources_off(&gi2c->se); if (ret) { enable_irq(gi2c->irq); @@ -654,6 +693,16 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev) if (ret) return ret; + /* Set the assigned performance state */ + if (gi2c->assigned_pstate) { + ret = dev_pm_genpd_set_performance_state(dev, + gi2c->assigned_pstate); + if (ret) { + dev_err(dev, "Failed to set performance state\n"); + return ret; + } + } + enable_irq(gi2c->irq); gi2c->suspended = 0; return 0; -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation