]> git.sur5r.net Git - groeck-it87/blobdiff - it87.c
Provide blacklist module parameter to override blacklist.
[groeck-it87] / it87.c
diff --git a/it87.c b/it87.c
index 21e5724409cacdd3986e7df3249bfa0cf247b7ce..930b81ed77163036de6627228807a6a4c780b08f 100644 (file)
--- a/it87.c
+++ b/it87.c
  *
  *  Supports: IT8603E  Super I/O chip w/LPC interface
  *            IT8607E  Super I/O chip w/LPC interface
+ *            IT8613E  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
+ *            IT8625E  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
 
 enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732,
             it8771, it8772, it8781, it8782, it8783, it8786, it8790,
-            it8792, it8603, it8607, it8620, it8622, it8628, it8655, it8665,
-            it8686 };
+            it8792, it8603, it8607, it8613, it8620, it8622, it8625, it8628,
+            it8655, it8665, it8686 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
+static unsigned short blacklist = 1;
+module_param(blacklist, ushort, 0);
+MODULE_PARM_DESC(blacklist,
+                "Enable/disable blacklist (1=enable, 0=disable, default 1)");
+
 static struct platform_device *it87_pdev[2];
 static bool it87_sio4e_broken;
 #ifdef __IT87_USE_ACPI_MUTEX
@@ -210,9 +217,11 @@ static inline void superio_exit(int ioreg)
 #define IT8790E_DEVID 0x8790
 #define IT8603E_DEVID 0x8603
 #define IT8607E_DEVID 0x8607
+#define IT8613E_DEVID 0x8613
 #define IT8620E_DEVID 0x8620
 #define IT8622E_DEVID 0x8622
 #define IT8623E_DEVID 0x8623
+#define IT8625E_DEVID 0x8625
 #define IT8628E_DEVID 0x8628
 #define IT8655E_DEVID 0x8655
 #define IT8665E_DEVID 0x8665
