*
* 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
#define DRVNAME "it87"
-/* Necessary API not (yet) exported in upstream kernel */
-/* #define __IT87_USE_ACPI_MUTEX */
-
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 struct platform_device *it87_pdev[2];
-static bool it87_sio4e_broken;
-#ifdef __IT87_USE_ACPI_MUTEX
-static acpi_handle it87_acpi_sio_handle;
-static char *it87_acpi_sio_mutex;
-#endif
#define REG_2E 0x2e /* The register to read/write */
#define REG_4E 0x4e /* Secondary register to read/write */
outb(reg, ioreg);
val = inb(ioreg + 1);
- if (it87_sio4e_broken && ioreg == 0x4e && val == 0xff) {
- __superio_enter(ioreg);
- outb(reg, ioreg);
- val = inb(ioreg + 1);
- pr_warn("Retry access 0x4e:0x%x -> 0x%x\n", reg, val);
- }
return val;
}
static inline int superio_enter(int ioreg)
{
-#ifdef __IT87_USE_ACPI_MUTEX
- if (it87_acpi_sio_mutex) {
- acpi_status status;
-
- status = acpi_acquire_mutex(NULL, it87_acpi_sio_mutex, 0x10);
- if (ACPI_FAILURE(status)) {
- pr_err("Failed to acquire ACPI mutex\n");
- return -EBUSY;
- }
- }
-#endif
/*
* Try to reserve ioreg and ioreg + 1 for exclusive access.
*/
return 0;
error:
-#ifdef __IT87_USE_ACPI_MUTEX
- if (it87_acpi_sio_mutex)
- acpi_release_mutex(it87_acpi_sio_handle, NULL);
-#endif
return -EBUSY;
}
-static inline void superio_exit(int ioreg)
+static inline void superio_exit(int ioreg, bool doexit)
{
- if (!it87_sio4e_broken || ioreg != 0x4e) {
+ if (doexit) {
outb(0x02, ioreg);
outb(0x02, ioreg + 1);
}
release_region(ioreg, 2);
-#ifdef __IT87_USE_ACPI_MUTEX
- if (it87_acpi_sio_mutex)
- acpi_release_mutex(it87_acpi_sio_handle, NULL);
-#endif
}
/* Logical device 4 registers */
#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
const char * const suffix;
u32 features;
u8 num_temp_limit;
+ u8 num_temp_offset;
u8 peci_mask;
u8 old_peci_mask;
};
#define FEAT_NEWER_AUTOPWM BIT(1)
#define FEAT_OLD_AUTOPWM BIT(2)
#define FEAT_16BIT_FANS BIT(3)
-#define FEAT_TEMP_OFFSET BIT(4)
#define FEAT_TEMP_PECI BIT(5)
#define FEAT_TEMP_OLD_PECI BIT(6)
#define FEAT_FAN16_CONFIG BIT(7) /* Need to enable 16-bit fans */
#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 */
+#define FEAT_11MV_ADC BIT(24)
+#define FEAT_NEW_TEMPMAP BIT(25) /* new temp input selection */
static const struct it87_devices it87_devices[] = {
[it87] = {
.features = FEAT_OLD_AUTOPWM | FEAT_FANCTL_ONOFF,
/* may need to overwrite */
.num_temp_limit = 3,
+ .num_temp_offset = 0,
},
[it8712] = {
.name = "it8712",
.features = FEAT_OLD_AUTOPWM | FEAT_VID | FEAT_FANCTL_ONOFF,
/* may need to overwrite */
.num_temp_limit = 3,
+ .num_temp_offset = 0,
},
[it8716] = {
.name = "it8716",
.suffix = "F",
- .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
+ .features = FEAT_16BIT_FANS | FEAT_VID
| FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2
| FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
},
[it8718] = {
.name = "it8718",
.suffix = "F",
- .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
+ .features = FEAT_16BIT_FANS | FEAT_VID
| FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS
| FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.old_peci_mask = 0x4,
},
[it8720] = {
.name = "it8720",
.suffix = "F",
- .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
+ .features = FEAT_16BIT_FANS | FEAT_VID
| FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS
| FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.old_peci_mask = 0x4,
},
[it8721] = {
.name = "it8721",
.suffix = "F",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
+ | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
| FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL
| FEAT_PWM_FREQ2 | FEAT_SCALING | FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.peci_mask = 0x05,
.old_peci_mask = 0x02, /* Actually reports PCH */
},
.name = "it8728",
.suffix = "F",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS
+ | FEAT_TEMP_PECI | FEAT_FIVE_FANS
| FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 | FEAT_SCALING
| FEAT_FANCTL_ONOFF,
- .num_temp_limit = 3,
+ .num_temp_limit = 6,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
},
[it8732] = {
.name = "it8732",
.suffix = "F",
.features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
+ | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
| FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FOUR_FANS
| FEAT_FOUR_PWM | FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
.old_peci_mask = 0x02, /* Actually reports PCH */
},
.name = "it8771",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+ | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
| FEAT_PWM_FREQ2 | FEAT_SCALING | FEAT_FANCTL_ONOFF,
/* PECI: guesswork */
/* 12mV ADC (OHM) */
/* 16 bit fans (OHM) */
/* three fans, always 16 bit (guesswork) */
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
},
[it8772] = {
.name = "it8772",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+ | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
| FEAT_PWM_FREQ2 | FEAT_SCALING | FEAT_FANCTL_ONOFF,
/* PECI (coreboot) */
/* 12mV ADC (HWSensors4, OHM) */
/* 16 bit fans (HWSensors4, OHM) */
/* three fans, always 16 bit (datasheet) */
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
},
[it8781] = {
.name = "it8781",
.suffix = "F",
- .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
+ .features = FEAT_16BIT_FANS
| FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
| FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.old_peci_mask = 0x4,
},
[it8782] = {
.name = "it8782",
.suffix = "F",
- .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
+ .features = FEAT_16BIT_FANS
| FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
| FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.old_peci_mask = 0x4,
},
[it8783] = {
.name = "it8783",
.suffix = "E/F",
- .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
+ .features = FEAT_16BIT_FANS
| FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
| FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.old_peci_mask = 0x4,
},
[it8786] = {
.name = "it8786",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+ | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
| FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
},
[it8790] = {
.name = "it8790",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_10_9MV_ADC | FEAT_SCALING
- | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI
+ | FEAT_16BIT_FANS | FEAT_TEMP_PECI
| FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
},
[it8792] = {
.name = "it8792",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_10_9MV_ADC | FEAT_SCALING
- | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI
+ | FEAT_16BIT_FANS | FEAT_TEMP_PECI
| FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
},
[it8603] = {
.name = "it8603",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+ | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
| FEAT_AVCC3 | FEAT_PWM_FREQ2 | FEAT_SCALING,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.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_TEMP_PECI | FEAT_IN7_INTERNAL
| FEAT_AVCC3 | FEAT_PWM_FREQ2 | FEAT_SCALING
| FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
+ .peci_mask = 0x07,
+ },
+ [it8613] = {
+ .name = "it8613",
+ .suffix = "E",
+ .features = FEAT_NEWER_AUTOPWM | FEAT_11MV_ADC | FEAT_16BIT_FANS
+ | 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,
+ .num_temp_offset = 6,
.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_TEMP_PECI | FEAT_SIX_FANS
| FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
| FEAT_SIX_TEMP | FEAT_VIN3_5V | FEAT_SCALING
| FEAT_FANCTL_ONOFF,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.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_TEMP_PECI | FEAT_FIVE_FANS
| FEAT_FIVE_PWM | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2
| FEAT_AVCC3 | FEAT_VIN3_5V | FEAT_SCALING,
.num_temp_limit = 3,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
},
+ [it8625] = {
+ .name = "it8625",
+ .suffix = "E",
+ .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
+ | 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,
+ .num_temp_offset = 6,
+ },
[it8628] = {
.name = "it8628",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
+ | FEAT_TEMP_PECI | FEAT_SIX_FANS
| FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
| FEAT_SIX_TEMP | FEAT_SCALING | FEAT_AVCC3
| FEAT_FANCTL_ONOFF,
- .num_temp_limit = 3,
+ .num_temp_limit = 6,
+ .num_temp_offset = 3,
.peci_mask = 0x07,
},
[it8655] = {
.name = "it8655",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_AVCC3
+ | FEAT_AVCC3 | FEAT_NEW_TEMPMAP
| FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_BANK_SEL,
.num_temp_limit = 6,
- .peci_mask = 0x07,
+ .num_temp_offset = 6,
},
[it8665] = {
.name = "it8665",
.suffix = "E",
.features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
- | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_AVCC3
+ | 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,
- .peci_mask = 0x07,
+ .num_temp_offset = 6,
},
[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_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,
- .peci_mask = 0x07,
+ .num_temp_offset = 6,
},
};
#define has_10_9mv_adc(data) ((data)->features & FEAT_10_9MV_ADC)
#define has_newer_autopwm(data) ((data)->features & FEAT_NEWER_AUTOPWM)
#define has_old_autopwm(data) ((data)->features & FEAT_OLD_AUTOPWM)
-#define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET)
#define has_temp_peci(data, nr) (((data)->features & FEAT_TEMP_PECI) && \
((data)->peci_mask & BIT(nr)))
#define has_temp_old_peci(data, nr) \
#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)
+#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;
u16 fan[NUM_FAN][2]; /* Register values, [nr][0]=fan, [1]=min */
u8 has_temp; /* Bitfield, temp sensors enabled */
s8 temp[NUM_TEMP][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */
- u8 num_temp_limit; /* Number of temp limit/offset registers */
+ u8 num_temp_limit; /* Number of temperature limit registers */
+ u8 num_temp_offset; /* Number of temperature offset registers */
u8 sensor; /* Register value (IT87_REG_TEMP_ENABLE) */
u8 extra; /* Register value (IT87_REG_TEMP_EXTRA) */
u8 fan_div[NUM_FAN_DIV];/* Register encoding, shifted right */
lsb = 120;
else if (has_10_9mv_adc(data))
lsb = 109;
+ else if (has_11mv_adc(data))
+ lsb = 110;
else
lsb = 160;
if (data->in_scaled & BIT(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 {
if (i >= data->num_temp_limit)
continue;
- if (has_temp_offset(data))
+ if (i < data->num_temp_offset)
data->temp[i][3] =
it87_read_value(data,
data->REG_TEMP_OFFSET[i]);
break;
}
break;
+ case it8625:
+ if (index < 3)
+ break;
case it8655:
case it8665:
if (src1 < 3) {
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));
}
if (kstrtol(buf, 10, &val) < 0)
return -EINVAL;
- if (nr >= 3)
+ if (nr >= 3 && !has_new_tempmap(data))
val -= 3;
switch (val) {
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;
* 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]);
}
if (has_vin3_5v(data) && nr == 0)
label = labels[0];
- else if (has_12mv_adc(data) || has_10_9mv_adc(data))
+ else if (has_12mv_adc(data) || has_10_9mv_adc(data) ||
+ has_11mv_adc(data))
label = labels_it8721[nr];
else
label = labels[nr];
return attr->mode;
}
- if (a == 5 && !has_temp_offset(data))
+ if (a == 5 && i >= data->num_temp_offset)
return 0;
if (a == 6 && !data->has_beep)
static int __init it87_find(int sioaddr, unsigned short *address,
struct it87_sio_data *sio_data)
{
- int err;
- u16 chip_type;
const struct it87_devices *config;
+ bool doexit = true;
+ u16 chip_type;
+ int err;
err = superio_enter(sioaddr);
if (err)
break;
case IT8792E_DEVID:
sio_data->type = it8792;
+ /*
+ * Disabling configuration mode on IT8792E can result in system
+ * hang-ups and access failures to the Super-IO chip at the
+ * second SIO address. Never exit configuration mode on this
+ * chip to avoid the problem.
+ */
+ doexit = false;
break;
case IT8771E_DEVID:
sio_data->type = it8771;
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;
if (reg29 & BIT(2))
sio_data->skip_fan |= BIT(1);
- if (sio_data->type == it8603) {
+ switch (sio_data->type) {
+ case it8603:
sio_data->skip_in |= BIT(5); /* No VIN5 */
sio_data->skip_in |= BIT(6); /* No VIN6 */
+ break;
+ case it8607:
+ sio_data->skip_pwm |= BIT(0);/* No fan1 */
+ sio_data->skip_fan |= BIT(0);
+ default:
+ break;
+ }
+
+ 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 ||
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,
pr_info("Beeping is supported\n");
exit:
- superio_exit(sioaddr);
+ superio_exit(sioaddr, doexit);
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) {
+ case it8628:
case it8686:
data->REG_FAN = IT87_REG_FAN;
data->REG_FANX = IT87_REG_FANX;
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;
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;
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:
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))
data->type = sio_data->type;
data->features = it87_devices[sio_data->type].features;
data->num_temp_limit = it87_devices[sio_data->type].num_temp_limit;
+ data->num_temp_offset = it87_devices[sio_data->type].num_temp_offset;
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;
mutex_init(&data->update_lock);
+ /* Initialize register pointers */
+ it87_init_regs(pdev);
+
/* Check PWM configuration */
enable_pwm_interface = it87_check_pwm(dev);
}
struct it87_dmi_data {
- bool sio4e_broken; /* SIO accesses @ 0x4e are broken */
- char *sio_mutex; /* SIO ACPI mutex */
u8 skip_pwm; /* pwm channels to skip for this board */
};
-/*
- * On Gigabyte AB350 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.
- */
-static struct it87_dmi_data gigabyte_ab350_gaming = {
- .sio4e_broken = true,
- .sio_mutex = "\\_SB.PCI0.SBRG.SIO1.MUT0",
-};
-
/*
* On the Shuttle SN68PT, FAN_CTL2 is apparently not
* connected to a fan, but to something else. One user
};
static const struct dmi_system_id it87_dmi_table[] __initconst = {
- {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Gigabyte Technology Co., Ltd."),
- DMI_MATCH(DMI_BOARD_NAME, "AB350-Gaming-CF"),
- },
- .driver_data = &gigabyte_ab350_gaming,
- },
- {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Gigabyte Technology Co., Ltd."),
- DMI_MATCH(DMI_BOARD_NAME, "AB350-Gaming 3-CF"),
- },
- .driver_data = &gigabyte_ab350_gaming,
- },
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "nVIDIA"),
if (dmi)
dmi_data = dmi->driver_data;
- if (dmi_data) {
- it87_sio4e_broken = dmi_data->sio4e_broken;
-#ifdef __IT87_USE_ACPI_MUTEX
- if (dmi_data->sio_mutex) {
- static acpi_status status;
-
- status = acpi_get_handle(NULL, dmi_data->sio_mutex,
- &it87_acpi_sio_handle);
- if (ACPI_SUCCESS(status)) {
- it87_acpi_sio_mutex = dmi_data->sio_mutex;
- pr_debug("Found ACPI SIO mutex %s\n",
- dmi_data->sio_mutex);
- } else {
- pr_warn("ACPI SIO mutex %s not found\n",
- dmi_data->sio_mutex);
- }
- }
-#endif /* __IT87_USE_ACPI_MUTEX */
- }
-
err = platform_driver_register(&it87_driver);
if (err)
return err;