diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-15 19:35:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-15 19:35:10 -0500 |
commit | 16cd9d1c0f149ee0c8073de037e7c57886234aa0 (patch) | |
tree | 8d9f08b1043b3e08eefbe46ceea7a5ea56380335 /drivers/hwmon | |
parent | f412f2c60b480fa5140a4b4cb321cd48c64e1812 (diff) | |
parent | aae7bce48176d5ffa4ccd4dbdb861488db892837 (diff) |
Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
Pull hwmon fixes and updates from Jean Delvare:
"All lm90 driver fixes and improvements"
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
Documentation: dt: hwmon: Add OF document for LM90
hwmon: (lm90) Add power control
hwmon: (lm90) Add support for TI TMP451
hwmon: (lm90) Use enums for the indexes of temp8 and temp11
hwmon: (lm90) Add support to handle IRQ
hwmon: (lm90) Define status bits
hwmon: (lm90) Fix max6696 alarm handling
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/lm90.c | 327 |
1 files changed, 230 insertions, 97 deletions
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index cdff74282955..4c4c1421bf28 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
@@ -60,6 +60,11 @@ | |||
60 | * This driver also supports the G781 from GMT. This device is compatible | 60 | * This driver also supports the G781 from GMT. This device is compatible |
61 | * with the ADM1032. | 61 | * with the ADM1032. |
62 | * | 62 | * |
63 | * This driver also supports TMP451 from Texas Instruments. This device is | ||
64 | * supported in both compatibility and extended mode. It's mostly compatible | ||
65 | * with ADT7461 except for local temperature low byte register and max | ||
66 | * conversion rate. | ||
67 | * | ||
63 | * Since the LM90 was the first chipset supported by this driver, most | 68 | * Since the LM90 was the first chipset supported by this driver, most |
64 | * comments will refer to this chipset, but are actually general and | 69 | * comments will refer to this chipset, but are actually general and |
65 | * concern all supported chipsets, unless mentioned otherwise. | 70 | * concern all supported chipsets, unless mentioned otherwise. |
@@ -89,6 +94,8 @@ | |||
89 | #include <linux/err.h> | 94 | #include <linux/err.h> |
90 | #include <linux/mutex.h> | 95 | #include <linux/mutex.h> |
91 | #include <linux/sysfs.h> | 96 | #include <linux/sysfs.h> |
97 | #include <linux/interrupt.h> | ||
98 | #include <linux/regulator/consumer.h> | ||
92 | 99 | ||
93 | /* | 100 | /* |
94 | * Addresses to scan | 101 | * Addresses to scan |
@@ -110,7 +117,7 @@ static const unsigned short normal_i2c[] = { | |||
110 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; | 117 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; |
111 | 118 | ||
112 | enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | 119 | enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, |
113 | max6646, w83l771, max6696, sa56004, g781 }; | 120 | max6646, w83l771, max6696, sa56004, g781, tmp451 }; |
114 | 121 | ||
115 | /* | 122 | /* |
116 | * The LM90 registers | 123 | * The LM90 registers |
@@ -167,6 +174,9 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | |||
167 | #define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ | 174 | #define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ |
168 | #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ | 175 | #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ |
169 | 176 | ||
177 | /* TMP451 registers */ | ||
178 | #define TMP451_REG_R_LOCAL_TEMPL 0x15 | ||
179 | |||
170 | /* | 180 | /* |
171 | * Device flags | 181 | * Device flags |
172 | */ | 182 | */ |
@@ -179,6 +189,23 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | |||
179 | #define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */ | 189 | #define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */ |
180 | #define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */ | 190 | #define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */ |
181 | 191 | ||
192 | /* LM90 status */ | ||
193 | #define LM90_STATUS_LTHRM (1 << 0) /* local THERM limit tripped */ | ||
194 | #define LM90_STATUS_RTHRM (1 << 1) /* remote THERM limit tripped */ | ||
195 | #define LM90_STATUS_ROPEN (1 << 2) /* remote is an open circuit */ | ||
196 | #define LM90_STATUS_RLOW (1 << 3) /* remote low temp limit tripped */ | ||
197 | #define LM90_STATUS_RHIGH (1 << 4) /* remote high temp limit tripped */ | ||
198 | #define LM90_STATUS_LLOW (1 << 5) /* local low temp limit tripped */ | ||
199 | #define LM90_STATUS_LHIGH (1 << 6) /* local high temp limit tripped */ | ||
200 | |||
201 | #define MAX6696_STATUS2_R2THRM (1 << 1) /* remote2 THERM limit tripped */ | ||
202 | #define MAX6696_STATUS2_R2OPEN (1 << 2) /* remote2 is an open circuit */ | ||
203 | #define MAX6696_STATUS2_R2LOW (1 << 3) /* remote2 low temp limit tripped */ | ||
204 | #define MAX6696_STATUS2_R2HIGH (1 << 4) /* remote2 high temp limit tripped */ | ||
205 | #define MAX6696_STATUS2_ROT2 (1 << 5) /* remote emergency limit tripped */ | ||
206 | #define MAX6696_STATUS2_R2OT2 (1 << 6) /* remote2 emergency limit tripped */ | ||
207 | #define MAX6696_STATUS2_LOT2 (1 << 7) /* local emergency limit tripped */ | ||
208 | |||
182 | /* | 209 | /* |
183 | * Driver data (common to all clients) | 210 | * Driver data (common to all clients) |
184 | */ | 211 | */ |
@@ -205,6 +232,7 @@ static const struct i2c_device_id lm90_id[] = { | |||
205 | { "nct1008", adt7461 }, | 232 | { "nct1008", adt7461 }, |
206 | { "w83l771", w83l771 }, | 233 | { "w83l771", w83l771 }, |
207 | { "sa56004", sa56004 }, | 234 | { "sa56004", sa56004 }, |
235 | { "tmp451", tmp451 }, | ||
208 | { } | 236 | { } |
209 | }; | 237 | }; |
210 | MODULE_DEVICE_TABLE(i2c, lm90_id); | 238 | MODULE_DEVICE_TABLE(i2c, lm90_id); |
@@ -278,7 +306,7 @@ static const struct lm90_params lm90_params[] = { | |||
278 | [max6696] = { | 306 | [max6696] = { |
279 | .flags = LM90_HAVE_EMERGENCY | 307 | .flags = LM90_HAVE_EMERGENCY |
280 | | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, | 308 | | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, |
281 | .alert_alarms = 0x187c, | 309 | .alert_alarms = 0x1c7c, |
282 | .max_convrate = 6, | 310 | .max_convrate = 6, |
283 | .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, | 311 | .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, |
284 | }, | 312 | }, |
@@ -293,6 +321,43 @@ static const struct lm90_params lm90_params[] = { | |||
293 | .max_convrate = 9, | 321 | .max_convrate = 9, |
294 | .reg_local_ext = SA56004_REG_R_LOCAL_TEMPL, | 322 | .reg_local_ext = SA56004_REG_R_LOCAL_TEMPL, |
295 | }, | 323 | }, |
324 | [tmp451] = { | ||
325 | .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | ||
326 | | LM90_HAVE_BROKEN_ALERT, | ||
327 | .alert_alarms = 0x7c, | ||
328 | .max_convrate = 9, | ||
329 | .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL, | ||
330 | } | ||
331 | }; | ||
332 | |||
333 | /* | ||
334 | * TEMP8 register index | ||
335 | */ | ||
336 | enum lm90_temp8_reg_index { | ||
337 | LOCAL_LOW = 0, | ||
338 | LOCAL_HIGH, | ||
339 | LOCAL_CRIT, | ||
340 | REMOTE_CRIT, | ||
341 | LOCAL_EMERG, /* max6659 and max6695/96 */ | ||
342 | REMOTE_EMERG, /* max6659 and max6695/96 */ | ||
343 | REMOTE2_CRIT, /* max6695/96 only */ | ||
344 | REMOTE2_EMERG, /* max6695/96 only */ | ||
345 | TEMP8_REG_NUM | ||
346 | }; | ||
347 | |||
348 | /* | ||
349 | * TEMP11 register index | ||
350 | */ | ||
351 | enum lm90_temp11_reg_index { | ||
352 | REMOTE_TEMP = 0, | ||
353 | REMOTE_LOW, | ||
354 | REMOTE_HIGH, | ||
355 | REMOTE_OFFSET, /* except max6646, max6657/58/59, and max6695/96 */ | ||
356 | LOCAL_TEMP, | ||
357 | REMOTE2_TEMP, /* max6695/96 only */ | ||
358 | REMOTE2_LOW, /* max6695/96 only */ | ||
359 | REMOTE2_HIGH, /* max6695/96 only */ | ||
360 | TEMP11_REG_NUM | ||
296 | }; | 361 | }; |
297 | 362 | ||
298 | /* | 363 | /* |
@@ -302,6 +367,7 @@ static const struct lm90_params lm90_params[] = { | |||
302 | struct lm90_data { | 367 | struct lm90_data { |
303 | struct device *hwmon_dev; | 368 | struct device *hwmon_dev; |
304 | struct mutex update_lock; | 369 | struct mutex update_lock; |
370 | struct regulator *regulator; | ||
305 | char valid; /* zero until following fields are valid */ | 371 | char valid; /* zero until following fields are valid */ |
306 | unsigned long last_updated; /* in jiffies */ | 372 | unsigned long last_updated; /* in jiffies */ |
307 | int kind; | 373 | int kind; |
@@ -317,25 +383,8 @@ struct lm90_data { | |||
317 | u8 reg_local_ext; /* local extension register offset */ | 383 | u8 reg_local_ext; /* local extension register offset */ |
318 | 384 | ||
319 | /* registers values */ | 385 | /* registers values */ |
320 | s8 temp8[8]; /* 0: local low limit | 386 | s8 temp8[TEMP8_REG_NUM]; |
321 | * 1: local high limit | 387 | s16 temp11[TEMP11_REG_NUM]; |
322 | * 2: local critical limit | ||
323 | * 3: remote critical limit | ||
324 | * 4: local emergency limit (max6659 and max6695/96) | ||
325 | * 5: remote emergency limit (max6659 and max6695/96) | ||
326 | * 6: remote 2 critical limit (max6695/96 only) | ||
327 | * 7: remote 2 emergency limit (max6695/96 only) | ||
328 | */ | ||
329 | s16 temp11[8]; /* 0: remote input | ||
330 | * 1: remote low limit | ||
331 | * 2: remote high limit | ||
332 | * 3: remote offset (except max6646, max6657/58/59, | ||
333 | * and max6695/96) | ||
334 | * 4: local input | ||
335 | * 5: remote 2 input (max6695/96 only) | ||
336 | * 6: remote 2 low limit (max6695/96 only) | ||
337 | * 7: remote 2 high limit (max6695/96 only) | ||
338 | */ | ||
339 | u8 temp_hyst; | 388 | u8 temp_hyst; |
340 | u16 alarms; /* bitvector (upper 8 bits for max6695/96) */ | 389 | u16 alarms; /* bitvector (upper 8 bits for max6695/96) */ |
341 | }; | 390 | }; |
@@ -477,37 +526,42 @@ static struct lm90_data *lm90_update_device(struct device *dev) | |||
477 | u8 alarms; | 526 | u8 alarms; |
478 | 527 | ||
479 | dev_dbg(&client->dev, "Updating lm90 data.\n"); | 528 | dev_dbg(&client->dev, "Updating lm90 data.\n"); |
480 | lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[0]); | 529 | lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, |
481 | lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[1]); | 530 | &data->temp8[LOCAL_LOW]); |
482 | lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[2]); | 531 | lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, |
483 | lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]); | 532 | &data->temp8[LOCAL_HIGH]); |
533 | lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, | ||
534 | &data->temp8[LOCAL_CRIT]); | ||
535 | lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, | ||
536 | &data->temp8[REMOTE_CRIT]); | ||
484 | lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); | 537 | lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); |
485 | 538 | ||
486 | if (data->reg_local_ext) { | 539 | if (data->reg_local_ext) { |
487 | lm90_read16(client, LM90_REG_R_LOCAL_TEMP, | 540 | lm90_read16(client, LM90_REG_R_LOCAL_TEMP, |
488 | data->reg_local_ext, | 541 | data->reg_local_ext, |
489 | &data->temp11[4]); | 542 | &data->temp11[LOCAL_TEMP]); |
490 | } else { | 543 | } else { |
491 | if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, | 544 | if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, |
492 | &h) == 0) | 545 | &h) == 0) |
493 | data->temp11[4] = h << 8; | 546 | data->temp11[LOCAL_TEMP] = h << 8; |
494 | } | 547 | } |
495 | lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, | 548 | lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, |
496 | LM90_REG_R_REMOTE_TEMPL, &data->temp11[0]); | 549 | LM90_REG_R_REMOTE_TEMPL, |
550 | &data->temp11[REMOTE_TEMP]); | ||
497 | 551 | ||
498 | if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) { | 552 | if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) { |
499 | data->temp11[1] = h << 8; | 553 | data->temp11[REMOTE_LOW] = h << 8; |
500 | if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) | 554 | if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) |
501 | && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, | 555 | && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, |
502 | &l) == 0) | 556 | &l) == 0) |
503 | data->temp11[1] |= l; | 557 | data->temp11[REMOTE_LOW] |= l; |
504 | } | 558 | } |
505 | if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) { | 559 | if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) { |
506 | data->temp11[2] = h << 8; | 560 | data->temp11[REMOTE_HIGH] = h << 8; |
507 | if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) | 561 | if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) |
508 | && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, | 562 | && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, |
509 | &l) == 0) | 563 | &l) == 0) |
510 | data->temp11[2] |= l; | 564 | data->temp11[REMOTE_HIGH] |= l; |
511 | } | 565 | } |
512 | 566 | ||
513 | if (data->flags & LM90_HAVE_OFFSET) { | 567 | if (data->flags & LM90_HAVE_OFFSET) { |
@@ -515,13 +569,13 @@ static struct lm90_data *lm90_update_device(struct device *dev) | |||
515 | &h) == 0 | 569 | &h) == 0 |
516 | && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, | 570 | && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, |
517 | &l) == 0) | 571 | &l) == 0) |
518 | data->temp11[3] = (h << 8) | l; | 572 | data->temp11[REMOTE_OFFSET] = (h << 8) | l; |
519 | } | 573 | } |
520 | if (data->flags & LM90_HAVE_EMERGENCY) { | 574 | if (data->flags & LM90_HAVE_EMERGENCY) { |
521 | lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG, | 575 | lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG, |
522 | &data->temp8[4]); | 576 | &data->temp8[LOCAL_EMERG]); |
523 | lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, | 577 | lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, |
524 | &data->temp8[5]); | 578 | &data->temp8[REMOTE_EMERG]); |
525 | } | 579 | } |
526 | lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); | 580 | lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); |
527 | data->alarms = alarms; /* save as 16 bit value */ | 581 | data->alarms = alarms; /* save as 16 bit value */ |
@@ -529,15 +583,16 @@ static struct lm90_data *lm90_update_device(struct device *dev) | |||
529 | if (data->kind == max6696) { | 583 | if (data->kind == max6696) { |
530 | lm90_select_remote_channel(client, data, 1); | 584 | lm90_select_remote_channel(client, data, 1); |
531 | lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, | 585 | lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, |
532 | &data->temp8[6]); | 586 | &data->temp8[REMOTE2_CRIT]); |
533 | lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, | 587 | lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, |
534 | &data->temp8[7]); | 588 | &data->temp8[REMOTE2_EMERG]); |
535 | lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, | 589 | lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, |
536 | LM90_REG_R_REMOTE_TEMPL, &data->temp11[5]); | 590 | LM90_REG_R_REMOTE_TEMPL, |
591 | &data->temp11[REMOTE2_TEMP]); | ||
537 | if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h)) | 592 | if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h)) |
538 | data->temp11[6] = h << 8; | 593 | data->temp11[REMOTE2_LOW] = h << 8; |
539 | if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h)) | 594 | if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h)) |
540 | data->temp11[7] = h << 8; | 595 | data->temp11[REMOTE2_HIGH] = h << 8; |
541 | lm90_select_remote_channel(client, data, 0); | 596 | lm90_select_remote_channel(client, data, 0); |
542 | 597 | ||
543 | if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2, | 598 | if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2, |
@@ -709,7 +764,7 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, | |||
709 | struct lm90_data *data = lm90_update_device(dev); | 764 | struct lm90_data *data = lm90_update_device(dev); |
710 | int temp; | 765 | int temp; |
711 | 766 | ||
712 | if (data->kind == adt7461) | 767 | if (data->kind == adt7461 || data->kind == tmp451) |
713 | temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); | 768 | temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); |
714 | else if (data->kind == max6646) | 769 | else if (data->kind == max6646) |
715 | temp = temp_from_u8(data->temp8[attr->index]); | 770 | temp = temp_from_u8(data->temp8[attr->index]); |
@@ -726,7 +781,7 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, | |||
726 | static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, | 781 | static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, |
727 | const char *buf, size_t count) | 782 | const char *buf, size_t count) |
728 | { | 783 | { |
729 | static const u8 reg[8] = { | 784 | static const u8 reg[TEMP8_REG_NUM] = { |
730 | LM90_REG_W_LOCAL_LOW, | 785 | LM90_REG_W_LOCAL_LOW, |
731 | LM90_REG_W_LOCAL_HIGH, | 786 | LM90_REG_W_LOCAL_HIGH, |
732 | LM90_REG_W_LOCAL_CRIT, | 787 | LM90_REG_W_LOCAL_CRIT, |
@@ -753,7 +808,7 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, | |||
753 | val -= 16000; | 808 | val -= 16000; |
754 | 809 | ||
755 | mutex_lock(&data->update_lock); | 810 | mutex_lock(&data->update_lock); |
756 | if (data->kind == adt7461) | 811 | if (data->kind == adt7461 || data->kind == tmp451) |
757 | data->temp8[nr] = temp_to_u8_adt7461(data, val); | 812 | data->temp8[nr] = temp_to_u8_adt7461(data, val); |
758 | else if (data->kind == max6646) | 813 | else if (data->kind == max6646) |
759 | data->temp8[nr] = temp_to_u8(val); | 814 | data->temp8[nr] = temp_to_u8(val); |
@@ -775,7 +830,7 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, | |||
775 | struct lm90_data *data = lm90_update_device(dev); | 830 | struct lm90_data *data = lm90_update_device(dev); |
776 | int temp; | 831 | int temp; |
777 | 832 | ||
778 | if (data->kind == adt7461) | 833 | if (data->kind == adt7461 || data->kind == tmp451) |
779 | temp = temp_from_u16_adt7461(data, data->temp11[attr->index]); | 834 | temp = temp_from_u16_adt7461(data, data->temp11[attr->index]); |
780 | else if (data->kind == max6646) | 835 | else if (data->kind == max6646) |
781 | temp = temp_from_u16(data->temp11[attr->index]); | 836 | temp = temp_from_u16(data->temp11[attr->index]); |
@@ -821,7 +876,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, | |||
821 | val -= 16000; | 876 | val -= 16000; |
822 | 877 | ||
823 | mutex_lock(&data->update_lock); | 878 | mutex_lock(&data->update_lock); |
824 | if (data->kind == adt7461) | 879 | if (data->kind == adt7461 || data->kind == tmp451) |
825 | data->temp11[index] = temp_to_u16_adt7461(data, val); | 880 | data->temp11[index] = temp_to_u16_adt7461(data, val); |
826 | else if (data->kind == max6646) | 881 | else if (data->kind == max6646) |
827 | data->temp11[index] = temp_to_u8(val) << 8; | 882 | data->temp11[index] = temp_to_u8(val) << 8; |
@@ -850,7 +905,7 @@ static ssize_t show_temphyst(struct device *dev, | |||
850 | struct lm90_data *data = lm90_update_device(dev); | 905 | struct lm90_data *data = lm90_update_device(dev); |
851 | int temp; | 906 | int temp; |
852 | 907 | ||
853 | if (data->kind == adt7461) | 908 | if (data->kind == adt7461 || data->kind == tmp451) |
854 | temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); | 909 | temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); |
855 | else if (data->kind == max6646) | 910 | else if (data->kind == max6646) |
856 | temp = temp_from_u8(data->temp8[attr->index]); | 911 | temp = temp_from_u8(data->temp8[attr->index]); |
@@ -878,12 +933,12 @@ static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy, | |||
878 | return err; | 933 | return err; |
879 | 934 | ||
880 | mutex_lock(&data->update_lock); | 935 | mutex_lock(&data->update_lock); |
881 | if (data->kind == adt7461) | 936 | if (data->kind == adt7461 || data->kind == tmp451) |
882 | temp = temp_from_u8_adt7461(data, data->temp8[2]); | 937 | temp = temp_from_u8_adt7461(data, data->temp8[LOCAL_CRIT]); |
883 | else if (data->kind == max6646) | 938 | else if (data->kind == max6646) |
884 | temp = temp_from_u8(data->temp8[2]); | 939 | temp = temp_from_u8(data->temp8[LOCAL_CRIT]); |
885 | else | 940 | else |
886 | temp = temp_from_s8(data->temp8[2]); | 941 | temp = temp_from_s8(data->temp8[LOCAL_CRIT]); |
887 | 942 | ||
888 | data->temp_hyst = hyst_to_reg(temp - val); | 943 | data->temp_hyst = hyst_to_reg(temp - val); |
889 | i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, | 944 | i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, |
@@ -937,25 +992,28 @@ static ssize_t set_update_interval(struct device *dev, | |||
937 | return count; | 992 | return count; |
938 | } | 993 | } |
939 | 994 | ||
940 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp11, NULL, 0, 4); | 995 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp11, NULL, |
941 | static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp11, NULL, 0, 0); | 996 | 0, LOCAL_TEMP); |
997 | static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp11, NULL, | ||
998 | 0, REMOTE_TEMP); | ||
942 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, | 999 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, |
943 | set_temp8, 0); | 1000 | set_temp8, LOCAL_LOW); |
944 | static SENSOR_DEVICE_ATTR_2(temp2_min, S_IWUSR | S_IRUGO, show_temp11, | 1001 | static SENSOR_DEVICE_ATTR_2(temp2_min, S_IWUSR | S_IRUGO, show_temp11, |
945 | set_temp11, 0, 1); | 1002 | set_temp11, 0, REMOTE_LOW); |
946 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, | 1003 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, |
947 | set_temp8, 1); | 1004 | set_temp8, LOCAL_HIGH); |
948 | static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp11, | 1005 | static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp11, |
949 | set_temp11, 1, 2); | 1006 | set_temp11, 1, REMOTE_HIGH); |
950 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8, | 1007 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8, |
951 | set_temp8, 2); | 1008 | set_temp8, LOCAL_CRIT); |
952 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, | 1009 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, |
953 | set_temp8, 3); | 1010 | set_temp8, REMOTE_CRIT); |
954 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, | 1011 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, |
955 | set_temphyst, 2); | 1012 | set_temphyst, LOCAL_CRIT); |
956 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 3); | 1013 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, |
1014 | REMOTE_CRIT); | ||
957 | static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, | 1015 | static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, |
958 | set_temp11, 2, 3); | 1016 | set_temp11, 2, REMOTE_OFFSET); |
959 | 1017 | ||
960 | /* Individual alarm files */ | 1018 | /* Individual alarm files */ |
961 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); | 1019 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); |
@@ -1003,13 +1061,13 @@ static const struct attribute_group lm90_group = { | |||
1003 | * Additional attributes for devices with emergency sensors | 1061 | * Additional attributes for devices with emergency sensors |
1004 | */ | 1062 | */ |
1005 | static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, show_temp8, | 1063 | static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, show_temp8, |
1006 | set_temp8, 4); | 1064 | set_temp8, LOCAL_EMERG); |
1007 | static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, show_temp8, | 1065 | static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, show_temp8, |
1008 | set_temp8, 5); | 1066 | set_temp8, REMOTE_EMERG); |
1009 | static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO, show_temphyst, | 1067 | static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO, show_temphyst, |
1010 | NULL, 4); | 1068 | NULL, LOCAL_EMERG); |
1011 | static SENSOR_DEVICE_ATTR(temp2_emergency_hyst, S_IRUGO, show_temphyst, | 1069 | static SENSOR_DEVICE_ATTR(temp2_emergency_hyst, S_IRUGO, show_temphyst, |
1012 | NULL, 5); | 1070 | NULL, REMOTE_EMERG); |
1013 | 1071 | ||
1014 | static struct attribute *lm90_emergency_attributes[] = { | 1072 | static struct attribute *lm90_emergency_attributes[] = { |
1015 | &sensor_dev_attr_temp1_emergency.dev_attr.attr, | 1073 | &sensor_dev_attr_temp1_emergency.dev_attr.attr, |
@@ -1039,18 +1097,20 @@ static const struct attribute_group lm90_emergency_alarm_group = { | |||
1039 | /* | 1097 | /* |
1040 | * Additional attributes for devices with 3 temperature sensors | 1098 | * Additional attributes for devices with 3 temperature sensors |
1041 | */ | 1099 | */ |
1042 | static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp11, NULL, 0, 5); | 1100 | static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp11, NULL, |
1101 | 0, REMOTE2_TEMP); | ||
1043 | static SENSOR_DEVICE_ATTR_2(temp3_min, S_IWUSR | S_IRUGO, show_temp11, | 1102 | static SENSOR_DEVICE_ATTR_2(temp3_min, S_IWUSR | S_IRUGO, show_temp11, |
1044 | set_temp11, 3, 6); | 1103 | set_temp11, 3, REMOTE2_LOW); |
1045 | static SENSOR_DEVICE_ATTR_2(temp3_max, S_IWUSR | S_IRUGO, show_temp11, | 1104 | static SENSOR_DEVICE_ATTR_2(temp3_max, S_IWUSR | S_IRUGO, show_temp11, |
1046 | set_temp11, 4, 7); | 1105 | set_temp11, 4, REMOTE2_HIGH); |
1047 | static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp8, | 1106 | static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp8, |
1048 | set_temp8, 6); | 1107 | set_temp8, REMOTE2_CRIT); |
1049 | static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_temphyst, NULL, 6); | 1108 | static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_temphyst, NULL, |
1109 | REMOTE2_CRIT); | ||
1050 | static SENSOR_DEVICE_ATTR(temp3_emergency, S_IWUSR | S_IRUGO, show_temp8, | 1110 | static SENSOR_DEVICE_ATTR(temp3_emergency, S_IWUSR | S_IRUGO, show_temp8, |
1051 | set_temp8, 7); | 1111 | set_temp8, REMOTE2_EMERG); |
1052 | static SENSOR_DEVICE_ATTR(temp3_emergency_hyst, S_IRUGO, show_temphyst, | 1112 | static SENSOR_DEVICE_ATTR(temp3_emergency_hyst, S_IRUGO, show_temphyst, |
1053 | NULL, 7); | 1113 | NULL, REMOTE2_EMERG); |
1054 | 1114 | ||
1055 | static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9); | 1115 | static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9); |
1056 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 10); | 1116 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 10); |
@@ -1306,6 +1366,19 @@ static int lm90_detect(struct i2c_client *client, | |||
1306 | && (config1 & 0x3F) == 0x00 | 1366 | && (config1 & 0x3F) == 0x00 |
1307 | && convrate <= 0x08) | 1367 | && convrate <= 0x08) |
1308 | name = "g781"; | 1368 | name = "g781"; |
1369 | } else | ||
1370 | if (address == 0x4C | ||
1371 | && man_id == 0x55) { /* Texas Instruments */ | ||
1372 | int local_ext; | ||
1373 | |||
1374 | local_ext = i2c_smbus_read_byte_data(client, | ||
1375 | TMP451_REG_R_LOCAL_TEMPL); | ||
1376 | |||
1377 | if (chip_id == 0x00 /* TMP451 */ | ||
1378 | && (config1 & 0x1B) == 0x00 | ||
1379 | && convrate <= 0x09 | ||
1380 | && (local_ext & 0x0F) == 0x00) | ||
1381 | name = "tmp451"; | ||
1309 | } | 1382 | } |
1310 | 1383 | ||
1311 | if (!name) { /* identification failed */ | 1384 | if (!name) { /* identification failed */ |
@@ -1367,7 +1440,7 @@ static void lm90_init_client(struct i2c_client *client) | |||
1367 | data->config_orig = config; | 1440 | data->config_orig = config; |
1368 | 1441 | ||
1369 | /* Check Temperature Range Select */ | 1442 | /* Check Temperature Range Select */ |
1370 | if (data->kind == adt7461) { | 1443 | if (data->kind == adt7461 || data->kind == tmp451) { |
1371 | if (config & 0x04) | 1444 | if (config & 0x04) |
1372 | data->flags |= LM90_FLAG_ADT7461_EXT; | 1445 | data->flags |= LM90_FLAG_ADT7461_EXT; |
1373 | } | 1446 | } |
@@ -1391,14 +1464,74 @@ static void lm90_init_client(struct i2c_client *client) | |||
1391 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); | 1464 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); |
1392 | } | 1465 | } |
1393 | 1466 | ||
1467 | static bool lm90_is_tripped(struct i2c_client *client, u16 *status) | ||
1468 | { | ||
1469 | struct lm90_data *data = i2c_get_clientdata(client); | ||
1470 | u8 st, st2 = 0; | ||
1471 | |||
1472 | lm90_read_reg(client, LM90_REG_R_STATUS, &st); | ||
1473 | |||
1474 | if (data->kind == max6696) | ||
1475 | lm90_read_reg(client, MAX6696_REG_R_STATUS2, &st2); | ||
1476 | |||
1477 | *status = st | (st2 << 8); | ||
1478 | |||
1479 | if ((st & 0x7f) == 0 && (st2 & 0xfe) == 0) | ||
1480 | return false; | ||
1481 | |||
1482 | if ((st & (LM90_STATUS_LLOW | LM90_STATUS_LHIGH | LM90_STATUS_LTHRM)) || | ||
1483 | (st2 & MAX6696_STATUS2_LOT2)) | ||
1484 | dev_warn(&client->dev, | ||
1485 | "temp%d out of range, please check!\n", 1); | ||
1486 | if ((st & (LM90_STATUS_RLOW | LM90_STATUS_RHIGH | LM90_STATUS_RTHRM)) || | ||
1487 | (st2 & MAX6696_STATUS2_ROT2)) | ||
1488 | dev_warn(&client->dev, | ||
1489 | "temp%d out of range, please check!\n", 2); | ||
1490 | if (st & LM90_STATUS_ROPEN) | ||
1491 | dev_warn(&client->dev, | ||
1492 | "temp%d diode open, please check!\n", 2); | ||
1493 | if (st2 & (MAX6696_STATUS2_R2LOW | MAX6696_STATUS2_R2HIGH | | ||
1494 | MAX6696_STATUS2_R2THRM | MAX6696_STATUS2_R2OT2)) | ||
1495 | dev_warn(&client->dev, | ||
1496 | "temp%d out of range, please check!\n", 3); | ||
1497 | if (st2 & MAX6696_STATUS2_R2OPEN) | ||
1498 | dev_warn(&client->dev, | ||
1499 | "temp%d diode open, please check!\n", 3); | ||
1500 | |||
1501 | return true; | ||
1502 | } | ||
1503 | |||
1504 | static irqreturn_t lm90_irq_thread(int irq, void *dev_id) | ||
1505 | { | ||
1506 | struct i2c_client *client = dev_id; | ||
1507 | u16 status; | ||
1508 | |||
1509 | if (lm90_is_tripped(client, &status)) | ||
1510 | return IRQ_HANDLED; | ||
1511 | else | ||
1512 | return IRQ_NONE; | ||
1513 | } | ||
1514 | |||
1394 | static int lm90_probe(struct i2c_client *client, | 1515 | static int lm90_probe(struct i2c_client *client, |
1395 | const struct i2c_device_id *id) | 1516 | const struct i2c_device_id *id) |
1396 | { | 1517 | { |
1397 | struct device *dev = &client->dev; | 1518 | struct device *dev = &client->dev; |
1398 | struct i2c_adapter *adapter = to_i2c_adapter(dev->parent); | 1519 | struct i2c_adapter *adapter = to_i2c_adapter(dev->parent); |
1399 | struct lm90_data *data; | 1520 | struct lm90_data *data; |
1521 | struct regulator *regulator; | ||
1400 | int err; | 1522 | int err; |
1401 | 1523 | ||
1524 | regulator = devm_regulator_get(dev, "vcc"); | ||
1525 | if (IS_ERR(regulator)) | ||
1526 | return PTR_ERR(regulator); | ||
1527 | |||
1528 | err = regulator_enable(regulator); | ||
1529 | if (err < 0) { | ||
1530 | dev_err(&client->dev, | ||
1531 | "Failed to enable regulator: %d\n", err); | ||
1532 | return err; | ||
1533 | } | ||
1534 | |||
1402 | data = devm_kzalloc(&client->dev, sizeof(struct lm90_data), GFP_KERNEL); | 1535 | data = devm_kzalloc(&client->dev, sizeof(struct lm90_data), GFP_KERNEL); |
1403 | if (!data) | 1536 | if (!data) |
1404 | return -ENOMEM; | 1537 | return -ENOMEM; |
@@ -1406,6 +1539,8 @@ static int lm90_probe(struct i2c_client *client, | |||
1406 | i2c_set_clientdata(client, data); | 1539 | i2c_set_clientdata(client, data); |
1407 | mutex_init(&data->update_lock); | 1540 | mutex_init(&data->update_lock); |
1408 | 1541 | ||
1542 | data->regulator = regulator; | ||
1543 | |||
1409 | /* Set the device type */ | 1544 | /* Set the device type */ |
1410 | data->kind = id->driver_data; | 1545 | data->kind = id->driver_data; |
1411 | if (data->kind == adm1032) { | 1546 | if (data->kind == adm1032) { |
@@ -1467,12 +1602,26 @@ static int lm90_probe(struct i2c_client *client, | |||
1467 | goto exit_remove_files; | 1602 | goto exit_remove_files; |
1468 | } | 1603 | } |
1469 | 1604 | ||
1605 | if (client->irq) { | ||
1606 | dev_dbg(dev, "IRQ: %d\n", client->irq); | ||
1607 | err = devm_request_threaded_irq(dev, client->irq, | ||
1608 | NULL, lm90_irq_thread, | ||
1609 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
1610 | "lm90", client); | ||
1611 | if (err < 0) { | ||
1612 | dev_err(dev, "cannot request IRQ %d\n", client->irq); | ||
1613 | goto exit_remove_files; | ||
1614 | } | ||
1615 | } | ||
1616 | |||
1470 | return 0; | 1617 | return 0; |
1471 | 1618 | ||
1472 | exit_remove_files: | 1619 | exit_remove_files: |
1473 | lm90_remove_files(client, data); | 1620 | lm90_remove_files(client, data); |
1474 | exit_restore: | 1621 | exit_restore: |
1475 | lm90_restore_conf(client, data); | 1622 | lm90_restore_conf(client, data); |
1623 | regulator_disable(data->regulator); | ||
1624 | |||
1476 | return err; | 1625 | return err; |
1477 | } | 1626 | } |
1478 | 1627 | ||
@@ -1483,49 +1632,33 @@ static int lm90_remove(struct i2c_client *client) | |||
1483 | hwmon_device_unregister(data->hwmon_dev); | 1632 | hwmon_device_unregister(data->hwmon_dev); |
1484 | lm90_remove_files(client, data); | 1633 | lm90_remove_files(client, data); |
1485 | lm90_restore_conf(client, data); | 1634 | lm90_restore_conf(client, data); |
1635 | regulator_disable(data->regulator); | ||
1486 | 1636 | ||
1487 | return 0; | 1637 | return 0; |
1488 | } | 1638 | } |
1489 | 1639 | ||
1490 | static void lm90_alert(struct i2c_client *client, unsigned int flag) | 1640 | static void lm90_alert(struct i2c_client *client, unsigned int flag) |
1491 | { | 1641 | { |
1492 | struct lm90_data *data = i2c_get_clientdata(client); | 1642 | u16 alarms; |
1493 | u8 config, alarms, alarms2 = 0; | ||
1494 | |||
1495 | lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); | ||
1496 | |||
1497 | if (data->kind == max6696) | ||
1498 | lm90_read_reg(client, MAX6696_REG_R_STATUS2, &alarms2); | ||
1499 | |||
1500 | if ((alarms & 0x7f) == 0 && (alarms2 & 0xfe) == 0) { | ||
1501 | dev_info(&client->dev, "Everything OK\n"); | ||
1502 | } else { | ||
1503 | if (alarms & 0x61) | ||
1504 | dev_warn(&client->dev, | ||
1505 | "temp%d out of range, please check!\n", 1); | ||
1506 | if (alarms & 0x1a) | ||
1507 | dev_warn(&client->dev, | ||
1508 | "temp%d out of range, please check!\n", 2); | ||
1509 | if (alarms & 0x04) | ||
1510 | dev_warn(&client->dev, | ||
1511 | "temp%d diode open, please check!\n", 2); | ||
1512 | |||
1513 | if (alarms2 & 0x18) | ||
1514 | dev_warn(&client->dev, | ||
1515 | "temp%d out of range, please check!\n", 3); | ||
1516 | 1643 | ||
1644 | if (lm90_is_tripped(client, &alarms)) { | ||
1517 | /* | 1645 | /* |
1518 | * Disable ALERT# output, because these chips don't implement | 1646 | * Disable ALERT# output, because these chips don't implement |
1519 | * SMBus alert correctly; they should only hold the alert line | 1647 | * SMBus alert correctly; they should only hold the alert line |
1520 | * low briefly. | 1648 | * low briefly. |
1521 | */ | 1649 | */ |
1650 | struct lm90_data *data = i2c_get_clientdata(client); | ||
1651 | |||
1522 | if ((data->flags & LM90_HAVE_BROKEN_ALERT) | 1652 | if ((data->flags & LM90_HAVE_BROKEN_ALERT) |
1523 | && (alarms & data->alert_alarms)) { | 1653 | && (alarms & data->alert_alarms)) { |
1654 | u8 config; | ||
1524 | dev_dbg(&client->dev, "Disabling ALERT#\n"); | 1655 | dev_dbg(&client->dev, "Disabling ALERT#\n"); |
1525 | lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); | 1656 | lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); |
1526 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, | 1657 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, |
1527 | config | 0x80); | 1658 | config | 0x80); |
1528 | } | 1659 | } |
1660 | } else { | ||
1661 | dev_info(&client->dev, "Everything OK\n"); | ||
1529 | } | 1662 | } |
1530 | } | 1663 | } |
1531 | 1664 | ||