diff options
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.c | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index fa5cac255c16..b59878a0d9b3 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c | |||
@@ -8,12 +8,11 @@ | |||
8 | * VIA have currently 3 different versions of Longhaul. | 8 | * VIA have currently 3 different versions of Longhaul. |
9 | * Version 1 (Longhaul) uses the BCR2 MSR at 0x1147. | 9 | * Version 1 (Longhaul) uses the BCR2 MSR at 0x1147. |
10 | * It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0. | 10 | * It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0. |
11 | * Version 2 of longhaul is the same as v1, but adds voltage scaling. | 11 | * Version 2 of longhaul is backward compatible with v1, but adds |
12 | * Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C) | 12 | * LONGHAUL MSR for purpose of both frequency and voltage scaling. |
13 | * voltage scaling support has currently been disabled in this driver | 13 | * Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C). |
14 | * until we have code that gets it right. | ||
15 | * Version 3 of longhaul got renamed to Powersaver and redesigned | 14 | * Version 3 of longhaul got renamed to Powersaver and redesigned |
16 | * to use the POWERSAVER MSR at 0x110a. | 15 | * to use only the POWERSAVER MSR at 0x110a. |
17 | * It is present in Ezra-T (C5M), Nehemiah (C5X) and above. | 16 | * It is present in Ezra-T (C5M), Nehemiah (C5X) and above. |
18 | * It's pretty much the same feature wise to longhaul v2, though | 17 | * It's pretty much the same feature wise to longhaul v2, though |
19 | * there is provision for scaling FSB too, but this doesn't work | 18 | * there is provision for scaling FSB too, but this doesn't work |
@@ -298,26 +297,19 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
298 | /* | 297 | /* |
299 | * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B]) | 298 | * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B]) |
300 | * Software controlled multipliers only. | 299 | * Software controlled multipliers only. |
301 | * | ||
302 | * *NB* Until we get voltage scaling working v1 & v2 are the same code. | ||
303 | * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C] | ||
304 | */ | 300 | */ |
305 | case TYPE_LONGHAUL_V1: | 301 | case TYPE_LONGHAUL_V1: |
306 | case TYPE_LONGHAUL_V2: | ||
307 | do_longhaul1(clock_ratio_index); | 302 | do_longhaul1(clock_ratio_index); |
308 | break; | 303 | break; |
309 | 304 | ||
310 | /* | 305 | /* |
306 | * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5B] and Ezra [C5C] | ||
307 | * | ||
311 | * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N]) | 308 | * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N]) |
312 | * We can scale voltage with this too, but that's currently | ||
313 | * disabled until we come up with a decent 'match freq to voltage' | ||
314 | * algorithm. | ||
315 | * When we add voltage scaling, we will also need to do the | ||
316 | * voltage/freq setting in order depending on the direction | ||
317 | * of scaling (like we do in powernow-k7.c) | ||
318 | * Nehemiah can do FSB scaling too, but this has never been proven | 309 | * Nehemiah can do FSB scaling too, but this has never been proven |
319 | * to work in practice. | 310 | * to work in practice. |
320 | */ | 311 | */ |
312 | case TYPE_LONGHAUL_V2: | ||
321 | case TYPE_POWERSAVER: | 313 | case TYPE_POWERSAVER: |
322 | if (longhaul_flags & USE_ACPI_C3) { | 314 | if (longhaul_flags & USE_ACPI_C3) { |
323 | /* Don't allow wakeup */ | 315 | /* Don't allow wakeup */ |
@@ -342,6 +334,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
342 | local_irq_restore(flags); | 334 | local_irq_restore(flags); |
343 | preempt_enable(); | 335 | preempt_enable(); |
344 | 336 | ||
337 | freqs.new = calc_speed(longhaul_get_cpu_mult()); | ||
345 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 338 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
346 | } | 339 | } |
347 | 340 | ||
@@ -471,6 +464,8 @@ static void __init longhaul_setup_voltagescaling(void) | |||
471 | mV_vrm_table = &mV_vrm85[0]; | 464 | mV_vrm_table = &mV_vrm85[0]; |
472 | } else { | 465 | } else { |
473 | printk (KERN_INFO PFX "Mobile VRM\n"); | 466 | printk (KERN_INFO PFX "Mobile VRM\n"); |
467 | if (cpu_model < CPU_NEHEMIAH) | ||
468 | return; | ||
474 | vrm_mV_table = &mobilevrm_mV[0]; | 469 | vrm_mV_table = &mobilevrm_mV[0]; |
475 | mV_vrm_table = &mV_mobilevrm[0]; | 470 | mV_vrm_table = &mV_mobilevrm[0]; |
476 | } | 471 | } |
@@ -656,6 +651,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
656 | struct cpuinfo_x86 *c = cpu_data; | 651 | struct cpuinfo_x86 *c = cpu_data; |
657 | char *cpuname=NULL; | 652 | char *cpuname=NULL; |
658 | int ret; | 653 | int ret; |
654 | u32 lo, hi; | ||
659 | int vt8235_present; | 655 | int vt8235_present; |
660 | 656 | ||
661 | /* Check what we have on this motherboard */ | 657 | /* Check what we have on this motherboard */ |
@@ -669,16 +665,20 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
669 | break; | 665 | break; |
670 | 666 | ||
671 | case 7: | 667 | case 7: |
672 | longhaul_version = TYPE_LONGHAUL_V1; | ||
673 | switch (c->x86_mask) { | 668 | switch (c->x86_mask) { |
674 | case 0: | 669 | case 0: |
670 | longhaul_version = TYPE_LONGHAUL_V1; | ||
675 | cpu_model = CPU_SAMUEL2; | 671 | cpu_model = CPU_SAMUEL2; |
676 | cpuname = "C3 'Samuel 2' [C5B]"; | 672 | cpuname = "C3 'Samuel 2' [C5B]"; |
677 | /* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */ | 673 | /* Note, this is not a typo, early Samuel2's had |
678 | memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio)); | 674 | * Samuel1 ratios. */ |
679 | memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr)); | 675 | memcpy(clock_ratio, samuel1_clock_ratio, |
676 | sizeof(samuel1_clock_ratio)); | ||
677 | memcpy(eblcr_table, samuel2_eblcr, | ||
678 | sizeof(samuel2_eblcr)); | ||
680 | break; | 679 | break; |
681 | case 1 ... 15: | 680 | case 1 ... 15: |
681 | longhaul_version = TYPE_LONGHAUL_V2; | ||
682 | if (c->x86_mask < 8) { | 682 | if (c->x86_mask < 8) { |
683 | cpu_model = CPU_SAMUEL2; | 683 | cpu_model = CPU_SAMUEL2; |
684 | cpuname = "C3 'Samuel 2' [C5B]"; | 684 | cpuname = "C3 'Samuel 2' [C5B]"; |
@@ -686,8 +686,10 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
686 | cpu_model = CPU_EZRA; | 686 | cpu_model = CPU_EZRA; |
687 | cpuname = "C3 'Ezra' [C5C]"; | 687 | cpuname = "C3 'Ezra' [C5C]"; |
688 | } | 688 | } |
689 | memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio)); | 689 | memcpy(clock_ratio, ezra_clock_ratio, |
690 | memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr)); | 690 | sizeof(ezra_clock_ratio)); |
691 | memcpy(eblcr_table, ezra_eblcr, | ||
692 | sizeof(ezra_eblcr)); | ||
691 | break; | 693 | break; |
692 | } | 694 | } |
693 | break; | 695 | break; |
@@ -728,6 +730,13 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
728 | cpuname = "Unknown"; | 730 | cpuname = "Unknown"; |
729 | break; | 731 | break; |
730 | } | 732 | } |
733 | /* Check Longhaul ver. 2 */ | ||
734 | if (longhaul_version == TYPE_LONGHAUL_V2) { | ||
735 | rdmsr(MSR_VIA_LONGHAUL, lo, hi); | ||
736 | if (lo == 0 && hi == 0) | ||
737 | /* Looks like MSR isn't present */ | ||
738 | longhaul_version = TYPE_LONGHAUL_V1; | ||
739 | } | ||
731 | 740 | ||
732 | printk (KERN_INFO PFX "VIA %s CPU detected. ", cpuname); | 741 | printk (KERN_INFO PFX "VIA %s CPU detected. ", cpuname); |
733 | switch (longhaul_version) { | 742 | switch (longhaul_version) { |
@@ -749,7 +758,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
749 | NULL, (void *)&pr); | 758 | NULL, (void *)&pr); |
750 | 759 | ||
751 | /* Check ACPI support for C3 state */ | 760 | /* Check ACPI support for C3 state */ |
752 | if (pr != NULL && longhaul_version == TYPE_POWERSAVER) { | 761 | if (pr != NULL && longhaul_version != TYPE_LONGHAUL_V1) { |
753 | cx = &pr->power.states[ACPI_STATE_C3]; | 762 | cx = &pr->power.states[ACPI_STATE_C3]; |
754 | if (cx->address > 0 && cx->latency <= 1000) { | 763 | if (cx->address > 0 && cx->latency <= 1000) { |
755 | longhaul_flags |= USE_ACPI_C3; | 764 | longhaul_flags |= USE_ACPI_C3; |