diff options
Diffstat (limited to 'drivers/hwmon/lm80.c')
-rw-r--r-- | drivers/hwmon/lm80.c | 247 |
1 files changed, 178 insertions, 69 deletions
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 0891b38ffec0..e2c43e1774be 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * lm80.c - From lm_sensors, Linux kernel modules for hardware | 2 | * lm80.c - From lm_sensors, Linux kernel modules for hardware |
3 | * monitoring | 3 | * monitoring |
4 | * Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> | 4 | * Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> |
5 | * and Philip Edelbrock <phil@netroedge.com> | 5 | * and Philip Edelbrock <phil@netroedge.com> |
6 | * | 6 | * |
7 | * Ported to Linux 2.6 by Tiago Sousa <mirage@kaotik.org> | 7 | * Ported to Linux 2.6 by Tiago Sousa <mirage@kaotik.org> |
8 | * | 8 | * |
@@ -60,11 +60,17 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, | |||
60 | #define LM80_REG_FANDIV 0x05 | 60 | #define LM80_REG_FANDIV 0x05 |
61 | #define LM80_REG_RES 0x06 | 61 | #define LM80_REG_RES 0x06 |
62 | 62 | ||
63 | #define LM96080_REG_CONV_RATE 0x07 | ||
64 | #define LM96080_REG_MAN_ID 0x3e | ||
65 | #define LM96080_REG_DEV_ID 0x3f | ||
63 | 66 | ||
64 | /* Conversions. Rounding and limit checking is only done on the TO_REG | 67 | |
65 | variants. Note that you should be a bit careful with which arguments | 68 | /* |
66 | these macros are called: arguments may be evaluated more than once. | 69 | * Conversions. Rounding and limit checking is only done on the TO_REG |
67 | Fixing this is just not worth it. */ | 70 | * variants. Note that you should be a bit careful with which arguments |
71 | * these macros are called: arguments may be evaluated more than once. | ||
72 | * Fixing this is just not worth it. | ||
73 | */ | ||
68 | 74 | ||
69 | #define IN_TO_REG(val) (SENSORS_LIMIT(((val) + 5) / 10, 0, 255)) | 75 | #define IN_TO_REG(val) (SENSORS_LIMIT(((val) + 5) / 10, 0, 255)) |
70 | #define IN_FROM_REG(val) ((val) * 10) | 76 | #define IN_FROM_REG(val) ((val) * 10) |
@@ -108,6 +114,7 @@ static inline long TEMP_FROM_REG(u16 temp) | |||
108 | struct lm80_data { | 114 | struct lm80_data { |
109 | struct device *hwmon_dev; | 115 | struct device *hwmon_dev; |
110 | struct mutex update_lock; | 116 | struct mutex update_lock; |
117 | char error; /* !=0 if error occurred during last update */ | ||
111 | char valid; /* !=0 if following fields are valid */ | 118 | char valid; /* !=0 if following fields are valid */ |
112 | unsigned long last_updated; /* In jiffies */ | 119 | unsigned long last_updated; /* In jiffies */ |
113 | 120 | ||
@@ -144,6 +151,7 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); | |||
144 | 151 | ||
145 | static const struct i2c_device_id lm80_id[] = { | 152 | static const struct i2c_device_id lm80_id[] = { |
146 | { "lm80", 0 }, | 153 | { "lm80", 0 }, |
154 | { "lm96080", 1 }, | ||
147 | { } | 155 | { } |
148 | }; | 156 | }; |
149 | MODULE_DEVICE_TABLE(i2c, lm80_id); | 157 | MODULE_DEVICE_TABLE(i2c, lm80_id); |
@@ -170,6 +178,8 @@ static ssize_t show_in_##suffix(struct device *dev, \ | |||
170 | { \ | 178 | { \ |
171 | int nr = to_sensor_dev_attr(attr)->index; \ | 179 | int nr = to_sensor_dev_attr(attr)->index; \ |
172 | struct lm80_data *data = lm80_update_device(dev); \ | 180 | struct lm80_data *data = lm80_update_device(dev); \ |
181 | if (IS_ERR(data)) \ | ||
182 | return PTR_ERR(data); \ | ||
173 | return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \ | 183 | return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \ |
174 | } | 184 | } |
175 | show_in(min, in_min) | 185 | show_in(min, in_min) |
@@ -183,7 +193,10 @@ static ssize_t set_in_##suffix(struct device *dev, \ | |||
183 | int nr = to_sensor_dev_attr(attr)->index; \ | 193 | int nr = to_sensor_dev_attr(attr)->index; \ |
184 | struct i2c_client *client = to_i2c_client(dev); \ | 194 | struct i2c_client *client = to_i2c_client(dev); \ |
185 | struct lm80_data *data = i2c_get_clientdata(client); \ | 195 | struct lm80_data *data = i2c_get_clientdata(client); \ |
186 | long val = simple_strtol(buf, NULL, 10); \ | 196 | long val; \ |
197 | int err = kstrtol(buf, 10, &val); \ | ||
198 | if (err < 0) \ | ||
199 | return err; \ | ||
187 | \ | 200 | \ |
188 | mutex_lock(&data->update_lock);\ | 201 | mutex_lock(&data->update_lock);\ |
189 | data->value[nr] = IN_TO_REG(val); \ | 202 | data->value[nr] = IN_TO_REG(val); \ |
@@ -200,6 +213,8 @@ static ssize_t show_fan_##suffix(struct device *dev, \ | |||
200 | { \ | 213 | { \ |
201 | int nr = to_sensor_dev_attr(attr)->index; \ | 214 | int nr = to_sensor_dev_attr(attr)->index; \ |
202 | struct lm80_data *data = lm80_update_device(dev); \ | 215 | struct lm80_data *data = lm80_update_device(dev); \ |
216 | if (IS_ERR(data)) \ | ||
217 | return PTR_ERR(data); \ | ||
203 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \ | 218 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \ |
204 | DIV_FROM_REG(data->fan_div[nr]))); \ | 219 | DIV_FROM_REG(data->fan_div[nr]))); \ |
205 | } | 220 | } |
@@ -211,6 +226,8 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | |||
211 | { | 226 | { |
212 | int nr = to_sensor_dev_attr(attr)->index; | 227 | int nr = to_sensor_dev_attr(attr)->index; |
213 | struct lm80_data *data = lm80_update_device(dev); | 228 | struct lm80_data *data = lm80_update_device(dev); |
229 | if (IS_ERR(data)) | ||
230 | return PTR_ERR(data); | ||
214 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | 231 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); |
215 | } | 232 | } |
216 | 233 | ||
@@ -220,7 +237,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | |||
220 | int nr = to_sensor_dev_attr(attr)->index; | 237 | int nr = to_sensor_dev_attr(attr)->index; |
221 | struct i2c_client *client = to_i2c_client(dev); | 238 | struct i2c_client *client = to_i2c_client(dev); |
222 | struct lm80_data *data = i2c_get_clientdata(client); | 239 | struct lm80_data *data = i2c_get_clientdata(client); |
223 | long val = simple_strtoul(buf, NULL, 10); | 240 | unsigned long val; |
241 | int err = kstrtoul(buf, 10, &val); | ||
242 | if (err < 0) | ||
243 | return err; | ||
224 | 244 | ||
225 | mutex_lock(&data->update_lock); | 245 | mutex_lock(&data->update_lock); |
226 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 246 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
@@ -229,18 +249,23 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | |||
229 | return count; | 249 | return count; |
230 | } | 250 | } |
231 | 251 | ||
232 | /* Note: we save and restore the fan minimum here, because its value is | 252 | /* |
233 | determined in part by the fan divisor. This follows the principle of | 253 | * Note: we save and restore the fan minimum here, because its value is |
234 | least surprise; the user doesn't expect the fan minimum to change just | 254 | * determined in part by the fan divisor. This follows the principle of |
235 | because the divisor changed. */ | 255 | * least surprise; the user doesn't expect the fan minimum to change just |
256 | * because the divisor changed. | ||
257 | */ | ||
236 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | 258 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, |
237 | const char *buf, size_t count) | 259 | const char *buf, size_t count) |
238 | { | 260 | { |
239 | int nr = to_sensor_dev_attr(attr)->index; | 261 | int nr = to_sensor_dev_attr(attr)->index; |
240 | struct i2c_client *client = to_i2c_client(dev); | 262 | struct i2c_client *client = to_i2c_client(dev); |
241 | struct lm80_data *data = i2c_get_clientdata(client); | 263 | struct lm80_data *data = i2c_get_clientdata(client); |
242 | unsigned long min, val = simple_strtoul(buf, NULL, 10); | 264 | unsigned long min, val; |
243 | u8 reg; | 265 | u8 reg; |
266 | int err = kstrtoul(buf, 10, &val); | ||
267 | if (err < 0) | ||
268 | return err; | ||
244 | 269 | ||
245 | /* Save fan_min */ | 270 | /* Save fan_min */ |
246 | mutex_lock(&data->update_lock); | 271 | mutex_lock(&data->update_lock); |
@@ -283,6 +308,8 @@ static ssize_t show_temp_input1(struct device *dev, | |||
283 | struct device_attribute *attr, char *buf) | 308 | struct device_attribute *attr, char *buf) |
284 | { | 309 | { |
285 | struct lm80_data *data = lm80_update_device(dev); | 310 | struct lm80_data *data = lm80_update_device(dev); |
311 | if (IS_ERR(data)) | ||
312 | return PTR_ERR(data); | ||
286 | return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp)); | 313 | return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp)); |
287 | } | 314 | } |
288 | 315 | ||
@@ -291,6 +318,8 @@ static ssize_t show_temp_##suffix(struct device *dev, \ | |||
291 | struct device_attribute *attr, char *buf) \ | 318 | struct device_attribute *attr, char *buf) \ |
292 | { \ | 319 | { \ |
293 | struct lm80_data *data = lm80_update_device(dev); \ | 320 | struct lm80_data *data = lm80_update_device(dev); \ |
321 | if (IS_ERR(data)) \ | ||
322 | return PTR_ERR(data); \ | ||
294 | return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \ | 323 | return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \ |
295 | } | 324 | } |
296 | show_temp(hot_max, temp_hot_max); | 325 | show_temp(hot_max, temp_hot_max); |
@@ -304,7 +333,10 @@ static ssize_t set_temp_##suffix(struct device *dev, \ | |||
304 | { \ | 333 | { \ |
305 | struct i2c_client *client = to_i2c_client(dev); \ | 334 | struct i2c_client *client = to_i2c_client(dev); \ |
306 | struct lm80_data *data = i2c_get_clientdata(client); \ | 335 | struct lm80_data *data = i2c_get_clientdata(client); \ |
307 | long val = simple_strtoul(buf, NULL, 10); \ | 336 | long val; \ |
337 | int err = kstrtol(buf, 10, &val); \ | ||
338 | if (err < 0) \ | ||
339 | return err; \ | ||
308 | \ | 340 | \ |
309 | mutex_lock(&data->update_lock); \ | 341 | mutex_lock(&data->update_lock); \ |
310 | data->value = TEMP_LIMIT_TO_REG(val); \ | 342 | data->value = TEMP_LIMIT_TO_REG(val); \ |
@@ -321,6 +353,8 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, | |||
321 | char *buf) | 353 | char *buf) |
322 | { | 354 | { |
323 | struct lm80_data *data = lm80_update_device(dev); | 355 | struct lm80_data *data = lm80_update_device(dev); |
356 | if (IS_ERR(data)) | ||
357 | return PTR_ERR(data); | ||
324 | return sprintf(buf, "%u\n", data->alarms); | 358 | return sprintf(buf, "%u\n", data->alarms); |
325 | } | 359 | } |
326 | 360 | ||
@@ -329,6 +363,8 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, | |||
329 | { | 363 | { |
330 | int bitnr = to_sensor_dev_attr(attr)->index; | 364 | int bitnr = to_sensor_dev_attr(attr)->index; |
331 | struct lm80_data *data = lm80_update_device(dev); | 365 | struct lm80_data *data = lm80_update_device(dev); |
366 | if (IS_ERR(data)) | ||
367 | return PTR_ERR(data); | ||
332 | return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); | 368 | return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); |
333 | } | 369 | } |
334 | 370 | ||
@@ -459,23 +495,44 @@ static const struct attribute_group lm80_group = { | |||
459 | static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info) | 495 | static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info) |
460 | { | 496 | { |
461 | struct i2c_adapter *adapter = client->adapter; | 497 | struct i2c_adapter *adapter = client->adapter; |
462 | int i, cur; | 498 | int i, cur, man_id, dev_id; |
499 | const char *name = NULL; | ||
463 | 500 | ||
464 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 501 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
465 | return -ENODEV; | 502 | return -ENODEV; |
466 | 503 | ||
467 | /* Now, we do the remaining detection. It is lousy. */ | 504 | /* First check for unused bits, common to both chip types */ |
468 | if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) | 505 | if ((lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) |
506 | || (lm80_read_value(client, LM80_REG_CONFIG) & 0x80)) | ||
469 | return -ENODEV; | 507 | return -ENODEV; |
470 | for (i = 0x2a; i <= 0x3d; i++) { | 508 | |
471 | cur = i2c_smbus_read_byte_data(client, i); | 509 | /* |
472 | if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) | 510 | * The LM96080 has manufacturer and stepping/die rev registers so we |
473 | || (i2c_smbus_read_byte_data(client, i + 0x80) != cur) | 511 | * can just check that. The LM80 does not have such registers so we |
474 | || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) | 512 | * have to use a more expensive trick. |
513 | */ | ||
514 | man_id = lm80_read_value(client, LM96080_REG_MAN_ID); | ||
515 | dev_id = lm80_read_value(client, LM96080_REG_DEV_ID); | ||
516 | if (man_id == 0x01 && dev_id == 0x08) { | ||
517 | /* Check more unused bits for confirmation */ | ||
518 | if (lm80_read_value(client, LM96080_REG_CONV_RATE) & 0xfe) | ||
475 | return -ENODEV; | 519 | return -ENODEV; |
520 | |||
521 | name = "lm96080"; | ||
522 | } else { | ||
523 | /* Check 6-bit addressing */ | ||
524 | for (i = 0x2a; i <= 0x3d; i++) { | ||
525 | cur = i2c_smbus_read_byte_data(client, i); | ||
526 | if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) | ||
527 | || (i2c_smbus_read_byte_data(client, i + 0x80) != cur) | ||
528 | || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) | ||
529 | return -ENODEV; | ||
530 | } | ||
531 | |||
532 | name = "lm80"; | ||
476 | } | 533 | } |
477 | 534 | ||
478 | strlcpy(info->type, "lm80", I2C_NAME_SIZE); | 535 | strlcpy(info->type, name, I2C_NAME_SIZE); |
479 | 536 | ||
480 | return 0; | 537 | return 0; |
481 | } | 538 | } |
@@ -547,9 +604,11 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value) | |||
547 | /* Called when we have found a new LM80. */ | 604 | /* Called when we have found a new LM80. */ |
548 | static void lm80_init_client(struct i2c_client *client) | 605 | static void lm80_init_client(struct i2c_client *client) |
549 | { | 606 | { |
550 | /* Reset all except Watchdog values and last conversion values | 607 | /* |
551 | This sets fan-divs to 2, among others. This makes most other | 608 | * Reset all except Watchdog values and last conversion values |
552 | initializations unnecessary */ | 609 | * This sets fan-divs to 2, among others. This makes most other |
610 | * initializations unnecessary | ||
611 | */ | ||
553 | lm80_write_value(client, LM80_REG_CONFIG, 0x80); | 612 | lm80_write_value(client, LM80_REG_CONFIG, 0x80); |
554 | /* Set 11-bit temperature resolution */ | 613 | /* Set 11-bit temperature resolution */ |
555 | lm80_write_value(client, LM80_REG_RES, 0x08); | 614 | lm80_write_value(client, LM80_REG_RES, 0x08); |
@@ -563,66 +622,116 @@ static struct lm80_data *lm80_update_device(struct device *dev) | |||
563 | struct i2c_client *client = to_i2c_client(dev); | 622 | struct i2c_client *client = to_i2c_client(dev); |
564 | struct lm80_data *data = i2c_get_clientdata(client); | 623 | struct lm80_data *data = i2c_get_clientdata(client); |
565 | int i; | 624 | int i; |
625 | int rv; | ||
626 | int prev_rv; | ||
627 | struct lm80_data *ret = data; | ||
566 | 628 | ||
567 | mutex_lock(&data->update_lock); | 629 | mutex_lock(&data->update_lock); |
568 | 630 | ||
631 | if (data->error) | ||
632 | lm80_init_client(client); | ||
633 | |||
569 | if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { | 634 | if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { |
570 | dev_dbg(&client->dev, "Starting lm80 update\n"); | 635 | dev_dbg(&client->dev, "Starting lm80 update\n"); |
571 | for (i = 0; i <= 6; i++) { | 636 | for (i = 0; i <= 6; i++) { |
572 | data->in[i] = | 637 | rv = lm80_read_value(client, LM80_REG_IN(i)); |
573 | lm80_read_value(client, LM80_REG_IN(i)); | 638 | if (rv < 0) |
574 | data->in_min[i] = | 639 | goto abort; |
575 | lm80_read_value(client, LM80_REG_IN_MIN(i)); | 640 | data->in[i] = rv; |
576 | data->in_max[i] = | 641 | |
577 | lm80_read_value(client, LM80_REG_IN_MAX(i)); | 642 | rv = lm80_read_value(client, LM80_REG_IN_MIN(i)); |
643 | if (rv < 0) | ||
644 | goto abort; | ||
645 | data->in_min[i] = rv; | ||
646 | |||
647 | rv = lm80_read_value(client, LM80_REG_IN_MAX(i)); | ||
648 | if (rv < 0) | ||
649 | goto abort; | ||
650 | data->in_max[i] = rv; | ||
578 | } | 651 | } |
579 | data->fan[0] = lm80_read_value(client, LM80_REG_FAN1); | 652 | |
580 | data->fan_min[0] = | 653 | rv = lm80_read_value(client, LM80_REG_FAN1); |
581 | lm80_read_value(client, LM80_REG_FAN_MIN(1)); | 654 | if (rv < 0) |
582 | data->fan[1] = lm80_read_value(client, LM80_REG_FAN2); | 655 | goto abort; |
583 | data->fan_min[1] = | 656 | data->fan[0] = rv; |
584 | lm80_read_value(client, LM80_REG_FAN_MIN(2)); | 657 | |
585 | 658 | rv = lm80_read_value(client, LM80_REG_FAN_MIN(1)); | |
586 | data->temp = | 659 | if (rv < 0) |
587 | (lm80_read_value(client, LM80_REG_TEMP) << 8) | | 660 | goto abort; |
588 | (lm80_read_value(client, LM80_REG_RES) & 0xf0); | 661 | data->fan_min[0] = rv; |
589 | data->temp_os_max = | 662 | |
590 | lm80_read_value(client, LM80_REG_TEMP_OS_MAX); | 663 | rv = lm80_read_value(client, LM80_REG_FAN2); |
591 | data->temp_os_hyst = | 664 | if (rv < 0) |
592 | lm80_read_value(client, LM80_REG_TEMP_OS_HYST); | 665 | goto abort; |
593 | data->temp_hot_max = | 666 | data->fan[1] = rv; |
594 | lm80_read_value(client, LM80_REG_TEMP_HOT_MAX); | 667 | |
595 | data->temp_hot_hyst = | 668 | rv = lm80_read_value(client, LM80_REG_FAN_MIN(2)); |
596 | lm80_read_value(client, LM80_REG_TEMP_HOT_HYST); | 669 | if (rv < 0) |
597 | 670 | goto abort; | |
598 | i = lm80_read_value(client, LM80_REG_FANDIV); | 671 | data->fan_min[1] = rv; |
599 | data->fan_div[0] = (i >> 2) & 0x03; | 672 | |
600 | data->fan_div[1] = (i >> 4) & 0x03; | 673 | prev_rv = rv = lm80_read_value(client, LM80_REG_TEMP); |
601 | data->alarms = lm80_read_value(client, LM80_REG_ALARM1) + | 674 | if (rv < 0) |
602 | (lm80_read_value(client, LM80_REG_ALARM2) << 8); | 675 | goto abort; |
676 | rv = lm80_read_value(client, LM80_REG_RES); | ||
677 | if (rv < 0) | ||
678 | goto abort; | ||
679 | data->temp = (prev_rv << 8) | (rv & 0xf0); | ||
680 | |||
681 | rv = lm80_read_value(client, LM80_REG_TEMP_OS_MAX); | ||
682 | if (rv < 0) | ||
683 | goto abort; | ||
684 | data->temp_os_max = rv; | ||
685 | |||
686 | rv = lm80_read_value(client, LM80_REG_TEMP_OS_HYST); | ||
687 | if (rv < 0) | ||
688 | goto abort; | ||
689 | data->temp_os_hyst = rv; | ||
690 | |||
691 | rv = lm80_read_value(client, LM80_REG_TEMP_HOT_MAX); | ||
692 | if (rv < 0) | ||
693 | goto abort; | ||
694 | data->temp_hot_max = rv; | ||
695 | |||
696 | rv = lm80_read_value(client, LM80_REG_TEMP_HOT_HYST); | ||
697 | if (rv < 0) | ||
698 | goto abort; | ||
699 | data->temp_hot_hyst = rv; | ||
700 | |||
701 | rv = lm80_read_value(client, LM80_REG_FANDIV); | ||
702 | if (rv < 0) | ||
703 | goto abort; | ||
704 | data->fan_div[0] = (rv >> 2) & 0x03; | ||
705 | data->fan_div[1] = (rv >> 4) & 0x03; | ||
706 | |||
707 | prev_rv = rv = lm80_read_value(client, LM80_REG_ALARM1); | ||
708 | if (rv < 0) | ||
709 | goto abort; | ||
710 | rv = lm80_read_value(client, LM80_REG_ALARM2); | ||
711 | if (rv < 0) | ||
712 | goto abort; | ||
713 | data->alarms = prev_rv + (rv << 8); | ||
714 | |||
603 | data->last_updated = jiffies; | 715 | data->last_updated = jiffies; |
604 | data->valid = 1; | 716 | data->valid = 1; |
717 | data->error = 0; | ||
605 | } | 718 | } |
719 | goto done; | ||
720 | |||
721 | abort: | ||
722 | ret = ERR_PTR(rv); | ||
723 | data->valid = 0; | ||
724 | data->error = 1; | ||
606 | 725 | ||
726 | done: | ||
607 | mutex_unlock(&data->update_lock); | 727 | mutex_unlock(&data->update_lock); |
608 | 728 | ||
609 | return data; | 729 | return ret; |
610 | } | 730 | } |
611 | 731 | ||
612 | static int __init sensors_lm80_init(void) | 732 | module_i2c_driver(lm80_driver); |
613 | { | ||
614 | return i2c_add_driver(&lm80_driver); | ||
615 | } | ||
616 | |||
617 | static void __exit sensors_lm80_exit(void) | ||
618 | { | ||
619 | i2c_del_driver(&lm80_driver); | ||
620 | } | ||
621 | 733 | ||
622 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " | 734 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " |
623 | "Philip Edelbrock <phil@netroedge.com>"); | 735 | "Philip Edelbrock <phil@netroedge.com>"); |
624 | MODULE_DESCRIPTION("LM80 driver"); | 736 | MODULE_DESCRIPTION("LM80 driver"); |
625 | MODULE_LICENSE("GPL"); | 737 | MODULE_LICENSE("GPL"); |
626 | |||
627 | module_init(sensors_lm80_init); | ||
628 | module_exit(sensors_lm80_exit); | ||