hwmon: (lm90) Support MAX6646, MAX6647 and MAX6649
authorBen Hutchings <bhutchings@solarflare.com>
Fri, 17 Oct 2008 15:51:11 +0000 (17:51 +0200)
committerJean Delvare <khali@mahadeva.delvare>
Fri, 17 Oct 2008 15:51:11 +0000 (17:51 +0200)
These Maxim chips are similar to MAX6657 but use unsigned temperature
values to allow for readings up to 145 degrees.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Documentation/hwmon/lm90
drivers/hwmon/Kconfig
drivers/hwmon/lm90.c

index 53cd829f3f4d97dfea3336a6d3a954c81408665a..e0d5206d1de347d5d4aeb332f0511443e13beae5 100644 (file)
@@ -32,6 +32,21 @@ Supported chips:
     Addresses scanned: I2C 0x4c and 0x4d
     Datasheet: Publicly available at the ON Semiconductor website
                http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461
     Addresses scanned: I2C 0x4c and 0x4d
     Datasheet: Publicly available at the ON Semiconductor website
                http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461
+  * Maxim MAX6646
+    Prefix: 'max6646'
+    Addresses scanned: I2C 0x4d
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497
+  * Maxim MAX6647
+    Prefix: 'max6646'
+    Addresses scanned: I2C 0x4e
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497
+  * Maxim MAX6649
+    Prefix: 'max6646'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497
   * Maxim MAX6657
     Prefix: 'max6657'
     Addresses scanned: I2C 0x4c
   * Maxim MAX6657
     Prefix: 'max6657'
     Addresses scanned: I2C 0x4c
index 96701e099e8141b994fca6cb59e65399cb4b21dc..6de1e0ffd391efe9669fcae51df41beeb9a39407 100644 (file)
@@ -511,7 +511,8 @@ config SENSORS_LM90
        help
          If you say yes here you get support for National Semiconductor LM90,
          LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim
        help
          If you say yes here you get support for National Semiconductor LM90,
          LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim
-         MAX6657, MAX6658, MAX6659, MAX6680 and MAX6681 sensor chips.
+         MAX6646, MAX6647, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680 and
+         MAX6681 sensor chips.
 
          This driver can also be built as a module.  If so, the module
          will be called lm90.
 
          This driver can also be built as a module.  If so, the module
          will be called lm90.
index 85ba2c4feb46ce6826a2a009edf182ac475adc79..fe09f82c42e8891f8e6200a822091dacc2cd3bf7 100644 (file)
  * supported by this driver. These chips lack the remote temperature
  * offset feature.
  *
  * supported by this driver. These chips lack the remote temperature
  * offset feature.
  *
+ * This driver also supports the MAX6646, MAX6647 and MAX6649 chips
+ * made by Maxim.  These are again similar to the LM86, but they use
+ * unsigned temperature values and can report temperatures from 0 to
+ * 145 degrees.
+ *
  * This driver also supports the MAX6680 and MAX6681, two other sensor
  * chips made by Maxim. These are quite similar to the other Maxim
  * chips. The MAX6680 and MAX6681 only differ in the pinout so they can
  * This driver also supports the MAX6680 and MAX6681, two other sensor
  * chips made by Maxim. These are quite similar to the other Maxim
  * chips. The MAX6680 and MAX6681 only differ in the pinout so they can
  * Addresses to scan
  * Address is fully defined internally and cannot be changed except for
  * MAX6659, MAX6680 and MAX6681.
  * Addresses to scan
  * Address is fully defined internally and cannot be changed except for
  * MAX6659, MAX6680 and MAX6681.
- * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658
- * have address 0x4c.
- * ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d.
+ * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6649, MAX6657
+ * and MAX6658 have address 0x4c.
+ * ADM1032-2, ADT7461-2, LM89-1, LM99-1 and MAX6646 have address 0x4d.
+ * MAX6647 has address 0x4e.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
  * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
  * 0x4c, 0x4d or 0x4e.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
  * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
  * 0x4c, 0x4d or 0x4e.
