]> git.sur5r.net Git - groeck-it87/commitdiff
Synchronize with upstream version
authorGuenter Roeck <linux@roeck-us.net>
Sat, 17 Jan 2015 18:00:02 +0000 (10:00 -0800)
committerGuenter Roeck <linux@roeck-us.net>
Sat, 17 Jan 2015 18:01:10 +0000 (10:01 -0800)
Also ensure the driver still builds with the latest upstream kernel.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Makefile
compat.h
it87.c

index 023674067083a8d64739f50baf11583ebf109951..1ee555c22e6f86a1482a40676c47e8d0243092bb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,8 +3,8 @@ TARGET          := $(shell uname -r)
 # Or specific version
 #TARGET                := 2.6.33.5
 KERNEL_MODULES := /lib/modules/$(TARGET)
-KERNEL_BUILD   := $(KERNEL_MODULES)/build
-# KERNEL_BUILD := /usr/src/linux-headers-$(TARGET)
+# KERNEL_BUILD := $(KERNEL_MODULES)/build
+KERNEL_BUILD   := /usr/src/linux-headers-$(TARGET)
 
 #SYSTEM_MAP    := $(KERNEL_BUILD)/System.map
 SYSTEM_MAP     := /boot/System.map-$(TARGET)
@@ -15,7 +15,8 @@ DRIVER := it87
 # the module:
 MOD_SUBDIR = drivers/hwmon
 
-obj-m  := $(DRIVER).o
+obj-m  := $(patsubst %,%.o,$(DRIVER))
+obj-ko  := $(patsubst %,%.ko,$(DRIVER))
 
 MAKEFLAGS += --no-print-directory
 
index bb256e8630cbbffad35ca20e09f8308ee0c5e970..29ccdb7f3ece2eb6aa532c5dd71dea8a02be9d6a 100644 (file)
--- a/compat.h
+++ b/compat.h
 
 #include <linux/version.h>
 
+#ifndef clamp_val
+#define clamp_val SENSORS_LIMIT
+#endif
+
 #ifndef request_muxed_region
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 28)
 #define request_muxed_region(start,n,name)     __request_region(&ioport_resource, (start), (n), (name))
diff --git a/it87.c b/it87.c
index 5379c6ab52ad3801b7c9580b5765b0144c6b5aac..125d15889d5169d66560c93ff9fae9487d04d933 100644 (file)
--- a/it87.c
+++ b/it87.c
@@ -10,7 +10,9 @@
  *  This driver supports only the Environment Controller in the IT8705F and
  *  similar parts.  The other devices are supported by different drivers.
  *
- *  Supports: IT8705F  Super I/O chip w/LPC interface
+ *  Supports: IT8603E  Super I/O chip w/LPC interface
+ *            IT8623E  Super I/O chip w/LPC interface
+ *            IT8705F  Super I/O chip w/LPC interface
  *            IT8712F  Super I/O chip w/LPC interface
  *            IT8716F  Super I/O chip w/LPC interface
  *            IT8718F  Super I/O chip w/LPC interface
  *            IT8726F  Super I/O chip w/LPC interface
  *            IT8728F  Super I/O chip w/LPC interface
  *            IT8758E  Super I/O chip w/LPC interface
+ *            IT8771E  Super I/O chip w/LPC interface
+ *            IT8772E  Super I/O chip w/LPC interface
  *            IT8782F  Super I/O chip w/LPC interface
  *            IT8783E/F Super I/O chip w/LPC interface
  *            Sis950   A clone of the IT8705F
  *
  *  Copyright (C) 2001 Chris Gauthron
- *  Copyright (C) 2005-2010 Jean Delvare <khali@linux-fr.org>
+ *  Copyright (C) 2005-2010 Jean Delvare <jdelvare@suse.de>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -62,8 +66,8 @@
 
 #define DRVNAME "it87"
 
-enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8782,
-            it8783 };
+enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771,
+            it8772, it8782, it8783, it8603 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -141,8 +145,12 @@ static inline void superio_exit(void)
 #define IT8721F_DEVID 0x8721
 #define IT8726F_DEVID 0x8726
 #define IT8728F_DEVID 0x8728
