aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/hwmon/w83627ehf.c50
2 files changed, 49 insertions, 2 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index fe7962bada1..dbdca6f10e4 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -618,6 +618,7 @@ config SENSORS_W83627HF
config SENSORS_W83627EHF
tristate "Winbond W83627EHF/DHG"
+ select HWMON_VID
help
If you say yes here you get support for the hardware
monitoring functionality of the Winbond W83627EHF Super-I/O chip.
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 0c2d929cf57..a336793c1ca 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -45,6 +45,7 @@
#include <linux/platform_device.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h>
@@ -68,8 +69,11 @@ static const char * w83627ehf_device_names[] = {
#define SIO_REG_LDSEL 0x07 /* Logical device select */
#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
+#define SIO_REG_EN_VRM10 0x2C /* GPIO3, GPIO4 selection */
#define SIO_REG_ENABLE 0x30 /* Logical device enable */
#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
+#define SIO_REG_VID_CTRL 0xF0 /* VID control */
+#define SIO_REG_VID_DATA 0xF1 /* VID data */
#define SIO_W83627EHF_ID 0x8850
#define SIO_W83627EHG_ID 0x8860
@@ -285,6 +289,9 @@ struct w83627ehf_data {
u8 fan_min_output[4]; /* minimum fan speed */
u8 fan_stop_time[4];
+
+ u8 vid;
+ u8 vrm;
};
struct w83627ehf_sio_data {
@@ -1127,6 +1134,14 @@ static struct sensor_device_attribute sda_sf3_arrays[] = {
store_fan_min_output, 2),
};
+static ssize_t
+show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83627ehf_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
/*
* Driver and device management
*/
@@ -1165,6 +1180,8 @@ static void w83627ehf_device_remove_files(struct device *dev)
device_remove_file(dev, &sda_temp[i].dev_attr);
device_remove_file(dev, &dev_attr_name);
+ if (data->vid != 0x3f)
+ device_remove_file(dev, &dev_attr_cpu0_vid);
}
/* Get the monitoring functions started */
@@ -1196,7 +1213,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
struct w83627ehf_sio_data *sio_data = dev->platform_data;
struct w83627ehf_data *data;
struct resource *res;
- u8 fan4pin, fan5pin;
+ u8 fan4pin, fan5pin, en_vrm10;
int i, err = 0;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1230,9 +1247,32 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
data->fan_min[i] = w83627ehf_read_value(data,
W83627EHF_REG_FAN_MIN[i]);
+ data->vrm = vid_which_vrm();
+ superio_enter(sio_data->sioreg);
+ /* Set VID input sensibility if needed. In theory the BIOS should
+ have set it, but in practice it's not always the case. */
+ en_vrm10 = superio_inb(sio_data->sioreg, SIO_REG_EN_VRM10);
+ if ((en_vrm10 & 0x08) && data->vrm != 100) {
+ dev_warn(dev, "Setting VID input voltage to TTL\n");
+ superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
+ en_vrm10 & ~0x08);
+ } else if (!(en_vrm10 & 0x08) && data->vrm == 100) {
+ dev_warn(dev, "Setting VID input voltage to VRM10\n");
+ superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
+ en_vrm10 | 0x08);
+ }
+ /* Read VID value */
+ superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+ if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80)
+ data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f;
+ else {
+ dev_info(dev, "VID pins in output mode, CPU VID not "
+ "available\n");
+ data->vid = 0x3f;
+ }
+
/* fan4 and fan5 share some pins with the GPIO and serial flash */
- superio_enter(sio_data->sioreg);
fan5pin = superio_inb(sio_data->sioreg, 0x24) & 0x2;
fan4pin = superio_inb(sio_data->sioreg, 0x29) & 0x6;
superio_exit(sio_data->sioreg);
@@ -1308,6 +1348,12 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
if (err)
goto exit_remove;
+ if (data->vid != 0x3f) {
+ err = device_create_file(dev, &dev_attr_cpu0_vid);
+ if (err)
+ goto exit_remove;
+ }
+
data->class_dev = hwmon_device_register(dev);
if (IS_ERR(data->class_dev)) {
err = PTR_ERR(data->class_dev);