aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig9
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Makefile1
-rw-r--r--arch/i386/kernel/cpu/cpufreq/e_powersaver.c334
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c308
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.h153
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c6
6 files changed, 546 insertions, 265 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index 5299c5bf4454..6c52182ca323 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -217,6 +217,15 @@ config X86_LONGHAUL
217 217
218 If in doubt, say N. 218 If in doubt, say N.
219 219
220config X86_E_POWERSAVER
221 tristate "VIA C7 Enhanced PowerSaver (EXPERIMENTAL)"
222 select CPU_FREQ_TABLE
223 depends on EXPERIMENTAL
224 help
225 This adds the CPUFreq driver for VIA C7 processors.
226
227 If in doubt, say N.
228
220comment "shared options" 229comment "shared options"
221 230
222config X86_ACPI_CPUFREQ_PROC_INTF 231config X86_ACPI_CPUFREQ_PROC_INTF
diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile
index 8de3abe322a9..560f7760dae5 100644
--- a/arch/i386/kernel/cpu/cpufreq/Makefile
+++ b/arch/i386/kernel/cpu/cpufreq/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
2obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o 2obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
3obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o 3obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
4obj-$(CONFIG_X86_LONGHAUL) += longhaul.o 4obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
5obj-$(CONFIG_X86_E_POWERSAVER) += e_powersaver.o
5obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o 6obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
6obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o 7obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o
7obj-$(CONFIG_X86_LONGRUN) += longrun.o 8obj-$(CONFIG_X86_LONGRUN) += longrun.o
diff --git a/arch/i386/kernel/cpu/cpufreq/e_powersaver.c b/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
new file mode 100644
index 000000000000..3243725f80ca
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
@@ -0,0 +1,334 @@
1/*
2 * Based on documentation provided by Dave Jones. Thanks!
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/cpufreq.h>
13#include <linux/ioport.h>
14#include <linux/slab.h>
15
16#include <asm/msr.h>
17#include <asm/tsc.h>
18#include <asm/timex.h>
19#include <asm/io.h>
20#include <asm/delay.h>
21
22#define EPS_BRAND_C7M 0
23#define EPS_BRAND_C7 1
24#define EPS_BRAND_EDEN 2
25#define EPS_BRAND_C3 3
26
27struct eps_cpu_data {
28 u32 fsb;
29 struct cpufreq_frequency_table freq_table[];
30};
31
32static struct eps_cpu_data *eps_cpu[NR_CPUS];
33
34
35static unsigned int eps_get(unsigned int cpu)
36{
37 struct eps_cpu_data *centaur;
38 u32 lo, hi;
39
40 if (cpu)
41 return 0;
42 centaur = eps_cpu[cpu];
43 if (centaur == NULL)
44 return 0;
45
46 /* Return current frequency */
47 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
48 return centaur->fsb * ((lo >> 8) & 0xff);
49}
50
51static int eps_set_state(struct eps_cpu_data *centaur,
52 unsigned int cpu,
53 u32 dest_state)
54{
55 struct cpufreq_freqs freqs;
56 u32 lo, hi;
57 int err = 0;
58 int i;
59
60 freqs.old = eps_get(cpu);
61 freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff);
62 freqs.cpu = cpu;
63 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
64
65 /* Wait while CPU is busy */
66 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
67 i = 0;
68 while (lo & ((1 << 16) | (1 << 17))) {
69 udelay(16);
70 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
71 i++;
72 if (unlikely(i > 64)) {
73 err = -ENODEV;
74 goto postchange;
75 }
76 }
77 /* Set new multiplier and voltage */
78 wrmsr(MSR_IA32_PERF_CTL, dest_state & 0xffff, 0);
79 /* Wait until transition end */
80 i = 0;
81 do {
82 udelay(16);
83 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
84 i++;
85 if (unlikely(i > 64)) {
86 err = -ENODEV;
87 goto postchange;
88 }
89 } while (lo & ((1 << 16) | (1 << 17)));
90
91 /* Return current frequency */
92postchange:
93 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
94 freqs.new = centaur->fsb * ((lo >> 8) & 0xff);
95
96 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
97 return err;
98}
99
100static int eps_target(struct cpufreq_policy *policy,
101 unsigned int target_freq,
102 unsigned int relation)
103{
104 struct eps_cpu_data *centaur;
105 unsigned int newstate = 0;
106 unsigned int cpu = policy->cpu;
107 unsigned int dest_state;
108 int ret;
109
110 if (unlikely(eps_cpu[cpu] == NULL))
111 return -ENODEV;
112 centaur = eps_cpu[cpu];
113
114 if (unlikely(cpufreq_frequency_table_target(policy,
115 &eps_cpu[cpu]->freq_table[0],
116 target_freq,
117 relation,
118 &newstate))) {
119 return -EINVAL;
120 }
121
122 /* Make frequency transition */
123 dest_state = centaur->freq_table[newstate].index & 0xffff;
124 ret = eps_set_state(centaur, cpu, dest_state);
125 if (ret)
126 printk(KERN_ERR "eps: Timeout!\n");
127 return ret;
128}
129
130static int eps_verify(struct cpufreq_policy *policy)
131{
132 return cpufreq_frequency_table_verify(policy,
133 &eps_cpu[policy->cpu]->freq_table[0]);
134}
135
136static int eps_cpu_init(struct cpufreq_policy *policy)
137{
138 unsigned int i;
139 u32 lo, hi;
140 u64 val;
141 u8 current_multiplier, current_voltage;
142 u8 max_multiplier, max_voltage;
143 u8 min_multiplier, min_voltage;
144 u8 brand;
145 u32 fsb;
146 struct eps_cpu_data *centaur;
147 struct cpufreq_frequency_table *f_table;
148 int k, step, voltage;
149 int ret;
150 int states;
151
152 if (policy->cpu != 0)
153 return -ENODEV;
154
155 /* Check brand */
156 printk("eps: Detected VIA ");
157 rdmsr(0x1153, lo, hi);
158 brand = (((lo >> 2) ^ lo) >> 18) & 3;
159 switch(brand) {
160 case EPS_BRAND_C7M:
161 printk("C7-M\n");
162 break;
163 case EPS_BRAND_C7:
164 printk("C7\n");
165 break;
166 case EPS_BRAND_EDEN:
167 printk("Eden\n");
168 break;
169 case EPS_BRAND_C3:
170 printk("C3\n");
171 return -ENODEV;
172 break;
173 }
174 /* Enable Enhanced PowerSaver */
175 rdmsrl(MSR_IA32_MISC_ENABLE, val);
176 if (!(val & 1 << 16)) {
177 val |= 1 << 16;
178 wrmsrl(MSR_IA32_MISC_ENABLE, val);
179 /* Can be locked at 0 */
180 rdmsrl(MSR_IA32_MISC_ENABLE, val);
181 if (!(val & 1 << 16)) {
182 printk("eps: Can't enable Enhanced PowerSaver\n");
183 return -ENODEV;
184 }
185 }
186
187 /* Print voltage and multiplier */
188 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
189 current_voltage = lo & 0xff;
190 printk("eps: Current voltage = %dmV\n", current_voltage * 16 + 700);
191 current_multiplier = (lo >> 8) & 0xff;
192 printk("eps: Current multiplier = %d\n", current_multiplier);
193
194 /* Print limits */
195 max_voltage = hi & 0xff;
196 printk("eps: Highest voltage = %dmV\n", max_voltage * 16 + 700);
197 max_multiplier = (hi >> 8) & 0xff;
198 printk("eps: Highest multiplier = %d\n", max_multiplier);
199 min_voltage = (hi >> 16) & 0xff;
200 printk("eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700);
201 min_multiplier = (hi >> 24) & 0xff;
202 printk("eps: Lowest multiplier = %d\n", min_multiplier);
203
204 /* Sanity checks */
205 if (current_multiplier == 0 || max_multiplier == 0
206 || min_multiplier == 0)
207 return -EINVAL;
208 if (current_multiplier > max_multiplier
209 || max_multiplier <= min_multiplier)
210 return -EINVAL;
211 if (current_voltage > 0x1c || max_voltage > 0x1c)
212 return -EINVAL;
213 if (max_voltage < min_voltage)
214 return -EINVAL;
215
216 /* Calc FSB speed */
217 fsb = cpu_khz / current_multiplier;
218 /* Calc number of p-states supported */
219 if (brand == EPS_BRAND_C7M)
220 states = max_multiplier - min_multiplier + 1;
221 else
222 states = 2;
223
224 /* Allocate private data and frequency table for current cpu */
225 centaur = kzalloc(sizeof(struct eps_cpu_data)
226 + (states + 1) * sizeof(struct cpufreq_frequency_table),
227 GFP_KERNEL);
228 if (!centaur)
229 return -ENOMEM;
230 eps_cpu[0] = centaur;
231
232 /* Copy basic values */
233 centaur->fsb = fsb;
234
235 /* Fill frequency and MSR value table */
236 f_table = &centaur->freq_table[0];
237 if (brand == EPS_BRAND_EDEN) {
238 f_table[0].frequency = fsb * min_multiplier;
239 f_table[0].index = (min_multiplier << 8) | min_voltage;
240 f_table[1].frequency = fsb * max_multiplier;
241 f_table[1].index = (max_multiplier << 8) | max_voltage;
242 f_table[2].frequency = CPUFREQ_TABLE_END;
243 } else {
244 k = 0;
245 step = ((max_voltage - min_voltage) * 256)
246 / (max_multiplier - min_multiplier);
247 for (i = min_multiplier; i <= max_multiplier; i++) {
248 voltage = (k * step) / 256 + min_voltage;
249 f_table[k].frequency = fsb * i;
250 f_table[k].index = (i << 8) | voltage;
251 k++;
252 }
253 f_table[k].frequency = CPUFREQ_TABLE_END;
254 }
255
256 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
257 policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
258 policy->cur = fsb * current_multiplier;
259
260 ret = cpufreq_frequency_table_cpuinfo(policy, &centaur->freq_table[0]);
261 if (ret) {
262 kfree(centaur);
263 return ret;
264 }
265
266 cpufreq_frequency_table_get_attr(&centaur->freq_table[0], policy->cpu);
267 return 0;
268}
269
270static int eps_cpu_exit(struct cpufreq_policy *policy)
271{
272 unsigned int cpu = policy->cpu;
273 struct eps_cpu_data *centaur;
274 u32 lo, hi;
275
276 if (eps_cpu[cpu] == NULL)
277 return -ENODEV;
278 centaur = eps_cpu[cpu];
279
280 /* Get max frequency */
281 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
282 /* Set max frequency */
283 eps_set_state(centaur, cpu, hi & 0xffff);
284 /* Bye */
285 cpufreq_frequency_table_put_attr(policy->cpu);
286 kfree(eps_cpu[cpu]);
287 eps_cpu[cpu] = NULL;
288 return 0;
289}
290
291static struct freq_attr* eps_attr[] = {
292 &cpufreq_freq_attr_scaling_available_freqs,
293 NULL,
294};
295
296static struct cpufreq_driver eps_driver = {
297 .verify = eps_verify,
298 .target = eps_target,
299 .init = eps_cpu_init,
300 .exit = eps_cpu_exit,
301 .get = eps_get,
302 .name = "e_powersaver",
303 .owner = THIS_MODULE,
304 .attr = eps_attr,
305};
306
307static int __init eps_init(void)
308{
309 struct cpuinfo_x86 *c = cpu_data;
310
311 /* This driver will work only on Centaur C7 processors with
312 * Enhanced SpeedStep/PowerSaver registers */
313 if (c->x86_vendor != X86_VENDOR_CENTAUR
314 || c->x86 != 6 || c->x86_model != 10)
315 return -ENODEV;
316 if (!cpu_has(c, X86_FEATURE_EST))
317 return -ENODEV;
318
319 if (cpufreq_register_driver(&eps_driver))
320 return -EINVAL;
321 return 0;
322}
323
324static void __exit eps_exit(void)
325{
326 cpufreq_unregister_driver(&eps_driver);
327}
328
329MODULE_AUTHOR("Rafa³ Bilski <rafalbilski@interia.pl>");
330MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");
331MODULE_LICENSE("GPL");
332
333module_init(eps_init);
334module_exit(eps_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index a3db9332d652..fa5cac255c16 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -51,10 +51,12 @@
51#define CPU_EZRA 3 51#define CPU_EZRA 3
52#define CPU_EZRA_T 4 52#define CPU_EZRA_T 4
53#define CPU_NEHEMIAH 5 53#define CPU_NEHEMIAH 5
54#define CPU_NEHEMIAH_C 6
54 55
55/* Flags */ 56/* Flags */
56#define USE_ACPI_C3 (1 << 1) 57#define USE_ACPI_C3 (1 << 1)
57#define USE_NORTHBRIDGE (1 << 2) 58#define USE_NORTHBRIDGE (1 << 2)
59#define USE_VT8235 (1 << 3)
58 60
59static int cpu_model; 61static int cpu_model;
60static unsigned int numscales=16; 62static unsigned int numscales=16;
@@ -63,7 +65,8 @@ static unsigned int fsb;
63static struct mV_pos *vrm_mV_table; 65static struct mV_pos *vrm_mV_table;
64static unsigned char *mV_vrm_table; 66static unsigned char *mV_vrm_table;
65struct f_msr { 67struct f_msr {
66 unsigned char vrm; 68 u8 vrm;
69 u8 pos;
67}; 70};
68static struct f_msr f_msr_table[32]; 71static struct f_msr f_msr_table[32];
69 72
@@ -73,10 +76,10 @@ static int can_scale_voltage;
73static struct acpi_processor *pr = NULL; 76static struct acpi_processor *pr = NULL;
74static struct acpi_processor_cx *cx = NULL; 77static struct acpi_processor_cx *cx = NULL;
75static u8 longhaul_flags; 78static u8 longhaul_flags;
79static u8 longhaul_pos;
76 80
77/* Module parameters */ 81/* Module parameters */
78static int scale_voltage; 82static int scale_voltage;
79static int ignore_latency;
80 83
81#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) 84#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
82 85
@@ -164,26 +167,47 @@ static void do_longhaul1(unsigned int clock_ratio_index)
164static void do_powersaver(int cx_address, unsigned int clock_ratio_index) 167static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
165{ 168{
166 union msr_longhaul longhaul; 169 union msr_longhaul longhaul;
170 u8 dest_pos;
167 u32 t; 171 u32 t;
168 172
173 dest_pos = f_msr_table[clock_ratio_index].pos;
174
169 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); 175 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
176 /* Setup new frequency */
170 longhaul.bits.RevisionKey = longhaul.bits.RevisionID; 177 longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
171 longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; 178 longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
172 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; 179 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
173 longhaul.bits.EnableSoftBusRatio = 1; 180 /* Setup new voltage */
174 181 if (can_scale_voltage)
175 if (can_scale_voltage) {
176 longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm; 182 longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
183 /* Sync to timer tick */
184 safe_halt();
185 /* Raise voltage if necessary */
186 if (can_scale_voltage && longhaul_pos < dest_pos) {
177 longhaul.bits.EnableSoftVID = 1; 187 longhaul.bits.EnableSoftVID = 1;
188 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
189 /* Change voltage */
190 if (!cx_address) {
191 ACPI_FLUSH_CPU_CACHE();
192 halt();
193 } else {
194 ACPI_FLUSH_CPU_CACHE();
195 /* Invoke C3 */
196 inb(cx_address);
197 /* Dummy op - must do something useless after P_LVL3
198 * read */
199 t = inl(acpi_gbl_FADT.xpm_timer_block.address);
200 }
201 longhaul.bits.EnableSoftVID = 0;
202 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
203 longhaul_pos = dest_pos;
178 } 204 }
179 205
180 /* Sync to timer tick */
181 safe_halt();
182 /* Change frequency on next halt or sleep */ 206 /* Change frequency on next halt or sleep */
207 longhaul.bits.EnableSoftBusRatio = 1;
183 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); 208 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
184 if (!cx_address) { 209 if (!cx_address) {
185 ACPI_FLUSH_CPU_CACHE(); 210 ACPI_FLUSH_CPU_CACHE();
186 /* Invoke C1 */
187 halt(); 211 halt();
188 } else { 212 } else {
189 ACPI_FLUSH_CPU_CACHE(); 213 ACPI_FLUSH_CPU_CACHE();
@@ -193,12 +217,29 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
193 t = inl(acpi_gbl_FADT.xpm_timer_block.address); 217 t = inl(acpi_gbl_FADT.xpm_timer_block.address);
194 } 218 }
195 /* Disable bus ratio bit */ 219 /* Disable bus ratio bit */
196 local_irq_disable();
197 longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
198 longhaul.bits.EnableSoftBusRatio = 0; 220 longhaul.bits.EnableSoftBusRatio = 0;
199 longhaul.bits.EnableSoftBSEL = 0;
200 longhaul.bits.EnableSoftVID = 0;
201 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); 221 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
222
223 /* Reduce voltage if necessary */
224 if (can_scale_voltage && longhaul_pos > dest_pos) {
225 longhaul.bits.EnableSoftVID = 1;
226 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
227 /* Change voltage */
228 if (!cx_address) {
229 ACPI_FLUSH_CPU_CACHE();
230 halt();
231 } else {
232 ACPI_FLUSH_CPU_CACHE();
233 /* Invoke C3 */
234 inb(cx_address);
235 /* Dummy op - must do something useless after P_LVL3
236 * read */
237 t = inl(acpi_gbl_FADT.xpm_timer_block.address);
238 }
239 longhaul.bits.EnableSoftVID = 0;
240 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
241 longhaul_pos = dest_pos;
242 }
202} 243}
203 244
204/** 245/**
@@ -315,31 +356,19 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
315 356
316#define ROUNDING 0xf 357#define ROUNDING 0xf
317 358
318static int _guess(int guess, int mult)
319{
320 int target;
321
322 target = ((mult/10)*guess);
323 if (mult%10 != 0)
324 target += (guess/2);
325 target += ROUNDING/2;
326 target &= ~ROUNDING;
327 return target;
328}
329
330
331static int guess_fsb(int mult) 359static int guess_fsb(int mult)
332{ 360{
333 int speed = (cpu_khz/1000); 361 int speed = cpu_khz / 1000;
334 int i; 362 int i;
335 int speeds[] = { 66, 100, 133, 200 }; 363 int speeds[] = { 666, 1000, 1333, 2000 };
336 364 int f_max, f_min;
337 speed += ROUNDING/2; 365
338 speed &= ~ROUNDING; 366 for (i = 0; i < 4; i++) {
339 367 f_max = ((speeds[i] * mult) + 50) / 100;
340 for (i=0; i<4; i++) { 368 f_max += (ROUNDING / 2);
341 if (_guess(speeds[i], mult) == speed) 369 f_min = f_max - ROUNDING;
342 return speeds[i]; 370 if ((speed <= f_max) && (speed >= f_min))
371 return speeds[i] / 10;
343 } 372 }
344 return 0; 373 return 0;
345} 374}
@@ -347,67 +376,40 @@ static int guess_fsb(int mult)
347 376
348static int __init longhaul_get_ranges(void) 377static int __init longhaul_get_ranges(void)
349{ 378{
350 unsigned long invalue;
351 unsigned int ezra_t_multipliers[32]= {
352 90, 30, 40, 100, 55, 35, 45, 95,
353 50, 70, 80, 60, 120, 75, 85, 65,
354 -1, 110, 120, -1, 135, 115, 125, 105,
355 130, 150, 160, 140, -1, 155, -1, 145 };
356 unsigned int j, k = 0; 379 unsigned int j, k = 0;
357 union msr_longhaul longhaul; 380 int mult;
358 int mult = 0;
359 381
360 switch (longhaul_version) { 382 /* Get current frequency */
361 case TYPE_LONGHAUL_V1: 383 mult = longhaul_get_cpu_mult();
362 case TYPE_LONGHAUL_V2: 384 if (mult == -1) {
363 /* Ugh, Longhaul v1 didn't have the min/max MSRs. 385 printk(KERN_INFO PFX "Invalid (reserved) multiplier!\n");
364 Assume min=3.0x & max = whatever we booted at. */ 386 return -EINVAL;
387 }
388 fsb = guess_fsb(mult);
389 if (fsb == 0) {
390 printk(KERN_INFO PFX "Invalid (reserved) FSB!\n");
391 return -EINVAL;
392 }
393 /* Get max multiplier - as we always did.
394 * Longhaul MSR is usefull only when voltage scaling is enabled.
395 * C3 is booting at max anyway. */
396 maxmult = mult;
397 /* Get min multiplier */
398 switch (cpu_model) {
399 case CPU_NEHEMIAH:
400 minmult = 50;
401 break;
402 case CPU_NEHEMIAH_C:
403 minmult = 40;
404 break;
405 default:
365 minmult = 30; 406 minmult = 30;
366 maxmult = mult = longhaul_get_cpu_mult();
367 break; 407 break;
368
369 case TYPE_POWERSAVER:
370 /* Ezra-T */
371 if (cpu_model==CPU_EZRA_T) {
372 minmult = 30;
373 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
374 invalue = longhaul.bits.MaxMHzBR;
375 if (longhaul.bits.MaxMHzBR4)
376 invalue += 16;
377 maxmult = mult = ezra_t_multipliers[invalue];
378 break;
379 }
380
381 /* Nehemiah */
382 if (cpu_model==CPU_NEHEMIAH) {
383 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
384
385 /*
386 * TODO: This code works, but raises a lot of questions.
387 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
388 * We get around this by using a hardcoded multiplier of 4.0x
389 * for the minimimum speed, and the speed we booted up at for the max.
390 * This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
391 * - According to some VIA documentation EBLCR is only
392 * in pre-Nehemiah C3s. How this still works is a mystery.
393 * We're possibly using something undocumented and unsupported,
394 * But it works, so we don't grumble.
395 */
396 minmult=40;
397 maxmult = mult = longhaul_get_cpu_mult();
398 break;
399 }
400 } 408 }
401 fsb = guess_fsb(mult);
402 409
403 dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n", 410 dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
404 minmult/10, minmult%10, maxmult/10, maxmult%10); 411 minmult/10, minmult%10, maxmult/10, maxmult%10);
405 412
406 if (fsb == 0) {
407 printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
408 return -EINVAL;
409 }
410
411 highest_speed = calc_speed(maxmult); 413 highest_speed = calc_speed(maxmult);
412 lowest_speed = calc_speed(minmult); 414 lowest_speed = calc_speed(minmult);
413 dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb, 415 dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb,
@@ -455,6 +457,7 @@ static void __init longhaul_setup_voltagescaling(void)
455 union msr_longhaul longhaul; 457 union msr_longhaul longhaul;
456 struct mV_pos minvid, maxvid; 458 struct mV_pos minvid, maxvid;
457 unsigned int j, speed, pos, kHz_step, numvscales; 459 unsigned int j, speed, pos, kHz_step, numvscales;
460 int min_vid_speed;
458 461
459 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); 462 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
460 if (!(longhaul.bits.RevisionID & 1)) { 463 if (!(longhaul.bits.RevisionID & 1)) {
@@ -474,8 +477,6 @@ static void __init longhaul_setup_voltagescaling(void)
474 477
475 minvid = vrm_mV_table[longhaul.bits.MinimumVID]; 478 minvid = vrm_mV_table[longhaul.bits.MinimumVID];
476 maxvid = vrm_mV_table[longhaul.bits.MaximumVID]; 479 maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
477 numvscales = maxvid.pos - minvid.pos + 1;
478 kHz_step = (highest_speed - lowest_speed) / numvscales;
479 480
480 if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) { 481 if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
481 printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. " 482 printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
@@ -491,20 +492,59 @@ static void __init longhaul_setup_voltagescaling(void)
491 return; 492 return;
492 } 493 }
493 494
494 printk(KERN_INFO PFX "Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n", 495 /* How many voltage steps */
496 numvscales = maxvid.pos - minvid.pos + 1;
497 printk(KERN_INFO PFX
498 "Max VID=%d.%03d "
499 "Min VID=%d.%03d, "
500 "%d possible voltage scales\n",
495 maxvid.mV/1000, maxvid.mV%1000, 501 maxvid.mV/1000, maxvid.mV%1000,
496 minvid.mV/1000, minvid.mV%1000, 502 minvid.mV/1000, minvid.mV%1000,
497 numvscales); 503 numvscales);
498 504
505 /* Calculate max frequency at min voltage */
506 j = longhaul.bits.MinMHzBR;
507 if (longhaul.bits.MinMHzBR4)
508 j += 16;
509 min_vid_speed = eblcr_table[j];
510 if (min_vid_speed == -1)
511 return;
512 switch (longhaul.bits.MinMHzFSB) {
513 case 0:
514 min_vid_speed *= 13333;
515 break;
516 case 1:
517 min_vid_speed *= 10000;
518 break;
519 case 3:
520 min_vid_speed *= 6666;
521 break;
522 default:
523 return;
524 break;
525 }
526 if (min_vid_speed >= highest_speed)
527 return;
528 /* Calculate kHz for one voltage step */
529 kHz_step = (highest_speed - min_vid_speed) / numvscales;
530
531
499 j = 0; 532 j = 0;
500 while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) { 533 while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
501 speed = longhaul_table[j].frequency; 534 speed = longhaul_table[j].frequency;
502 pos = (speed - lowest_speed) / kHz_step + minvid.pos; 535 if (speed > min_vid_speed)
536 pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
537 else
538 pos = minvid.pos;
503 f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos]; 539 f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
540 f_msr_table[longhaul_table[j].index].pos = pos;
504 j++; 541 j++;
505 } 542 }
506 543
544 longhaul_pos = maxvid.pos;
507 can_scale_voltage = 1; 545 can_scale_voltage = 1;
546 printk(KERN_INFO PFX "Voltage scaling enabled. "
547 "Use of \"conservative\" governor is highly recommended.\n");
508} 548}
509 549
510 550
@@ -573,20 +613,50 @@ static int enable_arbiter_disable(void)
573 if (dev != NULL) { 613 if (dev != NULL) {
574 /* Enable access to port 0x22 */ 614 /* Enable access to port 0x22 */
575 pci_read_config_byte(dev, reg, &pci_cmd); 615 pci_read_config_byte(dev, reg, &pci_cmd);
576 if ( !(pci_cmd & 1<<7) ) { 616 if (!(pci_cmd & 1<<7)) {
577 pci_cmd |= 1<<7; 617 pci_cmd |= 1<<7;
578 pci_write_config_byte(dev, reg, pci_cmd); 618 pci_write_config_byte(dev, reg, pci_cmd);
619 pci_read_config_byte(dev, reg, &pci_cmd);
620 if (!(pci_cmd & 1<<7)) {
621 printk(KERN_ERR PFX
622 "Can't enable access to port 0x22.\n");
623 return 0;
624 }
579 } 625 }
580 return 1; 626 return 1;
581 } 627 }
582 return 0; 628 return 0;
583} 629}
584 630
631static int longhaul_setup_vt8235(void)
632{
633 struct pci_dev *dev;
634 u8 pci_cmd;
635
636 /* Find VT8235 southbridge */
637 dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
638 if (dev != NULL) {
639 /* Set transition time to max */
640 pci_read_config_byte(dev, 0xec, &pci_cmd);
641 pci_cmd &= ~(1 << 2);
642 pci_write_config_byte(dev, 0xec, pci_cmd);
643 pci_read_config_byte(dev, 0xe4, &pci_cmd);
644 pci_cmd &= ~(1 << 7);
645 pci_write_config_byte(dev, 0xe4, pci_cmd);
646 pci_read_config_byte(dev, 0xe5, &pci_cmd);
647 pci_cmd |= 1 << 7;
648 pci_write_config_byte(dev, 0xe5, pci_cmd);
649 return 1;
650 }
651 return 0;
652}
653
585static int __init longhaul_cpu_init(struct cpufreq_policy *policy) 654static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
586{ 655{
587 struct cpuinfo_x86 *c = cpu_data; 656 struct cpuinfo_x86 *c = cpu_data;
588 char *cpuname=NULL; 657 char *cpuname=NULL;
589 int ret; 658 int ret;
659 int vt8235_present;
590 660
591 /* Check what we have on this motherboard */ 661 /* Check what we have on this motherboard */
592 switch (c->x86_model) { 662 switch (c->x86_model) {
@@ -632,24 +702,24 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
632 break; 702 break;
633 703
634 case 9: 704 case 9:
635 cpu_model = CPU_NEHEMIAH;
636 longhaul_version = TYPE_POWERSAVER; 705 longhaul_version = TYPE_POWERSAVER;
637 numscales=32; 706 numscales = 32;
707 memcpy(clock_ratio,
708 nehemiah_clock_ratio,
709 sizeof(nehemiah_clock_ratio));
710 memcpy(eblcr_table, nehemiah_eblcr, sizeof(nehemiah_eblcr));
638 switch (c->x86_mask) { 711 switch (c->x86_mask) {
639 case 0 ... 1: 712 case 0 ... 1:
640 cpuname = "C3 'Nehemiah A' [C5N]"; 713 cpu_model = CPU_NEHEMIAH;
641 memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio)); 714 cpuname = "C3 'Nehemiah A' [C5XLOE]";
642 memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
643 break; 715 break;
644 case 2 ... 4: 716 case 2 ... 4:
645 cpuname = "C3 'Nehemiah B' [C5N]"; 717 cpu_model = CPU_NEHEMIAH;
646 memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio)); 718 cpuname = "C3 'Nehemiah B' [C5XLOH]";
647 memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
648 break; 719 break;
649 case 5 ... 15: 720 case 5 ... 15:
650 cpuname = "C3 'Nehemiah C' [C5N]"; 721 cpu_model = CPU_NEHEMIAH_C;
651 memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio)); 722 cpuname = "C3 'Nehemiah C' [C5P]";
652 memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));
653 break; 723 break;
654 } 724 }
655 break; 725 break;
@@ -670,15 +740,18 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
670 break; 740 break;
671 }; 741 };
672 742
743 /* Doesn't hurt */
744 vt8235_present = longhaul_setup_vt8235();
745
673 /* Find ACPI data for processor */ 746 /* Find ACPI data for processor */
674 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 747 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
675 &longhaul_walk_callback, NULL, (void *)&pr); 748 ACPI_UINT32_MAX, &longhaul_walk_callback,
749 NULL, (void *)&pr);
676 750
677 /* Check ACPI support for C3 state */ 751 /* Check ACPI support for C3 state */
678 if ((pr != NULL) && (longhaul_version == TYPE_POWERSAVER)) { 752 if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
679 cx = &pr->power.states[ACPI_STATE_C3]; 753 cx = &pr->power.states[ACPI_STATE_C3];
680 if (cx->address > 0 && 754 if (cx->address > 0 && cx->latency <= 1000) {
681 (cx->latency <= 1000 || ignore_latency != 0) ) {
682 longhaul_flags |= USE_ACPI_C3; 755 longhaul_flags |= USE_ACPI_C3;
683 goto print_support_type; 756 goto print_support_type;
684 } 757 }
@@ -688,8 +761,11 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
688 longhaul_flags |= USE_NORTHBRIDGE; 761 longhaul_flags |= USE_NORTHBRIDGE;
689 goto print_support_type; 762 goto print_support_type;
690 } 763 }
691 764 /* Use VT8235 southbridge if present */
692 /* No ACPI C3 or we can't use it */ 765 if (longhaul_version == TYPE_POWERSAVER && vt8235_present) {
766 longhaul_flags |= USE_VT8235;
767 goto print_support_type;
768 }
693 /* Check ACPI support for bus master arbiter disable */ 769 /* Check ACPI support for bus master arbiter disable */
694 if ((pr == NULL) || !(pr->flags.bm_control)) { 770 if ((pr == NULL) || !(pr->flags.bm_control)) {
695 printk(KERN_ERR PFX 771 printk(KERN_ERR PFX
@@ -698,18 +774,18 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
698 } 774 }
699 775
700print_support_type: 776print_support_type:
701 if (!(longhaul_flags & USE_NORTHBRIDGE)) { 777 if (longhaul_flags & USE_NORTHBRIDGE)
702 printk (KERN_INFO PFX "Using ACPI support.\n");
703 } else {
704 printk (KERN_INFO PFX "Using northbridge support.\n"); 778 printk (KERN_INFO PFX "Using northbridge support.\n");
705 } 779 else if (longhaul_flags & USE_VT8235)
780 printk (KERN_INFO PFX "Using VT8235 support.\n");
781 else
782 printk (KERN_INFO PFX "Using ACPI support.\n");
706 783
707 ret = longhaul_get_ranges(); 784 ret = longhaul_get_ranges();
708 if (ret != 0) 785 if (ret != 0)
709 return ret; 786 return ret;
710 787
711 if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) && 788 if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0))
712 (scale_voltage != 0))
713 longhaul_setup_voltagescaling(); 789 longhaul_setup_voltagescaling();
714 790
715 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 791 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
@@ -797,8 +873,6 @@ static void __exit longhaul_exit(void)
797 873
798module_param (scale_voltage, int, 0644); 874module_param (scale_voltage, int, 0644);
799MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); 875MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
800module_param(ignore_latency, int, 0644);
801MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test");
802 876
803MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); 877MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
804MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); 878MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h
index bc4682aad69b..bb0a04b1d1ab 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.h
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h
@@ -235,84 +235,14 @@ static int __initdata ezrat_eblcr[32] = {
235/* 235/*
236 * VIA C3 Nehemiah */ 236 * VIA C3 Nehemiah */
237 237
238static int __initdata nehemiah_a_clock_ratio[32] = { 238static int __initdata nehemiah_clock_ratio[32] = {
239 100, /* 0000 -> 10.0x */ 239 100, /* 0000 -> 10.0x */
240 160, /* 0001 -> 16.0x */ 240 160, /* 0001 -> 16.0x */
241 -1, /* 0010 -> RESERVED */ 241 40, /* 0010 -> 4.0x */
242 90, /* 0011 -> 9.0x */
243 95, /* 0100 -> 9.5x */
244 -1, /* 0101 -> RESERVED */
245 -1, /* 0110 -> RESERVED */
246 55, /* 0111 -> 5.5x */
247 60, /* 1000 -> 6.0x */
248 70, /* 1001 -> 7.0x */
249 80, /* 1010 -> 8.0x */
250 50, /* 1011 -> 5.0x */
251 65, /* 1100 -> 6.5x */
252 75, /* 1101 -> 7.5x */
253 85, /* 1110 -> 8.5x */
254 120, /* 1111 -> 12.0x */
255 100, /* 0000 -> 10.0x */
256 -1, /* 0001 -> RESERVED */
257 120, /* 0010 -> 12.0x */
258 90, /* 0011 -> 9.0x */
259 105, /* 0100 -> 10.5x */
260 115, /* 0101 -> 11.5x */
261 125, /* 0110 -> 12.5x */
262 135, /* 0111 -> 13.5x */
263 140, /* 1000 -> 14.0x */
264 150, /* 1001 -> 15.0x */
265 160, /* 1010 -> 16.0x */
266 130, /* 1011 -> 13.0x */
267 145, /* 1100 -> 14.5x */
268 155, /* 1101 -> 15.5x */
269 -1, /* 1110 -> RESERVED (13.0x) */
270 120, /* 1111 -> 12.0x */
271};
272
273static int __initdata nehemiah_b_clock_ratio[32] = {
274 100, /* 0000 -> 10.0x */
275 160, /* 0001 -> 16.0x */
276 -1, /* 0010 -> RESERVED */
277 90, /* 0011 -> 9.0x */
278 95, /* 0100 -> 9.5x */
279 -1, /* 0101 -> RESERVED */
280 -1, /* 0110 -> RESERVED */
281 55, /* 0111 -> 5.5x */
282 60, /* 1000 -> 6.0x */
283 70, /* 1001 -> 7.0x */
284 80, /* 1010 -> 8.0x */
285 50, /* 1011 -> 5.0x */
286 65, /* 1100 -> 6.5x */
287 75, /* 1101 -> 7.5x */
288 85, /* 1110 -> 8.5x */
289 120, /* 1111 -> 12.0x */
290 100, /* 0000 -> 10.0x */
291 110, /* 0001 -> 11.0x */
292 120, /* 0010 -> 12.0x */
293 90, /* 0011 -> 9.0x */
294 105, /* 0100 -> 10.5x */
295 115, /* 0101 -> 11.5x */
296 125, /* 0110 -> 12.5x */
297 135, /* 0111 -> 13.5x */
298 140, /* 1000 -> 14.0x */
299 150, /* 1001 -> 15.0x */
300 160, /* 1010 -> 16.0x */
301 130, /* 1011 -> 13.0x */
302 145, /* 1100 -> 14.5x */
303 155, /* 1101 -> 15.5x */
304 -1, /* 1110 -> RESERVED (13.0x) */
305 120, /* 1111 -> 12.0x */
306};
307
308static int __initdata nehemiah_c_clock_ratio[32] = {
309 100, /* 0000 -> 10.0x */
310 160, /* 0001 -> 16.0x */
311 40, /* 0010 -> RESERVED */
312 90, /* 0011 -> 9.0x */ 242 90, /* 0011 -> 9.0x */
313 95, /* 0100 -> 9.5x */ 243 95, /* 0100 -> 9.5x */
314 -1, /* 0101 -> RESERVED */ 244 -1, /* 0101 -> RESERVED */
315 45, /* 0110 -> RESERVED */ 245 45, /* 0110 -> 4.5x */
316 55, /* 0111 -> 5.5x */ 246 55, /* 0111 -> 5.5x */
317 60, /* 1000 -> 6.0x */ 247 60, /* 1000 -> 6.0x */
318 70, /* 1001 -> 7.0x */ 248 70, /* 1001 -> 7.0x */
@@ -340,84 +270,14 @@ static int __initdata nehemiah_c_clock_ratio[32] = {
340 120, /* 1111 -> 12.0x */ 270 120, /* 1111 -> 12.0x */
341}; 271};
342 272
343static int __initdata nehemiah_a_eblcr[32] = { 273static int __initdata nehemiah_eblcr[32] = {
344 50, /* 0000 -> 5.0x */
345 160, /* 0001 -> 16.0x */
346 -1, /* 0010 -> RESERVED */
347 100, /* 0011 -> 10.0x */
348 55, /* 0100 -> 5.5x */
349 -1, /* 0101 -> RESERVED */
350 -1, /* 0110 -> RESERVED */
351 95, /* 0111 -> 9.5x */
352 90, /* 1000 -> 9.0x */
353 70, /* 1001 -> 7.0x */
354 80, /* 1010 -> 8.0x */
355 60, /* 1011 -> 6.0x */
356 120, /* 1100 -> 12.0x */
357 75, /* 1101 -> 7.5x */
358 85, /* 1110 -> 8.5x */
359 65, /* 1111 -> 6.5x */
360 90, /* 0000 -> 9.0x */
361 -1, /* 0001 -> RESERVED */
362 120, /* 0010 -> 12.0x */
363 100, /* 0011 -> 10.0x */
364 135, /* 0100 -> 13.5x */
365 115, /* 0101 -> 11.5x */
366 125, /* 0110 -> 12.5x */
367 105, /* 0111 -> 10.5x */
368 130, /* 1000 -> 13.0x */
369 150, /* 1001 -> 15.0x */
370 160, /* 1010 -> 16.0x */
371 140, /* 1011 -> 14.0x */
372 120, /* 1100 -> 12.0x */
373 155, /* 1101 -> 15.5x */
374 -1, /* 1110 -> RESERVED (13.0x) */
375 145 /* 1111 -> 14.5x */
376 /* end of table */
377};
378static int __initdata nehemiah_b_eblcr[32] = {
379 50, /* 0000 -> 5.0x */
380 160, /* 0001 -> 16.0x */
381 -1, /* 0010 -> RESERVED */
382 100, /* 0011 -> 10.0x */
383 55, /* 0100 -> 5.5x */
384 -1, /* 0101 -> RESERVED */
385 -1, /* 0110 -> RESERVED */
386 95, /* 0111 -> 9.5x */
387 90, /* 1000 -> 9.0x */
388 70, /* 1001 -> 7.0x */
389 80, /* 1010 -> 8.0x */
390 60, /* 1011 -> 6.0x */
391 120, /* 1100 -> 12.0x */
392 75, /* 1101 -> 7.5x */
393 85, /* 1110 -> 8.5x */
394 65, /* 1111 -> 6.5x */
395 90, /* 0000 -> 9.0x */
396 110, /* 0001 -> 11.0x */
397 120, /* 0010 -> 12.0x */
398 100, /* 0011 -> 10.0x */
399 135, /* 0100 -> 13.5x */
400 115, /* 0101 -> 11.5x */
401 125, /* 0110 -> 12.5x */
402 105, /* 0111 -> 10.5x */
403 130, /* 1000 -> 13.0x */
404 150, /* 1001 -> 15.0x */
405 160, /* 1010 -> 16.0x */
406 140, /* 1011 -> 14.0x */
407 120, /* 1100 -> 12.0x */
408 155, /* 1101 -> 15.5x */
409 -1, /* 1110 -> RESERVED (13.0x) */
410 145 /* 1111 -> 14.5x */
411 /* end of table */
412};
413static int __initdata nehemiah_c_eblcr[32] = {
414 50, /* 0000 -> 5.0x */ 274 50, /* 0000 -> 5.0x */
415 160, /* 0001 -> 16.0x */ 275 160, /* 0001 -> 16.0x */
416 40, /* 0010 -> RESERVED */ 276 40, /* 0010 -> 4.0x */
417 100, /* 0011 -> 10.0x */ 277 100, /* 0011 -> 10.0x */
418 55, /* 0100 -> 5.5x */ 278 55, /* 0100 -> 5.5x */
419 -1, /* 0101 -> RESERVED */ 279 -1, /* 0101 -> RESERVED */
420 45, /* 0110 -> RESERVED */ 280 45, /* 0110 -> 4.5x */
421 95, /* 0111 -> 9.5x */ 281 95, /* 0111 -> 9.5x */
422 90, /* 1000 -> 9.0x */ 282 90, /* 1000 -> 9.0x */
423 70, /* 1001 -> 7.0x */ 283 70, /* 1001 -> 7.0x */
@@ -443,7 +303,6 @@ static int __initdata nehemiah_c_eblcr[32] = {
443 155, /* 1101 -> 15.5x */ 303 155, /* 1101 -> 15.5x */
444 -1, /* 1110 -> RESERVED (13.0x) */ 304 -1, /* 1110 -> RESERVED (13.0x) */
445 145 /* 1111 -> 14.5x */ 305 145 /* 1111 -> 14.5x */
446 /* end of table */
447}; 306};
448 307
449/* 308/*
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 2d6491672559..fe3b67005ebb 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -1289,7 +1289,11 @@ static unsigned int powernowk8_get (unsigned int cpu)
1289 if (query_current_values_with_pending_wait(data)) 1289 if (query_current_values_with_pending_wait(data))
1290 goto out; 1290 goto out;
1291 1291
1292 khz = find_khz_freq_from_fid(data->currfid); 1292 if (cpu_family == CPU_HW_PSTATE)
1293 khz = find_khz_freq_from_fiddid(data->currfid, data->currdid);
1294 else
1295 khz = find_khz_freq_from_fid(data->currfid);
1296
1293 1297
1294out: 1298out:
1295 set_cpus_allowed(current, oldmask); 1299 set_cpus_allowed(current, oldmask);