aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorSaranya Gopal <saranya.gopal@intel.com>2012-07-13 23:20:07 -0400
committerAnton Vorontsov <anton.vorontsov@linaro.org>2012-07-13 23:26:20 -0400
commita66f59ba2e994bf70274ef0513e24e0e7ae20c63 (patch)
treef21bd27fde5fbd681c70aec69ab9b5cc24d3e6af /drivers/power
parent45cd4fb28b43756afcd752ed1e8b3b836c1b1a2a (diff)
bq27x00_battery: Add support for BQ27425 chip
This patch adds support for BQ27425 (TI) chip. This chip is same as BQ27500 with few registers removed and register address map changed. The data sheet for this chip is publicly available at http://www.ti.com/product/bq27425-g1 Signed-off-by: Saranya Gopal <saranya.gopal@intel.com> Reviewed-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/bq27x00_battery.c84
1 files changed, 69 insertions, 15 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 5657990b7ace..181ddece5181 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -22,6 +22,7 @@
22 * Datasheets: 22 * Datasheets:
23 * http://focus.ti.com/docs/prod/folders/print/bq27000.html 23 * http://focus.ti.com/docs/prod/folders/print/bq27000.html
24 * http://focus.ti.com/docs/prod/folders/print/bq27500.html 24 * http://focus.ti.com/docs/prod/folders/print/bq27500.html
25 * http://www.ti.com/product/bq27425-g1
25 */ 26 */
26 27
27#include <linux/module.h> 28#include <linux/module.h>
@@ -69,6 +70,10 @@
69#define BQ27500_FLAG_FC BIT(9) 70#define BQ27500_FLAG_FC BIT(9)
70#define BQ27500_FLAG_OTC BIT(15) 71#define BQ27500_FLAG_OTC BIT(15)
71 72
73/* bq27425 register addresses are same as bq27x00 addresses minus 4 */
74#define BQ27425_REG_OFFSET 0x04
75#define BQ27425_REG_SOC 0x18 /* Register address plus offset */
76
72#define BQ27000_RS 20 /* Resistor sense */ 77#define BQ27000_RS 20 /* Resistor sense */
73#define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000) 78#define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000)
74 79
@@ -77,7 +82,7 @@ struct bq27x00_access_methods {
77 int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); 82 int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
78}; 83};
79 84
80enum bq27x00_chip { BQ27000, BQ27500 }; 85enum bq27x00_chip { BQ27000, BQ27500, BQ27425};
81 86
82struct bq27x00_reg_cache { 87struct bq27x00_reg_cache {
83 int temperature; 88 int temperature;
@@ -132,6 +137,20 @@ static enum power_supply_property bq27x00_battery_props[] = {
132 POWER_SUPPLY_PROP_HEALTH, 137 POWER_SUPPLY_PROP_HEALTH,
133}; 138};
134 139
140static enum power_supply_property bq27425_battery_props[] = {
141 POWER_SUPPLY_PROP_STATUS,
142 POWER_SUPPLY_PROP_PRESENT,
143 POWER_SUPPLY_PROP_VOLTAGE_NOW,
144 POWER_SUPPLY_PROP_CURRENT_NOW,
145 POWER_SUPPLY_PROP_CAPACITY,
146 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
147 POWER_SUPPLY_PROP_TEMP,
148 POWER_SUPPLY_PROP_TECHNOLOGY,
149 POWER_SUPPLY_PROP_CHARGE_FULL,
150 POWER_SUPPLY_PROP_CHARGE_NOW,
151 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
152};
153
135static unsigned int poll_interval = 360; 154static unsigned int poll_interval = 360;
136module_param(poll_interval, uint, 0644); 155module_param(poll_interval, uint, 0644);
137MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ 156MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
@@ -144,10 +163,24 @@ MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
144static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, 163static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
145 bool single) 164 bool single)
146{ 165{
166 if (di->chip == BQ27425)
167 return di->bus.read(di, reg - BQ27425_REG_OFFSET, single);
147 return di->bus.read(di, reg, single); 168 return di->bus.read(di, reg, single);
148} 169}
149 170
150/* 171/*
172 * Higher versions of the chip like BQ27425 and BQ27500
173 * differ from BQ27000 and BQ27200 in calculation of certain
174 * parameters. Hence we need to check for the chip type.
175 */
176static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di)
177{
178 if (di->chip == BQ27425 || di->chip == BQ27500)
179 return true;
180 return false;
181}
182
183/*
151 * Return the battery Relative State-of-Charge 184 * Return the battery Relative State-of-Charge
152 * Or < 0 if something fails. 185 * Or < 0 if something fails.
153 */ 186 */
@@ -157,6 +190,8 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
157 190
158 if (di->chip == BQ27500) 191 if (di->chip == BQ27500)
159 rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); 192 rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
193 else if (di->chip == BQ27425)
194 rsoc = bq27x00_read(di, BQ27425_REG_SOC, false);
160 else 195 else
161 rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true); 196 rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
162 197
@@ -181,7 +216,7 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
181 return charge; 216 return charge;
182 } 217 }
183 218
184 if (di->chip == BQ27500) 219 if (bq27xxx_is_chip_version_higher(di))
185 charge *= 1000; 220 charge *= 1000;
186 else 221 else
187 charge = charge * 3570 / BQ27000_RS; 222 charge = charge * 3570 / BQ27000_RS;
@@ -215,7 +250,7 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
215{ 250{
216 int ilmd; 251 int ilmd;
217 252
218 if (di->chip == BQ27500) 253 if (bq27xxx_is_chip_version_higher(di))
219 ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); 254 ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
220 else 255 else
221 ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); 256 ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
@@ -225,7 +260,7 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
225 return ilmd; 260 return ilmd;
226 } 261 }
227 262
228 if (di->chip == BQ27500) 263 if (bq27xxx_is_chip_version_higher(di))
229 ilmd *= 1000; 264 ilmd *= 1000;
230 else 265 else
231 ilmd = ilmd * 256 * 3570 / BQ27000_RS; 266 ilmd = ilmd * 256 * 3570 / BQ27000_RS;
@@ -269,7 +304,7 @@ static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
269 return temp; 304 return temp;
270 } 305 }
271 306
272 if (di->chip == BQ27500) 307 if (bq27xxx_is_chip_version_higher(di))
273 temp -= 2731; 308 temp -= 2731;
274 else 309 else
275 temp = ((temp * 5) - 5463) / 2; 310 temp = ((temp * 5) - 5463) / 2;
@@ -371,10 +406,12 @@ static void bq27x00_update(struct bq27x00_device_info *di)
371{ 406{
372 struct bq27x00_reg_cache cache = {0, }; 407 struct bq27x00_reg_cache cache = {0, };
373 bool is_bq27500 = di->chip == BQ27500; 408 bool is_bq27500 = di->chip == BQ27500;
409 bool is_bq27425 = di->chip == BQ27425;
374 410
375 cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); 411 cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
376 if (cache.flags >= 0) { 412 if (cache.flags >= 0) {
377 if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) { 413 if (!is_bq27500 && !is_bq27425
414 && (cache.flags & BQ27000_FLAG_CI)) {
378 dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); 415 dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
379 cache.capacity = -ENODATA; 416 cache.capacity = -ENODATA;
380 cache.energy = -ENODATA; 417 cache.energy = -ENODATA;
@@ -385,14 +422,24 @@ static void bq27x00_update(struct bq27x00_device_info *di)
385 cache.health = -ENODATA; 422 cache.health = -ENODATA;
386 } else { 423 } else {
387 cache.capacity = bq27x00_battery_read_rsoc(di); 424 cache.capacity = bq27x00_battery_read_rsoc(di);
388 cache.energy = bq27x00_battery_read_energy(di); 425 if (!is_bq27425) {
389 cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); 426 cache.energy = bq27x00_battery_read_energy(di);
390 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); 427 cache.time_to_empty =
391 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); 428 bq27x00_battery_read_time(di,
429 BQ27x00_REG_TTE);
430 cache.time_to_empty_avg =
431 bq27x00_battery_read_time(di,
432 BQ27x00_REG_TTECP);
433 cache.time_to_full =
434 bq27x00_battery_read_time(di,
435 BQ27x00_REG_TTF);
436 }
392 cache.charge_full = bq27x00_battery_read_lmd(di); 437 cache.charge_full = bq27x00_battery_read_lmd(di);
393 cache.health = bq27x00_battery_read_health(di); 438 cache.health = bq27x00_battery_read_health(di);
394 } 439 }
395 cache.temperature = bq27x00_battery_read_temperature(di); 440 cache.temperature = bq27x00_battery_read_temperature(di);
441 if (!is_bq27425)
442 cache.cycle_count = bq27x00_battery_read_cyct(di);
396 cache.cycle_count = bq27x00_battery_read_cyct(di); 443 cache.cycle_count = bq27x00_battery_read_cyct(di);
397 cache.power_avg = 444 cache.power_avg =
398 bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); 445 bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG);
@@ -441,7 +488,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,
441 return curr; 488 return curr;
442 } 489 }
443 490
444 if (di->chip == BQ27500) { 491 if (bq27xxx_is_chip_version_higher(di)) {
445 /* bq27500 returns signed value */ 492 /* bq27500 returns signed value */
446 val->intval = (int)((s16)curr) * 1000; 493 val->intval = (int)((s16)curr) * 1000;
447 } else { 494 } else {
@@ -462,7 +509,7 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
462{ 509{
463 int status; 510 int status;
464 511
465 if (di->chip == BQ27500) { 512 if (bq27xxx_is_chip_version_higher(di)) {
466 if (di->cache.flags & BQ27500_FLAG_FC) 513 if (di->cache.flags & BQ27500_FLAG_FC)
467 status = POWER_SUPPLY_STATUS_FULL; 514 status = POWER_SUPPLY_STATUS_FULL;
468 else if (di->cache.flags & BQ27500_FLAG_DSC) 515 else if (di->cache.flags & BQ27500_FLAG_DSC)
@@ -490,7 +537,7 @@ static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
490{ 537{
491 int level; 538 int level;
492 539
493 if (di->chip == BQ27500) { 540 if (bq27xxx_is_chip_version_higher(di)) {
494 if (di->cache.flags & BQ27500_FLAG_FC) 541 if (di->cache.flags & BQ27500_FLAG_FC)
495 level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 542 level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
496 else if (di->cache.flags & BQ27500_FLAG_SOC1) 543 else if (di->cache.flags & BQ27500_FLAG_SOC1)
@@ -641,8 +688,14 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
641 int ret; 688 int ret;
642 689
643 di->bat.type = POWER_SUPPLY_TYPE_BATTERY; 690 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
644 di->bat.properties = bq27x00_battery_props; 691 di->chip = BQ27425;
645 di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); 692 if (di->chip == BQ27425) {
693 di->bat.properties = bq27425_battery_props;
694 di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props);
695 } else {
696 di->bat.properties = bq27x00_battery_props;
697 di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
698 }
646 di->bat.get_property = bq27x00_battery_get_property; 699 di->bat.get_property = bq27x00_battery_get_property;
647 di->bat.external_power_changed = bq27x00_external_power_changed; 700 di->bat.external_power_changed = bq27x00_external_power_changed;
648 701
@@ -800,6 +853,7 @@ static int bq27x00_battery_remove(struct i2c_client *client)
800static const struct i2c_device_id bq27x00_id[] = { 853static const struct i2c_device_id bq27x00_id[] = {
801 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ 854 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */
802 { "bq27500", BQ27500 }, 855 { "bq27500", BQ27500 },
856 { "bq27425", BQ27425 },
803 {}, 857 {},
804}; 858};
805MODULE_DEVICE_TABLE(i2c, bq27x00_id); 859MODULE_DEVICE_TABLE(i2c, bq27x00_id);