|
@@ -8,12 +8,11 @@
|
|
* VIA have currently 3 different versions of Longhaul.
|
|
* VIA have currently 3 different versions of Longhaul.
|
|
* Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
|
|
* Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
|
|
* It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
|
|
* It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
|
|
- * Version 2 of longhaul is the same as v1, but adds voltage scaling.
|
|
|
|
- * Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C)
|
|
|
|
- * voltage scaling support has currently been disabled in this driver
|
|
|
|
- * until we have code that gets it right.
|
|
|
|
|
|
+ * Version 2 of longhaul is backward compatible with v1, but adds
|
|
|
|
+ * LONGHAUL MSR for purpose of both frequency and voltage scaling.
|
|
|
|
+ * Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C).
|
|
* Version 3 of longhaul got renamed to Powersaver and redesigned
|
|
* Version 3 of longhaul got renamed to Powersaver and redesigned
|
|
- * to use the POWERSAVER MSR at 0x110a.
|
|
|
|
|
|
+ * to use only the POWERSAVER MSR at 0x110a.
|
|
* It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
|
|
* It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
|
|
* It's pretty much the same feature wise to longhaul v2, though
|
|
* It's pretty much the same feature wise to longhaul v2, though
|
|
* there is provision for scaling FSB too, but this doesn't work
|
|
* 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)
|
|
/*
|
|
/*
|
|
* Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
|
|
* Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
|
|
* Software controlled multipliers only.
|
|
* Software controlled multipliers only.
|
|
- *
|
|
|
|
- * *NB* Until we get voltage scaling working v1 & v2 are the same code.
|
|
|
|
- * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C]
|
|
|
|
*/
|
|
*/
|
|
case TYPE_LONGHAUL_V1:
|
|
case TYPE_LONGHAUL_V1:
|
|
- case TYPE_LONGHAUL_V2:
|
|
|
|
do_longhaul1(clock_ratio_index);
|
|
do_longhaul1(clock_ratio_index);
|
|
break;
|
|
break;
|
|
|
|
|
|
/*
|
|
/*
|
|
|
|
+ * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5B] and Ezra [C5C]
|
|
|
|
+ *
|
|
* Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
|
|
* Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
|
|
- * We can scale voltage with this too, but that's currently
|
|
|
|
- * disabled until we come up with a decent 'match freq to voltage'
|
|
|
|
- * algorithm.
|
|
|
|
- * When we add voltage scaling, we will also need to do the
|
|
|
|
- * voltage/freq setting in order depending on the direction
|
|
|
|
- * of scaling (like we do in powernow-k7.c)
|
|
|
|
* Nehemiah can do FSB scaling too, but this has never been proven
|
|
* Nehemiah can do FSB scaling too, but this has never been proven
|
|
* to work in practice.
|
|
* to work in practice.
|
|
*/
|
|
*/
|
|
|
|
+ case TYPE_LONGHAUL_V2:
|
|
case TYPE_POWERSAVER:
|
|
case TYPE_POWERSAVER:
|
|
if (longhaul_flags & USE_ACPI_C3) {
|
|
if (longhaul_flags & USE_ACPI_C3) {
|
|
/* Don't allow wakeup */
|
|
/* Don't allow wakeup */
|
|
@@ -342,6 +334,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
|
local_irq_restore(flags);
|
|
local_irq_restore(flags);
|
|
preempt_enable();
|
|
preempt_enable();
|
|
|
|
|
|
|
|
+ freqs.new = calc_speed(longhaul_get_cpu_mult());
|
|
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
|
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -471,6 +464,8 @@ static void __init longhaul_setup_voltagescaling(void)
|
|
mV_vrm_table = &mV_vrm85[0];
|
|
mV_vrm_table = &mV_vrm85[0];
|
|
} else {
|
|
} else {
|
|
printk (KERN_INFO PFX "Mobile VRM\n");
|
|
printk (KERN_INFO PFX "Mobile VRM\n");
|
|
|
|
+ if (cpu_model < CPU_NEHEMIAH)
|
|
|
|
+ return;
|
|
vrm_mV_table = &mobilevrm_mV[0];
|
|
vrm_mV_table = &mobilevrm_mV[0];
|
|
mV_vrm_table = &mV_mobilevrm[0];
|
|
mV_vrm_table = &mV_mobilevrm[0];
|
|
}
|
|
}
|
|
@@ -656,6 +651,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
|
struct cpuinfo_x86 *c = cpu_data;
|
|
struct cpuinfo_x86 *c = cpu_data;
|
|
char *cpuname=NULL;
|
|
char *cpuname=NULL;
|
|
int ret;
|
|
int ret;
|
|
|
|
+ u32 lo, hi;
|
|
int vt8235_present;
|
|
int vt8235_present;
|
|
|
|
|
|
/* Check what we have on this motherboard */
|
|
/* Check what we have on this motherboard */
|
|
@@ -669,16 +665,20 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
|
break;
|
|
break;
|
|
|
|
|
|
case 7:
|
|
case 7:
|
|
- longhaul_version = TYPE_LONGHAUL_V1;
|
|
|
|
switch (c->x86_mask) {
|
|
switch (c->x86_mask) {
|
|
case 0:
|
|
case 0:
|
|
|
|
+ longhaul_version = TYPE_LONGHAUL_V1;
|
|
cpu_model = CPU_SAMUEL2;
|
|
cpu_model = CPU_SAMUEL2;
|
|
cpuname = "C3 'Samuel 2' [C5B]";
|
|
cpuname = "C3 'Samuel 2' [C5B]";
|
|
- /* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */
|
|
|
|
- memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
|
|
|
|
- memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr));
|
|
|
|
|
|
+ /* Note, this is not a typo, early Samuel2's had
|
|
|
|
+ * Samuel1 ratios. */
|
|
|
|
+ memcpy(clock_ratio, samuel1_clock_ratio,
|
|
|
|
+ sizeof(samuel1_clock_ratio));
|
|
|
|
+ memcpy(eblcr_table, samuel2_eblcr,
|
|
|
|
+ sizeof(samuel2_eblcr));
|
|
break;
|
|
break;
|
|
case 1 ... 15:
|
|
case 1 ... 15:
|
|
|
|
+ longhaul_version = TYPE_LONGHAUL_V2;
|
|
if (c->x86_mask < 8) {
|
|
if (c->x86_mask < 8) {
|
|
cpu_model = CPU_SAMUEL2;
|
|
cpu_model = CPU_SAMUEL2;
|
|
cpuname = "C3 'Samuel 2' [C5B]";
|
|
cpuname = "C3 'Samuel 2' [C5B]";
|
|
@@ -686,8 +686,10 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
|
cpu_model = CPU_EZRA;
|
|
cpu_model = CPU_EZRA;
|
|
cpuname = "C3 'Ezra' [C5C]";
|
|
cpuname = "C3 'Ezra' [C5C]";
|
|
}
|
|
}
|
|
- memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio));
|
|
|
|
- memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr));
|
|
|
|
|
|
+ memcpy(clock_ratio, ezra_clock_ratio,
|
|
|
|
+ sizeof(ezra_clock_ratio));
|
|
|
|
+ memcpy(eblcr_table, ezra_eblcr,
|
|
|
|
+ sizeof(ezra_eblcr));
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
@@ -728,6 +730,13 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
|
cpuname = "Unknown";
|
|
cpuname = "Unknown";
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ /* Check Longhaul ver. 2 */
|
|
|
|
+ if (longhaul_version == TYPE_LONGHAUL_V2) {
|
|
|
|
+ rdmsr(MSR_VIA_LONGHAUL, lo, hi);
|
|
|
|
+ if (lo == 0 && hi == 0)
|
|
|
|
+ /* Looks like MSR isn't present */
|
|
|
|
+ longhaul_version = TYPE_LONGHAUL_V1;
|
|
|
|
+ }
|
|
|
|
|
|
printk (KERN_INFO PFX "VIA %s CPU detected. ", cpuname);
|
|
printk (KERN_INFO PFX "VIA %s CPU detected. ", cpuname);
|
|
switch (longhaul_version) {
|
|
switch (longhaul_version) {
|
|
@@ -749,7 +758,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
|
NULL, (void *)&pr);
|
|
NULL, (void *)&pr);
|
|
|
|
|
|
/* Check ACPI support for C3 state */
|
|
/* Check ACPI support for C3 state */
|
|
- if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
|
|
|
|
|
|
+ if (pr != NULL && longhaul_version != TYPE_LONGHAUL_V1) {
|
|
cx = &pr->power.states[ACPI_STATE_C3];
|
|
cx = &pr->power.states[ACPI_STATE_C3];
|
|
if (cx->address > 0 && cx->latency <= 1000) {
|
|
if (cx->address > 0 && cx->latency <= 1000) {
|
|
longhaul_flags |= USE_ACPI_C3;
|
|
longhaul_flags |= USE_ACPI_C3;
|