diff options
-rw-r--r-- | drivers/hwmon/lm63.c | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 24a96f89d206..a9e6212ed54a 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
@@ -117,6 +117,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; | |||
117 | (val) >= 127000 ? 127 : \ | 117 | (val) >= 127000 ? 127 : \ |
118 | (val) < 0 ? ((val) - 500) / 1000 : \ | 118 | (val) < 0 ? ((val) - 500) / 1000 : \ |
119 | ((val) + 500) / 1000) | 119 | ((val) + 500) / 1000) |
120 | #define TEMP8U_TO_REG(val) ((val) <= 0 ? 0 : \ | ||
121 | (val) >= 255000 ? 255 : \ | ||
122 | ((val) + 500) / 1000) | ||
120 | #define TEMP11_FROM_REG(reg) ((reg) / 32 * 125) | 123 | #define TEMP11_FROM_REG(reg) ((reg) / 32 * 125) |
121 | #define TEMP11_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ | 124 | #define TEMP11_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ |
122 | (val) >= 127875 ? 0x7FE0 : \ | 125 | (val) >= 127875 ? 0x7FE0 : \ |
@@ -313,22 +316,33 @@ static ssize_t show_remote_temp8(struct device *dev, | |||
313 | + data->temp2_offset); | 316 | + data->temp2_offset); |
314 | } | 317 | } |
315 | 318 | ||
316 | static ssize_t set_local_temp8(struct device *dev, | 319 | static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, |
317 | struct device_attribute *dummy, | 320 | const char *buf, size_t count) |
318 | const char *buf, size_t count) | ||
319 | { | 321 | { |
322 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
320 | struct i2c_client *client = to_i2c_client(dev); | 323 | struct i2c_client *client = to_i2c_client(dev); |
321 | struct lm63_data *data = i2c_get_clientdata(client); | 324 | struct lm63_data *data = i2c_get_clientdata(client); |
325 | int nr = attr->index; | ||
326 | int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH; | ||
322 | long val; | 327 | long val; |
323 | int err; | 328 | int err; |
329 | int temp; | ||
324 | 330 | ||
325 | err = kstrtol(buf, 10, &val); | 331 | err = kstrtol(buf, 10, &val); |
326 | if (err) | 332 | if (err) |
327 | return err; | 333 | return err; |
328 | 334 | ||
329 | mutex_lock(&data->update_lock); | 335 | mutex_lock(&data->update_lock); |
330 | data->temp8[1] = TEMP8_TO_REG(val); | 336 | if (nr == 2) { |
331 | i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]); | 337 | if (data->remote_unsigned) |
338 | temp = TEMP8U_TO_REG(val - data->temp2_offset); | ||
339 | else | ||
340 | temp = TEMP8_TO_REG(val - data->temp2_offset); | ||
341 | } else { | ||
342 | temp = TEMP8_TO_REG(val); | ||
343 | } | ||
344 | data->temp8[nr] = temp; | ||
345 | i2c_smbus_write_byte_data(client, reg, temp); | ||
332 | mutex_unlock(&data->update_lock); | 346 | mutex_unlock(&data->update_lock); |
333 | return count; | 347 | return count; |
334 | } | 348 | } |
@@ -461,7 +475,7 @@ static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL); | |||
461 | 475 | ||
462 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0); | 476 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0); |
463 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8, | 477 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8, |
464 | set_local_temp8, 1); | 478 | set_temp8, 1); |
465 | 479 | ||
466 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); | 480 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); |
467 | static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, | 481 | static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, |
@@ -470,12 +484,8 @@ static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, | |||
470 | set_temp11, 2); | 484 | set_temp11, 2); |
471 | static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, | 485 | static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, |
472 | set_temp11, 3); | 486 | set_temp11, 3); |
473 | /* | ||
474 | * On LM63, temp2_crit can be set only once, which should be job | ||
475 | * of the bootloader. | ||
476 | */ | ||
477 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8, | 487 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8, |
478 | NULL, 2); | 488 | set_temp8, 2); |
479 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, | 489 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, |
480 | set_temp2_crit_hyst); | 490 | set_temp2_crit_hyst); |
481 | 491 | ||
@@ -510,7 +520,30 @@ static struct attribute *lm63_attributes[] = { | |||
510 | NULL | 520 | NULL |
511 | }; | 521 | }; |
512 | 522 | ||
523 | /* | ||
524 | * On LM63, temp2_crit can be set only once, which should be job | ||
525 | * of the bootloader. | ||
526 | * On LM64, temp2_crit can always be set. | ||
527 | * On LM96163, temp2_crit can be set if bit 1 of the configuration | ||
528 | * register is true. | ||
529 | */ | ||
530 | static umode_t lm63_attribute_mode(struct kobject *kobj, | ||
531 | struct attribute *attr, int index) | ||
532 | { | ||
533 | struct device *dev = container_of(kobj, struct device, kobj); | ||
534 | struct i2c_client *client = to_i2c_client(dev); | ||
535 | struct lm63_data *data = i2c_get_clientdata(client); | ||
536 | |||
537 | if (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr | ||
538 | && (data->kind == lm64 || | ||
539 | (data->kind == lm96163 && (data->config & 0x02)))) | ||
540 | return attr->mode | S_IWUSR; | ||
541 | |||
542 | return attr->mode; | ||
543 | } | ||
544 | |||
513 | static const struct attribute_group lm63_group = { | 545 | static const struct attribute_group lm63_group = { |
546 | .is_visible = lm63_attribute_mode, | ||
514 | .attrs = lm63_attributes, | 547 | .attrs = lm63_attributes, |
515 | }; | 548 | }; |
516 | 549 | ||