aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu/cpufreq/longhaul.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/cpu/cpufreq/longhaul.c')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c60
1 files changed, 57 insertions, 3 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index ef8f0bc3fc71..f0cce3c2dc3a 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -76,6 +76,7 @@ static unsigned int longhaul_index;
76/* Module parameters */ 76/* Module parameters */
77static int scale_voltage; 77static int scale_voltage;
78static int disable_acpi_c3; 78static int disable_acpi_c3;
79static int revid_errata;
79 80
80#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) 81#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
81 82
@@ -168,7 +169,10 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index,
168 169
169 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); 170 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
170 /* Setup new frequency */ 171 /* Setup new frequency */
171 longhaul.bits.RevisionKey = longhaul.bits.RevisionID; 172 if (!revid_errata)
173 longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
174 else
175 longhaul.bits.RevisionKey = 0;
172 longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; 176 longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
173 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; 177 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
174 /* Setup new voltage */ 178 /* Setup new voltage */
@@ -272,7 +276,7 @@ static void longhaul_setstate(unsigned int table_index)
272 276
273 dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", 277 dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
274 fsb, mult/10, mult%10, print_speed(speed/1000)); 278 fsb, mult/10, mult%10, print_speed(speed/1000));
275 279retry_loop:
276 preempt_disable(); 280 preempt_disable();
277 local_irq_save(flags); 281 local_irq_save(flags);
278 282
@@ -344,6 +348,47 @@ static void longhaul_setstate(unsigned int table_index)
344 preempt_enable(); 348 preempt_enable();
345 349
346 freqs.new = calc_speed(longhaul_get_cpu_mult()); 350 freqs.new = calc_speed(longhaul_get_cpu_mult());
351 /* Check if requested frequency is set. */
352 if (unlikely(freqs.new != speed)) {
353 printk(KERN_INFO PFX "Failed to set requested frequency!\n");
354 /* Revision ID = 1 but processor is expecting revision key
355 * equal to 0. Jumpers at the bottom of processor will change
356 * multiplier and FSB, but will not change bits in Longhaul
357 * MSR nor enable voltage scaling. */
358 if (!revid_errata) {
359 printk(KERN_INFO PFX "Enabling \"Ignore Revision ID\" "
360 "option.\n");
361 revid_errata = 1;
362 msleep(200);
363 goto retry_loop;
364 }
365 /* Why ACPI C3 sometimes doesn't work is a mystery for me.
366 * But it does happen. Processor is entering ACPI C3 state,
367 * but it doesn't change frequency. I tried poking various
368 * bits in northbridge registers, but without success. */
369 if (longhaul_flags & USE_ACPI_C3) {
370 printk(KERN_INFO PFX "Disabling ACPI C3 support.\n");
371 longhaul_flags &= ~USE_ACPI_C3;
372 if (revid_errata) {
373 printk(KERN_INFO PFX "Disabling \"Ignore "
374 "Revision ID\" option.\n");
375 revid_errata = 0;
376 }
377 msleep(200);
378 goto retry_loop;
379 }
380 /* This shouldn't happen. Longhaul ver. 2 was reported not
381 * working on processors without voltage scaling, but with
382 * RevID = 1. RevID errata will make things right. Just
383 * to be 100% sure. */
384 if (longhaul_version == TYPE_LONGHAUL_V2) {
385 printk(KERN_INFO PFX "Switching to Longhaul ver. 1\n");
386 longhaul_version = TYPE_LONGHAUL_V1;
387 msleep(200);
388 goto retry_loop;
389 }
390 }
391 /* Report true CPU frequency */
347 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 392 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
348 393
349 if (!bm_timeout) 394 if (!bm_timeout)
@@ -956,11 +1001,20 @@ static void __exit longhaul_exit(void)
956 kfree(longhaul_table); 1001 kfree(longhaul_table);
957} 1002}
958 1003
1004/* Even if BIOS is exporting ACPI C3 state, and it is used
1005 * with success when CPU is idle, this state doesn't
1006 * trigger frequency transition in some cases. */
959module_param (disable_acpi_c3, int, 0644); 1007module_param (disable_acpi_c3, int, 0644);
960MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support"); 1008MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
961 1009/* Change CPU voltage with frequency. Very usefull to save
1010 * power, but most VIA C3 processors aren't supporting it. */
962module_param (scale_voltage, int, 0644); 1011module_param (scale_voltage, int, 0644);
963MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); 1012MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
1013/* Force revision key to 0 for processors which doesn't
1014 * support voltage scaling, but are introducing itself as
1015 * such. */
1016module_param(revid_errata, int, 0644);
1017MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID");
964 1018
965MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); 1019MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
966MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); 1020MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");