aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/e_powersaver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/e_powersaver.c')
-rw-r--r--drivers/cpufreq/e_powersaver.c59
1 files changed, 9 insertions, 50 deletions
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index 09f64cc83019..9012b8bb6b64 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -107,15 +107,9 @@ static int eps_set_state(struct eps_cpu_data *centaur,
107 struct cpufreq_policy *policy, 107 struct cpufreq_policy *policy,
108 u32 dest_state) 108 u32 dest_state)
109{ 109{
110 struct cpufreq_freqs freqs;
111 u32 lo, hi; 110 u32 lo, hi;
112 int err = 0;
113 int i; 111 int i;
114 112
115 freqs.old = eps_get(policy->cpu);
116 freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff);
117 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
118
119 /* Wait while CPU is busy */ 113 /* Wait while CPU is busy */
120 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 114 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
121 i = 0; 115 i = 0;
@@ -124,8 +118,7 @@ static int eps_set_state(struct eps_cpu_data *centaur,
124 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 118 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
125 i++; 119 i++;
126 if (unlikely(i > 64)) { 120 if (unlikely(i > 64)) {
127 err = -ENODEV; 121 return -ENODEV;
128 goto postchange;
129 } 122 }
130 } 123 }
131 /* Set new multiplier and voltage */ 124 /* Set new multiplier and voltage */
@@ -137,16 +130,10 @@ static int eps_set_state(struct eps_cpu_data *centaur,
137 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 130 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
138 i++; 131 i++;
139 if (unlikely(i > 64)) { 132 if (unlikely(i > 64)) {
140 err = -ENODEV; 133 return -ENODEV;
141 goto postchange;
142 } 134 }
143 } while (lo & ((1 << 16) | (1 << 17))); 135 } while (lo & ((1 << 16) | (1 << 17)));
144 136
145 /* Return current frequency */
146postchange:
147 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
148 freqs.new = centaur->fsb * ((lo >> 8) & 0xff);
149
150#ifdef DEBUG 137#ifdef DEBUG
151 { 138 {
152 u8 current_multiplier, current_voltage; 139 u8 current_multiplier, current_voltage;
@@ -161,19 +148,12 @@ postchange:
161 current_multiplier); 148 current_multiplier);
162 } 149 }
163#endif 150#endif
164 if (err) 151 return 0;
165 freqs.new = freqs.old;
166
167 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
168 return err;
169} 152}
170 153
171static int eps_target(struct cpufreq_policy *policy, 154static int eps_target(struct cpufreq_policy *policy, unsigned int index)
172 unsigned int target_freq,
173 unsigned int relation)
174{ 155{
175 struct eps_cpu_data *centaur; 156 struct eps_cpu_data *centaur;
176 unsigned int newstate = 0;
177 unsigned int cpu = policy->cpu; 157 unsigned int cpu = policy->cpu;
178 unsigned int dest_state; 158 unsigned int dest_state;
179 int ret; 159 int ret;
@@ -182,28 +162,14 @@ static int eps_target(struct cpufreq_policy *policy,
182 return -ENODEV; 162 return -ENODEV;
183 centaur = eps_cpu[cpu]; 163 centaur = eps_cpu[cpu];
184 164
185 if (unlikely(cpufreq_frequency_table_target(policy,
186 &eps_cpu[cpu]->freq_table[0],
187 target_freq,
188 relation,
189 &newstate))) {
190 return -EINVAL;
191 }
192
193 /* Make frequency transition */ 165 /* Make frequency transition */
194 dest_state = centaur->freq_table[newstate].driver_data & 0xffff; 166 dest_state = centaur->freq_table[index].driver_data & 0xffff;
195 ret = eps_set_state(centaur, policy, dest_state); 167 ret = eps_set_state(centaur, policy, dest_state);
196 if (ret) 168 if (ret)
197 printk(KERN_ERR "eps: Timeout!\n"); 169 printk(KERN_ERR "eps: Timeout!\n");
198 return ret; 170 return ret;
199} 171}
200 172
201static int eps_verify(struct cpufreq_policy *policy)
202{
203 return cpufreq_frequency_table_verify(policy,
204 &eps_cpu[policy->cpu]->freq_table[0]);
205}
206
207static int eps_cpu_init(struct cpufreq_policy *policy) 173static int eps_cpu_init(struct cpufreq_policy *policy)
208{ 174{
209 unsigned int i; 175 unsigned int i;
@@ -401,15 +367,13 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
401 } 367 }
402 368
403 policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ 369 policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
404 policy->cur = fsb * current_multiplier;
405 370
406 ret = cpufreq_frequency_table_cpuinfo(policy, &centaur->freq_table[0]); 371 ret = cpufreq_table_validate_and_show(policy, &centaur->freq_table[0]);
407 if (ret) { 372 if (ret) {
408 kfree(centaur); 373 kfree(centaur);
409 return ret; 374 return ret;
410 } 375 }
411 376
412 cpufreq_frequency_table_get_attr(&centaur->freq_table[0], policy->cpu);
413 return 0; 377 return 0;
414} 378}
415 379
@@ -424,19 +388,14 @@ static int eps_cpu_exit(struct cpufreq_policy *policy)
424 return 0; 388 return 0;
425} 389}
426 390
427static struct freq_attr *eps_attr[] = {
428 &cpufreq_freq_attr_scaling_available_freqs,
429 NULL,
430};
431
432static struct cpufreq_driver eps_driver = { 391static struct cpufreq_driver eps_driver = {
433 .verify = eps_verify, 392 .verify = cpufreq_generic_frequency_table_verify,
434 .target = eps_target, 393 .target_index = eps_target,
435 .init = eps_cpu_init, 394 .init = eps_cpu_init,
436 .exit = eps_cpu_exit, 395 .exit = eps_cpu_exit,
437 .get = eps_get, 396 .get = eps_get,
438 .name = "e_powersaver", 397 .name = "e_powersaver",
439 .attr = eps_attr, 398 .attr = cpufreq_generic_attr,
440}; 399};
441 400
442 401