diff options
Diffstat (limited to 'drivers/power/supply/sbs-battery.c')
-rw-r--r-- | drivers/power/supply/sbs-battery.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c index e3a114e60f1a..f7059459f0fb 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c @@ -171,6 +171,7 @@ struct sbs_info { u32 i2c_retry_count; u32 poll_retry_count; struct delayed_work work; + struct mutex mode_lock; }; static char model_name[I2C_SMBUS_BLOCK_MAX + 1]; @@ -199,7 +200,7 @@ static int sbs_read_word_data(struct i2c_client *client, u8 address) return ret; } - return le16_to_cpu(ret); + return ret; } static int sbs_read_string_data(struct i2c_client *client, u8 address, @@ -265,7 +266,7 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address, memcpy(values, block_buffer + 1, block_length); values[block_length] = '\0'; - return le16_to_cpu(ret); + return ret; } static int sbs_write_word_data(struct i2c_client *client, u8 address, @@ -278,8 +279,7 @@ static int sbs_write_word_data(struct i2c_client *client, u8 address, retries = chip->i2c_retry_count; while (retries > 0) { - ret = i2c_smbus_write_word_data(client, address, - le16_to_cpu(value)); + ret = i2c_smbus_write_word_data(client, address, value); if (ret >= 0) break; retries--; @@ -438,6 +438,11 @@ static int sbs_get_battery_property(struct i2c_client *client, } else { if (psp == POWER_SUPPLY_PROP_STATUS) val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + else if (psp == POWER_SUPPLY_PROP_CAPACITY) + /* sbs spec says that this can be >100 % + * even if max value is 100 % + */ + val->intval = min(ret, 100); else val->intval = 0; } @@ -548,12 +553,7 @@ static int sbs_get_battery_capacity(struct i2c_client *client, if (ret < 0) return ret; - if (psp == POWER_SUPPLY_PROP_CAPACITY) { - /* sbs spec says that this can be >100 % - * even if max value is 100 % */ - val->intval = min(ret, 100); - } else - val->intval = ret; + val->intval = ret; ret = sbs_set_battery_mode(client, mode); if (ret < 0) @@ -618,12 +618,17 @@ static int sbs_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGE_NOW: case POWER_SUPPLY_PROP_CHARGE_FULL: case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: - case POWER_SUPPLY_PROP_CAPACITY: ret = sbs_get_property_index(client, psp); if (ret < 0) break; + /* sbs_get_battery_capacity() will change the battery mode + * temporarily to read the requested attribute. Ensure we stay + * in the desired mode for the duration of the attribute read. + */ + mutex_lock(&chip->mode_lock); ret = sbs_get_battery_capacity(client, ret, psp, val); + mutex_unlock(&chip->mode_lock); break; case POWER_SUPPLY_PROP_SERIAL_NUMBER: @@ -640,6 +645,7 @@ static int sbs_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + case POWER_SUPPLY_PROP_CAPACITY: ret = sbs_get_property_index(client, psp); if (ret < 0) break; @@ -808,6 +814,7 @@ static int sbs_probe(struct i2c_client *client, psy_cfg.of_node = client->dev.of_node; psy_cfg.drv_data = chip; chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN; + mutex_init(&chip->mode_lock); /* use pdata if available, fall back to DT properties, * or hardcoded defaults if not |