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.c97
1 files changed, 56 insertions, 41 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 43bbf948d45d..f5cc9f5c9bab 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -53,19 +53,26 @@
53#define CPU_NEHEMIAH 5 53#define CPU_NEHEMIAH 5
54 54
55static int cpu_model; 55static int cpu_model;
56static unsigned int numscales=16, numvscales; 56static unsigned int numscales=16;
57static unsigned int fsb; 57static unsigned int fsb;
58static 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 */
59static unsigned int minmult, maxmult; 67static unsigned int minmult, maxmult;
60static int can_scale_voltage; 68static int can_scale_voltage;
61static int vrmrev;
62static struct acpi_processor *pr = NULL; 69static struct acpi_processor *pr = NULL;
63static struct acpi_processor_cx *cx = NULL; 70static struct acpi_processor_cx *cx = NULL;
64static int port22_en = 0; 71static int port22_en;
65 72
66/* Module parameters */ 73/* Module parameters */
67static int dont_scale_voltage; 74static int scale_voltage;
68static int ignore_latency = 0; 75static int ignore_latency;
69 76
70#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) 77#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
71 78
@@ -73,7 +80,6 @@ static int ignore_latency = 0;
73/* Clock ratios multiplied by 10 */ 80/* Clock ratios multiplied by 10 */
74static int clock_ratio[32]; 81static int clock_ratio[32];
75static int eblcr_table[32]; 82static int eblcr_table[32];
76static int voltage_table[32];
77static unsigned int highest_speed, lowest_speed; /* kHz */ 83static unsigned int highest_speed, lowest_speed; /* kHz */
78static int longhaul_version; 84static int longhaul_version;
79static struct cpufreq_frequency_table *longhaul_table; 85static struct cpufreq_frequency_table *longhaul_table;
@@ -163,6 +169,11 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
163 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; 169 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
164 longhaul.bits.EnableSoftBusRatio = 1; 170 longhaul.bits.EnableSoftBusRatio = 1;
165 171
172 if (can_scale_voltage) {
173 longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
174 longhaul.bits.EnableSoftVID = 1;
175 }
176
166 /* Sync to timer tick */ 177 /* Sync to timer tick */
167 safe_halt(); 178 safe_halt();
168 /* Change frequency on next halt or sleep */ 179 /* Change frequency on next halt or sleep */
@@ -454,53 +465,57 @@ static int __init longhaul_get_ranges(void)
454static void __init longhaul_setup_voltagescaling(void) 465static void __init longhaul_setup_voltagescaling(void)
455{ 466{
456 union msr_longhaul longhaul; 467 union msr_longhaul longhaul;
468 struct mV_pos minvid, maxvid;
469 unsigned int j, speed, pos, kHz_step, numvscales;
457 470
458 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); 471 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
459 472 if (!(longhaul.bits.RevisionID & 1)) {
460 if (!(longhaul.bits.RevisionID & 1)) 473 printk(KERN_INFO PFX "Voltage scaling not supported by CPU.\n");
461 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 }
462 486
463 minvid = longhaul.bits.MinimumVID; 487 minvid = vrm_mV_table[longhaul.bits.MinimumVID];
464 maxvid = longhaul.bits.MaximumVID; 488 maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
465 vrmrev = longhaul.bits.VRMRev; 489 numvscales = maxvid.pos - minvid.pos + 1;
490 kHz_step = (highest_speed - lowest_speed) / numvscales;
466 491
467 if (minvid == 0 || maxvid == 0) { 492 if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
468 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. "
469 "Voltage scaling disabled.\n", 494 "Voltage scaling disabled.\n",
470 minvid/1000, minvid%1000, maxvid/1000, maxvid%1000); 495 minvid.mV/1000, minvid.mV%1000, maxvid.mV/1000, maxvid.mV%1000);
471 return; 496 return;
472 } 497 }
473 498
474 if (minvid == maxvid) { 499 if (minvid.mV == maxvid.mV) {
475 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 "
476 "both %d.%03d. Voltage scaling disabled\n", 501 "both %d.%03d. Voltage scaling disabled\n",
477 maxvid/1000, maxvid%1000); 502 maxvid.mV/1000, maxvid.mV%1000);
478 return; 503 return;
479 } 504 }
480 505
481 if (vrmrev==0) { 506 printk(KERN_INFO PFX "Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n",
482 dprintk ("VRM 8.5\n"); 507 maxvid.mV/1000, maxvid.mV%1000,
483 memcpy (voltage_table, vrm85scales, sizeof(voltage_table)); 508 minvid.mV/1000, minvid.mV%1000,
484 numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25; 509 numvscales);
485 } else { 510
486 dprintk ("Mobile VRM\n"); 511 j = 0;
487 memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table)); 512 while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
488 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++;
489 } 517 }
490 518
491 /* Current voltage isn't readable at first, so we need to
492 set it to a known value. The spec says to use maxvid */
493 longhaul.bits.RevisionKey = longhaul.bits.RevisionID; /* FIXME: This is bad. */
494 longhaul.bits.EnableSoftVID = 1;
495 longhaul.bits.SoftVID = maxvid;
496 wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
497
498 minvid = voltage_table[minvid];
499 maxvid = voltage_table[maxvid];
500
501 dprintk ("Min VID=%d.%03d Max VID=%d.%03d, %d possible voltage scales\n",
502 maxvid/1000, maxvid%1000, minvid/1000, minvid%1000, numvscales);
503
504 can_scale_voltage = 1; 519 can_scale_voltage = 1;
505} 520}
506 521
@@ -685,7 +700,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
685 return ret; 700 return ret;
686 701
687 if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) && 702 if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
688 (dont_scale_voltage==0)) 703 (scale_voltage != 0))
689 longhaul_setup_voltagescaling(); 704 longhaul_setup_voltagescaling();
690 705
691 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 706 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
@@ -773,8 +788,8 @@ static void __exit longhaul_exit(void)
773 kfree(longhaul_table); 788 kfree(longhaul_table);
774} 789}
775 790
776module_param (dont_scale_voltage, int, 0644); 791module_param (scale_voltage, int, 0644);
777MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor"); 792MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
778module_param(ignore_latency, int, 0644); 793module_param(ignore_latency, int, 0644);
779MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test"); 794MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test");
780 795