]> git.sur5r.net Git - groeck-it87/blobdiff - it87.c
Experimental support for IT8607E
[groeck-it87] / it87.c
diff --git a/it87.c b/it87.c
index fb5fdcddd5adaee2a2a7ee8efa9308bbcd847a5f..3be865a6702e9cc4b134de1d38bdd74cba574200 100644 (file)
--- a/it87.c
+++ b/it87.c
@@ -11,7 +11,9 @@
  *  similar parts.  The other devices are supported by different drivers.
  *
  *  Supports: IT8603E  Super I/O chip w/LPC interface
+ *            IT8607E  Super I/O chip w/LPC interface
  *            IT8620E  Super I/O chip w/LPC interface
+ *            IT8622E  Super I/O chip w/LPC interface
  *            IT8623E  Super I/O chip w/LPC interface
  *            IT8628E  Super I/O chip w/LPC interface
  *            IT8705F  Super I/O chip w/LPC interface
@@ -31,6 +33,7 @@
  *            IT8783E/F Super I/O chip w/LPC interface
  *            IT8786E  Super I/O chip w/LPC interface
  *            IT8790E  Super I/O chip w/LPC interface
+ *            IT8792E  Super I/O chip w/LPC interface
  *            Sis950   A clone of the IT8705F
  *
  *  Copyright (C) 2001 Chris Gauthron
@@ -70,8 +73,8 @@
 #define DRVNAME "it87"
 
 enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732,
-            it8771, it8772, it8781, it8782, it8783, it8786, it8790, it8603,
-            it8620, it8628 };
+            it8771, it8772, it8781, it8782, it8783, it8786, it8790,
+            it8792, it8603, it8607, it8620, it8622, it8628 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -152,6 +155,7 @@ static inline void superio_exit(int ioreg)
 #define IT8726F_DEVID 0x8726
 #define IT8728F_DEVID 0x8728
 #define IT8732F_DEVID 0x8732
+#define IT8792E_DEVID 0x8733
 #define IT8771E_DEVID 0x8771
 #define IT8772E_DEVID 0x8772
 #define IT8781F_DEVID 0x8781
@@ -160,7 +164,9 @@ static inline void superio_exit(int ioreg)
 #define IT8786E_DEVID 0x8786
 #define IT8790E_DEVID 0x8790
 #define IT8603E_DEVID 0x8603
+#define IT8607E_DEVID 0x8607
 #define IT8620E_DEVID 0x8620
+#define IT8622E_DEVID 0x8622
 #define IT8623E_DEVID 0x8623
 #define IT8628E_DEVID 0x8628
 #define IT87_ACT_REG  0x30
