in it87.c [2387:2827]
static int __init it87_find(int sioaddr, unsigned short *address,
struct it87_sio_data *sio_data)
{
int err;
u16 chip_type;
const char *board_vendor, *board_name;
const struct it87_devices *config;
err = superio_enter(sioaddr);
if (err)
return err;
err = -ENODEV;
chip_type = force_id ? force_id : superio_inw(sioaddr, DEVID);
switch (chip_type) {
case IT8705F_DEVID:
sio_data->type = it87;
break;
case IT8712F_DEVID:
sio_data->type = it8712;
break;
case IT8716F_DEVID:
case IT8726F_DEVID:
sio_data->type = it8716;
break;
case IT8718F_DEVID:
sio_data->type = it8718;
break;
case IT8720F_DEVID:
sio_data->type = it8720;
break;
case IT8721F_DEVID:
sio_data->type = it8721;
break;
case IT8728F_DEVID:
sio_data->type = it8728;
break;
case IT8732F_DEVID:
sio_data->type = it8732;
break;
case IT8792E_DEVID:
sio_data->type = it8792;
break;
case IT8771E_DEVID:
sio_data->type = it8771;
break;
case IT8772E_DEVID:
sio_data->type = it8772;
break;
case IT8781F_DEVID:
sio_data->type = it8781;
break;
case IT8782F_DEVID:
sio_data->type = it8782;
break;
case IT8783E_DEVID:
sio_data->type = it8783;
break;
case IT8786E_DEVID:
sio_data->type = it8786;
break;
case IT8790E_DEVID:
sio_data->type = it8790;
break;
case IT8603E_DEVID:
case IT8623E_DEVID:
sio_data->type = it8603;
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;
case 0xffff: /* No device at all */
goto exit;
default:
pr_debug("Unsupported chip (DEVID=0x%x)\n", chip_type);
goto exit;
}
superio_select(sioaddr, PME);
if (!(superio_inb(sioaddr, IT87_ACT_REG) & 0x01)) {
pr_info("Device not activated, skipping\n");
goto exit;
}
*address = superio_inw(sioaddr, IT87_BASE_REG) & ~(IT87_EXTENT - 1);
if (*address == 0) {
pr_info("Base address not set, skipping\n");
goto exit;
}
err = 0;
sio_data->sioaddr = sioaddr;
sio_data->revision = superio_inb(sioaddr, DEVREV) & 0x0f;
pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type,
it87_devices[sio_data->type].suffix,
*address, sio_data->revision);
config = &it87_devices[sio_data->type];
/* in7 (VSB or VCCH5V) is always internal on some chips */
if (has_in7_internal(config))
sio_data->internal |= BIT(1);
/* in8 (Vbat) is always internal */
sio_data->internal |= BIT(2);
/* in9 (AVCC3), always internal if supported */
if (has_avcc3(config))
sio_data->internal |= BIT(3); /* in9 is AVCC */
else
sio_data->skip_in |= BIT(9);
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;
/* Read GPIO config and VID value from LDN 7 (GPIO) */
if (sio_data->type == it87) {
/* The IT8705F has a different LD number for GPIO */
superio_select(sioaddr, 5);
sio_data->beep_pin = superio_inb(sioaddr,
IT87_SIO_BEEP_PIN_REG) & 0x3f;
} else if (sio_data->type == it8783) {
int reg25, reg27, reg2a, reg2c, regef;
superio_select(sioaddr, GPIO);
reg25 = superio_inb(sioaddr, IT87_SIO_GPIO1_REG);
reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
reg2a = superio_inb(sioaddr, IT87_SIO_PINX1_REG);
reg2c = superio_inb(sioaddr, IT87_SIO_PINX2_REG);
regef = superio_inb(sioaddr, IT87_SIO_SPI_REG);
/* Check if fan3 is there or not */
if ((reg27 & BIT(0)) || !(reg2c & BIT(2)))
sio_data->skip_fan |= BIT(2);
if ((reg25 & BIT(4)) ||
(!(reg2a & BIT(1)) && (regef & BIT(0))))
sio_data->skip_pwm |= BIT(2);
/* Check if fan2 is there or not */
if (reg27 & BIT(7))
sio_data->skip_fan |= BIT(1);
if (reg27 & BIT(3))
sio_data->skip_pwm |= BIT(1);
/* VIN5 */
if ((reg27 & BIT(0)) || (reg2c & BIT(2)))
sio_data->skip_in |= BIT(5); /* No VIN5 */
/* VIN6 */
if (reg27 & BIT(1))
sio_data->skip_in |= BIT(6); /* No VIN6 */
/*
* VIN7
* Does not depend on bit 2 of Reg2C, contrary to datasheet.
*/
if (reg27 & BIT(2)) {
/*
* The data sheet is a bit unclear regarding the
* internal voltage divider for VCCH5V. It says
* "This bit enables and switches VIN7 (pin 91) to the
* internal voltage divider for VCCH5V".
* This is different to other chips, where the internal
* voltage divider would connect VIN7 to an internal
* voltage source. Maybe that is the case here as well.
*
* Since we don't know for sure, re-route it if that is
* not the case, and ask the user to report if the
* resulting voltage is sane.
*/
if (!(reg2c & BIT(1))) {
reg2c |= BIT(1);
superio_outb(sioaddr, IT87_SIO_PINX2_REG,
reg2c);
sio_data->need_in7_reroute = true;
pr_notice("Routing internal VCCH5V to in7.\n");
}
pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
pr_notice("Please report if it displays a reasonable voltage.\n");
}
if (reg2c & BIT(0))
sio_data->internal |= BIT(0);
if (reg2c & BIT(1))
sio_data->internal |= BIT(1);
sio_data->beep_pin = superio_inb(sioaddr,
IT87_SIO_BEEP_PIN_REG) & 0x3f;
} else if (sio_data->type == it8603) {
int reg27, reg29;
superio_select(sioaddr, GPIO);
reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
/* Check if fan3 is there or not */
if (reg27 & BIT(6))
sio_data->skip_pwm |= BIT(2);
if (reg27 & BIT(7))
sio_data->skip_fan |= BIT(2);
/* Check if fan2 is there or not */
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);
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;
} else if (sio_data->type == it8620 || sio_data->type == it8628) {
int reg;
superio_select(sioaddr, GPIO);
/* Check for pwm5 */
reg = superio_inb(sioaddr, IT87_SIO_GPIO1_REG);
if (reg & BIT(6))
sio_data->skip_pwm |= BIT(4);
/* Check for fan4, fan5 */
reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG);
if (!(reg & BIT(5)))
sio_data->skip_fan |= BIT(3);
if (!(reg & BIT(4)))
sio_data->skip_fan |= BIT(4);
/* Check for pwm3, fan3 */
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);
/* Check for pwm4 */
reg = superio_inb(sioaddr, IT87_SIO_GPIO4_REG);
if (reg & BIT(2))
sio_data->skip_pwm |= BIT(3);
/* 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 pwm6, fan6 */
if (!(reg & BIT(7))) {
sio_data->skip_pwm |= BIT(5);
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 {
int reg;
bool uart6;
superio_select(sioaddr, GPIO);
/* Check for fan4, fan5 */
if (has_five_fans(config)) {
reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG);
switch (sio_data->type) {
case it8718:
if (reg & BIT(5))
sio_data->skip_fan |= BIT(3);
if (reg & BIT(4))
sio_data->skip_fan |= BIT(4);
break;
case it8720:
case it8721:
case it8728:
if (!(reg & BIT(5)))
sio_data->skip_fan |= BIT(3);
if (!(reg & BIT(4)))
sio_data->skip_fan |= BIT(4);
break;
default:
break;
}
}
reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
if (!sio_data->skip_vid) {
/* We need at least 4 VID pins */
if (reg & 0x0f) {
pr_info("VID is disabled (pins used for GPIO)\n");
sio_data->skip_vid = 1;
}
}
/* Check if fan3 is there or not */
if (reg & BIT(6))
sio_data->skip_pwm |= BIT(2);
if (reg & BIT(7))
sio_data->skip_fan |= BIT(2);
/* Check if fan2 is there or not */
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);
if ((sio_data->type == it8718 || sio_data->type == it8720) &&
!(sio_data->skip_vid))
sio_data->vid_value = superio_inb(sioaddr,
IT87_SIO_VID_REG);
reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG);
uart6 = sio_data->type == it8782 && (reg & BIT(2));
/*
* The IT8720F has no VIN7 pin, so VCCH5V should always be
* routed internally to VIN7 with an internal divider.
* Curiously, there still is a configuration bit to control
* this, which means it can be set incorrectly. And even
* more curiously, many boards out there are improperly
* configured, even though the IT8720F datasheet claims
* that the internal routing of VCCH5V to VIN7 is the default
* setting. So we force the internal routing in this case.
*
* On IT8782F, VIN7 is multiplexed with one of the UART6 pins.
* If UART6 is enabled, re-route VIN7 to the internal divider
* if that is not already the case.
*/
if ((sio_data->type == it8720 || uart6) && !(reg & BIT(1))) {
reg |= BIT(1);
superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg);
sio_data->need_in7_reroute = true;
pr_notice("Routing internal VCCH5V to in7\n");
}
if (reg & BIT(0))
sio_data->internal |= BIT(0);
if (reg & BIT(1))
sio_data->internal |= BIT(1);
/*
* On IT8782F, UART6 pins overlap with VIN5, VIN6, and VIN7.
* While VIN7 can be routed to the internal voltage divider,
* VIN5 and VIN6 are not available if UART6 is enabled.
*
* Also, temp3 is not available if UART6 is enabled and TEMPIN3
* is the temperature source. Since we can not read the
* temperature source here, skip_temp is preliminary.
*/
if (uart6) {
sio_data->skip_in |= BIT(5) | BIT(6);
sio_data->skip_temp |= BIT(2);
}
sio_data->beep_pin = superio_inb(sioaddr,
IT87_SIO_BEEP_PIN_REG) & 0x3f;
}
if (sio_data->beep_pin)
pr_info("Beeping is supported\n");
/* Disable specific features based on DMI strings */
board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
board_name = dmi_get_system_info(DMI_BOARD_NAME);
if (board_vendor && board_name) {
if (strcmp(board_vendor, "nVIDIA") == 0 &&
strcmp(board_name, "FN68PT") == 0) {
/*
* On the Shuttle SN68PT, FAN_CTL2 is apparently not
* connected to a fan, but to something else. One user
* has reported instant system power-off when changing
* the PWM2 duty cycle, so we disable it.
* I use the board name string as the trigger in case
* the same board is ever used in other systems.
*/
pr_info("Disabling pwm2 due to hardware constraints\n");
sio_data->skip_pwm = BIT(1);
}
}
exit:
superio_exit(sioaddr);
return err;
}