aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/imx6q-cpufreq.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-08-14 10:08:24 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-10-30 19:11:08 -0400
commitd4019f0a92ab802f385cc9c8ad3ab7b5449712cb (patch)
treeebd06695585e457ae1bf219653452b111e7508db /drivers/cpufreq/imx6q-cpufreq.c
parent7dbf694db6ac7c759599316d50d7050efcbd512a (diff)
cpufreq: move freq change notifications to cpufreq core
Most of the drivers do following in their ->target_index() routines: struct cpufreq_freqs freqs; freqs.old = old freq... freqs.new = new freq... cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); /* Change rate here */ cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); This is replicated over all cpufreq drivers today and there doesn't exists a good enough reason why this shouldn't be moved to cpufreq core instead. There are few special cases though, like exynos5440, which doesn't do everything on the call to ->target_index() routine and call some kind of bottom halves for doing this work, work/tasklet/etc.. They may continue doing notification from their own code as flag: CPUFREQ_ASYNC_NOTIFICATION is already set for them. All drivers are also modified in this patch to avoid breaking 'git bisect', as double notification would happen otherwise. Acked-by: Hans-Christian Egtvedt <egtvedt@samfundet.no> Acked-by: Jesper Nilsson <jesper.nilsson@axis.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Russell King <linux@arm.linux.org.uk> Acked-by: Stephen Warren <swarren@nvidia.com> Tested-by: Andrew Lunn <andrew@lunn.ch> Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org> Reviewed-by: Lan Tianyu <tianyu.lan@intel.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/imx6q-cpufreq.c')
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c37
1 files changed, 15 insertions, 22 deletions
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 07af3b0de069..4b3f18e5f36b 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -42,14 +42,14 @@ static unsigned int imx6q_get_speed(unsigned int cpu)
42 42
43static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) 43static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
44{ 44{
45 struct cpufreq_freqs freqs;
46 struct dev_pm_opp *opp; 45 struct dev_pm_opp *opp;
47 unsigned long freq_hz, volt, volt_old; 46 unsigned long freq_hz, volt, volt_old;
47 unsigned int old_freq, new_freq;
48 int ret; 48 int ret;
49 49
50 freqs.new = freq_table[index].frequency; 50 new_freq = freq_table[index].frequency;
51 freq_hz = freqs.new * 1000; 51 freq_hz = new_freq * 1000;
52 freqs.old = clk_get_rate(arm_clk) / 1000; 52 old_freq = clk_get_rate(arm_clk) / 1000;
53 53
54 rcu_read_lock(); 54 rcu_read_lock();
55 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); 55 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
@@ -64,26 +64,23 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
64 volt_old = regulator_get_voltage(arm_reg); 64 volt_old = regulator_get_voltage(arm_reg);
65 65
66 dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", 66 dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
67 freqs.old / 1000, volt_old / 1000, 67 old_freq / 1000, volt_old / 1000,
68 freqs.new / 1000, volt / 1000); 68 new_freq / 1000, volt / 1000);
69
70 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
71 69
72 /* scaling up? scale voltage before frequency */ 70 /* scaling up? scale voltage before frequency */
73 if (freqs.new > freqs.old) { 71 if (new_freq > old_freq) {
74 ret = regulator_set_voltage_tol(arm_reg, volt, 0); 72 ret = regulator_set_voltage_tol(arm_reg, volt, 0);
75 if (ret) { 73 if (ret) {
76 dev_err(cpu_dev, 74 dev_err(cpu_dev,
77 "failed to scale vddarm up: %d\n", ret); 75 "failed to scale vddarm up: %d\n", ret);
78 freqs.new = freqs.old; 76 return ret;
79 goto post_notify;
80 } 77 }
81 78
82 /* 79 /*
83 * Need to increase vddpu and vddsoc for safety 80 * Need to increase vddpu and vddsoc for safety
84 * if we are about to run at 1.2 GHz. 81 * if we are about to run at 1.2 GHz.
85 */ 82 */
86 if (freqs.new == FREQ_1P2_GHZ / 1000) { 83 if (new_freq == FREQ_1P2_GHZ / 1000) {
87 regulator_set_voltage_tol(pu_reg, 84 regulator_set_voltage_tol(pu_reg,
88 PU_SOC_VOLTAGE_HIGH, 0); 85 PU_SOC_VOLTAGE_HIGH, 0);
89 regulator_set_voltage_tol(soc_reg, 86 regulator_set_voltage_tol(soc_reg,
@@ -103,21 +100,20 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
103 clk_set_parent(step_clk, pll2_pfd2_396m_clk); 100 clk_set_parent(step_clk, pll2_pfd2_396m_clk);
104 clk_set_parent(pll1_sw_clk, step_clk); 101 clk_set_parent(pll1_sw_clk, step_clk);
105 if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { 102 if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
106 clk_set_rate(pll1_sys_clk, freqs.new * 1000); 103 clk_set_rate(pll1_sys_clk, new_freq * 1000);
107 clk_set_parent(pll1_sw_clk, pll1_sys_clk); 104 clk_set_parent(pll1_sw_clk, pll1_sys_clk);
108 } 105 }
109 106
110 /* Ensure the arm clock divider is what we expect */ 107 /* Ensure the arm clock divider is what we expect */
111 ret = clk_set_rate(arm_clk, freqs.new * 1000); 108 ret = clk_set_rate(arm_clk, new_freq * 1000);
112 if (ret) { 109 if (ret) {
113 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); 110 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
114 regulator_set_voltage_tol(arm_reg, volt_old, 0); 111 regulator_set_voltage_tol(arm_reg, volt_old, 0);
115 freqs.new = freqs.old; 112 return ret;
116 goto post_notify;
117 } 113 }
118 114
119 /* scaling down? scale voltage after frequency */ 115 /* scaling down? scale voltage after frequency */
120 if (freqs.new < freqs.old) { 116 if (new_freq < old_freq) {
121 ret = regulator_set_voltage_tol(arm_reg, volt, 0); 117 ret = regulator_set_voltage_tol(arm_reg, volt, 0);
122 if (ret) { 118 if (ret) {
123 dev_warn(cpu_dev, 119 dev_warn(cpu_dev,
@@ -125,7 +121,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
125 ret = 0; 121 ret = 0;
126 } 122 }
127 123
128 if (freqs.old == FREQ_1P2_GHZ / 1000) { 124 if (old_freq == FREQ_1P2_GHZ / 1000) {
129 regulator_set_voltage_tol(pu_reg, 125 regulator_set_voltage_tol(pu_reg,
130 PU_SOC_VOLTAGE_NORMAL, 0); 126 PU_SOC_VOLTAGE_NORMAL, 0);
131 regulator_set_voltage_tol(soc_reg, 127 regulator_set_voltage_tol(soc_reg,
@@ -133,10 +129,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
133 } 129 }
134 } 130 }
135 131
136post_notify: 132 return 0;
137 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
138
139 return ret;
140} 133}
141 134
142static int imx6q_cpufreq_init(struct cpufreq_policy *policy) 135static int imx6q_cpufreq_init(struct cpufreq_policy *policy)