提交 9c1ed894 编写于 作者: G Guenter Roeck

hwmon: (pmbus) Add support for virtual pages

Some PMBus chips have non-standard sensor registers. An easy way to
support such sensors is to introduce virtual pages and map the non-standard
registers into standard registers on an extra page.

For this to work, the code verifying if the configured number of pages exists
has to be removed. Since a wrong number of pages can only be configured in a
front-end driver, this should not have a practical impact since the resulting
errors should be found during development and testing.

Also, functions to read the chip status while checking if a command register
exists must be modified to no longer set the page register before reading the
status, since the physical page associated with the checked register may not
exist. This does not make a functional difference since the page was already set
when the attempt to read the register was made.
Signed-off-by: NGuenter Roeck <guenter.roeck@ericsson.com>
Reviewed-by: NRobert Coulson <robert.coulson@ericsson.com>
上级 46243f3a
...@@ -303,7 +303,7 @@ struct pmbus_driver_info { ...@@ -303,7 +303,7 @@ struct pmbus_driver_info {
int pmbus_set_page(struct i2c_client *client, u8 page); int pmbus_set_page(struct i2c_client *client, u8 page);
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
int pmbus_read_byte_data(struct i2c_client *client, u8 page, u8 reg); int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
void pmbus_clear_faults(struct i2c_client *client); void pmbus_clear_faults(struct i2c_client *client);
bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
......
...@@ -164,13 +164,15 @@ int pmbus_set_page(struct i2c_client *client, u8 page) ...@@ -164,13 +164,15 @@ int pmbus_set_page(struct i2c_client *client, u8 page)
} }
EXPORT_SYMBOL_GPL(pmbus_set_page); EXPORT_SYMBOL_GPL(pmbus_set_page);
static int pmbus_write_byte(struct i2c_client *client, u8 page, u8 value) static int pmbus_write_byte(struct i2c_client *client, int page, u8 value)
{ {
int rv; int rv;
rv = pmbus_set_page(client, page); if (page >= 0) {
if (rv < 0) rv = pmbus_set_page(client, page);
return rv; if (rv < 0)
return rv;
}
return i2c_smbus_write_byte(client, value); return i2c_smbus_write_byte(client, value);
} }
...@@ -238,13 +240,15 @@ static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -238,13 +240,15 @@ static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg)
return pmbus_read_word_data(client, page, reg); return pmbus_read_word_data(client, page, reg);
} }
int pmbus_read_byte_data(struct i2c_client *client, u8 page, u8 reg) int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg)
{ {
int rv; int rv;
rv = pmbus_set_page(client, page); if (page >= 0) {
if (rv < 0) rv = pmbus_set_page(client, page);
return rv; if (rv < 0)
return rv;
}
return i2c_smbus_read_byte_data(client, reg); return i2c_smbus_read_byte_data(client, reg);
} }
...@@ -265,13 +269,13 @@ void pmbus_clear_faults(struct i2c_client *client) ...@@ -265,13 +269,13 @@ void pmbus_clear_faults(struct i2c_client *client)
} }
EXPORT_SYMBOL_GPL(pmbus_clear_faults); EXPORT_SYMBOL_GPL(pmbus_clear_faults);
static int pmbus_check_status_cml(struct i2c_client *client, int page) static int pmbus_check_status_cml(struct i2c_client *client)
{ {
int status, status2; int status, status2;
status = pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE); status = pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
if (status < 0 || (status & PB_STATUS_CML)) { if (status < 0 || (status & PB_STATUS_CML)) {
status2 = pmbus_read_byte_data(client, page, PMBUS_STATUS_CML); status2 = pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
return -EINVAL; return -EINVAL;
} }
...@@ -285,8 +289,8 @@ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg) ...@@ -285,8 +289,8 @@ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg)
rv = pmbus_read_byte_data(client, page, reg); rv = pmbus_read_byte_data(client, page, reg);
if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
rv = pmbus_check_status_cml(client, page); rv = pmbus_check_status_cml(client);
pmbus_clear_fault_page(client, page); pmbus_clear_fault_page(client, -1);
return rv >= 0; return rv >= 0;
} }
EXPORT_SYMBOL_GPL(pmbus_check_byte_register); EXPORT_SYMBOL_GPL(pmbus_check_byte_register);
...@@ -298,8 +302,8 @@ bool pmbus_check_word_register(struct i2c_client *client, int page, int reg) ...@@ -298,8 +302,8 @@ bool pmbus_check_word_register(struct i2c_client *client, int page, int reg)
rv = pmbus_read_word_data(client, page, reg); rv = pmbus_read_word_data(client, page, reg);
if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
rv = pmbus_check_status_cml(client, page); rv = pmbus_check_status_cml(client);
pmbus_clear_fault_page(client, page); pmbus_clear_fault_page(client, -1);
return rv >= 0; return rv >= 0;
} }
EXPORT_SYMBOL_GPL(pmbus_check_word_register); EXPORT_SYMBOL_GPL(pmbus_check_word_register);
...@@ -1541,18 +1545,6 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, ...@@ -1541,18 +1545,6 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
ret = -EINVAL; ret = -EINVAL;
goto out_data; goto out_data;
} }
/*
* Bail out if more than one page was configured, but we can not
* select the highest page. This is an indication that the wrong
* chip type was selected. Better bail out now than keep
* returning errors later on.
*/
if (info->pages > 1 && pmbus_set_page(client, info->pages - 1) < 0) {
dev_err(&client->dev, "Failed to select page %d\n",
info->pages - 1);
ret = -EINVAL;
goto out_data;
}
ret = pmbus_identify_common(client, data); ret = pmbus_identify_common(client, data);
if (ret < 0) { if (ret < 0) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册