aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c73
1 files changed, 28 insertions, 45 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index b679aaf0c6b4..849a6dfdfea8 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -51,6 +51,7 @@
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)
@@ -349,67 +350,47 @@ static int guess_fsb(int mult)
349 350
350static int __init longhaul_get_ranges(void) 351static int __init longhaul_get_ranges(void)
351{ 352{
352 unsigned long invalue;
353 unsigned int ezra_t_multipliers[32]= {
354 90, 30, 40, 100, 55, 35, 45, 95,
355 50, 70, 80, 60, 120, 75, 85, 65,
356 -1, 110, 120, -1, 135, 115, 125, 105,
357 130, 150, 160, 140, -1, 155, -1, 145 };
358 unsigned int j, k = 0; 353 unsigned int j, k = 0;
359 union msr_longhaul longhaul; 354 int mult;
360 int mult = 0;
361 355
356 /* Get current frequency */
357 mult = longhaul_get_cpu_mult();
358 if (mult == -1) {
359 printk(KERN_INFO PFX "Invalid (reserved) multiplier!\n");
360 return -EINVAL;
361 }
362 fsb = guess_fsb(mult);
363 if (fsb == 0) {
364 printk(KERN_INFO PFX "Invalid (reserved) FSB!\n");
365 return -EINVAL;
366 }
367 /* Get max multiplier - as we always did.
368 * Longhaul MSR is usefull only when voltage scaling is enabled.
369 * C3 is booting at max anyway. */
370 maxmult = mult;
371 /* Get min multiplier */
362 switch (longhaul_version) { 372 switch (longhaul_version) {
363 case TYPE_LONGHAUL_V1: 373 case TYPE_LONGHAUL_V1:
364 case TYPE_LONGHAUL_V2: 374 case TYPE_LONGHAUL_V2:
365 /* Ugh, Longhaul v1 didn't have the min/max MSRs.
366 Assume min=3.0x & max = whatever we booted at. */
367 minmult = 30; 375 minmult = 30;
368 maxmult = mult = longhaul_get_cpu_mult();
369 break; 376 break;
370 377
371 case TYPE_POWERSAVER: 378 case TYPE_POWERSAVER:
372 /* Ezra-T */ 379 /* Ezra-T */
373 if (cpu_model==CPU_EZRA_T) { 380 if (cpu_model == CPU_EZRA_T)
374 minmult = 30; 381 minmult = 30;
375 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
376 invalue = longhaul.bits.MaxMHzBR;
377 if (longhaul.bits.MaxMHzBR4)
378 invalue += 16;
379 maxmult = mult = ezra_t_multipliers[invalue];
380 break;
381 }
382
383 /* Nehemiah */ 382 /* Nehemiah */
384 if (cpu_model==CPU_NEHEMIAH) { 383 else if (cpu_model == CPU_NEHEMIAH)
385 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); 384 minmult = 50;
386 385 /* Nehemiah C */
387 /* 386 else if (cpu_model == CPU_NEHEMIAH_C)
388 * TODO: This code works, but raises a lot of questions. 387 minmult = 40;
389 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's. 388 break;
390 * We get around this by using a hardcoded multiplier of 4.0x
391 * for the minimimum speed, and the speed we booted up at for the max.
392 * This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
393 * - According to some VIA documentation EBLCR is only
394 * in pre-Nehemiah C3s. How this still works is a mystery.
395 * We're possibly using something undocumented and unsupported,
396 * But it works, so we don't grumble.
397 */
398 minmult=40;
399 maxmult = mult = longhaul_get_cpu_mult();
400 break;
401 }
402 } 389 }
403 fsb = guess_fsb(mult);
404 390
405 dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n", 391 dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
406 minmult/10, minmult%10, maxmult/10, maxmult%10); 392 minmult/10, minmult%10, maxmult/10, maxmult%10);
407 393
408 if (fsb == 0) {
409 printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
410 return -EINVAL;
411 }
412
413 highest_speed = calc_speed(maxmult); 394 highest_speed = calc_speed(maxmult);
414 lowest_speed = calc_speed(minmult); 395 lowest_speed = calc_speed(minmult);
415 dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb, 396 dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb,
@@ -634,21 +615,23 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
634 break; 615 break;
635 616
636 case 9: 617 case 9:
637 cpu_model = CPU_NEHEMIAH;
638 longhaul_version = TYPE_POWERSAVER; 618 longhaul_version = TYPE_POWERSAVER;
639 numscales=32; 619 numscales=32;
640 switch (c->x86_mask) { 620 switch (c->x86_mask) {
641 case 0 ... 1: 621 case 0 ... 1:
622 cpu_model = CPU_NEHEMIAH;
642 cpuname = "C3 'Nehemiah A' [C5N]"; 623 cpuname = "C3 'Nehemiah A' [C5N]";
643 memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio)); 624 memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio));
644 memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr)); 625 memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
645 break; 626 break;
646 case 2 ... 4: 627 case 2 ... 4:
628 cpu_model = CPU_NEHEMIAH;
647 cpuname = "C3 'Nehemiah B' [C5N]"; 629 cpuname = "C3 'Nehemiah B' [C5N]";
648 memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio)); 630 memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio));
649 memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr)); 631 memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
650 break; 632 break;
651 case 5 ... 15: 633 case 5 ... 15:
634 cpu_model = CPU_NEHEMIAH_C;
652 cpuname = "C3 'Nehemiah C' [C5N]"; 635 cpuname = "C3 'Nehemiah C' [C5N]";
653 memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio)); 636 memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio));
654 memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr)); 637 memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));