]> git.sur5r.net Git - groeck-nct6775/blobdiff - nct6775.c
Add basic support for NCT6795D
[groeck-nct6775] / nct6775.c
index 36cd1e487f11432dc2af2097beecbccaea567992..20b17a4f8bec14472782e3887b0df238bd76847d 100644 (file)
--- a/nct6775.c
+++ b/nct6775.c
@@ -40,6 +40,7 @@
  * 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    15?     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).
@@ -65,7 +66,8 @@
 
 #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[] = {
@@ -76,6 +78,7 @@ static const char * const nct6775_device_names[] = {
        "nct6791",
        "nct6792",
        "nct6793",
+       "nct6795",
 };
 
 static const char * const nct6775_sio_names[] __initconst = {
@@ -86,6 +89,7 @@ static const char * const nct6775_sio_names[] __initconst = {
        "NCT6791D",
        "NCT6792D",
        "NCT6793D",
+       "NCT6795D",
 };
 
 static unsigned short force_id;
@@ -118,6 +122,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #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 };
@@ -196,6 +201,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 */
@@ -1050,7 +1057,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;
@@ -1157,6 +1165,7 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
        case nct6791:
        case nct6792:
        case nct6793:
+       case nct6795:
                return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
                  ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
                  reg == 0x402 ||
@@ -1509,6 +1518,7 @@ static void nct6775_update_pwm_limits(struct device *dev)
                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)
@@ -1832,7 +1842,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,
 };
@@ -2051,7 +2061,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,
@@ -2260,7 +2270,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,
@@ -2937,6 +2947,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
                case nct6791:
                case nct6792:
                case nct6793:
+               case nct6795:
                        nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
                                            val);
                        reg = nct6775_read_value(data,
@@ -3134,7 +3145,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,
@@ -3373,7 +3384,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                pwm4pin = false;
                pwm5pin = false;
                pwm6pin = false;
-       } else {        /* NCT6779D, NCT6791D, NCT6792D, or NCT6793D */
+       } else {        /* NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D */
                regval = superio_inb(sioreg, 0x1c);
 
                fan3pin = !(regval & (1 << 5));
@@ -3387,7 +3398,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                fan4min = fan4pin;
 
                if (data->kind == nct6791 || data->kind == nct6792 ||
-                   data->kind == nct6793) {
+                   data->kind == nct6793 || data->kind == nct6795) {
                        regval = superio_inb(sioreg, 0x2d);
                        fan6pin = (regval & (1 << 1));
                        pwm6pin = (regval & (1 << 0));
@@ -3762,6 +3773,7 @@ static int nct6775_probe(struct platform_device *pdev)
        case nct6791:
        case nct6792:
        case nct6793:
+       case nct6795:
                data->in_num = 15;
                data->pwm_num = 6;
                data->auto_pwm_num = 4;
@@ -3790,6 +3802,8 @@ static int nct6775_probe(struct platform_device *pdev)
                case nct6793:
                        data->temp_label = nct6793_temp_label;
                        break;
+               case nct6795:   /* unknown */
+                       break;
                }
                data->temp_label_num = NCT6791_NUM_LABELS;
 
@@ -3958,7 +3972,7 @@ 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 ||
@@ -3970,7 +3984,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) {
@@ -4049,6 +4072,7 @@ static int nct6775_probe(struct platform_device *pdev)
        case nct6791:
        case nct6792:
        case nct6793:
+       case nct6795:
                break;
        }
 
@@ -4082,6 +4106,7 @@ static int nct6775_probe(struct platform_device *pdev)
                case nct6791:
                case nct6792:
                case nct6793:
+               case nct6795:
                        tmp |= 0x7e;
                        break;
                }
@@ -4203,7 +4228,7 @@ static int __maybe_unused nct6775_resume(struct device *dev)
                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);
@@ -4277,11 +4302,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;
@@ -4304,6 +4329,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
        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);
@@ -4330,7 +4358,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
        }
 
        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);