diff options
author | Rafał Bilski <rafalbilski@interia.pl> | 2007-02-14 16:00:37 -0500 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2007-02-14 17:32:06 -0500 |
commit | 2b8c0e13026c30bd154dc521ffc235360830c712 (patch) | |
tree | cdf66598cd4cbb69587a7e1f5601a78c6c2db6f4 /arch/i386/kernel/cpu | |
parent | b6f45a4b071d77777d70e097d429273aeedff717 (diff) |
[CPUFREQ] Longhaul - Redo Longhaul ver. 2
Start using v2 version of Longhaul when available. It provides
voltage scaling and can use ACPI C3 state. That's curious. CPU
will not change frequency on ACPI C3 when v1 is in use, but it will
when v2 is used. Driver will return max frequency all the time if
this isn't true for all processors. There is strange thing with
mobile voltage. Looks like only Nehemiah (C3-M) supports it.
Earlier processors have different mobile VRM (in docs), but I can't
find any which is using it. Looks like all are using VRM 8.5. So
fail for non Nehemiah with mobile VRM.
Signed-off-by: Rafal Bilski <rafalbilski@interia.pl>
Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'arch/i386/kernel/cpu')
-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; |