diff options
author | Guenter Roeck <linux@roeck-us.net> | 2012-01-16 16:51:46 -0500 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2012-01-16 16:51:46 -0500 |
commit | e872c91e726e7f7f74817cf9a81a138bf0d0a583 (patch) | |
tree | 5cba7f2c9b5afa53f5e3dad11e2272aed5e1fb2f /drivers/hwmon | |
parent | 210961c436d5c552a816ae9c6b38cbc8b993395a (diff) |
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>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/lm63.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 3d882c93b46d..24a96f89d206 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
@@ -92,6 +92,8 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; | |||
92 | #define LM63_REG_MAN_ID 0xFE | 92 | #define LM63_REG_MAN_ID 0xFE |
93 | #define LM63_REG_CHIP_ID 0xFF | 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 | #define LM96163_REG_CONFIG_ENHANCED 0x45 | 97 | #define LM96163_REG_CONFIG_ENHANCED 0x45 |
96 | 98 | ||
97 | /* | 99 | /* |
@@ -120,6 +122,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; | |||
120 | (val) >= 127875 ? 0x7FE0 : \ | 122 | (val) >= 127875 ? 0x7FE0 : \ |
121 | (val) < 0 ? ((val) - 62) / 125 * 32 : \ | 123 | (val) < 0 ? ((val) - 62) / 125 * 32 : \ |
122 | ((val) + 62) / 125 * 32) | 124 | ((val) + 62) / 125 * 32) |
125 | #define TEMP11U_TO_REG(val) ((val) <= 0 ? 0 : \ | ||
126 | (val) >= 255875 ? 0xFFE0 : \ | ||
127 | ((val) + 62) / 125 * 32) | ||
123 | #define HYST_TO_REG(val) ((val) <= 0 ? 0 : \ | 128 | #define HYST_TO_REG(val) ((val) <= 0 ? 0 : \ |
124 | (val) >= 127000 ? 127 : \ | 129 | (val) >= 127000 ? 127 : \ |
125 | ((val) + 500) / 1000) | 130 | ((val) + 500) / 1000) |
@@ -188,11 +193,20 @@ struct lm63_data { | |||
188 | 1: remote low limit | 193 | 1: remote low limit |
189 | 2: remote high limit | 194 | 2: remote high limit |
190 | 3: remote offset */ | 195 | 3: remote offset */ |
196 | u16 temp11u; /* remote input (unsigned) */ | ||
191 | u8 temp2_crit_hyst; | 197 | u8 temp2_crit_hyst; |
192 | u8 alarms; | 198 | u8 alarms; |
193 | bool pwm_highres; | 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 | * Sysfs callback functions and files | 211 | * Sysfs callback functions and files |
198 | */ | 212 | */ |
@@ -295,7 +309,7 @@ static ssize_t show_remote_temp8(struct device *dev, | |||
295 | { | 309 | { |
296 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 310 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
297 | struct lm63_data *data = lm63_update_device(dev); | 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 | + data->temp2_offset); | 313 | + data->temp2_offset); |
300 | } | 314 | } |
301 | 315 | ||
@@ -324,8 +338,25 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, | |||
324 | { | 338 | { |
325 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 339 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
326 | struct lm63_data *data = lm63_update_device(dev); | 340 | struct lm63_data *data = lm63_update_device(dev); |
327 | return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index]) | 341 | int nr = attr->index; |
328 | + data->temp2_offset); | 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 | static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, | 362 | static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, |
@@ -352,7 +383,11 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, | |||
352 | return err; | 383 | return err; |
353 | 384 | ||
354 | mutex_lock(&data->update_lock); | 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 | i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], | 391 | i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], |
357 | data->temp11[nr] >> 8); | 392 | data->temp11[nr] >> 8); |
358 | i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], | 393 | i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], |
@@ -369,7 +404,7 @@ static ssize_t show_temp2_crit_hyst(struct device *dev, | |||
369 | struct device_attribute *dummy, char *buf) | 404 | struct device_attribute *dummy, char *buf) |
370 | { | 405 | { |
371 | struct lm63_data *data = lm63_update_device(dev); | 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 | + data->temp2_offset | 408 | + data->temp2_offset |
374 | - TEMP8_FROM_REG(data->temp2_crit_hyst)); | 409 | - TEMP8_FROM_REG(data->temp2_crit_hyst)); |
375 | } | 410 | } |
@@ -393,7 +428,7 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, | |||
393 | return err; | 428 | return err; |
394 | 429 | ||
395 | mutex_lock(&data->update_lock); | 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 | i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, | 432 | i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, |
398 | HYST_TO_REG(hyst)); | 433 | HYST_TO_REG(hyst)); |
399 | mutex_unlock(&data->update_lock); | 434 | mutex_unlock(&data->update_lock); |
@@ -620,9 +655,8 @@ static void lm63_init_client(struct i2c_client *client) | |||
620 | data->pwm1_freq = 1; | 655 | data->pwm1_freq = 1; |
621 | 656 | ||
622 | /* | 657 | /* |
623 | * For LM96163, check if high resolution PWM is enabled. | 658 | * For LM96163, check if high resolution PWM |
624 | * Also, check if unsigned temperature format is enabled | 659 | * and unsigned temperature format is enabled. |
625 | * and display a warning message if it is. | ||
626 | */ | 660 | */ |
627 | if (data->kind == lm96163) { | 661 | if (data->kind == lm96163) { |
628 | u8 config_enhanced | 662 | u8 config_enhanced |
@@ -632,8 +666,7 @@ static void lm63_init_client(struct i2c_client *client) | |||
632 | && !(data->config_fan & 0x08) && data->pwm1_freq == 8) | 666 | && !(data->config_fan & 0x08) && data->pwm1_freq == 8) |
633 | data->pwm_highres = true; | 667 | data->pwm_highres = true; |
634 | if (config_enhanced & 0x08) | 668 | if (config_enhanced & 0x08) |
635 | dev_warn(&client->dev, | 669 | data->remote_unsigned = true; |
636 | "Unsigned format for High and Crit setpoints enabled but not supported by driver\n"); | ||
637 | } | 670 | } |
638 | 671 | ||
639 | /* Show some debug info about the LM63 configuration */ | 672 | /* Show some debug info about the LM63 configuration */ |
@@ -709,6 +742,13 @@ static struct lm63_data *lm63_update_device(struct device *dev) | |||
709 | LM63_REG_REMOTE_OFFSET_MSB) << 8) | 742 | LM63_REG_REMOTE_OFFSET_MSB) << 8) |
710 | | i2c_smbus_read_byte_data(client, | 743 | | i2c_smbus_read_byte_data(client, |
711 | LM63_REG_REMOTE_OFFSET_LSB); | 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 | data->temp8[2] = i2c_smbus_read_byte_data(client, | 752 | data->temp8[2] = i2c_smbus_read_byte_data(client, |
713 | LM63_REG_REMOTE_TCRIT); | 753 | LM63_REG_REMOTE_TCRIT); |
714 | data->temp2_crit_hyst = i2c_smbus_read_byte_data(client, | 754 | data->temp2_crit_hyst = i2c_smbus_read_byte_data(client, |