Przeglądaj źródła

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>
Andrew Paprocki 16 lat temu
rodzic
commit
0475169c13
2 zmienionych plików z 27 dodań i 14 usunięć
  1. 5 4
      Documentation/hwmon/it87
  2. 22 10
      drivers/hwmon/it87.c

+ 5 - 4
Documentation/hwmon/it87

@@ -11,7 +11,9 @@ Supported chips:
     Prefix: 'it8712'
     Prefix: 'it8712'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Publicly available at the ITE website
     Datasheet: Publicly available at the ITE website
-               http://www.ite.com.tw/
+               http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.1.pdf
+               http://www.ite.com.tw/product_info/file/pc/Errata%20V0.1%20for%20IT8712F%20V0.9.1.pdf
+               http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.3.pdf
   * IT8716F/IT8726F
   * IT8716F/IT8726F
     Prefix: 'it8716'
     Prefix: 'it8716'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -90,14 +92,13 @@ upper VID bits share their pins with voltage inputs (in5 and in6) so you
 can't have both on a given board.
 can't have both on a given board.
 
 
 The IT8716F, IT8718F and later IT8712F revisions have support for
 The IT8716F, IT8718F and later IT8712F revisions have support for
-2 additional fans. They are supported by the driver for the IT8716F and
-IT8718F but not for the IT8712F
+2 additional fans. The additional fans are supported by the driver.
 
 
 The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
 The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
 16-bit tachometer counters for fans 1 to 3. This is better (no more fan
 16-bit tachometer counters for fans 1 to 3. This is better (no more fan
 clock divider mess) but not compatible with the older chips and
 clock divider mess) but not compatible with the older chips and
 revisions. For now, the driver only uses the 16-bit mode on the
 revisions. For now, the driver only uses the 16-bit mode on the
-IT8716F and IT8718F.
+late IT8712F, IT8716F and IT8718F.
 
 
 The IT8726F is just bit enhanced IT8716F with additional hardware
 The IT8726F is just bit enhanced IT8716F with additional hardware
 for AMD power sequencing. Therefore the chip will appear as IT8716F
 for AMD power sequencing. Therefore the chip will appear as IT8716F

+ 22 - 10
drivers/hwmon/it87.c

@@ -151,9 +151,9 @@ static int fix_pwm_polarity;
 /* The IT8718F has the VID value in a different register, in Super-I/O
 /* The IT8718F has the VID value in a different register, in Super-I/O
    configuration space. */
    configuration space. */
 #define IT87_REG_VID           0x0a
 #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_DIV       0x0b
 #define IT87_REG_FAN_16BIT     0x0c
 #define IT87_REG_FAN_16BIT     0x0c
 
 
@@ -234,6 +234,7 @@ static const unsigned int pwm_freq[8] = {
 struct it87_sio_data {
 struct it87_sio_data {
 	enum chips type;
 	enum chips type;
 	/* Values read from Super-I/O config space */
 	/* Values read from Super-I/O config space */
+	u8 revision;
 	u8 vid_value;
 	u8 vid_value;
 };
 };
 
 
@@ -242,6 +243,7 @@ struct it87_sio_data {
 struct it87_data {
 struct it87_data {
 	struct device *hwmon_dev;
 	struct device *hwmon_dev;
 	enum chips type;
 	enum chips type;
+	u8 revision;
 
 
 	unsigned short addr;
 	unsigned short addr;
 	const char *name;
 	const char *name;
@@ -268,6 +270,14 @@ struct it87_data {
 	u8 manual_pwm_ctl[3];   /* manual PWM value set by user */
 	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 it87_probe(struct platform_device *pdev);
 static int __devexit it87_remove(struct platform_device *pdev);
 static int __devexit it87_remove(struct platform_device *pdev);
@@ -991,8 +1001,9 @@ static int __init it87_find(unsigned short *address,
 	}
 	}
 
 
 	err = 0;
 	err = 0;
+	sio_data->revision = superio_inb(DEVREV) & 0x0f;
 	pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
 	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) */
 	/* Read GPIO config and VID value from LDN 7 (GPIO) */
 	if (chip_type != IT8705F_DEVID) {
 	if (chip_type != IT8705F_DEVID) {
@@ -1045,6 +1056,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
 
 
 	data->addr = res->start;
 	data->addr = res->start;
 	data->type = sio_data->type;
 	data->type = sio_data->type;
+	data->revision = sio_data->revision;
 	data->name = names[sio_data->type];
 	data->name = names[sio_data->type];
 
 
 	/* Now, we do the remaining detection. */
 	/* Now, we do the remaining detection. */
@@ -1069,7 +1081,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
 		goto ERROR2;
 		goto ERROR2;
 
 
 	/* Do not create fan files for disabled fans */
 	/* Do not create fan files for disabled fans */
-	if (data->type == it8716 || data->type == it8718) {
+	if (has_16bit_fans(data)) {
 		/* 16-bit tachometers */
 		/* 16-bit tachometers */
 		if (data->has_fan & (1 << 0)) {
 		if (data->has_fan & (1 << 0)) {
 			if ((err = device_create_file(dev,
 			if ((err = device_create_file(dev,
@@ -1350,7 +1362,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
 	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
 	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
 
 
 	/* Set tachometers to 16-bit mode if needed */
 	/* 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);
 		tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
 		if (~tmp & 0x07 & data->has_fan) {
 		if (~tmp & 0x07 & data->has_fan) {
 			dev_dbg(&pdev->dev,
 			dev_dbg(&pdev->dev,
@@ -1426,7 +1438,7 @@ static struct it87_data *it87_update_device(struct device *dev)
 			data->fan[i] = it87_read_value(data,
 			data->fan[i] = it87_read_value(data,
 				       IT87_REG_FAN[i]);
 				       IT87_REG_FAN[i]);
 			/* Add high byte if in 16-bit mode */
 			/* 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,
 				data->fan[i] |= it87_read_value(data,
 						IT87_REG_FANX[i]) << 8;
 						IT87_REG_FANX[i]) << 8;
 				data->fan_min[i] |= it87_read_value(data,
 				data->fan_min[i] |= it87_read_value(data,
@@ -1443,8 +1455,7 @@ static struct it87_data *it87_update_device(struct device *dev)
 		}
 		}
 
 
 		/* Newer chips don't have clock dividers */
 		/* 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);
 			i = it87_read_value(data, IT87_REG_FAN_DIV);
 			data->fan_div[0] = i & 0x07;
 			data->fan_div[0] = i & 0x07;
 			data->fan_div[1] = (i >> 3) & 0x07;
 			data->fan_div[1] = (i >> 3) & 0x07;
@@ -1460,7 +1471,8 @@ static struct it87_data *it87_update_device(struct device *dev)
 		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
 		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
 
 
 		data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
 		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) {
 		if (data->type == it8712 || data->type == it8716) {
 			data->vid = it87_read_value(data, IT87_REG_VID);
 			data->vid = it87_read_value(data, IT87_REG_VID);
 			/* The older IT8712F revisions had only 5 VID pins,
 			/* The older IT8712F revisions had only 5 VID pins,