Commit 94e55df48a230162edc641e55c28d058f5b6cb76

Authored by Guenter Roeck
Committed by Jean Delvare
1 parent e872c91e72

hwmon: (lm63) Add support for writing the external critical temperature

On LM64, the external critical temperature limit is always writable. On LM96163,
it is writable if the chip is configured for it. Add conditional support for
writing the register dependent on chip type and configuration.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Jean Delvare <khali@linux-fr.org>

Showing 1 changed file with 44 additions and 11 deletions Side-by-side Diff

drivers/hwmon/lm63.c
... ... @@ -117,6 +117,9 @@
117 117 (val) >= 127000 ? 127 : \
118 118 (val) < 0 ? ((val) - 500) / 1000 : \
119 119 ((val) + 500) / 1000)
  120 +#define TEMP8U_TO_REG(val) ((val) <= 0 ? 0 : \
  121 + (val) >= 255000 ? 255 : \
  122 + ((val) + 500) / 1000)
120 123 #define TEMP11_FROM_REG(reg) ((reg) / 32 * 125)
121 124 #define TEMP11_TO_REG(val) ((val) <= -128000 ? 0x8000 : \
122 125 (val) >= 127875 ? 0x7FE0 : \
123 126  
124 127  
125 128  
126 129  
... ... @@ -313,22 +316,33 @@
313 316 + data->temp2_offset);
314 317 }
315 318  
316   -static ssize_t set_local_temp8(struct device *dev,
317   - struct device_attribute *dummy,
318   - const char *buf, size_t count)
  319 +static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
  320 + const char *buf, size_t count)
319 321 {
  322 + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
320 323 struct i2c_client *client = to_i2c_client(dev);
321 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 327 long val;
323 328 int err;
  329 + int temp;
324 330  
325 331 err = kstrtol(buf, 10, &val);
326 332 if (err)
327 333 return err;
328 334  
329 335 mutex_lock(&data->update_lock);
330   - data->temp8[1] = TEMP8_TO_REG(val);
331   - i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]);
  336 + if (nr == 2) {
  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 346 mutex_unlock(&data->update_lock);
333 347 return count;
334 348 }
... ... @@ -461,7 +475,7 @@
461 475  
462 476 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0);
463 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 480 static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
467 481 static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
468 482  
... ... @@ -470,12 +484,8 @@
470 484 set_temp11, 2);
471 485 static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
472 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 487 static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
478   - NULL, 2);
  488 + set_temp8, 2);
479 489 static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
480 490 set_temp2_crit_hyst);
481 491  
482 492  
... ... @@ -510,7 +520,30 @@
510 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 545 static const struct attribute_group lm63_group = {
  546 + .is_visible = lm63_attribute_mode,
514 547 .attrs = lm63_attributes,
515 548 };
516 549