[PATCH] hwmon: it87 support for 16-bit fan reading in 8712 rev 8 and new module param

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This splits the it8712 chip type into two chip types to distinguish the
changes made in rev 8 of the chip. A new type it8712old represents all
revs prior to rev 8. The it8712 chip type now represents rev 8 and
greater. For clarity, the it87 chip type is now named it8705.

The it8712 chip type now enables 16-bit fan tachometer reading to get
proper readings. The register used in the it8712old chip type no longer
has the same meaning in rev 8 of the chip.

Also, a new module param array enable_fans is added. This was needed to
get fan2 to show up on an it8712 rev 8 chip which was not enabled at
boot time by the BIOS. The module param is checked and if a fan index
value is 1, the fan is forced on even if it is not configured that way
from the BIOS.

Signed-off-by: Andrew Paprocki <andrew at ishiboo.com>
---
  drivers/hwmon/it87.c |   84
+++++++++++++++++++++++++++++++++++++-------------
  1 files changed, 62 insertions(+), 22 deletions(-)

diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index ad6c8a3..3c23726 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -50,7 +50,7 @@

  #define DRVNAME "it87"

-enum chips { it87, it8712, it8716, it8718 };
+enum chips { it8705, it8712old, it8712, it8716, it8718 };

  static struct platform_device *pdev;

@@ -121,6 +121,9 @@ static int update_vbat;
  /* Not all BIOSes properly configure the PWM registers */
  static int fix_pwm_polarity;

+/* Not all BIOSes properly enable all available fans */
+static int enable_fans[5];
+
  /* Many IT87 constants specified below */

  /* Length of ISA address segment */
@@ -145,11 +148,11 @@ static int fix_pwm_polarity;
  #define IT87_REG_ALARM3        0x03

  /* The IT8718F has the VID value in a different register, in Super-I/O
-   configuration space. */
+ * 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

