Commit e872c91e726e7f7f74817cf9a81a138bf0d0a583

Authored by Guenter Roeck
Committed by Jean Delvare
1 parent 210961c436

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,