hwmon: (tmp401) Add support for TI TMP461
[cascardo/linux.git] / drivers / hwmon / tmp401.c
index ccf4cff..eeeed2c 100644 (file)
@@ -47,7 +47,7 @@
 static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c, 0x4d,
        0x4e, 0x4f, I2C_CLIENT_END };
 
-enum chips { tmp401, tmp411, tmp431, tmp432, tmp435 };
+enum chips { tmp401, tmp411, tmp431, tmp432, tmp435, tmp461 };
 
 /*
  * The TMP401 registers, note some registers have different addresses for
@@ -62,31 +62,34 @@ enum chips { tmp401, tmp411, tmp431, tmp432, tmp435 };
 #define TMP401_MANUFACTURER_ID_REG             0xFE
 #define TMP401_DEVICE_ID_REG                   0xFF
 
-static const u8 TMP401_TEMP_MSB_READ[6][2] = {
+static const u8 TMP401_TEMP_MSB_READ[7][2] = {
        { 0x00, 0x01 }, /* temp */
        { 0x06, 0x08 }, /* low limit */
        { 0x05, 0x07 }, /* high limit */
        { 0x20, 0x19 }, /* therm (crit) limit */
        { 0x30, 0x34 }, /* lowest */
        { 0x32, 0x36 }, /* highest */
+       { 0, 0x11 },    /* offset */
 };
 
-static const u8 TMP401_TEMP_MSB_WRITE[6][2] = {
+static const u8 TMP401_TEMP_MSB_WRITE[7][2] = {
        { 0, 0 },       /* temp (unused) */
        { 0x0C, 0x0E }, /* low limit */
        { 0x0B, 0x0D }, /* high limit */
        { 0x20, 0x19 }, /* therm (crit) limit */
        { 0x30, 0x34 }, /* lowest */
        { 0x32, 0x36 }, /* highest */
+       { 0, 0x11 },    /* offset */
 };
 
-static const u8 TMP401_TEMP_LSB[6][2] = {
+static const u8 TMP401_TEMP_LSB[7][2] = {
        { 0x15, 0x10 }, /* temp */
        { 0x17, 0x14 }, /* low limit */
        { 0x16, 0x13 }, /* high limit */
        { 0, 0 },       /* therm (crit) limit (unused) */
        { 0x31, 0x35 }, /* lowest */
        { 0x33, 0x37 }, /* highest */
+       { 0, 0x12 },    /* offset */
 };
 
 static const u8 TMP432_TEMP_MSB_READ[4][3] = {
@@ -149,6 +152,7 @@ static const struct i2c_device_id tmp401_id[] = {
        { "tmp431", tmp431 },
        { "tmp432", tmp432 },
        { "tmp435", tmp435 },
+       { "tmp461", tmp461 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, tmp401_id);
@@ -170,7 +174,7 @@ struct tmp401_data {
        /* register values */
        u8 status[4];
        u8 config;
-       u16 temp[6][3];
+       u16 temp[7][3];
        u8 temp_crit_hyst;
 };
 
@@ -612,6 +616,22 @@ static const struct attribute_group tmp432_group = {
        .attrs = tmp432_attributes,
 };
 
+/*
+ * Additional features of the TMP461 chip.
+ * The TMP461 temperature offset for the remote channel.
+ */
+static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IWUSR | S_IRUGO, show_temp,
+                           store_temp, 6, 1);
+
+static struct attribute *tmp461_attributes[] = {
+       &sensor_dev_attr_temp2_offset.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group tmp461_group = {
+       .attrs = tmp461_attributes,
+};
+
 /*
  * Begin non sysfs callback code (aka Real code)
  */
@@ -714,7 +734,7 @@ static int tmp401_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        static const char * const names[] = {
-               "TMP401", "TMP411", "TMP431", "TMP432", "TMP435"
+               "TMP401", "TMP411", "TMP431", "TMP432", "TMP435", "TMP461"
        };
        struct device *dev = &client->dev;
        struct device *hwmon_dev;
@@ -745,6 +765,9 @@ static int tmp401_probe(struct i2c_client *client,
        if (data->kind == tmp432)
                data->groups[groups++] = &tmp432_group;
 
+       if (data->kind == tmp461)
+               data->groups[groups++] = &tmp461_group;
+
        hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
                                                           data, data->groups);
        if (IS_ERR(hwmon_dev))