aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/bq27x00_battery.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/bq27x00_battery.c')
-rw-r--r--drivers/power/bq27x00_battery.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index f5d6d379f2fb..5657990b7ace 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -51,6 +51,7 @@
51#define BQ27x00_REG_LMD 0x12 /* Last measured discharge */ 51#define BQ27x00_REG_LMD 0x12 /* Last measured discharge */
52#define BQ27x00_REG_CYCT 0x2A /* Cycle count total */ 52#define BQ27x00_REG_CYCT 0x2A /* Cycle count total */
53#define BQ27x00_REG_AE 0x22 /* Available energy */ 53#define BQ27x00_REG_AE 0x22 /* Available energy */
54#define BQ27x00_POWER_AVG 0x24
54 55
55#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ 56#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
56#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ 57#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */
@@ -66,8 +67,10 @@
66#define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ 67#define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
67#define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ 68#define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
68#define BQ27500_FLAG_FC BIT(9) 69#define BQ27500_FLAG_FC BIT(9)
70#define BQ27500_FLAG_OTC BIT(15)
69 71
70#define BQ27000_RS 20 /* Resistor sense */ 72#define BQ27000_RS 20 /* Resistor sense */
73#define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000)
71 74
72struct bq27x00_device_info; 75struct bq27x00_device_info;
73struct bq27x00_access_methods { 76struct bq27x00_access_methods {
@@ -86,6 +89,8 @@ struct bq27x00_reg_cache {
86 int capacity; 89 int capacity;
87 int energy; 90 int energy;
88 int flags; 91 int flags;
92 int power_avg;
93 int health;
89}; 94};
90 95
91struct bq27x00_device_info { 96struct bq27x00_device_info {
@@ -123,6 +128,8 @@ static enum power_supply_property bq27x00_battery_props[] = {
123 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 128 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
124 POWER_SUPPLY_PROP_CYCLE_COUNT, 129 POWER_SUPPLY_PROP_CYCLE_COUNT,
125 POWER_SUPPLY_PROP_ENERGY_NOW, 130 POWER_SUPPLY_PROP_ENERGY_NOW,
131 POWER_SUPPLY_PROP_POWER_AVG,
132 POWER_SUPPLY_PROP_HEALTH,
126}; 133};
127 134
128static unsigned int poll_interval = 360; 135static unsigned int poll_interval = 360;
@@ -306,6 +313,60 @@ static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
306 return tval * 60; 313 return tval * 60;
307} 314}
308 315
316/*
317 * Read a power avg register.
318 * Return < 0 if something fails.
319 */
320static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg)
321{
322 int tval;
323
324 tval = bq27x00_read(di, reg, false);
325 if (tval < 0) {
326 dev_err(di->dev, "error reading power avg rgister %02x: %d\n",
327 reg, tval);
328 return tval;
329 }
330
331 if (di->chip == BQ27500)
332 return tval;
333 else
334 return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS;
335}
336
337/*
338 * Read flag register.
339 * Return < 0 if something fails.
340 */
341static int bq27x00_battery_read_health(struct bq27x00_device_info *di)
342{
343 int tval;
344
345 tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
346 if (tval < 0) {
347 dev_err(di->dev, "error reading flag register:%d\n", tval);
348 return tval;
349 }
350
351 if ((di->chip == BQ27500)) {
352 if (tval & BQ27500_FLAG_SOCF)
353 tval = POWER_SUPPLY_HEALTH_DEAD;
354 else if (tval & BQ27500_FLAG_OTC)
355 tval = POWER_SUPPLY_HEALTH_OVERHEAT;
356 else
357 tval = POWER_SUPPLY_HEALTH_GOOD;
358 return tval;
359 } else {
360 if (tval & BQ27000_FLAG_EDV1)
361 tval = POWER_SUPPLY_HEALTH_DEAD;
362 else
363 tval = POWER_SUPPLY_HEALTH_GOOD;
364 return tval;
365 }
366
367 return -1;
368}
369
309static void bq27x00_update(struct bq27x00_device_info *di) 370static void bq27x00_update(struct bq27x00_device_info *di)
310{ 371{
311 struct bq27x00_reg_cache cache = {0, }; 372 struct bq27x00_reg_cache cache = {0, };
@@ -321,6 +382,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
321 cache.time_to_empty_avg = -ENODATA; 382 cache.time_to_empty_avg = -ENODATA;
322 cache.time_to_full = -ENODATA; 383 cache.time_to_full = -ENODATA;
323 cache.charge_full = -ENODATA; 384 cache.charge_full = -ENODATA;
385 cache.health = -ENODATA;
324 } else { 386 } else {
325 cache.capacity = bq27x00_battery_read_rsoc(di); 387 cache.capacity = bq27x00_battery_read_rsoc(di);
326 cache.energy = bq27x00_battery_read_energy(di); 388 cache.energy = bq27x00_battery_read_energy(di);
@@ -328,9 +390,12 @@ static void bq27x00_update(struct bq27x00_device_info *di)
328 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); 390 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
329 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); 391 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
330 cache.charge_full = bq27x00_battery_read_lmd(di); 392 cache.charge_full = bq27x00_battery_read_lmd(di);
393 cache.health = bq27x00_battery_read_health(di);
331 } 394 }
332 cache.temperature = bq27x00_battery_read_temperature(di); 395 cache.temperature = bq27x00_battery_read_temperature(di);
333 cache.cycle_count = bq27x00_battery_read_cyct(di); 396 cache.cycle_count = bq27x00_battery_read_cyct(di);
397 cache.power_avg =
398 bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG);
334 399
335 /* We only have to read charge design full once */ 400 /* We only have to read charge design full once */
336 if (di->charge_design_full <= 0) 401 if (di->charge_design_full <= 0)
@@ -550,6 +615,12 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
550 case POWER_SUPPLY_PROP_ENERGY_NOW: 615 case POWER_SUPPLY_PROP_ENERGY_NOW:
551 ret = bq27x00_simple_value(di->cache.energy, val); 616 ret = bq27x00_simple_value(di->cache.energy, val);
552 break; 617 break;
618 case POWER_SUPPLY_PROP_POWER_AVG:
619 ret = bq27x00_simple_value(di->cache.power_avg, val);
620 break;
621 case POWER_SUPPLY_PROP_HEALTH:
622 ret = bq27x00_simple_value(di->cache.health, val);
623 break;
553 default: 624 default:
554 return -EINVAL; 625 return -EINVAL;
555 } 626 }