@@ -91,7 +97,8 @@ static const unsigned short normal_i2c[] = {
  * Insmod parameters
  */
 
  * Insmod parameters
  */
 
-I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
+I2C_CLIENT_INSMOD_8(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680,
+                   max6646);
 
 /*
  * The LM90 registers
 
 /*
  * The LM90 registers
@@ -132,7 +139,7 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
 #define LM90_REG_R_TCRIT_HYST          0x21
 #define LM90_REG_W_TCRIT_HYST          0x21
 
 #define LM90_REG_R_TCRIT_HYST          0x21
 #define LM90_REG_W_TCRIT_HYST          0x21
 
-/* MAX6657-specific registers */
+/* MAX6646/6647/6649/6657/6658/6659 registers */
 
 #define MAX6657_REG_R_LOCAL_TEMPL      0x11
 
 
 #define MAX6657_REG_R_LOCAL_TEMPL      0x11
 
@@ -164,6 +171,9 @@ static const struct i2c_device_id lm90_id[] = {
        { "lm86", lm86 },
        { "lm89", lm99 },
        { "lm99", lm99 },       /* Missing temperature offset */
        { "lm86", lm86 },
        { "lm89", lm99 },
        { "lm99", lm99 },       /* Missing temperature offset */
+       { "max6646", max6646 },
+       { "max6647", max6646 },
+       { "max6649", max6646 },
        { "max6657", max6657 },
        { "max6658", max6657 },
        { "max6659", max6657 },
        { "max6657", max6657 },
        { "max6658", max6657 },
        { "max6659", max6657 },
@@ -205,7 +215,7 @@ struct lm90_data {
        s16 temp11[5];  /* 0: remote input
                           1: remote low limit
                           2: remote high limit
        s16 temp11[5];  /* 0: remote input
                           1: remote low limit
                           2: remote high limit
-                          3: remote offset (except max6657)
+                          3: remote offset (except max6646 and max6657)
                           4: local input */
        u8 temp_hyst;
        u8 alarms; /* bitvector */
                           4: local input */
        u8 temp_hyst;
        u8 alarms; /* bitvector */
@@ -216,7 +226,8 @@ struct lm90_data {
  * For local temperatures and limits, critical limits and the hysteresis
  * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
  * For remote temperatures and limits, it uses signed 11-bit values with
  * For local temperatures and limits, critical limits and the hysteresis
  * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
  * For remote temperatures and limits, it uses signed 11-bit values with
- * LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
+ * LSB = 0.125 degree Celsius, left-justified in 16-bit registers.  Some
+ * Maxim chips use unsigned values.
  */
 
 static inline int temp_from_s8(s8 val)
  */
 
 static inline int temp_from_s8(s8 val)
@@ -224,11 +235,21 @@ static inline int temp_from_s8(s8 val)
        return val * 1000;
 }
 
        return val * 1000;
 }
 
+static inline int temp_from_u8(u8 val)
+{
+       return val * 1000;
+}
+
 static inline int temp_from_s16(s16 val)
 {
        return val / 32 * 125;
 }
 
 static inline int temp_from_s16(s16 val)
 {
        return val / 32 * 125;
 }
 
+static inline int temp_from_u16(u16 val)
+{
+       return val / 32 * 125;
+}
+
 static s8 temp_to_s8(long val)
 {
        if (val <= -128000)
 static s8 temp_to_s8(long val)
 {
        if (val <= -128000)
@@ -240,6 +261,15 @@ static s8 temp_to_s8(long val)
        return (val + 500) / 1000;
 }
 
        return (val + 500) / 1000;
 }
 
+static u8 temp_to_u8(long val)
+{
+       if (val <= 0)
+               return 0;
+       if (val >= 255000)
+               return 255;
+       return (val + 500) / 1000;
+}
+
 static s16 temp_to_s16(long val)
 {
        if (val <= -128000)
 static s16 temp_to_s16(long val)
 {
        if (val <= -128000)
@@ -331,6 +361,8 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
 
        if (data->kind == adt7461)
                temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
 
        if (data->kind == adt7461)
                temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
+       else if (data->kind == max6646)
+               temp = temp_from_u8(data->temp8[attr->index]);
        else
                temp = temp_from_s8(data->temp8[attr->index]);
 
        else
                temp = temp_from_s8(data->temp8[attr->index]);
 
@@ -356,6 +388,8 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
        mutex_lock(&data->update_lock);
        if (data->kind == adt7461)
                data->temp8[nr] = temp_to_u8_adt7461(data, val);
        mutex_lock(&data->update_lock);
        if (data->kind == adt7461)
                data->temp8[nr] = temp_to_u8_adt7461(data, val);
+       else if (data->kind == max6646)
+               data->temp8[nr] = temp_to_u8(val);
        else
                data->temp8[nr] = temp_to_s8(val);
        i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]);
        else
                data->temp8[nr] = temp_to_s8(val);
        i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]);
@@ -372,6 +406,8 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
 
        if (data->kind == adt7461)
                temp = temp_from_u16_adt7461(data, data->temp11[attr->index]);
 
        if (data->kind == adt7461)
                temp = temp_from_u16_adt7461(data, data->temp11[attr->index]);
+       else if (data->kind == max6646)
+               temp = temp_from_u16(data->temp11[attr->index]);
        else
                temp = temp_from_s16(data->temp11[attr->index]);
 
        else
                temp = temp_from_s16(data->temp11[attr->index]);
 
@@ -401,12 +437,15 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
                data->temp11[nr] = temp_to_u16_adt7461(data, val);
        else if (data->kind == max6657 || data->kind == max6680)
                data->temp11[nr] = temp_to_s8(val) << 8;
                data->temp11[nr] = temp_to_u16_adt7461(data, val);
        else if (data->kind == max6657 || data->kind == max6680)
                data->temp11[nr] = temp_to_s8(val) << 8;
