powernow-k8 updates
Hi!
Few updates, enable ACPI, add common printing function, fix typo, move "pst out of sequence" where it belongs, fix formating in powernow-k8.h. I'm not quite sure what this is against, so this is "eyes only".
Pavel
arch/i386/kernel/cpu/cpufreq/powernow-k8.c renamed from linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +68 -25
@@ -33,6 +33,9 @@#include <asm/io.h> #include <asm/delay.h> +#ifdef CONFIG_ACPI +#define CONFIG_X86_POWERNOW_K8_ACPI +#endif #ifdef CONFIG_X86_POWERNOW_K8_ACPI #include <linux/acpi.h>
@@ -42,7 +45,7 @@#define PFX "powernow-k8: " -#define VERSION "version 1.20.07 - March 18, 2004" +#define VERSION "version 1.20.08b - March 20, 2004"#include "powernow-k8.h" /* serialize freq changes */
@@ -63,6 +66,12 @@return 1000 *find_freq_from_fid (fid); } +/* Return a voltage in miliVolts, given an input vid */ +static inline u32 find_milivolts_from_vid (struct powernow_k8_data *data,u32 vid) +{ +return 1550 -vid*25 ; +} +/* Return the vco fid for an input fid */ static u32 convert_fid_to_vco_fid (u32 fid) {
@@ -498,16 +507,36 @@return 0 ; } +static void print_basics (struct powernow_k8_data *data) +{ +int j; +for (j =0 ; j < data->numps; j++) { + printk(KERN_INFO PFX " %d : fid %x (%d MHz), vid %x (%d mV)\n", j, + data->powernow_table[j].index &0xff , + data->powernow_table[j].frequency/1000 , + data->powernow_table[j].index >>8 , + find_milivolts_from_vid(data, data->powernow_table[j].index >> 8)); + } +if (data->batps) + printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps); +} +static inline int fill_powernow_table (struct powernow_k8_data *data,struct pst_s *pst,u8 maxvid) {struct cpufreq_frequency_table *powernow_table;unsigned int j;if (data->batps) {/* use ACPI support to get full speed on mains power */ - printk(KERN_INFO PFX "only %d pstates on battery\n", data->batps); + printk(KERN_WARNING PFX "Only %d pstates usable (use ACPI driver for full range\n", data->batps); data->numps = data->batps; } +for ( j=1 ; j<data->numps; j++ ) +if (pst[j-1 ].fid >= pst[j].fid) { + printk(KERN_ERR PFX "PST out of sequence\n"); +return -EINVAL ; + } +if (data->numps <2 ) { printk(KERN_ERR PFX "no p states to transition\n");return -ENODEV ;
@@ -527,10 +556,6 @@ powernow_table[j].index = pst[j].fid;/* lower 8 bits */ powernow_table[j].index |= (pst[j].vid <<8 );/* upper 8 bits */ powernow_table[j].frequency =find_khz_freq_from_fid (pst[j].fid); - - printk(KERN_INFO PFX " %d : fid %x (%d MHz), vid %x\n", j, - pst[j].fid, powernow_table[j].frequency/1000, pst[j].vid); - } powernow_table[data->numps].frequency =CPUFREQ_TABLE_END ; powernow_table[data->numps].index =0 ;
@@ -540,14 +565,15 @@return -EIO ; } - printk(KERN_INFO PFX "cfid %x, cvid %x\n", data->currfid, data->currvid); + dprintk(KERN_INFO PFX "cfid %x, cvid %x\n", data->currfid, data->currvid); data->powernow_table = powernow_table; +print_basics (data);for (j =0 ; j < data->numps; j++)if ((pst[j].fid==data->currfid) && (pst[j].vid==data->currvid))return 0 ; - printk(KERN_ERR PFX "currfid/vid do not match PST, ignoring\n"); + dprintk(KERN_ERR PFX "currfid/vid do not match PST, ignoring\n");return 0 ; }
@@ -616,6 +642,17 @@return fill_powernow_table (data, (struct pst_s *)(psb+1 ), maxvid); } +/* +* If you see this message, complain to BIOS manufacturer. If +* he tells you "we do not support Linux" or some similar +* nonsense, remember that Windows 2000 uses the same legacy +* mechanism that the old Linux PSB driver uses. Tell them it +* is broken with Windows 2000. +* +* The reference to the AMD documentation is chapter 9 in the +* BIOS and Kernel Developer's Guide, which is available on +* www.amd.com +*/ printk(KERN_ERR PFX "BIOS error - no PSB\n");#if 1
@@ -632,17 +669,17 @@ data->irt =2 ; mvs =1 ; data->vidmvs =1 << mvs; - data->batps =3 ; - data->numps =3 ; + data->batps =4 ; + data->numps =4 ; data->plllock =2 ; { -struct pst_s override[3 ] = {{ .vid =0x12 , .fid =0x00 },/* 0.8GHz @ 1.100v */ +struct pst_s override[4 ] = {{ .vid =0x12 , .fid =0x00 },/* 0.8GHz @ 1.100v */ { .vid =0x06 , .fid =0x08 },/* 1.6GHz @ 1.400v */ - { .vid =0x02 , .fid =0x0a }};/* 1.8GHz @ 1.500v */ + { .vid =0x04 , .fid =0x0a },/* 1.8GHz @ 1.450v */ + { .vid =0x02 , .fid =0x0c }};/* 2.0GHz @ 1.500v */ return fill_powernow_table (data, override,0 ); }#endif -return -ENODEV ; }
@@ -664,6 +701,7 @@static int powernow_k8_cpu_init_acpi (struct powernow_k8_data *data) {int i; +int cntlofreq =0 ;struct cpufreq_frequency_table *powernow_table;if (acpi_processor_register_performance (&data->acpi_data, data->cpu)) {
@@ -683,8 +721,6 @@ goto err_out; } -/* FIXME: more tests? */ -/* fill in data->powernow_table */ powernow_table =kmalloc ((sizeof (struct cpufreq_frequency_table ) * (data->acpi_data.state_count +1 )),GFP_KERNEL );
@@ -704,12 +740,19 @@ powernow_table[i].frequency =find_khz_freq_from_fid (fid);/* verify frequency is OK */ -if (powernow_table[i].frequency > (MAX_FREQ *1000 )) { +if ((powernow_table[i].frequency > (MAX_FREQ *1000 )) || + (powernow_table[i].frequency < (MIN_FREQ *1000 ))) { dprintk(KERN_INFO PFX "invalid freq %u kHz\n", powernow_table[i].frequency); powernow_table[i].frequency =CPUFREQ_ENTRY_INVALID ;continue ; } +/* verify only 1 entry from the lo frequency table */ +if ((fid <HI_FID_TABLE_BOTTOM ) && (cntlofreq++)) { + printk(KERN_ERR PFX "Too many lo freq table entries\n"); + goto err_out; + } +if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency *1000 )) { printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", powernow_table[i].frequency,
@@ -719,11 +762,13 @@ } } powernow_table[data->acpi_data.state_count].frequency =CPUFREQ_TABLE_END ; - + powernow_table[data->acpi_data.state_count].index =0 ; data->powernow_table = powernow_table;/* fill in data */ data->numps = data->acpi_data.state_count; +print_basics (data); +powernow_k8_acpi_pst_values (data,0 );return 0 ;
@@ -899,8 +944,7 @@ data->cpu = pol->cpu; -if (powernow_k8_cpu_init_acpi (data)) - { +if (powernow_k8_cpu_init_acpi (data)) {/* * Use the PSB BIOS structure. This is only availabe on * an UP version, and is deprecated by AMD.
@@ -912,9 +956,8 @@return -ENODEV ; } -if ((num_online_cpus () !=1 ) || - (num_possible_cpus () !=1 )) { - printk(KERN_INFO PFX "multiprocessor systems not supported by PSB BIOS structure\n"); +if ((num_online_cpus () !=1 ) || (num_possible_cpus () !=1 )) { + printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");kfree (data);return 0 ; }
@@ -971,7 +1014,7 @@ }cpufreq_frequency_table_get_attr (data->powernow_table, pol->cpu); - printk(KERN_INFO PFX "init, curr fid %x vid %x\n", data->currfid, data->currvid); + dprintk(KERN_INFO PFX "init, curr fid %x vid %x\n", data->currfid, data->currvid); powernow_data[pol->cpu] = data;
@@ -1017,7 +1060,6 @@ .attr = powernow_k8_attr, }; -/* driver entry point for init */ static int __init powernowk8_init (void ) {
@@ -1031,7 +1073,8 @@ }if (supported_cpus ==num_online_cpus ()) { - printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron processors (" VERSION ")\n", supported_cpus); + printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron processors (" VERSION ")\n", + supported_cpus);return cpufreq_register_driver (&cpufreq_amd64_driver); }
arch/i386/kernel/cpu/cpufreq/powernow-k8.h renamed from linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +24 -15
@@ -6,36 +6,32 @@*/ struct powernow_k8_data { -unsigned int cpu; +unsigned int cpu; -u32 numps;/* number of p-states */ -u32 batps;/* number of p-states -* supported on battery */ +u32 numps;/* number of p-states */ +u32 batps;/* number of p-states supported on battery */ /* these values are constant when the PSB is used to determine * vid/fid pairings, but are modified during the ->target() call * when ACPI is used */ -u32 rvo;/* ramp voltage offset */ -u32 irt;/* isochronous relief time */ -u32 vidmvs;/* usable value calculated -* from mvs */ -u32 vstable;/* voltage stabilization time, -* units 20 us */ -u32 plllock;/* pll lock time, -* units 1 us */ +u32 rvo;/* ramp voltage offset */ +u32 irt;/* isochronous relief time */ +u32 vidmvs;/* usable value calculated from mvs */ +u32 vstable;/* voltage stabilization time, units 20 us */ +u32 plllock;/* pll lock time, units 1 us */ /* keep track of the current fid / vid */ -u32 currvid; -u32 currfid; +u32 currvid; +u32 currfid;/* the powernow_table includes all frequency and vid/fid pairings: * fid are the lower 8 bits of the index, vid are the upper 8 bits. * frequency is in kHz */ struct cpufreq_frequency_table *powernow_table; +#ifdef CONFIG_X86_POWERNOW_K8_ACPI /* the acpi table needs to be kept. it's only available if ACPI was * used to determine valid frequency/vid/fid states */ -#ifdef CONFIG_X86_POWERNOW_K8_ACPI struct acpi_processor_performance acpi_data;#endif };
@@ -78,6 +74,19 @@#define MSR_S_HI_CURRENT_VID 0x0000001f#define MSR_C_HI_STP_GNT_BENIGN 0x00000001 +/* +There are restrictions frequencies have to follow: +- only 1 entry in the low fid table ( <=1.4GHz ) +- lowest entry in the high fid table must be >= 2 * the +entry in the low fid table +- lowest entry in the high fid table must be a <= 200MHz + +2 * the entry in the low fid table +- the parts can only step at 200 MHz intervals, so 1.9 GHz is +never valid +- lowest frequency must be >= interprocessor hypertransport link +speed (only applies to MP systems obviously) +*/ +/* fids (frequency identifiers) are arranged in 2 tables - lo and hi */ #define LO_FID_TABLE_TOP 6/* fid values marking the boundary */ #define HI_FID_TABLE_BOTTOM 8/* between the low and high tables */
Signature · 2 lines
When do you have a heart between your knees? [Johanka's followup: and *two* hearts?]
Hi!
Quoted 4 lines
Few updates, enable ACPI, add common printing function, fix typo, move "pst out of sequence" where it belongs, fix formating in
powernow-k8.h. I'm not quite sure what this is against, so this is "eyes only".
Its strange, ACPI code does not seem to mention batps at all, still cpu goes to 800MHz when I unplug the cord... Perhaps it should at least say something into the syslog?
Pavel
Signature · 2 lines
When do you have a heart between your knees? [Johanka's followup: and *two* hearts?]
Quoted 10 lines · Pavel Machek
Hi!
Quoted 4 lines
Few updates, enable ACPI, add common printing function, fix typo, move "pst out of sequence" where it belongs, fix formating in
powernow-k8.h. I'm not quite sure what this is against, so this is "eyes only".Its strange, ACPI code does not seem to mention batps at all, still cpu goes to 800MHz when I unplug the cord... Perhaps it should at least say something into the syslog?
... again our differences about verbosity... :-)
Dominik
_______________________________________________
Cpufreq mailing list
[email protected]
http://www.linux.org.uk/mailman/listinfo/cpufreq
Quoted 8 lines · Dominik Brodowski
Quoted 7 lines · Pavel Machek
Hi!
Quoted 4 lines
Few updates, enable ACPI, add common printing function, fix typo, move "pst out of sequence" where it belongs, fix formating in
powernow-k8.h. I'm not quite sure what this is against, so this is "eyes only".
Quoted 5 lines
Quoted 3 lines
Its strange, ACPI code does not seem to mention batps at all, still cpu goes to 800MHz when I unplug the cord... Perhaps it should at least say something into the syslog?
... again our differences about verbosity... :-)
Actually, I do not understand how it works. How does cpufreq know how many states are there on battery? It does something, but I'd like to understand it...
Pavel
Signature · 2 lines
When do you have a heart between your knees? [Johanka's followup: and *two* hearts?]
Quoted 13 lines · Pavel Machek
Quoted 12 lines · Dominik Brodowski
Quoted 10 lines · Pavel Machek
Hi!
Quoted 4 lines
Few updates, enable ACPI, add common printing function, fix typo, move "pst out of sequence" where it belongs, fix formating in
powernow-k8.h. I'm not quite sure what this is against, so this is "eyes only".Its strange, ACPI code does not seem to mention batps at all, still cpu goes to 800MHz when I unplug the cord... Perhaps it should at least say something into the syslog?
Quoted 5 lines
Quoted 1 line
... again our differences about verbosity... :-)
Actually, I do not understand how it works. How does cpufreq know how many states are there on battery? It does something, but I'd like to understand it...
The BIOS notifies the acpi processor module of a platform limit change (acpi_processor_notify). The acpi processor module then reads out the _PDC value of the ACPI table, which contains the maximum current supported P-State [P0 is highest freq, Px is lowest].
Then the cpufreq_update_policy() function is called: the last cpufreq policy set is send to the cpufreq notifiers, among them is acpi_processor_ppc_notifier(), which limits the max allowed frequency, see
cpufreq_verify_within_limits(policy, 0,
pr->performance->states[ppc].core_frequency * 1000);Then the policy (min/max frequency) is passed to a cpufreq governor [in most cases the userspace governor], which selects one speed between min and max frequency and tells the driver via ->target() of the frequency to set.
Hope this clarifies,
Dominik
_______________________________________________
Cpufreq mailing list
[email protected]
http://www.linux.org.uk/mailman/listinfo/cpufreq
Quoted 7 lines · Pavel Machek
Hi!
Few updates, enable ACPI, add common printing function, fix typo, move "pst out of sequence" where it belongs, fix formating in
powernow-k8.h. I'm not quite sure what this is against, so this is "eyes only".
Pavel
If I ignore our different opinions about driver verbosity if DEBUG isn't set (print_basics()), it looks good to me.
Dominik
_______________________________________________
Cpufreq mailing list
[email protected]
http://www.linux.org.uk/mailman/listinfo/cpufreq
Hi!
Quoted 7 lines
Quoted 4 lines
Few updates, enable ACPI, add common printing function, fix typo, move "pst out of sequence" where it belongs, fix formating in
powernow-k8.h. I'm not quite sure what this is against, so this is "eyes only".If I ignore our different opinions about driver verbosity if DEBUG isn't set (
print_basics()), it looks good to me.
For now, I'd like to print tables to the user.. When driver gets more stable, I agree it can go.
Pavel
Signature · 2 lines
When do you have a heart between your knees? [Johanka's followup: and *two* hearts?]