hwmon: (it87) Support for 16-bit fan reading in it8712 >= rev 0x07

The it8712 chip supports 16-bit fan tachometers in revisions >= 0x07.
Revisions >= 0x08 dropped support for 8-bit fan divisor registers. The
patch enables 16-bit fan readings on all revisions >= 0x07 just like
the it8716 and it8718 chips.

Signed-off-by: Andrew Paprocki <andrew@ishiboo.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index e12c132..2a36568 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -151,9 +151,9 @@
 /* The IT8718F has the VID value in a different register, in Super-I/O
    configuration space. */
 #define IT87_REG_VID           0x0a
-/* Warning: register 0x0b is used for something completely different in
-   new chips/revisions. I suspect only 16-bit tachometer mode will work
-   for these. */
+/* The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b
+   for fan divisors. Later IT8712F revisions must use 16-bit tachometer
+   mode. */
 #define IT87_REG_FAN_DIV       0x0b
 #define IT87_REG_FAN_16BIT     0x0c
 
@@ -234,6 +234,7 @@
 struct it87_sio_data {
 	enum chips type;
 	/* Values read from Super-I/O config space */
+	u8 revision;
 	u8 vid_value;
 };
 
@@ -242,6 +243,7 @@
 struct it87_data {
 	struct device *hwmon_dev;
 	enum chips type;
+	u8 revision;
 
 	unsigned short addr;
 	const char *name;
@@ -268,6 +270,14 @@
 	u8 manual_pwm_ctl[3];   /* manual PWM value set by user */
 };
 
+static inline int has_16bit_fans(const struct it87_data *data)
+{
+	/* IT8712F Datasheet 0.9.1, section 8.3.5 indicates 7h == Version I.
+	   This is the first revision with 16bit tachometer support. */
+	return (data->type == it8712 && data->revision >= 0x07)
+	    || data->type == it8716
+	    || data->type == it8718;
+}
 
 static int it87_probe(struct platform_device *pdev);
 static int __devexit it87_remove(struct platform_device *pdev);
@@ -991,8 +1001,9 @@
 	}
 
 	err = 0;
+	sio_data->revision = superio_inb(DEVREV) & 0x0f;
 	pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
-		chip_type, *address, superio_inb(DEVREV) & 0x0f);
+		chip_type, *address, sio_data->revision);
 
 	/* Read GPIO config and VID value from LDN 7 (GPIO) */
 	if (chip_type != IT8705F_DEVID) {
@@ -1045,6 +1056,7 @@
 
 	data->addr = res->start;
 	data->type = sio_data->type;
+	data->revision = sio_data->revision;
 	data->name = names[sio_data->type];
 
 	/* Now, we do the remaining detection. */
@@ -1069,7 +1081,7 @@
 		goto ERROR2;
 
 	/* Do not create fan files for disabled fans */
-	if (data->type == it8716 || data->type == it8718) {
+	if (has_16bit_fans(data)) {
 		/* 16-bit tachometers */
 		if (data->has_fan & (1 << 0)) {
 			if ((err = device_create_file(dev,
@@ -1350,7 +1362,7 @@
 	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
 
 	/* Set tachometers to 16-bit mode if needed */
-	if (data->type == it8716 || data->type == it8718) {
+	if (has_16bit_fans(data)) {
 		tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
 		if (~tmp & 0x07 & data->has_fan) {
 			dev_dbg(&pdev->dev,
@@ -1426,7 +1438,7 @@
 			data->fan[i] = it87_read_value(data,
 				       IT87_REG_FAN[i]);
 			/* Add high byte if in 16-bit mode */
-			if (data->type == it8716 || data->type == it8718) {
+			if (has_16bit_fans(data)) {
 				data->fan[i] |= it87_read_value(data,
 						IT87_REG_FANX[i]) << 8;
 				data->fan_min[i] |= it87_read_value(data,
@@ -1443,8 +1455,7 @@
 		}
 
 		/* Newer chips don't have clock dividers */
-		if ((data->has_fan & 0x07) && data->type != it8716
-		 && data->type != it8718) {
+		if ((data->has_fan & 0x07) && !has_16bit_fans(data)) {
 			i = it87_read_value(data, IT87_REG_FAN_DIV);
 			data->fan_div[0] = i & 0x07;
 			data->fan_div[1] = (i >> 3) & 0x07;
@@ -1460,7 +1471,8 @@
 		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
 
 		data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
-		/* The 8705 does not have VID capability */
+		/* The 8705 does not have VID capability.
+		   The 8718 does not use IT87_REG_VID for the same purpose. */
 		if (data->type == it8712 || data->type == it8716) {
 			data->vid = it87_read_value(data, IT87_REG_VID);
 			/* The older IT8712F revisions had only 5 VID pins,