diff options
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.c | 60 |
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 */ |
| 77 | static int scale_voltage; | 77 | static int scale_voltage; |
| 78 | static int disable_acpi_c3; | 78 | static int disable_acpi_c3; |
| 79 | static 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 | 279 | retry_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. */ | ||
| 959 | module_param (disable_acpi_c3, int, 0644); | 1007 | module_param (disable_acpi_c3, int, 0644); |
| 960 | MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support"); | 1008 | MODULE_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. */ | ||
| 962 | module_param (scale_voltage, int, 0644); | 1011 | module_param (scale_voltage, int, 0644); |
| 963 | MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); | 1012 | MODULE_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. */ | ||
| 1016 | module_param(revid_errata, int, 0644); | ||
| 1017 | MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID"); | ||
| 964 | 1018 | ||
| 965 | MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); | 1019 | MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); |
| 966 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); | 1020 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); |
