summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2014-05-14 18:02:23 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-17 01:32:15 +0200
commitf8269c19222550dd357e515673f628071880d64c (patch)
tree265159658442e42a23a28952651eb601f8965523
parente54173b4ed0fca1a5dce9911f54e71f2917d4869 (diff)
downloadlinux-stable-f8269c19222550dd357e515673f628071880d64c.tar.gz
linux-stable-f8269c19222550dd357e515673f628071880d64c.tar.bz2
linux-stable-f8269c19222550dd357e515673f628071880d64c.zip
cpufreq: imx6q: Drop devm_clk/regulator_get usage
This driver is using devres managed calls incorrectly, giving the cpu0 device as first parameter instead of the cpufreq platform device. This results in resources not being freed if the cpufreq platform device is unbound, for example if probing has to be deferred for a missing regulator. Supporting probe deferral properly is a prerequisite to enabling the internal LDO bypass on i.MX6 and regulating the CPU voltage with an external regulator. Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Shawn Guo <shawn.guo@freescale.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index e27fca86fe4f..92a82ec763c6 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -170,25 +170,25 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
return -ENOENT;
}
- arm_clk = devm_clk_get(cpu_dev, "arm");
- pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys");
- pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw");
- step_clk = devm_clk_get(cpu_dev, "step");
- pll2_pfd2_396m_clk = devm_clk_get(cpu_dev, "pll2_pfd2_396m");
+ arm_clk = clk_get(cpu_dev, "arm");
+ pll1_sys_clk = clk_get(cpu_dev, "pll1_sys");
+ pll1_sw_clk = clk_get(cpu_dev, "pll1_sw");
+ step_clk = clk_get(cpu_dev, "step");
+ pll2_pfd2_396m_clk = clk_get(cpu_dev, "pll2_pfd2_396m");
if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) ||
IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) {
dev_err(cpu_dev, "failed to get clocks\n");
ret = -ENOENT;
- goto put_node;
+ goto put_clk;
}
- arm_reg = devm_regulator_get(cpu_dev, "arm");
- pu_reg = devm_regulator_get(cpu_dev, "pu");
- soc_reg = devm_regulator_get(cpu_dev, "soc");
+ arm_reg = regulator_get(cpu_dev, "arm");
+ pu_reg = regulator_get(cpu_dev, "pu");
+ soc_reg = regulator_get(cpu_dev, "soc");
if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) {
dev_err(cpu_dev, "failed to get regulators\n");
ret = -ENOENT;
- goto put_node;
+ goto put_reg;
}
/*
@@ -201,21 +201,21 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
ret = of_init_opp_table(cpu_dev);
if (ret < 0) {
dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
- goto put_node;
+ goto put_reg;
}
num = dev_pm_opp_get_opp_count(cpu_dev);
if (num < 0) {
ret = num;
dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
- goto put_node;
+ goto put_reg;
}
}
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
if (ret) {
dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
- goto put_node;
+ goto put_reg;
}
/* Make imx6_soc_volt array's size same as arm opp number */
@@ -301,7 +301,24 @@ soc_opp_out:
free_freq_table:
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
-put_node:
+put_reg:
+ if (!IS_ERR(arm_reg))
+ regulator_put(arm_reg);
+ if (!IS_ERR(pu_reg))
+ regulator_put(pu_reg);
+ if (!IS_ERR(soc_reg))
+ regulator_put(soc_reg);
+put_clk:
+ if (!IS_ERR(arm_clk))
+ clk_put(arm_clk);
+ if (!IS_ERR(pll1_sys_clk))
+ clk_put(pll1_sys_clk);
+ if (!IS_ERR(pll1_sw_clk))
+ clk_put(pll1_sw_clk);
+ if (!IS_ERR(step_clk))
+ clk_put(step_clk);
+ if (!IS_ERR(pll2_pfd2_396m_clk))
+ clk_put(pll2_pfd2_396m_clk);
of_node_put(np);
return ret;
}
@@ -310,6 +327,14 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev)
{
cpufreq_unregister_driver(&imx6q_cpufreq_driver);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+ regulator_put(arm_reg);
+ regulator_put(pu_reg);
+ regulator_put(soc_reg);
+ clk_put(arm_clk);
+ clk_put(pll1_sys_clk);
+ clk_put(pll1_sw_clk);
+ clk_put(step_clk);
+ clk_put(pll2_pfd2_396m_clk);
return 0;
}