cpufreq: Add support for x86 cpuinfo auto loading v4
This marks all the x86 cpuinfo tables to the CPU specific device drivers, to allow auto loading by udev. This should simplify the distribution startup scripts for this greatly. I didn't add MODULE_DEVICE_IDs to the centrino and p4-clockmod drivers, because those probably shouldn't be auto loaded and the acpi driver be used instead (not fully sure on that, would appreciate feedback) The old nforce drivers autoload based on the PCI ID. ACPI cpufreq is autoloaded in another patch. v3: Autoload gx based on PCI IDs only. Remove cpu check (Dave Jones) v4: Use newly introduce HW_PSTATE feature for powernow-k8 loading Cc: Dave Jones <davej@redhat.com> Cc: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Thomas Renninger <trenn@suse.de> Acked-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
2f1e097e24
Коммит
fa8031aefe
|
@ -385,6 +385,14 @@ static struct cpufreq_driver nforce2_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = {
|
||||
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, nforce2_ids);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic
|
||||
*
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/tsc.h>
|
||||
|
||||
|
@ -437,18 +438,19 @@ static struct cpufreq_driver eps_driver = {
|
|||
.attr = eps_attr,
|
||||
};
|
||||
|
||||
|
||||
/* This driver will work only on Centaur C7 processors with
|
||||
* Enhanced SpeedStep/PowerSaver registers */
|
||||
static const struct x86_cpu_id eps_cpu_id[] = {
|
||||
{ X86_VENDOR_CENTAUR, 6, X86_MODEL_ANY, X86_FEATURE_EST },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, eps_cpu_id);
|
||||
|
||||
static int __init eps_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
||||
/* This driver will work only on Centaur C7 processors with
|
||||
* Enhanced SpeedStep/PowerSaver registers */
|
||||
if (c->x86_vendor != X86_VENDOR_CENTAUR
|
||||
|| c->x86 != 6 || c->x86_model < 10)
|
||||
if (!x86_match_cpu(eps_cpu_id) || boot_cpu_data.x86_model < 10)
|
||||
return -ENODEV;
|
||||
if (!cpu_has(c, X86_FEATURE_EST))
|
||||
return -ENODEV;
|
||||
|
||||
if (cpufreq_register_driver(&eps_driver))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/msr.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/io.h>
|
||||
|
@ -277,17 +278,16 @@ static struct cpufreq_driver elanfreq_driver = {
|
|||
.attr = elanfreq_attr,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id elan_id[] = {
|
||||
{ X86_VENDOR_AMD, 4, 10, },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, elan_id);
|
||||
|
||||
static int __init elanfreq_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
||||
/* Test if we have the right hardware */
|
||||
if ((c->x86_vendor != X86_VENDOR_AMD) ||
|
||||
(c->x86 != 4) || (c->x86_model != 10)) {
|
||||
printk(KERN_INFO "elanfreq: error: no Elan processor found!\n");
|
||||
if (!x86_match_cpu(elan_id))
|
||||
return -ENODEV;
|
||||
}
|
||||
return cpufreq_register_driver(&elanfreq_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/processor-cyrix.h>
|
||||
|
||||
/* PCI config registers, all at F0 */
|
||||
|
@ -171,6 +172,7 @@ static struct pci_device_id gx_chipset_tbl[] __initdata = {
|
|||
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), },
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(gx_chipset_tbl);
|
||||
|
||||
static void gx_write_byte(int reg, int value)
|
||||
{
|
||||
|
@ -185,13 +187,6 @@ static __init struct pci_dev *gx_detect_chipset(void)
|
|||
{
|
||||
struct pci_dev *gx_pci = NULL;
|
||||
|
||||
/* check if CPU is a MediaGX or a Geode. */
|
||||
if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
|
||||
(boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) {
|
||||
pr_debug("error: no MediaGX/Geode processor found!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* detect which companion chip is used */
|
||||
for_each_pci_dev(gx_pci) {
|
||||
if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL)
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/acpi.h>
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <acpi/processor.h>
|
||||
|
||||
#include "longhaul.h"
|
||||
|
@ -951,12 +952,17 @@ static struct cpufreq_driver longhaul_driver = {
|
|||
.attr = longhaul_attr,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id longhaul_id[] = {
|
||||
{ X86_VENDOR_CENTAUR, 6 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, longhaul_id);
|
||||
|
||||
static int __init longhaul_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
||||
if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
|
||||
if (!x86_match_cpu(longhaul_id))
|
||||
return -ENODEV;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
static struct cpufreq_driver longrun_driver;
|
||||
|
||||
|
@ -288,6 +289,12 @@ static struct cpufreq_driver longrun_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id longrun_ids[] = {
|
||||
{ X86_VENDOR_TRANSMETA, X86_FAMILY_ANY, X86_MODEL_ANY,
|
||||
X86_FEATURE_LONGRUN },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, longrun_ids);
|
||||
|
||||
/**
|
||||
* longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
|
||||
|
@ -296,12 +303,8 @@ static struct cpufreq_driver longrun_driver = {
|
|||
*/
|
||||
static int __init longrun_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
||||
if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
|
||||
!cpu_has(c, X86_FEATURE_LONGRUN))
|
||||
if (!x86_match_cpu(longrun_ids))
|
||||
return -ENODEV;
|
||||
|
||||
return cpufreq_register_driver(&longrun_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#include "speedstep-lib.h"
|
||||
|
||||
|
@ -289,21 +290,25 @@ static struct cpufreq_driver p4clockmod_driver = {
|
|||
.attr = p4clockmod_attr,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id cpufreq_p4_id[] = {
|
||||
{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ACC },
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Intentionally no MODULE_DEVICE_TABLE here: this driver should not
|
||||
* be auto loaded. Please don't add one.
|
||||
*/
|
||||
|
||||
static int __init cpufreq_p4_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* 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_cpu_cap(c, X86_FEATURE_ACPI) ||
|
||||
!test_cpu_cap(c, X86_FEATURE_ACC))
|
||||
if (!x86_match_cpu(cpufreq_p4_id) || !boot_cpu_has(X86_FEATURE_ACPI))
|
||||
return -ENODEV;
|
||||
|
||||
ret = cpufreq_register_driver(&p4clockmod_driver);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/timex.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
#define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long
|
||||
|
@ -210,6 +211,12 @@ static struct cpufreq_driver powernow_k6_driver = {
|
|||
.attr = powernow_k6_attr,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id powernow_k6_ids[] = {
|
||||
{ X86_VENDOR_AMD, 5, 12 },
|
||||
{ X86_VENDOR_AMD, 5, 13 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver
|
||||
|
@ -220,10 +227,7 @@ static struct cpufreq_driver powernow_k6_driver = {
|
|||
*/
|
||||
static int __init powernow_k6_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
||||
if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
|
||||
((c->x86_model != 12) && (c->x86_model != 13)))
|
||||
if (!x86_match_cpu(powernow_k6_ids))
|
||||
return -ENODEV;
|
||||
|
||||
if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */
|
||||
#include <asm/msr.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#ifdef CONFIG_X86_POWERNOW_K7_ACPI
|
||||
#include <linux/acpi.h>
|
||||
|
@ -110,18 +111,19 @@ static int check_fsb(unsigned int fsbspeed)
|
|||
return delta < 5;
|
||||
}
|
||||
|
||||
static const struct x86_cpu_id powernow_k7_cpuids[] = {
|
||||
{ X86_VENDOR_AMD, 7, },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids);
|
||||
|
||||
static int check_powernow(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
unsigned int maxei, eax, ebx, ecx, edx;
|
||||
|
||||
if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) {
|
||||
#ifdef MODULE
|
||||
printk(KERN_INFO PFX "This module only works with "
|
||||
"AMD K7 CPUs\n");
|
||||
#endif
|
||||
if (!x86_match_cpu(powernow_k7_cpuids))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get maximum capabilities */
|
||||
maxei = cpuid_eax(0x80000000);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -520,6 +521,15 @@ static int core_voltage_post_transition(struct powernow_k8_data *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct x86_cpu_id powernow_k8_ids[] = {
|
||||
/* IO based frequency switching */
|
||||
{ X86_VENDOR_AMD, 0xf },
|
||||
/* MSR based frequency switching supported */
|
||||
X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE),
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids);
|
||||
|
||||
static void check_supported_cpu(void *_rc)
|
||||
{
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
@ -527,13 +537,7 @@ static void check_supported_cpu(void *_rc)
|
|||
|
||||
*rc = -ENODEV;
|
||||
|
||||
if (__this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_AMD)
|
||||
return;
|
||||
|
||||
eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
|
||||
if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) &&
|
||||
((eax & CPUID_XFAM) < CPUID_XFAM_10H))
|
||||
return;
|
||||
|
||||
if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
|
||||
if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
|
||||
|
@ -1553,6 +1557,9 @@ static int __cpuinit powernowk8_init(void)
|
|||
unsigned int i, supported_cpus = 0, cpu;
|
||||
int rv;
|
||||
|
||||
if (!x86_match_cpu(powernow_k8_ids))
|
||||
return -ENODEV;
|
||||
|
||||
for_each_online_cpu(i) {
|
||||
int rc;
|
||||
smp_call_function_single(i, check_supported_cpu, &rc, 1);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/timex.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
#define MMCR_BASE 0xfffef000 /* The default base address */
|
||||
|
@ -150,18 +151,19 @@ static struct cpufreq_driver sc520_freq_driver = {
|
|||
.attr = sc520_freq_attr,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id sc520_ids[] = {
|
||||
{ X86_VENDOR_AMD, 4, 9 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, sc520_ids);
|
||||
|
||||
static int __init sc520_freq_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
int err;
|
||||
|
||||
/* Test if we have the right hardware */
|
||||
if (c->x86_vendor != X86_VENDOR_AMD ||
|
||||
c->x86 != 4 || c->x86_model != 9) {
|
||||
pr_debug("no Elan SC520 processor found!\n");
|
||||
if (!x86_match_cpu(sc520_ids))
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
|
||||
if (!cpuctl) {
|
||||
printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <asm/msr.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#define PFX "speedstep-centrino: "
|
||||
#define MAINTAINER "cpufreq@vger.kernel.org"
|
||||
|
@ -595,6 +596,24 @@ static struct cpufreq_driver centrino_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/*
|
||||
* This doesn't replace the detailed checks above because
|
||||
* the generic CPU IDs don't have a way to match for steppings
|
||||
* or ASCII model IDs.
|
||||
*/
|
||||
static const struct x86_cpu_id centrino_ids[] = {
|
||||
{ X86_VENDOR_INTEL, 6, 9, X86_FEATURE_EST },
|
||||
{ X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
|
||||
{ X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
|
||||
{ X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
|
||||
{ X86_VENDOR_INTEL, 15, 3, X86_FEATURE_EST },
|
||||
{ X86_VENDOR_INTEL, 15, 4, X86_FEATURE_EST },
|
||||
{}
|
||||
};
|
||||
#if 0
|
||||
/* Autoload or not? Do not for now. */
|
||||
MODULE_DEVICE_TABLE(x86cpu, centrino_ids);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* centrino_init - initializes the Enhanced SpeedStep CPUFreq driver
|
||||
|
@ -612,11 +631,8 @@ static struct cpufreq_driver centrino_driver = {
|
|||
*/
|
||||
static int __init centrino_init(void)
|
||||
{
|
||||
struct cpuinfo_x86 *cpu = &cpu_data(0);
|
||||
|
||||
if (!cpu_has(cpu, X86_FEATURE_EST))
|
||||
if (!x86_match_cpu(centrino_ids))
|
||||
return -ENODEV;
|
||||
|
||||
return cpufreq_register_driver(¢rino_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#include "speedstep-lib.h"
|
||||
|
||||
|
||||
|
@ -388,6 +390,16 @@ static struct cpufreq_driver speedstep_driver = {
|
|||
.attr = speedstep_attr,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id ss_smi_ids[] = {
|
||||
{ X86_VENDOR_INTEL, 6, 0xb, },
|
||||
{ X86_VENDOR_INTEL, 6, 0x8, },
|
||||
{ X86_VENDOR_INTEL, 15, 2 },
|
||||
{}
|
||||
};
|
||||
#if 0
|
||||
/* Autoload or not? Do not for now. */
|
||||
MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* speedstep_init - initializes the SpeedStep CPUFreq driver
|
||||
|
@ -398,6 +410,9 @@ static struct cpufreq_driver speedstep_driver = {
|
|||
*/
|
||||
static int __init speedstep_init(void)
|
||||
{
|
||||
if (!x86_match_cpu(ss_smi_ids))
|
||||
return -ENODEV;
|
||||
|
||||
/* detect processor */
|
||||
speedstep_processor = speedstep_detect_processor();
|
||||
if (!speedstep_processor) {
|
||||
|
|
|
@ -249,6 +249,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_frequency);
|
|||
* DETECT SPEEDSTEP-CAPABLE PROCESSOR *
|
||||
*********************************************************************/
|
||||
|
||||
/* Keep in sync with the x86_cpu_id tables in the different modules */
|
||||
unsigned int speedstep_detect_processor(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/ist.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#include "speedstep-lib.h"
|
||||
|
||||
|
@ -379,6 +380,17 @@ static struct cpufreq_driver speedstep_driver = {
|
|||
.attr = speedstep_attr,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id ss_smi_ids[] = {
|
||||
{ X86_VENDOR_INTEL, 6, 0xb, },
|
||||
{ X86_VENDOR_INTEL, 6, 0x8, },
|
||||
{ X86_VENDOR_INTEL, 15, 2 },
|
||||
{}
|
||||
};
|
||||
#if 0
|
||||
/* Not auto loaded currently */
|
||||
MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* speedstep_init - initializes the SpeedStep CPUFreq driver
|
||||
*
|
||||
|
@ -388,6 +400,9 @@ static struct cpufreq_driver speedstep_driver = {
|
|||
*/
|
||||
static int __init speedstep_init(void)
|
||||
{
|
||||
if (!x86_match_cpu(ss_smi_ids))
|
||||
return -ENODEV;
|
||||
|
||||
speedstep_processor = speedstep_detect_processor();
|
||||
|
||||
switch (speedstep_processor) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче