diff options
Diffstat (limited to 'drivers/hwmon/pmbus/bpa-rs600.c')
-rw-r--r-- | drivers/hwmon/pmbus/bpa-rs600.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/hwmon/pmbus/bpa-rs600.c b/drivers/hwmon/pmbus/bpa-rs600.c index f6558ee9dec3..2be69fedfa36 100644 --- a/drivers/hwmon/pmbus/bpa-rs600.c +++ b/drivers/hwmon/pmbus/bpa-rs600.c @@ -46,6 +46,32 @@ static int bpa_rs600_read_byte_data(struct i2c_client *client, int page, int reg return ret; } +/* + * The BPA-RS600 violates the PMBus spec. Specifically it treats the + * mantissa as unsigned. Deal with this here to allow the PMBus core + * to work with correctly encoded data. + */ +static int bpa_rs600_read_vin(struct i2c_client *client) +{ + int ret, exponent, mantissa; + + ret = pmbus_read_word_data(client, 0, 0xff, PMBUS_READ_VIN); + if (ret < 0) + return ret; + + if (ret & BIT(10)) { + exponent = ret >> 11; + mantissa = ret & 0x7ff; + + exponent++; + mantissa >>= 1; + + ret = (exponent << 11) | mantissa; + } + + return ret; +} + static int bpa_rs600_read_word_data(struct i2c_client *client, int page, int phase, int reg) { int ret; @@ -85,6 +111,9 @@ static int bpa_rs600_read_word_data(struct i2c_client *client, int page, int pha /* These commands return data but it is invalid/un-documented */ ret = -ENXIO; break; + case PMBUS_READ_VIN: + ret = bpa_rs600_read_vin(client); + break; default: if (reg >= PMBUS_VIRT_BASE) ret = -ENXIO; |