diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2013-08-14 10:08:24 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-10-30 19:11:08 -0400 |
commit | d4019f0a92ab802f385cc9c8ad3ab7b5449712cb (patch) | |
tree | ebd06695585e457ae1bf219653452b111e7508db /drivers/cpufreq/imx6q-cpufreq.c | |
parent | 7dbf694db6ac7c759599316d50d7050efcbd512a (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.c | 37 |
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 | ||
43 | static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) | 43 | static 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 | ||
136 | post_notify: | 132 | return 0; |
137 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||
138 | |||
139 | return ret; | ||
140 | } | 133 | } |
141 | 134 | ||
142 | static int imx6q_cpufreq_init(struct cpufreq_policy *policy) | 135 | static int imx6q_cpufreq_init(struct cpufreq_policy *policy) |