aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
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
commit04738b2b2f37c13bbe37b7695fec6c1c60d79c7a (patch)
tree77802752c8901e35eab6bfb1763e7160e37c7328 /drivers/hwmon
parent94e55df48a230162edc641e55c28d058f5b6cb76 (diff)
hwmon: (lm63) Add support for update_interval sysfs attribute
The update interval is configurable on LM63 and compatibles. Add support for it. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/lm63.c92
1 files changed, 90 insertions, 2 deletions
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index a9e6212ed54a..5f6da52a7219 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -61,6 +61,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
61 */ 61 */
62 62
63#define LM63_REG_CONFIG1 0x03 63#define LM63_REG_CONFIG1 0x03
64#define LM63_REG_CONVRATE 0x04
64#define LM63_REG_CONFIG2 0xBF 65#define LM63_REG_CONFIG2 0xBF
65#define LM63_REG_CONFIG_FAN 0x4A 66#define LM63_REG_CONFIG_FAN 0x4A
66 67
@@ -96,6 +97,11 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
96#define LM96163_REG_REMOTE_TEMP_U_LSB 0x32 97#define LM96163_REG_REMOTE_TEMP_U_LSB 0x32
97#define LM96163_REG_CONFIG_ENHANCED 0x45 98#define LM96163_REG_CONFIG_ENHANCED 0x45
98 99
100#define LM63_MAX_CONVRATE 9
101
102#define LM63_MAX_CONVRATE_HZ 32
103#define LM96163_MAX_CONVRATE_HZ 26
104
99/* 105/*
100 * Conversions and various macros 106 * Conversions and various macros
101 * For tachometer counts, the LM63 uses 16-bit values. 107 * For tachometer counts, the LM63 uses 16-bit values.
@@ -132,6 +138,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
132 (val) >= 127000 ? 127 : \ 138 (val) >= 127000 ? 127 : \
133 ((val) + 500) / 1000) 139 ((val) + 500) / 1000)
134 140
141#define UPDATE_INTERVAL(max, rate) \
142 ((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
143
135/* 144/*
136 * Functions declaration 145 * Functions declaration
137 */ 146 */
@@ -180,9 +189,12 @@ struct lm63_data {
180 struct mutex update_lock; 189 struct mutex update_lock;
181 char valid; /* zero until following fields are valid */ 190 char valid; /* zero until following fields are valid */
182 unsigned long last_updated; /* in jiffies */ 191 unsigned long last_updated; /* in jiffies */
183 int kind; 192 enum chips kind;
184 int temp2_offset; 193 int temp2_offset;
185 194
195 int update_interval; /* in milliseconds */
196 int max_convrate_hz;
197
186 /* registers values */ 198 /* registers values */
187 u8 config, config_fan; 199 u8 config, config_fan;
188 u16 fan[2]; /* 0: input 200 u16 fan[2]; /* 0: input
@@ -449,6 +461,58 @@ static ssize_t set_temp2_crit_hyst(struct device *dev,
449 return count; 461 return count;
450} 462}
451 463
464/*
465 * Set conversion rate.
466 * client->update_lock must be held when calling this function.
467 */
468static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data,
469 unsigned int interval)
470{
471 int i;
472 unsigned int update_interval;
473
474 /* Shift calculations to avoid rounding errors */
475 interval <<= 6;
476
477 /* find the nearest update rate */
478 update_interval = (1 << (LM63_MAX_CONVRATE + 6)) * 1000
479 / data->max_convrate_hz;
480 for (i = 0; i < LM63_MAX_CONVRATE; i++, update_interval >>= 1)
481 if (interval >= update_interval * 3 / 4)
482 break;
483
484 i2c_smbus_write_byte_data(client, LM63_REG_CONVRATE, i);
485 data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, i);
486}
487
488static ssize_t show_update_interval(struct device *dev,
489 struct device_attribute *attr, char *buf)
490{
491 struct lm63_data *data = dev_get_drvdata(dev);
492
493 return sprintf(buf, "%u\n", data->update_interval);
494}
495
496static ssize_t set_update_interval(struct device *dev,
497 struct device_attribute *attr,
498 const char *buf, size_t count)
499{
500 struct i2c_client *client = to_i2c_client(dev);
501 struct lm63_data *data = i2c_get_clientdata(client);
502 unsigned long val;
503 int err;
504
505 err = kstrtoul(buf, 10, &val);
506 if (err)
507 return err;
508
509 mutex_lock(&data->update_lock);
510 lm63_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
511 mutex_unlock(&data->update_lock);
512
513 return count;
514}
515
452static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, 516static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
453 char *buf) 517 char *buf)
454{ 518{
@@ -499,6 +563,9 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
499/* Raw alarm file for compatibility */ 563/* Raw alarm file for compatibility */
500static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 564static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
501 565
566static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
567 set_update_interval);
568
502static struct attribute *lm63_attributes[] = { 569static struct attribute *lm63_attributes[] = {
503 &dev_attr_pwm1.attr, 570 &dev_attr_pwm1.attr,
504 &dev_attr_pwm1_enable.attr, 571 &dev_attr_pwm1_enable.attr,
@@ -517,6 +584,7 @@ static struct attribute *lm63_attributes[] = {
517 &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, 584 &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
518 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 585 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
519 &dev_attr_alarms.attr, 586 &dev_attr_alarms.attr,
587 &dev_attr_update_interval.attr,
520 NULL 588 NULL
521}; 589};
522 590
@@ -669,6 +737,7 @@ exit:
669static void lm63_init_client(struct i2c_client *client) 737static void lm63_init_client(struct i2c_client *client)
670{ 738{
671 struct lm63_data *data = i2c_get_clientdata(client); 739 struct lm63_data *data = i2c_get_clientdata(client);
740 u8 convrate;
672 741
673 data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1); 742 data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
674 data->config_fan = i2c_smbus_read_byte_data(client, 743 data->config_fan = i2c_smbus_read_byte_data(client,
@@ -687,6 +756,21 @@ static void lm63_init_client(struct i2c_client *client)
687 if (data->pwm1_freq == 0) 756 if (data->pwm1_freq == 0)
688 data->pwm1_freq = 1; 757 data->pwm1_freq = 1;
689 758
759 switch (data->kind) {
760 case lm63:
761 case lm64:
762 data->max_convrate_hz = LM63_MAX_CONVRATE_HZ;
763 break;
764 case lm96163:
765 data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ;
766 break;
767 }
768 convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE);
769 if (unlikely(convrate > LM63_MAX_CONVRATE))
770 convrate = LM63_MAX_CONVRATE;
771 data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz,
772 convrate);
773
690 /* 774 /*
691 * For LM96163, check if high resolution PWM 775 * For LM96163, check if high resolution PWM
692 * and unsigned temperature format is enabled. 776 * and unsigned temperature format is enabled.
@@ -730,10 +814,14 @@ static struct lm63_data *lm63_update_device(struct device *dev)
730{ 814{
731 struct i2c_client *client = to_i2c_client(dev); 815 struct i2c_client *client = to_i2c_client(dev);
732 struct lm63_data *data = i2c_get_clientdata(client); 816 struct lm63_data *data = i2c_get_clientdata(client);
817 unsigned long next_update;
733 818
734 mutex_lock(&data->update_lock); 819 mutex_lock(&data->update_lock);
735 820
736 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { 821 next_update = data->last_updated
822 + msecs_to_jiffies(data->update_interval) + 1;
823
824 if (time_after(jiffies, next_update) || !data->valid) {
737 if (data->config & 0x04) { /* tachometer enabled */ 825 if (data->config & 0x04) { /* tachometer enabled */
738 /* order matters for fan1_input */ 826 /* order matters for fan1_input */
739 data->fan[0] = i2c_smbus_read_byte_data(client, 827 data->fan[0] = i2c_smbus_read_byte_data(client,