aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-03-28 05:03:10 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-04-21 11:27:38 -0400
commit0846e30dd403ca613c203ccb6e4a89c09235480c (patch)
treef0bc7014c6f7708a3c725cacc5bd5769ceb96611 /drivers/hwmon
parent8eb6d90fec24244f80bba018d955413ea6117a34 (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.c54
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
380static 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
389static 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
375static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0); 420static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
376static SENSOR_DEVICE_ATTR_2(temp1_min, S_IWUSR | S_IRUGO, show_temp, 421static 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,
405static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_status, NULL, 450static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_status, NULL,
406 TMP401_STATUS_REMOTE_CRIT); 451 TMP401_STATUS_REMOTE_CRIT);
407 452
453static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
454 set_update_interval);
455
408static struct attribute *tmp401_attributes[] = { 456static 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 = {
466static void tmp401_init_client(struct i2c_client *client) 516static 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);