hwmon: (nct6755) Add support for NCT6799D
authorGuenter Roeck <linux@roeck-us.net>
Wed, 28 Dec 2022 13:57:44 +0000 (05:57 -0800)
committerGuenter Roeck <linux@roeck-us.net>
Sun, 18 Jun 2023 03:50:30 +0000 (20:50 -0700)
NCT6799D is mostly compatible to NCT6798D, with minor variations.

Note that NCT6798D and NCT6799D have a new means to select temperature
sources, and to report temperatures from those sources. This is not
currently implemented, meaning that most likely not all temperatures
are reported.

Cc: Sebastian Arnhold <sebastian.arnhold@posteo.de>
Cc: Ahmad Khalifa <ahmad@khalifa.ws>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Arnhold <sebastian.arnhold@posteo.de>
Tested-by: Corentin Labbe <clabbe.montjoie@gmail.com>
Link: https://lore.kernel.org/r/20221228135744.281752-1-linux@roeck-us.net
drivers/hwmon/nct6775-core.c
drivers/hwmon/nct6775-i2c.c
drivers/hwmon/nct6775-platform.c
drivers/hwmon/nct6775.h

index c54233f0369b2487376d13a76b453f191dc5c0f4..236dc97f4d2292beb8bfc7cd688b9846bf74aa40 100644 (file)
@@ -33,6 +33,7 @@
  *                                           (0xd451)
  * nct6798d    14      7       7       2+6    0xd428 0xc1    0x5ca3
  *                                           (0xd429)
+ * nct6799d    14      7       7       2+6    0xd802 0xc1    0x5ca3
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -73,6 +74,7 @@ static const char * const nct6775_device_names[] = {
        "nct6796",
        "nct6797",
        "nct6798",
+       "nct6799",
 };
 
 /* Common and NCT6775 specific data */
@@ -381,7 +383,7 @@ static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
        0x39, 0x155 };
 
 static const u16 NCT6779_REG_TEMP_OFFSET[] = {
-       0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
+       0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c, 0x44d, 0x449 };
 
 static const char *const nct6779_temp_label[] = {
        "",
@@ -654,6 +656,44 @@ static const char *const nct6798_temp_label[] = {
 #define NCT6798_TEMP_MASK      0xbfff0ffe
 #define NCT6798_VIRT_TEMP_MASK 0x80000c00
 
+static const char *const nct6799_temp_label[] = {
+       "",
+       "SYSTIN",
+       "CPUTIN",
+       "AUXTIN0",
+       "AUXTIN1",
+       "AUXTIN2",
+       "AUXTIN3",
+       "AUXTIN4",
+       "SMBUSMASTER 0",
+       "SMBUSMASTER 1",
+       "Virtual_TEMP",
+       "Virtual_TEMP",
+       "",
+       "AUXTIN5",
+       "",
+       "",
+       "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",     /* undocumented */
+       "PECI Agent 1 Calibration",     /* undocumented */
+       "",
+       "Virtual_TEMP"
+};
+
+#define NCT6799_TEMP_MASK      0xbfff2ffe
+#define NCT6799_VIRT_TEMP_MASK 0x80000c00
+
 /* NCT6102D/NCT6106D specific data */
 
 #define NCT6106_REG_VBAT       0x318
@@ -1109,6 +1149,7 @@ bool nct6775_reg_is_word_sized(struct nct6775_data *data, u16 reg)
        case nct6796:
        case nct6797:
        case nct6798:
+       case nct6799:
                return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
                  (reg & 0xfff0) == 0x4c0 ||
                  reg == 0x402 ||
@@ -1462,6 +1503,7 @@ static int nct6775_update_pwm_limits(struct device *dev)
                case nct6796:
                case nct6797:
                case nct6798:
+               case nct6799:
                        err = nct6775_read_value(data, data->REG_CRITICAL_PWM_ENABLE[i], &reg);
                        if (err)
                                return err;
@@ -3109,6 +3151,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
                case nct6796:
                case nct6797:
                case nct6798:
+               case nct6799:
                        err = nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], val);
                        if (err)
                                break;
@@ -3807,10 +3850,12 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
        case nct6796:
        case nct6797:
        case nct6798:
+       case nct6799:
                data->in_num = 15;
                data->pwm_num = (data->kind == nct6796 ||
                                 data->kind == nct6797 ||
-                                data->kind == nct6798) ? 7 : 6;
+                                data->kind == nct6798 ||
+                                data->kind == nct6799) ? 7 : 6;
                data->auto_pwm_num = 4;
                data->has_fan_div = false;
                data->temp_fixed_num = 6;
@@ -3859,6 +3904,11 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
                        data->temp_mask = NCT6798_TEMP_MASK;
                        data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
                        break;
+               case nct6799:
+                       data->temp_label = nct6799_temp_label;
+                       data->temp_mask = NCT6799_TEMP_MASK;
+                       data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK;
+                       break;
                }
 
                data->REG_CONFIG = NCT6775_REG_CONFIG;
@@ -3918,6 +3968,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
                case nct6796:
                case nct6797:
                case nct6798:
+               case nct6799:
                        data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
                        num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
                        break;
index 8acd83e1e00990cd0e275bb494a262a28c8a104e..87a4fc78c5711f2539ac7ed8ddf3f81c43ca85f1 100644 (file)
@@ -87,6 +87,7 @@ static const struct of_device_id __maybe_unused nct6775_i2c_of_match[] = {
        { .compatible = "nuvoton,nct6796", .data = (void *)nct6796, },
        { .compatible = "nuvoton,nct6797", .data = (void *)nct6797, },
        { .compatible = "nuvoton,nct6798", .data = (void *)nct6798, },
+       { .compatible = "nuvoton,nct6799", .data = (void *)nct6799, },
        { },
 };
 MODULE_DEVICE_TABLE(of, nct6775_i2c_of_match);
