From: Patrick Rudolph <patrick.rudolph@xxxxxxxxxxxxx> Add get_status for pmbus_regulator_ops. Changes: - use lock throughout the function - Avoid line continuation upto 100 column - Optimize use of & and | operator - Check for VOUT, IOUT, TEMPERATURE bit in status word before checking respective status register for fault. - Report regulator current status. Signed-off-by: Patrick Rudolph <patrick.rudolph@xxxxxxxxxxxxx> Signed-off-by: Naresh Solanki <Naresh.Solanki@xxxxxxxxxxxxx> --- drivers/hwmon/pmbus/pmbus_core.c | 88 ++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 7ec04934747e..f7a322d5b453 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -2851,6 +2851,93 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned return 0; } +static int pmbus_regulator_get_status(struct regulator_dev *rdev) +{ + struct device *dev = rdev_get_dev(rdev); + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + u8 page = rdev_get_id(rdev); + int status, status2, ret; + + mutex_lock(&data->update_lock); + status = pmbus_get_status(client, page, PMBUS_STATUS_WORD); + if (status < 0) { + ret = status; + goto unlock; + } + + if (status & PB_STATUS_OFF) { + ret = REGULATOR_STATUS_OFF; + goto unlock; + } + + /* If regulator is ON & reports power good then return ON */ + if (!(status & PB_STATUS_POWER_GOOD_N)) { + ret = REGULATOR_STATUS_ON; + goto unlock; + } + + if (status & (PB_STATUS_VIN_UV | PB_STATUS_IOUT_OC | PB_STATUS_VOUT_OV | + PB_STATUS_UNKNOWN)){ + ret = REGULATOR_STATUS_ERROR; + goto unlock; + } + + if (status & PB_STATUS_VOUT && data->info->func[page] & PMBUS_HAVE_STATUS_VOUT) { + status2 = _pmbus_read_byte_data(client, page, + PMBUS_STATUS_VOUT); + if (status2 < 0) { + ret = status2; + goto unlock; + } + if (status2 & (PB_VOLTAGE_OV_FAULT | PB_VOLTAGE_UV_FAULT)) { + ret = REGULATOR_STATUS_ERROR; + goto unlock; + } + } + + if (status & PB_STATUS_IOUT_POUT && data->info->func[page] & PMBUS_HAVE_STATUS_IOUT) { + status2 = _pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT); + if (status2 < 0) { + ret = status2; + goto unlock; + } + if (status2 & (PB_POUT_OP_FAULT | PB_IOUT_UC_FAULT | PB_IOUT_OC_LV_FAULT | + PB_IOUT_OC_FAULT)) { + ret = REGULATOR_STATUS_ERROR; + goto unlock; + } + } + + if (status & PB_STATUS_INPUT && data->info->func[page] & PMBUS_HAVE_STATUS_INPUT) { + status2 = _pmbus_read_byte_data(client, page, PMBUS_STATUS_INPUT); + if (status2 < 0) { + ret = status2; + goto unlock; + } + if (status2 & (PB_IIN_OC_FAULT | PB_VOLTAGE_OV_FAULT | PB_VOLTAGE_UV_FAULT)) { + ret = REGULATOR_STATUS_ERROR; + goto unlock; + } + } + + if (status & PB_STATUS_TEMPERATURE && data->info->func[page] & PMBUS_HAVE_STATUS_TEMP) { + status2 = _pmbus_read_byte_data(client, page, PMBUS_STATUS_TEMPERATURE); + if (status2 < 0) { + ret = status2; + goto unlock; + } + if (status2 & (PB_TEMP_UT_FAULT | PB_TEMP_OT_FAULT)) { + ret = REGULATOR_STATUS_ERROR; + goto unlock; + } + } + +unlock: + mutex_unlock(&data->update_lock); + return ret; +} + static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page) { struct pmbus_data *data = i2c_get_clientdata(client); @@ -2991,6 +3078,7 @@ const struct regulator_ops pmbus_regulator_ops = { .disable = pmbus_regulator_disable, .is_enabled = pmbus_regulator_is_enabled, .get_error_flags = pmbus_regulator_get_error_flags, + .get_status = pmbus_regulator_get_status, .get_voltage = pmbus_regulator_get_voltage, .set_voltage = pmbus_regulator_set_voltage, .list_voltage = pmbus_regulator_list_voltage, base-commit: 27fea302952d8c90cafbdbee96bafeca03544401 -- 2.37.3