Commit a1db2e00 authored by Dave Jones's avatar Dave Jones Committed by Dave Jones

[CPUFREQ] Introduce some defines for the longhaul version, and use them.

This makes some of the code quite a bit cleaner, and a lot more
obvious whats going on on which CPUs.
Signed-off-by: default avatarDave Jones <davej@redhat.com>
parent eb2b0751
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
#define PFX "longhaul: " #define PFX "longhaul: "
#define TYPE_LONGHAUL_V1 1
#define TYPE_LONGHAUL_V2 2
#define TYPE_POWERSAVER 3
static unsigned int numscales=16, numvscales; static unsigned int numscales=16, numvscales;
static unsigned int fsb; static unsigned int fsb;
static int minvid, maxvid; static int minvid, maxvid;
...@@ -92,7 +96,7 @@ static int longhaul_get_cpu_mult(void) ...@@ -92,7 +96,7 @@ static int longhaul_get_cpu_mult(void)
rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22; invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22;
if (longhaul_version==2 || longhaul_version==3) { if (longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) {
if (lo & (1<<27)) if (lo & (1<<27))
invalue+=16; invalue+=16;
} }
...@@ -101,8 +105,20 @@ static int longhaul_get_cpu_mult(void) ...@@ -101,8 +105,20 @@ static int longhaul_get_cpu_mult(void)
static void do_powersaver(union msr_longhaul *longhaul, static void do_powersaver(union msr_longhaul *longhaul,
unsigned int clock_ratio_index, int version) unsigned int clock_ratio_index)
{ {
struct cpuinfo_x86 *c = cpu_data;
int version;
switch (c->x86_model) {
case 8: version = 3;
break;
case 9: version = 0xf;
break;
default:
return;
}
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf; longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
...@@ -160,7 +176,8 @@ static void longhaul_setstate(unsigned int clock_ratio_index) ...@@ -160,7 +176,8 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
* *NB* Until we get voltage scaling working v1 & v2 are the same code. * *NB* Until we get voltage scaling working v1 & v2 are the same code.
* Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C] * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C]
*/ */
case 1: case TYPE_LONGHAUL_V1:
case TYPE_LONGHAUL_V2:
rdmsrl (MSR_VIA_BCR2, bcr2.val); rdmsrl (MSR_VIA_BCR2, bcr2.val);
/* Enable software clock multiplier */ /* Enable software clock multiplier */
bcr2.bits.ESOFTBF = 1; bcr2.bits.ESOFTBF = 1;
...@@ -180,26 +197,18 @@ static void longhaul_setstate(unsigned int clock_ratio_index) ...@@ -180,26 +197,18 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
break; break;
/* /*
* Longhaul v3 (aka Powersaver). (Ezra-T [C5M]) * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
* We can scale voltage with this too, but that's currently * We can scale voltage with this too, but that's currently
* disabled until we come up with a decent 'match freq to voltage' * disabled until we come up with a decent 'match freq to voltage'
* algorithm. * algorithm.
* When we add voltage scaling, we will also need to do the * When we add voltage scaling, we will also need to do the
* voltage/freq setting in order depending on the direction * voltage/freq setting in order depending on the direction
* of scaling (like we do in powernow-k7.c) * of scaling (like we do in powernow-k7.c)
*/ * Nehemiah can do FSB scaling too, but this has never been proven
case 2:
do_powersaver(&longhaul, clock_ratio_index, 3);
break;
/*
* Powersaver. (Nehemiah [C5N])
* As for Ezra-T, we don't do voltage yet.
* This can do FSB scaling too, but it has never been proven
* to work in practice. * to work in practice.
*/ */
case 3: case TYPE_POWERSAVER:
do_powersaver(&longhaul, clock_ratio_index, 0xf); do_powersaver(&longhaul, clock_ratio_index);
break; break;
} }
...@@ -261,7 +270,8 @@ static int __init longhaul_get_ranges(void) ...@@ -261,7 +270,8 @@ static int __init longhaul_get_ranges(void)
unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 }; unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 };
switch (longhaul_version) { switch (longhaul_version) {
case 1: case TYPE_LONGHAUL_V1:
case TYPE_LONGHAUL_V2:
/* Ugh, Longhaul v1 didn't have the min/max MSRs. /* Ugh, Longhaul v1 didn't have the min/max MSRs.
Assume min=3.0x & max = whatever we booted at. */ Assume min=3.0x & max = whatever we booted at. */
minmult = 30; minmult = 30;
...@@ -274,46 +284,49 @@ static int __init longhaul_get_ranges(void) ...@@ -274,46 +284,49 @@ static int __init longhaul_get_ranges(void)
fsb = guess_fsb(); fsb = guess_fsb();
break; break;
case 2: case TYPE_POWERSAVER:
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); /* Ezra-T */
if (c->x86_model == 8) {
invalue = longhaul.bits.MaxMHzBR; rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
if (longhaul.bits.MaxMHzBR4) invalue = longhaul.bits.MaxMHzBR;
invalue += 16; if (longhaul.bits.MaxMHzBR4)
maxmult=multipliers[invalue]; invalue += 16;
maxmult=multipliers[invalue];
invalue = longhaul.bits.MinMHzBR;
if (longhaul.bits.MinMHzBR4 == 1) invalue = longhaul.bits.MinMHzBR;
minmult = 30; if (longhaul.bits.MinMHzBR4 == 1)
else minmult = 30;
minmult = multipliers[invalue]; else
minmult = multipliers[invalue];
fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
break;
case 3:
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
/*
* TODO: This code works, but raises a lot of questions.
* - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
* We get around this by using a hardcoded multiplier of 5.0x
* for the minimimum speed, and the speed we booted up at for the max.
* This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
* - According to some VIA documentation EBLCR is only
* in pre-Nehemiah C3s. How this still works is a mystery.
* We're possibly using something undocumented and unsupported,
* But it works, so we don't grumble.
*/
minmult=50;
maxmult=longhaul_get_cpu_mult();
/* Starting with the 1.2GHz parts, theres a 200MHz bus. */
if ((cpu_khz/1000) > 1200)
fsb = 200;
else
fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
break; break;
}
/* Nehemiah */
if (c->x86_model == 9) {
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
/*
* TODO: This code works, but raises a lot of questions.
* - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
* We get around this by using a hardcoded multiplier of 4.0x
* for the minimimum speed, and the speed we booted up at for the max.
* This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
* - According to some VIA documentation EBLCR is only
* in pre-Nehemiah C3s. How this still works is a mystery.
* We're possibly using something undocumented and unsupported,
* But it works, so we don't grumble.
*/
minmult=40;
maxmult=longhaul_get_cpu_mult();
/* Starting with the 1.2GHz parts, theres a 200MHz bus. */
if ((cpu_khz/1000) > 1200)
fsb = 200;
else
fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
break;
}
} }
dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n", dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n",
...@@ -458,13 +471,13 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) ...@@ -458,13 +471,13 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
switch (c->x86_model) { switch (c->x86_model) {
case 6: case 6:
cpuname = "C3 'Samuel' [C5A]"; cpuname = "C3 'Samuel' [C5A]";
longhaul_version=1; longhaul_version = TYPE_LONGHAUL_V1;
memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio)); memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr)); memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr));
break; break;
case 7: /* C5B / C5C */ case 7: /* C5B / C5C */
longhaul_version=1; longhaul_version = TYPE_LONGHAUL_V1;
switch (c->x86_mask) { switch (c->x86_mask) {
case 0: case 0:
cpuname = "C3 'Samuel 2' [C5B]"; cpuname = "C3 'Samuel 2' [C5B]";
...@@ -485,14 +498,14 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) ...@@ -485,14 +498,14 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
case 8: case 8:
cpuname = "C3 'Ezra-T' [C5M]"; cpuname = "C3 'Ezra-T' [C5M]";
longhaul_version=2; longhaul_version = TYPE_POWERSAVER;
numscales=32; numscales=32;
memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio)); memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio));
memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr)); memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr));
break; break;
case 9: case 9:
longhaul_version=3; longhaul_version = TYPE_POWERSAVER;
numscales=32; numscales=32;
switch (c->x86_mask) { switch (c->x86_mask) {
case 0 ... 1: case 0 ... 1:
...@@ -518,14 +531,22 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) ...@@ -518,14 +531,22 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
break; break;
} }
printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n", printk (KERN_INFO PFX "VIA %s CPU detected.", cpuname);
cpuname, longhaul_version); switch (longhaul_version) {
case TYPE_LONGHAUL_V1:
case TYPE_LONGHAUL_V2:
printk ("Longhaul v%d supported.\n", longhaul_version);
break;
case TYPE_POWERSAVER:
printk ("Powersaver supported.\n");
break;
};
ret = longhaul_get_ranges(); ret = longhaul_get_ranges();
if (ret != 0) if (ret != 0)
return ret; return ret;
if ((longhaul_version==2) && (dont_scale_voltage==0)) if ((longhaul_version==TYPE_LONGHAUL_V2) && (dont_scale_voltage==0))
longhaul_setup_voltagescaling(); longhaul_setup_voltagescaling();
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment