Commit 7cdf272f authored by Dave Jones's avatar Dave Jones Committed by Dave Jones

[CPUFREQ] Longhaul >v1 can't use EBLCR for FSB, has to calculate it instead.

parent b6df4b5b
...@@ -70,21 +70,6 @@ static unsigned int calc_speed (int mult, int fsb) ...@@ -70,21 +70,6 @@ static unsigned int calc_speed (int mult, int fsb)
} }
static unsigned int longhaul_get_cpu_fsb (void)
{
unsigned long lo, hi;
unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 };
unsigned int invalue=0;
if (fsb == 0) {
rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
invalue = (lo & (1<<18|1<<19)) >>18;
fsb = eblcr_fsb_table[invalue];
}
return fsb;
}
static int longhaul_get_cpu_mult (void) static int longhaul_get_cpu_mult (void)
{ {
unsigned long invalue=0,lo, hi; unsigned long invalue=0,lo, hi;
...@@ -193,6 +178,39 @@ static void longhaul_setstate (unsigned int clock_ratio_index) ...@@ -193,6 +178,39 @@ static void longhaul_setstate (unsigned int clock_ratio_index)
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
} }
/*
* Centaur decided to make life a little more tricky.
* Only longhaul v1 is allowed to read EBLCR BSEL[0:1].
* Samuel2 and above have to try and guess what the FSB is.
* We do this by assuming we booted at maximum multiplier, and interpolate
* between that value multiplied by possible FSBs and cpu_mhz which
* was calculated at boot time. Really ugly, but no other way to do this.
*/
static int _guess (int guess, int maxmult)
{
int target;
target = ((maxmult/10)*guess);
if (maxmult%10 != 0)
target += (guess/2);
target &= ~0xf;
return target;
}
static int guess_fsb(int maxmult)
{
int speed = (cpu_khz/1000) & ~0xf;
int i;
int speeds[3] = { 66, 100, 133 };
for (i=0; i<3; i++) {
if (_guess(speeds[i],maxmult) == speed)
return speeds[i];
}
return 0;
}
static int __init longhaul_get_ranges (void) static int __init longhaul_get_ranges (void)
{ {
...@@ -203,8 +221,8 @@ static int __init longhaul_get_ranges (void) ...@@ -203,8 +221,8 @@ static int __init longhaul_get_ranges (void)
-1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 }; -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 };
unsigned int j, k = 0; unsigned int j, k = 0;
union msr_longhaul longhaul; union msr_longhaul longhaul;
unsigned long lo, hi;
fsb = longhaul_get_cpu_fsb(); unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 };
switch (longhaul_version) { switch (longhaul_version) {
case 1: case 1:
...@@ -212,6 +230,9 @@ static int __init longhaul_get_ranges (void) ...@@ -212,6 +230,9 @@ static int __init longhaul_get_ranges (void)
Assume min=3.0x & max = whatever we booted at. */ Assume min=3.0x & max = whatever we booted at. */
minmult = 30; minmult = 30;
maxmult = longhaul_get_cpu_mult(); maxmult = longhaul_get_cpu_mult();
rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
invalue = (lo & (1<<18|1<<19)) >>18;
fsb = eblcr_fsb_table[invalue];
break; break;
case 2 ... 3: case 2 ... 3:
...@@ -222,14 +243,13 @@ static int __init longhaul_get_ranges (void) ...@@ -222,14 +243,13 @@ static int __init longhaul_get_ranges (void)
invalue += 16; invalue += 16;
maxmult=multipliers[invalue]; maxmult=multipliers[invalue];
#if 0
invalue = longhaul.bits.MinMHzBR; invalue = longhaul.bits.MinMHzBR;
if (longhaul.bits.MinMHzBR4); if (longhaul.bits.MinMHzBR4 == 1)
invalue += 16; minmult = 30;
minmult = multipliers[invalue]; else
#else minmult = multipliers[invalue];
minmult = 30; /* as per spec */
#endif fsb = guess_fsb(maxmult);
break; break;
} }
......
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