@@ -294,9 +300,11 @@ struct it87_devices {
 #define FEAT_SIX_FANS          BIT(11) /* Supports six fans */
 #define FEAT_10_9MV_ADC                BIT(12)
 #define FEAT_AVCC3             BIT(13) /* Chip supports in9/AVCC3 */
-#define FEAT_SIX_PWM           BIT(14) /* Chip supports 6 pwm chn */
-#define FEAT_PWM_FREQ2         BIT(15) /* Separate pwm freq 2 */
-#define FEAT_SIX_TEMP          BIT(16) /* Up to 6 temp sensors */
+#define FEAT_FIVE_PWM          BIT(14) /* Chip supports 5 pwm chn */
+#define FEAT_SIX_PWM           BIT(15) /* Chip supports 6 pwm chn */
+#define FEAT_PWM_FREQ2         BIT(16) /* Separate pwm freq 2 */
+#define FEAT_SIX_TEMP          BIT(17) /* Up to 6 temp sensors */
+#define FEAT_VIN3_5V           BIT(18) /* VIN3 connected to +5V */
 
 static const struct it87_devices it87_devices[] = {
        [it87] = {
@@ -420,6 +428,15 @@ static const struct it87_devices it87_devices[] = {
                  | FEAT_PWM_FREQ2,
                .peci_mask = 0x07,
        },
+       [it8792] = {
+               .name = "it8792",
+               .suffix = "E",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
+                 | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL,
+               .peci_mask = 0x07,
+               .old_peci_mask = 0x02,  /* Actually reports PCH */
+       },
        [it8603] = {
                .name = "it8603",
                .suffix = "E",
@@ -428,13 +445,30 @@ static const struct it87_devices it87_devices[] = {
                  | FEAT_AVCC3 | FEAT_PWM_FREQ2,
                .peci_mask = 0x07,
        },
+       [it8607] = {
+               .name = "it8607",
+               .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,
+               .peci_mask = 0x07,
+       },
        [it8620] = {
                .name = "it8620",
                .suffix = "E",
                .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_VIN3_5V,
+               .peci_mask = 0x07,
+       },
+       [it8622] = {
+               .name = "it8622",
+               .suffix = "E",
+               .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,
                .peci_mask = 0x07,
        },
        [it8628] = {
@@ -443,7 +477,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_SIX_TEMP | FEAT_VIN3_5V,
                .peci_mask = 0x07,
        },
 };
@@ -466,9 +500,12 @@ static const struct it87_devices it87_devices[] = {
 #define has_in7_internal(data) ((data)->features & FEAT_IN7_INTERNAL)
 #define has_six_fans(data)     ((data)->features & FEAT_SIX_FANS)
 #define has_avcc3(data)                ((data)->features & FEAT_AVCC3)
+#define has_five_pwm(data)     ((data)->features & (FEAT_FIVE_PWM \
+                                                    | FEAT_SIX_PWM))
 #define has_six_pwm(data)      ((data)->features & FEAT_SIX_PWM)
 #define has_pwm_freq2(data)    ((data)->features & FEAT_PWM_FREQ2)
 #define has_six_temp(data)     ((data)->features & FEAT_SIX_TEMP)
+#define has_vin3_5v(data)      ((data)->features & FEAT_VIN3_5V)
 
 struct it87_sio_data {
        enum chips type;
@@ -492,7 +529,7 @@ struct it87_sio_data {
 struct it87_data {
        const struct attribute_group *groups[7];
        enum chips type;
-       u16 features;
+       u32 features;
        u8 peci_mask;
        u8 old_peci_mask;
 
@@ -1076,14 +1113,13 @@ static int pwm_mode(const struct it87_data *data, int nr)
 {
        if (data->type != it8603 && nr < 3 && !(data->fan_main_ctrl & BIT(nr)))
                return 0;                               /* Full speed */
-       if (data->pwm_ctrl[nr] & 0x80) {
+       if (data->pwm_ctrl[nr] & 0x80)
                return 2;                               /* Automatic mode */
-       } else {
-               if ((data->type == it8603 || nr >= 3) &&
-                   data->pwm_duty[nr] == pwm_to_reg(data, 0xff))
-                       return 0;                       /* Full speed */
-               return 1;                               /* Manual mode */
-       }
+       if ((data->type == it8603 || nr >= 3) &&
+           data->pwm_duty[nr] == pwm_to_reg(data, 0xff))
+               return 0;                       /* Full speed */
+
+       return 1;                               /* Manual mode */
 }
 
 static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
@@ -1346,6 +1382,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
+       it87_update_pwm_ctrl(data, nr);
        if (has_newer_autopwm(data)) {
                /*
                 * If we are in automatic mode, the PWM duty cycle register
@@ -1458,6 +1495,7 @@ static ssize_t set_pwm_temp_map(struct device *dev,
        }
 
        mutex_lock(&data->update_lock);
+       it87_update_pwm_ctrl(data, nr);
        data->pwm_temp_map[nr] = reg;
        /*
         * If we are in automatic mode, write the temp mapping immediately;
@@ -1918,17 +1956,21 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
                "+5V",
                "5VSB",
                "Vbat",
+               "AVCC",
        };
        static const char * const labels_it8721[] = {
                "+3.3V",
                "3VSB",
                "Vbat",
+               "+3.3V",
        };
        struct it87_data *data = dev_get_drvdata(dev);
        int nr = to_sensor_dev_attr(attr)->index;
        const char *label;
 
-       if (has_12mv_adc(data) || has_10_9mv_adc(data))
+       if (has_vin3_5v(data) && nr == 0)
+               label = labels[0];
+       else if (has_12mv_adc(data) || has_10_9mv_adc(data))
                label = labels_it8721[nr];
        else
                label = labels[nr];
@@ -1939,7 +1981,7 @@ 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);
 /* AVCC3 */
-static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 3);
 
 static umode_t it87_in_is_visible(struct kobject *kobj,
                                  struct attribute *attr, int index)
@@ -2017,6 +2059,7 @@ static struct attribute *it87_attributes_in[] = {
        &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 */
+       NULL
 };
 
 static const struct attribute_group it87_group_in = {
@@ -2272,7 +2315,7 @@ static umode_t it87_auto_pwm_is_visible(struct kobject *kobj,
                        return 0;
        }
        if (has_old_autopwm(data)) {
-               if (a >= 9)     /* no pwm_auto_start, pwm_auto_slope */
+               if (a >= 9)     /* no pwm_auto_start, pwm_auto_slope */
                        return 0;
        }
 
@@ -2387,6 +2430,9 @@ static int __init it87_find(int sioaddr, unsigned short *address,
        case IT8732F_DEVID:
                sio_data->type = it8732;
                break;
+       case IT8792E_DEVID:
+               sio_data->type = it8792;
+               break;
        case IT8771E_DEVID:
                sio_data->type = it8771;
                break;
@@ -2412,9 +2458,15 @@ static int __init it87_find(int sioaddr, unsigned short *address,
        case IT8623E_DEVID:
                sio_data->type = it8603;
                break;
+       case IT8607E_DEVID:
+               sio_data->type = it8607;
+               break;
        case IT8620E_DEVID:
                sio_data->type = it8620;
                break;
+       case IT8622E_DEVID:
+               sio_data->type = it8622;
+               break;
        case IT8628E_DEVID:
                sio_data->type = it8628;
                break;
@@ -2458,8 +2510,10 @@ static int __init it87_find(int sioaddr, unsigned short *address,
        else
                sio_data->skip_in |= BIT(9);
 
-       if (!has_six_pwm(config))
+       if (!has_five_pwm(config))
                sio_data->skip_pwm |= BIT(3) | BIT(4) | BIT(5);
+       else if (!has_six_pwm(config))
+               sio_data->skip_pwm |= BIT(5);
 
        if (!has_vid(config))
                sio_data->skip_vid = 1;
@@ -2537,7 +2591,7 @@ static int __init it87_find(int sioaddr, unsigned short *address,
 
                sio_data->beep_pin = superio_inb(sioaddr,
                                                 IT87_SIO_BEEP_PIN_REG) & 0x3f;
-       } else if (sio_data->type == it8603) {
+       } else if (sio_data->type == it8603 || sio_data->type == it8607) {
                int reg27, reg29;
 
                superio_select(sioaddr, GPIO);
@@ -2557,8 +2611,10 @@ static int __init it87_find(int sioaddr, unsigned short *address,
                if (reg29 & BIT(2))
                        sio_data->skip_fan |= BIT(1);
 
-               sio_data->skip_in |= BIT(5); /* No VIN5 */
-               sio_data->skip_in |= BIT(6); /* No VIN6 */
+               if (sio_data->type == it8603) {
+                       sio_data->skip_in |= BIT(5); /* No VIN5 */
+                       sio_data->skip_in |= BIT(6); /* No VIN6 */
+               }
 
                sio_data->beep_pin = superio_inb(sioaddr,
                                                 IT87_SIO_BEEP_PIN_REG) & 0x3f;
@@ -2603,6 +2659,50 @@ static int __init it87_find(int sioaddr, unsigned short *address,
                        sio_data->skip_fan |= BIT(5);
                }
 
+               /* Check if AVCC is on VIN3 */
+               reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG);
+               if (reg & BIT(0))
+                       sio_data->internal |= BIT(0);
+               else
+                       sio_data->skip_in |= BIT(9);
+
+               sio_data->beep_pin = superio_inb(sioaddr,
+                                                IT87_SIO_BEEP_PIN_REG) & 0x3f;
+       } else if (sio_data->type == it8622) {
+               int reg;
+
+               superio_select(sioaddr, GPIO);
+
+               /* Check for pwm4, fan4 */
+               reg = superio_inb(sioaddr, IT87_SIO_GPIO1_REG);
+               if (reg & BIT(6))
+                       sio_data->skip_fan |= BIT(3);
+               if (reg & BIT(5))
+                       sio_data->skip_pwm |= BIT(3);
+
+               /* Check for pwm3, fan3, pwm5, fan5 */
+               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);
+               if (reg & BIT(3))
+                       sio_data->skip_pwm |= BIT(4);
+               if (reg & BIT(1))
+                       sio_data->skip_fan |= BIT(4);
+
+               /* Check for pwm2, fan2 */
+               reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+               if (reg & BIT(1))
+                       sio_data->skip_pwm |= BIT(1);
+               if (reg & BIT(2))
+                       sio_data->skip_fan |= BIT(1);
+
+               /* Check for AVCC */
+               reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG);
+               if (!(reg & BIT(0)))
+                       sio_data->skip_in |= BIT(9);
+
                sio_data->beep_pin = superio_inb(sioaddr,
                                                 IT87_SIO_BEEP_PIN_REG) & 0x3f;
        } else {