aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel
diff options
context:
space:
mode:
authorRafał Bilski <rafalbilski@interia.pl>2007-01-01 17:49:34 -0500
committerDave Jones <davej@redhat.com>2007-01-02 23:38:39 -0500
commit24ebead82bbf9785909d4cf205e2df5e9ff7da32 (patch)
tree921f686860e918a01c3d3fb6cd106ba82bf4ace6 /arch/i386/kernel
parent264166e604a7e14c278e31cadd1afb06a7d51a11 (diff)
[CPUFREQ] Longhaul - Always guess FSB
This is patch that solves Ebox mini PC issue and make FSB code more specification compilant. At start guess_fsb function is guessing 200MHz FSB too. It is better to make it in this way because, thanks to this function, driver will fail for bogus FSB values caused by bogus multiplier value. For PowerSaver processors we can't depend on Max / MinMHzFSB because these values are only used for PowerSaver 2.0 and 3.0. Most processors on which Longhaul is used are PowerSaver 1.0 only. I'm changing code for older CPU's too, but not so much as previously, and this code was already used for Ezra. Using MinMHzBR for Ezra-T is outside spec. It is for voltage scaling purpose and don't have to be equal to minmult (but it is). Same for Nehemiah (it isn't for sure). Added mult - current multiplier value. Signed-off-by: Rafał Bilski <rafalbilski@interia.pl> Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c44
1 files changed, 14 insertions, 30 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index fd70c77acc1c..f152c291e7c8 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -318,12 +318,12 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
318 318
319#define ROUNDING 0xf 319#define ROUNDING 0xf
320 320
321static int _guess(int guess) 321static int _guess(int guess, int mult)
322{ 322{
323 int target; 323 int target;
324 324
325 target = ((maxmult/10)*guess); 325 target = ((mult/10)*guess);
326 if (maxmult%10 != 0) 326 if (mult%10 != 0)
327 target += (guess/2); 327 target += (guess/2);
328 target += ROUNDING/2; 328 target += ROUNDING/2;
329 target &= ~ROUNDING; 329 target &= ~ROUNDING;
@@ -331,17 +331,17 @@ static int _guess(int guess)
331} 331}
332 332
333 333
334static int guess_fsb(void) 334static int guess_fsb(int mult)
335{ 335{
336 int speed = (cpu_khz/1000); 336 int speed = (cpu_khz/1000);
337 int i; 337 int i;
338 int speeds[3] = { 66, 100, 133 }; 338 int speeds[] = { 66, 100, 133, 200 };
339 339
340 speed += ROUNDING/2; 340 speed += ROUNDING/2;
341 speed &= ~ROUNDING; 341 speed &= ~ROUNDING;
342 342
343 for (i=0; i<3; i++) { 343 for (i=0; i<4; i++) {
344 if (_guess(speeds[i]) == speed) 344 if (_guess(speeds[i], mult) == speed)
345 return speeds[i]; 345 return speeds[i];
346 } 346 }
347 return 0; 347 return 0;
@@ -361,6 +361,7 @@ static int __init longhaul_get_ranges(void)
361 unsigned long lo, hi; 361 unsigned long lo, hi;
362 unsigned int eblcr_fsb_table_v1[] = { 66, 133, 100, -1 }; 362 unsigned int eblcr_fsb_table_v1[] = { 66, 133, 100, -1 };
363 unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 }; 363 unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 };
364 int mult;
364 365
365 switch (longhaul_version) { 366 switch (longhaul_version) {
366 case TYPE_LONGHAUL_V1: 367 case TYPE_LONGHAUL_V1:
@@ -368,30 +369,18 @@ static int __init longhaul_get_ranges(void)
368 /* Ugh, Longhaul v1 didn't have the min/max MSRs. 369 /* Ugh, Longhaul v1 didn't have the min/max MSRs.
369 Assume min=3.0x & max = whatever we booted at. */ 370 Assume min=3.0x & max = whatever we booted at. */
370 minmult = 30; 371 minmult = 30;
371 maxmult = longhaul_get_cpu_mult(); 372 maxmult = mult = longhaul_get_cpu_mult();
372 rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
373 invalue = (lo & (1<<18|1<<19)) >>18;
374 if (cpu_model==CPU_SAMUEL || cpu_model==CPU_SAMUEL2)
375 fsb = eblcr_fsb_table_v1[invalue];
376 else
377 fsb = guess_fsb();
378 break; 373 break;
379 374
380 case TYPE_POWERSAVER: 375 case TYPE_POWERSAVER:
381 /* Ezra-T */ 376 /* Ezra-T */
382 if (cpu_model==CPU_EZRA_T) { 377 if (cpu_model==CPU_EZRA_T) {
378 minmult = 30;
383 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); 379 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
384 invalue = longhaul.bits.MaxMHzBR; 380 invalue = longhaul.bits.MaxMHzBR;
385 if (longhaul.bits.MaxMHzBR4) 381 if (longhaul.bits.MaxMHzBR4)
386 invalue += 16; 382 invalue += 16;
387 maxmult=ezra_t_multipliers[invalue]; 383 maxmult = mult = ezra_t_multipliers[invalue];
388
389 invalue = longhaul.bits.MinMHzBR;
390 if (longhaul.bits.MinMHzBR4 == 1)
391 minmult = 30;
392 else
393 minmult = ezra_t_multipliers[invalue];
394 fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
395 break; 384 break;
396 } 385 }
397 386
@@ -411,21 +400,16 @@ static int __init longhaul_get_ranges(void)
411 * But it works, so we don't grumble. 400 * But it works, so we don't grumble.
412 */ 401 */
413 minmult=40; 402 minmult=40;
414 maxmult=longhaul_get_cpu_mult(); 403 maxmult = mult = longhaul_get_cpu_mult();
415
416 /* Starting with the 1.2GHz parts, theres a 200MHz bus. */
417 if ((cpu_khz/maxmult) > 13400)
418 fsb = 200;
419 else
420 fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
421 break; 404 break;
422 } 405 }
423 } 406 }
407 fsb = guess_fsb(mult);
424 408
425 dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n", 409 dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
426 minmult/10, minmult%10, maxmult/10, maxmult%10); 410 minmult/10, minmult%10, maxmult/10, maxmult%10);
427 411
428 if (fsb == -1) { 412 if (fsb == 0) {
429 printk (KERN_INFO PFX "Invalid (reserved) FSB!\n"); 413 printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
430 return -EINVAL; 414 return -EINVAL;
431 } 415 }