Commit c4b12a2f authored by Sebastian Reichel's avatar Sebastian Reichel Committed by Sebastian Reichel

power: supply: sbs-battery: simplify read_read_string_data

The SBS battery implements SMBus block reads. Currently the
driver "emulates" this by doing an I2C byte read for the
length followed by an I2C block read. The I2C subsystem
actually provides a proper API for doing SMBus block reads,
which can and should be used instead. The current implementation
does not properly handle packet error checking (PEC).

This change requires, that I2C bus drivers support I2C_M_RECV_LEN
or directly provide the SMBus API to access device manufacturer
and model name.
Reviewed-by: default avatarEmil Velikov <emil.velikov@collabora.com>
Signed-off-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
parent d6f56321
...@@ -202,66 +202,32 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address, ...@@ -202,66 +202,32 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address,
char *values) char *values)
{ {
struct sbs_info *chip = i2c_get_clientdata(client); struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret = 0, block_length = 0; int retries = chip->i2c_retry_count;
int retries_length, retries_block; s32 ret = 0;
u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
retries_length = chip->i2c_retry_count;
retries_block = chip->i2c_retry_count;
/* Adapter needs to support these two functions */
if (!i2c_check_functionality(client->adapter, if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_READ_BLOCK_DATA)) {
I2C_FUNC_SMBUS_I2C_BLOCK)){
return -ENODEV; return -ENODEV;
} }
/* Get the length of block data */
while (retries_length > 0) {
ret = i2c_smbus_read_byte_data(client, address);
if (ret >= 0)
break;
retries_length--;
}
if (ret < 0) {
dev_dbg(&client->dev,
"%s: i2c read at address 0x%x failed\n",
__func__, address);
return ret;
}
/* block_length does not include NULL terminator */
block_length = ret;
if (block_length > I2C_SMBUS_BLOCK_MAX) {
dev_err(&client->dev,
"%s: Returned block_length is longer than 0x%x\n",
__func__, I2C_SMBUS_BLOCK_MAX);
return -EINVAL;
}
/* Get the block data */ /* Get the block data */
while (retries_block > 0) { while (retries > 0) {
ret = i2c_smbus_read_i2c_block_data( ret = i2c_smbus_read_block_data(client, address, values);
client, address,
block_length + 1, block_buffer);
if (ret >= 0) if (ret >= 0)
break; break;
retries_block--; retries--;
} }
if (ret < 0) { if (ret < 0) {
dev_dbg(&client->dev, dev_dbg(&client->dev, "%s: failed to read block 0x%x: %d\n",
"%s: i2c read at address 0x%x failed\n", __func__, address, ret);
__func__, address);
return ret; return ret;
} }
/* block_buffer[0] == block_length */ /* add string termination */
memcpy(values, block_buffer + 1, block_length); values[ret] = '\0';
values[block_length] = '\0';
return ret; return 0;
} }
static int sbs_write_word_data(struct i2c_client *client, u8 address, static int sbs_write_word_data(struct i2c_client *client, u8 address,
...@@ -465,14 +431,7 @@ static int sbs_get_battery_property(struct i2c_client *client, ...@@ -465,14 +431,7 @@ static int sbs_get_battery_property(struct i2c_client *client,
static int sbs_get_battery_string_property(struct i2c_client *client, static int sbs_get_battery_string_property(struct i2c_client *client,
int reg_offset, enum power_supply_property psp, char *val) int reg_offset, enum power_supply_property psp, char *val)
{ {
s32 ret; return sbs_read_string_data(client, sbs_data[reg_offset].addr, val);
ret = sbs_read_string_data(client, sbs_data[reg_offset].addr, val);
if (ret < 0)
return ret;
return 0;
} }
static void sbs_unit_adjustment(struct i2c_client *client, static void sbs_unit_adjustment(struct i2c_client *client,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment