diff options
author | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2015-02-28 12:59:28 -0500 |
---|---|---|
committer | Sebastian Reichel <sre@kernel.org> | 2015-02-28 14:30:44 -0500 |
commit | f46bf82e23846fc419861bb7b2c4b041e69b831f (patch) | |
tree | d5f5b714aa7c700c3b17b544f2b51ec8c100c6d4 | |
parent | 5d8a4219a0795a321606c51582898223db80e874 (diff) |
power: bq27x00_battery: add bq27510 support
Add support for bq27510 to the bq27x00 driver.
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
-rw-r--r-- | drivers/power/bq27x00_battery.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 3cd8c68e2bdb..ba08b5926bfd 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c | |||
@@ -21,6 +21,7 @@ | |||
21 | * http://focus.ti.com/docs/prod/folders/print/bq27500.html | 21 | * http://focus.ti.com/docs/prod/folders/print/bq27500.html |
22 | * http://www.ti.com/product/bq27425-g1 | 22 | * http://www.ti.com/product/bq27425-g1 |
23 | * http://www.ti.com/product/BQ27742-G1 | 23 | * http://www.ti.com/product/BQ27742-G1 |
24 | * http://www.ti.com/product/BQ27510-G3 | ||
24 | */ | 25 | */ |
25 | 26 | ||
26 | #include <linux/device.h> | 27 | #include <linux/device.h> |
@@ -71,6 +72,10 @@ | |||
71 | 72 | ||
72 | #define BQ27742_POWER_AVG 0x76 | 73 | #define BQ27742_POWER_AVG 0x76 |
73 | 74 | ||
75 | #define BQ27510_REG_SOC 0x20 | ||
76 | #define BQ27510_REG_DCAP 0x2E /* Design capacity */ | ||
77 | #define BQ27510_REG_CYCT 0x1E /* Cycle count total */ | ||
78 | |||
74 | /* bq27425 register addresses are same as bq27x00 addresses minus 4 */ | 79 | /* bq27425 register addresses are same as bq27x00 addresses minus 4 */ |
75 | #define BQ27425_REG_OFFSET 0x04 | 80 | #define BQ27425_REG_OFFSET 0x04 |
76 | #define BQ27425_REG_SOC (0x1C + BQ27425_REG_OFFSET) | 81 | #define BQ27425_REG_SOC (0x1C + BQ27425_REG_OFFSET) |
@@ -84,7 +89,7 @@ struct bq27x00_access_methods { | |||
84 | int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); | 89 | int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); |
85 | }; | 90 | }; |
86 | 91 | ||
87 | enum bq27x00_chip { BQ27000, BQ27500, BQ27425, BQ27742}; | 92 | enum bq27x00_chip { BQ27000, BQ27500, BQ27425, BQ27742, BQ27510}; |
88 | 93 | ||
89 | struct bq27x00_reg_cache { | 94 | struct bq27x00_reg_cache { |
90 | int temperature; | 95 | int temperature; |
@@ -171,6 +176,24 @@ static enum power_supply_property bq27742_battery_props[] = { | |||
171 | POWER_SUPPLY_PROP_HEALTH, | 176 | POWER_SUPPLY_PROP_HEALTH, |
172 | }; | 177 | }; |
173 | 178 | ||
179 | static enum power_supply_property bq27510_battery_props[] = { | ||
180 | POWER_SUPPLY_PROP_STATUS, | ||
181 | POWER_SUPPLY_PROP_PRESENT, | ||
182 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
183 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
184 | POWER_SUPPLY_PROP_CAPACITY, | ||
185 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
186 | POWER_SUPPLY_PROP_TEMP, | ||
187 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
188 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
189 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
190 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
191 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
192 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
193 | POWER_SUPPLY_PROP_POWER_AVG, | ||
194 | POWER_SUPPLY_PROP_HEALTH, | ||
195 | }; | ||
196 | |||
174 | static unsigned int poll_interval = 360; | 197 | static unsigned int poll_interval = 360; |
175 | module_param(poll_interval, uint, 0644); | 198 | module_param(poll_interval, uint, 0644); |
176 | MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ | 199 | MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ |
@@ -195,7 +218,8 @@ static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, | |||
195 | */ | 218 | */ |
196 | static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di) | 219 | static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di) |
197 | { | 220 | { |
198 | if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742) | 221 | if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742 |
222 | || di->chip == BQ27510) | ||
199 | return true; | 223 | return true; |
200 | return false; | 224 | return false; |
201 | } | 225 | } |
@@ -210,6 +234,8 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di) | |||
210 | 234 | ||
211 | if (di->chip == BQ27500 || di->chip == BQ27742) | 235 | if (di->chip == BQ27500 || di->chip == BQ27742) |
212 | rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); | 236 | rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); |
237 | else if (di->chip == BQ27510) | ||
238 | rsoc = bq27x00_read(di, BQ27510_REG_SOC, false); | ||
213 | else if (di->chip == BQ27425) | 239 | else if (di->chip == BQ27425) |
214 | rsoc = bq27x00_read(di, BQ27425_REG_SOC, false); | 240 | rsoc = bq27x00_read(di, BQ27425_REG_SOC, false); |
215 | else | 241 | else |
@@ -283,6 +309,8 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di) | |||
283 | if (bq27xxx_is_chip_version_higher(di)) { | 309 | if (bq27xxx_is_chip_version_higher(di)) { |
284 | if (di->chip == BQ27425) | 310 | if (di->chip == BQ27425) |
285 | ilmd = bq27x00_read(di, BQ27425_REG_DCAP, false); | 311 | ilmd = bq27x00_read(di, BQ27425_REG_DCAP, false); |
312 | else if (di->chip == BQ27510) | ||
313 | ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false); | ||
286 | else | 314 | else |
287 | ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); | 315 | ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); |
288 | } else | 316 | } else |
@@ -351,7 +379,10 @@ static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di) | |||
351 | { | 379 | { |
352 | int cyct; | 380 | int cyct; |
353 | 381 | ||
354 | cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false); | 382 | if (di->chip == BQ27510) |
383 | cyct = bq27x00_read(di, BQ27510_REG_CYCT, false); | ||
384 | else | ||
385 | cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false); | ||
355 | if (cyct < 0) | 386 | if (cyct < 0) |
356 | dev_err(di->dev, "error reading cycle count total\n"); | 387 | dev_err(di->dev, "error reading cycle count total\n"); |
357 | 388 | ||
@@ -422,6 +453,10 @@ static int bq27x00_battery_read_health(struct bq27x00_device_info *di) | |||
422 | else | 453 | else |
423 | tval = POWER_SUPPLY_HEALTH_GOOD; | 454 | tval = POWER_SUPPLY_HEALTH_GOOD; |
424 | return tval; | 455 | return tval; |
456 | } else if (di->chip == BQ27510) { | ||
457 | if (tval & BQ27500_FLAG_OTC) | ||
458 | return POWER_SUPPLY_HEALTH_OVERHEAT; | ||
459 | return POWER_SUPPLY_HEALTH_GOOD; | ||
425 | } else { | 460 | } else { |
426 | if (tval & BQ27000_FLAG_EDV1) | 461 | if (tval & BQ27000_FLAG_EDV1) |
427 | tval = POWER_SUPPLY_HEALTH_DEAD; | 462 | tval = POWER_SUPPLY_HEALTH_DEAD; |
@@ -437,6 +472,7 @@ static void bq27x00_update(struct bq27x00_device_info *di) | |||
437 | { | 472 | { |
438 | struct bq27x00_reg_cache cache = {0, }; | 473 | struct bq27x00_reg_cache cache = {0, }; |
439 | bool is_bq27500 = di->chip == BQ27500; | 474 | bool is_bq27500 = di->chip == BQ27500; |
475 | bool is_bq27510 = di->chip == BQ27510; | ||
440 | bool is_bq27425 = di->chip == BQ27425; | 476 | bool is_bq27425 = di->chip == BQ27425; |
441 | bool is_bq27742 = di->chip == BQ27742; | 477 | bool is_bq27742 = di->chip == BQ27742; |
442 | bool flags_1b = !(is_bq27500 || is_bq27742); | 478 | bool flags_1b = !(is_bq27500 || is_bq27742); |
@@ -446,7 +482,7 @@ static void bq27x00_update(struct bq27x00_device_info *di) | |||
446 | /* read error */ | 482 | /* read error */ |
447 | cache.flags = -1; | 483 | cache.flags = -1; |
448 | if (cache.flags >= 0) { | 484 | if (cache.flags >= 0) { |
449 | if (!is_bq27500 && !is_bq27425 && !is_bq27742 | 485 | if (!is_bq27500 && !is_bq27425 && !is_bq27742 && !is_bq27510 |
450 | && (cache.flags & BQ27000_FLAG_CI)) { | 486 | && (cache.flags & BQ27000_FLAG_CI)) { |
451 | dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); | 487 | dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); |
452 | cache.capacity = -ENODATA; | 488 | cache.capacity = -ENODATA; |
@@ -458,7 +494,7 @@ static void bq27x00_update(struct bq27x00_device_info *di) | |||
458 | cache.health = -ENODATA; | 494 | cache.health = -ENODATA; |
459 | } else { | 495 | } else { |
460 | cache.capacity = bq27x00_battery_read_rsoc(di); | 496 | cache.capacity = bq27x00_battery_read_rsoc(di); |
461 | if (is_bq27742) | 497 | if (is_bq27742 || is_bq27510) |
462 | cache.time_to_empty = | 498 | cache.time_to_empty = |
463 | bq27x00_battery_read_time(di, | 499 | bq27x00_battery_read_time(di, |
464 | BQ27x00_REG_TTE); | 500 | BQ27x00_REG_TTE); |
@@ -742,6 +778,9 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) | |||
742 | } else if (di->chip == BQ27742) { | 778 | } else if (di->chip == BQ27742) { |
743 | di->bat.properties = bq27742_battery_props; | 779 | di->bat.properties = bq27742_battery_props; |
744 | di->bat.num_properties = ARRAY_SIZE(bq27742_battery_props); | 780 | di->bat.num_properties = ARRAY_SIZE(bq27742_battery_props); |
781 | } else if (di->chip == BQ27510) { | ||
782 | di->bat.properties = bq27510_battery_props; | ||
783 | di->bat.num_properties = ARRAY_SIZE(bq27510_battery_props); | ||
745 | } else { | 784 | } else { |
746 | di->bat.properties = bq27x00_battery_props; | 785 | di->bat.properties = bq27x00_battery_props; |
747 | di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); | 786 | di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); |
@@ -899,6 +938,7 @@ static const struct i2c_device_id bq27x00_id[] = { | |||
899 | { "bq27500", BQ27500 }, | 938 | { "bq27500", BQ27500 }, |
900 | { "bq27425", BQ27425 }, | 939 | { "bq27425", BQ27425 }, |
901 | { "bq27742", BQ27742 }, | 940 | { "bq27742", BQ27742 }, |
941 | { "bq27510", BQ27510 }, | ||
902 | {}, | 942 | {}, |
903 | }; | 943 | }; |
904 | MODULE_DEVICE_TABLE(i2c, bq27x00_id); | 944 | MODULE_DEVICE_TABLE(i2c, bq27x00_id); |