cpufreq: imx6q: switch to Use clk_bulk_get() to refine clk operations
Use clk_bulk_get() to simplify the driver's clocks handling. Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
3eff5f67a2
commit
2332bd0419
|
@ -25,15 +25,29 @@ static struct regulator *arm_reg;
|
||||||
static struct regulator *pu_reg;
|
static struct regulator *pu_reg;
|
||||||
static struct regulator *soc_reg;
|
static struct regulator *soc_reg;
|
||||||
|
|
||||||
static struct clk *arm_clk;
|
enum IMX6_CPUFREQ_CLKS {
|
||||||
static struct clk *pll1_sys_clk;
|
ARM,
|
||||||
static struct clk *pll1_sw_clk;
|
PLL1_SYS,
|
||||||
static struct clk *step_clk;
|
STEP,
|
||||||
static struct clk *pll2_pfd2_396m_clk;
|
PLL1_SW,
|
||||||
|
PLL2_PFD2_396M,
|
||||||
|
/* MX6UL requires two more clks */
|
||||||
|
PLL2_BUS,
|
||||||
|
SECONDARY_SEL,
|
||||||
|
};
|
||||||
|
#define IMX6Q_CPUFREQ_CLK_NUM 5
|
||||||
|
#define IMX6UL_CPUFREQ_CLK_NUM 7
|
||||||
|
|
||||||
/* clk used by i.MX6UL */
|
static int num_clks;
|
||||||
static struct clk *pll2_bus_clk;
|
static struct clk_bulk_data clks[] = {
|
||||||
static struct clk *secondary_sel_clk;
|
{ .id = "arm" },
|
||||||
|
{ .id = "pll1_sys" },
|
||||||
|
{ .id = "step" },
|
||||||
|
{ .id = "pll1_sw" },
|
||||||
|
{ .id = "pll2_pfd2_396m" },
|
||||||
|
{ .id = "pll2_bus" },
|
||||||
|
{ .id = "secondary_sel" },
|
||||||
|
};
|
||||||
|
|
||||||
static struct device *cpu_dev;
|
static struct device *cpu_dev;
|
||||||
static bool free_opp;
|
static bool free_opp;
|
||||||
|
@ -53,7 +67,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||||
|
|
||||||
new_freq = freq_table[index].frequency;
|
new_freq = freq_table[index].frequency;
|
||||||
freq_hz = new_freq * 1000;
|
freq_hz = new_freq * 1000;
|
||||||
old_freq = clk_get_rate(arm_clk) / 1000;
|
old_freq = clk_get_rate(clks[ARM].clk) / 1000;
|
||||||
|
|
||||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
|
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
|
||||||
if (IS_ERR(opp)) {
|
if (IS_ERR(opp)) {
|
||||||
|
@ -112,29 +126,31 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||||
* voltage of 528MHz, so lower the CPU frequency to one
|
* voltage of 528MHz, so lower the CPU frequency to one
|
||||||
* half before changing CPU frequency.
|
* half before changing CPU frequency.
|
||||||
*/
|
*/
|
||||||
clk_set_rate(arm_clk, (old_freq >> 1) * 1000);
|
clk_set_rate(clks[ARM].clk, (old_freq >> 1) * 1000);
|
||||||
clk_set_parent(pll1_sw_clk, pll1_sys_clk);
|
clk_set_parent(clks[PLL1_SW].clk, clks[PLL1_SYS].clk);
|
||||||
if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk))
|
if (freq_hz > clk_get_rate(clks[PLL2_PFD2_396M].clk))
|
||||||
clk_set_parent(secondary_sel_clk, pll2_bus_clk);
|
clk_set_parent(clks[SECONDARY_SEL].clk,
|
||||||
|
clks[PLL2_BUS].clk);
|
||||||
else
|
else
|
||||||
clk_set_parent(secondary_sel_clk, pll2_pfd2_396m_clk);
|
clk_set_parent(clks[SECONDARY_SEL].clk,
|
||||||
clk_set_parent(step_clk, secondary_sel_clk);
|
clks[PLL2_PFD2_396M].clk);
|
||||||
clk_set_parent(pll1_sw_clk, step_clk);
|
clk_set_parent(clks[STEP].clk, clks[SECONDARY_SEL].clk);
|
||||||
|
clk_set_parent(clks[PLL1_SW].clk, clks[STEP].clk);
|
||||||
} else {
|
} else {
|
||||||
clk_set_parent(step_clk, pll2_pfd2_396m_clk);
|
clk_set_parent(clks[STEP].clk, clks[PLL2_PFD2_396M].clk);
|
||||||
clk_set_parent(pll1_sw_clk, step_clk);
|
clk_set_parent(clks[PLL1_SW].clk, clks[STEP].clk);
|
||||||
if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
|
if (freq_hz > clk_get_rate(clks[PLL2_PFD2_396M].clk)) {
|
||||||
clk_set_rate(pll1_sys_clk, new_freq * 1000);
|
clk_set_rate(clks[PLL1_SYS].clk, new_freq * 1000);
|
||||||
clk_set_parent(pll1_sw_clk, pll1_sys_clk);
|
clk_set_parent(clks[PLL1_SW].clk, clks[PLL1_SYS].clk);
|
||||||
} else {
|
} else {
|
||||||
/* pll1_sys needs to be enabled for divider rate change to work. */
|
/* pll1_sys needs to be enabled for divider rate change to work. */
|
||||||
pll1_sys_temp_enabled = true;
|
pll1_sys_temp_enabled = true;
|
||||||
clk_prepare_enable(pll1_sys_clk);
|
clk_prepare_enable(clks[PLL1_SYS].clk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure the arm clock divider is what we expect */
|
/* Ensure the arm clock divider is what we expect */
|
||||||
ret = clk_set_rate(arm_clk, new_freq * 1000);
|
ret = clk_set_rate(clks[ARM].clk, new_freq * 1000);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
|
dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
|
||||||
regulator_set_voltage_tol(arm_reg, volt_old, 0);
|
regulator_set_voltage_tol(arm_reg, volt_old, 0);
|
||||||
|
@ -143,7 +159,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||||
|
|
||||||
/* PLL1 is only needed until after ARM-PODF is set. */
|
/* PLL1 is only needed until after ARM-PODF is set. */
|
||||||
if (pll1_sys_temp_enabled)
|
if (pll1_sys_temp_enabled)
|
||||||
clk_disable_unprepare(pll1_sys_clk);
|
clk_disable_unprepare(clks[PLL1_SYS].clk);
|
||||||
|
|
||||||
/* scaling down? scale voltage after frequency */
|
/* scaling down? scale voltage after frequency */
|
||||||
if (new_freq < old_freq) {
|
if (new_freq < old_freq) {
|
||||||
|
@ -174,7 +190,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
policy->clk = arm_clk;
|
policy->clk = clks[ARM].clk;
|
||||||
ret = cpufreq_generic_init(policy, freq_table, transition_latency);
|
ret = cpufreq_generic_init(policy, freq_table, transition_latency);
|
||||||
policy->suspend_freq = policy->max;
|
policy->suspend_freq = policy->max;
|
||||||
|
|
||||||
|
@ -266,28 +282,15 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (of_machine_is_compatible("fsl,imx6ul") ||
|
if (of_machine_is_compatible("fsl,imx6ul") ||
|
||||||
of_machine_is_compatible("fsl,imx6ull")) {
|
of_machine_is_compatible("fsl,imx6ull"))
|
||||||
pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
|
num_clks = IMX6UL_CPUFREQ_CLK_NUM;
|
||||||
secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
|
else
|
||||||
if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
|
num_clks = IMX6Q_CPUFREQ_CLK_NUM;
|
||||||
dev_err(cpu_dev, "failed to get clocks specific to imx6ul\n");
|
|
||||||
ret = -ENOENT;
|
ret = clk_bulk_get(cpu_dev, num_clks, clks);
|
||||||
goto put_clk;
|
if (ret)
|
||||||
}
|
goto put_node;
|
||||||
}
|
|
||||||
|
|
||||||
arm_reg = regulator_get(cpu_dev, "arm");
|
arm_reg = regulator_get(cpu_dev, "arm");
|
||||||
pu_reg = regulator_get_optional(cpu_dev, "pu");
|
pu_reg = regulator_get_optional(cpu_dev, "pu");
|
||||||
|
@ -424,22 +427,11 @@ put_reg:
|
||||||
regulator_put(pu_reg);
|
regulator_put(pu_reg);
|
||||||
if (!IS_ERR(soc_reg))
|
if (!IS_ERR(soc_reg))
|
||||||
regulator_put(soc_reg);
|
regulator_put(soc_reg);
|
||||||
put_clk:
|
|
||||||
if (!IS_ERR(arm_clk))
|
clk_bulk_put(num_clks, clks);
|
||||||
clk_put(arm_clk);
|
put_node:
|
||||||
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);
|
|
||||||
if (!IS_ERR(pll2_bus_clk))
|
|
||||||
clk_put(pll2_bus_clk);
|
|
||||||
if (!IS_ERR(secondary_sel_clk))
|
|
||||||
clk_put(secondary_sel_clk);
|
|
||||||
of_node_put(np);
|
of_node_put(np);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,13 +445,8 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev)
|
||||||
if (!IS_ERR(pu_reg))
|
if (!IS_ERR(pu_reg))
|
||||||
regulator_put(pu_reg);
|
regulator_put(pu_reg);
|
||||||
regulator_put(soc_reg);
|
regulator_put(soc_reg);
|
||||||
clk_put(arm_clk);
|
|
||||||
clk_put(pll1_sys_clk);
|
clk_bulk_put(num_clks, clks);
|
||||||
clk_put(pll1_sw_clk);
|
|
||||||
clk_put(step_clk);
|
|
||||||
clk_put(pll2_pfd2_396m_clk);
|
|
||||||
clk_put(pll2_bus_clk);
|
|
||||||
clk_put(secondary_sel_clk);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue