aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/lm90.c
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 /drivers/hwmon/lm90.c
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>
Diffstat (limited to 'drivers/hwmon/lm90.c')
-rw-r--r--drivers/hwmon/lm90.c120
1 files changed, 93 insertions, 27 deletions
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index b2d9b3f0946..fe5d860fc83 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