aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorJonghwan Choi <jhbird.choi@samsung.com>2012-12-23 18:57:48 -0500
committerKukjin Kim <kgene.kim@samsung.com>2012-12-23 18:57:48 -0500
commit0e0e425f58fc91b7559350e12060938f8fa7a1c2 (patch)
tree0ad8546486ad9abf9eb684f197eac1d5064f673b /drivers/cpufreq
parent9d0554fff9a21d846adcfbd14cfb02e82773162c (diff)
cpufreq: exynos: Split exynos_target function into two functions
Split exynos_target function into exynos_target & exynos_cpufreq_scale. The exynos_cpufreq_scale changes the voltage & frequency. Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c151
1 files changed, 86 insertions, 65 deletions
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 0d40eb7b1dee..232208cf6c03 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -42,54 +42,55 @@ static unsigned int exynos_getspeed(unsigned int cpu)
42 return clk_get_rate(exynos_info->cpu_clk) / 1000; 42 return clk_get_rate(exynos_info->cpu_clk) / 1000;
43} 43}
44 44
45static int exynos_target(struct cpufreq_policy *policy, 45static int exynos_cpufreq_get_index(unsigned int freq)
46 unsigned int target_freq, 46{
47 unsigned int relation) 47 struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
48 int index;
49
50 for (index = 0;
51 freq_table[index].frequency != CPUFREQ_TABLE_END; index++)
52 if (freq_table[index].frequency == freq)
53 break;
54
55 if (freq_table[index].frequency == CPUFREQ_TABLE_END)
56 return -EINVAL;
57
58 return index;
59}
60
61static int exynos_cpufreq_scale(unsigned int target_freq)
48{ 62{
49 unsigned int index, old_index;
50 unsigned int arm_volt, safe_arm_volt = 0;
51 int ret = 0;
52 struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; 63 struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
53 unsigned int *volt_table = exynos_info->volt_table; 64 unsigned int *volt_table = exynos_info->volt_table;
65 struct cpufreq_policy *policy = cpufreq_cpu_get(0);
66 unsigned int arm_volt, safe_arm_volt = 0;
54 unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz; 67 unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
55 68 unsigned int index, old_index;
56 mutex_lock(&cpufreq_lock); 69 int ret = 0;
57 70
58 freqs.old = policy->cur; 71 freqs.old = policy->cur;
72 freqs.cpu = policy->cpu;
59 73
60 if (frequency_locked && target_freq != locking_frequency) { 74 if (target_freq == freqs.old)
61 ret = -EAGAIN;
62 goto out; 75 goto out;
63 }
64 76
65 /* 77 /*
66 * The policy max have been changed so that we cannot get proper 78 * The policy max have been changed so that we cannot get proper
67 * old_index with cpufreq_frequency_table_target(). Thus, ignore 79 * old_index with cpufreq_frequency_table_target(). Thus, ignore
68 * policy and get the index from the raw freqeuncy table. 80 * policy and get the index from the raw freqeuncy table.
69 */ 81 */
70 for (old_index = 0; 82 old_index = exynos_cpufreq_get_index(freqs.old);
71 freq_table[old_index].frequency != CPUFREQ_TABLE_END; 83 if (old_index < 0) {
72 old_index++) 84 ret = old_index;
73 if (freq_table[old_index].frequency == freqs.old)
74 break;
75
76 if (freq_table[old_index].frequency == CPUFREQ_TABLE_END) {
77 ret = -EINVAL;
78 goto out; 85 goto out;
79 } 86 }
80 87
81 if (cpufreq_frequency_table_target(policy, freq_table, 88 index = exynos_cpufreq_get_index(target_freq);
82 target_freq, relation, &index)) { 89 if (index < 0) {
83 ret = -EINVAL; 90 ret = index;
84 goto out; 91 goto out;
85 } 92 }
86 93
87 freqs.new = freq_table[index].frequency;
88 freqs.cpu = policy->cpu;
89
90 if (freqs.new == freqs.old)
91 goto out;
92
93 /* 94 /*
94 * ARM clock source will be changed APLL to MPLL temporary 95 * ARM clock source will be changed APLL to MPLL temporary
95 * To support this level, need to control regulator for 96 * To support this level, need to control regulator for
@@ -109,13 +110,23 @@ static int exynos_target(struct cpufreq_policy *policy,
109 /* When the new frequency is higher than current frequency */ 110 /* When the new frequency is higher than current frequency */
110 if ((freqs.new > freqs.old) && !safe_arm_volt) { 111 if ((freqs.new > freqs.old) && !safe_arm_volt) {
111 /* Firstly, voltage up to increase frequency */ 112 /* Firstly, voltage up to increase frequency */
112 regulator_set_voltage(arm_regulator, arm_volt, 113 ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
113 arm_volt); 114 if (ret) {
115 pr_err("%s: failed to set cpu voltage to %d\n",
116 __func__, arm_volt);
117 goto out;
118 }
114 } 119 }
115 120
116 if (safe_arm_volt) 121 if (safe_arm_volt) {
117 regulator_set_voltage(arm_regulator, safe_arm_volt, 122 ret = regulator_set_voltage(arm_regulator, safe_arm_volt,
118 safe_arm_volt); 123 safe_arm_volt);
124 if (ret) {
125 pr_err("%s: failed to set cpu voltage to %d\n",
126 __func__, safe_arm_volt);
127 goto out;
128 }
129 }
119 130
120 exynos_info->set_freq(old_index, index); 131 exynos_info->set_freq(old_index, index);
121 132
@@ -128,8 +139,43 @@ static int exynos_target(struct cpufreq_policy *policy,
128 /* down the voltage after frequency change */ 139 /* down the voltage after frequency change */
129 regulator_set_voltage(arm_regulator, arm_volt, 140 regulator_set_voltage(arm_regulator, arm_volt,
130 arm_volt); 141 arm_volt);
142 if (ret) {
143 pr_err("%s: failed to set cpu voltage to %d\n",
144 __func__, arm_volt);
145 goto out;
146 }
147 }
148
149out:
150
151 cpufreq_cpu_put(policy);
152
153 return ret;
154}
155
156static int exynos_target(struct cpufreq_policy *policy,
157 unsigned int target_freq,
158 unsigned int relation)
159{
160 struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
161 unsigned int index;
162 int ret;
163
164 mutex_lock(&cpufreq_lock);
165
166 if (frequency_locked)
167 goto out;
168
169 if (cpufreq_frequency_table_target(policy, freq_table,
170 target_freq, relation, &index)) {
171 ret = -EINVAL;
172 goto out;
131 } 173 }
132 174
175 freqs.new = freq_table[index].frequency;
176
177 ret = exynos_cpufreq_scale(freqs.new);
178
133out: 179out:
134 mutex_unlock(&cpufreq_lock); 180 mutex_unlock(&cpufreq_lock);
135 181
@@ -166,51 +212,26 @@ static int exynos_cpufreq_resume(struct cpufreq_policy *policy)
166static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier, 212static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier,
167 unsigned long pm_event, void *v) 213 unsigned long pm_event, void *v)
168{ 214{
169 struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */ 215 int ret;
170 static unsigned int saved_frequency;
171 unsigned int temp;
172 216
173 mutex_lock(&cpufreq_lock);
174 switch (pm_event) { 217 switch (pm_event) {
175 case PM_SUSPEND_PREPARE: 218 case PM_SUSPEND_PREPARE:
176 if (frequency_locked) 219 mutex_lock(&cpufreq_lock);
177 goto out;
178
179 frequency_locked = true; 220 frequency_locked = true;
221 mutex_unlock(&cpufreq_lock);
180 222
181 if (locking_frequency) { 223 ret = exynos_cpufreq_scale(locking_frequency);
182 saved_frequency = exynos_getspeed(0); 224 if (ret < 0)
225 return NOTIFY_BAD;
183 226
184 mutex_unlock(&cpufreq_lock);
185 exynos_target(policy, locking_frequency,
186 CPUFREQ_RELATION_H);
187 mutex_lock(&cpufreq_lock);
188 }
189 break; 227 break;
190 228
191 case PM_POST_SUSPEND: 229 case PM_POST_SUSPEND:
192 if (saved_frequency) { 230 mutex_lock(&cpufreq_lock);
193 /*
194 * While frequency_locked, only locking_frequency
195 * is valid for target(). In order to use
196 * saved_frequency while keeping frequency_locked,
197 * we temporarly overwrite locking_frequency.
198 */
199 temp = locking_frequency;
200 locking_frequency = saved_frequency;
201
202 mutex_unlock(&cpufreq_lock);
203 exynos_target(policy, locking_frequency,
204 CPUFREQ_RELATION_H);
205 mutex_lock(&cpufreq_lock);
206
207 locking_frequency = temp;
208 }
209 frequency_locked = false; 231 frequency_locked = false;
232 mutex_unlock(&cpufreq_lock);
210 break; 233 break;
211 } 234 }
212out:
213 mutex_unlock(&cpufreq_lock);
214 235
215 return NOTIFY_OK; 236 return NOTIFY_OK;
216} 237}