Commit b0727d49 authored by Dave Jones's avatar Dave Jones

Merge delerium.codemonkey.org.uk:/mnt/data/src/bk/bk-linus

into delerium.codemonkey.org.uk:/mnt/data/src/bk/cpufreq
parents 5a528e75 db44090b
...@@ -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,9 +284,10 @@ static int __init longhaul_get_ranges(void) ...@@ -274,9 +284,10 @@ static int __init longhaul_get_ranges(void)
fsb = guess_fsb(); fsb = guess_fsb();
break; break;
case 2: case TYPE_POWERSAVER:
/* Ezra-T */
if (c->x86_model == 8) {
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
invalue = longhaul.bits.MaxMHzBR; invalue = longhaul.bits.MaxMHzBR;
if (longhaul.bits.MaxMHzBR4) if (longhaul.bits.MaxMHzBR4)
invalue += 16; invalue += 16;
...@@ -287,17 +298,18 @@ static int __init longhaul_get_ranges(void) ...@@ -287,17 +298,18 @@ static int __init longhaul_get_ranges(void)
minmult = 30; minmult = 30;
else else
minmult = multipliers[invalue]; minmult = multipliers[invalue];
fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
break; break;
}
case 3: /* Nehemiah */
if (c->x86_model == 9) {
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
/* /*
* TODO: This code works, but raises a lot of questions. * TODO: This code works, but raises a lot of questions.
* - Some Nehemiah's seem to have broken Min/MaxMHzBR's. * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
* We get around this by using a hardcoded multiplier of 5.0x * 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. * 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. * This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
* - According to some VIA documentation EBLCR is only * - According to some VIA documentation EBLCR is only
...@@ -305,7 +317,7 @@ static int __init longhaul_get_ranges(void) ...@@ -305,7 +317,7 @@ static int __init longhaul_get_ranges(void)
* We're possibly using something undocumented and unsupported, * We're possibly using something undocumented and unsupported,
* But it works, so we don't grumble. * But it works, so we don't grumble.
*/ */
minmult=50; minmult=40;
maxmult=longhaul_get_cpu_mult(); maxmult=longhaul_get_cpu_mult();
/* Starting with the 1.2GHz parts, theres a 200MHz bus. */ /* Starting with the 1.2GHz parts, theres a 200MHz bus. */
...@@ -315,6 +327,7 @@ static int __init longhaul_get_ranges(void) ...@@ -315,6 +327,7 @@ static int __init longhaul_get_ranges(void)
fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
break; break;
} }
}
dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n", dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n",
minmult/10, minmult%10, maxmult/10, maxmult%10); minmult/10, minmult%10, maxmult/10, maxmult%10);
...@@ -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:
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,23 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) ...@@ -518,14 +531,23 @@ 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 || longhaul_version==TYPE_POWERSAVER) &&
(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