aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2012-01-16 16:51:46 -0500
committerJean Delvare <khali@endymion.delvare>2012-01-16 16:51:46 -0500
commit94e55df48a230162edc641e55c28d058f5b6cb76 (patch)
tree19b93afcb7e23289cf2cc82c7aaa114f6f54a158
parente872c91e726e7f7f74817cf9a81a138bf0d0a583 (diff)
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>
-rw-r--r--drivers/hwmon/lm63.c55
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
316static ssize_t set_local_temp8(struct device *dev, 319static 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
462static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0); 476static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0);
463static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8, 477static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8,
464 set_local_temp8, 1); 478 set_temp8, 1);
465 479
466static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); 480static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
467static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, 481static 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);
471static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, 485static 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 */
477static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8, 487static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
478 NULL, 2); 488 set_temp8, 2);
479static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, 489static 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 */
530static 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
513static const struct attribute_group lm63_group = { 545static const struct attribute_group lm63_group = {
546 .is_visible = lm63_attribute_mode,
514 .attrs = lm63_attributes, 547 .attrs = lm63_attributes,
515}; 548};
516 549