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; |
