diff options
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/Kconfig | 1 | ||||
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 50 |
2 files changed, 49 insertions, 2 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index fe7962bada13..dbdca6f10e46 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 0c2d929cf573..a336793c1caf 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); |