]> git.sur5r.net Git - groeck-it87/blobdiff - it87.c
Register map as CSV
[groeck-it87] / it87.c
diff --git a/it87.c b/it87.c
index f54724106da14bf2e88e0a077f5e4a565f7da395..6f62ff6201bf451ed7f648e1829d3063e14b5d86 100644 (file)
--- a/it87.c
+++ b/it87.c
@@ -16,6 +16,8 @@
  *            IT8622E  Super I/O chip w/LPC interface
  *            IT8623E  Super I/O chip w/LPC interface
  *            IT8628E  Super I/O chip w/LPC interface
+ *            IT8655E  Super I/O chip w/LPC interface
+ *            IT8665E  Super I/O chip w/LPC interface
  *            IT8686E  Super I/O chip w/LPC interface
  *            IT8705F  Super I/O chip w/LPC interface
  *            IT8712F  Super I/O chip w/LPC interface
@@ -75,7 +77,8 @@
 
 enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732,
             it8771, it8772, it8781, it8782, it8783, it8786, it8790,
-            it8792, it8603, it8607, it8620, it8622, it8628, it8686 };
+            it8792, it8603, it8607, it8620, it8622, it8628, it8655, it8665,
+            it8686 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -170,6 +173,8 @@ static inline void superio_exit(int ioreg)
 #define IT8622E_DEVID 0x8622
 #define IT8623E_DEVID 0x8623
 #define IT8628E_DEVID 0x8628
+#define IT8655E_DEVID 0x8655
+#define IT8665E_DEVID 0x8665
 #define IT8686E_DEVID 0x8686
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
@@ -180,8 +185,10 @@ static inline void superio_exit(int ioreg)
 #define IT87_SIO_GPIO3_REG     0x27
 #define IT87_SIO_GPIO4_REG     0x28
 #define IT87_SIO_GPIO5_REG     0x29
+#define IT87_SIO_GPIO9_REG     0xd3
 #define IT87_SIO_PINX1_REG     0x2a    /* Pin selection */
 #define IT87_SIO_PINX2_REG     0x2c    /* Pin selection */
+#define IT87_SIO_PINX4_REG     0x2d    /* Pin selection */
 #define IT87_SIO_SPI_REG       0xef    /* SPI function pin select */
 #define IT87_SIO_VID_REG       0xfc    /* VID value */
 #define IT87_SIO_BEEP_PIN_REG  0xf6    /* Beep pin mapping */
@@ -237,16 +244,27 @@ static bool fix_pwm_polarity;
  * - up to 6 fan (1 to 6)
  */
 
-static const u8 IT87_REG_FAN[]         = { 0x0d, 0x0e, 0x0f, 0x80, 0x82, 0x4c };
-static const u8 IT87_REG_FAN_MIN[]     = { 0x10, 0x11, 0x12, 0x84, 0x86, 0x4e };
-static const u8 IT87_REG_FANX[]        = { 0x18, 0x19, 0x1a, 0x81, 0x83, 0x4d };
-static const u8 IT87_REG_FANX_MIN[]    = { 0x1b, 0x1c, 0x1d, 0x85, 0x87, 0x4f };
+static const u8 IT87_REG_FAN[] =       { 0x0d, 0x0e, 0x0f, 0x80, 0x82, 0x4c };
+static const u8 IT87_REG_FAN_MIN[] =   { 0x10, 0x11, 0x12, 0x84, 0x86, 0x4e };
+static const u8 IT87_REG_FANX[] =      { 0x18, 0x19, 0x1a, 0x81, 0x83, 0x4d };
+static const u8 IT87_REG_FANX_MIN[] =  { 0x1b, 0x1c, 0x1d, 0x85, 0x87, 0x4f };
+
+static const u8 IT87_REG_FAN_8665[] =  { 0x0d, 0x0e, 0x0f, 0x80, 0x82, 0x93 };
+static const u8 IT87_REG_FAN_MIN_8665[] =
+                                       { 0x10, 0x11, 0x12, 0x84, 0x86, 0xb2 };
+static const u8 IT87_REG_FANX_8665[] = { 0x18, 0x19, 0x1a, 0x81, 0x83, 0x94 };
+static const u8 IT87_REG_FANX_MIN_8665[] =
+                                       { 0x1b, 0x1c, 0x1d, 0x85, 0x87, 0xb3 };
+
 static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 };
 
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
-static const u8 IT87_REG_PWM[]         = { 0x15, 0x16, 0x17, 0x7f, 0xa7, 0xaf };
-static const u8 IT87_REG_PWM_DUTY[]    = { 0x63, 0x6b, 0x73, 0x7b, 0xa3, 0xab };
+
+static const u8 IT87_REG_PWM[] =       { 0x15, 0x16, 0x17, 0x7f, 0xa7, 0xaf };
+static const u8 IT87_REG_PWM_8665[] =  { 0x15, 0x16, 0x17, 0x1e, 0x1f, 0x92 };
+
+static const u8 IT87_REG_PWM_DUTY[] =  { 0x63, 0x6b, 0x73, 0x7b, 0xa3, 0xab };
 
 static const u8 IT87_REG_VIN[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
                                    0x27, 0x28, 0x2f, 0x2c, 0x2d, 0x2e };