+#define IT8771E_DEVID 0x8771
+#define IT8772E_DEVID 0x8772
 #define IT8782F_DEVID 0x8782
 #define IT8783E_DEVID 0x8783
+#define IT8603E_DEVID 0x8603
+#define IT8623E_DEVID 0x8623
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
@@ -282,6 +290,24 @@ static const struct it87_devices it87_devices[] = {
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
                .peci_mask = 0x07,
        },
+       [it8771] = {
+               .name = "it8771",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
+                                       /* PECI: guesswork */
+                                       /* 12mV ADC (OHM) */
+                                       /* 16 bit fans (OHM) */
+               .peci_mask = 0x07,
+       },
+       [it8772] = {
+               .name = "it8772",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
+                                       /* PECI (coreboot) */
+                                       /* 12mV ADC (HWSensors4, OHM) */
+                                       /* 16 bit fans (HWSensors4, OHM) */
+               .peci_mask = 0x07,
+       },
        [it8782] = {
                .name = "it8782",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
@@ -294,6 +320,12 @@ static const struct it87_devices it87_devices[] = {
                  | FEAT_TEMP_OLD_PECI,
                .old_peci_mask = 0x4,
        },
+       [it8603] = {
+               .name = "it8603",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
+               .peci_mask = 0x07,
+       },
 };
 
 #define has_16bit_fans(data)   ((data)->features & FEAT_16BIT_FANS)
@@ -340,7 +372,7 @@ struct it87_data {
        unsigned long last_updated;     /* In jiffies */
 
        u16 in_scaled;          /* Internal voltage sensors are scaled */
-       u8 in[9][3];            /* [nr][0]=in, [1]=min, [2]=max */
+       u8 in[10][3];           /* [nr][0]=in, [1]=min, [2]=max */
        u8 has_fan;             /* Bitfield, fans enabled */
        u16 fan[5][2];          /* Register values, [nr][0]=fan, [1]=min */
        u8 has_temp;            /* Bitfield, temp sensors enabled */
@@ -385,7 +417,7 @@ static int adc_lsb(const struct it87_data *data, int nr)
 static u8 in_to_reg(const struct it87_data *data, int nr, long val)
 {
        val = DIV_ROUND_CLOSEST(val, adc_lsb(data, nr));
-       return SENSORS_LIMIT(val, 0, 255);
+       return clamp_val(val, 0, 255);
 }
 
 static int in_from_reg(const struct it87_data *data, int nr, int val)
@@ -397,16 +429,15 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 {
        if (rpm == 0)
                return 255;
-       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
-       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
-                            254);
+       rpm = clamp_val(rpm, 1, 1000000);
+       return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
 static inline u16 FAN16_TO_REG(long rpm)
 {
        if (rpm == 0)
                return 0xffff;
-       return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
+       return clamp_val((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
 }
 
 #define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 255 ? 0 : \
@@ -415,8 +446,8 @@ static inline u16 FAN16_TO_REG(long rpm)
 #define FAN16_FROM_REG(val) ((val) == 0 ? -1 : (val) == 0xffff ? 0 : \
                             1350000 / ((val) * 2))
 
-#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (((val) - 500) / 1000) : \
-                                       ((val) + 500) / 1000), -128, 127))
+#define TEMP_TO_REG(val) (clamp_val(((val) < 0 ? (((val) - 500) / 1000) : \
+                                   ((val) + 500) / 1000), -128, 127))
 #define TEMP_FROM_REG(val) ((val) * 1000)
 
 static u8 pwm_to_reg(const struct it87_data *data, long val)
@@ -457,7 +488,7 @@ static const unsigned int pwm_freq[8] = {
 };
 
 static int it87_probe(struct platform_device *pdev);
-static int __devexit it87_remove(struct platform_device *pdev);
+static int it87_remove(struct platform_device *pdev);
 
 static int it87_read_value(struct it87_data *data, u8 reg);
 static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
