Skip to content

Commit

Permalink
sbs-battery: make writes to ManufacturerAccess optional
Browse files Browse the repository at this point in the history
According to the Smart Battery Data Specification, the use
of ManufacturerAcess (register 0x0) is implementation-defined.
It appears that some batteries use writes to this register
in order to implement certain functionality, but others may
simply NAK all writes to it. As a result, write failures to
ManufacturerAccess should not be used as an indicator of
battery presence, nor as a failure to enter sleep mode.

The failed write access was seen with SANYO AP13J3K.

Cc: Brian Norris <[email protected]>
Signed-off-by: Guenter Roeck <[email protected]>
Signed-off-by: Sebastian Reichel <[email protected]>
  • Loading branch information
groeck authored and sre committed Sep 19, 2016
1 parent 0610735 commit 17c6d39
Showing 1 changed file with 15 additions and 14 deletions.
29 changes: 15 additions & 14 deletions drivers/power/supply/sbs-battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,21 +317,22 @@ static int sbs_get_battery_presence_and_health(
return ret;
}

/* Write to ManufacturerAccess with
* ManufacturerAccess command and then
* read the status */
ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
MANUFACTURER_ACCESS_STATUS);
/*
* Write to ManufacturerAccess with ManufacturerAccess command
* and then read the status. Do not check for error on the write
* since not all batteries implement write access to this command,
* while others mandate it.
*/
sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
MANUFACTURER_ACCESS_STATUS);

ret = sbs_read_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr);
if (ret < 0) {
if (psp == POWER_SUPPLY_PROP_PRESENT)
val->intval = 0; /* battery removed */
return ret;
}

ret = sbs_read_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr);
if (ret < 0)
return ret;

if (ret < sbs_data[REG_MANUFACTURER_DATA].min_value ||
ret > sbs_data[REG_MANUFACTURER_DATA].max_value) {
val->intval = 0;
Expand Down Expand Up @@ -882,16 +883,16 @@ static int sbs_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret;

if (chip->poll_time > 0)
cancel_delayed_work_sync(&chip->work);

/* write to manufacturer access with sleep command */
ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
/*
* Write to manufacturer access with sleep command.
* Support is manufacturer dependend, so ignore errors.
*/
sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
MANUFACTURER_ACCESS_SLEEP);
if (chip->is_present && ret < 0)
return ret;

return 0;
}
Expand Down

0 comments on commit 17c6d39

Please sign in to comment.