diff options
author | Guenter Roeck <linux@roeck-us.net> | 2013-03-28 05:03:10 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-04-21 11:27:38 -0400 |
commit | 0846e30dd403ca613c203ccb6e4a89c09235480c (patch) | |
tree | f0bc7014c6f7708a3c725cacc5bd5769ceb96611 /drivers/hwmon | |
parent | 8eb6d90fec24244f80bba018d955413ea6117a34 (diff) |
hwmon: (tmp401) Add support for update_interval attribute
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/tmp401.c | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index 061146288e41..fa6af51b300d 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c | |||
@@ -127,6 +127,8 @@ struct tmp401_data { | |||
127 | unsigned long last_updated; /* in jiffies */ | 127 | unsigned long last_updated; /* in jiffies */ |
128 | enum chips kind; | 128 | enum chips kind; |
129 | 129 | ||
130 | unsigned int update_interval; /* in milliseconds */ | ||
131 | |||
130 | /* register values */ | 132 | /* register values */ |
131 | u8 status; | 133 | u8 status; |
132 | u8 config; | 134 | u8 config; |
@@ -194,10 +196,13 @@ static struct tmp401_data *tmp401_update_device(struct device *dev) | |||
194 | struct tmp401_data *data = i2c_get_clientdata(client); | 196 | struct tmp401_data *data = i2c_get_clientdata(client); |
195 | struct tmp401_data *ret = data; | 197 | struct tmp401_data *ret = data; |
196 | int val; | 198 | int val; |
199 | unsigned long next_update; | ||
197 | 200 | ||
198 | mutex_lock(&data->update_lock); | 201 | mutex_lock(&data->update_lock); |
199 | 202 | ||
200 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | 203 | next_update = data->last_updated + |
204 | msecs_to_jiffies(data->update_interval) + 1; | ||
205 | if (time_after(jiffies, next_update) || !data->valid) { | ||
201 | val = i2c_smbus_read_byte_data(client, TMP401_STATUS); | 206 | val = i2c_smbus_read_byte_data(client, TMP401_STATUS); |
202 | if (val < 0) { | 207 | if (val < 0) { |
203 | ret = ERR_PTR(val); | 208 | ret = ERR_PTR(val); |
@@ -372,6 +377,46 @@ static ssize_t reset_temp_history(struct device *dev, | |||
372 | return count; | 377 | return count; |
373 | } | 378 | } |
374 | 379 | ||
380 | static ssize_t show_update_interval(struct device *dev, | ||
381 | struct device_attribute *attr, char *buf) | ||
382 | { | ||
383 | struct i2c_client *client = to_i2c_client(dev); | ||
384 | struct tmp401_data *data = i2c_get_clientdata(client); | ||
385 | |||
386 | return sprintf(buf, "%u\n", data->update_interval); | ||
387 | } | ||
388 | |||
389 | static ssize_t set_update_interval(struct device *dev, | ||
390 | struct device_attribute *attr, | ||
391 | const char *buf, size_t count) | ||
392 | { | ||
393 | struct i2c_client *client = to_i2c_client(dev); | ||
394 | struct tmp401_data *data = i2c_get_clientdata(client); | ||
395 | unsigned long val; | ||
396 | int err, rate; | ||
397 | |||
398 | err = kstrtoul(buf, 10, &val); | ||
399 | if (err) | ||
400 | return err; | ||
401 | |||
402 | /* | ||
403 | * For valid rates, interval can be calculated as | ||
404 | * interval = (1 << (7 - rate)) * 125; | ||
405 | * Rounded rate is therefore | ||
406 | * rate = 7 - __fls(interval * 4 / (125 * 3)); | ||
407 | * Use clamp_val() to avoid overflows, and to ensure valid input | ||
408 | * for __fls. | ||
409 | */ | ||
410 | val = clamp_val(val, 125, 16000); | ||
411 | rate = 7 - __fls(val * 4 / (125 * 3)); | ||
412 | mutex_lock(&data->update_lock); | ||
413 | i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, rate); | ||
414 | data->update_interval = (1 << (7 - rate)) * 125; | ||
415 | mutex_unlock(&data->update_lock); | ||
416 | |||
417 | return count; | ||
418 | } | ||
419 | |||
375 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0); | 420 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0); |
376 | static SENSOR_DEVICE_ATTR_2(temp1_min, S_IWUSR | S_IRUGO, show_temp, | 421 | static SENSOR_DEVICE_ATTR_2(temp1_min, S_IWUSR | S_IRUGO, show_temp, |
377 | store_temp, 1, 0); | 422 | store_temp, 1, 0); |
@@ -405,6 +450,9 @@ static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_status, NULL, | |||
405 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_status, NULL, | 450 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_status, NULL, |
406 | TMP401_STATUS_REMOTE_CRIT); | 451 | TMP401_STATUS_REMOTE_CRIT); |
407 | 452 | ||
453 | static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, | ||
454 | set_update_interval); | ||
455 | |||
408 | static struct attribute *tmp401_attributes[] = { | 456 | static struct attribute *tmp401_attributes[] = { |
409 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 457 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
410 | &sensor_dev_attr_temp1_min.dev_attr.attr, | 458 | &sensor_dev_attr_temp1_min.dev_attr.attr, |
@@ -425,6 +473,8 @@ static struct attribute *tmp401_attributes[] = { | |||
425 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | 473 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, |
426 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | 474 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, |
427 | 475 | ||
476 | &dev_attr_update_interval.attr, | ||
477 | |||
428 | NULL | 478 | NULL |
429 | }; | 479 | }; |
430 | 480 | ||
@@ -466,9 +516,11 @@ static const struct attribute_group tmp411_group = { | |||
466 | static void tmp401_init_client(struct i2c_client *client) | 516 | static void tmp401_init_client(struct i2c_client *client) |
467 | { | 517 | { |
468 | int config, config_orig; | 518 | int config, config_orig; |
519 | struct tmp401_data *data = i2c_get_clientdata(client); | ||
469 | 520 | ||
470 | /* Set the conversion rate to 2 Hz */ | 521 | /* Set the conversion rate to 2 Hz */ |
471 | i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5); | 522 | i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5); |
523 | data->update_interval = 500; | ||
472 | 524 | ||
473 | /* Start conversions (disable shutdown if necessary) */ | 525 | /* Start conversions (disable shutdown if necessary) */ |
474 | config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); | 526 | config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); |