@@ -468,11 +499,10 @@ static void it87_init_device(struct platform_device *pdev);
 
 static struct platform_driver it87_driver = {
        .driver = {
-               .owner  = THIS_MODULE,
                .name   = DRVNAME,
        },
        .probe  = it87_probe,
-       .remove = __devexit_p(it87_remove),
+       .remove = it87_remove,
 };
 
 static ssize_t show_in(struct device *dev, struct device_attribute *attr,
@@ -558,6 +588,7 @@ static SENSOR_DEVICE_ATTR_2(in7_max, S_IRUGO | S_IWUSR, show_in, set_in,
                            7, 2);
 
 static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0);
+static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 9, 0);
 
 /* 3 temperatures */
 static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
@@ -714,7 +745,7 @@ static int pwm_mode(const struct it87_data *data, int nr)
 {
        int ctrl = data->fan_main_ctrl & (1 << nr);
 
-       if (ctrl == 0)                                  /* Full speed */
+       if (ctrl == 0 && data->type != it8603)          /* Full speed */
                return 0;
        if (data->pwm_ctrl[nr] & 0x80)                  /* Automatic mode */
                return 2;
@@ -909,6 +940,10 @@ static ssize_t set_pwm_enable(struct device *dev,
                        return -EINVAL;
        }
 
+       /* IT8603E does not have on/off mode */
+       if (val == 0 && data->type == it8603)
+               return -EINVAL;
+
        mutex_lock(&data->update_lock);
 
        if (val == 0) {
@@ -928,10 +963,13 @@ static ssize_t set_pwm_enable(struct device *dev,
                else                                    /* Automatic mode */
                        data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
                it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
-               /* set SmartGuardian mode */
-               data->fan_main_ctrl |= (1 << nr);
-               it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
-                                data->fan_main_ctrl);
+
+               if (data->type != it8603) {
+                       /* set SmartGuardian mode */
+                       data->fan_main_ctrl |= (1 << nr);
+                       it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+                                        data->fan_main_ctrl);
+               }
        }
 
        mutex_unlock(&data->update_lock);
@@ -1395,6 +1433,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
 static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
 static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
 static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2);
+/* special AVCC3 IT8603E in9 */
+static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0);
 
 static ssize_t show_name(struct device *dev, struct device_attribute
                         *devattr, char *buf)
