Index: linux-6.1.95-rt34/drivers/hwmon/it87.c =================================================================== --- linux-6.1.95-rt34.orig/drivers/hwmon/it87.c +++ linux-6.1.95-rt34/drivers/hwmon/it87.c @@ -12,6 +12,7 @@ * similar parts. The other devices are supported by different drivers. * * Supports: IT8603E 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 @@ -63,7 +64,7 @@ enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732, it8771, it8772, it8781, it8782, it8783, it8786, it8790, - it8792, it8603, it8620, it8622, it8628 }; + it8792, it8603, it8613, it8620, it8622, it8628 }; static unsigned short force_id; module_param(force_id, ushort, 0); @@ -153,6 +154,7 @@ static inline void superio_exit(int iore #define IT8786E_DEVID 0x8786 #define IT8790E_DEVID 0x8790 #define IT8603E_DEVID 0x8603 +#define IT8613E_DEVID 0x8613 #define IT8620E_DEVID 0x8620 #define IT8622E_DEVID 0x8622 #define IT8623E_DEVID 0x8623 @@ -205,14 +207,14 @@ static bool fix_pwm_polarity; * The IT8718F and IT8720F have the VID value in a different register, in * Super-I/O configuration space. */ -#define IT87_REG_VID 0x0a +#define IT87_REG_VID 0x0a /* * The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b * for fan divisors. Later IT8712F revisions must use 16-bit tachometer * mode. */ -#define IT87_REG_FAN_DIV 0x0b -#define IT87_REG_FAN_16BIT 0x0c +#define IT87_REG_FAN_DIV 0x0b +#define IT87_REG_FAN_16BIT 0x0c /* * Monitors: @@ -433,6 +435,15 @@ static const struct it87_devices it87_de | FEAT_AVCC3 | FEAT_PWM_FREQ2, .peci_mask = 0x07, }, + [it8613] = { + .name = "it8613", + .suffix = "E", + .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS + | FEAT_TEMP_PECI | FEAT_FIVE_FANS + | FEAT_FIVE_PWM | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 + | FEAT_AVCC3, + .peci_mask = 0x07, + }, [it8620] = { .name = "it8620", .suffix = "E", @@ -575,6 +586,8 @@ static int adc_lsb(const struct it87_dat lsb = 109; else lsb = 160; + if (data->type == it8613) + lsb = 110; if (data->in_scaled & BIT(nr)) lsb <<= 1; return lsb; @@ -2455,6 +2468,9 @@ static int __init it87_find(int sioaddr, case IT8623E_DEVID: sio_data->type = it8603; break; + case IT8613E_DEVID: + sio_data->type = it8613; + break; case IT8620E_DEVID: sio_data->type = it8620; break; @@ -2519,6 +2535,48 @@ static int __init it87_find(int sioaddr, superio_select(sioaddr, 5); sio_data->beep_pin = superio_inb(sioaddr, IT87_SIO_BEEP_PIN_REG) & 0x3f; + } else if (sio_data->type == it8613) { + int reg27, reg29, reg2a; + int reg25, reg26, reg28; + + 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; + reg25 = superio_inb(sioaddr, IT87_SIO_GPIO1_REG); + reg26 = superio_inb(sioaddr, IT87_SIO_GPIO2_REG); + reg28 = superio_inb(sioaddr, IT87_SIO_GPIO4_REG); + } else if (sio_data->type == it8783) { int reg25, reg27, reg2a, reg2c, regef; @@ -3041,6 +3099,7 @@ static int it87_probe(struct platform_de struct it87_sio_data *sio_data = dev_get_platdata(dev); int enable_pwm_interface; struct device *hwmon_dev; + int config, chipid; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, @@ -3052,8 +3111,10 @@ static int it87_probe(struct platform_de } data = devm_kzalloc(&pdev->dev, sizeof(struct it87_data), GFP_KERNEL); - if (!data) + if (!data) { + dev_err(dev, "Failed to get %lu Bytes of kernel memory\n", sizeof(struct it87_data)); return -ENOMEM; + } data->addr = res->start; data->sioaddr = sio_data->sioaddr; @@ -3085,9 +3146,23 @@ static int it87_probe(struct platform_de } /* Now, we do the remaining detection. */ - if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) || - it87_read_value(data, IT87_REG_CHIPID) != 0x90) + config = it87_read_value(data, IT87_REG_CONFIG); + if (config & 0x80) { + pr_err("Device must not have IT87_REG_CONFIG (0x%02x) bit 7 set\n", config); return -ENODEV; + } + chipid = it87_read_value(data, IT87_REG_CHIPID); + if (sio_data->type == it8613) { + if (chipid != 0x7f && chipid != 0x90) { + pr_err("IT87_REG_CHIPID (0x%02x) must be 0x7f or 0x90\n", chipid); + return -ENODEV; + } + } else { + if (chipid != 0x90) { + pr_err("IT87_REG_CHIPID (0x%02x) must be 0x90\n", chipid); + return -ENODEV; + } + } platform_set_drvdata(pdev, data);