aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pmbus
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2011-07-09 10:41:01 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-07-28 20:02:15 -0400
commit9c1ed8941d30fd6252e84a9941e6507e497d242b (patch)
tree5c46c60dafa61427931ab66897a0443e49280894 /drivers/hwmon/pmbus
parent46243f3ab44ad0d2e9ca62e6485ca433659f3881 (diff)
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: Guenter Roeck <guenter.roeck@ericsson.com> Reviewed-by: Robert Coulson <robert.coulson@ericsson.com>
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r--drivers/hwmon/pmbus/pmbus.h2
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c46
2 files changed, 20 insertions, 28 deletions
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index d631caeda106..ceb71f7b91ac 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -303,7 +303,7 @@ struct pmbus_driver_info {
303int pmbus_set_page(struct i2c_client *client, u8 page); 303int pmbus_set_page(struct i2c_client *client, u8 page);
304int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); 304int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
305int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); 305int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
306int pmbus_read_byte_data(struct i2c_client *client, u8 page, u8 reg); 306int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
307void pmbus_clear_faults(struct i2c_client *client); 307void pmbus_clear_faults(struct i2c_client *client);
308bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); 308bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
309bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); 309bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 29143bf886b6..50634497db8d 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -164,13 +164,15 @@ int pmbus_set_page(struct i2c_client *client, u8 page)
164} 164}
165EXPORT_SYMBOL_GPL(pmbus_set_page); 165EXPORT_SYMBOL_GPL(pmbus_set_page);
166 166
167static int pmbus_write_byte(struct i2c_client *client, u8 page, u8 value) 167static int pmbus_write_byte(struct i2c_client *client, int page, u8 value)
168{ 168{
169 int rv; 169 int rv;
170 170
171 rv = pmbus_set_page(client, page); 171 if (page >= 0) {
172 if (rv < 0) 172 rv = pmbus_set_page(client, page);
173 return rv; 173 if (rv < 0)
174 return rv;
175 }
174 176
175 return i2c_smbus_write_byte(client, value); 177 return i2c_smbus_write_byte(client, value);
176} 178}
@@ -238,13 +240,15 @@ static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg)
238 return pmbus_read_word_data(client, page, reg); 240 return pmbus_read_word_data(client, page, reg);
239} 241}
240 242
241int pmbus_read_byte_data(struct i2c_client *client, u8 page, u8 reg) 243int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg)
242{ 244{
243 int rv; 245 int rv;
244 246
245 rv = pmbus_set_page(client, page); 247 if (page >= 0) {
246 if (rv < 0) 248 rv = pmbus_set_page(client, page);
247 return rv; 249 if (rv < 0)
250 return rv;
251 }
248 252
249 return i2c_smbus_read_byte_data(client, reg); 253 return i2c_smbus_read_byte_data(client, reg);
250} 254}
@@ -265,13 +269,13 @@ void pmbus_clear_faults(struct i2c_client *client)
265} 269}
266EXPORT_SYMBOL_GPL(pmbus_clear_faults); 270EXPORT_SYMBOL_GPL(pmbus_clear_faults);
267 271
268static int pmbus_check_status_cml(struct i2c_client *client, int page) 272static int pmbus_check_status_cml(struct i2c_client *client)
269{ 273{
270 int status, status2; 274 int status, status2;
271 275
272 status = pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE); 276 status = pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
273 if (status < 0 || (status & PB_STATUS_CML)) { 277 if (status < 0 || (status & PB_STATUS_CML)) {
274 status2 = pmbus_read_byte_data(client, page, PMBUS_STATUS_CML); 278 status2 = pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
275 if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) 279 if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
276 return -EINVAL; 280 return -EINVAL;
277 } 281 }
@@ -285,8 +289,8 @@ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg)
285 289
286 rv = pmbus_read_byte_data(client, page, reg); 290 rv = pmbus_read_byte_data(client, page, reg);
287 if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) 291 if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
288 rv = pmbus_check_status_cml(client, page); 292 rv = pmbus_check_status_cml(client);
289 pmbus_clear_fault_page(client, page); 293 pmbus_clear_fault_page(client, -1);
290 return rv >= 0; 294 return rv >= 0;
291} 295}
292EXPORT_SYMBOL_GPL(pmbus_check_byte_register); 296EXPORT_SYMBOL_GPL(pmbus_check_byte_register);
@@ -298,8 +302,8 @@ bool pmbus_check_word_register(struct i2c_client *client, int page, int reg)
298 302
299 rv = pmbus_read_word_data(client, page, reg); 303 rv = pmbus_read_word_data(client, page, reg);
300 if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) 304 if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
301 rv = pmbus_check_status_cml(client, page); 305 rv = pmbus_check_status_cml(client);
302 pmbus_clear_fault_page(client, page); 306 pmbus_clear_fault_page(client, -1);
303 return rv >= 0; 307 return rv >= 0;
304} 308}
305EXPORT_SYMBOL_GPL(pmbus_check_word_register); 309EXPORT_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 ret = -EINVAL; 1545 ret = -EINVAL;
1542 goto out_data; 1546 goto out_data;
1543 } 1547 }
1544 /*
1545 * Bail out if more than one page was configured, but we can not
1546 * select the highest page. This is an indication that the wrong
1547 * chip type was selected. Better bail out now than keep
1548 * returning errors later on.
1549 */
1550 if (info->pages > 1 && pmbus_set_page(client, info->pages - 1) < 0) {
1551 dev_err(&client->dev, "Failed to select page %d\n",
1552 info->pages - 1);
1553 ret = -EINVAL;
1554 goto out_data;
1555 }
1556 1548
1557 ret = pmbus_identify_common(client, data); 1549 ret = pmbus_identify_common(client, data);
1558 if (ret < 0) { 1550 if (ret < 0) {