@@ -1404,7 +1444,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute
 }
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static struct attribute *it87_attributes_in[9][5] = {
+static struct attribute *it87_attributes_in[10][5] = {
 {
        &sensor_dev_attr_in0_input.dev_attr.attr,
        &sensor_dev_attr_in0_min.dev_attr.attr,
@@ -1456,9 +1496,12 @@ static struct attribute *it87_attributes_in[9][5] = {
 }, {
        &sensor_dev_attr_in8_input.dev_attr.attr,
        NULL
+}, {
+       &sensor_dev_attr_in9_input.dev_attr.attr,
+       NULL
 } };
 
-static const struct attribute_group it87_group_in[9] = {
+static const struct attribute_group it87_group_in[10] = {
        { .attrs = it87_attributes_in[0] },
        { .attrs = it87_attributes_in[1] },
        { .attrs = it87_attributes_in[2] },
@@ -1468,6 +1511,7 @@ static const struct attribute_group it87_group_in[9] = {
        { .attrs = it87_attributes_in[6] },
        { .attrs = it87_attributes_in[7] },
        { .attrs = it87_attributes_in[8] },
+       { .attrs = it87_attributes_in[9] },
 };
 
 static struct attribute *it87_attributes_temp[3][6] = {
@@ -1526,7 +1570,8 @@ static struct attribute *it87_attributes_in_beep[] = {
        &sensor_dev_attr_in5_beep.dev_attr.attr,
        &sensor_dev_attr_in6_beep.dev_attr.attr,
        &sensor_dev_attr_in7_beep.dev_attr.attr,
-       NULL
+       NULL,
+       NULL,
 };
 
 static struct attribute *it87_attributes_temp_beep[] = {
@@ -1665,6 +1710,7 @@ static struct attribute *it87_attributes_label[] = {
        &sensor_dev_attr_in3_label.dev_attr.attr,
        &sensor_dev_attr_in7_label.dev_attr.attr,
        &sensor_dev_attr_in8_label.dev_attr.attr,
+       &sensor_dev_attr_in9_label.dev_attr.attr,
        NULL
 };
 
@@ -1710,12 +1756,22 @@ static int __init it87_find(unsigned short *address,
        case IT8728F_DEVID:
                sio_data->type = it8728;
                break;
+       case IT8771E_DEVID:
+               sio_data->type = it8771;
+               break;
+       case IT8772E_DEVID:
+               sio_data->type = it8772;
+               break;
        case IT8782F_DEVID:
                sio_data->type = it8782;
                break;
        case IT8783E_DEVID:
                sio_data->type = it8783;
                break;
+       case IT8603E_DEVID:
+       case IT8623E_DEVID:
+               sio_data->type = it8603;
+               break;
        case 0xffff:    /* No device at all */
                goto exit;
        default:
@@ -1737,11 +1793,16 @@ static int __init it87_find(unsigned short *address,
 
        err = 0;
        sio_data->revision = superio_inb(DEVREV) & 0x0f;
-       pr_info("Found IT%04xF chip at 0x%x, revision %d\n",
-               chip_type, *address, sio_data->revision);
+       pr_info("Found IT%04x%c chip at 0x%x, revision %d\n", chip_type,
+               chip_type == 0x8771 || chip_type == 0x8772 ||
+               chip_type == 0x8603 ? 'E' : 'F', *address,
+               sio_data->revision);
 
        /* in8 (Vbat) is always internal */
        sio_data->internal = (1 << 2);
+       /* Only the IT8603E has in9 */
+       if (sio_data->type != it8603)
+               sio_data->skip_in |= (1 << 9);
 
        /* Read GPIO config and VID value from LDN 7 (GPIO) */
        if (sio_data->type == it87) {
@@ -1752,7 +1813,7 @@ static int __init it87_find(unsigned short *address,
                superio_select(5);
                sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
        } else if (sio_data->type == it8783) {
-               int reg25, reg27, reg2A, reg2C, regEF;
+               int reg25, reg27, reg2a, reg2c, regef;
 
                sio_data->skip_vid = 1; /* No VID */
 
@@ -1760,15 +1821,15 @@ static int __init it87_find(unsigned short *address,
 
                reg25 = superio_inb(IT87_SIO_GPIO1_REG);
                reg27 = superio_inb(IT87_SIO_GPIO3_REG);
-               reg2A = superio_inb(IT87_SIO_PINX1_REG);
-               reg2C = superio_inb(IT87_SIO_PINX2_REG);
-               regEF = superio_inb(IT87_SIO_SPI_REG);
+               reg2a = superio_inb(IT87_SIO_PINX1_REG);
+               reg2c = superio_inb(IT87_SIO_PINX2_REG);
+               regef = superio_inb(IT87_SIO_SPI_REG);
 
                /* Check if fan3 is there or not */
-               if ((reg27 & (1 << 0)) || !(reg2C & (1 << 2)))
+               if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2)))
                        sio_data->skip_fan |= (1 << 2);
                if ((reg25 & (1 << 4))
-                   || (!(reg2A & (1 << 1)) && (regEF & (1 << 0))))
+                   || (!(reg2a & (1 << 1)) && (regef & (1 << 0))))
                        sio_data->skip_pwm |= (1 << 2);
 
                /* Check if fan2 is there or not */
@@ -1778,7 +1839,7 @@ static int __init it87_find(unsigned short *address,
                        sio_data->skip_pwm |= (1 << 1);
 
                /* VIN5 */
-               if ((reg27 & (1 << 0)) || (reg2C & (1 << 2)))
+               if ((reg27 & (1 << 0)) || (reg2c & (1 << 2)))
                        sio_data->skip_in |= (1 << 5); /* No VIN5 */
 
                /* VIN6 */
@@ -1803,22 +1864,53 @@ static int __init it87_find(unsigned short *address,
                         * not the case, and ask the user to report if the
                         * resulting voltage is sane.
                         */
-                       if (!(reg2C & (1 << 1))) {
-                               reg2C |= (1 << 1);
-                               superio_outb(IT87_SIO_PINX2_REG, reg2C);
+                       if (!(reg2c & (1 << 1))) {
+                               reg2c |= (1 << 1);
+                               superio_outb(IT87_SIO_PINX2_REG, reg2c);
                                pr_notice("Routing internal VCCH5V to in7.\n");
                        }
                        pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
                        pr_notice("Please report if it displays a reasonable voltage.\n");
                }
 
-               if (reg2C & (1 << 0))
+               if (reg2c & (1 << 0))
                        sio_data->internal |= (1 << 0);
-               if (reg2C & (1 << 1))
+               if (reg2c & (1 << 1))
                        sio_data->internal |= (1 << 1);
 
                sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+       } else if (sio_data->type == it8603) {
+               int reg27, reg29;
+
+               sio_data->skip_vid = 1; /* No VID */
+               superio_select(GPIO);
+
+               reg27 = superio_inb(IT87_SIO_GPIO3_REG);
+
+               /* Check if fan3 is there or not */
+               if (reg27 & (1 << 6))
+                       sio_data->skip_pwm |= (1 << 2);
+               if (reg27 & (1 << 7))
+                       sio_data->skip_fan |= (1 << 2);
+
+               /* Check if fan2 is there or not */
+               reg29 = superio_inb(IT87_SIO_GPIO5_REG);
+               if (reg29 & (1 << 1))
+                       sio_data->skip_pwm |= (1 << 1);
+               if (reg29 & (1 << 2))
+                       sio_data->skip_fan |= (1 << 1);
+
+               sio_data->skip_in |= (1 << 5); /* No VIN5 */
+               sio_data->skip_in |= (1 << 6); /* No VIN6 */
 
+               /* no fan4 */
+               sio_data->skip_pwm |= (1 << 3);
+               sio_data->skip_fan |= (1 << 3);
+
+               sio_data->internal |= (1 << 1); /* in7 is VSB */
+               sio_data->internal |= (1 << 3); /* in9 is AVCC */
+
+               sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
        } else {
                int reg;
                bool uart6;
@@ -1827,10 +1919,11 @@ static int __init it87_find(unsigned short *address,
 
                reg = superio_inb(IT87_SIO_GPIO3_REG);
                if (sio_data->type == it8721 || sio_data->type == it8728 ||
+                   sio_data->type == it8771 || sio_data->type == it8772 ||
                    sio_data->type == it8782) {
                        /*
                         * IT8721F/IT8758E, and IT8782F don't have VID pins
-                        * at all, not sure about the IT8728F.
+                        * at all, not sure about the IT8728F and compatibles.
                         */
                        sio_data->skip_vid = 1;
                } else {
@@ -1884,7 +1977,9 @@ static int __init it87_find(unsigned short *address,
                if (reg & (1 << 0))
                        sio_data->internal |= (1 << 0);
                if ((reg & (1 << 1)) || sio_data->type == it8721 ||
-                   sio_data->type == it8728)
+                   sio_data->type == it8728 ||
+                   sio_data->type == it8771 ||
+                   sio_data->type == it8772)
                        sio_data->internal |= (1 << 1);
 
                /*
@@ -1933,11 +2028,11 @@ exit:
 static void it87_remove_files(struct device *dev)
 {
        struct it87_data *data = platform_get_drvdata(pdev);
-       struct it87_sio_data *sio_data = dev->platform_data;
+       struct it87_sio_data *sio_data = dev_get_platdata(dev);
        int i;
 
        sysfs_remove_group(&dev->kobj, &it87_group);
-       for (i = 0; i < 9; i++) {
+       for (i = 0; i < 10; i++) {
                if (sio_data->skip_in & (1 << i))
                        continue;
                sysfs_remove_group(&dev->kobj, &it87_group_in[i]);
@@ -1980,12 +2075,12 @@ static void it87_remove_files(struct device *dev)
        sysfs_remove_group(&dev->kobj, &it87_group_label);
 }
 
-static int __devinit it87_probe(struct platform_device *pdev)
+static int it87_probe(struct platform_device *pdev)
 {
        struct it87_data *data;
        struct resource *res;
        struct device *dev = &pdev->dev;
-       struct it87_sio_data *sio_data = dev->platform_data;
+       struct it87_sio_data *sio_data = dev_get_platdata(dev);
        int err = 0, i;
        int enable_pwm_interface;
        int fan_beep_need_rw;
@@ -2051,6 +2146,8 @@ static int __devinit it87_probe(struct platform_device *pdev)
                        data->in_scaled |= (1 << 7);    /* in7 is VSB */
                if (sio_data->internal & (1 << 2))
                        data->in_scaled |= (1 << 8);    /* in8 is Vbat */
+               if (sio_data->internal & (1 << 3))
+                       data->in_scaled |= (1 << 9);    /* in9 is AVCC */
        } else if (sio_data->type == it8782 || sio_data->type == it8783) {
                if (sio_data->internal & (1 << 0))
                        data->in_scaled |= (1 << 3);    /* in3 is VCC5V */
@@ -2073,7 +2170,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       for (i = 0; i < 9; i++) {
+       for (i = 0; i < 10; i++) {
                if (sio_data->skip_in & (1 << i))
                        continue;
                err = sysfs_create_group(&dev->kobj, &it87_group_in[i]);
@@ -2173,7 +2270,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
        }
 
        /* Export labels for internal sensors */
-       for (i = 0; i < 3; i++) {
+       for (i = 0; i < 4; i++) {
                if (!(sio_data->internal & (1 << i)))
                        continue;
                err = sysfs_create_file(&dev->kobj,
@@ -2195,7 +2292,7 @@ error:
        return err;
 }
 
-static int __devexit it87_remove(struct platform_device *pdev)
+static int it87_remove(struct platform_device *pdev)
 {
        struct it87_data *data = platform_get_drvdata(pdev);
 
@@ -2228,7 +2325,7 @@ static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
 }
 
 /* Return 1 if and only if the PWM interface is safe to use */
-static int __devinit it87_check_pwm(struct device *dev)
+static int it87_check_pwm(struct device *dev)
 {
        struct it87_data *data = dev_get_drvdata(dev);
        /*
@@ -2285,9 +2382,9 @@ static int __devinit it87_check_pwm(struct device *dev)
 }
 
 /* Called when we have found a new IT87. */
-static void __devinit it87_init_device(struct platform_device *pdev)
+static void it87_init_device(struct platform_device *pdev)
 {
-       struct it87_sio_data *sio_data = pdev->dev.platform_data;
+       struct it87_sio_data *sio_data = dev_get_platdata(&pdev->dev);
        struct it87_data *data = platform_get_drvdata(pdev);
        int tmp, i;
        u8 mask;
@@ -2354,8 +2451,9 @@ static void __devinit it87_init_device(struct platform_device *pdev)
        }
        data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
 
-       /* Set tachometers to 16-bit mode if needed */
-       if (has_16bit_fans(data)) {
+       /* Set tachometers to 16-bit mode if needed, IT8603E (and IT8728F?)
+        * has it by default */
+       if (has_16bit_fans(data) && data->type != it8603) {
                tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
                if (~tmp & 0x07 & data->has_fan) {
                        dev_dbg(&pdev->dev,
@@ -2435,6 +2533,8 @@ static struct it87_data *it87_update_device(struct device *dev)
                }
                /* in8 (battery) has no limit registers */
                data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8));
+               if (data->type == it8603)
+                       data->in[9][0] = it87_read_value(data, 0x2f);
 
                for (i = 0; i < 5; i++) {
                        /* Skip disabled fans */
@@ -2591,7 +2691,7 @@ static void __exit sm_it87_exit(void)
 }
 
 
-MODULE_AUTHOR("Chris Gauthron, Jean Delvare <khali@linux-fr.org>");
+MODULE_AUTHOR("Chris Gauthron, Jean Delvare <jdelvare@suse.de>");
 MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver");
 module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");