Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: hwmon: Make PCI device ids constant hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs hwmon: (k10temp) Blacklist more family 10h processors hwmon: (asus_atk0110) Add debugfs interface hwmon: (asus_atk0110) Refactor interface probe code hwmon: (adt7462) Fix pin 28 monitoring
This commit is contained in:
commit
6102c315d8
10 changed files with 299 additions and 75 deletions
|
@ -3,8 +3,8 @@ Kernel driver k10temp
|
||||||
|
|
||||||
Supported chips:
|
Supported chips:
|
||||||
* AMD Family 10h processors:
|
* AMD Family 10h processors:
|
||||||
Socket F: Quad-Core/Six-Core/Embedded Opteron
|
Socket F: Quad-Core/Six-Core/Embedded Opteron (but see below)
|
||||||
Socket AM2+: Opteron, Phenom (II) X3/X4
|
Socket AM2+: Quad-Core Opteron, Phenom (II) X3/X4, Athlon X2 (but see below)
|
||||||
Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II
|
Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II
|
||||||
Socket S1G3: Athlon II, Sempron, Turion II
|
Socket S1G3: Athlon II, Sempron, Turion II
|
||||||
* AMD Family 11h processors:
|
* AMD Family 11h processors:
|
||||||
|
@ -36,10 +36,15 @@ Description
|
||||||
This driver permits reading of the internal temperature sensor of AMD
|
This driver permits reading of the internal temperature sensor of AMD
|
||||||
Family 10h and 11h processors.
|
Family 10h and 11h processors.
|
||||||
|
|
||||||
All these processors have a sensor, but on older revisions of Family 10h
|
All these processors have a sensor, but on those for Socket F or AM2+,
|
||||||
processors, the sensor may return inconsistent values (erratum 319). The
|
the sensor may return inconsistent values (erratum 319). The driver
|
||||||
driver will refuse to load on these revisions unless you specify the
|
will refuse to load on these revisions unless you specify the "force=1"
|
||||||
"force=1" module parameter.
|
module parameter.
|
||||||
|
|
||||||
|
Due to technical reasons, the driver can detect only the mainboard's
|
||||||
|
socket type, not the processor's actual capabilities. Therefore, if you
|
||||||
|
are using an AM3 processor on an AM2+ mainboard, you can safely use the
|
||||||
|
"force=1" parameter.
|
||||||
|
|
||||||
There is one temperature measurement value, available as temp1_input in
|
There is one temperature measurement value, available as temp1_input in
|
||||||
sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
|
sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
|
||||||
|
|
|
@ -392,7 +392,7 @@ config SENSORS_GL520SM
|
||||||
|
|
||||||
config SENSORS_CORETEMP
|
config SENSORS_CORETEMP
|
||||||
tristate "Intel Core/Core2/Atom temperature sensor"
|
tristate "Intel Core/Core2/Atom temperature sensor"
|
||||||
depends on X86 && EXPERIMENTAL
|
depends on X86 && PCI && EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes here you get support for the temperature
|
If you say yes here you get support for the temperature
|
||||||
sensor inside your CPU. Most of the family 6 CPUs
|
sensor inside your CPU. Most of the family 6 CPUs
|
||||||
|
|
|
@ -94,7 +94,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
|
||||||
#define ADT7462_PIN24_SHIFT 6
|
#define ADT7462_PIN24_SHIFT 6
|
||||||
#define ADT7462_PIN26_VOLT_INPUT 0x08
|
#define ADT7462_PIN26_VOLT_INPUT 0x08
|
||||||
#define ADT7462_PIN25_VOLT_INPUT 0x20
|
#define ADT7462_PIN25_VOLT_INPUT 0x20
|
||||||
#define ADT7462_PIN28_SHIFT 6 /* cfg3 */
|
#define ADT7462_PIN28_SHIFT 4 /* cfg3 */
|
||||||
#define ADT7462_PIN28_VOLT 0x5
|
#define ADT7462_PIN28_VOLT 0x5
|
||||||
|
|
||||||
#define ADT7462_REG_ALARM1 0xB8
|
#define ADT7462_REG_ALARM1 0xB8
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* See COPYING in the top level directory of the kernel tree.
|
* See COPYING in the top level directory of the kernel tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/debugfs.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
@ -101,6 +102,11 @@ struct atk_data {
|
||||||
int temperature_count;
|
int temperature_count;
|
||||||
int fan_count;
|
int fan_count;
|
||||||
struct list_head sensor_list;
|
struct list_head sensor_list;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct dentry *root;
|
||||||
|
u32 id;
|
||||||
|
} debugfs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -624,6 +630,187 @@ static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
static int atk_debugfs_gitm_get(void *p, u64 *val)
|
||||||
|
{
|
||||||
|
struct atk_data *data = p;
|
||||||
|
union acpi_object *ret;
|
||||||
|
struct atk_acpi_ret_buffer *buf;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (!data->read_handle)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (!data->debugfs.id)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = atk_gitm(data, data->debugfs.id);
|
||||||
|
if (IS_ERR(ret))
|
||||||
|
return PTR_ERR(ret);
|
||||||
|
|
||||||
|
buf = (struct atk_acpi_ret_buffer *)ret->buffer.pointer;
|
||||||
|
if (buf->flags)
|
||||||
|
*val = buf->value;
|
||||||
|
else
|
||||||
|
err = -EIO;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_SIMPLE_ATTRIBUTE(atk_debugfs_gitm,
|
||||||
|
atk_debugfs_gitm_get,
|
||||||
|
NULL,
|
||||||
|
"0x%08llx\n")
|
||||||
|
|
||||||
|
static int atk_acpi_print(char *buf, size_t sz, union acpi_object *obj)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch (obj->type) {
|
||||||
|
case ACPI_TYPE_INTEGER:
|
||||||
|
ret = snprintf(buf, sz, "0x%08llx\n", obj->integer.value);
|
||||||
|
break;
|
||||||
|
case ACPI_TYPE_STRING:
|
||||||
|
ret = snprintf(buf, sz, "%s\n", obj->string.pointer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void atk_pack_print(char *buf, size_t sz, union acpi_object *pack)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < pack->package.count; i++) {
|
||||||
|
union acpi_object *obj = &pack->package.elements[i];
|
||||||
|
|
||||||
|
ret = atk_acpi_print(buf, sz, obj);
|
||||||
|
if (ret >= sz)
|
||||||
|
break;
|
||||||
|
buf += ret;
|
||||||
|
sz -= ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atk_debugfs_ggrp_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct atk_data *data = inode->i_private;
|
||||||
|
char *buf = NULL;
|
||||||
|
union acpi_object *ret;
|
||||||
|
u8 cls;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!data->enumerate_handle)
|
||||||
|
return -ENODEV;
|
||||||
|
if (!data->debugfs.id)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
cls = (data->debugfs.id & 0xff000000) >> 24;
|
||||||
|
ret = atk_ggrp(data, cls);
|
||||||
|
if (IS_ERR(ret))
|
||||||
|
return PTR_ERR(ret);
|
||||||
|
|
||||||
|
for (i = 0; i < ret->package.count; i++) {
|
||||||
|
union acpi_object *pack = &ret->package.elements[i];
|
||||||
|
union acpi_object *id;
|
||||||
|
|
||||||
|
if (pack->type != ACPI_TYPE_PACKAGE)
|
||||||
|
continue;
|
||||||
|
if (!pack->package.count)
|
||||||
|
continue;
|
||||||
|
id = &pack->package.elements[0];
|
||||||
|
if (id->integer.value == data->debugfs.id) {
|
||||||
|
/* Print the package */
|
||||||
|
buf = kzalloc(512, GFP_KERNEL);
|
||||||
|
if (!buf) {
|
||||||
|
ACPI_FREE(ret);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
atk_pack_print(buf, 512, pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ACPI_FREE(ret);
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
file->private_data = buf;
|
||||||
|
|
||||||
|
return nonseekable_open(inode, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t atk_debugfs_ggrp_read(struct file *file, char __user *buf,
|
||||||
|
size_t count, loff_t *pos)
|
||||||
|
{
|
||||||
|
char *str = file->private_data;
|
||||||
|
size_t len = strlen(str);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(buf, count, pos, str, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atk_debugfs_ggrp_release(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
kfree(file->private_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations atk_debugfs_ggrp_fops = {
|
||||||
|
.read = atk_debugfs_ggrp_read,
|
||||||
|
.open = atk_debugfs_ggrp_open,
|
||||||
|
.release = atk_debugfs_ggrp_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void atk_debugfs_init(struct atk_data *data)
|
||||||
|
{
|
||||||
|
struct dentry *d;
|
||||||
|
struct dentry *f;
|
||||||
|
|
||||||
|
data->debugfs.id = 0;
|
||||||
|
|
||||||
|
d = debugfs_create_dir("asus_atk0110", NULL);
|
||||||
|
if (!d || IS_ERR(d))
|
||||||
|
return;
|
||||||
|
|
||||||
|
f = debugfs_create_x32("id", S_IRUSR | S_IWUSR, d, &data->debugfs.id);
|
||||||
|
if (!f || IS_ERR(f))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
f = debugfs_create_file("gitm", S_IRUSR, d, data,
|
||||||
|
&atk_debugfs_gitm);
|
||||||
|
if (!f || IS_ERR(f))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
f = debugfs_create_file("ggrp", S_IRUSR, d, data,
|
||||||
|
&atk_debugfs_ggrp_fops);
|
||||||
|
if (!f || IS_ERR(f))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
data->debugfs.root = d;
|
||||||
|
|
||||||
|
return;
|
||||||
|
cleanup:
|
||||||
|
debugfs_remove_recursive(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void atk_debugfs_cleanup(struct atk_data *data)
|
||||||
|
{
|
||||||
|
debugfs_remove_recursive(data->debugfs.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* CONFIG_DEBUG_FS */
|
||||||
|
|
||||||
|
static void atk_debugfs_init(struct atk_data *data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void atk_debugfs_cleanup(struct atk_data *data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
|
static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
|
||||||
{
|
{
|
||||||
struct device *dev = &data->acpi_dev->dev;
|
struct device *dev = &data->acpi_dev->dev;
|
||||||
|
@ -1047,76 +1234,75 @@ static int atk_register_hwmon(struct atk_data *data)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int atk_check_old_if(struct atk_data *data)
|
static int atk_probe_if(struct atk_data *data)
|
||||||
{
|
{
|
||||||
struct device *dev = &data->acpi_dev->dev;
|
struct device *dev = &data->acpi_dev->dev;
|
||||||
acpi_handle ret;
|
acpi_handle ret;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
/* RTMP: read temperature */
|
/* RTMP: read temperature */
|
||||||
status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret);
|
status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret);
|
||||||
if (status != AE_OK) {
|
if (ACPI_SUCCESS(status))
|
||||||
|
data->rtmp_handle = ret;
|
||||||
|
else
|
||||||
dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n",
|
dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n",
|
||||||
acpi_format_exception(status));
|
acpi_format_exception(status));
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
data->rtmp_handle = ret;
|
|
||||||
|
|
||||||
/* RVLT: read voltage */
|
/* RVLT: read voltage */
|
||||||
status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret);
|
status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret);
|
||||||
if (status != AE_OK) {
|
if (ACPI_SUCCESS(status))
|
||||||
|
data->rvlt_handle = ret;
|
||||||
|
else
|
||||||
dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n",
|
dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n",
|
||||||
acpi_format_exception(status));
|
acpi_format_exception(status));
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
data->rvlt_handle = ret;
|
|
||||||
|
|
||||||
/* RFAN: read fan status */
|
/* RFAN: read fan status */
|
||||||
status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret);
|
status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret);
|
||||||
if (status != AE_OK) {
|
if (ACPI_SUCCESS(status))
|
||||||
|
data->rfan_handle = ret;
|
||||||
|
else
|
||||||
dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n",
|
dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n",
|
||||||
acpi_format_exception(status));
|
acpi_format_exception(status));
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
data->rfan_handle = ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int atk_check_new_if(struct atk_data *data)
|
|
||||||
{
|
|
||||||
struct device *dev = &data->acpi_dev->dev;
|
|
||||||
acpi_handle ret;
|
|
||||||
acpi_status status;
|
|
||||||
|
|
||||||
/* Enumeration */
|
/* Enumeration */
|
||||||
status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret);
|
status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret);
|
||||||
if (status != AE_OK) {
|
if (ACPI_SUCCESS(status))
|
||||||
|
data->enumerate_handle = ret;
|
||||||
|
else
|
||||||
dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n",
|
dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n",
|
||||||
acpi_format_exception(status));
|
acpi_format_exception(status));
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
data->enumerate_handle = ret;
|
|
||||||
|
|
||||||
/* De-multiplexer (read) */
|
/* De-multiplexer (read) */
|
||||||
status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret);
|
status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret);
|
||||||
if (status != AE_OK) {
|
if (ACPI_SUCCESS(status))
|
||||||
|
data->read_handle = ret;
|
||||||
|
else
|
||||||
dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
|
dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
|
||||||
acpi_format_exception(status));
|
acpi_format_exception(status));
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
data->read_handle = ret;
|
|
||||||
|
|
||||||
/* De-multiplexer (write) */
|
/* De-multiplexer (write) */
|
||||||
status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret);
|
status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret);
|
||||||
if (status != AE_OK) {
|
if (ACPI_SUCCESS(status))
|
||||||
dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
|
data->write_handle = ret;
|
||||||
|
else
|
||||||
|
dev_dbg(dev, "method " METHOD_WRITE " not found: %s\n",
|
||||||
acpi_format_exception(status));
|
acpi_format_exception(status));
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
data->write_handle = ret;
|
|
||||||
|
|
||||||
return 0;
|
/* Check for hwmon methods: first check "old" style methods; note that
|
||||||
|
* both may be present: in this case we stick to the old interface;
|
||||||
|
* analysis of multiple DSDTs indicates that when both interfaces
|
||||||
|
* are present the new one (GGRP/GITM) is not functional.
|
||||||
|
*/
|
||||||
|
if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle)
|
||||||
|
data->old_interface = true;
|
||||||
|
else if (data->enumerate_handle && data->read_handle &&
|
||||||
|
data->write_handle)
|
||||||
|
data->old_interface = false;
|
||||||
|
else
|
||||||
|
err = -ENODEV;
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int atk_add(struct acpi_device *device)
|
static int atk_add(struct acpi_device *device)
|
||||||
|
@ -1155,28 +1341,19 @@ static int atk_add(struct acpi_device *device)
|
||||||
}
|
}
|
||||||
ACPI_FREE(buf.pointer);
|
ACPI_FREE(buf.pointer);
|
||||||
|
|
||||||
/* Check for hwmon methods: first check "old" style methods; note that
|
err = atk_probe_if(data);
|
||||||
* both may be present: in this case we stick to the old interface;
|
if (err) {
|
||||||
* analysis of multiple DSDTs indicates that when both interfaces
|
dev_err(&device->dev, "No usable hwmon interface detected\n");
|
||||||
* are present the new one (GGRP/GITM) is not functional.
|
goto out;
|
||||||
*/
|
|
||||||
err = atk_check_old_if(data);
|
|
||||||
if (!err) {
|
|
||||||
dev_dbg(&device->dev, "Using old hwmon interface\n");
|
|
||||||
data->old_interface = true;
|
|
||||||
} else {
|
|
||||||
err = atk_check_new_if(data);
|
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
dev_dbg(&device->dev, "Using new hwmon interface\n");
|
|
||||||
data->old_interface = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->old_interface)
|
if (data->old_interface) {
|
||||||
|
dev_dbg(&device->dev, "Using old hwmon interface\n");
|
||||||
err = atk_enumerate_old_hwmon(data);
|
err = atk_enumerate_old_hwmon(data);
|
||||||
else
|
} else {
|
||||||
|
dev_dbg(&device->dev, "Using new hwmon interface\n");
|
||||||
err = atk_enumerate_new_hwmon(data);
|
err = atk_enumerate_new_hwmon(data);
|
||||||
|
}
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
|
@ -1190,6 +1367,8 @@ static int atk_add(struct acpi_device *device)
|
||||||
if (err)
|
if (err)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
atk_debugfs_init(data);
|
||||||
|
|
||||||
device->driver_data = data;
|
device->driver_data = data;
|
||||||
return 0;
|
return 0;
|
||||||
cleanup:
|
cleanup:
|
||||||
|
@ -1208,6 +1387,8 @@ static int atk_remove(struct acpi_device *device, int type)
|
||||||
|
|
||||||
device->driver_data = NULL;
|
device->driver_data = NULL;
|
||||||
|
|
||||||
|
atk_debugfs_cleanup(data);
|
||||||
|
|
||||||
atk_remove_files(data);
|
atk_remove_files(data);
|
||||||
atk_free_sensors(data);
|
atk_free_sensors(data);
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
hwmon_device_unregister(data->hwmon_dev);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
|
||||||
|
@ -161,6 +162,7 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
|
||||||
int usemsr_ee = 1;
|
int usemsr_ee = 1;
|
||||||
int err;
|
int err;
|
||||||
u32 eax, edx;
|
u32 eax, edx;
|
||||||
|
struct pci_dev *host_bridge;
|
||||||
|
|
||||||
/* Early chips have no MSR for TjMax */
|
/* Early chips have no MSR for TjMax */
|
||||||
|
|
||||||
|
@ -168,11 +170,21 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
|
||||||
usemsr_ee = 0;
|
usemsr_ee = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Atoms seems to have TjMax at 90C */
|
/* Atom CPUs */
|
||||||
|
|
||||||
if (c->x86_model == 0x1c) {
|
if (c->x86_model == 0x1c) {
|
||||||
usemsr_ee = 0;
|
usemsr_ee = 0;
|
||||||
tjmax = 90000;
|
|
||||||
|
host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
|
||||||
|
|
||||||
|
if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
|
||||||
|
&& (host_bridge->device == 0xa000 /* NM10 based nettop */
|
||||||
|
|| host_bridge->device == 0xa010)) /* NM10 based netbook */
|
||||||
|
tjmax = 100000;
|
||||||
|
else
|
||||||
|
tjmax = 90000;
|
||||||
|
|
||||||
|
pci_dev_put(host_bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c->x86_model > 0xe) && (usemsr_ee)) {
|
if ((c->x86_model > 0xe) && (usemsr_ee)) {
|
||||||
|
|
|
@ -33,6 +33,16 @@ static bool force;
|
||||||
module_param(force, bool, 0444);
|
module_param(force, bool, 0444);
|
||||||
MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
|
MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
|
||||||
|
|
||||||
|
/* CPUID function 0x80000001, ebx */
|
||||||
|
#define CPUID_PKGTYPE_MASK 0xf0000000
|
||||||
|
#define CPUID_PKGTYPE_F 0x00000000
|
||||||
|
#define CPUID_PKGTYPE_AM2R2_AM3 0x10000000
|
||||||
|
|
||||||
|
/* DRAM controller (PCI function 2) */
|
||||||
|
#define REG_DCT0_CONFIG_HIGH 0x094
|
||||||
|
#define DDR3_MODE 0x00000100
|
||||||
|
|
||||||
|
/* miscellaneous (PCI function 3) */
|
||||||
#define REG_HARDWARE_THERMAL_CONTROL 0x64
|
#define REG_HARDWARE_THERMAL_CONTROL 0x64
|
||||||
#define HTC_ENABLE 0x00000001
|
#define HTC_ENABLE 0x00000001
|
||||||
|
|
||||||
|
@ -85,13 +95,28 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
|
||||||
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
|
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
|
||||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
||||||
|
|
||||||
static bool __devinit has_erratum_319(void)
|
static bool __devinit has_erratum_319(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
|
u32 pkg_type, reg_dram_cfg;
|
||||||
|
|
||||||
|
if (boot_cpu_data.x86 != 0x10)
|
||||||
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Erratum 319: The thermal sensor of older Family 10h processors
|
* Erratum 319: The thermal sensor of Socket F/AM2+ processors
|
||||||
* (B steppings) may be unreliable.
|
* may be unreliable.
|
||||||
*/
|
*/
|
||||||
return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2;
|
pkg_type = cpuid_ebx(0x80000001) & CPUID_PKGTYPE_MASK;
|
||||||
|
if (pkg_type == CPUID_PKGTYPE_F)
|
||||||
|
return true;
|
||||||
|
if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Differentiate between AM2+ (bad) and AM3 (good) */
|
||||||
|
pci_bus_read_config_dword(pdev->bus,
|
||||||
|
PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
|
||||||
|
REG_DCT0_CONFIG_HIGH, ®_dram_cfg);
|
||||||
|
return !(reg_dram_cfg & DDR3_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit k10temp_probe(struct pci_dev *pdev,
|
static int __devinit k10temp_probe(struct pci_dev *pdev,
|
||||||
|
@ -99,9 +124,10 @@ static int __devinit k10temp_probe(struct pci_dev *pdev,
|
||||||
{
|
{
|
||||||
struct device *hwmon_dev;
|
struct device *hwmon_dev;
|
||||||
u32 reg_caps, reg_htc;
|
u32 reg_caps, reg_htc;
|
||||||
|
int unreliable = has_erratum_319(pdev);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (has_erratum_319() && !force) {
|
if (unreliable && !force) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"unreliable CPU thermal sensor; monitoring disabled\n");
|
"unreliable CPU thermal sensor; monitoring disabled\n");
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
|
@ -139,7 +165,7 @@ static int __devinit k10temp_probe(struct pci_dev *pdev,
|
||||||
}
|
}
|
||||||
dev_set_drvdata(&pdev->dev, hwmon_dev);
|
dev_set_drvdata(&pdev->dev, hwmon_dev);
|
||||||
|
|
||||||
if (has_erratum_319() && force)
|
if (unreliable && force)
|
||||||
dev_warn(&pdev->dev,
|
dev_warn(&pdev->dev,
|
||||||
"unreliable CPU thermal sensor; check erratum 319\n");
|
"unreliable CPU thermal sensor; check erratum 319\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -169,7 +195,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev)
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
dev_set_drvdata(&pdev->dev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pci_device_id k10temp_id_table[] = {
|
static const struct pci_device_id k10temp_id_table[] = {
|
||||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
|
||||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -136,7 +136,7 @@ static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
|
||||||
static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
|
static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
|
||||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
||||||
|
|
||||||
static struct pci_device_id k8temp_ids[] = {
|
static const struct pci_device_id k8temp_ids[] = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
|
@ -697,7 +697,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pci_device_id sis5595_pci_ids[] = {
|
static const struct pci_device_id sis5595_pci_ids[] = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
|
||||||
{ 0, }
|
{ 0, }
|
||||||
};
|
};
|
||||||
|
|
|
@ -767,7 +767,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pci_device_id via686a_pci_ids[] = {
|
static const struct pci_device_id via686a_pci_ids[] = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
|
||||||
{ 0, }
|
{ 0, }
|
||||||
};
|
};
|
||||||
|
|
|
@ -697,7 +697,7 @@ static struct platform_driver vt8231_driver = {
|
||||||
.remove = __devexit_p(vt8231_remove),
|
.remove = __devexit_p(vt8231_remove),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pci_device_id vt8231_pci_ids[] = {
|
static const struct pci_device_id vt8231_pci_ids[] = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
|
||||||
{ 0, }
|
{ 0, }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue