Message ID | 7524aaac106af01da2b52662b160535a211ebcd0.1559140351.git.krzysztof.adamski@nokia.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | [v2,1/2] pmbus: (core) mutex_lock write in pmbus_set_samples | expand |
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@nokia.com> > Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> > --- > > 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; >
On Wed, May 29, 2019 at 02:36:21PM +0000, 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. > > Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> > Reviewed-by: Alexander Sverdlin <alexander.sverdlin@nokia.com> Applied. Thanks, Guenter > --- > > 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;
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;
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. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> --- 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(-)