diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-22 20:50:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-22 20:50:22 -0400 |
commit | 2ee8099f2c2bc74a7c2fac7f83e12a5d651681d3 (patch) | |
tree | 433ebb87a3d5d02e7df3700c846ac9af632c55f3 /arch/i386 | |
parent | c03efdb202a4882f426ce49766859af4058c9b8a (diff) | |
parent | 24669f7d00d387799fc6a39452ab22d7f078f043 (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.c | 39 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.c | 186 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.h | 48 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 42 |
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 | */ | ||
397 | static int bios_with_sw_any_bug; | ||
398 | |||
399 | static int __init sw_any_bug_found(struct dmi_system_id *d) | ||
400 | { | ||
401 | bios_with_sw_any_bug = 1; | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static 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 | |||
390 | static int | 418 | static int |
391 | acpi_cpufreq_cpu_init ( | 419 | acpi_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 | ||
54 | static int cpu_model; | 55 | static int cpu_model; |
55 | static unsigned int numscales=16, numvscales; | 56 | static unsigned int numscales=16; |
56 | static unsigned int fsb; | 57 | static unsigned int fsb; |
57 | static int minvid, maxvid; | 58 | |
59 | static struct mV_pos *vrm_mV_table; | ||
60 | static unsigned char *mV_vrm_table; | ||
61 | struct f_msr { | ||
62 | unsigned char vrm; | ||
63 | }; | ||
64 | static struct f_msr f_msr_table[32]; | ||
65 | |||
66 | static unsigned int highest_speed, lowest_speed; /* kHz */ | ||
58 | static unsigned int minmult, maxmult; | 67 | static unsigned int minmult, maxmult; |
59 | static int can_scale_voltage; | 68 | static int can_scale_voltage; |
60 | static int vrmrev; | ||
61 | static struct acpi_processor *pr = NULL; | 69 | static struct acpi_processor *pr = NULL; |
62 | static struct acpi_processor_cx *cx = NULL; | 70 | static struct acpi_processor_cx *cx = NULL; |
71 | static int port22_en; | ||
63 | 72 | ||
64 | /* Module parameters */ | 73 | /* Module parameters */ |
65 | static int dont_scale_voltage; | 74 | static int scale_voltage; |
66 | 75 | static 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 */ |
72 | static int clock_ratio[32]; | 81 | static int clock_ratio[32]; |
73 | static int eblcr_table[32]; | 82 | static int eblcr_table[32]; |
74 | static int voltage_table[32]; | ||
75 | static unsigned int highest_speed, lowest_speed; /* kHz */ | 83 | static unsigned int highest_speed, lowest_speed; /* kHz */ |
76 | static int longhaul_version; | 84 | static int longhaul_version; |
77 | static struct cpufreq_frequency_table *longhaul_table; | 85 | static 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 | ||
127 | static void do_longhaul1(int cx_address, unsigned int clock_ratio_index) | 135 | static 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) | |||
446 | static void __init longhaul_setup_voltagescaling(void) | 465 | static 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 */ | ||
567 | static 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 | |||
543 | static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | 586 | static 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 | ||
732 | module_param (dont_scale_voltage, int, 0644); | 791 | module_param (scale_voltage, int, 0644); |
733 | MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor"); | 792 | MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); |
793 | module_param(ignore_latency, int, 0644); | ||
794 | MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test"); | ||
734 | 795 | ||
735 | MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); | 796 | MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); |
736 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); | 797 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); |
@@ -738,4 +799,3 @@ MODULE_LICENSE ("GPL"); | |||
738 | 799 | ||
739 | late_initcall(longhaul_init); | 800 | late_initcall(longhaul_init); |
740 | module_exit(longhaul_exit); | 801 | module_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 | */ |
453 | static int __initdata vrm85scales[32] = { | 453 | |
454 | 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, | 454 | struct 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 | |||
459 | static 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 | |||
470 | static 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 | |||
477 | static 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 | ||
460 | static int __initdata mobilevrmscales[32] = { | 488 | static 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 | */ | ||
388 | static int bios_with_sw_any_bug; | ||
389 | static 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 | |||
396 | static 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) { |