aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-22 20:50:22 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-22 20:50:22 -0400
commit2ee8099f2c2bc74a7c2fac7f83e12a5d651681d3 (patch)
tree433ebb87a3d5d02e7df3700c846ac9af632c55f3 /arch/i386
parentc03efdb202a4882f426ce49766859af4058c9b8a (diff)
parent24669f7d00d387799fc6a39452ab22d7f078f043 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
* master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq: [CPUFREQ] sw_any_bug_dmi_table can be used on resume, so it isn't initdata [CPUFREQ] Fix some more CPU hotplug locking. [CPUFREQ] Workaround for BIOS bug in software coordination of frequency [CPUFREQ] Longhaul - Add voltage scaling to driver [CPUFREQ] Fix sparse warning in ondemand [CPUFREQ] make drivers/cpufreq/cpufreq_ondemand.c:powersave_bias_target() static [CPUFREQ] Longhaul - Add ignore_latency option [CPUFREQ] Longhaul - Disable arbiter [CPUFREQ][2/2] ondemand: updated add powersave_bias tunable [CPUFREQ][1/2] ondemand: updated tune for hardware coordination [CPUFREQ] Fix typo.
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c39
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c186
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.h48
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c42
4 files changed, 240 insertions, 75 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index e6ea00edcb54..ea19d091fd41 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -32,6 +32,7 @@
32#include <linux/seq_file.h> 32#include <linux/seq_file.h>
33#include <linux/compiler.h> 33#include <linux/compiler.h>
34#include <linux/sched.h> /* current */ 34#include <linux/sched.h> /* current */
35#include <linux/dmi.h>
35#include <asm/io.h> 36#include <asm/io.h>
36#include <asm/delay.h> 37#include <asm/delay.h>
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
@@ -387,6 +388,33 @@ static int acpi_cpufreq_early_init_acpi(void)
387 return acpi_processor_preregister_performance(acpi_perf_data); 388 return acpi_processor_preregister_performance(acpi_perf_data);
388} 389}
389 390
391/*
392 * Some BIOSes do SW_ANY coordination internally, either set it up in hw
393 * or do it in BIOS firmware and won't inform about it to OS. If not
394 * detected, this has a side effect of making CPU run at a different speed
395 * than OS intended it to run at. Detect it and handle it cleanly.
396 */
397static int bios_with_sw_any_bug;
398
399static int __init sw_any_bug_found(struct dmi_system_id *d)
400{
401 bios_with_sw_any_bug = 1;
402 return 0;
403}
404
405static struct dmi_system_id __initdata sw_any_bug_dmi_table[] = {
406 {
407 .callback = sw_any_bug_found,
408 .ident = "Supermicro Server X6DLP",
409 .matches = {
410 DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
411 DMI_MATCH(DMI_BIOS_VERSION, "080010"),
412 DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
413 },
414 },
415 { }
416};
417
390static int 418static int
391acpi_cpufreq_cpu_init ( 419acpi_cpufreq_cpu_init (
392 struct cpufreq_policy *policy) 420 struct cpufreq_policy *policy)
@@ -422,8 +450,17 @@ acpi_cpufreq_cpu_init (
422 * coordination is required. 450 * coordination is required.
423 */ 451 */
424 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || 452 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
425 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) 453 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
426 policy->cpus = perf->shared_cpu_map; 454 policy->cpus = perf->shared_cpu_map;
455 }
456
457#ifdef CONFIG_SMP
458 dmi_check_system(sw_any_bug_dmi_table);
459 if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
460 policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
461 policy->cpus = cpu_core_map[cpu];
462 }
463#endif
427 464
428 if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { 465 if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
429 acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; 466 acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 4f2c3aeef724..f5cc9f5c9bab 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -27,6 +27,7 @@
27#include <linux/moduleparam.h> 27#include <linux/moduleparam.h>
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/cpufreq.h> 29#include <linux/cpufreq.h>
30#include <linux/pci.h>
30#include <linux/slab.h> 31#include <linux/slab.h>
31#include <linux/string.h> 32#include <linux/string.h>
32 33
@@ -52,18 +53,26 @@
52#define CPU_NEHEMIAH 5 53#define CPU_NEHEMIAH 5
53 54
54static int cpu_model; 55static int cpu_model;
55static unsigned int numscales=16, numvscales; 56static unsigned int numscales=16;
56static unsigned int fsb; 57static unsigned int fsb;
57static int minvid, maxvid; 58
59static struct mV_pos *vrm_mV_table;
60static unsigned char *mV_vrm_table;
61struct f_msr {
62 unsigned char vrm;
63};
64static struct f_msr f_msr_table[32];
65
66static unsigned int highest_speed, lowest_speed; /* kHz */
58static unsigned int minmult, maxmult; 67static unsigned int minmult, maxmult;
59static int can_scale_voltage; 68static int can_scale_voltage;
60static int vrmrev;
61static struct acpi_processor *pr = NULL; 69static struct acpi_processor *pr = NULL;
62static struct acpi_processor_cx *cx = NULL; 70static struct acpi_processor_cx *cx = NULL;
71static int port22_en;
63 72
64/* Module parameters */ 73/* Module parameters */
65static int dont_scale_voltage; 74static int scale_voltage;
66 75static int ignore_latency;
67 76
68#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) 77#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
69 78
@@ -71,7 +80,6 @@ static int dont_scale_voltage;
71/* Clock ratios multiplied by 10 */ 80/* Clock ratios multiplied by 10 */
72static int clock_ratio[32]; 81static int clock_ratio[32];
73static int eblcr_table[32]; 82static int eblcr_table[32];
74static int voltage_table[32];
75static unsigned int highest_speed, lowest_speed; /* kHz */ 83static unsigned int highest_speed, lowest_speed; /* kHz */
76static int longhaul_version; 84static int longhaul_version;
77static struct cpufreq_frequency_table *longhaul_table; 85static struct cpufreq_frequency_table *longhaul_table;
@@ -124,10 +132,9 @@ static int longhaul_get_cpu_mult(void)
124 132
125/* For processor with BCR2 MSR */ 133/* For processor with BCR2 MSR */
126 134
127static void do_longhaul1(int cx_address, unsigned int clock_ratio_index) 135static void do_longhaul1(unsigned int clock_ratio_index)
128{ 136{
129 union msr_bcr2 bcr2; 137 union msr_bcr2 bcr2;
130 u32 t;
131 138
132 rdmsrl(MSR_VIA_BCR2, bcr2.val); 139 rdmsrl(MSR_VIA_BCR2, bcr2.val);
133 /* Enable software clock multiplier */ 140 /* Enable software clock multiplier */
@@ -136,13 +143,11 @@ static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
136 143
137 /* Sync to timer tick */ 144 /* Sync to timer tick */
138 safe_halt(); 145 safe_halt();
139 ACPI_FLUSH_CPU_CACHE();
140 /* Change frequency on next halt or sleep */ 146 /* Change frequency on next halt or sleep */
141 wrmsrl(MSR_VIA_BCR2, bcr2.val); 147 wrmsrl(MSR_VIA_BCR2, bcr2.val);
142 /* Invoke C3 */ 148 /* Invoke transition */
143 inb(cx_address); 149 ACPI_FLUSH_CPU_CACHE();
144 /* Dummy op - must do something useless after P_LVL3 read */ 150 halt();
145 t = inl(acpi_fadt.xpm_tmr_blk.address);
146 151
147 /* Disable software clock multiplier */ 152 /* Disable software clock multiplier */
148 local_irq_disable(); 153 local_irq_disable();
@@ -164,11 +169,16 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
164 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; 169 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
165 longhaul.bits.EnableSoftBusRatio = 1; 170 longhaul.bits.EnableSoftBusRatio = 1;
166 171
172 if (can_scale_voltage) {
173 longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
174 longhaul.bits.EnableSoftVID = 1;
175 }
176
167 /* Sync to timer tick */ 177 /* Sync to timer tick */
168 safe_halt(); 178 safe_halt();
169 ACPI_FLUSH_CPU_CACHE();
170 /* Change frequency on next halt or sleep */ 179 /* Change frequency on next halt or sleep */
171 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); 180 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
181 ACPI_FLUSH_CPU_CACHE();
172 /* Invoke C3 */ 182 /* Invoke C3 */
173 inb(cx_address); 183 inb(cx_address);
174 /* Dummy op - must do something useless after P_LVL3 read */ 184 /* Dummy op - must do something useless after P_LVL3 read */
@@ -227,10 +237,13 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
227 outb(0xFF,0xA1); /* Overkill */ 237 outb(0xFF,0xA1); /* Overkill */
228 outb(0xFE,0x21); /* TMR0 only */ 238 outb(0xFE,0x21); /* TMR0 only */
229 239
230 /* Disable bus master arbitration */ 240 if (pr->flags.bm_control) {
231 if (pr->flags.bm_check) { 241 /* Disable bus master arbitration */
232 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, 242 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
233 ACPI_MTX_DO_NOT_LOCK); 243 ACPI_MTX_DO_NOT_LOCK);
244 } else if (port22_en) {
245 /* Disable AGP and PCI arbiters */
246 outb(3, 0x22);
234 } 247 }
235 248
236 switch (longhaul_version) { 249 switch (longhaul_version) {
@@ -244,7 +257,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
244 */ 257 */
245 case TYPE_LONGHAUL_V1: 258 case TYPE_LONGHAUL_V1:
246 case TYPE_LONGHAUL_V2: 259 case TYPE_LONGHAUL_V2:
247 do_longhaul1(cx->address, clock_ratio_index); 260 do_longhaul1(clock_ratio_index);
248 break; 261 break;
249 262
250 /* 263 /*
@@ -259,14 +272,20 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
259 * to work in practice. 272 * to work in practice.
260 */ 273 */
261 case TYPE_POWERSAVER: 274 case TYPE_POWERSAVER:
275 /* Don't allow wakeup */
276 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
277 ACPI_MTX_DO_NOT_LOCK);
262 do_powersaver(cx->address, clock_ratio_index); 278 do_powersaver(cx->address, clock_ratio_index);
263 break; 279 break;
264 } 280 }
265 281
266 /* Enable bus master arbitration */ 282 if (pr->flags.bm_control) {
267 if (pr->flags.bm_check) { 283 /* Enable bus master arbitration */
268 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, 284 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
269 ACPI_MTX_DO_NOT_LOCK); 285 ACPI_MTX_DO_NOT_LOCK);
286 } else if (port22_en) {
287 /* Enable arbiters */
288 outb(0, 0x22);
270 } 289 }
271 290
272 outb(pic2_mask,0xA1); /* restore mask */ 291 outb(pic2_mask,0xA1); /* restore mask */
@@ -446,53 +465,57 @@ static int __init longhaul_get_ranges(void)
446static void __init longhaul_setup_voltagescaling(void) 465static void __init longhaul_setup_voltagescaling(void)
447{ 466{
448 union msr_longhaul longhaul; 467 union msr_longhaul longhaul;
468 struct mV_pos minvid, maxvid;
469 unsigned int j, speed, pos, kHz_step, numvscales;
449 470
450 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); 471 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
451 472 if (!(longhaul.bits.RevisionID & 1)) {
452 if (!(longhaul.bits.RevisionID & 1)) 473 printk(KERN_INFO PFX "Voltage scaling not supported by CPU.\n");
453 return; 474 return;
475 }
476
477 if (!longhaul.bits.VRMRev) {
478 printk (KERN_INFO PFX "VRM 8.5\n");
479 vrm_mV_table = &vrm85_mV[0];
480 mV_vrm_table = &mV_vrm85[0];
481 } else {
482 printk (KERN_INFO PFX "Mobile VRM\n");
483 vrm_mV_table = &mobilevrm_mV[0];
484 mV_vrm_table = &mV_mobilevrm[0];
485 }
454 486
455 minvid = longhaul.bits.MinimumVID; 487 minvid = vrm_mV_table[longhaul.bits.MinimumVID];
456 maxvid = longhaul.bits.MaximumVID; 488 maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
457 vrmrev = longhaul.bits.VRMRev; 489 numvscales = maxvid.pos - minvid.pos + 1;
490 kHz_step = (highest_speed - lowest_speed) / numvscales;
458 491
459 if (minvid == 0 || maxvid == 0) { 492 if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
460 printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. " 493 printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
461 "Voltage scaling disabled.\n", 494 "Voltage scaling disabled.\n",
462 minvid/1000, minvid%1000, maxvid/1000, maxvid%1000); 495 minvid.mV/1000, minvid.mV%1000, maxvid.mV/1000, maxvid.mV%1000);
463 return; 496 return;
464 } 497 }
465 498
466 if (minvid == maxvid) { 499 if (minvid.mV == maxvid.mV) {
467 printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are " 500 printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are "
468 "both %d.%03d. Voltage scaling disabled\n", 501 "both %d.%03d. Voltage scaling disabled\n",
469 maxvid/1000, maxvid%1000); 502 maxvid.mV/1000, maxvid.mV%1000);
470 return; 503 return;
471 } 504 }
472 505
473 if (vrmrev==0) { 506 printk(KERN_INFO PFX "Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n",
474 dprintk ("VRM 8.5\n"); 507 maxvid.mV/1000, maxvid.mV%1000,
475 memcpy (voltage_table, vrm85scales, sizeof(voltage_table)); 508 minvid.mV/1000, minvid.mV%1000,
476 numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25; 509 numvscales);
477 } else { 510
478 dprintk ("Mobile VRM\n"); 511 j = 0;
479 memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table)); 512 while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
480 numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5; 513 speed = longhaul_table[j].frequency;
514 pos = (speed - lowest_speed) / kHz_step + minvid.pos;
515 f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
516 j++;
481 } 517 }
482 518
483 /* Current voltage isn't readable at first, so we need to
484 set it to a known value. The spec says to use maxvid */
485 longhaul.bits.RevisionKey = longhaul.bits.RevisionID; /* FIXME: This is bad. */
486 longhaul.bits.EnableSoftVID = 1;
487 longhaul.bits.SoftVID = maxvid;
488 wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
489
490 minvid = voltage_table[minvid];
491 maxvid = voltage_table[maxvid];
492
493 dprintk ("Min VID=%d.%03d Max VID=%d.%03d, %d possible voltage scales\n",
494 maxvid/1000, maxvid%1000, minvid/1000, minvid%1000, numvscales);
495
496 can_scale_voltage = 1; 519 can_scale_voltage = 1;
497} 520}
498 521
@@ -540,21 +563,33 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
540 return 1; 563 return 1;
541} 564}
542 565
566/* VIA don't support PM2 reg, but have something similar */
567static int enable_arbiter_disable(void)
568{
569 struct pci_dev *dev;
570 u8 pci_cmd;
571
572 /* Find PLE133 host bridge */
573 dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL);
574 if (dev != NULL) {
575 /* Enable access to port 0x22 */
576 pci_read_config_byte(dev, 0x78, &pci_cmd);
577 if ( !(pci_cmd & 1<<7) ) {
578 pci_cmd |= 1<<7;
579 pci_write_config_byte(dev, 0x78, pci_cmd);
580 }
581 return 1;
582 }
583 return 0;
584}
585
543static int __init longhaul_cpu_init(struct cpufreq_policy *policy) 586static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
544{ 587{
545 struct cpuinfo_x86 *c = cpu_data; 588 struct cpuinfo_x86 *c = cpu_data;
546 char *cpuname=NULL; 589 char *cpuname=NULL;
547 int ret; 590 int ret;
548 591
549 /* Check ACPI support for C3 state */ 592 /* Check what we have on this motherboard */
550 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
551 &longhaul_walk_callback, NULL, (void *)&pr);
552 if (pr == NULL) goto err_acpi;
553
554 cx = &pr->power.states[ACPI_STATE_C3];
555 if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
556
557 /* Now check what we have on this motherboard */
558 switch (c->x86_model) { 593 switch (c->x86_model) {
559 case 6: 594 case 6:
560 cpu_model = CPU_SAMUEL; 595 cpu_model = CPU_SAMUEL;
@@ -636,12 +671,36 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
636 break; 671 break;
637 }; 672 };
638 673
674 /* Find ACPI data for processor */
675 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
676 &longhaul_walk_callback, NULL, (void *)&pr);
677 if (pr == NULL)
678 goto err_acpi;
679
680 if (longhaul_version == TYPE_POWERSAVER) {
681 /* Check ACPI support for C3 state */
682 cx = &pr->power.states[ACPI_STATE_C3];
683 if (cx->address == 0 ||
684 (cx->latency > 1000 && ignore_latency == 0) )
685 goto err_acpi;
686
687 } else {
688 /* Check ACPI support for bus master arbiter disable */
689 if (!pr->flags.bm_control) {
690 if (!enable_arbiter_disable()) {
691 printk(KERN_ERR PFX "No ACPI support. No VT8601 host bridge. Aborting.\n");
692 return -ENODEV;
693 } else
694 port22_en = 1;
695 }
696 }
697
639 ret = longhaul_get_ranges(); 698 ret = longhaul_get_ranges();
640 if (ret != 0) 699 if (ret != 0)
641 return ret; 700 return ret;
642 701
643 if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) && 702 if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
644 (dont_scale_voltage==0)) 703 (scale_voltage != 0))
645 longhaul_setup_voltagescaling(); 704 longhaul_setup_voltagescaling();
646 705
647 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 706 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
@@ -729,8 +788,10 @@ static void __exit longhaul_exit(void)
729 kfree(longhaul_table); 788 kfree(longhaul_table);
730} 789}
731 790
732module_param (dont_scale_voltage, int, 0644); 791module_param (scale_voltage, int, 0644);
733MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor"); 792MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
793module_param(ignore_latency, int, 0644);
794MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test");
734 795
735MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); 796MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
736MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); 797MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
@@ -738,4 +799,3 @@ MODULE_LICENSE ("GPL");
738 799
739late_initcall(longhaul_init); 800late_initcall(longhaul_init);
740module_exit(longhaul_exit); 801module_exit(longhaul_exit);
741
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h
index d3a95d77ee85..bc4682aad69b 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.h
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h
@@ -450,17 +450,45 @@ static int __initdata nehemiah_c_eblcr[32] = {
450 * Voltage scales. Div/Mod by 1000 to get actual voltage. 450 * Voltage scales. Div/Mod by 1000 to get actual voltage.
451 * Which scale to use depends on the VRM type in use. 451 * Which scale to use depends on the VRM type in use.
452 */ 452 */
453static int __initdata vrm85scales[32] = { 453
454 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, 454struct mV_pos {
455 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300, 455 unsigned short mV;
456 1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725, 456 unsigned short pos;
457 1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325, 457};
458
459static struct mV_pos __initdata vrm85_mV[32] = {
460 {1250, 8}, {1200, 6}, {1150, 4}, {1100, 2},
461 {1050, 0}, {1800, 30}, {1750, 28}, {1700, 26},
462 {1650, 24}, {1600, 22}, {1550, 20}, {1500, 18},
463 {1450, 16}, {1400, 14}, {1350, 12}, {1300, 10},
464 {1275, 9}, {1225, 7}, {1175, 5}, {1125, 3},
465 {1075, 1}, {1825, 31}, {1775, 29}, {1725, 27},
466 {1675, 25}, {1625, 23}, {1575, 21}, {1525, 19},
467 {1475, 17}, {1425, 15}, {1375, 13}, {1325, 11}
468};
469
470static unsigned char __initdata mV_vrm85[32] = {
471 0x04, 0x14, 0x03, 0x13, 0x02, 0x12, 0x01, 0x11,
472 0x00, 0x10, 0x0f, 0x1f, 0x0e, 0x1e, 0x0d, 0x1d,
473 0x0c, 0x1c, 0x0b, 0x1b, 0x0a, 0x1a, 0x09, 0x19,
474 0x08, 0x18, 0x07, 0x17, 0x06, 0x16, 0x05, 0x15
475};
476
477static struct mV_pos __initdata mobilevrm_mV[32] = {
478 {1750, 31}, {1700, 30}, {1650, 29}, {1600, 28},
479 {1550, 27}, {1500, 26}, {1450, 25}, {1400, 24},
480 {1350, 23}, {1300, 22}, {1250, 21}, {1200, 20},
481 {1150, 19}, {1100, 18}, {1050, 17}, {1000, 16},
482 {975, 15}, {950, 14}, {925, 13}, {900, 12},
483 {875, 11}, {850, 10}, {825, 9}, {800, 8},
484 {775, 7}, {750, 6}, {725, 5}, {700, 4},
485 {675, 3}, {650, 2}, {625, 1}, {600, 0}
458}; 486};
459 487
460static int __initdata mobilevrmscales[32] = { 488static unsigned char __initdata mV_mobilevrm[32] = {
461 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, 489 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
462 1600, 1550, 1500, 1450, 1500, 1350, 1300, -1, 490 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
463 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, 491 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
464 1075, 1050, 1025, 1000, 975, 950, 925, -1, 492 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
465}; 493};
466 494
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index b77f1358bd79..7a9325349e94 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -23,6 +23,7 @@
23 23
24#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI 24#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
25#include <linux/acpi.h> 25#include <linux/acpi.h>
26#include <linux/dmi.h>
26#include <acpi/processor.h> 27#include <acpi/processor.h>
27#endif 28#endif
28 29
@@ -377,6 +378,35 @@ static int centrino_cpu_early_init_acpi(void)
377 return 0; 378 return 0;
378} 379}
379 380
381
382/*
383 * Some BIOSes do SW_ANY coordination internally, either set it up in hw
384 * or do it in BIOS firmware and won't inform about it to OS. If not
385 * detected, this has a side effect of making CPU run at a different speed
386 * than OS intended it to run at. Detect it and handle it cleanly.
387 */
388static int bios_with_sw_any_bug;
389static int __init sw_any_bug_found(struct dmi_system_id *d)
390{
391 bios_with_sw_any_bug = 1;
392 return 0;
393}
394
395
396static struct dmi_system_id sw_any_bug_dmi_table[] = {
397 {
398 .callback = sw_any_bug_found,
399 .ident = "Supermicro Server X6DLP",
400 .matches = {
401 DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
402 DMI_MATCH(DMI_BIOS_VERSION, "080010"),
403 DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
404 },
405 },
406 { }
407};
408
409
380/* 410/*
381 * centrino_cpu_init_acpi - register with ACPI P-States library 411 * centrino_cpu_init_acpi - register with ACPI P-States library
382 * 412 *
@@ -398,14 +428,24 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
398 dprintk(PFX "obtaining ACPI data failed\n"); 428 dprintk(PFX "obtaining ACPI data failed\n");
399 return -EIO; 429 return -EIO;
400 } 430 }
431
401 policy->shared_type = p->shared_type; 432 policy->shared_type = p->shared_type;
402 /* 433 /*
403 * Will let policy->cpus know about dependency only when software 434 * Will let policy->cpus know about dependency only when software
404 * coordination is required. 435 * coordination is required.
405 */ 436 */
406 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || 437 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
407 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) 438 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
408 policy->cpus = p->shared_cpu_map; 439 policy->cpus = p->shared_cpu_map;
440 }
441
442#ifdef CONFIG_SMP
443 dmi_check_system(sw_any_bug_dmi_table);
444 if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
445 policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
446 policy->cpus = cpu_core_map[cpu];
447 }
448#endif
409 449
410 /* verify the acpi_data */ 450 /* verify the acpi_data */
411 if (p->state_count <= 1) { 451 if (p->state_count <= 1) {