@@ -104,6 +105,7 @@ static const struct i2c_device_id nct6775_i2c_id[] = {
        { "nct6796", nct6796 },
        { "nct6797", nct6797 },
        { "nct6798", nct6798 },
+       { "nct6799", nct6799 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, nct6775_i2c_id);
index 5782acfb4ee1beec0e847ec7a1d8111e64bbeb28..ada867d6b98acd4092e59bbe916218fa68d88805 100644 (file)
@@ -35,6 +35,7 @@ static const char * const nct6775_sio_names[] __initconst = {
        "NCT6796D",
        "NCT6797D",
        "NCT6798D",
+       "NCT6799D",
 };
 
 static unsigned short force_id;
@@ -85,6 +86,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_NCT6796_ID         0xd420
 #define SIO_NCT6797_ID         0xd450
 #define SIO_NCT6798_ID         0xd428
+#define SIO_NCT6799_ID         0xd800
 #define SIO_ID_MASK            0xFFF8
 
 /*
@@ -418,7 +420,7 @@ static int nct6775_resume(struct device *dev)
        if (data->kind == nct6791 || data->kind == nct6792 ||
            data->kind == nct6793 || data->kind == nct6795 ||
            data->kind == nct6796 || data->kind == nct6797 ||
-           data->kind == nct6798)
+           data->kind == nct6798 || data->kind == nct6799)
                nct6791_enable_io_mapping(sio_data);
 
        sio_data->sio_exit(sio_data);
@@ -565,7 +567,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio
        } else {
                /*
                 * NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D,
-                * NCT6797D, NCT6798D
+                * NCT6797D, NCT6798D, NCT6799D
                 */
                int cr1a = sio_data->sio_inb(sio_data, 0x1a);
                int cr1b = sio_data->sio_inb(sio_data, 0x1b);
@@ -575,12 +577,17 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio
                int cr2b = sio_data->sio_inb(sio_data, 0x2b);
                int cr2d = sio_data->sio_inb(sio_data, 0x2d);
                int cr2f = sio_data->sio_inb(sio_data, 0x2f);
+               bool vsb_ctl_en = cr2f & BIT(0);
                bool dsw_en = cr2f & BIT(3);
                bool ddr4_en = cr2f & BIT(4);
+               bool as_seq1_en = cr2f & BIT(7);
                int cre0;
+               int cre6;
                int creb;
                int cred;
 
+               cre6 = sio_data->sio_inb(sio_data, 0xe0);
+
                sio_data->sio_select(sio_data, NCT6775_LD_12);
                cre0 = sio_data->sio_inb(sio_data, 0xe0);
                creb = sio_data->sio_inb(sio_data, 0xeb);
@@ -683,6 +690,29 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio
                        pwm7pin = !(cr1d & (BIT(2) | BIT(3)));
                        pwm7pin |= cr2d & BIT(7);
                        pwm7pin |= creb & BIT(2);
+                       break;
+               case nct6799:
+                       fan4pin = cr1c & BIT(6);
+                       fan5pin = cr1c & BIT(7);
+
+                       fan6pin = !(cr1b & BIT(0)) && (cre0 & BIT(3));
+                       fan6pin |= cre6 & BIT(5);
+                       fan6pin |= creb & BIT(5);
+                       fan6pin |= !as_seq1_en && (cr2a & BIT(4));
+
+                       fan7pin = cr1b & BIT(5);
+                       fan7pin |= !vsb_ctl_en && !(cr2b & BIT(2));
+                       fan7pin |= creb & BIT(3);
+
+                       pwm6pin = !(cr1b & BIT(0)) && (cre0 & BIT(4));
+                       pwm6pin |= !as_seq1_en && !(cred & BIT(2)) && (cr2a & BIT(3));
+                       pwm6pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
+                       pwm6pin |= cre6 & BIT(3);
+
+                       pwm7pin = !vsb_ctl_en && !(cr1d & (BIT(2) | BIT(3)));
+                       pwm7pin |= creb & BIT(2);
+                       pwm7pin |= cr2d & BIT(7);
+
                        break;
                default:        /* NCT6779D */
                        break;
@@ -838,6 +868,7 @@ static int nct6775_platform_probe_init(struct nct6775_data *data)
        case nct6796:
        case nct6797:
        case nct6798:
+       case nct6799:
                break;
        }
 
@@ -876,6 +907,7 @@ static int nct6775_platform_probe_init(struct nct6775_data *data)
                case nct6796:
                case nct6797:
                case nct6798:
+               case nct6799:
                        tmp |= 0x7e;
                        break;
                }
@@ -1005,6 +1037,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
        case SIO_NCT6798_ID:
                sio_data->kind = nct6798;
                break;
+       case SIO_NCT6799_ID:
+               sio_data->kind = nct6799;
+               break;
        default:
                if (val != 0xffff)
                        pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -1033,7 +1068,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 == nct6795 ||
            sio_data->kind == nct6796 || sio_data->kind == nct6797 ||
-           sio_data->kind == nct6798)
+           sio_data->kind == nct6798 || sio_data->kind == nct6799)
                nct6791_enable_io_mapping(sio_data);
 
        sio_data->sio_exit(sio_data);
index be41848c3cd29fd8c207ee4703c3e4acb70e0ec8..44f79c5726a9c1ec72a8cb54e780c48344fe0166 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/types.h>
 
 enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
-            nct6793, nct6795, nct6796, nct6797, nct6798 };
+            nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 };
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
 
 #define NUM_TEMP       10      /* Max number of temp attribute sets w/ limits*/