@@ -904,16 +907,21 @@ static int __init it87_find(unsigned short *address,
  {
  	int err = -ENODEV;
  	u16 chip_type;
+        u8 revision;

  	superio_enter();
  	chip_type = superio_inw(DEVID);
+        revision = superio_inb(DEVREV);

  	switch (chip_type) {
  	case IT8705F_DEVID:
-		sio_data->type = it87;
+		sio_data->type = it8705;
  		break;
  	case IT8712F_DEVID:
-		sio_data->type = it8712;
+                if (revision < 0x08)
+                        sio_data->type = it8712old;
+                else
+                        sio_data->type = it8712;
  		break;
  	case IT8716F_DEVID:
  	case IT8726F_DEVID:
@@ -975,7 +983,8 @@ static int __devinit it87_probe(struct
platform_device *pdev)
  	int err = 0;
  	int enable_pwm_interface;
  	static const char *names[] = {
-		"it87",
+		"it8705",
+		"it8712",
  		"it8712",
  		"it8716",
  		"it8718",
@@ -1021,7 +1030,7 @@ static int __devinit it87_probe(struct
platform_device *pdev)
  		goto ERROR2;

  	/* Do not create fan files for disabled fans */
-	if (data->type == it8716 || data->type == it8718) {
+        if (data->type != it8705 && data->type != it8712old) {
  		/* 16-bit tachometers */
  		if (data->has_fan & (1 << 0)) {
  			if ((err = device_create_file(dev,
@@ -1111,8 +1120,7 @@ static int __devinit it87_probe(struct
platform_device *pdev)
  			goto ERROR4;
  	}

-	if (data->type == it8712 || data->type == it8716
-	 || data->type == it8718) {
+	if (data->type != it8705) {
  		data->vrm = vid_which_vrm();
  		/* VID reading from Super-I/O config space if available */
  		data->vid = sio_data->vid_value;
@@ -1232,6 +1240,7 @@ static void __devinit it87_init_device(struct
platform_device *pdev)
  {
  	struct it87_data *data = platform_get_drvdata(pdev);
  	int tmp, i;
+        u8 force_fan_main_ctrl;

  	/* initialize to sane defaults:
  	 * - if the chip is in manual pwm mode, this will be overwritten with
@@ -1283,21 +1292,43 @@ static void __devinit it87_init_device(struct
platform_device *pdev)
  		data->fan_main_ctrl |= 0x70;
  		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
  	}
+
+        /* Force on any of the first three fans */
+        force_fan_main_ctrl = data->fan_main_ctrl;
+        if (enable_fans[0])
+                force_fan_main_ctrl |= (1 << 4);
+        if (enable_fans[1])
+                force_fan_main_ctrl |= (1 << 5);
+        if (enable_fans[2])
+                force_fan_main_ctrl |= (1 << 6);
+        if (force_fan_main_ctrl != data->fan_main_ctrl) {
+                data->fan_main_ctrl = force_fan_main_ctrl;
+                it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+                                 data->fan_main_ctrl);
+        }
+
  	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;

  	/* Set tachometers to 16-bit mode if needed */
-	if (data->type == it8716 || data->type == it8718) {
-		tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
+	if (data->type == it8712 || data->type == it8716
+         || data->type == it8718) {
+                int new_tmp = tmp = it87_read_value(data,
IT87_REG_FAN_16BIT);
  		if (~tmp & 0x07 & data->has_fan) {
  			dev_dbg(&pdev->dev,
-				"Setting fan1-3 to 16-bit mode\n");
-			it87_write_value(data, IT87_REG_FAN_16BIT,
-					 tmp | 0x07);
+				"Setting all fans to 16-bit mode\n");
+			it87_write_value(data, IT87_REG_FAN_16BIT, tmp | 0x07);
  		}
  		if (tmp & (1 << 4))
  			data->has_fan |= (1 << 3);	/* fan4 enabled */
+                else if (enable_fans[3])
+                        new_tmp |= (1 << 3);            /* fan4 force
enabled */
  		if (tmp & (1 << 5))
  			data->has_fan |= (1 << 4);	/* fan5 enabled */
+                else if (enable_fans[4])
+                        new_tmp |= (1 << 4);            /* fan5 force
enabled */
+
+                if (new_tmp != tmp)
+                        it87_write_value(data, IT87_REG_FAN_16BIT,
new_tmp);
  	}

  	/* Set current fan mode registers and the default settings for the
@@ -1316,7 +1347,9 @@ static void __devinit it87_init_device(struct
platform_device *pdev)
  				data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp);
  			}
  		}
- 	}
+	}
+
+        /* FIXME: perform the above logic for fan4 and fan5 if necessary */

  	/* Start monitoring */
  	it87_write_value(data, IT87_REG_CONFIG,
@@ -1362,7 +1395,8 @@ static struct it87_data *it87_update_device(struct
device *dev)
  			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 (data->type == it8712 || data->type == it8716
+                         || data->type == it8718) {
  				data->fan[i] |= it87_read_value(data,
  						IT87_REG_FANX[i]) << 8;
  				data->fan_min[i] |= it87_read_value(data,
@@ -1378,9 +1412,11 @@ static struct it87_data
*it87_update_device(struct device *dev)
  			    it87_read_value(data, IT87_REG_TEMP_LOW(i));
  		}

-		/* Newer chips don't have clock dividers */
-		if ((data->has_fan & 0x07) && data->type != it8716
-		 && data->type != it8718) {
+                /* The 8705 uses fan divisors. The 8712 had fan divisors
+                 * prior to revision 0x08.
+                 */
+		if ((data->has_fan & 0x07) &&
+                    (data->type == it8705 || data->type == it8712old)) {
  			i = it87_read_value(data, IT87_REG_FAN_DIV);
  			data->fan_div[0] = i & 0x07;
  			data->fan_div[1] = (i >> 3) & 0x07;
@@ -1396,7 +1432,9 @@ static struct it87_data *it87_update_device(struct
device *dev)
  		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,
@@ -1495,6 +1533,8 @@ module_param(update_vbat, bool, 0);
  MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup
value");
  module_param(fix_pwm_polarity, bool, 0);
  MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high
(DANGEROUS)");
+module_param_array(enable_fans, bool, 0, 0444);
+MODULE_PARM_DESC(enable_fans, "Force enable fans (up to 5 fans when
supported)");
  MODULE_LICENSE("GPL");

  module_init(sm_it87_init);




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux