aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/s5pv210-cpufreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/s5pv210-cpufreq.c')
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c86
1 files changed, 21 insertions, 65 deletions
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 5c7757073793..e3973dae28a7 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -26,7 +26,6 @@
26static struct clk *cpu_clk; 26static struct clk *cpu_clk;
27static struct clk *dmc0_clk; 27static struct clk *dmc0_clk;
28static struct clk *dmc1_clk; 28static struct clk *dmc1_clk;
29static struct cpufreq_freqs freqs;
30static DEFINE_MUTEX(set_freq_lock); 29static DEFINE_MUTEX(set_freq_lock);
31 30
32/* APLL M,P,S values for 1G/800Mhz */ 31/* APLL M,P,S values for 1G/800Mhz */
@@ -36,16 +35,7 @@ static DEFINE_MUTEX(set_freq_lock);
36/* Use 800MHz when entering sleep mode */ 35/* Use 800MHz when entering sleep mode */
37#define SLEEP_FREQ (800 * 1000) 36#define SLEEP_FREQ (800 * 1000)
38 37
39/* 38/* Tracks if cpu freqency can be updated anymore */
40 * relation has an additional symantics other than the standard of cpufreq
41 * DISALBE_FURTHER_CPUFREQ: disable further access to target
42 * ENABLE_FURTUER_CPUFREQ: enable access to target
43 */
44enum cpufreq_access {
45 DISABLE_FURTHER_CPUFREQ = 0x10,
46 ENABLE_FURTHER_CPUFREQ = 0x20,
47};
48
49static bool no_cpufreq_access; 39static bool no_cpufreq_access;
50 40
51/* 41/*
@@ -174,14 +164,6 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
174 __raw_writel(tmp1, reg); 164 __raw_writel(tmp1, reg);
175} 165}
176 166
177static int s5pv210_verify_speed(struct cpufreq_policy *policy)
178{
179 if (policy->cpu)
180 return -EINVAL;
181
182 return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
183}
184
185static unsigned int s5pv210_getspeed(unsigned int cpu) 167static unsigned int s5pv210_getspeed(unsigned int cpu)
186{ 168{
187 if (cpu) 169 if (cpu)
@@ -190,22 +172,18 @@ static unsigned int s5pv210_getspeed(unsigned int cpu)
190 return clk_get_rate(cpu_clk) / 1000; 172 return clk_get_rate(cpu_clk) / 1000;
191} 173}
192 174
193static int s5pv210_target(struct cpufreq_policy *policy, 175static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
194 unsigned int target_freq,
195 unsigned int relation)
196{ 176{
197 unsigned long reg; 177 unsigned long reg;
198 unsigned int index, priv_index; 178 unsigned int priv_index;
199 unsigned int pll_changing = 0; 179 unsigned int pll_changing = 0;
200 unsigned int bus_speed_changing = 0; 180 unsigned int bus_speed_changing = 0;
181 unsigned int old_freq, new_freq;
201 int arm_volt, int_volt; 182 int arm_volt, int_volt;
202 int ret = 0; 183 int ret = 0;
203 184
204 mutex_lock(&set_freq_lock); 185 mutex_lock(&set_freq_lock);
205 186
206 if (relation & ENABLE_FURTHER_CPUFREQ)
207 no_cpufreq_access = false;
208
209 if (no_cpufreq_access) { 187 if (no_cpufreq_access) {
210#ifdef CONFIG_PM_VERBOSE 188#ifdef CONFIG_PM_VERBOSE
211 pr_err("%s:%d denied access to %s as it is disabled" 189 pr_err("%s:%d denied access to %s as it is disabled"
@@ -215,27 +193,13 @@ static int s5pv210_target(struct cpufreq_policy *policy,
215 goto exit; 193 goto exit;
216 } 194 }
217 195
218 if (relation & DISABLE_FURTHER_CPUFREQ) 196 old_freq = s5pv210_getspeed(0);
219 no_cpufreq_access = true; 197 new_freq = s5pv210_freq_table[index].frequency;
220
221 relation &= ~(ENABLE_FURTHER_CPUFREQ | DISABLE_FURTHER_CPUFREQ);
222
223 freqs.old = s5pv210_getspeed(0);
224
225 if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
226 target_freq, relation, &index)) {
227 ret = -EINVAL;
228 goto exit;
229 }
230
231 freqs.new = s5pv210_freq_table[index].frequency;
232
233 if (freqs.new == freqs.old)
234 goto exit;
235 198
236 /* Finding current running level index */ 199 /* Finding current running level index */
237 if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, 200 if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
238 freqs.old, relation, &priv_index)) { 201 old_freq, CPUFREQ_RELATION_H,
202 &priv_index)) {
239 ret = -EINVAL; 203 ret = -EINVAL;
240 goto exit; 204 goto exit;
241 } 205 }
@@ -243,7 +207,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
243 arm_volt = dvs_conf[index].arm_volt; 207 arm_volt = dvs_conf[index].arm_volt;
244 int_volt = dvs_conf[index].int_volt; 208 int_volt = dvs_conf[index].int_volt;
245 209
246 if (freqs.new > freqs.old) { 210 if (new_freq > old_freq) {
247 ret = regulator_set_voltage(arm_regulator, 211 ret = regulator_set_voltage(arm_regulator,
248 arm_volt, arm_volt_max); 212 arm_volt, arm_volt_max);
249 if (ret) 213 if (ret)
@@ -255,8 +219,6 @@ static int s5pv210_target(struct cpufreq_policy *policy,
255 goto exit; 219 goto exit;
256 } 220 }
257 221
258 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
259
260 /* Check if there need to change PLL */ 222 /* Check if there need to change PLL */
261 if ((index == L0) || (priv_index == L0)) 223 if ((index == L0) || (priv_index == L0))
262 pll_changing = 1; 224 pll_changing = 1;
@@ -467,9 +429,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
467 } 429 }
468 } 430 }
469 431
470 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); 432 if (new_freq < old_freq) {
471
472 if (freqs.new < freqs.old) {
473 regulator_set_voltage(int_regulator, 433 regulator_set_voltage(int_regulator,
474 int_volt, int_volt_max); 434 int_volt, int_volt_max);
475 435
@@ -551,13 +511,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
551 s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); 511 s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
552 s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); 512 s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
553 513
554 policy->cur = policy->min = policy->max = s5pv210_getspeed(0); 514 return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
555
556 cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu);
557
558 policy->cpuinfo.transition_latency = 40000;
559
560 return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
561 515
562out_dmc1: 516out_dmc1:
563 clk_put(dmc0_clk); 517 clk_put(dmc0_clk);
@@ -573,16 +527,18 @@ static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
573 527
574 switch (event) { 528 switch (event) {
575 case PM_SUSPEND_PREPARE: 529 case PM_SUSPEND_PREPARE:
576 ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 530 ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
577 DISABLE_FURTHER_CPUFREQ);
578 if (ret < 0) 531 if (ret < 0)
579 return NOTIFY_BAD; 532 return NOTIFY_BAD;
580 533
534 /* Disable updation of cpu frequency */
535 no_cpufreq_access = true;
581 return NOTIFY_OK; 536 return NOTIFY_OK;
582 case PM_POST_RESTORE: 537 case PM_POST_RESTORE:
583 case PM_POST_SUSPEND: 538 case PM_POST_SUSPEND:
584 cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 539 /* Enable updation of cpu frequency */
585 ENABLE_FURTHER_CPUFREQ); 540 no_cpufreq_access = false;
541 cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
586 542
587 return NOTIFY_OK; 543 return NOTIFY_OK;
588 } 544 }
@@ -595,18 +551,18 @@ static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
595{ 551{
596 int ret; 552 int ret;
597 553
598 ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 554 ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
599 DISABLE_FURTHER_CPUFREQ);
600 if (ret < 0) 555 if (ret < 0)
601 return NOTIFY_BAD; 556 return NOTIFY_BAD;
602 557
558 no_cpufreq_access = true;
603 return NOTIFY_DONE; 559 return NOTIFY_DONE;
604} 560}
605 561
606static struct cpufreq_driver s5pv210_driver = { 562static struct cpufreq_driver s5pv210_driver = {
607 .flags = CPUFREQ_STICKY, 563 .flags = CPUFREQ_STICKY,
608 .verify = s5pv210_verify_speed, 564 .verify = cpufreq_generic_frequency_table_verify,
609 .target = s5pv210_target, 565 .target_index = s5pv210_target,
610 .get = s5pv210_getspeed, 566 .get = s5pv210_getspeed,
611 .init = s5pv210_cpu_init, 567 .init = s5pv210_cpu_init,
612 .name = "s5pv210", 568 .name = "s5pv210",