+       else if (data->kind == max6646)
+               data->temp11[nr] = temp_to_u8(val) << 8;
        else
                data->temp11[nr] = temp_to_s16(val);
 
        i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
                                  data->temp11[nr] >> 8);
        else
                data->temp11[nr] = temp_to_s16(val);
 
        i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
                                  data->temp11[nr] >> 8);
-       if (data->kind != max6657 && data->kind != max6680)
+       if (data->kind != max6657 && data->kind != max6680
+           && data->kind != max6646)
                i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
                                          data->temp11[nr] & 0xff);
        mutex_unlock(&data->update_lock);
                i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
                                          data->temp11[nr] & 0xff);
        mutex_unlock(&data->update_lock);
@@ -689,6 +728,16 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
                         && (reg_config1 & 0x03) == 0x00
                         && reg_convrate <= 0x07) {
                                kind = max6680;
                         && (reg_config1 & 0x03) == 0x00
                         && reg_convrate <= 0x07) {
                                kind = max6680;
+                       } else
+                       /* The chip_id register of the MAX6646/6647/6649
+                        * holds the revision of the chip.
+                        * The lowest 6 bits of the config1 register are
+                        * unused and should return zero when read.
+                        */
+                       if (chip_id == 0x59
+                        && (reg_config1 & 0x3f) == 0x00
+                        && reg_convrate <= 0x07) {
+                               kind = max6646;
                        }
                }
 
                        }
                }
 
@@ -719,6 +768,8 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
                name = "max6680";
        } else if (kind == adt7461) {
                name = "adt7461";
                name = "max6680";
        } else if (kind == adt7461) {
                name = "adt7461";
+       } else if (kind == max6646) {
+               name = "max6646";
        }
        strlcpy(info->type, name, I2C_NAME_SIZE);
 
        }
        strlcpy(info->type, name, I2C_NAME_SIZE);
 
@@ -758,7 +809,7 @@ static int lm90_probe(struct i2c_client *new_client,
                                              &dev_attr_pec)))
                        goto exit_remove_files;
        }
                                              &dev_attr_pec)))
                        goto exit_remove_files;
        }
-       if (data->kind != max6657) {
+       if (data->kind != max6657 && data->kind != max6646) {
                if ((err = device_create_file(&new_client->dev,
                                &sensor_dev_attr_temp2_offset.dev_attr)))
                        goto exit_remove_files;
                if ((err = device_create_file(&new_client->dev,
                                &sensor_dev_attr_temp2_offset.dev_attr)))
                        goto exit_remove_files;
@@ -824,7 +875,7 @@ static int lm90_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm90_group);
        device_remove_file(&client->dev, &dev_attr_pec);
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm90_group);
        device_remove_file(&client->dev, &dev_attr_pec);
-       if (data->kind != max6657)
+       if (data->kind != max6657 && data->kind != max6646)
                device_remove_file(&client->dev,
                                   &sensor_dev_attr_temp2_offset.dev_attr);
 
                device_remove_file(&client->dev,
                                   &sensor_dev_attr_temp2_offset.dev_attr);
 
@@ -881,7 +932,7 @@ static struct lm90_data *lm90_update_device(struct device *dev)
                lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
                lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
 
                lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
                lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
 
-               if (data->kind == max6657) {
+               if (data->kind == max6657 || data->kind == max6646) {
                        lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
                                    MAX6657_REG_R_LOCAL_TEMPL,
                                    &data->temp11[4]);
                        lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
                                    MAX6657_REG_R_LOCAL_TEMPL,
                                    &data->temp11[4]);
@@ -896,6 +947,7 @@ static struct lm90_data *lm90_update_device(struct device *dev)
                if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) {
                        data->temp11[1] = h << 8;
                        if (data->kind != max6657 && data->kind != max6680
                if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) {
                        data->temp11[1] = h << 8;
                        if (data->kind != max6657 && data->kind != max6680
+                        && data->kind != max6646
                         && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL,
                                          &l) == 0)
                                data->temp11[1] |= l;
                         && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL,
                                          &l) == 0)
                                data->temp11[1] |= l;
@@ -903,12 +955,13 @@ static struct lm90_data *lm90_update_device(struct device *dev)
                if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) {
                        data->temp11[2] = h << 8;
                        if (data->kind != max6657 && data->kind != max6680
                if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) {
                        data->temp11[2] = h << 8;
                        if (data->kind != max6657 && data->kind != max6680
+                        && data->kind != max6646
                         && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL,
                                          &l) == 0)
                                data->temp11[2] |= l;
                }
 
                         && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL,
                                          &l) == 0)
                                data->temp11[2] |= l;
                }
 
-               if (data->kind != max6657) {
+               if (data->kind != max6657 && data->kind != max6646) {
                        if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
                                          &h) == 0
                         && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,
                        if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
                                          &h) == 0
                         && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,
This page took 0.046843 seconds and 5 git commands to generate.