* nct6791d 15 6 6 2+6 0xc800 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).
#define USE_ALTERNATE
-enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793 };
+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[] = {
"nct6791",
"nct6792",
"nct6793",
+ "nct6795",
};
static const char * const nct6775_sio_names[] __initconst = {
"NCT6791D",
"NCT6792D",
"NCT6793D",
+ "NCT6795D",
};
static unsigned short force_id;
#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) */
#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 };
#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 */
"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 */
"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_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_ALTERNATE[32] = {
+ [14] = 0x401,
+ [15] = 0x402,
+ [16] = 0x404,
+};
+
+static const u16 NCT6776_REG_TEMP_CRIT[32] = {
+ [11] = 0x709,
+ [12] = 0x70a,
+};
/* NCT6779 specific data */
"Virtual_TEMP"
};
-#define NCT6779_NUM_LABELS (ARRAY_SIZE(nct6779_temp_label) - 5)
-#define NCT6791_NUM_LABELS ARRAY_SIZE(nct6779_temp_label)
+#define NCT6779_TEMP_MASK 0x07ffff7e
+#define NCT6791_TEMP_MASK 0x87ffff7e
-static const u16 NCT6779_REG_TEMP_ALTERNATE[NCT6791_NUM_LABELS - 1]
+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[NCT6791_NUM_LABELS - 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 */
"Virtual_TEMP"
};
+#define NCT6792_TEMP_MASK 0x9fffff7e
+
static const char *const nct6793_temp_label[] = {
"",
"SYSTIN",
"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
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)
{
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;
case nct6791:
case nct6792:
case nct6793:
+ case nct6795:
return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
reg == 0x402 ||
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)
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 */
case nct6791:
case nct6792:
case nct6793:
+ case nct6795:
nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
val);
reg = nct6775_read_value(data,
pwm4pin = false;
pwm5pin = false;
pwm6pin = false;
- } else { /* NCT6779D, NCT6791D, NCT6792D, or NCT6793D */
+ } else { /* NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D */
+ int regval_1b, regval_2a, regval_eb;
+
regval = superio_inb(sioreg, 0x1c);
fan3pin = !(regval & (1 << 5));
pwm4pin = !(regval & (1 << 1));
pwm5pin = !(regval & (1 << 2));
- fan4min = fan4pin;
-
- if (data->kind == nct6791 || data->kind == nct6792 ||
- data->kind == nct6793) {
- 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 */
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);
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;
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;
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;
data->speed_tolerance_limit = 63;
data->temp_label = nct6779_temp_label;
- data->temp_label_num = NCT6779_NUM_LABELS;
+ data->temp_mask = NCT6779_TEMP_MASK;
data->REG_CONFIG = NCT6775_REG_CONFIG;
data->REG_VBAT = NCT6775_REG_VBAT;
case nct6791:
case nct6792:
case nct6793:
+ case nct6795:
data->in_num = 15;
data->pwm_num = 6;
data->auto_pwm_num = 4;
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->temp_label_num = NCT6791_NUM_LABELS;
data->REG_CONFIG = NCT6775_REG_CONFIG;
data->REG_VBAT = NCT6775_REG_VBAT;
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]);
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],
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) {
* The temperature is already monitored if the respective bit in <mask>
* 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)))
case nct6791:
case nct6792:
case nct6793:
+ case nct6795:
break;
}
case nct6791:
case nct6792:
case nct6793:
+ case nct6795:
tmp |= 0x7e;
break;
}
superio_outb(sioreg, SIO_REG_ENABLE, data->sio_reg_enable);
if (data->kind == nct6791 || data->kind == nct6792 ||
- data->kind == nct6793)
+ data->kind == nct6793 || data->kind == nct6795)
nct6791_enable_io_mapping(sioreg);
superio_exit(sioreg);
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);
}
if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
- sio_data->kind == nct6793)
+ sio_data->kind == nct6793 || sio_data->kind == nct6795)
nct6791_enable_io_mapping(sioaddr);
superio_exit(sioaddr);