@@ -384,6 +393,7 @@ struct it87_devices {
 #define FEAT_SCALING           BIT(22) /* Internal voltage scaling */
 #define FEAT_FANCTL_ONOFF      BIT(23) /* chip has FAN_CTL ON/OFF */
 #define FEAT_11MV_ADC          BIT(24)
+#define FEAT_NEW_TEMPMAP       BIT(25) /* new temp input selection */
 
 static const struct it87_devices it87_devices[] = {
        [it87] = {
@@ -557,6 +567,16 @@ static const struct it87_devices it87_devices[] = {
                .num_temp_limit = 3,
                .peci_mask = 0x07,
        },
+       [it8613] = {
+               .name = "it8613",
+               .suffix = "E",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_11MV_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_SCALING | FEAT_NEW_TEMPMAP,
+               .num_temp_limit = 6,
+               .peci_mask = 0x07,
+       },
        [it8620] = {
                .name = "it8620",
                .suffix = "E",
@@ -578,6 +598,15 @@ static const struct it87_devices it87_devices[] = {
                .num_temp_limit = 3,
                .peci_mask = 0x07,
        },
+       [it8625] = {
+               .name = "it8625",
+               .suffix = "E",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_AVCC3 | FEAT_NEW_TEMPMAP
+                 | FEAT_11MV_ADC | FEAT_IN7_INTERNAL | FEAT_SIX_FANS
+                 | FEAT_SIX_PWM | FEAT_BANK_SEL | FEAT_SCALING,
+               .num_temp_limit = 6,
+       },
        [it8628] = {
                .name = "it8628",
                .suffix = "E",
@@ -593,7 +622,7 @@ static const struct it87_devices it87_devices[] = {
                .name = "it8655",
                .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_AVCC3
+                 | FEAT_TEMP_OFFSET | FEAT_AVCC3 | FEAT_NEW_TEMPMAP
                  | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_BANK_SEL,
                .num_temp_limit = 6,
        },
@@ -601,7 +630,7 @@ static const struct it87_devices it87_devices[] = {
                .name = "it8665",
                .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_AVCC3
+                 | FEAT_TEMP_OFFSET | FEAT_AVCC3 | FEAT_NEW_TEMPMAP
                  | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_SIX_FANS
                  | FEAT_SIX_PWM | FEAT_BANK_SEL,
                .num_temp_limit = 6,
@@ -610,7 +639,7 @@ static const struct it87_devices it87_devices[] = {
                .name = "it8686",
                .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_SIX_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_SIX_FANS | FEAT_NEW_TEMPMAP
                  | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
                  | FEAT_SIX_TEMP | FEAT_BANK_SEL | FEAT_SCALING | FEAT_AVCC3,
                .num_temp_limit = 6,
@@ -651,6 +680,7 @@ static const struct it87_devices it87_devices[] = {
 #define has_scaling(data)      ((data)->features & FEAT_SCALING)
 #define has_fanctl_onoff(data) ((data)->features & FEAT_FANCTL_ONOFF)
 #define has_11mv_adc(data)     ((data)->features & FEAT_11MV_ADC)
+#define has_new_tempmap(data)  ((data)->features & FEAT_NEW_TEMPMAP)
 
 struct it87_sio_data {
        enum chips type;
@@ -888,7 +918,10 @@ static void it87_update_pwm_ctrl(struct it87_data *data, int 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;
+               if (has_new_tempmap(data))
+                       data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x38;
+               else
+                       data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
                data->pwm_duty[nr] = it87_read_value(data,
                                                     IT87_REG_PWM_DUTY[nr]);
        } else {
@@ -1266,6 +1299,9 @@ static int get_temp_type(struct it87_data *data, int index)
                                break;
                        }
                        break;
+               case it8625:
+                       if (index < 3)
+                               break;
                case it8655:
                case it8665:
                        if (src1 < 3) {
@@ -1739,10 +1775,16 @@ static ssize_t show_pwm_temp_map(struct device *dev,
        int map;
 
        map = data->pwm_temp_map[nr];
-       if (map >= 3)
-               map = 0;        /* Should never happen */
-       if (nr >= 3)            /* pwm channels 3..6 map to temp4..6 */
-               map += 3;
+       if (has_new_tempmap(data)) {
+               map >>= 3;
+               if (map >= 6)
+                       map = 0;        /* Should never happen */
+       } else {
+               if (map >= 3)
+                       map = 0;        /* Should never happen */
+               if (nr >= 3)            /* pwm channels 3..6 map to temp4..6 */
+                       map += 3;
+       }
 
        return sprintf(buf, "%d\n", (int)BIT(map));
 }
@@ -1760,7 +1802,7 @@ static ssize_t set_pwm_temp_map(struct device *dev,
        if (kstrtol(buf, 10, &val) < 0)
                return -EINVAL;
 
-       if (nr >= 3)
+       if (nr >= 3 && !has_new_tempmap(data))
                val -= 3;
 
        switch (val) {
@@ -1773,10 +1815,27 @@ static ssize_t set_pwm_temp_map(struct device *dev,
        case BIT(2):
                reg = 0x02;
                break;
+       case BIT(3):
+               reg = 0x03;
+               break;
+       case BIT(4):
+               reg = 0x04;
+               break;
+       case BIT(5):
+               reg = 0x05;
+               break;
+       case BIT(6):
+               reg = 0x06;
+               break;
        default:
                return -EINVAL;
        }
 
+       if (has_new_tempmap(data))
+               reg <<= 3;
+       else if (reg > 0x02)
+               return -EINVAL;
+
        mutex_lock(&data->update_lock);
        it87_update_pwm_ctrl(data, nr);
        data->pwm_temp_map[nr] = reg;
@@ -1785,7 +1844,9 @@ static ssize_t set_pwm_temp_map(struct device *dev,
         * otherwise, just store it for later use.
         */
        if (data->pwm_ctrl[nr] & 0x80) {
-               data->pwm_ctrl[nr] = (data->pwm_ctrl[nr] & 0xfc) |
+               u8 mask = has_new_tempmap(data) ? 0xc7 : 0xfc;
+
+               data->pwm_ctrl[nr] = (data->pwm_ctrl[nr] & mask) |
                                                data->pwm_temp_map[nr];
                it87_write_value(data, data->REG_PWM[nr], data->pwm_ctrl[nr]);
        }
@@ -2784,12 +2845,18 @@ static int __init it87_find(int sioaddr, unsigned short *address,
        case IT8607E_DEVID:
                sio_data->type = it8607;
                break;
+       case IT8613E_DEVID:
+               sio_data->type = it8613;
+               break;
        case IT8620E_DEVID:
                sio_data->type = it8620;
                break;
        case IT8622E_DEVID:
                sio_data->type = it8622;
                break;
+       case IT8625E_DEVID:
+               sio_data->type = it8625;
+               break;
        case IT8628E_DEVID:
                sio_data->type = it8628;
                break;
@@ -2950,6 +3017,43 @@ static int __init it87_find(int sioaddr, unsigned short *address,
                        sio_data->skip_in |= BIT(6); /* No VIN6 */
                }
 
+               sio_data->beep_pin = superio_inb(sioaddr,
+                                                IT87_SIO_BEEP_PIN_REG) & 0x3f;
+       } else if (sio_data->type == it8613) {
+               int reg27, reg29, reg2a;
+
+               superio_select(sioaddr, GPIO);
+
+               /* Check for pwm3, fan3, pwm5, fan5 */
+               reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
+               if (reg27 & BIT(1))
+                       sio_data->skip_fan |= BIT(4);
+               if (reg27 & BIT(3))
+                       sio_data->skip_pwm |= BIT(4);
+               if (reg27 & BIT(6))
+                       sio_data->skip_pwm |= BIT(2);
+               if (reg27 & BIT(7))
+                       sio_data->skip_fan |= BIT(2);
+
+               /* Check for pwm2, fan2 */
+               reg29 = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+               if (reg29 & BIT(1))
+                       sio_data->skip_pwm |= BIT(1);
+               if (reg29 & BIT(2))
+                       sio_data->skip_fan |= BIT(1);
+
+               /* Check for pwm4, fan4 */
+               reg2a = superio_inb(sioaddr, IT87_SIO_PINX1_REG);
+               if (!(reg2a & BIT(0)) || (reg29 & BIT(7))) {
+                       sio_data->skip_fan |= BIT(3);
+                       sio_data->skip_pwm |= BIT(3);
+               }
+
+               sio_data->skip_pwm |= BIT(0); /* No pwm1 */
+               sio_data->skip_fan |= BIT(0); /* No fan1 */
+               sio_data->skip_in |= BIT(3);  /* No VIN3 */
+               sio_data->skip_in |= BIT(6);  /* No VIN6 */
+
                sio_data->beep_pin = superio_inb(sioaddr,
                                                 IT87_SIO_BEEP_PIN_REG) & 0x3f;
        } else if (sio_data->type == it8620 || sio_data->type == it8628 ||
@@ -3096,44 +3200,57 @@ 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 == it8665) {
-               int reg;
+       } else if (sio_data->type == it8665 || sio_data->type == it8625) {
+               int reg27, reg29, reg2d, regd3;
 
                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);
+               reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
+               reg29 = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+               reg2d = superio_inb(sioaddr, IT87_SIO_PINX4_REG);
+               regd3 = superio_inb(sioaddr, IT87_SIO_GPIO9_REG);
 
-               /* Check for fan2 */
-               reg = superio_inb(sioaddr, IT87_SIO_PINX4_REG);
-               if (reg & BIT(4))
+               /* Check for pwm2, fan2 */
+               if (reg29 & BIT(1))
+                       sio_data->skip_pwm |= BIT(1);
+               if (reg2d & BIT(4))
                        sio_data->skip_fan |= BIT(1);
 
                /* Check for pwm3, fan3 */
-               reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
-               if (reg & BIT(6))
+               if (reg27 & BIT(6))
                        sio_data->skip_pwm |= BIT(2);
-               if (reg & BIT(7))
+               if (reg27 & 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, pwm5, fan5 */
+               if (sio_data->type == it8625) {
+                       int reg25 = superio_inb(sioaddr, IT87_SIO_GPIO1_REG);
+
+                       if (reg25 & BIT(6))
+                               sio_data->skip_fan |= BIT(3);
+                       if (reg25 & BIT(5))
+                               sio_data->skip_pwm |= BIT(3);
+                       if (reg27 & BIT(3))
+                               sio_data->skip_pwm |= BIT(4);
+                       if (reg27 & BIT(1))
+                               sio_data->skip_fan |= BIT(4);
+               } else {
+                       int reg26 = superio_inb(sioaddr, IT87_SIO_GPIO2_REG);
+
+                       if (regd3 & BIT(2))
+                               sio_data->skip_pwm |= BIT(3);
+                       if (regd3 & BIT(3))
+                               sio_data->skip_fan |= BIT(3);
+                       if (reg26 & BIT(5))
+                               sio_data->skip_pwm |= BIT(4);
+                       if (!(reg26 & 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))
+               /* Check for pwm6, fan6 */
+               if (regd3 & BIT(0))
                        sio_data->skip_pwm |= BIT(5);
-               if (reg & BIT(1))
+               if (regd3 & BIT(1))
                        sio_data->skip_fan |= BIT(5);
 
                sio_data->beep_pin = superio_inb(sioaddr,
@@ -3247,13 +3364,9 @@ exit:
        return err;
 }
 
-/* Called when we have found a new IT87. */
-static void it87_init_device(struct platform_device *pdev)
+static void it87_init_regs(struct platform_device *pdev)
 {
-       struct it87_sio_data *sio_data = dev_get_platdata(&pdev->dev);
        struct it87_data *data = platform_get_drvdata(pdev);
-       int tmp, i;
-       u8 mask;
 
        /* Initialize chip specific register pointers */
        switch (data->type) {
@@ -3267,6 +3380,7 @@ static void it87_init_device(struct platform_device *pdev)
                data->REG_TEMP_LOW = IT87_REG_TEMP_LOW_8686;
                data->REG_TEMP_HIGH = IT87_REG_TEMP_HIGH_8686;
                break;
+       case it8625:
        case it8655:
        case it8665:
                data->REG_FAN = IT87_REG_FAN_8665;
@@ -3288,6 +3402,16 @@ static void it87_init_device(struct platform_device *pdev)
                data->REG_TEMP_LOW = IT87_REG_TEMP_LOW;
                data->REG_TEMP_HIGH = IT87_REG_TEMP_HIGH;
                break;
+       case it8613:
+               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;
+               data->REG_TEMP_OFFSET = IT87_REG_TEMP_OFFSET;
+               data->REG_TEMP_LOW = IT87_REG_TEMP_LOW;
+               data->REG_TEMP_HIGH = IT87_REG_TEMP_HIGH;
+               break;
        default:
                data->REG_FAN = IT87_REG_FAN;
                data->REG_FANX = IT87_REG_FANX;
@@ -3299,6 +3423,15 @@ static void it87_init_device(struct platform_device *pdev)
                data->REG_TEMP_HIGH = IT87_REG_TEMP_HIGH;
                break;
        }
+}
+
+/* Called when we have found a new IT87. */
+static void it87_init_device(struct platform_device *pdev)
+{
+       struct it87_sio_data *sio_data = dev_get_platdata(&pdev->dev);
+       struct it87_data *data = platform_get_drvdata(pdev);
+       int tmp, i;
+       u8 mask;
 
        /*
         * For each PWM channel:
@@ -3387,6 +3520,7 @@ static void it87_init_device(struct platform_device *pdev)
                        if (tmp & BIT(2))
                                data->has_fan |= BIT(5); /* fan6 enabled */
                        break;
+               case it8625:
                case it8665:
                        tmp = it87_read_value(data, IT87_REG_FAN_DIV);
                        if (tmp & BIT(3))
@@ -3540,6 +3674,9 @@ static int it87_probe(struct platform_device *pdev)
 
        mutex_init(&data->update_lock);
 
+       /* Initialize register pointers */
+       it87_init_regs(pdev);
+
        /* Check PWM configuration */
        enable_pwm_interface = it87_check_pwm(dev);
 
@@ -3685,7 +3822,7 @@ struct it87_dmi_data {
 };
 
 /*
- * On Gigabyte AB350 boards, accesses to the Super-IO chip
+ * On Gigabyte AB350 and AX370 boards, accesses to the Super-IO chip
  * at address 0x4e/0x4f can result in a system hang.
  * Accesses to address 0x2e/0x2f need to be mutex protected.
  */
@@ -3721,6 +3858,27 @@ static const struct dmi_system_id it87_dmi_table[] __initconst = {
                },
                .driver_data = &gigabyte_ab350_gaming,
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Gigabyte Technology Co., Ltd."),
+                       DMI_MATCH(DMI_BOARD_NAME, "AB350M-D3H-CF"),
+               },
+               .driver_data = &gigabyte_ab350_gaming,
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Gigabyte Technology Co., Ltd."),
+                       DMI_MATCH(DMI_BOARD_NAME, "AX370-Gaming K7"),
+               },
+               .driver_data = &gigabyte_ab350_gaming,
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Gigabyte Technology Co., Ltd."),
+                       DMI_MATCH(DMI_BOARD_NAME, "AX370-Gaming 5"),
+               },
+               .driver_data = &gigabyte_ab350_gaming,
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "nVIDIA"),
@@ -3770,10 +3928,10 @@ static int __init sm_it87_init(void)
 
        for (i = 0; i < ARRAY_SIZE(sioaddr); i++) {
                /*
-                * Accessing the second Super-IO chi can result in board
+                * Accessing the second Super-IO chip can result in board
                 * hangs. Disable until we figure out what is going on.
                 */
-               if (it87_sio4e_broken && sioaddr[i] == 0x4e)
+               if (blacklist && it87_sio4e_broken && sioaddr[i] == 0x4e)
                        continue;
                memset(&sio_data, 0, sizeof(struct it87_sio_data));
                isa_address = 0;