Skip to content

Commit 6f24ff9

Browse files
Dan Murphysre
authored andcommitted
power: supply: bq27xxx_battery: Add the BQ27Z561 Battery monitor
Add the Texas Instruments BQ27Z561 battery monitor. The register address map is laid out the same as compared to other devices within the file. The battery status register has differing bits to determine if the battery is full, discharging or dead. Signed-off-by: Dan Murphy <[email protected]> Signed-off-by: Sebastian Reichel <[email protected]>
1 parent 36d1b69 commit 6f24ff9

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

drivers/power/supply/bq27xxx_battery.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
* https://www.ti.com/product/bq27411-g1
4444
* https://www.ti.com/product/bq27441-g1
4545
* https://www.ti.com/product/bq27621-g1
46+
* https://www.ti.com/product/bq27z561
4647
*/
4748

4849
#include <linux/device.h>
@@ -79,6 +80,11 @@
7980
#define BQ27000_FLAG_FC BIT(5)
8081
#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
8182

83+
/* BQ27Z561 has different layout for Flags register */
84+
#define BQ27Z561_FLAG_FDC BIT(4) /* Battery fully discharged */
85+
#define BQ27Z561_FLAG_FC BIT(5) /* Battery fully charged */
86+
#define BQ27Z561_FLAG_DIS_CH BIT(6) /* Battery is discharging */
87+
8288
/* control register params */
8389
#define BQ27XXX_SEALED 0x20
8490
#define BQ27XXX_SET_CFGUPDATE 0x13
@@ -431,12 +437,32 @@ static u8
431437
[BQ27XXX_REG_DCAP] = 0x3c,
432438
[BQ27XXX_REG_AP] = 0x18,
433439
BQ27XXX_DM_REG_ROWS,
434-
};
440+
},
435441
#define bq27411_regs bq27421_regs
436442
#define bq27425_regs bq27421_regs
437443
#define bq27426_regs bq27421_regs
438444
#define bq27441_regs bq27421_regs
439445
#define bq27621_regs bq27421_regs
446+
bq27z561_regs[BQ27XXX_REG_MAX] = {
447+
[BQ27XXX_REG_CTRL] = 0x00,
448+
[BQ27XXX_REG_TEMP] = 0x06,
449+
[BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR,
450+
[BQ27XXX_REG_VOLT] = 0x08,
451+
[BQ27XXX_REG_AI] = 0x14,
452+
[BQ27XXX_REG_FLAGS] = 0x0a,
453+
[BQ27XXX_REG_TTE] = 0x16,
454+
[BQ27XXX_REG_TTF] = 0x18,
455+
[BQ27XXX_REG_TTES] = INVALID_REG_ADDR,
456+
[BQ27XXX_REG_TTECP] = INVALID_REG_ADDR,
457+
[BQ27XXX_REG_NAC] = INVALID_REG_ADDR,
458+
[BQ27XXX_REG_FCC] = 0x12,
459+
[BQ27XXX_REG_CYCT] = 0x2a,
460+
[BQ27XXX_REG_AE] = 0x22,
461+
[BQ27XXX_REG_SOC] = 0x2c,
462+
[BQ27XXX_REG_DCAP] = 0x3c,
463+
[BQ27XXX_REG_AP] = 0x22,
464+
BQ27XXX_DM_REG_ROWS,
465+
};
440466

441467
static enum power_supply_property bq27000_props[] = {
442468
POWER_SUPPLY_PROP_STATUS,
@@ -672,6 +698,25 @@ static enum power_supply_property bq27421_props[] = {
672698
#define bq27441_props bq27421_props
673699
#define bq27621_props bq27421_props
674700

701+
static enum power_supply_property bq27z561_props[] = {
702+
POWER_SUPPLY_PROP_STATUS,
703+
POWER_SUPPLY_PROP_PRESENT,
704+
POWER_SUPPLY_PROP_VOLTAGE_NOW,
705+
POWER_SUPPLY_PROP_CURRENT_NOW,
706+
POWER_SUPPLY_PROP_CAPACITY,
707+
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
708+
POWER_SUPPLY_PROP_TEMP,
709+
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
710+
POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
711+
POWER_SUPPLY_PROP_TECHNOLOGY,
712+
POWER_SUPPLY_PROP_CHARGE_FULL,
713+
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
714+
POWER_SUPPLY_PROP_CYCLE_COUNT,
715+
POWER_SUPPLY_PROP_POWER_AVG,
716+
POWER_SUPPLY_PROP_HEALTH,
717+
POWER_SUPPLY_PROP_MANUFACTURER,
718+
};
719+
675720
struct bq27xxx_dm_reg {
676721
u8 subclass_id;
677722
u8 offset;
@@ -767,11 +812,14 @@ static struct bq27xxx_dm_reg bq27621_dm_regs[] = {
767812
#define bq27621_dm_regs 0
768813
#endif
769814

815+
#define bq27z561_dm_regs 0
816+
770817
#define BQ27XXX_O_ZERO 0x00000001
771818
#define BQ27XXX_O_OTDC 0x00000002 /* has OTC/OTD overtemperature flags */
772819
#define BQ27XXX_O_UTOT 0x00000004 /* has OT overtemperature flag */
773820
#define BQ27XXX_O_CFGUP 0x00000008
774821
#define BQ27XXX_O_RAM 0x00000010
822+
#define BQ27Z561_O_BITS 0x00000020
775823

776824
#define BQ27XXX_DATA(ref, key, opt) { \
777825
.opts = (opt), \
@@ -816,6 +864,7 @@ static struct {
816864
[BQ27426] = BQ27XXX_DATA(bq27426, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM),
817865
[BQ27441] = BQ27XXX_DATA(bq27441, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM),
818866
[BQ27621] = BQ27XXX_DATA(bq27621, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM),
867+
[BQ27Z561] = BQ27XXX_DATA(bq27z561, 0 , BQ27Z561_O_BITS),
819868
};
820869

821870
static DEFINE_MUTEX(bq27xxx_list_lock);
@@ -1551,6 +1600,8 @@ static bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags)
15511600
{
15521601
if (di->opts & BQ27XXX_O_ZERO)
15531602
return flags & (BQ27000_FLAG_EDV1 | BQ27000_FLAG_EDVF);
1603+
else if (di->opts & BQ27Z561_O_BITS)
1604+
return flags & BQ27Z561_FLAG_FDC;
15541605
else
15551606
return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF);
15561607
}
@@ -1595,6 +1646,7 @@ void bq27xxx_battery_update(struct bq27xxx_device_info *di)
15951646
cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
15961647
if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
15971648
cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
1649+
15981650
cache.charge_full = bq27xxx_battery_read_fcc(di);
15991651
cache.capacity = bq27xxx_battery_read_soc(di);
16001652
if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
@@ -1682,6 +1734,13 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
16821734
status = POWER_SUPPLY_STATUS_NOT_CHARGING;
16831735
else
16841736
status = POWER_SUPPLY_STATUS_DISCHARGING;
1737+
} else if (di->opts & BQ27Z561_O_BITS) {
1738+
if (di->cache.flags & BQ27Z561_FLAG_FC)
1739+
status = POWER_SUPPLY_STATUS_FULL;
1740+
else if (di->cache.flags & BQ27Z561_FLAG_DIS_CH)
1741+
status = POWER_SUPPLY_STATUS_DISCHARGING;
1742+
else
1743+
status = POWER_SUPPLY_STATUS_CHARGING;
16851744
} else {
16861745
if (di->cache.flags & BQ27XXX_FLAG_FC)
16871746
status = POWER_SUPPLY_STATUS_FULL;
@@ -1710,6 +1769,13 @@ static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
17101769
level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
17111770
else
17121771
level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
1772+
} else if (di->opts & BQ27Z561_O_BITS) {
1773+
if (di->cache.flags & BQ27Z561_FLAG_FC)
1774+
level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
1775+
else if (di->cache.flags & BQ27Z561_FLAG_FDC)
1776+
level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
1777+
else
1778+
level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
17131779
} else {
17141780
if (di->cache.flags & BQ27XXX_FLAG_FC)
17151781
level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;

drivers/power/supply/bq27xxx_battery_i2c.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
253253
{ "bq27426", BQ27426 },
254254
{ "bq27441", BQ27441 },
255255
{ "bq27621", BQ27621 },
256+
{ "bq27z561", BQ27Z561 },
256257
{},
257258
};
258259
MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
@@ -286,6 +287,7 @@ static const struct of_device_id bq27xxx_battery_i2c_of_match_table[] = {
286287
{ .compatible = "ti,bq27426" },
287288
{ .compatible = "ti,bq27441" },
288289
{ .compatible = "ti,bq27621" },
290+
{ .compatible = "ti,bq27z561" },
289291
{},
290292
};
291293
MODULE_DEVICE_TABLE(of, bq27xxx_battery_i2c_of_match_table);

include/linux/power/bq27xxx_battery.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum bq27xxx_chip {
3030
BQ27426,
3131
BQ27441,
3232
BQ27621,
33+
BQ27Z561,
3334
};
3435

3536
struct bq27xxx_device_info;

0 commit comments

Comments
 (0)