X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=nct6775.c;h=a6f3b73acb154bf4fabe6fe1ce6dbf52fbdfc85f;hb=50cbc4e8bd8731c269f08a95e1f74b9d511eb3c5;hp=3272356015af5478fda2d31588cb2056c05156cf;hpb=c4e40c4f7602f70286948e7376ee4db975095672;p=groeck-nct6775 diff --git a/nct6775.c b/nct6775.c index 3272356..a6f3b73 100644 --- a/nct6775.c +++ b/nct6775.c @@ -38,7 +38,9 @@ * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3 * nct6791d 15 6 6 2+6 0xc800 0xc1 0x5ca3 - * nct6792d 15 6 6 2+6 0xc911 0xc1 0x5ca3 + * nct6792d 15 6 6 2+6 0xc910 0xc1 0x5ca3 + * nct6793d 15 6 6 2+6 0xd120 0xc1 0x5ca3 + * nct6795d 14 6 6 2+6 0xd350 0xc1 0x5ca3 * * #temp lists the number of monitored temperature sources (first value) plus * the number of directly connectable temperature sensors (second value). @@ -57,13 +59,15 @@ #include #include #include +#include #include #include "lm75.h" #include "compat.h" #define USE_ALTERNATE -enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792 }; +enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793, + nct6795 }; /* used to set data->name = nct6775_device_names[data->sio_kind] */ static const char * const nct6775_device_names[] = { @@ -73,6 +77,19 @@ static const char * const nct6775_device_names[] = { "nct6779", "nct6791", "nct6792", + "nct6793", + "nct6795", +}; + +static const char * const nct6775_sio_names[] __initconst = { + "NCT6106D", + "NCT6775F", + "NCT6776D/F", + "NCT6779D", + "NCT6791D", + "NCT6792D", + "NCT6793D", + "NCT6795D", }; static unsigned short force_id; @@ -92,6 +109,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); #define NCT6775_LD_ACPI 0x0a #define NCT6775_LD_HWM 0x0b #define NCT6775_LD_VID 0x0d +#define NCT6775_LD_12 0x12 #define SIO_REG_LDSEL 0x07 /* Logical device select */ #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ @@ -104,6 +122,8 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); #define SIO_NCT6779_ID 0xc560 #define SIO_NCT6791_ID 0xc800 #define SIO_NCT6792_ID 0xc910 +#define SIO_NCT6793_ID 0xd120 +#define SIO_NCT6795_ID 0xd350 #define SIO_ID_MASK 0xFFF0 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; @@ -182,6 +202,8 @@ superio_exit(int ioreg) #define NUM_FAN 6 +#define TEMP_SOURCE_VIRTUAL 0x1f + /* Common and NCT6775 specific data */ /* Voltage min/max registers for nr=7..14 are in bank 5 */ @@ -345,15 +367,31 @@ static const char *const nct6775_temp_label[] = { "PCH_DIM3_TEMP" }; -static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 }; +#define NCT6775_TEMP_MASK 0x001ffffe -static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1] - = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06, - 0xa07 }; +static const u16 NCT6775_REG_TEMP_ALTERNATE[32] = { + [13] = 0x661, + [14] = 0x662, + [15] = 0x664, +}; + +static const u16 NCT6775_REG_TEMP_CRIT[32] = { + [4] = 0xa00, + [5] = 0xa01, + [6] = 0xa02, + [7] = 0xa03, + [8] = 0xa04, + [9] = 0xa05, + [10] = 0xa06, + [11] = 0xa07 +}; /* NCT6776 specific data */ +/* STEP_UP_TIME and STEP_DOWN_TIME regs are swapped for all chips but NCT6775 */ +#define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME +#define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME + static const s8 NCT6776_ALARM_BITS[] = { 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ @@ -415,11 +453,18 @@ static const char *const nct6776_temp_label[] = { "BYTE_TEMP" }; -static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 }; +#define NCT6776_TEMP_MASK 0x007ffffe + +static const u16 NCT6776_REG_TEMP_ALTERNATE[32] = { + [14] = 0x401, + [15] = 0x402, + [16] = 0x404, +}; -static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; +static const u16 NCT6776_REG_TEMP_CRIT[32] = { + [11] = 0x709, + [12] = 0x70a, +}; /* NCT6779 specific data */ @@ -498,17 +543,27 @@ static const char *const nct6779_temp_label[] = { "PCH_DIM1_TEMP", "PCH_DIM2_TEMP", "PCH_DIM3_TEMP", - "BYTE_TEMP" + "BYTE_TEMP", + "", + "", + "", + "", + "Virtual_TEMP" }; -static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1] +#define NCT6779_TEMP_MASK 0x07ffff7e +#define NCT6791_TEMP_MASK 0x87ffff7e + +static const u16 NCT6779_REG_TEMP_ALTERNATE[32] = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407, 0x408, 0 }; -static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; +static const u16 NCT6779_REG_TEMP_CRIT[32] = { + [15] = 0x709, + [16] = 0x70a, +}; /* NCT6791 specific data */ @@ -533,13 +588,124 @@ static const s8 NCT6791_ALARM_BITS[] = { 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ 12, 9 }; /* intrusion0, intrusion1 */ -/* NCT6792 specific data */ +/* NCT6792/NCT6793 specific data */ static const u16 NCT6792_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d }; static const u16 NCT6792_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5, 0xbf }; +static const char *const nct6792_temp_label[] = { + "", + "SYSTIN", + "CPUTIN", + "AUXTIN0", + "AUXTIN1", + "AUXTIN2", + "AUXTIN3", + "", + "SMBUSMASTER 0", + "SMBUSMASTER 1", + "SMBUSMASTER 2", + "SMBUSMASTER 3", + "SMBUSMASTER 4", + "SMBUSMASTER 5", + "SMBUSMASTER 6", + "SMBUSMASTER 7", + "PECI Agent 0", + "PECI Agent 1", + "PCH_CHIP_CPU_MAX_TEMP", + "PCH_CHIP_TEMP", + "PCH_CPU_TEMP", + "PCH_MCH_TEMP", + "PCH_DIM0_TEMP", + "PCH_DIM1_TEMP", + "PCH_DIM2_TEMP", + "PCH_DIM3_TEMP", + "BYTE_TEMP", + "PECI Agent 0 Calibration", + "PECI Agent 1 Calibration", + "", + "", + "Virtual_TEMP" +}; + +#define NCT6792_TEMP_MASK 0x9fffff7e + +static const char *const nct6793_temp_label[] = { + "", + "SYSTIN", + "CPUTIN", + "AUXTIN0", + "AUXTIN1", + "AUXTIN2", + "AUXTIN3", + "", + "SMBUSMASTER 0", + "SMBUSMASTER 1", + "", + "", + "", + "", + "", + "", + "PECI Agent 0", + "PECI Agent 1", + "PCH_CHIP_CPU_MAX_TEMP", + "PCH_CHIP_TEMP", + "PCH_CPU_TEMP", + "PCH_MCH_TEMP", + "Agent0 Dimm0 ", + "Agent0 Dimm1", + "Agent1 Dimm0", + "Agent1 Dimm1", + "BYTE_TEMP0", + "BYTE_TEMP1", + "PECI Agent 0 Calibration", + "PECI Agent 1 Calibration", + "", + "Virtual_TEMP" +}; + +#define NCT6793_TEMP_MASK 0xbfff037e + +static const char *const nct6795_temp_label[] = { + "", + "SYSTIN", + "CPUTIN", + "AUXTIN0", + "AUXTIN1", + "AUXTIN2", + "AUXTIN3", + "", + "SMBUSMASTER 0", + "SMBUSMASTER 1", + "SMBUSMASTER 2", + "SMBUSMASTER 3", + "SMBUSMASTER 4", + "SMBUSMASTER 5", + "SMBUSMASTER 6", + "SMBUSMASTER 7", + "PECI Agent 0", + "PECI Agent 1", + "PCH_CHIP_CPU_MAX_TEMP", + "PCH_CHIP_TEMP", + "PCH_CPU_TEMP", + "PCH_MCH_TEMP", + "PCH_DIM0_TEMP", + "PCH_DIM1_TEMP", + "PCH_DIM2_TEMP", + "PCH_DIM3_TEMP", + "BYTE_TEMP0", + "BYTE_TEMP1", + "PECI Agent 0 Calibration", + "PECI Agent 1 Calibration", + "", + "Virtual_TEMP" +}; + +#define NCT6795_TEMP_MASK 0xbfffff7e + /* NCT6102D/NCT6106D specific data */ #define NCT6106_REG_VBAT 0x318 @@ -634,11 +800,16 @@ static const s8 NCT6106_BEEP_BITS[] = { 34, -1 /* intrusion0, intrusion1 */ }; -static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 }; +static const u16 NCT6106_REG_TEMP_ALTERNATE[32] = { + [14] = 0x51, + [15] = 0x52, + [16] = 0x54, +}; -static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 }; +static const u16 NCT6106_REG_TEMP_CRIT[32] = { + [11] = 0x204, + [12] = 0x205, +}; static enum pwm_enable reg_to_pwm_enable(int pwm, int mode) { @@ -757,7 +928,7 @@ struct nct6775_data { u8 temp_src[NUM_TEMP]; u16 reg_temp_config[NUM_TEMP]; const char * const *temp_label; - int temp_label_num; + u32 temp_mask; u16 REG_CONFIG; u16 REG_VBAT; @@ -885,12 +1056,12 @@ struct nct6775_data { u16 have_temp; u16 have_temp_fixed; u16 have_in; -#ifdef CONFIG_PM + /* Remember extra register values over suspend/resume */ u8 vbat; u8 fandiv1; u8 fandiv2; -#endif + u8 sio_reg_enable; }; struct nct6775_sio_data { @@ -954,7 +1125,8 @@ struct sensor_template_group { }; static struct attribute_group * -nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg, +nct6775_create_attr_group(struct device *dev, + const struct sensor_template_group *tg, int repeat) { struct attribute_group *group; @@ -999,6 +1171,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg, (*t)->dev_attr.attr.name, tg->base + i); if ((*t)->s2) { a2 = &su->u.a2; + sysfs_attr_init(&a2->dev_attr.attr); a2->dev_attr.attr.name = su->name; a2->nr = (*t)->u.s.nr + i; a2->index = (*t)->u.s.index; @@ -1009,6 +1182,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg, *attrs = &a2->dev_attr.attr; } else { a = &su->u.a1; + sysfs_attr_init(&a->dev_attr.attr); a->dev_attr.attr.name = su->name; a->index = (*t)->u.index + i; a->dev_attr.attr.mode = @@ -1058,6 +1232,8 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg) case nct6779: case nct6791: case nct6792: + case nct6793: + case nct6795: return reg == 0x150 || reg == 0x153 || reg == 0x155 || ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) || reg == 0x402 || @@ -1409,6 +1585,8 @@ static void nct6775_update_pwm_limits(struct device *dev) case nct6779: case nct6791: case nct6792: + case nct6793: + case nct6795: reg = nct6775_read_value(data, data->REG_CRITICAL_PWM_ENABLE[i]); if (reg & data->CRITICAL_PWM_ENABLE_MASK) @@ -1732,7 +1910,7 @@ static struct sensor_device_template *nct6775_attributes_in_template[] = { NULL }; -static struct sensor_template_group nct6775_in_template_group = { +static const struct sensor_template_group nct6775_in_template_group = { .templates = nct6775_attributes_in_template, .is_visible = nct6775_in_is_visible, }; @@ -1951,7 +2129,7 @@ static struct sensor_device_template *nct6775_attributes_fan_template[] = { NULL }; -static struct sensor_template_group nct6775_fan_template_group = { +static const struct sensor_template_group nct6775_fan_template_group = { .templates = nct6775_attributes_fan_template, .is_visible = nct6775_fan_is_visible, .base = 1, @@ -2098,6 +2276,9 @@ static umode_t nct6775_temp_is_visible(struct kobject *kobj, if (!(data->have_temp & (1 << temp))) return 0; + if (nr == 1 && !data->temp_label) + return 0; + if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0) return 0; /* alarm */ @@ -2160,7 +2341,7 @@ static struct sensor_device_template *nct6775_attributes_temp_template[] = { NULL }; -static struct sensor_template_group nct6775_temp_template_group = { +static const struct sensor_template_group nct6775_temp_template_group = { .templates = nct6775_attributes_temp_template, .is_visible = nct6775_temp_is_visible, .base = 1, @@ -2836,6 +3017,8 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr, case nct6779: case nct6791: case nct6792: + case nct6793: + case nct6795: nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], val); reg = nct6775_read_value(data, @@ -3033,7 +3216,7 @@ static struct sensor_device_template *nct6775_attributes_pwm_template[] = { NULL }; -static struct sensor_template_group nct6775_pwm_template_group = { +static const struct sensor_template_group nct6775_pwm_template_group = { .templates = nct6775_attributes_pwm_template, .is_visible = nct6775_pwm_is_visible, .base = 1, @@ -3197,6 +3380,10 @@ nct6775_check_fan_inputs(struct nct6775_data *data) int sioreg = data->sioreg; int regval; + /* Store SIO_REG_ENABLE for use during resume */ + superio_select(sioreg, NCT6775_LD_HWM); + data->sio_reg_enable = superio_inb(sioreg, SIO_REG_ENABLE); + /* fan4 and fan5 share some pins with the GPIO and serial flash */ if (data->kind == nct6775) { regval = superio_inb(sioreg, 0x2c); @@ -3214,21 +3401,38 @@ nct6775_check_fan_inputs(struct nct6775_data *data) pwm6pin = false; } else if (data->kind == nct6776) { bool gpok = superio_inb(sioreg, 0x27) & 0x80; + const char *board_vendor, *board_name; - superio_select(sioreg, NCT6775_LD_HWM); - regval = superio_inb(sioreg, SIO_REG_ENABLE); + board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); + board_name = dmi_get_system_info(DMI_BOARD_NAME); - if (regval & 0x80) + if (board_name && board_vendor && + !strcmp(board_vendor, "ASRock")) { + /* + * Auxiliary fan monitoring is not enabled on ASRock + * Z77 Pro4-M if booted in UEFI Ultra-FastBoot mode. + * Observed with BIOS version 2.00. + */ + if (!strcmp(board_name, "Z77 Pro4-M")) { + if ((data->sio_reg_enable & 0xe0) != 0xe0) { + data->sio_reg_enable |= 0xe0; + superio_outb(sioreg, SIO_REG_ENABLE, + data->sio_reg_enable); + } + } + } + + if (data->sio_reg_enable & 0x80) fan3pin = gpok; else fan3pin = !(superio_inb(sioreg, 0x24) & 0x40); - if (regval & 0x40) + if (data->sio_reg_enable & 0x40) fan4pin = gpok; else fan4pin = superio_inb(sioreg, 0x1C) & 0x01; - if (regval & 0x20) + if (data->sio_reg_enable & 0x20) fan5pin = gpok; else fan5pin = superio_inb(sioreg, 0x1C) & 0x02; @@ -3251,7 +3455,9 @@ nct6775_check_fan_inputs(struct nct6775_data *data) pwm4pin = false; pwm5pin = false; pwm6pin = false; - } else { /* NCT6779D, NCT6791D, or NCT6792D */ + } else { /* NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D */ + int regval_1b, regval_2a, regval_eb; + regval = superio_inb(sioreg, 0x1c); fan3pin = !(regval & (1 << 5)); @@ -3262,16 +3468,44 @@ nct6775_check_fan_inputs(struct nct6775_data *data) pwm4pin = !(regval & (1 << 1)); pwm5pin = !(regval & (1 << 2)); - fan4min = fan4pin; - - if (data->kind == nct6791 || data->kind == nct6792) { - regval = superio_inb(sioreg, 0x2d); - fan6pin = (regval & (1 << 1)); - pwm6pin = (regval & (1 << 0)); - } else { /* NCT6779D */ + regval = superio_inb(sioreg, 0x2d); + switch (data->kind) { + case nct6791: + case nct6792: + fan6pin = regval & (1 << 1); + pwm6pin = regval & (1 << 0); + break; + case nct6793: + case nct6795: + regval_1b = superio_inb(sioreg, 0x1b); + regval_2a = superio_inb(sioreg, 0x2a); + + if (!pwm5pin) + pwm5pin = regval & (1 << 7); + fan6pin = regval & (1 << 1); + pwm6pin = regval & (1 << 0); + if (!fan5pin) + fan5pin = regval_1b & (1 << 5); + + superio_select(sioreg, NCT6775_LD_12); + regval_eb = superio_inb(sioreg, 0xeb); + if (!fan5pin) + fan5pin = regval_eb & (1 << 5); + if (!pwm5pin) + pwm5pin = (regval_eb & (1 << 4)) && + !(regval_2a & (1 << 0)); + if (!fan6pin) + fan6pin = regval_eb & (1 << 3); + if (!pwm6pin) + pwm6pin = regval_eb & (1 << 2); + break; + default: /* NCT6779D */ fan6pin = false; pwm6pin = false; + break; } + + fan4min = fan4pin; } /* fan 1 and 2 (0x03) are always present */ @@ -3298,8 +3532,7 @@ static void add_temp_sensors(struct nct6775_data *data, const u16 *regp, src &= 0x1f; if (!src || (*mask & (1 << src))) continue; - if (src >= data->temp_label_num || - !strlen(data->temp_label[src])) + if (!(data->temp_mask & BIT(src))) continue; index = __ffs(*available); @@ -3357,7 +3590,7 @@ static int nct6775_probe(struct platform_device *pdev) data->fan_from_reg_min = fan_from_reg13; data->temp_label = nct6776_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); + data->temp_mask = NCT6776_TEMP_MASK; data->REG_VBAT = NCT6106_REG_VBAT; data->REG_DIODE = NCT6106_REG_DIODE; @@ -3435,7 +3668,7 @@ static int nct6775_probe(struct platform_device *pdev) data->speed_tolerance_limit = 15; data->temp_label = nct6775_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6775_temp_label); + data->temp_mask = NCT6775_TEMP_MASK; data->REG_CONFIG = NCT6775_REG_CONFIG; data->REG_VBAT = NCT6775_REG_VBAT; @@ -3507,7 +3740,7 @@ static int nct6775_probe(struct platform_device *pdev) data->speed_tolerance_limit = 63; data->temp_label = nct6776_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); + data->temp_mask = NCT6776_TEMP_MASK; data->REG_CONFIG = NCT6775_REG_CONFIG; data->REG_VBAT = NCT6775_REG_VBAT; @@ -3523,8 +3756,8 @@ static int nct6775_probe(struct platform_device *pdev) data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; - data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; - data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; + data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME; + data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME; data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; data->REG_PWM[0] = NCT6775_REG_PWM; data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; @@ -3579,7 +3812,7 @@ static int nct6775_probe(struct platform_device *pdev) data->speed_tolerance_limit = 63; data->temp_label = nct6779_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6779_temp_label); + data->temp_mask = NCT6779_TEMP_MASK; data->REG_CONFIG = NCT6775_REG_CONFIG; data->REG_VBAT = NCT6775_REG_VBAT; @@ -3595,8 +3828,8 @@ static int nct6775_probe(struct platform_device *pdev) data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; - data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; - data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; + data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME; + data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME; data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; data->REG_PWM[0] = NCT6775_REG_PWM; data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; @@ -3638,6 +3871,8 @@ static int nct6775_probe(struct platform_device *pdev) break; case nct6791: case nct6792: + case nct6793: + case nct6795: data->in_num = 15; data->pwm_num = 6; data->auto_pwm_num = 4; @@ -3655,8 +3890,25 @@ static int nct6775_probe(struct platform_device *pdev) data->tolerance_mask = 0x07; data->speed_tolerance_limit = 63; - data->temp_label = nct6779_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6779_temp_label); + switch (data->kind) { + default: + case nct6791: + data->temp_label = nct6779_temp_label; + data->temp_mask = NCT6791_TEMP_MASK; + break; + case nct6792: + data->temp_label = nct6792_temp_label; + data->temp_mask = NCT6792_TEMP_MASK; + break; + case nct6793: + data->temp_label = nct6793_temp_label; + data->temp_mask = NCT6793_TEMP_MASK; + break; + case nct6795: + data->temp_label = nct6795_temp_label; + data->temp_mask = NCT6795_TEMP_MASK; + break; + } data->REG_CONFIG = NCT6775_REG_CONFIG; data->REG_VBAT = NCT6775_REG_VBAT; @@ -3672,8 +3924,8 @@ static int nct6775_probe(struct platform_device *pdev) data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; - data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; - data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; + data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME; + data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME; data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; data->REG_PWM[0] = NCT6775_REG_PWM; data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; @@ -3765,8 +4017,7 @@ static int nct6775_probe(struct platform_device *pdev) if (!src || (mask & (1 << src))) continue; - if (src >= data->temp_label_num || - !strlen(data->temp_label[src])) { + if (!(data->temp_mask & BIT(src))) { dev_info(dev, "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n", src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]); @@ -3823,11 +4074,10 @@ static int nct6775_probe(struct platform_device *pdev) continue; src = nct6775_read_value(data, data->REG_TEMP_SEL[i]) & 0x1f; - if (!src || (mask & (1 << src))) + if (!src) continue; - if (src >= data->temp_label_num || - !strlen(data->temp_label[src])) { + if (!(data->temp_mask & BIT(src))) { dev_info(dev, "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n", src, i, data->REG_TEMP_SEL[i], @@ -3835,7 +4085,16 @@ static int nct6775_probe(struct platform_device *pdev) continue; } - mask |= 1 << src; + /* + * For virtual temperature sources, the 'virtual' temperature + * for each fan reflects a different temperature, and there + * are no duplicates. + */ + if (src != TEMP_SOURCE_VIRTUAL) { + if (mask & (1 << src)) + continue; + mask |= 1 << src; + } /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */ if (src <= data->temp_fixed_num) { @@ -3865,7 +4124,9 @@ static int nct6775_probe(struct platform_device *pdev) * The temperature is already monitored if the respective bit in * is set. */ - for (i = 0; i < data->temp_label_num - 1; i++) { + for (i = 0; i < 32; i++) { + if (!(data->temp_mask & BIT(i))) + continue; if (!reg_temp_alternate[i]) continue; if (mask & (1 << (i + 1))) @@ -3913,6 +4174,8 @@ static int nct6775_probe(struct platform_device *pdev) case nct6779: case nct6791: case nct6792: + case nct6793: + case nct6795: break; } @@ -3945,6 +4208,8 @@ static int nct6775_probe(struct platform_device *pdev) break; case nct6791: case nct6792: + case nct6793: + case nct6795: tmp |= 0x7e; break; } @@ -4031,8 +4296,7 @@ static void nct6791_enable_io_mapping(int sioaddr) } } -#ifdef CONFIG_PM -static int nct6775_suspend(struct device *dev) +static int __maybe_unused nct6775_suspend(struct device *dev) { struct nct6775_data *data = nct6775_update_device(dev); @@ -4047,22 +4311,30 @@ static int nct6775_suspend(struct device *dev) return 0; } -static int nct6775_resume(struct device *dev) +static int __maybe_unused nct6775_resume(struct device *dev) { struct nct6775_data *data = dev_get_drvdata(dev); + int sioreg = data->sioreg; int i, j, err = 0; + u8 reg; mutex_lock(&data->update_lock); data->bank = 0xff; /* Force initial bank selection */ - if (data->kind == nct6791 || data->kind == nct6792) { - err = superio_enter(data->sioreg); - if (err) - goto abort; + err = superio_enter(sioreg); + if (err) + goto abort; - nct6791_enable_io_mapping(data->sioreg); - superio_exit(data->sioreg); - } + superio_select(sioreg, NCT6775_LD_HWM); + reg = superio_inb(sioreg, SIO_REG_ENABLE); + if (reg != data->sio_reg_enable) + superio_outb(sioreg, SIO_REG_ENABLE, data->sio_reg_enable); + + if (data->kind == nct6791 || data->kind == nct6792 || + data->kind == nct6793 || data->kind == nct6795) + nct6791_enable_io_mapping(sioreg); + + superio_exit(sioreg); /* Restore limits */ for (i = 0; i < data->in_num; i++) { @@ -4108,23 +4380,13 @@ abort: return err; } -static const struct dev_pm_ops nct6775_dev_pm_ops = { - .suspend = nct6775_suspend, - .resume = nct6775_resume, - .freeze = nct6775_suspend, - .restore = nct6775_resume, -}; - -#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops) -#else -#define NCT6775_DEV_PM_OPS NULL -#endif /* CONFIG_PM */ +static SIMPLE_DEV_PM_OPS(nct6775_dev_pm_ops, nct6775_suspend, nct6775_resume); static struct platform_driver nct6775_driver = { .driver = { .owner = THIS_MODULE, .name = DRVNAME, - .pm = NCT6775_DEV_PM_OPS, + .pm = &nct6775_dev_pm_ops, }, .probe = nct6775_probe, #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) @@ -4132,15 +4394,6 @@ static struct platform_driver nct6775_driver = { #endif }; -static const char * const nct6775_sio_names[] __initconst = { - "NCT6106D", - "NCT6775F", - "NCT6776D/F", - "NCT6779D", - "NCT6791D", - "NCT6792D", -}; - /* nct6775_find() looks for a '627 in the Super-I/O config space */ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) { @@ -4152,11 +4405,11 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) if (err) return err; - if (force_id) + val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | + superio_inb(sioaddr, SIO_REG_DEVID + 1); + if (force_id && val != 0xffff) val = force_id; - else - val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) - | superio_inb(sioaddr, SIO_REG_DEVID + 1); + switch (val & SIO_ID_MASK) { case SIO_NCT6106_ID: sio_data->kind = nct6106; @@ -4176,6 +4429,12 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) case SIO_NCT6792_ID: sio_data->kind = nct6792; break; + case SIO_NCT6793_ID: + sio_data->kind = nct6793; + break; + case SIO_NCT6795_ID: + sio_data->kind = nct6795; + break; default: if (val != 0xffff) pr_debug("unsupported chip ID: 0x%04x\n", val); @@ -4201,7 +4460,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); } - if (sio_data->kind == nct6791 || sio_data->kind == nct6792) + if (sio_data->kind == nct6791 || sio_data->kind == nct6792 || + sio_data->kind == nct6793 || sio_data->kind == nct6795) nct6791_enable_io_mapping(sioaddr); superio_exit(sioaddr); @@ -4311,7 +4571,7 @@ static void __exit sensors_nct6775_exit(void) } MODULE_AUTHOR("Guenter Roeck "); -MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D/NCT6792D driver"); +MODULE_DESCRIPTION("Driver for NCT6775F and compatible chips"); MODULE_LICENSE("GPL"); module_init(sensors_nct6775_init);