Commit 764e043b authored by Jean Delvare's avatar Jean Delvare Committed by Jean Delvare

hwmon: (via-cputemp) Add VID reporting support

At least VIA family 6 model D CPU report the VID settings in a MSR,
so expose the value to user-space. Not sure about model A.
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
Acked-by: default avatarGuenter Roeck <guenter.roeck@ericsson.com>
Tested-by: default avatarJeff Rickman <jrickman@myamigos.us>
parent 0a88f4b5
...@@ -1162,6 +1162,7 @@ config SENSORS_TWL4030_MADC ...@@ -1162,6 +1162,7 @@ config SENSORS_TWL4030_MADC
config SENSORS_VIA_CPUTEMP config SENSORS_VIA_CPUTEMP
tristate "VIA CPU temperature sensor" tristate "VIA CPU temperature sensor"
depends on X86 depends on X86
select HWMON_VID
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. Supported are all known variants of sensor inside your CPU. Supported are all known variants of
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -48,8 +49,10 @@ enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME }; ...@@ -48,8 +49,10 @@ enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME };
struct via_cputemp_data { struct via_cputemp_data {
struct device *hwmon_dev; struct device *hwmon_dev;
const char *name; const char *name;
u8 vrm;
u32 id; u32 id;
u32 msr; u32 msr_temp;
u32 msr_vid;
}; };
/* /*
...@@ -77,13 +80,27 @@ static ssize_t show_temp(struct device *dev, ...@@ -77,13 +80,27 @@ static ssize_t show_temp(struct device *dev,
u32 eax, edx; u32 eax, edx;
int err; int err;
err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx); err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx);
if (err) if (err)
return -EAGAIN; return -EAGAIN;
return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000); return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000);
} }
static ssize_t show_cpu_vid(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct via_cputemp_data *data = dev_get_drvdata(dev);
u32 eax, edx;
int err;
err = rdmsr_safe_on_cpu(data->id, data->msr_vid, &eax, &edx);
if (err)
return -EAGAIN;
return sprintf(buf, "%d\n", vid_from_reg(~edx & 0x7f, data->vrm));
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
SHOW_TEMP); SHOW_TEMP);
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
...@@ -100,6 +117,9 @@ static const struct attribute_group via_cputemp_group = { ...@@ -100,6 +117,9 @@ static const struct attribute_group via_cputemp_group = {
.attrs = via_cputemp_attributes, .attrs = via_cputemp_attributes,
}; };
/* Optional attributes */
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_cpu_vid, NULL);
static int __devinit via_cputemp_probe(struct platform_device *pdev) static int __devinit via_cputemp_probe(struct platform_device *pdev)
{ {
struct via_cputemp_data *data; struct via_cputemp_data *data;
...@@ -122,11 +142,12 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) ...@@ -122,11 +142,12 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
/* C7 A */ /* C7 A */
case 0xD: case 0xD:
/* C7 D */ /* C7 D */
data->msr = 0x1169; data->msr_temp = 0x1169;
data->msr_vid = 0x198;
break; break;
case 0xF: case 0xF:
/* Nano */ /* Nano */
data->msr = 0x1423; data->msr_temp = 0x1423;
break; break;
default: default:
err = -ENODEV; err = -ENODEV;
...@@ -134,7 +155,7 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) ...@@ -134,7 +155,7 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
} }
/* test if we can access the TEMPERATURE MSR */ /* test if we can access the TEMPERATURE MSR */
err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx); err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx);
if (err) { if (err) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Unable to access TEMPERATURE MSR, giving up\n"); "Unable to access TEMPERATURE MSR, giving up\n");
...@@ -147,6 +168,15 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) ...@@ -147,6 +168,15 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
if (err) if (err)
goto exit_free; goto exit_free;
if (data->msr_vid)
data->vrm = vid_which_vrm();
if (data->vrm) {
err = device_create_file(&pdev->dev, &dev_attr_cpu0_vid);
if (err)
goto exit_remove;
}
data->hwmon_dev = hwmon_device_register(&pdev->dev); data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev); err = PTR_ERR(data->hwmon_dev);
...@@ -158,6 +188,8 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) ...@@ -158,6 +188,8 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
return 0; return 0;
exit_remove: exit_remove:
if (data->vrm)
device_remove_file(&pdev->dev, &dev_attr_cpu0_vid);
sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
exit_free: exit_free:
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
...@@ -171,6 +203,8 @@ static int __devexit via_cputemp_remove(struct platform_device *pdev) ...@@ -171,6 +203,8 @@ static int __devexit via_cputemp_remove(struct platform_device *pdev)
struct via_cputemp_data *data = platform_get_drvdata(pdev); struct via_cputemp_data *data = platform_get_drvdata(pdev);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
if (data->vrm)
device_remove_file(&pdev->dev, &dev_attr_cpu0_vid);
sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
kfree(data); kfree(data);
......
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