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>
This commit is contained in:
Jean Delvare 2007-06-24 11:19:42 +02:00 committed by Mark M. Hoffman
parent 6b3e464580
commit fc18d6c047
3 changed files with 52 additions and 5 deletions

View File

@ -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 speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
with beep warnings (control unimplemented), and some automatic fan regulation VID (6 pins), alarms with beep warnings (control unimplemented), and
strategies (plus manual fan control mode). 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

View File

@ -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.

View File

@ -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);