aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNate Case <ncase@xes-inc.com>2008-10-17 11:51:10 -0400
committerJean Delvare <khali@mahadeva.delvare>2008-10-17 11:51:10 -0400
commit23b2d4778ad33ee6bfe60439fb73c16580f204f2 (patch)
tree9122f72ca2c06558b6e1f176e277393c85dda52d
parentcea50fe2fdea36174aa24b58c69c4eb9770e7c49 (diff)
hwmon: (lm90) Support ADT7461 in extended mode
Support ADT7461 in extended temperature range mode, which will change the range of readings from 0..127 to -64..191 degC. Adjust the register conversion functions accordingly. Signed-off-by: Nate Case <ncase@xes-inc.com> Signed-off-by: Jean Delvare <khali@linux-fr.org> Tested-by: Martyn Welch <martyn.welch@gefanuc.com>
-rw-r--r--Documentation/hwmon/lm908
-rw-r--r--drivers/hwmon/Kconfig7
-rw-r--r--drivers/hwmon/lm90.c120
3 files changed, 97 insertions, 38 deletions
diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90
index 0c08c5c5637b..53cd829f3f4d 100644
--- a/Documentation/hwmon/lm90
+++ b/Documentation/hwmon/lm90
@@ -32,7 +32,6 @@ Supported chips:
32 Addresses scanned: I2C 0x4c and 0x4d 32 Addresses scanned: I2C 0x4c and 0x4d
33 Datasheet: Publicly available at the ON Semiconductor website 33 Datasheet: Publicly available at the ON Semiconductor website
34 http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461 34 http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461
35 Note: Only if in ADM1032 compatibility mode
36 * Maxim MAX6657 35 * Maxim MAX6657
37 Prefix: 'max6657' 36 Prefix: 'max6657'
38 Addresses scanned: I2C 0x4c 37 Addresses scanned: I2C 0x4c
@@ -70,16 +69,13 @@ Description
70 69
71The LM90 is a digital temperature sensor. It senses its own temperature as 70The LM90 is a digital temperature sensor. It senses its own temperature as
72well as the temperature of up to one external diode. It is compatible 71well as the temperature of up to one external diode. It is compatible
73with many other devices such as the LM86, the LM89, the LM99, the ADM1032, 72with many other devices, many of which are supported by this driver.
74the MAX6657, MAX6658, MAX6659, MAX6680 and the MAX6681 all of which are
75supported by this driver.
76 73
77Note that there is no easy way to differentiate between the MAX6657, 74Note that there is no easy way to differentiate between the MAX6657,
78MAX6658 and MAX6659 variants. The extra address and features of the 75MAX6658 and MAX6659 variants. The extra address and features of the
79MAX6659 are not supported by this driver. The MAX6680 and MAX6681 only 76MAX6659 are not supported by this driver. The MAX6680 and MAX6681 only
80differ in their pinout, therefore they obviously can't (and don't need to) 77differ in their pinout, therefore they obviously can't (and don't need to)
81be distinguished. Additionally, the ADT7461 is supported if found in 78be distinguished.
82ADM1032 compatibility mode.
83 79
84The specificity of this family of chipsets over the ADM1021/LM84 80The specificity of this family of chipsets over the ADM1021/LM84
85family is that it features critical limits with hysteresis, and an 81family is that it features critical limits with hysteresis, and an
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index ebacc0af40fe..96701e099e81 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -510,11 +510,8 @@ config SENSORS_LM90
510 depends on I2C 510 depends on I2C
511 help 511 help
512 If you say yes here you get support for National Semiconductor LM90, 512 If you say yes here you get support for National Semiconductor LM90,
513 LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657, 513 LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim
514 MAX6658, MAX6659, MAX6680 and MAX6681 sensor chips. 514 MAX6657, MAX6658, MAX6659, MAX6680 and MAX6681 sensor chips.
515
516 The Analog Devices ADT7461 sensor chip is also supported, but only
517 if found in ADM1032 compatibility mode.
518 515
519 This driver can also be built as a module. If so, the module 516 This driver can also be built as a module. If so, the module
520 will be called lm90. 517 will be called lm90.
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index b2d9b3f0946d..fe5d860fc838 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -37,11 +37,10 @@
37 * chips. The MAX6680 and MAX6681 only differ in the pinout so they can 37 * chips. The MAX6680 and MAX6681 only differ in the pinout so they can
38 * be treated identically. 38 * be treated identically.
39 * 39 *
40 * This driver also supports the ADT7461 chip from Analog Devices but 40 * This driver also supports the ADT7461 chip from Analog Devices.
41 * only in its "compatability mode". If an ADT7461 chip is found but 41 * It's supported in both compatibility and extended mode. It is mostly
42 * is configured in non-compatible mode (where its temperature 42 * compatible with LM90 except for a data format difference for the
43 * register values are decoded differently) it is ignored by this 43 * temperature value registers.
44 * driver.
45 * 44 *
46 * Since the LM90 was the first chipset supported by this driver, most 45 * Since the LM90 was the first chipset supported by this driver, most
47 * comments will refer to this chipset, but are actually general and 46 * comments will refer to this chipset, but are actually general and
@@ -138,6 +137,11 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
138#define MAX6657_REG_R_LOCAL_TEMPL 0x11 137#define MAX6657_REG_R_LOCAL_TEMPL 0x11
139 138
140/* 139/*
140 * Device flags
141 */
142#define LM90_FLAG_ADT7461_EXT 0x01 /* ADT7461 extended mode */
143
144/*
141 * Functions declaration 145 * Functions declaration
142 */ 146 */
143 147
@@ -191,6 +195,7 @@ struct lm90_data {
191 char valid; /* zero until following fields are valid */ 195 char valid; /* zero until following fields are valid */
192 unsigned long last_updated; /* in jiffies */ 196 unsigned long last_updated; /* in jiffies */
193 int kind; 197 int kind;
198 int flags;
194 199
195 /* registers values */ 200 /* registers values */
196 s8 temp8[4]; /* 0: local low limit 201 s8 temp8[4]; /* 0: local low limit
@@ -256,26 +261,61 @@ static u8 hyst_to_reg(long val)
256} 261}
257 262
258/* 263/*
259 * ADT7461 is almost identical to LM90 except that attempts to write 264 * ADT7461 in compatibility mode is almost identical to LM90 except that
260 * values that are outside the range 0 < temp < 127 are treated as 265 * attempts to write values that are outside the range 0 < temp < 127 are
261 * the boundary value. 266 * treated as the boundary value.
267 *
268 * ADT7461 in "extended mode" operation uses unsigned integers offset by
269 * 64 (e.g., 0 -> -64 degC). The range is restricted to -64..191 degC.
262 */ 270 */
263static u8 temp1_to_reg_adt7461(long val) 271static inline int temp1_from_reg_adt7461(struct lm90_data *data, u8 val)
264{ 272{
265 if (val <= 0) 273 if (data->flags & LM90_FLAG_ADT7461_EXT)
266 return 0; 274 return (val - 64) * 1000;
267 if (val >= 127000) 275 else
268 return 127; 276 return temp1_from_reg(val);
269 return (val + 500) / 1000;
270} 277}
271 278
272static u16 temp2_to_reg_adt7461(long val) 279static inline int temp2_from_reg_adt7461(struct lm90_data *data, u16 val)
273{ 280{
274 if (val <= 0) 281 if (data->flags & LM90_FLAG_ADT7461_EXT)
275 return 0; 282 return (val - 0x4000) / 64 * 250;
276 if (val >= 127750) 283 else
277 return 0x7FC0; 284 return temp2_from_reg(val);
278 return (val + 125) / 250 * 64; 285}
286
287static u8 temp1_to_reg_adt7461(struct lm90_data *data, long val)
288{
289 if (data->flags & LM90_FLAG_ADT7461_EXT) {
290 if (val <= -64000)
291 return 0;
292 if (val >= 191000)
293 return 0xFF;
294 return (val + 500 + 64000) / 1000;
295 } else {
296 if (val <= 0)
297 return 0;
298 if (val >= 127000)
299 return 127;
300 return (val + 500) / 1000;
301 }
302}
303
304static u16 temp2_to_reg_adt7461(struct lm90_data *data, long val)
305{
306 if (data->flags & LM90_FLAG_ADT7461_EXT) {
307 if (val <= -64000)
308 return 0;
309 if (val >= 191750)
310 return 0xFFC0;
311 return (val + 64000 + 125) / 250 * 64;
312 } else {
313 if (val <= 0)
314 return 0;
315 if (val >= 127750)
316 return 0x7FC0;
317 return (val + 125) / 250 * 64;
318 }
279} 319}
280 320
281/* 321/*
@@ -287,7 +327,14 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
287{ 327{
288 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 328 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
289 struct lm90_data *data = lm90_update_device(dev); 329 struct lm90_data *data = lm90_update_device(dev);
290 return sprintf(buf, "%d\n", temp1_from_reg(data->temp8[attr->index])); 330 int temp;
331
332 if (data->kind == adt7461)
333 temp = temp1_from_reg_adt7461(data, data->temp8[attr->index]);
334 else
335 temp = temp1_from_reg(data->temp8[attr->index]);
336
337 return sprintf(buf, "%d\n", temp);
291} 338}
292 339
293static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, 340static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
@@ -308,7 +355,7 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
308 355
309 mutex_lock(&data->update_lock); 356 mutex_lock(&data->update_lock);
310 if (data->kind == adt7461) 357 if (data->kind == adt7461)
311 data->temp8[nr] = temp1_to_reg_adt7461(val); 358 data->temp8[nr] = temp1_to_reg_adt7461(data, val);
312 else 359 else
313 data->temp8[nr] = temp1_to_reg(val); 360 data->temp8[nr] = temp1_to_reg(val);
314 i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]); 361 i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]);
@@ -321,7 +368,14 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
321{ 368{
322 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 369 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
323 struct lm90_data *data = lm90_update_device(dev); 370 struct lm90_data *data = lm90_update_device(dev);
324 return sprintf(buf, "%d\n", temp2_from_reg(data->temp11[attr->index])); 371 int temp;
372
373 if (data->kind == adt7461)
374 temp = temp2_from_reg_adt7461(data, data->temp11[attr->index]);
375 else
376 temp = temp2_from_reg(data->temp11[attr->index]);
377
378 return sprintf(buf, "%d\n", temp);
325} 379}
326 380
327static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, 381static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
@@ -344,7 +398,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
344 398
345 mutex_lock(&data->update_lock); 399 mutex_lock(&data->update_lock);
346 if (data->kind == adt7461) 400 if (data->kind == adt7461)
347 data->temp11[nr] = temp2_to_reg_adt7461(val); 401 data->temp11[nr] = temp2_to_reg_adt7461(data, val);
348 else if (data->kind == max6657 || data->kind == max6680) 402 else if (data->kind == max6657 || data->kind == max6680)
349 data->temp11[nr] = temp1_to_reg(val) << 8; 403 data->temp11[nr] = temp1_to_reg(val) << 8;
350 else 404 else
@@ -364,8 +418,14 @@ static ssize_t show_temphyst(struct device *dev, struct device_attribute *devatt
364{ 418{
365 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 419 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
366 struct lm90_data *data = lm90_update_device(dev); 420 struct lm90_data *data = lm90_update_device(dev);
367 return sprintf(buf, "%d\n", temp1_from_reg(data->temp8[attr->index]) 421 int temp;
368 - temp1_from_reg(data->temp_hyst)); 422
423 if (data->kind == adt7461)
424 temp = temp1_from_reg_adt7461(data, data->temp8[attr->index]);
425 else
426 temp = temp1_from_reg(data->temp8[attr->index]);
427
428 return sprintf(buf, "%d\n", temp - temp1_from_reg(data->temp_hyst));
369} 429}
370 430
371static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy, 431static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
@@ -598,7 +658,7 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
598 kind = adm1032; 658 kind = adm1032;
599 } else 659 } else
600 if (chip_id == 0x51 /* ADT7461 */ 660 if (chip_id == 0x51 /* ADT7461 */
601 && (reg_config1 & 0x1F) == 0x00 /* check compat mode */ 661 && (reg_config1 & 0x1B) == 0x00
602 && reg_convrate <= 0x0A) { 662 && reg_convrate <= 0x0A) {
603 kind = adt7461; 663 kind = adt7461;
604 } 664 }
@@ -737,6 +797,12 @@ static void lm90_init_client(struct i2c_client *client)
737 } 797 }
738 config_orig = config; 798 config_orig = config;
739 799
800 /* Check Temperature Range Select */
801 if (data->kind == adt7461) {
802 if (config & 0x04)
803 data->flags |= LM90_FLAG_ADT7461_EXT;
804 }
805
740 /* 806 /*
741 * Put MAX6680/MAX8881 into extended resolution (bit 0x10, 807 * Put MAX6680/MAX8881 into extended resolution (bit 0x10,
742 * 0.125 degree resolution) and range (0x08, extend range 808 * 0.125 degree resolution) and range (0x08, extend range