diff options
-rw-r--r-- | drivers/power/bq27x00_battery.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 42232c296171..b33eae795fab 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -60,8 +60,10 @@ #define BQ27500_REG_SOC 0x2C #define BQ27500_REG_DCAP 0x3C /* Design capacity */ #define BQ27500_FLAG_DSC BIT(0) +#define BQ27500_FLAG_SOCF BIT(1) #define BQ27500_FLAG_BAT_DET BIT(3) #define BQ27500_FLAG_FC BIT(9) +#define BQ27500_FLAG_OTC BIT(15) #define BQ27000_RS 20 /* Resistor sense */ @@ -133,6 +135,7 @@ static enum power_supply_property bq27x00_battery_props[] = { POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_SERIAL_NUMBER, + POWER_SUPPLY_PROP_HEALTH, }; static unsigned int poll_interval = 360; @@ -150,6 +153,31 @@ static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, return di->bus.read(di, reg, single); } +static int bq27510_battery_health(struct bq27x00_device_info *di, + int reg_offset) +{ + int ret; + int status; + + if (di->chip == BQ27500 || di->chip == BQ27510) { + ret = i2c_smbus_read_word_data(di->client, reg_offset); + if (ret < 0) { + dev_err(di->dev, "read failure\n"); + return ret; + } + + if (ret & BQ27500_FLAG_SOCF) + status = POWER_SUPPLY_HEALTH_DEAD; + else if (ret & BQ27500_FLAG_OTC) + status = POWER_SUPPLY_HEALTH_OVERHEAT; + else + status = POWER_SUPPLY_HEALTH_GOOD; + return status; + } + + return -1; +} + /* * Return the battery Relative State-of-Charge * Or < 0 if something fails. @@ -594,6 +622,9 @@ static int bq27x00_battery_get_property(struct power_supply *psy, if (bq27510_get_battery_serial_number(di, val)) return -EINVAL; break; + case POWER_SUPPLY_PROP_HEALTH: + val->intval = bq27510_battery_health(di, BQ27x00_REG_FLAGS); + break; default: return -EINVAL; } |