[PATCH v6 2/2] hwmon: (pmbus) Try use read_status() to read status register

ainux.wang
2021-07-02T07:32:06Z

There is a case(like MP2949A) that the chip do not support STATUS_WORD
and STATUS_BYTE command, but return some random data when reading.

So we should call read_status() instead of i2c_smbus_read_word_data()
and i2c_smbus_read_byte_data(), and the chip driver should implement a
read_word_data() function and a read_byte_data() function to return
-ENXIO.

Signed-off-by: Ainux.Wang <ainux.wang@gmail.com>
---
drivers/hwmon/pmbus/pmbus_core.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 776ee2237be2..d3273a20e76e 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -503,6 +503,9 @@ static int pmbus_check_status_cml(struct i2c_client *client)
struct pmbus_data *data = i2c_get_clientdata(client);
int status, status2;

+ if (!data->read_status)
+ return -EINVAL;
+
status = data->read_status(client, -1);
if (status < 0 || (status & PB_STATUS_CML)) {
status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
@@ -534,6 +537,9 @@ static bool pmbus_check_status_register(struct i2c_client *client, int page)
int status;
struct pmbus_data *data = i2c_get_clientdata(client);

+ if (!data->read_status)
+ return false;
+
status = data->read_status(client, page);
if (status >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK) &&
(status & PB_STATUS_CML)) {
@@ -573,6 +579,8 @@ static int pmbus_get_status(struct i2c_client *client, int page, int reg)

switch (reg) {
case PMBUS_STATUS_WORD:
+ if (!data->read_status)
+ return -EINVAL;
status = data->read_status(client, page);
break;
default:
@@ -2306,16 +2314,15 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
/*
* Some PMBus chips don't support PMBUS_STATUS_WORD, so try
* to use PMBUS_STATUS_BYTE instead if that is the case.
- * Bail out if both registers are not supported.
*/
data->read_status = pmbus_read_status_word;
- ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD);
+ ret = data->read_status(client, -1);
if (ret < 0 || ret == 0xffff) {
data->read_status = pmbus_read_status_byte;
- ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE);
+ ret = data->read_status(client, -1);
if (ret < 0 || ret == 0xff) {
- dev_err(dev, "PMBus status register not found\n");
- return -ENODEV;
+ /* Both registers are not supported. */
+ data->read_status = NULL;
}
} else {
data->has_status_word = true;
@@ -2484,6 +2491,9 @@ static int pmbus_debugfs_get_status(void *data, u64 *val)
struct pmbus_debugfs_entry *entry = data;
struct pmbus_data *pdata = i2c_get_clientdata(entry->client);

+ if (!pdata->read_status)
+ return -EINVAL;
+
rc = pdata->read_status(entry->client, entry->page);
if (rc < 0)
return rc;
--
2.18.1