On Mon, Feb 24, 2020 at 11:50:31PM +0200, Vadim Pasternak wrote: > Provide read_word_data() callback for overvoltage and undervoltage > output readouts conversion. These registers are presented in > 'slinear11' format, while default conversion for 'vout' class for the > devices is 'vid'. It is resulted in wrong conversion in pmbus_reg2data() > for in{3-4}_lcrit and in{3-4}_crit attributes. > ) > Fixes: aaafb7c8eb1c ("hwmon: (pmbus) Add support for Infineon Multi-phase xdpe122 family controllers") > Signed-off-by: Vadim Pasternak <vadimp@xxxxxxxxxxxx> > --- > v1->v2: > Comments pointed out by Guenter: > - Drop reg2data() callback, provide conversion through > read_word_data() callback instead. > --- > drivers/hwmon/pmbus/xdpe12284.c | 51 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 51 insertions(+) > > diff --git a/drivers/hwmon/pmbus/xdpe12284.c b/drivers/hwmon/pmbus/xdpe12284.c > index ecd9b65627ec..44b737d0bc24 100644 > --- a/drivers/hwmon/pmbus/xdpe12284.c > +++ b/drivers/hwmon/pmbus/xdpe12284.c > @@ -18,6 +18,56 @@ > #define XDPE122_AMD_625MV 0x10 /* AMD mode 6.25mV */ > #define XDPE122_PAGE_NUM 2 > > +static int xdpe122_read_word_data(struct i2c_client *client, int page, > + int phase, int reg) > +{ > + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); > + long val; > + s16 exponent; > + s32 mantissa; > + int ret; > + > + switch (reg) { > + case PMBUS_VOUT_OV_FAULT_LIMIT: > + case PMBUS_VOUT_UV_FAULT_LIMIT: > + ret = pmbus_read_word_data(client, page, phase, reg); > + if (ret < 0) > + return ret; > + > + /* Convert register value to LINEAR11 data. */ > + exponent = ((s16)ret) >> 11; > + mantissa = ((s16)((ret & GENMASK(10, 0)) << 5)) >> 5; > + val = mantissa * 1000L; > + if (exponent >= 0) > + val <<= exponent; > + else > + val >>= -exponent; > + > + /* Convert data to VID register. */ > + switch (info->vrm_version[page]) { > + case vr13: > + if (val >= 500) > + return 1 + DIV_ROUND_CLOSEST(val - 500, 10); return 0; ? > + case vr12: > + if (val >= 250) > + return 1 + DIV_ROUND_CLOSEST(val - 250, 5); return 0; ? > + case imvp9: > + if (val >= 200) > + return 1 + DIV_ROUND_CLOSEST(val - 200, 10); return 0; ? > + case amd625mv: > + if (val >= 200 && val <= 968750) > + return DIV_ROUND_CLOSEST((1550 - val) * 100, > + 625); return 0; ? Also, are you sure that this calculation is correct ? 1550 - val is almost always negative. > + default: > + return -EINVAL; > + } > + default: > + return -ENODATA; > + } > + > + return 0; > +} > + > static int xdpe122_identify(struct i2c_client *client, > struct pmbus_driver_info *info) > { > @@ -70,6 +120,7 @@ static struct pmbus_driver_info xdpe122_info = { > PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | > PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT, > .identify = xdpe122_identify, > + .read_word_data = xdpe122_read_word_data, > }; > > static int xdpe122_probe(struct i2c_client *client, > -- > 2.11.0 >