Commit ade30b83 authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Linus Torvalds

[PATCH] cpufreq: x86 driver updates (speedstep, longrun, p4-clockmod)

 - switch the Intel x86 speedstep/Pentium 4/Xeon drivers and the
   Transmeta Crusoe Longrun driver to use the advanced cpufreq_driver
   registration process
 - cleanups
 - spelling fixes (Petri Koistinen) - thanks!
parent 39de8270
/* /*
* $Id: longrun.c,v 1.14 2002/10/31 21:17:40 db Exp $ * $Id: longrun.c,v 1.22 2003/02/10 17:31:50 db Exp $
* *
* (C) 2002 Dominik Brodowski <linux@brodo.de> * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
* *
* Licensed under the terms of the GNU GPL License version 2. * Licensed under the terms of the GNU GPL License version 2.
* *
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/timex.h> #include <asm/timex.h>
static struct cpufreq_driver *longrun_driver; static struct cpufreq_driver longrun_driver;
/** /**
* longrun_{low,high}_freq is needed for the conversion of cpufreq kHz * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz
...@@ -39,9 +39,6 @@ static void longrun_get_policy(struct cpufreq_policy *policy) ...@@ -39,9 +39,6 @@ static void longrun_get_policy(struct cpufreq_policy *policy)
{ {
u32 msr_lo, msr_hi; u32 msr_lo, msr_hi;
if (!longrun_driver)
return;
rdmsr(MSR_TMTA_LONGRUN_FLAGS, msr_lo, msr_hi); rdmsr(MSR_TMTA_LONGRUN_FLAGS, msr_lo, msr_hi);
if (msr_lo & 0x01) if (msr_lo & 0x01)
policy->policy = CPUFREQ_POLICY_PERFORMANCE; policy->policy = CPUFREQ_POLICY_PERFORMANCE;
...@@ -72,7 +69,7 @@ static int longrun_set_policy(struct cpufreq_policy *policy) ...@@ -72,7 +69,7 @@ static int longrun_set_policy(struct cpufreq_policy *policy)
u32 msr_lo, msr_hi; u32 msr_lo, msr_hi;
u32 pctg_lo, pctg_hi; u32 pctg_lo, pctg_hi;
if (!longrun_driver || !policy) if (!policy)
return -EINVAL; return -EINVAL;
pctg_lo = (policy->min - longrun_low_freq) / pctg_lo = (policy->min - longrun_low_freq) /
...@@ -117,13 +114,16 @@ static int longrun_set_policy(struct cpufreq_policy *policy) ...@@ -117,13 +114,16 @@ static int longrun_set_policy(struct cpufreq_policy *policy)
*/ */
static int longrun_verify_policy(struct cpufreq_policy *policy) static int longrun_verify_policy(struct cpufreq_policy *policy)
{ {
if (!policy || !longrun_driver) if (!policy)
return -EINVAL; return -EINVAL;
policy->cpu = 0; policy->cpu = 0;
cpufreq_verify_within_limits(policy, cpufreq_verify_within_limits(policy,
longrun_driver->policy[0].cpuinfo.min_freq, policy->cpuinfo.min_freq,
longrun_driver->policy[0].cpuinfo.max_freq); policy->cpuinfo.max_freq);
if (policy->policy == CPUFREQ_POLICY_GOVERNOR)
policy->policy = longrun_driver.policy[0].policy;
return 0; return 0;
} }
...@@ -221,59 +221,59 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, ...@@ -221,59 +221,59 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
} }
/** static int longrun_cpu_init(struct cpufreq_policy *policy)
* longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
*
* Initializes the LongRun support.
*/
static int __init longrun_init(void)
{ {
int result; int result = 0;
struct cpufreq_driver *driver;
struct cpuinfo_x86 *c = cpu_data; struct cpuinfo_x86 *c = cpu_data;
/* capability check */
if (policy->cpu != 0)
return -ENODEV;
if (c->x86_vendor != X86_VENDOR_TRANSMETA || if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
!cpu_has(c, X86_FEATURE_LONGRUN)) !cpu_has(c, X86_FEATURE_LONGRUN))
return 0; return -ENODEV;
/* initialization of main "cpufreq" code*/ /* detect low and high frequency */
driver = kmalloc(sizeof(struct cpufreq_driver) + result = longrun_determine_freqs(&longrun_low_freq, &longrun_high_freq);
NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL); if (result)
if (!driver) return result;
return -ENOMEM;
memset(driver, 0, sizeof(struct cpufreq_driver) + /* cpuinfo and default policy values */
NR_CPUS * sizeof(struct cpufreq_policy)); policy->cpuinfo.min_freq = longrun_low_freq;
policy->cpuinfo.max_freq = longrun_high_freq;
driver->policy = (struct cpufreq_policy *) (driver + 1); policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
longrun_get_policy(policy);
if (longrun_determine_freqs(&longrun_low_freq, &longrun_high_freq)) {
kfree(driver); #ifdef CONFIG_CPU_FREQ_24_API
return -EIO; longrun_driver.cpu_cur_freq[policy->cpu] = longrun_low_freq; /* dummy value */
} #endif
driver->policy[0].cpuinfo.min_freq = longrun_low_freq;
driver->policy[0].cpuinfo.max_freq = longrun_high_freq;
driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
strncpy(driver->name, "longrun", CPUFREQ_NAME_LEN); return 0;
}
longrun_get_policy(&driver->policy[0]);
#ifdef CONFIG_CPU_FREQ_24_API static struct cpufreq_driver longrun_driver = {
driver->cpu_cur_freq[0] = longrun_high_freq; /* dummy value */ .verify = longrun_verify_policy,
#endif .setpolicy = longrun_set_policy,
.init = longrun_cpu_init,
.name = "longrun",
};
driver->verify = &longrun_verify_policy;
driver->setpolicy = &longrun_set_policy;
longrun_driver = driver; /**
* longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
*
* Initializes the LongRun support.
*/
static int __init longrun_init(void)
{
struct cpuinfo_x86 *c = cpu_data;
result = cpufreq_register(driver); if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
if (result) { !cpu_has(c, X86_FEATURE_LONGRUN))
longrun_driver = NULL; return -ENODEV;
kfree(driver);
}
return result; return cpufreq_register_driver(&longrun_driver);
} }
...@@ -282,15 +282,13 @@ static int __init longrun_init(void) ...@@ -282,15 +282,13 @@ static int __init longrun_init(void)
*/ */
static void __exit longrun_exit(void) static void __exit longrun_exit(void)
{ {
if (longrun_driver) { cpufreq_unregister_driver(&longrun_driver);
cpufreq_unregister();
kfree(longrun_driver);
}
} }
MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>"); MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION ("LongRun driver for Transmeta Crusoe processors."); MODULE_DESCRIPTION ("LongRun driver for Transmeta Crusoe processors.");
MODULE_LICENSE ("GPL"); MODULE_LICENSE ("GPL");
module_init(longrun_init); module_init(longrun_init);
module_exit(longrun_exit); module_exit(longrun_exit);
/* /*
* Pentium 4/Xeon CPU on demand clock modulation/speed scaling * Pentium 4/Xeon CPU on demand clock modulation/speed scaling
* (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
* (C) 2002 Zwane Mwaikambo <zwane@commfireservices.com> * (C) 2002 Zwane Mwaikambo <zwane@commfireservices.com>
* (C) 2002 Arjan van de Ven <arjanv@redhat.com> * (C) 2002 Arjan van de Ven <arjanv@redhat.com>
* (C) 2002 Tora T. Engstad * (C) 2002 Tora T. Engstad
...@@ -45,11 +46,10 @@ enum { ...@@ -45,11 +46,10 @@ enum {
#define DC_ENTRIES 8 #define DC_ENTRIES 8
static int has_N44_O17_errata; static int has_N44_O17_errata[NR_CPUS];
static int stock_freq; static int stock_freq;
MODULE_PARM(stock_freq, "i");
static struct cpufreq_driver *cpufreq_p4_driver; static struct cpufreq_driver p4clockmod_driver;
static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
...@@ -107,17 +107,17 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) ...@@ -107,17 +107,17 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
rdmsr(MSR_IA32_THERM_STATUS, l, h); rdmsr(MSR_IA32_THERM_STATUS, l, h);
if (l & 0x01) if (l & 0x01)
printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu); // printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu);
if (has_N44_O17_errata && (newstate == DC_25PT || newstate == DC_DFLT)) if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT))
newstate = DC_38PT; newstate = DC_38PT;
rdmsr(MSR_IA32_THERM_CONTROL, l, h); rdmsr(MSR_IA32_THERM_CONTROL, l, h);
if (newstate == DC_DISABLE) { if (newstate == DC_DISABLE) {
printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); // printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu);
wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
} else { } else {
printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10)); // printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10));
/* bits 63 - 5 : reserved /* bits 63 - 5 : reserved
* bit 4 : enable/disable * bit 4 : enable/disable
* bits 3-1 : duty cycle * bits 3-1 : duty cycle
...@@ -155,14 +155,16 @@ static struct cpufreq_frequency_table p4clockmod_table[] = { ...@@ -155,14 +155,16 @@ static struct cpufreq_frequency_table p4clockmod_table[] = {
}; };
static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy) static int cpufreq_p4_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{ {
unsigned int newstate = DC_RESV; unsigned int newstate = DC_RESV;
if (cpufreq_frequency_table_setpolicy(policy, &p4clockmod_table[0], &newstate)) if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate))
return -EINVAL; return -EINVAL;
cpufreq_p4_setdc(policy->cpu, newstate); cpufreq_p4_setdc(policy->cpu, p4clockmod_table[newstate].index);
return 0; return 0;
} }
...@@ -174,39 +176,30 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy) ...@@ -174,39 +176,30 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy)
} }
static int __init cpufreq_p4_init(void) static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
{ {
struct cpuinfo_x86 *c = cpu_data; struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
int cpuid; int cpuid = 0;
int ret;
struct cpufreq_driver *driver;
unsigned int i; unsigned int i;
/* /* capability check */
* THERM_CONTROL is architectural for IA32 now, so
* we can rely on the capability checks
*/
if (c->x86_vendor != X86_VENDOR_INTEL) if (c->x86_vendor != X86_VENDOR_INTEL)
return -ENODEV; return -ENODEV;
if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) || if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) ||
!test_bit(X86_FEATURE_ACC, c->x86_capability)) !test_bit(X86_FEATURE_ACC, c->x86_capability))
return -ENODEV; return -ENODEV;
/* Errata workarounds */ /* Errata workaround */
cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask; cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask;
switch (cpuid) { switch (cpuid) {
case 0x0f07: case 0x0f07:
case 0x0f0a: case 0x0f0a:
case 0x0f11: case 0x0f11:
case 0x0f12: case 0x0f12:
has_N44_O17_errata = 1; has_N44_O17_errata[policy->cpu] = 1;
default:
break;
} }
printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); /* get frequency */
if (!stock_freq) { if (!stock_freq) {
if (cpu_khz) if (cpu_khz)
stock_freq = cpu_khz; stock_freq = cpu_khz;
...@@ -216,71 +209,69 @@ static int __init cpufreq_p4_init(void) ...@@ -216,71 +209,69 @@ static int __init cpufreq_p4_init(void)
} }
} }
driver = kmalloc(sizeof(struct cpufreq_driver) +
NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
if (!driver)
return -ENOMEM;
memset(driver, 0, sizeof(struct cpufreq_driver) +
NR_CPUS * sizeof(struct cpufreq_policy));
driver->policy = (struct cpufreq_policy *) (driver + 1);
/* table init */ /* table init */
for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) { for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
if ((i<2) && (has_N44_O17_errata)) if ((i<2) && (has_N44_O17_errata[policy->cpu]))
p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID; p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
else else
p4clockmod_table[i].frequency = (stock_freq * i)/8; p4clockmod_table[i].frequency = (stock_freq * i)/8;
} }
/* cpuinfo and default policy values */
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->cpuinfo.transition_latency = 1000;
#ifdef CONFIG_CPU_FREQ_24_API #ifdef CONFIG_CPU_FREQ_24_API
for (i=0;i<NR_CPUS;i++) { p4clockmod_driver.cpu_cur_freq[policy->cpu] = stock_freq;
driver->cpu_cur_freq[i] = stock_freq;
}
#endif #endif
driver->verify = &cpufreq_p4_verify; return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
driver->setpolicy = &cpufreq_p4_setpolicy; }
strncpy(driver->name, "p4-clockmod", CPUFREQ_NAME_LEN);
for (i=0;i<NR_CPUS;i++) {
driver->policy[i].cpu = i;
ret = cpufreq_frequency_table_cpuinfo(&driver->policy[i], &p4clockmod_table[0]);
if (ret) {
kfree(driver);
return ret;
}
driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;
driver->policy[i].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
}
cpufreq_p4_driver = driver; static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
{
ret = cpufreq_register(driver); return cpufreq_p4_setdc(policy->cpu, DC_DISABLE);
if (ret) { }
cpufreq_p4_driver = NULL;
kfree(driver);
}
return ret;
static struct cpufreq_driver p4clockmod_driver = {
.verify = cpufreq_p4_verify,
.target = cpufreq_p4_target,
.init = cpufreq_p4_cpu_init,
.exit = cpufreq_p4_cpu_exit,
.name = "p4-clockmod",
};
static int __init cpufreq_p4_init(void)
{
struct cpuinfo_x86 *c = cpu_data;
/*
* THERM_CONTROL is architectural for IA32 now, so
* we can rely on the capability checks
*/
if (c->x86_vendor != X86_VENDOR_INTEL)
return -ENODEV;
if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) ||
!test_bit(X86_FEATURE_ACC, c->x86_capability))
return -ENODEV;
printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n");
return cpufreq_register_driver(&p4clockmod_driver);
} }
static void __exit cpufreq_p4_exit(void) static void __exit cpufreq_p4_exit(void)
{ {
unsigned int i; cpufreq_unregister_driver(&p4clockmod_driver);
if (cpufreq_p4_driver) {
for (i=0; i<NR_CPUS; i++) {
if (cpu_online(i))
cpufreq_p4_setdc(i, DC_DISABLE);
}
cpufreq_unregister();
kfree(cpufreq_p4_driver);
}
} }
MODULE_PARM(stock_freq, "i");
MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>"); MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>");
MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)"); MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)");
MODULE_LICENSE ("GPL"); MODULE_LICENSE ("GPL");
......
/* /*
* $Id: speedstep.c,v 1.58 2002/11/11 15:35:46 db Exp $ * $Id: speedstep.c,v 1.68 2003/01/20 17:31:47 db Exp $
* *
* (C) 2001 Dave Jones, Arjan van de ven. * (C) 2001 Dave Jones, Arjan van de ven.
* (C) 2002 Dominik Brodowski <linux@brodo.de> * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
* *
* Licensed under the terms of the GNU GPL License version 2. * Licensed under the terms of the GNU GPL License version 2.
* Based upon reverse engineered information, and on Intel documentation * Based upon reverse engineered information, and on Intel documentation
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <asm/msr.h> #include <asm/msr.h>
static struct cpufreq_driver *speedstep_driver; static struct cpufreq_driver speedstep_driver;
/* speedstep_chipset: /* speedstep_chipset:
* It is necessary to know which chipset is used. As accesses to * It is necessary to know which chipset is used. As accesses to
...@@ -208,7 +208,7 @@ static void speedstep_set_state (unsigned int state, int notify) ...@@ -208,7 +208,7 @@ static void speedstep_set_state (unsigned int state, int notify)
pm2_blk &= 0xfe; pm2_blk &= 0xfe;
outb(pm2_blk, (pmbase + 0x20)); outb(pm2_blk, (pmbase + 0x20));
/* check if transition was sucessful */ /* check if transition was successful */
value = inb(pmbase + 0x50); value = inb(pmbase + 0x50);
/* Enable IRQs */ /* Enable IRQs */
...@@ -217,7 +217,7 @@ static void speedstep_set_state (unsigned int state, int notify) ...@@ -217,7 +217,7 @@ static void speedstep_set_state (unsigned int state, int notify)
dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
if (state == (value & 0x1)) { if (state == (value & 0x1)) {
dprintk (KERN_INFO "cpufreq: change to %u MHz succeded\n", (freqs.new / 1000)); dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (freqs.new / 1000));
} else { } else {
printk (KERN_ERR "cpufreq: change failed - I/O error\n"); printk (KERN_ERR "cpufreq: change failed - I/O error\n");
} }
...@@ -311,7 +311,7 @@ static unsigned int speedstep_detect_chipset (void) ...@@ -311,7 +311,7 @@ static unsigned int speedstep_detect_chipset (void)
pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
if (rev < 5) { if (rev < 5) {
dprintk(KERN_INFO "cpufreq: hostbrige does not support speedstep\n"); dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n");
speedstep_chipset_dev = NULL; speedstep_chipset_dev = NULL;
return 0; return 0;
} }
...@@ -573,11 +573,13 @@ static int speedstep_detect_speeds (void) ...@@ -573,11 +573,13 @@ static int speedstep_detect_speeds (void)
* *
* Sets a new CPUFreq policy. * Sets a new CPUFreq policy.
*/ */
static int speedstep_setpolicy (struct cpufreq_policy *policy) static int speedstep_target (struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{ {
unsigned int newstate = 0; unsigned int newstate = 0;
if (cpufreq_frequency_table_setpolicy(policy, &speedstep_freqs[0], &newstate)) if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
return -EINVAL; return -EINVAL;
speedstep_set_state(newstate, 1); speedstep_set_state(newstate, 1);
...@@ -599,6 +601,42 @@ static int speedstep_verify (struct cpufreq_policy *policy) ...@@ -599,6 +601,42 @@ static int speedstep_verify (struct cpufreq_policy *policy)
} }
static int speedstep_cpu_init(struct cpufreq_policy *policy)
{
int result = 0;
unsigned int speed;
/* capability check */
if (policy->cpu != 0)
return -ENODEV;
/* detect low and high frequency */
result = speedstep_detect_speeds();
if (result)
return result;
/* get current speed setting */
result = speedstep_get_state(&speed);
if (result)
return result;
speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq;
dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n",
(speed == speedstep_low_freq) ? "low" : "high",
(speed / 1000));
/* cpuinfo and default policy values */
policy->policy = (speed == speedstep_low_freq) ?
CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
#ifdef CONFIG_CPU_FREQ_24_API
speedstep_driver.cpu_cur_freq[policy->cpu] = speed;
#endif
return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]);
}
#ifndef MODULE #ifndef MODULE
/** /**
* speedstep_setup speedstep command line parameter parsing * speedstep_setup speedstep command line parameter parsing
...@@ -608,7 +646,7 @@ static int speedstep_verify (struct cpufreq_policy *policy) ...@@ -608,7 +646,7 @@ static int speedstep_verify (struct cpufreq_policy *policy)
* if the CPU in your notebook is a SpeedStep-capable Intel * if the CPU in your notebook is a SpeedStep-capable Intel
* Pentium III Coppermine. These processors cannot be detected * Pentium III Coppermine. These processors cannot be detected
* automatically, as Intel continues to consider the detection * automatically, as Intel continues to consider the detection
* alogrithm as proprietary material. * algorithm as proprietary material.
*/ */
static int __init speedstep_setup(char *str) static int __init speedstep_setup(char *str)
{ {
...@@ -618,6 +656,15 @@ static int __init speedstep_setup(char *str) ...@@ -618,6 +656,15 @@ static int __init speedstep_setup(char *str)
__setup("speedstep_coppermine=", speedstep_setup); __setup("speedstep_coppermine=", speedstep_setup);
#endif #endif
static struct cpufreq_driver speedstep_driver = {
.name = "speedstep",
.verify = speedstep_verify,
.target = speedstep_target,
.init = speedstep_cpu_init,
};
/** /**
* speedstep_init - initializes the SpeedStep CPUFreq driver * speedstep_init - initializes the SpeedStep CPUFreq driver
* *
...@@ -627,11 +674,6 @@ __setup("speedstep_coppermine=", speedstep_setup); ...@@ -627,11 +674,6 @@ __setup("speedstep_coppermine=", speedstep_setup);
*/ */
static int __init speedstep_init(void) static int __init speedstep_init(void)
{ {
int result;
unsigned int speed;
struct cpufreq_driver *driver;
/* detect chipset */ /* detect chipset */
speedstep_chipset = speedstep_detect_chipset(); speedstep_chipset = speedstep_detect_chipset();
...@@ -644,70 +686,13 @@ static int __init speedstep_init(void) ...@@ -644,70 +686,13 @@ static int __init speedstep_init(void)
return -ENODEV; return -ENODEV;
} }
dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.58 $\n"); dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.68 $\n");
dprintk(KERN_DEBUG "cpufreq: chipset 0x%x - processor 0x%x\n",
speedstep_chipset, speedstep_processor);
/* activate speedstep support */ /* activate speedstep support */
result = speedstep_activate(); if (speedstep_activate())
if (result) return -EINVAL;
return result;
/* detect low and high frequency */
result = speedstep_detect_speeds();
if (result)
return result;
/* get current speed setting */
result = speedstep_get_state(&speed);
if (result)
return result;
speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq;
dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n",
(speed == speedstep_low_freq) ? "low" : "high",
(speed / 1000));
/* initialization of main "cpufreq" code*/
driver = kmalloc(sizeof(struct cpufreq_driver) +
NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
if (!driver)
return -ENOMEM;
memset(driver, 0, sizeof(struct cpufreq_driver) +
NR_CPUS * sizeof(struct cpufreq_policy));
driver->policy = (struct cpufreq_policy *) (driver + 1);
driver->policy[0].cpu = 0;
result = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &speedstep_freqs[0]);
if (result) {
kfree(driver);
return result;
}
#ifdef CONFIG_CPU_FREQ_24_API
driver->cpu_cur_freq[0] = speed;
#endif
driver->verify = &speedstep_verify;
driver->setpolicy = &speedstep_setpolicy;
strncpy(driver->name, "speedstep", CPUFREQ_NAME_LEN);
driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
driver->policy[0].policy = (speed == speedstep_low_freq) ?
CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
speedstep_driver = driver;
result = cpufreq_register(driver);
if (result) {
speedstep_driver = NULL;
kfree(driver);
}
return result; return cpufreq_register_driver(&speedstep_driver);
} }
...@@ -718,17 +703,15 @@ static int __init speedstep_init(void) ...@@ -718,17 +703,15 @@ static int __init speedstep_init(void)
*/ */
static void __exit speedstep_exit(void) static void __exit speedstep_exit(void)
{ {
if (speedstep_driver) { cpufreq_unregister_driver(&speedstep_driver);
cpufreq_unregister();
kfree(speedstep_driver);
}
} }
MODULE_PARM (speedstep_coppermine, "i");
MODULE_AUTHOR ("Dave Jones <davej@suse.de>, Dominik Brodowski <linux@brodo.de>"); MODULE_AUTHOR ("Dave Jones <davej@suse.de>, Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors."); MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors.");
MODULE_LICENSE ("GPL"); MODULE_LICENSE ("GPL");
module_init(speedstep_init); module_init(speedstep_init);
module_exit(speedstep_exit); module_exit(speedstep_exit);
MODULE_PARM (speedstep_coppermine, "i");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment