Skip to content

Commit 7222bd6

Browse files
committed
power: supply: sbs-battery: add PEC support
SBS batteries optionally have support for PEC. This enables PEC handling based on the implemented SBS version as suggested by the standard. The support for PEC is re-evaluated when the battery is hotplugged into the system, since there might be systems supporting batteries from different SBS generations. Tested-by: Marek Szyprowski <[email protected]> Signed-off-by: Sebastian Reichel <[email protected]>
1 parent 05e0430 commit 7222bd6

File tree

1 file changed

+61
-3
lines changed

1 file changed

+61
-3
lines changed

drivers/power/supply/sbs-battery.c

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ enum {
5151
REG_CHARGE_VOLTAGE,
5252
};
5353

54+
#define REG_ADDR_SPEC_INFO 0x1A
55+
#define SPEC_INFO_VERSION_MASK GENMASK(7, 4)
56+
#define SPEC_INFO_VERSION_SHIFT 4
57+
58+
#define SBS_VERSION_1_0 1
59+
#define SBS_VERSION_1_1 2
60+
#define SBS_VERSION_1_1_WITH_PEC 3
61+
5462
#define REG_ADDR_MANUFACTURE_DATE 0x1B
5563

5664
/* Battery Mode defines */
@@ -224,14 +232,57 @@ static void sbs_disable_charger_broadcasts(struct sbs_info *chip)
224232

225233
static int sbs_update_presence(struct sbs_info *chip, bool is_present)
226234
{
235+
struct i2c_client *client = chip->client;
236+
int retries = chip->i2c_retry_count;
237+
s32 ret = 0;
238+
u8 version;
239+
227240
if (chip->is_present == is_present)
228241
return 0;
229242

230243
if (!is_present) {
231244
chip->is_present = false;
245+
/* Disable PEC when no device is present */
246+
client->flags &= ~I2C_CLIENT_PEC;
232247
return 0;
233248
}
234249

250+
/* Check if device supports packet error checking and use it */
251+
while (retries > 0) {
252+
ret = i2c_smbus_read_word_data(client, REG_ADDR_SPEC_INFO);
253+
if (ret >= 0)
254+
break;
255+
256+
/*
257+
* Some batteries trigger the detection pin before the
258+
* I2C bus is properly connected. This works around the
259+
* issue.
260+
*/
261+
msleep(100);
262+
263+
retries--;
264+
}
265+
266+
if (ret < 0) {
267+
dev_dbg(&client->dev, "failed to read spec info: %d\n", ret);
268+
269+
/* fallback to old behaviour */
270+
client->flags &= ~I2C_CLIENT_PEC;
271+
chip->is_present = true;
272+
273+
return ret;
274+
}
275+
276+
version = (ret & SPEC_INFO_VERSION_MASK) >> SPEC_INFO_VERSION_SHIFT;
277+
278+
if (version == SBS_VERSION_1_1_WITH_PEC)
279+
client->flags |= I2C_CLIENT_PEC;
280+
else
281+
client->flags &= ~I2C_CLIENT_PEC;
282+
283+
dev_dbg(&client->dev, "PEC: %s\n", (client->flags & I2C_CLIENT_PEC) ?
284+
"enabled" : "disabled");
285+
235286
if (!chip->is_present && is_present && !chip->charger_broadcasts)
236287
sbs_disable_charger_broadcasts(chip);
237288

@@ -273,7 +324,8 @@ static int sbs_read_string_data_fallback(struct i2c_client *client, u8 address,
273324
retries_length = chip->i2c_retry_count;
274325
retries_block = chip->i2c_retry_count;
275326

276-
dev_warn_once(&client->dev, "I2C adapter does not support I2C_FUNC_SMBUS_READ_BLOCK_DATA.\n");
327+
dev_warn_once(&client->dev, "I2C adapter does not support I2C_FUNC_SMBUS_READ_BLOCK_DATA.\n"
328+
"Fallback method does not support PEC.\n");
277329

278330
/* Adapter needs to support these two functions */
279331
if (!i2c_check_functionality(client->adapter,
@@ -336,8 +388,14 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address, char *val
336388
int retries = chip->i2c_retry_count;
337389
int ret = 0;
338390

339-
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BLOCK_DATA))
340-
return sbs_read_string_data_fallback(client, address, values);
391+
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BLOCK_DATA)) {
392+
bool pec = client->flags & I2C_CLIENT_PEC;
393+
client->flags &= ~I2C_CLIENT_PEC;
394+
ret = sbs_read_string_data_fallback(client, address, values);
395+
if (pec)
396+
client->flags |= I2C_CLIENT_PEC;
397+
return ret;
398+
}
341399

342400
while (retries > 0) {
343401
ret = i2c_smbus_read_block_data(client, address, values);

0 commit comments

Comments
 (0)