Commit 04738b2b2f37c13bbe37b7695fec6c1c60d79c7a

Authored by Guenter Roeck
Committed by Jean Delvare
1 parent 94e55df48a

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>

Showing 2 changed files with 93 additions and 5 deletions Side-by-side Diff

Documentation/hwmon/lm63
... ... @@ -61,9 +61,9 @@
61 61 (you cannot define your custom PWM/temperature curve), and mode change isn't
62 62 supported either.
63 63  
64   -The lm63 driver will not update its values more frequently than every
65   -second; reading them more often will do no harm, but will return 'old'
66   -values.
  64 +The lm63 driver will not update its values more frequently than configured with
  65 +the update_interval sysfs attribute; reading them more often will do no harm,
  66 +but will return 'old' values.
67 67  
68 68 The LM64 is effectively an LM63 with GPIO lines. The driver does not
69 69 support these GPIO lines at present.
drivers/hwmon/lm63.c
... ... @@ -61,6 +61,7 @@
61 61 */
62 62  
63 63 #define LM63_REG_CONFIG1 0x03
  64 +#define LM63_REG_CONVRATE 0x04
64 65 #define LM63_REG_CONFIG2 0xBF
65 66 #define LM63_REG_CONFIG_FAN 0x4A
66 67  
... ... @@ -96,6 +97,11 @@
96 97 #define LM96163_REG_REMOTE_TEMP_U_LSB 0x32
97 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 106 * Conversions and various macros
101 107 * For tachometer counts, the LM63 uses 16-bit values.
... ... @@ -132,6 +138,9 @@
132 138 (val) >= 127000 ? 127 : \
133 139 ((val) + 500) / 1000)
134 140  
  141 +#define UPDATE_INTERVAL(max, rate) \
  142 + ((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
  143 +
135 144 /*
136 145 * Functions declaration
137 146 */
138 147  
... ... @@ -180,9 +189,12 @@
180 189 struct mutex update_lock;
181 190 char valid; /* zero until following fields are valid */
182 191 unsigned long last_updated; /* in jiffies */
183   - int kind;
  192 + enum chips kind;
184 193 int temp2_offset;
185 194  
  195 + int update_interval; /* in milliseconds */
  196 + int max_convrate_hz;
  197 +
186 198 /* registers values */
187 199 u8 config, config_fan;
188 200 u16 fan[2]; /* 0: input
... ... @@ -449,6 +461,58 @@
449 461 return count;
450 462 }
451 463  
  464 +/*
  465 + * Set conversion rate.
  466 + * client->update_lock must be held when calling this function.
  467 + */
  468 +static 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 +
  488 +static 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 +
  496 +static 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 +
452 516 static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
453 517 char *buf)
454 518 {
... ... @@ -499,6 +563,9 @@
499 563 /* Raw alarm file for compatibility */
500 564 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
501 565  
  566 +static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
  567 + set_update_interval);
  568 +
502 569 static struct attribute *lm63_attributes[] = {
503 570 &dev_attr_pwm1.attr,
504 571 &dev_attr_pwm1_enable.attr,
... ... @@ -517,6 +584,7 @@
517 584 &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
518 585 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
519 586 &dev_attr_alarms.attr,
  587 + &dev_attr_update_interval.attr,
520 588 NULL
521 589 };
522 590  
... ... @@ -669,6 +737,7 @@
669 737 static void lm63_init_client(struct i2c_client *client)
670 738 {
671 739 struct lm63_data *data = i2c_get_clientdata(client);
  740 + u8 convrate;
672 741  
673 742 data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
674 743 data->config_fan = i2c_smbus_read_byte_data(client,
... ... @@ -687,6 +756,21 @@
687 756 if (data->pwm1_freq == 0)
688 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 775 * For LM96163, check if high resolution PWM
692 776 * and unsigned temperature format is enabled.
693 777  
... ... @@ -730,10 +814,14 @@
730 814 {
731 815 struct i2c_client *client = to_i2c_client(dev);
732 816 struct lm63_data *data = i2c_get_clientdata(client);
  817 + unsigned long next_update;
733 818  
734 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 825 if (data->config & 0x04) { /* tachometer enabled */
738 826 /* order matters for fan1_input */
739 827 data->fan[0] = i2c_smbus_read_byte_data(client,