diff options
author | Bai Ping <b51503@freescale.com> | 2015-09-11 11:41:05 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-09-25 21:02:11 -0400 |
commit | a35fc5a33b62a6c658b8ffe7544c966c1776d128 (patch) | |
tree | 14b6d68b27e3d3019da53a7915879473d44484c0 | |
parent | febf63cf616083e9a4ee05e2c28163b074890f36 (diff) |
cpufreq: imx: update the clock switch flow to support imx6ul
For i.MX6UL, the clock switch flow is slightly different from
other i.MX6 SOCs. It has a 'secondary_sel' clk that will be used
when the CPU freq is higher than 396MHz. So the clock switch flow in
'set_target' callback need to update to support i.MX6UL in the common
i.MX6 SOC cpufreq driver.
Signed-off-by: Bai Ping <b51503@freescale.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/cpufreq/imx6q-cpufreq.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 380a90d3c57e..9b4a7bd04dea 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c | |||
@@ -30,6 +30,10 @@ static struct clk *pll1_sw_clk; | |||
30 | static struct clk *step_clk; | 30 | static struct clk *step_clk; |
31 | static struct clk *pll2_pfd2_396m_clk; | 31 | static struct clk *pll2_pfd2_396m_clk; |
32 | 32 | ||
33 | /* clk used by i.MX6UL */ | ||
34 | static struct clk *pll2_bus_clk; | ||
35 | static struct clk *secondary_sel_clk; | ||
36 | |||
33 | static struct device *cpu_dev; | 37 | static struct device *cpu_dev; |
34 | static bool free_opp; | 38 | static bool free_opp; |
35 | static struct cpufreq_frequency_table *freq_table; | 39 | static struct cpufreq_frequency_table *freq_table; |
@@ -91,16 +95,36 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) | |||
91 | * The setpoints are selected per PLL/PDF frequencies, so we need to | 95 | * The setpoints are selected per PLL/PDF frequencies, so we need to |
92 | * reprogram PLL for frequency scaling. The procedure of reprogramming | 96 | * reprogram PLL for frequency scaling. The procedure of reprogramming |
93 | * PLL1 is as below. | 97 | * PLL1 is as below. |
94 | * | 98 | * For i.MX6UL, it has a secondary clk mux, the cpu frequency change |
99 | * flow is slightly different from other i.MX6 OSC. | ||
100 | * The cpu frequeny change flow for i.MX6(except i.MX6UL) is as below: | ||
95 | * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it | 101 | * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it |
96 | * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it | 102 | * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it |
97 | * - Disable pll2_pfd2_396m_clk | 103 | * - Disable pll2_pfd2_396m_clk |
98 | */ | 104 | */ |
99 | clk_set_parent(step_clk, pll2_pfd2_396m_clk); | 105 | if (of_machine_is_compatible("fsl,imx6ul")) { |
100 | clk_set_parent(pll1_sw_clk, step_clk); | 106 | /* |
101 | if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { | 107 | * When changing pll1_sw_clk's parent to pll1_sys_clk, |
102 | clk_set_rate(pll1_sys_clk, new_freq * 1000); | 108 | * CPU may run at higher than 528MHz, this will lead to |
109 | * the system unstable if the voltage is lower than the | ||
110 | * voltage of 528MHz, so lower the CPU frequency to one | ||
111 | * half before changing CPU frequency. | ||
112 | */ | ||
113 | clk_set_rate(arm_clk, (old_freq >> 1) * 1000); | ||
103 | clk_set_parent(pll1_sw_clk, pll1_sys_clk); | 114 | clk_set_parent(pll1_sw_clk, pll1_sys_clk); |
115 | if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) | ||
116 | clk_set_parent(secondary_sel_clk, pll2_bus_clk); | ||
117 | else | ||
118 | clk_set_parent(secondary_sel_clk, pll2_pfd2_396m_clk); | ||
119 | clk_set_parent(step_clk, secondary_sel_clk); | ||
120 | clk_set_parent(pll1_sw_clk, step_clk); | ||
121 | } else { | ||
122 | clk_set_parent(step_clk, pll2_pfd2_396m_clk); | ||
123 | clk_set_parent(pll1_sw_clk, step_clk); | ||
124 | if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { | ||
125 | clk_set_rate(pll1_sys_clk, new_freq * 1000); | ||
126 | clk_set_parent(pll1_sw_clk, pll1_sys_clk); | ||
127 | } | ||
104 | } | 128 | } |
105 | 129 | ||
106 | /* Ensure the arm clock divider is what we expect */ | 130 | /* Ensure the arm clock divider is what we expect */ |
@@ -186,6 +210,16 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) | |||
186 | goto put_clk; | 210 | goto put_clk; |
187 | } | 211 | } |
188 | 212 | ||
213 | if (of_machine_is_compatible("fsl,imx6ul")) { | ||
214 | pll2_bus_clk = clk_get(cpu_dev, "pll2_bus"); | ||
215 | secondary_sel_clk = clk_get(cpu_dev, "secondary_sel"); | ||
216 | if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) { | ||
217 | dev_err(cpu_dev, "failed to get clocks specific to imx6ul\n"); | ||
218 | ret = -ENOENT; | ||
219 | goto put_clk; | ||
220 | } | ||
221 | } | ||
222 | |||
189 | arm_reg = regulator_get(cpu_dev, "arm"); | 223 | arm_reg = regulator_get(cpu_dev, "arm"); |
190 | pu_reg = regulator_get_optional(cpu_dev, "pu"); | 224 | pu_reg = regulator_get_optional(cpu_dev, "pu"); |
191 | soc_reg = regulator_get(cpu_dev, "soc"); | 225 | soc_reg = regulator_get(cpu_dev, "soc"); |
@@ -331,6 +365,10 @@ put_clk: | |||
331 | clk_put(step_clk); | 365 | clk_put(step_clk); |
332 | if (!IS_ERR(pll2_pfd2_396m_clk)) | 366 | if (!IS_ERR(pll2_pfd2_396m_clk)) |
333 | clk_put(pll2_pfd2_396m_clk); | 367 | clk_put(pll2_pfd2_396m_clk); |
368 | if (!IS_ERR(pll2_bus_clk)) | ||
369 | clk_put(pll2_bus_clk); | ||
370 | if (!IS_ERR(secondary_sel_clk)) | ||
371 | clk_put(secondary_sel_clk); | ||
334 | of_node_put(np); | 372 | of_node_put(np); |
335 | return ret; | 373 | return ret; |
336 | } | 374 | } |
@@ -350,6 +388,8 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev) | |||
350 | clk_put(pll1_sw_clk); | 388 | clk_put(pll1_sw_clk); |
351 | clk_put(step_clk); | 389 | clk_put(step_clk); |
352 | clk_put(pll2_pfd2_396m_clk); | 390 | clk_put(pll2_pfd2_396m_clk); |
391 | clk_put(pll2_bus_clk); | ||
392 | clk_put(secondary_sel_clk); | ||
353 | 393 | ||
354 | return 0; | 394 | return 0; |
355 | } | 395 | } |