Hi! On 29/05/2019 16:36, Adamski, Krzysztof (Nokia - PL/Wroclaw) wrote: > The device supports setting the number of samples for averaging the > measurements. There are two separate settings - PWR_AVG for averaging > PIN and VI_AVG for averaging VIN/VAUX/IOUT, both being part of > PMON_CONFIG register. The values are stored as exponent of base 2 of the > actual number of samples that will be taken. Reviewed-by: Alexander Sverdlin <alexander.sverdlin@xxxxxxxxx> > Signed-off-by: Krzysztof Adamski <krzysztof.adamski@xxxxxxxxx> > --- > > Changes in v2: > - Moved mutex lock to pmbus_set_samples (see patch 1/2) > - Changed mask type passed as argument to adm1275_read_pmon_config and > adm1275_write_pmon_config to u16 > - Changed 1 << ret to BIT(ret) > > drivers/hwmon/pmbus/adm1275.c | 61 ++++++++++++++++++++++++++++++++++- > 1 file changed, 60 insertions(+), 1 deletion(-) > > diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c > index f569372c9204..0c3493fa53ea 100644 > --- a/drivers/hwmon/pmbus/adm1275.c > +++ b/drivers/hwmon/pmbus/adm1275.c > @@ -23,6 +23,8 @@ > #include <linux/slab.h> > #include <linux/i2c.h> > #include <linux/bitops.h> > +#include <linux/bitfield.h> > +#include <linux/log2.h> > #include "pmbus.h" > > enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 }; > @@ -78,6 +80,10 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 }; > #define ADM1075_VAUX_OV_WARN BIT(7) > #define ADM1075_VAUX_UV_WARN BIT(6) > > +#define ADM1275_PWR_AVG_MASK GENMASK(13, 11) > +#define ADM1275_VI_AVG_MASK GENMASK(10, 8) > +#define ADM1275_SAMPLES_AVG_MAX 128 > + > struct adm1275_data { > int id; > bool have_oc_fault; > @@ -164,6 +170,34 @@ static const struct coefficients adm1293_coefficients[] = { > [18] = { 7658, 0, -3 }, /* power, 21V, irange200 */ > }; > > +static inline int adm1275_read_pmon_config(struct i2c_client *client, u16 mask) > +{ > + int ret; > + > + ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG); > + if (ret < 0) > + return ret; > + > + return FIELD_GET(mask, (u16)ret); > +} > + > +static inline int adm1275_write_pmon_config(struct i2c_client *client, u16 mask, > + u16 word) > +{ > + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); > + struct adm1275_data *data = to_adm1275_data(info); > + int ret; > + > + ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG); > + if (ret < 0) > + return ret; > + > + word = FIELD_PREP(mask, word) | (ret & ~mask); > + ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, word); > + > + return ret; > +} > + > static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) > { > const struct pmbus_driver_info *info = pmbus_get_driver_info(client); > @@ -242,6 +276,19 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) > if (!data->have_temp_max) > return -ENXIO; > break; > + case PMBUS_VIRT_POWER_SAMPLES: > + ret = adm1275_read_pmon_config(client, ADM1275_PWR_AVG_MASK); > + if (ret < 0) > + break; > + ret = BIT(ret); > + break; > + case PMBUS_VIRT_IN_SAMPLES: > + case PMBUS_VIRT_CURR_SAMPLES: > + ret = adm1275_read_pmon_config(client, ADM1275_VI_AVG_MASK); > + if (ret < 0) > + break; > + ret = BIT(ret); > + break; > default: > ret = -ENODATA; > break; > @@ -286,6 +333,17 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, > case PMBUS_VIRT_RESET_TEMP_HISTORY: > ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0); > break; > + case PMBUS_VIRT_POWER_SAMPLES: > + word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX); > + ret = adm1275_write_pmon_config(client, ADM1275_PWR_AVG_MASK, > + ilog2(word)); > + break; > + case PMBUS_VIRT_IN_SAMPLES: > + case PMBUS_VIRT_CURR_SAMPLES: > + word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX); > + ret = adm1275_write_pmon_config(client, ADM1275_VI_AVG_MASK, > + ilog2(word)); > + break; > default: > ret = -ENODATA; > break; > @@ -439,7 +497,8 @@ static int adm1275_probe(struct i2c_client *client, > info->format[PSC_CURRENT_OUT] = direct; > info->format[PSC_POWER] = direct; > info->format[PSC_TEMPERATURE] = direct; > - info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; > + info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | > + PMBUS_HAVE_SAMPLES; > > info->read_word_data = adm1275_read_word_data; > info->read_byte_data = adm1275_read_byte_data; > -- Best regards, Alexander Sverdlin.