Longhaul - Use information from Longhaul
PATCH 1/1 Longhaul - Use information from Longhaul
First. I lost very important line in do_powersaver. Again. Sorry.
Longhaul don't report minimum multiplier. It reports minimum frequency. So not always minimum multiplier at minimum FSB is really minimum. This is most important for Nehemiah witch allows FSB 66MHz, 100MHz and 133MHz. Ezra seems to support only 100MHz and 133MHz so in this case minimum multiplier at min FSB reported is in fact minimum PLL multiplier. So we are testing against min/max frequency. Minimum PLL multiplier is from clock_ratio table. If processor will report multiplier less then 5.0 then reported multiplier will be added to clock_ratio table.
Looks like all VIA CPUs allow to read FSB frequency from EBL_CR_POWERON. Only some have 66MHz reserved.
More precise speed calculations. This is bad when kernel first reports 999MHz and we are saying later that max is 997MHz.
---
arch/i386/kernel/cpu/cpufreq/longhaul.c renamed from arch/i386/kernel/cpu/cpufreq/longhaul.c.orig +53 -115
@@ -53,11 +53,12 @@static int cpu_model;static unsigned int numscales=16 , numvscales; -static unsigned int fsb; +static unsigned int fsb, fsb_min;static int minvid, maxvid;static unsigned int minmult, maxmult;static int can_scale_voltage;static int vrmrev; +static int old_speed;static struct acpi_processor *pr =NULL ;static struct acpi_processor_cx *cx =NULL ;
@@ -98,12 +99,10 @@ static char *print_speed(int speed)#endif -static unsigned int calc_speed (int mult) +static unsigned int calc_speed (int mult,int fsb) {int khz; - khz = (mult/10 )*fsb; -if (mult%10 ) - khz += fsb/2 ; + khz = (mult * fsb +50 ) /100 ; khz *=1000 ;return khz; }
@@ -162,6 +161,7 @@ static void do_powersaver(int cx_address longhaul.bits.RevisionKey = longhaul.bits.RevisionID; longhaul.bits.SoftBusRatio = clock_ratio_index &0xf ; longhaul.bits.SoftBusRatio4 = (clock_ratio_index &0x10 ) >>4 ; + longhaul.bits.EnableSoftBusRatio =1 ;/* Sync to timer tick */ safe_halt ();
@@ -193,23 +193,20 @@ static void longhaul_setstate(unsigned i {int speed, mult;struct cpufreq_freqs freqs; -static unsigned int old_ratio=-1 ;unsigned long flags;unsigned int pic1_mask, pic2_mask; -if (old_ratio == clock_ratio_index) -return ; - old_ratio = clock_ratio_index; - mult = clock_ratio[clock_ratio_index];if (mult ==-1 )return ; - speed =calc_speed (mult); -if ((speed > highest_speed) || (speed < lowest_speed)) + speed =calc_speed (mult, fsb); +if ( (speed == old_speed) + || (speed > highest_speed) + || (speed < lowest_speed) )return ; - freqs.old =calc_speed (longhaul_get_cpu_mult ()); + freqs.old = old_speed; freqs.new = speed; freqs.cpu =0 ;/* longhaul.c is UP only driver */
@@ -275,46 +272,7 @@ static void longhaul_setstate(unsigned ipreempt_enable ();cpufreq_notify_transition (&freqs,CPUFREQ_POSTCHANGE ); -} - -/* -* Centaur decided to make life a little more tricky. -* Only longhaul v1 is allowed to read EBLCR BSEL[0:1]. -* Samuel2 and above have to try and guess what the FSB is. -* We do this by assuming we booted at maximum multiplier, and interpolate -* between that value multiplied by possible FSBs and cpu_mhz which -* was calculated at boot time. Really ugly, but no other way to do this. -*/ - -#define ROUNDING 0xf - -static int _guess (int guess) -{ -int target; - - target = ((maxmult/10 )*guess); -if (maxmult%10 !=0 ) - target += (guess/2 ); - target +=ROUNDING /2 ; - target &= ~ROUNDING ; -return target; -} - - -static int guess_fsb (void ) -{ -int speed = (cpu_khz/1000 ); -int i; -int speeds[3 ] = {66 ,100 ,133 }; - - speed +=ROUNDING /2 ; - speed &= ~ROUNDING ; - -for (i=0 ; i<3 ; i++) { -if (_guess (speeds[i]) == speed) -return speeds[i]; - } -return 0 ; + old_speed = speed; }
@@ -327,8 +285,8 @@ static int __init longhaul_get_ranges(vounsigned int j, k =0 ;union msr_longhaul longhaul;unsigned long lo, hi; -unsigned int eblcr_fsb_table_v1[] = {66 ,133 ,100 ,-1 }; -unsigned int eblcr_fsb_table_v2[] = {133 ,100 ,-1 ,66 }; +unsigned int eblcr_fsb_table_v1[] = {666 ,1332 ,999 ,-1 }; +unsigned int eblcr_fsb_table_v2[] = {1332 ,999 ,1998 ,666 };switch (longhaul_version) {case TYPE_LONGHAUL_V1 :
@@ -339,73 +297,52 @@ static int __init longhaul_get_ranges(vo maxmult =longhaul_get_cpu_mult ();rdmsr (MSR_IA32_EBL_CR_POWERON , lo, hi); invalue = (lo & (1 <<18 |1 <<19 )) >>18 ; -if (cpu_model==CPU_SAMUEL || cpu_model==CPU_SAMUEL2 ) - fsb = eblcr_fsb_table_v1[invalue]; -else - fsb =guess_fsb (); + fsb_min = fsb = eblcr_fsb_table_v1[invalue]; + printk (KERN_INFO PFX "CPU don't have the min/max MSRs.\n");break ;case TYPE_POWERSAVER : -/* Ezra-T */ -if (cpu_model==CPU_EZRA_T ) { -rdmsrl (MSR_VIA_LONGHAUL , longhaul.val); - invalue = longhaul.bits.MaxMHzBR; -if (longhaul.bits.MaxMHzBR4) - invalue +=16 ; - maxmult=multipliers[invalue]; - - invalue = longhaul.bits.MinMHzBR; -if (longhaul.bits.MinMHzBR4 ==1 ) - minmult =30 ; -else - minmult = multipliers[invalue]; - fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; -break ; - } +rdmsrl (MSR_VIA_LONGHAUL , longhaul.val); -/* Nehemiah */ -if (cpu_model==CPU_NEHEMIAH ) { -rdmsrl (MSR_VIA_LONGHAUL , longhaul.val); - -/* -* TODO: This code works, but raises a lot of questions. -* - Some Nehemiah's seem to have broken Min/MaxMHzBR's. -* We get around this by using a hardcoded multiplier of 4.0x -* for the minimimum speed, and the speed we booted up at for the max. -* This is done in longhaul_get_cpu_mult() by reading the EBLCR register. -* - According to some VIA documentation EBLCR is only -* in pre-Nehemiah C3s. How this still works is a mystery. -* We're possibly using something undocumented and unsupported, -* But it works, so we don't grumble. -*/ - minmult=40 ; - maxmult=longhaul_get_cpu_mult (); - -/* Starting with the 1.2GHz parts, theres a 200MHz bus. */ -if ((cpu_khz/1000 ) >1200 ) - fsb =200 ; -else - fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; -break ; - } - } + invalue = longhaul.bits.MaxMHzBR; +if (longhaul.bits.MaxMHzBR4) + invalue +=16 ; + maxmult = multipliers[invalue]; + + invalue = longhaul.bits.MinMHzBR; +if (longhaul.bits.MinMHzBR4 ==1 ) + minmult =30 ; +else + minmult = multipliers[invalue]; -dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n" , - minmult/10 , minmult%10 , maxmult/10 , maxmult%10 ); +if (minmult <=45 ) clock_ratio[6 ] =45 ; +if (minmult <=40 ) clock_ratio[2 ] =40 ; +if (minmult <=35 ) clock_ratio[5 ] =35 ; +if (minmult ==30 ) clock_ratio[1 ] =30 ; + + fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; + fsb_min = eblcr_fsb_table_v2[longhaul.bits.MinMHzFSB]; +break ; + }if (fsb ==-1 ) { printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");return -EINVAL ; } - highest_speed =calc_speed (maxmult); - lowest_speed =calc_speed (minmult); -dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n" , fsb, -print_speed (lowest_speed/1000 ), -print_speed (highest_speed/1000 )); + highest_speed =calc_speed (maxmult, fsb); + lowest_speed =calc_speed (minmult, fsb_min); + printk(KERN_INFO PFX "Maximum frequency = %dMHz (%d.%d x %dMHz)\n", + highest_speed/1000 , + maxmult/10 , maxmult%10 , + fsb/10); + printk(KERN_INFO PFX "Minimum frequency = %dMHz (%d.%d x %dMHz)\n", + lowest_speed/1000 , + minmult/10 , minmult%10 , + fsb_min/10);if (lowest_speed == highest_speed) { - printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n"); + printk (KERN_INFO PFX "highest speed == lowest, aborting.\n");return -EINVAL ; }if (lowest_speed > highest_speed) {
@@ -418,14 +355,15 @@ static int __init longhaul_get_ranges(voif (!longhaul_table)return -ENOMEM ; -for (j=0 ; j < numscales; j++) { -unsigned int ratio; +for (j =0 ; j < numscales; j++) { +unsigned int ratio, speed; ratio = clock_ratio[j];if (ratio ==-1 )continue ; -if (ratio > maxmult || ratio < minmult) + speed =calc_speed (ratio, fsb); +if (speed > highest_speed || speed < lowest_speed)continue ; - longhaul_table[k].frequency =calc_speed (ratio); + longhaul_table[k].frequency = speed; longhaul_table[k].index = j; k++; }
@@ -521,7 +459,7 @@ static unsigned int longhaul_get(unsigne {if (cpu)return 0 ; -return calc_speed (longhaul_get_cpu_mult ()); +return calc_speed (longhaul_get_cpu_mult (), fsb); } acpi_status longhaul_walk_callback(acpi_handle obj_handle,
@@ -652,7 +590,7 @@ static int __init longhaul_cpu_init(stru policy->governor =CPUFREQ_DEFAULT_GOVERNOR ; policy->cpuinfo.transition_latency =200000 ;/* nsec */ - policy->cur =calc_speed (longhaul_get_cpu_mult ()); + policy->cur = old_speed =calc_speed (longhaul_get_cpu_mult (), fsb); ret =cpufreq_frequency_table_cpuinfo (policy, longhaul_table);if (ret)
------------------------------------------------------------------------
Znajdz krotsza droge do pracy!
http://map24.interia.pl/ - interaktywny planer podrozy.
Quoted 1 line · RafaÅ‚ Bilski
First. I lost very important line in
do_powersaver. Again. Sorry.
So why is this diff longer than one line ? :-)
Quoted 2 lines
Longhaul don't report minimum multiplier. It reports minimum frequency. So not always minimum multiplier at minimum FSB is really minimum.
I don't follow your logic. How can lowest mult * lowest fsb not be lowest frequency ? The MSRs most definitly only report the multipliers.
Quoted 3 lines
This is most important for Nehemiah witch allows FSB 66MHz, 100MHz and 133MHz. Ezra seems to support only 100MHz and 133MHz so in this case minimum multiplier at min FSB reported is in fact minimum PLL multiplier.
Note, that we don't (and won't) do FSB scaling even the hardware in some variants of longhaul claim to support it. The reality is that there are very few boards out there that can do it, and it's impossible to detect at runtime which boards they are. Given this, all boards should always boot up at the fastest FSB, so the FSB we read at startup should remain constant.
Quoted 2 lines
Looks like all VIA CPUs allow to read FSB frequency from
EBL_CR_POWERON. Only some have 66MHz reserved.
ISTR there was at least one (Ezra maybe?) that didn't.
Quoted 2 lines
More precise speed calculations. This is bad when kernel first reports 999MHz and we are saying later that max is 997MHz.
I'd rather keep the code readable and lose a tiny bit of accuracy here. The tables match the descriptions in the datasheets exactly, which makes it easier to review.
Dave
Signature · 1 line
http://www.codemonkey.org.uk
Quoted 5 lines · Rafa³ Bilski
Quoted 1 line
First. I lost very important line in
do_powersaver. Again. Sorry.So why is this diff longer than one line ? :-)
[...]
Quoted 2 lines
Dave
Right.
---
arch/i386/kernel/cpu/cpufreq/longhaul.c renamed from arch/i386/kernel/cpu/cpufreq/longhaul.c.orig +1 -0
@@ -162,6 +162,7 @@ static void do_powersaver(int cx_address longhaul.bits.RevisionKey = longhaul.bits.RevisionID; longhaul.bits.SoftBusRatio = clock_ratio_index &0xf ; longhaul.bits.SoftBusRatio4 = (clock_ratio_index &0x10 ) >>4 ; + longhaul.bits.EnableSoftBusRatio =1 ;/* Sync to timer tick */ safe_halt ();
----------------------------------------------------------------------
PS. Fajny portal... >>> http://link.interia.pl/f196a
[...]
Quoted 5 lines
Quoted 2 lines
Longhaul don't report minimum multiplier. It reports minimum frequency. So not always minimum multiplier at minimum FSB is really minimum.
I don't follow your logic. How can lowest mult * lowest fsb not be lowest frequency ? The MSRs most definitly only report the multipliers.
I don't know how to explain this properly in English. I will use example. This is from my Nehemiah:
min f = 433MHz = 6.5 * 66MHz
max f = 999MHz = 7.5 * 133MHz
but this is Nehemiah "C" and it is working downto 4.0 multiplier.
This is Ezra that I have found in Google (output from Your program):
min f = 300MHz = 3.0 * 100MHz
max f = 864MHz = 6.5 * 133MHz
Quoted 10 lines
Quoted 4 lines
This is most important for Nehemiah witch allows FSB 66MHz, 100MHz and 133MHz. Ezra seems to support only 100MHz and 133MHz so in this case minimum multiplier at min FSB reported is in fact minimum PLL multiplier.
Note, that we don't (and won't) do FSB scaling even the hardware in some variants of longhaul claim to support it. The reality is that there are very few boards out there that can do it, and it's impossible to detect at runtime which boards they are. Given this, all boards should always boot up at the fastest FSB, so the FSB we read at startup should remain constant.
I don't intend to do FSB scaling. I really don't belive that boards that don't have hardware necesary for voltage scaling are capable of scaling FSB. And I have removed FSB scaling capability code from my patch. Unfortunatly I have removed to much and I lost that line.
I'm trying to be more compatible with information from Longhaul MSR. Even if this register is broken for my CPU, using min frequency insteed of min multiplier is fixing this.
Quoted 6 lines
Quoted 3 lines
Looks like all VIA CPUs allow to read FSB frequency from
EBL_CR_POWERON. Only some have 66MHz reserved.ISTR there was at least one (Ezra maybe?) that didn't.
I don't have NDA protected information, but acording to this available to public both Ezra and Ezra-T have bus frequency bits.
Quoted 10 lines
Quoted 2 lines
More precise speed calculations. This is bad when kernel first reports 999MHz and we are saying later that max is 997MHz.
I'd rather keep the code readable and lose a tiny bit of accuracy here. The tables match the descriptions in the datasheets exactly, which makes it easier to review.
Dave
Come on. We are changing only two tables. Function "calc speed" must be changed to support FSB anyway.
Rafa³
----------------------------------------------------------------------
PS. Fajny portal... >>> http://link.interia.pl/f196a
Quoted 13 lines · RafaÅ‚ Bilski
[...]
Quoted 5 lines
Quoted 2 lines
Longhaul don't report minimum multiplier. It reports minimum frequency. So not always minimum multiplier at minimum FSB is really minimum.
I don't follow your logic. How can lowest mult * lowest fsb not be lowest frequency ? The MSRs most definitly only report the multipliers.
I don't know how to explain this properly in English. I will use example. This is from my Nehemiah:
min f = 433MHz = 6.5 * 66MHz
max f = 999MHz = 7.5 * 133MHz
but this is Nehemiah "C" and it is working downto 4.0 multiplier.
Quoted 3 lines
This is Ezra that I have found in Google (output from Your program):
min f = 300MHz = 3.0 * 100MHz
max f = 864MHz = 6.5 * 133MHz
But this is only true IFF we scale the FSB, which we don't. The above scenarios will not happen for as long as that is true.
Quoted 3 lines
I'm trying to be more compatible with information from Longhaul MSR. Even if this register is broken for my CPU, using min frequency insteed of min multiplier is fixing this.
when you say 'min frequency', which MSR bits are you talking about?
Dave
Signature · 1 line
http://www.codemonkey.org.uk
Quoted 7 lines
Quoted 7 lines
I don't know how to explain this properly in English. I will use example. This is from my Nehemiah:
min f = 433MHz = 6.5 * 66MHz
max f = 999MHz = 7.5 * 133MHz
but this is Nehemiah "C" and it is working downto 4.0 multiplier.
Quoted 6 lines
Quoted 3 lines
This is Ezra that I have found in Google (output from Your program):
min f = 300MHz = 3.0 * 100MHz
max f = 864MHz = 6.5 * 133MHzBut this is only true IFF we scale the FSB, which we don't. The above scenarios will not happen for as long as that is true.
Yes.
Quoted 9 lines
Quoted 4 lines
I'm trying to be more compatible with information from Longhaul MSR. Even if this register is broken for my CPU, using min frequency insteed of min multiplier is fixing this.
when you say 'min frequency', which MSR bits are you talking about?
Dave
I mean that
min frequency = MinMHzFSB * MinMHzBR
of course values from multipliers and fsb tables.
This is big patch, but change I want to do is in this:
ratio = clock_ratio[j];
if (ratio == -1)
continue;
- if (ratio > maxmult || ratio < minmult)
+ speed = calc_speed(ratio, fsb);
+ if (speed > highest_speed || speed < lowest_speed)
continue;
- longhaul_table[k].frequency = calc_speed(ratio);
+ longhaul_table[k].frequency = speed;
If I would blindly read MinMHzBR for my CPU then minimal multiplier would be 6.5, but in fact this processor is capable of 4.0.
Rafa³
------------------------------------------------------------------------
Wyjezdzasz na wakacje? Zaplanuj trase z map24.
http://map24.interia.pl/
Quoted 6 lines
Quoted 6 lines
I don't know how to explain this properly in English. I will use example. This is from my Nehemiah:
min f = 433MHz = 6.5 * 66MHz
max f = 999MHz = 7.5 * 133MHz
but this is Nehemiah "C" and it is working downto 4.0 multiplier.
Quoted 7 lines
Quoted 3 lines
This is Ezra that I have found in Google (output from Your program):
min f = 300MHz = 3.0 * 100MHz
max f = 864MHz = 6.5 * 133MHzBut this is only true IFF we scale the FSB, which we don't. The above scenarios will not happen for as long as that is true.
I'm starting to thinking that printing this information to user isn't good idea. Probably will cause confusion. What are You thinking about printing min( longhaul_table[].frequency )? This would print motherboard, not processor, limit.
Rafa³
----------------------------------------------------------------------
PS. Fajny portal... >>> http://link.interia.pl/f196a
Quoted 10 lines · RafaÅ‚ Bilski
Quoted 10 lines
Quoted 9 lines
I don't know how to explain this properly in English. I will use example. This is from my Nehemiah:
min f = 433MHz = 6.5 * 66MHz
max f = 999MHz = 7.5 * 133MHz
but this is Nehemiah "C" and it is working downto 4.0 multiplier.This is Ezra that I have found in Google (output from Your program):
min f = 300MHz = 3.0 * 100MHz
max f = 864MHz = 6.5 * 133MHz
Quoted 6 lines
Quoted 3 lines
But this is only true IFF we scale the FSB, which we don't. The above scenarios will not happen for as long as that is true.
I'm starting to thinking that printing this information to user isn't good idea.
Leaving such printk's as 'dprintk's is the best way forward. That way they only get displayed if someone boots up with cpufreq.debug=
Dave
Signature · 1 line
http://www.codemonkey.org.uk