Register custom sysfs attribute to be registered by pmbus allowing
read/write access to the manufacturer specific SAMPLES_FOR_AVG register.
This register allows setting the number of samples used in computing the
average values (PMBUS_VIRT_READ_*_AVG). The number we write is an
exponent of base 2 of the number of samples so for example writing 3
will result in 8 samples average.

Signed-off-by: Krzysztof Adamski <[email protected]>
---
 drivers/hwmon/pmbus/lm25066.c | 45 +++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index 53db78753a0d..c78af0a7e5ff 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -26,6 +26,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/log2.h>
 #include "pmbus.h"
 
 enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
@@ -38,6 +39,7 @@ enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
 #define LM25066_READ_PIN_PEAK          0xd5
 #define LM25066_CLEAR_PIN_PEAK         0xd6
 #define LM25066_DEVICE_SETUP           0xd9
+#define LM25066_SAMPLES_FOR_AVG                0xdb
 #define LM25066_READ_AVG_VIN           0xdc
 #define LM25066_READ_AVG_VOUT          0xdd
 #define LM25066_READ_AVG_IIN           0xde
@@ -405,6 +407,47 @@ static int lm25066_write_word_data(struct i2c_client 
*client, int page, int reg,
        return ret;
 }
 
+static ssize_t samples_for_avg_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       int ret;
+
+       ret = pmbus_read_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", 1 << ret);
+}
+
+static ssize_t samples_for_avg_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       int ret, val;
+
+       ret = kstrtoint(buf, 0, &val);
+       if (ret < 0)
+               return ret;
+
+       ret = pmbus_write_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG,
+                                   ilog2(val));
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR_RW(samples_for_avg);
+
+static struct attribute *lm25056_attrs[] = {
+       &dev_attr_samples_for_avg.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(lm25056); // should we set a name of this group to put all
+                          // those attributes in subdirectory? Like "custom" ?
+
 static int lm25066_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
@@ -476,6 +519,8 @@ static int lm25066_probe(struct i2c_client *client,
                info->b[PSC_POWER] = coeff[PSC_POWER].b;
        }
 
+       info->groups = lm25056_groups;
+
        return pmbus_do_probe(client, id, info);
 }
 
-- 
2.20.1

Reply via email to