浏览代码

hwmon/w83627ehf: Add support for the VID inputs

The W83627EHF and similar chips have 6 VID input pins, add support
for them. The driver changes the input voltage level automatically
if the current setting is not correct for the detected CPU model.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
Jean Delvare 18 年之前
父节点
当前提交
fc18d6c047
共有 3 个文件被更改,包括 52 次插入5 次删除
  1. 3 3
      Documentation/hwmon/w83627ehf
  2. 1 0
      drivers/hwmon/Kconfig
  3. 48 2
      drivers/hwmon/w83627ehf.c

+ 3 - 3
Documentation/hwmon/w83627ehf

@@ -22,9 +22,9 @@ This driver implements support for the Winbond W83627EHF, W83627EHG, and
 W83627DHG super I/O chips. We will refer to them collectively as Winbond chips.
 W83627DHG super I/O chips. We will refer to them collectively as Winbond chips.
 
 
 The chips implement three temperature sensors, five fan rotation
 The chips implement three temperature sensors, five fan rotation
-speed sensors, ten analog voltage sensors (only nine for the 627DHG), alarms
-with beep warnings (control unimplemented), and some automatic fan regulation
-strategies (plus manual fan control mode).
+speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
+VID (6 pins), alarms with beep warnings (control unimplemented), and
+some automatic fan regulation strategies (plus manual fan control mode).
 
 
 Temperatures are measured in degrees Celsius and measurement resolution is 1
 Temperatures are measured in degrees Celsius and measurement resolution is 1
 degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
 degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when

+ 1 - 0
drivers/hwmon/Kconfig

@@ -618,6 +618,7 @@ config SENSORS_W83627HF
 
 
 config SENSORS_W83627EHF
 config SENSORS_W83627EHF
 	tristate "Winbond W83627EHF/DHG"
 	tristate "Winbond W83627EHF/DHG"
+	select HWMON_VID
 	help
 	help
 	  If you say yes here you get support for the hardware
 	  If you say yes here you get support for the hardware
 	  monitoring functionality of the Winbond W83627EHF Super-I/O chip.
 	  monitoring functionality of the Winbond W83627EHF Super-I/O chip.

+ 48 - 2
drivers/hwmon/w83627ehf.c

@@ -45,6 +45,7 @@
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <asm/io.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_LDSEL		0x07	/* Logical device select */
 #define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
 #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_ENABLE		0x30	/* Logical device enable */
 #define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
 #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_W83627EHF_ID	0x8850
 #define SIO_W83627EHG_ID	0x8860
 #define SIO_W83627EHG_ID	0x8860
@@ -285,6 +289,9 @@ struct w83627ehf_data {
 
 
 	u8 fan_min_output[4]; /* minimum fan speed */
 	u8 fan_min_output[4]; /* minimum fan speed */
 	u8 fan_stop_time[4];
 	u8 fan_stop_time[4];
+
+	u8 vid;
+	u8 vrm;
 };
 };
 
 
 struct w83627ehf_sio_data {
 struct w83627ehf_sio_data {
@@ -1127,6 +1134,14 @@ static struct sensor_device_attribute sda_sf3_arrays[] = {
 		    store_fan_min_output, 2),
 		    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
  * 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, &sda_temp[i].dev_attr);
 
 
 	device_remove_file(dev, &dev_attr_name);
 	device_remove_file(dev, &dev_attr_name);
+	if (data->vid != 0x3f)
+		device_remove_file(dev, &dev_attr_cpu0_vid);
 }
 }
 
 
 /* Get the monitoring functions started */
 /* 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_sio_data *sio_data = dev->platform_data;
 	struct w83627ehf_data *data;
 	struct w83627ehf_data *data;
 	struct resource *res;
 	struct resource *res;
-	u8 fan4pin, fan5pin;
+	u8 fan4pin, fan5pin, en_vrm10;
 	int i, err = 0;
 	int i, err = 0;
 
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 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,
 		data->fan_min[i] = w83627ehf_read_value(data,
 				   W83627EHF_REG_FAN_MIN[i]);
 				   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 */
 	/* 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;
 	fan5pin = superio_inb(sio_data->sioreg, 0x24) & 0x2;
 	fan4pin = superio_inb(sio_data->sioreg, 0x29) & 0x6;
 	fan4pin = superio_inb(sio_data->sioreg, 0x29) & 0x6;
 	superio_exit(sio_data->sioreg);
 	superio_exit(sio_data->sioreg);
@@ -1308,6 +1348,12 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 	if (err)
 	if (err)
 		goto exit_remove;
 		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);
 	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		err = PTR_ERR(data->class_dev);