]> git.sur5r.net Git - groeck-it87/blobdiff - it87.c
Separate internal scaling from 12mV ADC
[groeck-it87] / it87.c
diff --git a/it87.c b/it87.c
index 5a96c5c879ba2ad54954970859f86ac153914cb1..5b07d009d76278c92872e9a13c60a5008fc10e7f 100644 (file)
--- a/it87.c
+++ b/it87.c
@@ -16,6 +16,7 @@
  *            IT8622E  Super I/O chip w/LPC interface
  *            IT8623E  Super I/O chip w/LPC interface
  *            IT8628E  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
  *            IT8716F  Super I/O chip w/LPC interface
@@ -74,7 +75,7 @@
 
 enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732,
             it8771, it8772, it8781, it8782, it8783, it8786, it8790,
-            it8792, it8603, it8607, it8620, it8622, it8628 };
+            it8792, it8603, it8607, it8620, it8622, it8628, it8686 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -169,6 +170,7 @@ static inline void superio_exit(int ioreg)
 #define IT8622E_DEVID 0x8622
 #define IT8623E_DEVID 0x8623
 #define IT8628E_DEVID 0x8628
+#define IT8686E_DEVID 0x8686
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
@@ -213,6 +215,8 @@ static bool fix_pwm_polarity;
 #define IT87_REG_ALARM2        0x02
 #define IT87_REG_ALARM3        0x03
 
+#define IT87_REG_BANK          0x06
+
 /*
  * The IT8718F and IT8720F have the VID value in a different register, in
  * Super-I/O configuration space.
@@ -307,6 +311,8 @@ struct it87_devices {
 #define FEAT_VIN3_5V           BIT(18) /* VIN3 connected to +5V */
 #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 */
 
 static const struct it87_devices it87_devices[] = {
        [it87] = {
@@ -348,7 +354,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,
                .peci_mask = 0x05,
                .old_peci_mask = 0x02,  /* Actually reports PCH */
        },
@@ -357,7 +363,7 @@ 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,
                .peci_mask = 0x07,
        },
        [it8732] = {
@@ -375,7 +381,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,
                                /* PECI: guesswork */
                                /* 12mV ADC (OHM) */
                                /* 16 bit fans (OHM) */
@@ -387,7 +393,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,
                                /* PECI (coreboot) */
                                /* 12mV ADC (HWSensors4, OHM) */
                                /* 16 bit fans (HWSensors4, OHM) */
@@ -426,17 +432,17 @@ static const struct it87_devices it87_devices[] = {
        [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,
                .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,
                .peci_mask = 0x07,
        },
        [it8603] = {
@@ -444,7 +450,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] = {
@@ -452,7 +458,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,
        },
        [it8620] = {
@@ -461,7 +467,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_VIN3_5V,
+                 | FEAT_SIX_TEMP | FEAT_VIN3_5V | FEAT_SCALING,
                .peci_mask = 0x07,
        },
        [it8622] = {
@@ -470,7 +476,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] = {
@@ -479,7 +485,16 @@ 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_SCALING,
+               .peci_mask = 0x07,
+       },
+       [it8686] = {
+               .name = "it8686",
+               .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_BANK_SEL | FEAT_SCALING,
                .peci_mask = 0x07,
        },
 };
@@ -514,6 +529,8 @@ static const struct it87_devices it87_devices[] = {
 #define has_four_pwm(data)     ((data)->features & (FEAT_FOUR_PWM | \
                                                     FEAT_FIVE_PWM \
                                                     | FEAT_SIX_PWM))
+#define has_bank_sel(data)     ((data)->features & FEAT_BANK_SEL)
+#define has_scaling(data)      ((data)->features & FEAT_SCALING)
 
 struct it87_sio_data {
        enum chips type;
@@ -538,6 +555,7 @@ struct it87_data {
        const struct attribute_group *groups[7];
        enum chips type;
        u32 features;
+       u8 bank;
        u8 peci_mask;
        u8 old_peci_mask;
 
@@ -686,15 +704,39 @@ static const unsigned int pwm_freq[8] = {
        750000,
 };
 
+static int _it87_read_value(struct it87_data *data, u8 reg)
+{
+       outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
+       return inb_p(data->addr + IT87_DATA_REG_OFFSET);
+}
+
+static void _it87_write_value(struct it87_data *data, u8 reg, u8 value)
+{
+       outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
+       outb_p(value, data->addr + IT87_DATA_REG_OFFSET);
+}
+
+static void it87_set_bank(struct it87_data *data, u8 bank)
+{
+       if (has_bank_sel(data) && bank != data->bank) {
+               u8 breg = _it87_read_value(data, IT87_REG_BANK);
+
+               breg &= 0x1f;
+               breg |= (bank << 5);
+               data->bank = bank;
+               _it87_write_value(data, IT87_REG_BANK, breg);
+       }
+}
+
 /*
  * Must be called with data->update_lock held, except during initialization.
  * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
  * would slow down the IT87 access and should not be necessary.
  */
-static int it87_read_value(struct it87_data *data, u8 reg)
+static int it87_read_value(struct it87_data *data, u16 reg)
 {
-       outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
-       return inb_p(data->addr + IT87_DATA_REG_OFFSET);
+       it87_set_bank(data, reg >> 8);
+       return _it87_read_value(data, reg & 0xff);
 }
 
 /*
@@ -702,10 +744,10 @@ static int it87_read_value(struct it87_data *data, u8 reg)
  * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
  * would slow down the IT87 access and should not be necessary.
  */
-static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
+static void it87_write_value(struct it87_data *data, u16 reg, u8 value)
 {
-       outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
-       outb_p(value, data->addr + IT87_DATA_REG_OFFSET);
+       it87_set_bank(data, reg >> 8);
+       _it87_write_value(data, reg & 0xff, value);
 }
 
 static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
@@ -2494,6 +2536,9 @@ static int __init it87_find(int sioaddr, unsigned short *address,
        case IT8628E_DEVID:
                sio_data->type = it8628;
                break;
+       case IT8686E_DEVID:
+               sio_data->type = it8686;
+               break;
        case 0xffff:    /* No device at all */
                goto exit;
        default:
@@ -2644,7 +2689,8 @@ 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 == it8620 || sio_data->type == it8628) {
+       } else if (sio_data->type == it8620 || sio_data->type == it8628 ||
+                  sio_data->type == it8686) {
                int reg;
 
                superio_select(sioaddr, GPIO);
@@ -3081,6 +3127,8 @@ static int it87_probe(struct platform_device *pdev)
        data->features = it87_devices[sio_data->type].features;
        data->peci_mask = it87_devices[sio_data->type].peci_mask;
        data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask;
+       data->bank = 0xff;
+
        /*
         * IT8705F Datasheet 0.4.1, 3h == Version G.
         * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
@@ -3117,7 +3165,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))