Commit e872c91e726e7f7f74817cf9a81a138bf0d0a583
Committed by
Jean Delvare
1 parent
210961c436
Exists in
master
and in
6 other branches
hwmon: (lm63) Add support for unsigned upper temperature limits
LM96163 supports unsigned upper limits for the external temperature sensor. Add support for it. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Showing 1 changed file with 51 additions and 11 deletions Side-by-side Diff
drivers/hwmon/lm63.c
... | ... | @@ -92,6 +92,8 @@ |
92 | 92 | #define LM63_REG_MAN_ID 0xFE |
93 | 93 | #define LM63_REG_CHIP_ID 0xFF |
94 | 94 | |
95 | +#define LM96163_REG_REMOTE_TEMP_U_MSB 0x31 | |
96 | +#define LM96163_REG_REMOTE_TEMP_U_LSB 0x32 | |
95 | 97 | #define LM96163_REG_CONFIG_ENHANCED 0x45 |
96 | 98 | |
97 | 99 | /* |
... | ... | @@ -120,6 +122,9 @@ |
120 | 122 | (val) >= 127875 ? 0x7FE0 : \ |
121 | 123 | (val) < 0 ? ((val) - 62) / 125 * 32 : \ |
122 | 124 | ((val) + 62) / 125 * 32) |
125 | +#define TEMP11U_TO_REG(val) ((val) <= 0 ? 0 : \ | |
126 | + (val) >= 255875 ? 0xFFE0 : \ | |
127 | + ((val) + 62) / 125 * 32) | |
123 | 128 | #define HYST_TO_REG(val) ((val) <= 0 ? 0 : \ |
124 | 129 | (val) >= 127000 ? 127 : \ |
125 | 130 | ((val) + 500) / 1000) |
126 | 131 | |
127 | 132 | |
... | ... | @@ -188,11 +193,20 @@ |
188 | 193 | 1: remote low limit |
189 | 194 | 2: remote high limit |
190 | 195 | 3: remote offset */ |
196 | + u16 temp11u; /* remote input (unsigned) */ | |
191 | 197 | u8 temp2_crit_hyst; |
192 | 198 | u8 alarms; |
193 | 199 | bool pwm_highres; |
200 | + bool remote_unsigned; /* true if unsigned remote upper limits */ | |
194 | 201 | }; |
195 | 202 | |
203 | +static inline int temp8_from_reg(struct lm63_data *data, int nr) | |
204 | +{ | |
205 | + if (data->remote_unsigned) | |
206 | + return TEMP8_FROM_REG((u8)data->temp8[nr]); | |
207 | + return TEMP8_FROM_REG(data->temp8[nr]); | |
208 | +} | |
209 | + | |
196 | 210 | /* |
197 | 211 | * Sysfs callback functions and files |
198 | 212 | */ |
... | ... | @@ -295,7 +309,7 @@ |
295 | 309 | { |
296 | 310 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
297 | 311 | struct lm63_data *data = lm63_update_device(dev); |
298 | - return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index]) | |
312 | + return sprintf(buf, "%d\n", temp8_from_reg(data, attr->index) | |
299 | 313 | + data->temp2_offset); |
300 | 314 | } |
301 | 315 | |
... | ... | @@ -324,8 +338,25 @@ |
324 | 338 | { |
325 | 339 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
326 | 340 | struct lm63_data *data = lm63_update_device(dev); |
327 | - return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index]) | |
328 | - + data->temp2_offset); | |
341 | + int nr = attr->index; | |
342 | + int temp; | |
343 | + | |
344 | + if (!nr) { | |
345 | + /* | |
346 | + * Use unsigned temperature unless its value is zero. | |
347 | + * If it is zero, use signed temperature. | |
348 | + */ | |
349 | + if (data->temp11u) | |
350 | + temp = TEMP11_FROM_REG(data->temp11u); | |
351 | + else | |
352 | + temp = TEMP11_FROM_REG(data->temp11[nr]); | |
353 | + } else { | |
354 | + if (data->remote_unsigned && nr == 2) | |
355 | + temp = TEMP11_FROM_REG((u16)data->temp11[nr]); | |
356 | + else | |
357 | + temp = TEMP11_FROM_REG(data->temp11[nr]); | |
358 | + } | |
359 | + return sprintf(buf, "%d\n", temp + data->temp2_offset); | |
329 | 360 | } |
330 | 361 | |
331 | 362 | static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, |
... | ... | @@ -352,7 +383,11 @@ |
352 | 383 | return err; |
353 | 384 | |
354 | 385 | mutex_lock(&data->update_lock); |
355 | - data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset); | |
386 | + if (data->remote_unsigned && nr == 2) | |
387 | + data->temp11[nr] = TEMP11U_TO_REG(val - data->temp2_offset); | |
388 | + else | |
389 | + data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset); | |
390 | + | |
356 | 391 | i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], |
357 | 392 | data->temp11[nr] >> 8); |
358 | 393 | i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], |
... | ... | @@ -369,7 +404,7 @@ |
369 | 404 | struct device_attribute *dummy, char *buf) |
370 | 405 | { |
371 | 406 | struct lm63_data *data = lm63_update_device(dev); |
372 | - return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2]) | |
407 | + return sprintf(buf, "%d\n", temp8_from_reg(data, 2) | |
373 | 408 | + data->temp2_offset |
374 | 409 | - TEMP8_FROM_REG(data->temp2_crit_hyst)); |
375 | 410 | } |
... | ... | @@ -393,7 +428,7 @@ |
393 | 428 | return err; |
394 | 429 | |
395 | 430 | mutex_lock(&data->update_lock); |
396 | - hyst = TEMP8_FROM_REG(data->temp8[2]) + data->temp2_offset - val; | |
431 | + hyst = temp8_from_reg(data, 2) + data->temp2_offset - val; | |
397 | 432 | i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, |
398 | 433 | HYST_TO_REG(hyst)); |
399 | 434 | mutex_unlock(&data->update_lock); |
... | ... | @@ -620,9 +655,8 @@ |
620 | 655 | data->pwm1_freq = 1; |
621 | 656 | |
622 | 657 | /* |
623 | - * For LM96163, check if high resolution PWM is enabled. | |
624 | - * Also, check if unsigned temperature format is enabled | |
625 | - * and display a warning message if it is. | |
658 | + * For LM96163, check if high resolution PWM | |
659 | + * and unsigned temperature format is enabled. | |
626 | 660 | */ |
627 | 661 | if (data->kind == lm96163) { |
628 | 662 | u8 config_enhanced |
... | ... | @@ -632,8 +666,7 @@ |
632 | 666 | && !(data->config_fan & 0x08) && data->pwm1_freq == 8) |
633 | 667 | data->pwm_highres = true; |
634 | 668 | if (config_enhanced & 0x08) |
635 | - dev_warn(&client->dev, | |
636 | - "Unsigned format for High and Crit setpoints enabled but not supported by driver\n"); | |
669 | + data->remote_unsigned = true; | |
637 | 670 | } |
638 | 671 | |
639 | 672 | /* Show some debug info about the LM63 configuration */ |
... | ... | @@ -709,6 +742,13 @@ |
709 | 742 | LM63_REG_REMOTE_OFFSET_MSB) << 8) |
710 | 743 | | i2c_smbus_read_byte_data(client, |
711 | 744 | LM63_REG_REMOTE_OFFSET_LSB); |
745 | + | |
746 | + if (data->kind == lm96163) | |
747 | + data->temp11u = (i2c_smbus_read_byte_data(client, | |
748 | + LM96163_REG_REMOTE_TEMP_U_MSB) << 8) | |
749 | + | i2c_smbus_read_byte_data(client, | |
750 | + LM96163_REG_REMOTE_TEMP_U_LSB); | |
751 | + | |
712 | 752 | data->temp8[2] = i2c_smbus_read_byte_data(client, |
713 | 753 | LM63_REG_REMOTE_TCRIT); |
714 | 754 | data->temp2_crit_hyst = i2c_smbus_read_byte_data(client, |