diff mbox

[v2] cpufreq: imx: update the clock switch flow to support imx6ul

Message ID 1441986065-8821-1-git-send-email-b51503@freescale.com (mailing list archive)
State Accepted, archived
Delegated to: Rafael Wysocki
Headers show

Commit Message

Bai Ping Sept. 11, 2015, 3:41 p.m. UTC
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>
---

change for v2:
  add the missed 'clk_put' in imx6q_cpufreq_remove().

 drivers/cpufreq/imx6q-cpufreq.c | 50 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)

Comments

Viresh Kumar Sept. 11, 2015, 8:07 a.m. UTC | #1
On 11-09-15, 23:41, Bai Ping wrote:
> +	if (of_machine_is_compatible("fsl,imx6ul")) {
> +		pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
> +		secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
> +		if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
> +			dev_err(cpu_dev, "failed to get clocks specific to imx6ul\n");
> +			ret = -ENOENT;
> +			goto put_clk;
> +		}
> +	}
> +
>  	arm_reg = regulator_get(cpu_dev, "arm");
>  	pu_reg = regulator_get_optional(cpu_dev, "pu");
>  	soc_reg = regulator_get(cpu_dev, "soc");
> @@ -331,6 +365,10 @@ put_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);
>  	return ret;
>  }

As part of good coding practices, you should free resources in the
reverse order to which they were allocated. The clocks don't follow
that, but its not a problem with just your patch. That's how it is
present today. Maybe you can write another patch to fix that.

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Bai Ping Sept. 11, 2015, 8:38 a.m. UTC | #2
On 2015/9/11 16:07, Viresh Kumar wrote:
> On 11-09-15, 23:41, Bai Ping wrote:
>> +	if (of_machine_is_compatible("fsl,imx6ul")) {
>> +		pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
>> +		secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
>> +		if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
>> +			dev_err(cpu_dev, "failed to get clocks specific to imx6ul\n");
>> +			ret = -ENOENT;
>> +			goto put_clk;
>> +		}
>> +	}
>> +
>>   	arm_reg = regulator_get(cpu_dev, "arm");
>>   	pu_reg = regulator_get_optional(cpu_dev, "pu");
>>   	soc_reg = regulator_get(cpu_dev, "soc");
>> @@ -331,6 +365,10 @@ put_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);
>>   	return ret;
>>   }
> As part of good coding practices, you should free resources in the
> reverse order to which they were allocated. The clocks don't follow
> that, but its not a problem with just your patch. That's how it is
> present today. Maybe you can write another patch to fix that.

thanks for your suggestion, I will pay more attention to it in future 
coding.

> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki Oct. 5, 2015, 8:49 p.m. UTC | #3
On Friday, September 11, 2015 04:38:05 PM Bai Ping wrote:
> 
> On 2015/9/11 16:07, Viresh Kumar wrote:
> > On 11-09-15, 23:41, Bai Ping wrote:
> >> +	if (of_machine_is_compatible("fsl,imx6ul")) {
> >> +		pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
> >> +		secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
> >> +		if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
> >> +			dev_err(cpu_dev, "failed to get clocks specific to imx6ul\n");
> >> +			ret = -ENOENT;
> >> +			goto put_clk;
> >> +		}
> >> +	}
> >> +
> >>   	arm_reg = regulator_get(cpu_dev, "arm");
> >>   	pu_reg = regulator_get_optional(cpu_dev, "pu");
> >>   	soc_reg = regulator_get(cpu_dev, "soc");
> >> @@ -331,6 +365,10 @@ put_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);
> >>   	return ret;
> >>   }
> > As part of good coding practices, you should free resources in the
> > reverse order to which they were allocated. The clocks don't follow
> > that, but its not a problem with just your patch. That's how it is
> > present today. Maybe you can write another patch to fix that.
> 
> thanks for your suggestion, I will pay more attention to it in future 
> coding.
> 
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

Patch applied, thanks!

Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 380a90d..9b4a7bd 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -30,6 +30,10 @@  static struct clk *pll1_sw_clk;
 static struct clk *step_clk;
 static struct clk *pll2_pfd2_396m_clk;
 
+/* clk used by i.MX6UL */
+static struct clk *pll2_bus_clk;
+static struct clk *secondary_sel_clk;
+
 static struct device *cpu_dev;
 static bool free_opp;
 static struct cpufreq_frequency_table *freq_table;
@@ -91,16 +95,36 @@  static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
 	 * The setpoints are selected per PLL/PDF frequencies, so we need to
 	 * reprogram PLL for frequency scaling.  The procedure of reprogramming
 	 * PLL1 is as below.
-	 *
+	 * For i.MX6UL, it has a secondary clk mux, the cpu frequency change
+	 * flow is slightly different from other i.MX6 OSC.
+	 * The cpu frequeny change flow for i.MX6(except i.MX6UL) is as below:
 	 *  - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it
 	 *  - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it
 	 *  - Disable pll2_pfd2_396m_clk
 	 */
-	clk_set_parent(step_clk, pll2_pfd2_396m_clk);
-	clk_set_parent(pll1_sw_clk, step_clk);
-	if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
-		clk_set_rate(pll1_sys_clk, new_freq * 1000);
+	if (of_machine_is_compatible("fsl,imx6ul")) {
+		/*
+		 * When changing pll1_sw_clk's parent to pll1_sys_clk,
+		 * CPU may run at higher than 528MHz, this will lead to
+		 * the system unstable if the voltage is lower than the
+		 * voltage of 528MHz, so lower the CPU frequency to one
+		 * half before changing CPU frequency.
+		 */
+		clk_set_rate(arm_clk, (old_freq >> 1) * 1000);
 		clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+		if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk))
+			clk_set_parent(secondary_sel_clk, pll2_bus_clk);
+		else
+			clk_set_parent(secondary_sel_clk, pll2_pfd2_396m_clk);
+		clk_set_parent(step_clk, secondary_sel_clk);
+		clk_set_parent(pll1_sw_clk, step_clk);
+	} else {
+		clk_set_parent(step_clk, pll2_pfd2_396m_clk);
+		clk_set_parent(pll1_sw_clk, step_clk);
+		if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
+			clk_set_rate(pll1_sys_clk, new_freq * 1000);
+			clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+		}
 	}
 
 	/* Ensure the arm clock divider is what we expect */
@@ -186,6 +210,16 @@  static int imx6q_cpufreq_probe(struct platform_device *pdev)
 		goto put_clk;
 	}
 
+	if (of_machine_is_compatible("fsl,imx6ul")) {
+		pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
+		secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
+		if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
+			dev_err(cpu_dev, "failed to get clocks specific to imx6ul\n");
+			ret = -ENOENT;
+			goto put_clk;
+		}
+	}
+
 	arm_reg = regulator_get(cpu_dev, "arm");
 	pu_reg = regulator_get_optional(cpu_dev, "pu");
 	soc_reg = regulator_get(cpu_dev, "soc");
@@ -331,6 +365,10 @@  put_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);
 	return ret;
 }
@@ -350,6 +388,8 @@  static int imx6q_cpufreq_remove(struct platform_device *pdev)
 	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;
 }