@@ -312,31 +330,35 @@ struct it87_devices {
 #define FEAT_FOUR_FANS         BIT(19) /* Supports four fans */
 #define FEAT_FOUR_PWM          BIT(20) /* Supports four fan controls */
 #define FEAT_BANK_SEL          BIT(21) /* Chip has multi-bank support */
+#define FEAT_SCALING           BIT(22) /* Internal voltage scaling */
+#define FEAT_FANCTL_ONOFF      BIT(23) /* chip has FAN_CTL ON/OFF */
 
 static const struct it87_devices it87_devices[] = {
        [it87] = {
                .name = "it87",
                .suffix = "F",
-               .features = FEAT_OLD_AUTOPWM,   /* may need to overwrite */
+               .features = FEAT_OLD_AUTOPWM | FEAT_FANCTL_ONOFF,
+                                               /* may need to overwrite */
        },
        [it8712] = {
                .name = "it8712",
                .suffix = "F",
-               .features = FEAT_OLD_AUTOPWM | FEAT_VID,
+               .features = FEAT_OLD_AUTOPWM | FEAT_VID | FEAT_FANCTL_ONOFF,
                                                /* may need to overwrite */
        },
        [it8716] = {
                .name = "it8716",
                .suffix = "F",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
-                 | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2,
+                 | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2
+                 | FEAT_FANCTL_ONOFF,
        },
        [it8718] = {
                .name = "it8718",
                .suffix = "F",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
                  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS
-                 | FEAT_PWM_FREQ2,
+                 | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
                .old_peci_mask = 0x4,
        },
        [it8720] = {
@@ -344,7 +366,7 @@ static const struct it87_devices it87_devices[] = {
                .suffix = "F",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
                  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS
-                 | FEAT_PWM_FREQ2,
+                 | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
                .old_peci_mask = 0x4,
        },
        [it8721] = {
@@ -353,7 +375,7 @@ static const struct it87_devices it87_devices[] = {
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
                  | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL
-                 | FEAT_PWM_FREQ2,
+                 | FEAT_PWM_FREQ2 | FEAT_SCALING | FEAT_FANCTL_ONOFF,
                .peci_mask = 0x05,
                .old_peci_mask = 0x02,  /* Actually reports PCH */
        },
@@ -362,7 +384,8 @@ static const struct it87_devices it87_devices[] = {
                .suffix = "F",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS
-                 | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2,
+                 | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 | FEAT_SCALING
+                 | FEAT_FANCTL_ONOFF,
                .peci_mask = 0x07,
        },
        [it8732] = {
@@ -371,7 +394,7 @@ static const struct it87_devices it87_devices[] = {
                .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
                  | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FOUR_FANS
-                 | FEAT_FOUR_PWM,
+                 | FEAT_FOUR_PWM | FEAT_FANCTL_ONOFF,
                .peci_mask = 0x07,
                .old_peci_mask = 0x02,  /* Actually reports PCH */
        },
@@ -380,7 +403,7 @@ static const struct it87_devices it87_devices[] = {
                .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
-                 | FEAT_PWM_FREQ2,
+                 | FEAT_PWM_FREQ2 | FEAT_SCALING | FEAT_FANCTL_ONOFF,
                                /* PECI: guesswork */
                                /* 12mV ADC (OHM) */
                                /* 16 bit fans (OHM) */
@@ -392,7 +415,7 @@ static const struct it87_devices it87_devices[] = {
                .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
-                 | FEAT_PWM_FREQ2,
+                 | FEAT_PWM_FREQ2 | FEAT_SCALING | FEAT_FANCTL_ONOFF,
                                /* PECI (coreboot) */
                                /* 12mV ADC (HWSensors4, OHM) */
                                /* 16 bit fans (HWSensors4, OHM) */
@@ -403,21 +426,24 @@ static const struct it87_devices it87_devices[] = {
                .name = "it8781",
                .suffix = "F",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
+                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
+                 | FEAT_FANCTL_ONOFF,
                .old_peci_mask = 0x4,
        },
        [it8782] = {
                .name = "it8782",
                .suffix = "F",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
+                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
+                 | FEAT_FANCTL_ONOFF,
                .old_peci_mask = 0x4,
        },
        [it8783] = {
                .name = "it8783",
                .suffix = "E/F",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
+                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
+                 | FEAT_FANCTL_ONOFF,
                .old_peci_mask = 0x4,
        },
        [it8786] = {
@@ -425,23 +451,23 @@ static const struct it87_devices it87_devices[] = {
                .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
-                 | FEAT_PWM_FREQ2,
+                 | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
                .peci_mask = 0x07,
        },
        [it8790] = {
                .name = "it8790",
                .suffix = "E",
-               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
-                 | FEAT_PWM_FREQ2,
+               .features = FEAT_NEWER_AUTOPWM | FEAT_10_9MV_ADC | FEAT_SCALING
+                 | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI
+                 | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
                .peci_mask = 0x07,
        },
        [it8792] = {
                .name = "it8792",
                .suffix = "E",
-               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
-                 | FEAT_PWM_FREQ2,
+               .features = FEAT_NEWER_AUTOPWM | FEAT_10_9MV_ADC | FEAT_SCALING
+                 | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI
+                 | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
                .peci_mask = 0x07,
        },
        [it8603] = {
@@ -449,7 +475,7 @@ static const struct it87_devices it87_devices[] = {
                .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
-                 | FEAT_AVCC3 | FEAT_PWM_FREQ2,
+                 | FEAT_AVCC3 | FEAT_PWM_FREQ2 | FEAT_SCALING,
                .peci_mask = 0x07,
        },
        [it8607] = {
@@ -457,7 +483,8 @@ static const struct it87_devices it87_devices[] = {
                .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
-                 | FEAT_AVCC3 | FEAT_PWM_FREQ2,
+                 | FEAT_AVCC3 | FEAT_PWM_FREQ2 | FEAT_SCALING
+                 | FEAT_FANCTL_ONOFF,
                .peci_mask = 0x07,
        },
        [it8620] = {
@@ -466,7 +493,8 @@ static const struct it87_devices it87_devices[] = {
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
                  | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
-                 | FEAT_SIX_TEMP | FEAT_VIN3_5V,
+                 | FEAT_SIX_TEMP | FEAT_VIN3_5V | FEAT_SCALING
+                 | FEAT_FANCTL_ONOFF,
                .peci_mask = 0x07,
        },
        [it8622] = {
@@ -475,7 +503,7 @@ static const struct it87_devices it87_devices[] = {
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS
                  | FEAT_FIVE_PWM | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2
-                 | FEAT_AVCC3 | FEAT_VIN3_5V,
+                 | FEAT_AVCC3 | FEAT_VIN3_5V | FEAT_SCALING,
                .peci_mask = 0x07,
        },
        [it8628] = {
@@ -484,7 +512,25 @@ static const struct it87_devices it87_devices[] = {
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
                  | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
-                 | FEAT_SIX_TEMP,
+                 | FEAT_SIX_TEMP | FEAT_SCALING | FEAT_AVCC3
+                 | FEAT_FANCTL_ONOFF,
+               .peci_mask = 0x07,
+       },
+       [it8655] = {
+               .name = "it8655",
+               .suffix = "E",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_AVCC3
+                 | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_BANK_SEL,
+               .peci_mask = 0x07,
+       },
+       [it8665] = {
+               .name = "it8665",
+               .suffix = "E",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_AVCC3
+                 | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_SIX_FANS
+                 | FEAT_SIX_PWM | FEAT_BANK_SEL,
                .peci_mask = 0x07,
        },
        [it8686] = {
@@ -493,7 +539,7 @@ static const struct it87_devices it87_devices[] = {
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
                  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
                  | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
-                 | FEAT_SIX_TEMP | FEAT_BANK_SEL,
+                 | FEAT_SIX_TEMP | FEAT_BANK_SEL | FEAT_SCALING | FEAT_AVCC3,
                .peci_mask = 0x07,
        },
 };
@@ -529,6 +575,8 @@ static const struct it87_devices it87_devices[] = {
                                                     FEAT_FIVE_PWM \
                                                     | FEAT_SIX_PWM))
 #define has_bank_sel(data)     ((data)->features & FEAT_BANK_SEL)
+#define has_scaling(data)      ((data)->features & FEAT_SCALING)
+#define has_fanctl_onoff(data) ((data)->features & FEAT_FANCTL_ONOFF)
 
 struct it87_sio_data {
        enum chips type;
@@ -557,6 +605,13 @@ struct it87_data {
        u8 peci_mask;
        u8 old_peci_mask;
 
+       const u8 *REG_FAN;
+       const u8 *REG_FANX;
+       const u8 *REG_FAN_MIN;
+       const u8 *REG_FANX_MIN;
+
+       const u8 *REG_PWM;
+
        unsigned short addr;
        const char *name;
        struct mutex update_lock;
@@ -750,7 +805,7 @@ static void it87_write_value(struct it87_data *data, u16 reg, u8 value)
 
 static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
 {
-       data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM[nr]);
+       data->pwm_ctrl[nr] = it87_read_value(data, data->REG_PWM[nr]);
        if (has_newer_autopwm(data)) {
                data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
                data->pwm_duty[nr] = it87_read_value(data,
@@ -838,15 +893,15 @@ static struct it87_data *it87_update_device(struct device *dev)
                                continue;
 
                        data->fan[i][1] =
-                               it87_read_value(data, IT87_REG_FAN_MIN[i]);
+                               it87_read_value(data, data->REG_FAN_MIN[i]);
                        data->fan[i][0] = it87_read_value(data,
-                                      IT87_REG_FAN[i]);
+                                      data->REG_FAN[i]);
                        /* Add high byte if in 16-bit mode */
                        if (has_16bit_fans(data)) {
                                data->fan[i][0] |= it87_read_value(data,
-                                               IT87_REG_FANX[i]) << 8;
+                                               data->REG_FANX[i]) << 8;
                                data->fan[i][1] |= it87_read_value(data,
-                                               IT87_REG_FANX_MIN[i]) << 8;
+                                               data->REG_FANX_MIN[i]) << 8;
                        }
                }
                for (i = 0; i < NUM_TEMP; i++) {
@@ -1159,11 +1214,12 @@ static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
 
 static int pwm_mode(const struct it87_data *data, int nr)
 {
-       if (data->type != it8603 && nr < 3 && !(data->fan_main_ctrl & BIT(nr)))
+       if (has_fanctl_onoff(data) && nr < 3 &&
+           !(data->fan_main_ctrl & BIT(nr)))
                return 0;                               /* Full speed */
        if (data->pwm_ctrl[nr] & 0x80)
                return 2;                               /* Automatic mode */
-       if ((data->type == it8603 || nr >= 3) &&
+       if ((!has_fanctl_onoff(data) || nr >= 3) &&
            data->pwm_duty[nr] == pwm_to_reg(data, 0xff))
                return 0;                       /* Full speed */
 
@@ -1254,9 +1310,9 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
 
        if (has_16bit_fans(data)) {
                data->fan[nr][index] = FAN16_TO_REG(val);
-               it87_write_value(data, IT87_REG_FAN_MIN[nr],
+               it87_write_value(data, data->REG_FAN_MIN[nr],
                                 data->fan[nr][index] & 0xff);
-               it87_write_value(data, IT87_REG_FANX_MIN[nr],
+               it87_write_value(data, data->REG_FANX_MIN[nr],
                                 data->fan[nr][index] >> 8);
        } else {
                reg = it87_read_value(data, IT87_REG_FAN_DIV);
@@ -1273,7 +1329,7 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
                }
                data->fan[nr][index] =
                  FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
-               it87_write_value(data, IT87_REG_FAN_MIN[nr],
+               it87_write_value(data, data->REG_FAN_MIN[nr],
                                 data->fan[nr][index]);
        }
 
@@ -1320,7 +1376,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 
        /* Restore fan min limit */
        data->fan[nr][1] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-       it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan[nr][1]);
+       it87_write_value(data, data->REG_FAN_MIN[nr], data->fan[nr][1]);
 
        mutex_unlock(&data->update_lock);
        return count;
@@ -1376,7 +1432,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
        mutex_lock(&data->update_lock);
 
        if (val == 0) {
-               if (nr < 3 && data->type != it8603) {
+               if (nr < 3 && has_fanctl_onoff(data)) {
                        int tmp;
                        /* make sure the fan is on when in on/off mode */
                        tmp = it87_read_value(data, IT87_REG_FAN_CTL);
@@ -1400,7 +1456,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
                                ctrl = data->pwm_duty[nr];
                        }
                        data->pwm_ctrl[nr] = ctrl;
-                       it87_write_value(data, IT87_REG_PWM[nr], ctrl);
+                       it87_write_value(data, data->REG_PWM[nr], ctrl);
                }
        } else {
                u8 ctrl;
@@ -1414,9 +1470,9 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
                        ctrl = (val == 1 ? data->pwm_duty[nr] : 0x80);
                }
                data->pwm_ctrl[nr] = ctrl;
-               it87_write_value(data, IT87_REG_PWM[nr], ctrl);
+               it87_write_value(data, data->REG_PWM[nr], ctrl);
 
-               if (data->type != it8603 && nr < 3) {
+               if (has_fanctl_onoff(data) && nr < 3) {
                        /* set SmartGuardian mode */
                        data->fan_main_ctrl |= BIT(nr);
                        it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
@@ -1461,7 +1517,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                 */
                if (!(data->pwm_ctrl[nr] & 0x80)) {
                        data->pwm_ctrl[nr] = data->pwm_duty[nr];
-                       it87_write_value(data, IT87_REG_PWM[nr],
+                       it87_write_value(data, data->REG_PWM[nr],
                                         data->pwm_ctrl[nr]);
                }
        }
@@ -1562,7 +1618,7 @@ static ssize_t set_pwm_temp_map(struct device *dev,
        if (data->pwm_ctrl[nr] & 0x80) {
                data->pwm_ctrl[nr] = (data->pwm_ctrl[nr] & 0xfc) |
                                                data->pwm_temp_map[nr];
-               it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]);
+               it87_write_value(data, data->REG_PWM[nr], data->pwm_ctrl[nr]);
        }
        mutex_unlock(&data->update_lock);
        return count;
@@ -2115,9 +2171,9 @@ static struct attribute *it87_attributes_in[] = {
 
        &sensor_dev_attr_in8_input.dev_attr.attr,       /* 40 */
        &sensor_dev_attr_in9_input.dev_attr.attr,       /* 41 */
-       &sensor_dev_attr_in10_input.dev_attr.attr,      /* 41 */
-       &sensor_dev_attr_in11_input.dev_attr.attr,      /* 41 */
-       &sensor_dev_attr_in12_input.dev_attr.attr,      /* 41 */
+       &sensor_dev_attr_in10_input.dev_attr.attr,      /* 42 */
+       &sensor_dev_attr_in11_input.dev_attr.attr,      /* 43 */
+       &sensor_dev_attr_in12_input.dev_attr.attr,      /* 44 */
        NULL
 };
 
@@ -2534,6 +2590,12 @@ static int __init it87_find(int sioaddr, unsigned short *address,
        case IT8628E_DEVID:
                sio_data->type = it8628;
                break;
+       case IT8655E_DEVID:
+               sio_data->type = it8655;
+               break;
+       case IT8665E_DEVID:
+               sio_data->type = it8665;
+               break;
        case IT8686E_DEVID:
                sio_data->type = it8686;
                break;
@@ -2731,10 +2793,14 @@ static int __init it87_find(int sioaddr, unsigned short *address,
 
                /* Check if AVCC is on VIN3 */
                reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG);
-               if (reg & BIT(0))
-                       sio_data->internal |= BIT(0);
-               else
+               if (reg & BIT(0)) {
+                       /* For it8686, the bit just enables AVCC3 */
+                       if (sio_data->type != it8686)
+                               sio_data->internal |= BIT(0);
+               } else {
+                       sio_data->internal &= ~BIT(3);
                        sio_data->skip_in |= BIT(9);
+               }
 
                sio_data->beep_pin = superio_inb(sioaddr,
                                                 IT87_SIO_BEEP_PIN_REG) & 0x3f;
@@ -2801,6 +2867,72 @@ static int __init it87_find(int sioaddr, unsigned short *address,
                if (reg & BIT(0))
                        sio_data->internal |= BIT(0);
 
+               sio_data->beep_pin = superio_inb(sioaddr,
+                                                IT87_SIO_BEEP_PIN_REG) & 0x3f;
+       } else if (sio_data->type == it8655) {
+               int reg;
+
+               superio_select(sioaddr, GPIO);
+
+               /* Check for pwm2 */
+               reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+               if (reg & BIT(1))
+                       sio_data->skip_pwm |= BIT(1);
+
+               /* Check for fan2 */
+               reg = superio_inb(sioaddr, IT87_SIO_PINX4_REG);
+               if (reg & BIT(4))
+                       sio_data->skip_fan |= BIT(1);
+
+               /* Check for pwm3, fan3 */
+               reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
+               if (reg & BIT(6))
+                       sio_data->skip_pwm |= BIT(2);
+               if (reg & BIT(7))
+                       sio_data->skip_fan |= BIT(2);
+
+               sio_data->beep_pin = superio_inb(sioaddr,
+                                                IT87_SIO_BEEP_PIN_REG) & 0x3f;
+       } else if (sio_data->type == it8665) {
+               int reg;
+
+               superio_select(sioaddr, GPIO);
+
+               /* Check for pwm2 */
+               reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+               if (reg & BIT(1))
+                       sio_data->skip_pwm |= BIT(1);
+
+               /* Check for fan2 */
+               reg = superio_inb(sioaddr, IT87_SIO_PINX4_REG);
+               if (reg & BIT(4))
+                       sio_data->skip_fan |= BIT(1);
+
+               /* Check for pwm3, fan3 */
+               reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
+               if (reg & BIT(6))
+                       sio_data->skip_pwm |= BIT(2);
+               if (reg & BIT(7))
+                       sio_data->skip_fan |= BIT(2);
+
+               /* Check for pwm5, fan5 */
+               reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG);
+               if (reg & BIT(5))
+                       sio_data->skip_pwm |= BIT(4);
+               if (!(reg & BIT(4)))
+                       sio_data->skip_fan |= BIT(4);
+
+               /* Check for pwm4, fan4, pwm6, fan6 */
+               reg = superio_inb(sioaddr, IT87_SIO_GPIO9_REG);
+               if (reg & BIT(2))
+                       sio_data->skip_pwm |= BIT(3);
+               if (reg & BIT(3))
+                       sio_data->skip_fan |= BIT(3);
+               if (reg & BIT(0))
+                       sio_data->skip_pwm |= BIT(5);
+               if (reg & BIT(1))
+                       sio_data->skip_fan |= BIT(5);
+
                sio_data->beep_pin = superio_inb(sioaddr,
                                                 IT87_SIO_BEEP_PIN_REG) & 0x3f;
        } else {
@@ -2939,6 +3071,32 @@ static void it87_init_device(struct platform_device *pdev)
        int tmp, i;
        u8 mask;
 
+       /* Initialize chip specific register pointers */
+       switch (data->type) {
+       case it8655:
+       case it8665:
+               data->REG_FAN = IT87_REG_FAN_8665;
+               data->REG_FANX = IT87_REG_FANX_8665;
+               data->REG_FAN_MIN = IT87_REG_FAN_MIN_8665;
+               data->REG_FANX_MIN = IT87_REG_FANX_MIN_8665;
+               data->REG_PWM = IT87_REG_PWM_8665;
+               break;
+       case it8622:
+               data->REG_FAN = IT87_REG_FAN;
+               data->REG_FANX = IT87_REG_FANX;
+               data->REG_FAN_MIN = IT87_REG_FAN_MIN;
+               data->REG_FANX_MIN = IT87_REG_FANX_MIN;
+               data->REG_PWM = IT87_REG_PWM_8665;
+               break;
+       default:
+               data->REG_FAN = IT87_REG_FAN;
+               data->REG_FANX = IT87_REG_FANX;
+               data->REG_FAN_MIN = IT87_REG_FAN_MIN;
+               data->REG_FANX_MIN = IT87_REG_FANX_MIN;
+               data->REG_PWM = IT87_REG_PWM;
+               break;
+       }
+
        /*
         * For each PWM channel:
         * - If it is in automatic mode, setting to manual mode should set
@@ -3018,20 +3176,39 @@ static void it87_init_device(struct platform_device *pdev)
                data->has_fan |= BIT(3); /* fan4 enabled */
        if (has_five_fans(data) && (tmp & BIT(5)))
                data->has_fan |= BIT(4); /* fan5 enabled */
-       if (!has_fan16_config(data) && has_six_fans(data) && (tmp & BIT(2)))
-               data->has_fan |= BIT(5); /* fan6 enabled */
+       if (has_six_fans(data)) {
+               switch (data->type) {
+               case it8620:
+               case it8628:
+               case it8686:
+                       if (tmp & BIT(2))
+                               data->has_fan |= BIT(5); /* fan6 enabled */
+                       break;
+               case it8665:
+                       tmp = it87_read_value(data, IT87_REG_FAN_DIV);
+                       if (tmp & BIT(3))
+                               data->has_fan |= BIT(5); /* fan6 enabled */
+                       break;
+               default:
+                       break;
+               }
+       }
 
        /* Fan input pins may be used for alternative functions */
        data->has_fan &= ~sio_data->skip_fan;
 
-       /* Check if pwm5, pwm6 are enabled */
+       /* Check if pwm6 is enabled */
        if (has_six_pwm(data)) {
-               /* The following code may be IT8620E specific */
-               tmp = it87_read_value(data, IT87_REG_FAN_DIV);
-               if ((tmp & 0xc0) == 0xc0)
-                       sio_data->skip_pwm |= BIT(4);
-               if (!(tmp & BIT(3)))
-                       sio_data->skip_pwm |= BIT(5);
+               switch (data->type) {
+               case it8620:
+               case it8686:
+                       tmp = it87_read_value(data, IT87_REG_FAN_DIV);
+                       if (!(tmp & BIT(3)))
+                               sio_data->skip_pwm |= BIT(5);
+                       break;
+               default:
+                       break;
+               }
        }
 
        /* Start monitoring */
@@ -3063,7 +3240,7 @@ static int it87_check_pwm(struct device *dev)
 
                        for (i = 0; i < ARRAY_SIZE(pwm); i++)
                                pwm[i] = it87_read_value(data,
-                                                        IT87_REG_PWM[i]);
+                                                        data->REG_PWM[i]);
 
                        /*
                         * If any fan is in automatic pwm mode, the polarity
@@ -3078,7 +3255,7 @@ static int it87_check_pwm(struct device *dev)
                                                 tmp | 0x87);
                                for (i = 0; i < 3; i++)
                                        it87_write_value(data,
-                                                        IT87_REG_PWM[i],
+                                                        data->REG_PWM[i],
                                                         0x7f & ~pwm[i]);
                                return 1;
                        }
@@ -3163,7 +3340,7 @@ static int it87_probe(struct platform_device *pdev)
        enable_pwm_interface = it87_check_pwm(dev);
 
        /* Starting with IT8721F, we handle scaling of internal voltages */
-       if (has_12mv_adc(data)) {
+       if (has_scaling(data)) {
                if (sio_data->internal & BIT(0))
                        data->in_scaled |= BIT(3);      /* in3 is AVCC */
                if (sio_data->internal & BIT(1))