Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2332bd04 authored by Dong Aisheng's avatar Dong Aisheng Committed by Rafael J. Wysocki
Browse files

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: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarDong Aisheng <aisheng.dong@nxp.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 3eff5f67
Loading
Loading
Loading
Loading
+56 −69
Original line number Original line Diff line number Diff line
@@ -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,
/* clk used by i.MX6UL */
	/* MX6UL requires two more clks */
static struct clk *pll2_bus_clk;
	PLL2_BUS,
static struct clk *secondary_sel_clk;
	SECONDARY_SEL,
};
#define IMX6Q_CPUFREQ_CLK_NUM		5
#define IMX6UL_CPUFREQ_CLK_NUM		7

static int num_clks;
static struct clk_bulk_data clks[] = {
	{ .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 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
		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;
}
}