diff options
author | Jonghwan Choi <jhbird.choi@samsung.com> | 2011-06-24 03:04:14 -0400 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2011-07-13 18:29:56 -0400 |
commit | e8b4c1986efbb5b1e1bab9f359c340816e4d9869 (patch) | |
tree | c785578962af93033cc0136ae2dcf66ff72cc4de /drivers/cpufreq/s5pv210-cpufreq.c | |
parent | 90d5d0a119bcf189e8b33f776b4f8371b789b311 (diff) |
[CPUFREQ] S5PV210: Add arm/int voltage control support
Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'drivers/cpufreq/s5pv210-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/s5pv210-cpufreq.c | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 48a4a9058864..9a5b28474342 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/cpufreq.h> | 18 | #include <linux/cpufreq.h> |
19 | #include <linux/regulator/consumer.h> | ||
19 | 20 | ||
20 | #include <mach/map.h> | 21 | #include <mach/map.h> |
21 | #include <mach/regs-clock.h> | 22 | #include <mach/regs-clock.h> |
@@ -77,6 +78,40 @@ static struct cpufreq_frequency_table s5pv210_freq_table[] = { | |||
77 | {0, CPUFREQ_TABLE_END}, | 78 | {0, CPUFREQ_TABLE_END}, |
78 | }; | 79 | }; |
79 | 80 | ||
81 | static struct regulator *arm_regulator; | ||
82 | static struct regulator *int_regulator; | ||
83 | |||
84 | struct s5pv210_dvs_conf { | ||
85 | int arm_volt; /* uV */ | ||
86 | int int_volt; /* uV */ | ||
87 | }; | ||
88 | |||
89 | static const int arm_volt_max = 1350000; | ||
90 | static const int int_volt_max = 1250000; | ||
91 | |||
92 | static struct s5pv210_dvs_conf dvs_conf[] = { | ||
93 | [L0] = { | ||
94 | .arm_volt = 1250000, | ||
95 | .int_volt = 1100000, | ||
96 | }, | ||
97 | [L1] = { | ||
98 | .arm_volt = 1200000, | ||
99 | .int_volt = 1100000, | ||
100 | }, | ||
101 | [L2] = { | ||
102 | .arm_volt = 1050000, | ||
103 | .int_volt = 1100000, | ||
104 | }, | ||
105 | [L3] = { | ||
106 | .arm_volt = 950000, | ||
107 | .int_volt = 1100000, | ||
108 | }, | ||
109 | [L4] = { | ||
110 | .arm_volt = 950000, | ||
111 | .int_volt = 1000000, | ||
112 | }, | ||
113 | }; | ||
114 | |||
80 | static u32 clkdiv_val[5][11] = { | 115 | static u32 clkdiv_val[5][11] = { |
81 | /* | 116 | /* |
82 | * Clock divider value for following | 117 | * Clock divider value for following |
@@ -157,6 +192,8 @@ static int s5pv210_target(struct cpufreq_policy *policy, | |||
157 | unsigned int index, priv_index; | 192 | unsigned int index, priv_index; |
158 | unsigned int pll_changing = 0; | 193 | unsigned int pll_changing = 0; |
159 | unsigned int bus_speed_changing = 0; | 194 | unsigned int bus_speed_changing = 0; |
195 | int arm_volt, int_volt; | ||
196 | int ret = 0; | ||
160 | 197 | ||
161 | if (relation & ENABLE_FURTHER_CPUFREQ) | 198 | if (relation & ENABLE_FURTHER_CPUFREQ) |
162 | no_cpufreq_access = false; | 199 | no_cpufreq_access = false; |
@@ -191,12 +228,23 @@ static int s5pv210_target(struct cpufreq_policy *policy, | |||
191 | freqs.old, relation, &priv_index)) | 228 | freqs.old, relation, &priv_index)) |
192 | return -EINVAL; | 229 | return -EINVAL; |
193 | 230 | ||
194 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 231 | arm_volt = dvs_conf[index].arm_volt; |
232 | int_volt = dvs_conf[index].int_volt; | ||
195 | 233 | ||
196 | if (freqs.new > freqs.old) { | 234 | if (freqs.new > freqs.old) { |
197 | /* Voltage up: will be implemented */ | 235 | ret = regulator_set_voltage(arm_regulator, |
236 | arm_volt, arm_volt_max); | ||
237 | if (ret) | ||
238 | return ret; | ||
239 | |||
240 | ret = regulator_set_voltage(int_regulator, | ||
241 | int_volt, int_volt_max); | ||
242 | if (ret) | ||
243 | return ret; | ||
198 | } | 244 | } |
199 | 245 | ||
246 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
247 | |||
200 | /* Check if there need to change PLL */ | 248 | /* Check if there need to change PLL */ |
201 | if ((index == L0) || (priv_index == L0)) | 249 | if ((index == L0) || (priv_index == L0)) |
202 | pll_changing = 1; | 250 | pll_changing = 1; |
@@ -408,7 +456,11 @@ static int s5pv210_target(struct cpufreq_policy *policy, | |||
408 | } | 456 | } |
409 | 457 | ||
410 | if (freqs.new < freqs.old) { | 458 | if (freqs.new < freqs.old) { |
411 | /* Voltage down: will be implemented */ | 459 | regulator_set_voltage(int_regulator, |
460 | int_volt, int_volt_max); | ||
461 | |||
462 | regulator_set_voltage(arm_regulator, | ||
463 | arm_volt, arm_volt_max); | ||
412 | } | 464 | } |
413 | 465 | ||
414 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 466 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
@@ -515,6 +567,19 @@ static struct cpufreq_driver s5pv210_driver = { | |||
515 | 567 | ||
516 | static int __init s5pv210_cpufreq_init(void) | 568 | static int __init s5pv210_cpufreq_init(void) |
517 | { | 569 | { |
570 | arm_regulator = regulator_get(NULL, "vddarm"); | ||
571 | if (IS_ERR(arm_regulator)) { | ||
572 | pr_err("failed to get regulator vddarm"); | ||
573 | return PTR_ERR(arm_regulator); | ||
574 | } | ||
575 | |||
576 | int_regulator = regulator_get(NULL, "vddint"); | ||
577 | if (IS_ERR(int_regulator)) { | ||
578 | pr_err("failed to get regulator vddint"); | ||
579 | regulator_put(arm_regulator); | ||
580 | return PTR_ERR(int_regulator); | ||
581 | } | ||
582 | |||
518 | return cpufreq_register_driver(&s5pv210_driver); | 583 | return cpufreq_register_driver(&s5pv210_driver); |
519 | } | 584 | } |
520 | 585 | ||