Put ADT7461 into extended temperature range mode, which will change
the range of readings from 0..127 to -64..191 degC. Adjust the
register conversion functions accordingly. This also eliminates the
need to check the compatibility mode bit during probing since we
always force extended mode now.
Signed-off-by: Nate Case <ncase at xes-inc.com>
---
drivers/hwmon/lm90.c | 76 ++++++++++++++++++++++++++++++++++++-------------
1 files changed, 56 insertions(+), 20 deletions(-)
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 5f2db18..5a1fc2d 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -51,12 +51,11 @@
* The MAX6680 and MAX6681 only differ in the pinout so they can be
* treated identically.
*
- * This driver also supports the ADT7461 chip from Analog Devices but
- * only in its "compatability mode". If an ADT7461 chip is found but
- * is configured in non-compatible mode (where its temperature
- * register values are decoded differently) it is ignored by this
- * driver. Complete datasheet can be obtained from Analog's website
- * at:
+ * This driver also supports the ADT7461 chip from Analog Devices.
+ * The chip is placed into "extended mode" to support a range of
+ * -64..191 degC. It is mostly compatible with LM90 except for this
+ * data format difference in extended mode. Complete datasheet can be
+ * obtained from Analog's website at:
* http://www.analog.com/en/prod/0,2877,ADT7461,00.html
*
* Since the LM90 was the first chipset supported by this driver, most
@@ -242,22 +241,32 @@ static s16 temp2_to_reg(int val)
}
/*
- * ADT7461 is almost identical to LM90 except that attempts to write
- * values that are outside the range 0 < temp < 127 are treated as
- * the boundary value.
+ * ADT7461 versions of the above for "extended mode" operation
+ * which follows the same data format as LM90, but with an offset
+ * of 64 and unsigned integers. The range is restricted to -64..191 degC.
*/
+static int temp1_from_reg_adt7461(s8 val)
+{
+ return ((u8) val - 64) * 1000;
+}
+
+static int temp2_from_reg_adt7461(s16 val)
+{
+ return ((u16) val - 0x4000) / 32 * 125;
+}
+
static s8 temp1_to_reg_adt7461(int val)
{
- return val <= 0 ? 0 :
- val >= 127000 ? 127 :
- (val + 500) / 1000;
+ return val <= -64000 ? 0 :
+ val >= 191000 ? (s8) 0xff :
+ (s8) ((val + 500) / 1000 + 64);
}
static s16 temp2_to_reg_adt7461(int val)
{
- return val <= 0 ? 0 :
- val >= 127750 ? 0x7FC0 :
- (val + 125) / 250 * 64;
+ return val <= -64000 ? 0 :
+ val >= 191750 ? (s16) 0xffc0 :
+ (s16) ((val + 125) / 250 * 64 + 0x4000);
}
/*
@@ -269,7 +278,14 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm90_data *data = lm90_update_device(dev);
- return sprintf(buf, "%d\n", temp1_from_reg(data->temp8[attr->index]));
+ int temp;
+
+ if (data->kind == adt7461)
+ temp = temp1_from_reg_adt7461(data->temp8[attr->index]);
+ else
+ temp = temp1_from_reg(data->temp8[attr->index]);
+
+ return sprintf(buf, "%d\n", temp);
}
static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
@@ -303,7 +319,14 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm90_data *data = lm90_update_device(dev);
- return sprintf(buf, "%d\n", temp2_from_reg(data->temp11[attr->index]));
+ int temp;
+
+ if (data->kind == adt7461)
+ temp = temp2_from_reg_adt7461(data->temp11[attr->index]);
+ else
+ temp = temp2_from_reg(data->temp11[attr->index]);
+
+ return sprintf(buf, "%d\n", temp);
}
static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
@@ -342,8 +365,14 @@ static ssize_t show_temphyst(struct device *dev, struct device_attribute *devatt
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm90_data *data = lm90_update_device(dev);
- return sprintf(buf, "%d\n", temp1_from_reg(data->temp8[attr->index])
- - temp1_from_reg(data->temp_hyst));
+ int temp;
+
+ if (data->kind == adt7461)
+ temp = temp1_from_reg_adt7461(data->temp8[attr->index]);
+ else
+ temp = temp1_from_reg(data->temp8[attr->index]);
+
+ return sprintf(buf, "%d\n", temp - temp1_from_reg(data->temp_hyst));
}
static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
@@ -600,7 +629,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
kind = adm1032;
} else
if (chip_id == 0x51 /* ADT7461 */
- && (reg_config1 & 0x1F) == 0x00 /* check compat mode */
&& reg_convrate <= 0x0A) {
kind = adt7461;
}
@@ -733,6 +761,14 @@ static void lm90_init_client(struct i2c_client *client)
config |= 0x18;
}
+ /*
+ * Put ADT7461 into extended temperature range mode, which will
+ * change the range of readings from 0..127 to -64..191 degC.
+ * This also affects the format of the limit registers.
+ */
+ if (data->kind == adt7461)
+ config |= 0x04;
+
config &= 0xBF; /* run */
if (config != config_orig) /* Only write if changed */
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
--
1.5.4.4