aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/tps80031_battery_gauge.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/tps80031_battery_gauge.c')
-rw-r--r--drivers/power/tps80031_battery_gauge.c606
1 files changed, 606 insertions, 0 deletions
diff --git a/drivers/power/tps80031_battery_gauge.c b/drivers/power/tps80031_battery_gauge.c
new file mode 100644
index 00000000000..9ccfaad4144
--- /dev/null
+++ b/drivers/power/tps80031_battery_gauge.c
@@ -0,0 +1,606 @@
1/*
2 * drivers/power/tps80031_battery_gauge.c
3 *
4 * Gas Gauge driver for TI's tps80031
5 *
6 * Copyright (c) 2011, NVIDIA Corporation.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22#include <linux/kernel.h>
23#include <linux/platform_device.h>
24#include <linux/regulator/driver.h>
25#include <linux/err.h>
26#include <linux/regulator/machine.h>
27#include <linux/mutex.h>
28
29#include <linux/module.h>
30#include <linux/param.h>
31#include <linux/jiffies.h>
32#include <linux/workqueue.h>
33#include <linux/pm.h>
34#include <linux/i2c.h>
35#include <linux/slab.h>
36#include <linux/platform_device.h>
37#include <linux/power_supply.h>
38
39#include <linux/mfd/core.h>
40#include <linux/mfd/tps80031.h>
41#include <linux/tps80031-charger.h>
42
43#define CHARGERUSB_CINLIMIT 0xee
44#define CONTROLLER_STAT1 0xe3
45#define LINEAR_CHARGE_STS 0xde
46#define STS_HW_CONDITIONS 0x21
47#define TOGGLE1 0x90
48#define TOGGLE1_FGS BIT(5)
49#define TOGGLE1_GPADCR BIT(1)
50#define GPCH0_LSB 0x3b
51#define GPCH0_MSB 0x3c
52#define GPCH0_MSB_COLLISION_GP BIT(4)
53#define GPSELECT_ISB 0x35
54#define GPADC_CTRL 0x2e
55#define MISC1 0xe4
56#define CTRL_P1 0x36
57#define CTRL_P1_SP1 BIT(3)
58#define CTRL_P1_EOCRT BIT(2)
59#define CTRL_P1_EOCP1 BIT(1)
60#define CTRL_P1_BUSY BIT(0)
61#define FG_REG_00 0xc0
62#define FG_REG_00_CC_CAL_EN BIT(1)
63#define FG_REG_00_CC_AUTOCLEAR BIT(2)
64#define FG_REG_01 0xc1 /* CONV_NR (unsigned) 0 - 7 */
65#define FG_REG_02 0xc2 /* CONV_NR (unsigned) 8 - 15 */
66#define FG_REG_03 0xc3 /* CONV_NR (unsigned) 16 - 23 */
67#define FG_REG_04 0xc4 /* ACCM (signed) 0 - 7 */
68#define FG_REG_05 0xc5 /* ACCM (signed) 8 - 15 */
69#define FG_REG_06 0xc6 /* ACCM (signed) 16 - 23 */
70#define FG_REG_07 0xc7 /* ACCM (signed) 24 - 31 */
71#define FG_REG_08 0xc8 /* OFFSET (signed) 0 - 7 */
72#define FG_REG_09 0xc9 /* OFFSET (signed) 8 - 9 */
73#define FG_REG_10 0xca /* LAST_READ (signed) 0 - 7 */
74#define FG_REG_11 0xcb /* LAST_READ (signed) 8 - 13 */
75
76#define TPS80031_VBUS_DET BIT(2)
77#define TPS80031_VAC_DET BIT(3)
78#define TPS80031_STS_VYSMIN_HI BIT(4)
79#define END_OF_CHARGE BIT(5)
80
81#define DRIVER_VERSION "1.1.0"
82#define BATTERY_POLL_PERIOD 30000
83
84static int tps80031_temp_table[] = {
85 /* adc code for temperature in degree C */
86 929, 925, /* -2, -1 */
87 920, 917, 912, 908, 904, 899, 895, 890, 885, 880, /* 00 - 09 */
88 875, 869, 864, 858, 853, 847, 841, 835, 829, 823, /* 10 - 19 */
89 816, 810, 804, 797, 790, 783, 776, 769, 762, 755, /* 20 - 29 */
90 748, 740, 732, 725, 718, 710, 703, 695, 687, 679, /* 30 - 39 */
91 671, 663, 655, 647, 639, 631, 623, 615, 607, 599, /* 40 - 49 */
92 591, 583, 575, 567, 559, 551, 543, 535, 527, 519, /* 50 - 59 */
93 511, 504, 496 /* 60 - 62 */
94};
95
96struct tps80031_device_info {
97 struct device *dev;
98 struct i2c_client *client;
99 struct power_supply bat;
100 struct power_supply ac;
101 struct power_supply usb;
102 struct timer_list battery_poll_timer;
103 uint32_t vsys;
104 uint8_t usb_online;
105 uint8_t ac_online;
106 uint8_t usb_status;
107 uint8_t capacity_sts;
108 uint8_t health;
109 uint8_t sys_vlow_intr;
110 uint8_t fg_calib_intr;
111 int16_t fg_offset;
112 struct mutex adc_lock;
113};
114
115static enum power_supply_property tps80031_bat_props[] = {
116 POWER_SUPPLY_PROP_TECHNOLOGY,
117 POWER_SUPPLY_PROP_VOLTAGE_NOW,
118 POWER_SUPPLY_PROP_TEMP,
119 POWER_SUPPLY_PROP_CAPACITY,
120 POWER_SUPPLY_PROP_HEALTH,
121 POWER_SUPPLY_PROP_STATUS,
122 POWER_SUPPLY_PROP_CHARGE_NOW,
123 POWER_SUPPLY_PROP_CHARGE_COUNTER,
124};
125
126static enum power_supply_property tps80031_usb_props[] = {
127 POWER_SUPPLY_PROP_ONLINE,
128};
129
130static enum power_supply_property tps80031_ac_props[] = {
131 POWER_SUPPLY_PROP_ONLINE,
132};
133
134static int tps80031_reg_read(struct tps80031_device_info *di, int sid, int reg,
135 uint8_t *val)
136{
137 int ret;
138
139 ret = tps80031_read(di->dev->parent, sid, reg, val);
140 if (ret < 0)
141 dev_err(di->dev, "Failed read register 0x%02x\n",
142 reg);
143 return ret;
144}
145
146static int tps80031_reg_write(struct tps80031_device_info *di, int sid, int reg,
147 uint8_t val)
148{
149 int ret;
150
151 ret = tps80031_write(di->dev->parent, sid, reg, val);
152 if (ret < 0)
153 dev_err(di->dev, "Failed write register 0x%02x\n",
154 reg);
155 return ret;
156}
157
158static int tps80031_battery_capacity(struct tps80031_device_info *di,
159 union power_supply_propval *val)
160{
161 uint8_t hwsts;
162 int ret;
163
164 ret = tps80031_reg_read(di, SLAVE_ID2, LINEAR_CHARGE_STS, &hwsts);
165 if (ret < 0)
166 return ret;
167
168 di->capacity_sts = di->vsys;
169 if (hwsts & END_OF_CHARGE)
170 di->capacity_sts = 100;
171
172 if (di->sys_vlow_intr) {
173 di->capacity_sts = 10;
174 di->sys_vlow_intr = 0;
175 }
176
177 if (di->capacity_sts <= 10)
178 di->health = POWER_SUPPLY_HEALTH_DEAD;
179 else
180 di->health = POWER_SUPPLY_HEALTH_GOOD;
181
182 return di->capacity_sts;
183}
184
185static int tps80031_battery_voltage(struct tps80031_device_info *di,
186 union power_supply_propval *val)
187{
188 int voltage;
189
190 voltage = tps80031_gpadc_conversion(SYSTEM_SUPPLY);
191 if (voltage < 0)
192 return voltage;
193 voltage = ((voltage * 1000) / 4) * 5;
194
195 if (voltage < 3700000)
196 di->vsys = 10;
197 else if (voltage > 3700000 && voltage <= 3800000)
198 di->vsys = 20;
199 else if (voltage > 3800000 && voltage <= 3900000)
200 di->vsys = 50;
201 else if (voltage > 3900000 && voltage <= 4000000)
202 di->vsys = 75;
203 else if (voltage >= 4000000)
204 di->vsys = 90;
205
206 return voltage;
207}
208
209static int tps80031_battery_charge_now(struct tps80031_device_info *di,
210 union power_supply_propval *val)
211{
212 int charge;
213
214 charge = tps80031_gpadc_conversion(BATTERY_CHARGING_CURRENT);
215 if (charge < 0)
216 return charge;
217 charge = charge * 78125 / 40;
218
219 return charge;
220}
221
222static int tps80031_battery_charge_counter(struct tps80031_device_info *di,
223 union power_supply_propval *val)
224{
225 int retval, ret;
226 uint32_t cnt_byte;
227 uint32_t acc_byte;
228
229 /* check if calibrated */
230 if (di->fg_calib_intr == 0)
231 return 0;
232
233 /* get current accumlator */
234 ret = tps80031_reads(di->dev->parent, SLAVE_ID2, FG_REG_04, 4,
235 (uint8_t *) &acc_byte);
236 if (ret < 0)
237 return ret;
238 /* counter value is mAs, need report uAh */
239 retval = (int32_t) acc_byte / 18 * 5;
240
241 /* get counter */
242 ret = tps80031_reads(di->dev->parent, SLAVE_ID2, FG_REG_01, 3,
243 (uint8_t *) &cnt_byte);
244 if (ret < 0)
245 return ret;
246 /* we need calibrate the offset current in uAh*/
247 retval = retval - (di->fg_offset / 4 * cnt_byte);
248
249 /* @todo, counter value will overflow if battery get continuously
250 * charged discharged for more than 108Ah using 250mS integration
251 * period althrough it is hightly impossible.
252 */
253
254 return retval;
255}
256
257static int tps80031_battery_temp(struct tps80031_device_info *di,
258 union power_supply_propval *val)
259{
260 int adc_code, temp;
261
262 adc_code = tps80031_gpadc_conversion(BATTERY_TEMPERATURE);
263 if (adc_code < 0)
264 return adc_code;
265
266 for (temp = 0; temp < ARRAY_SIZE(tps80031_temp_table); temp++) {
267 if (adc_code >= tps80031_temp_table[temp])
268 break;
269 }
270 /* first 2 values are for negative temperature */
271 val->intval = (temp - 2) * 10; /* in tenths of degree Celsius */
272
273 return val->intval;
274}
275
276#define to_tps80031_device_info_bat(x) container_of((x), \
277 struct tps80031_device_info, bat);
278
279static int tps80031_bat_get_property(struct power_supply *psy,
280 enum power_supply_property psp, union power_supply_propval *val)
281{
282 struct tps80031_device_info *di = to_tps80031_device_info_bat(psy);
283
284 switch (psp) {
285
286 case POWER_SUPPLY_PROP_TECHNOLOGY:
287 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
288 break;
289
290 case POWER_SUPPLY_PROP_HEALTH:
291 val->intval = di->health;
292 break;
293
294 case POWER_SUPPLY_PROP_CAPACITY:
295 val->intval = tps80031_battery_capacity(di, val);
296 break;
297
298 case POWER_SUPPLY_PROP_CHARGE_NOW:
299 val->intval = tps80031_battery_charge_now(di, val);
300 break;
301
302 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
303 val->intval = tps80031_battery_voltage(di, val);
304 break;
305
306 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
307 val->intval = tps80031_battery_charge_counter(di, val);
308 break;
309
310 case POWER_SUPPLY_PROP_STATUS:
311 val->intval = di->usb_status;
312 break;
313
314 case POWER_SUPPLY_PROP_TEMP:
315 val->intval = tps80031_battery_temp(di, val);
316 break;
317
318 default:
319 return -EINVAL;
320 }
321 return 0;
322}
323
324#define to_tps80031_device_info_usb(x) container_of((x), \
325 struct tps80031_device_info, usb);
326
327static int tps80031_usb_get_property(struct power_supply *psy,
328 enum power_supply_property psp, union power_supply_propval *val)
329{
330 struct tps80031_device_info *di = to_tps80031_device_info_usb(psy);
331
332 switch (psp) {
333 case POWER_SUPPLY_PROP_ONLINE:
334 val->intval = di->usb_online;
335 break;
336 default:
337 return -EINVAL;
338 }
339 return 0;
340}
341
342#define to_tps80031_device_info_ac(x) container_of((x), \
343 struct tps80031_device_info, ac);
344
345static int tps80031_ac_get_property(struct power_supply *psy,
346 enum power_supply_property psp, union power_supply_propval *val)
347{
348 struct tps80031_device_info *di = to_tps80031_device_info_ac(psy);
349
350 switch (psp) {
351 case POWER_SUPPLY_PROP_ONLINE:
352 val->intval = di->ac_online;
353 break;
354 default:
355 return -EINVAL;
356 }
357 return 0;
358}
359
360static irqreturn_t tps80031_sys_vlow(int irq, void *data)
361{
362 struct tps80031_device_info *di = data;
363
364 di->sys_vlow_intr = 1;
365 power_supply_changed(&di->bat);
366 return IRQ_HANDLED;
367}
368
369static irqreturn_t tps80031_fg_calibrated(int irq, void *data)
370{
371 struct tps80031_device_info *di = data;
372 uint8_t acc_byte0;
373 uint8_t acc_byte1;
374 int ret;
375
376 ret = tps80031_reg_read(di, SLAVE_ID2, FG_REG_08, &acc_byte0);
377 if (ret < 0)
378 return IRQ_HANDLED;
379 ret = tps80031_reg_read(di, SLAVE_ID2, FG_REG_09, &acc_byte1);
380 if (ret < 0)
381 return IRQ_HANDLED;
382 /* sign extension */
383 if (acc_byte1 & 0x02)
384 acc_byte1 = acc_byte1 | 0xFC;
385 else
386 acc_byte1 = acc_byte1 & 0x03;
387
388 di->fg_offset = (int16_t) ((acc_byte1 << 8) | acc_byte0);
389 /* fuel gauge auto calibration finished */
390 di->fg_calib_intr = 1;
391 return IRQ_HANDLED;
392}
393
394static int tps80031_fg_start_gas_gauge(struct tps80031_device_info *di)
395{
396 int ret = 0;
397 di->fg_calib_intr = 0;
398
399 /* start gas gauge */
400 ret = tps80031_reg_write(di, SLAVE_ID2, TOGGLE1, 0x20);
401 if (ret < 0)
402 return ret;
403 /* set ADC update time to 3.9ms and start calibration */
404 ret = tps80031_reg_write(di, SLAVE_ID2, FG_REG_00, FG_REG_00_CC_CAL_EN);
405 if (ret < 0)
406 return ret;
407 return ret;
408}
409
410void tps80031_battery_status(enum charging_states status, void *data)
411{
412 struct tps80031_device_info *di = data;
413 int ret;
414 uint8_t retval;
415
416 if ((status == charging_state_charging_in_progress)) {
417 di->usb_status = POWER_SUPPLY_STATUS_CHARGING;
418 di->health = POWER_SUPPLY_HEALTH_GOOD;
419 ret = tps80031_reg_read(di, SLAVE_ID2,
420 CHARGERUSB_CINLIMIT, &retval);
421 if (ret < 0) {
422 di->ac_online = 0;
423 di->usb_online = 0;
424 }
425 if (retval == 0x9) {
426 di->ac_online = 0;
427 di->usb_online = 1;
428 } else {
429 di->usb_online = 0;
430 di->ac_online = 1;
431 }
432 } else if (status == charging_state_charging_stopped) {
433 di->usb_status = POWER_SUPPLY_STATUS_DISCHARGING;
434 di->ac_online = 0;
435 di->usb_online = 0;
436 }
437 power_supply_changed(&di->usb);
438 power_supply_changed(&di->bat);
439 power_supply_changed(&di->ac);
440}
441
442static void battery_poll_timer_func(unsigned long pdi)
443{
444 struct tps80031_device_info *di = (void *)pdi;
445 power_supply_changed(&di->bat);
446 mod_timer(&di->battery_poll_timer,
447 jiffies + msecs_to_jiffies(BATTERY_POLL_PERIOD));
448}
449
450static int tps80031_battery_probe(struct platform_device *pdev)
451{
452 int ret;
453 uint8_t retval;
454 struct device *dev = &pdev->dev;
455 struct tps80031_device_info *di;
456 struct tps80031_bg_platform_data *pdata = pdev->dev.platform_data;
457
458 di = devm_kzalloc(&pdev->dev, sizeof *di, GFP_KERNEL);
459 if (!di) {
460 dev_err(dev->parent, "failed to allocate device info data\n");
461 return -ENOMEM;
462 }
463
464 if (!pdata->battery_present) {
465 dev_err(dev, "%s() No battery detected, exiting..\n",
466 __func__);
467 return -ENODEV;
468 }
469
470 di->dev = &pdev->dev;
471
472 ret = tps80031_reg_read(di, SLAVE_ID2, CONTROLLER_STAT1, &retval);
473 if (ret < 0)
474 return ret;
475
476 if ((retval & TPS80031_VAC_DET) | (retval & TPS80031_VBUS_DET)) {
477 di->usb_status = POWER_SUPPLY_STATUS_CHARGING;
478 di->usb_online = 1;
479 } else {
480 di->usb_status = POWER_SUPPLY_STATUS_DISCHARGING;
481 di->usb_online = 0;
482 }
483
484 di->capacity_sts = 50;
485 di->health = POWER_SUPPLY_HEALTH_GOOD;
486
487 di->bat.name = "tps80031-bat";
488 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
489 di->bat.properties = tps80031_bat_props;
490 di->bat.num_properties = ARRAY_SIZE(tps80031_bat_props);
491 di->bat.get_property = tps80031_bat_get_property;
492
493 ret = power_supply_register(dev->parent, &di->bat);
494 if (ret) {
495 dev_err(dev->parent, "failed to register bat power supply\n");
496 return ret;
497 }
498
499 di->usb.name = "tps80031-usb";
500 di->usb.type = POWER_SUPPLY_TYPE_USB;
501 di->usb.properties = tps80031_usb_props;
502 di->usb.num_properties = ARRAY_SIZE(tps80031_usb_props);
503 di->usb.get_property = tps80031_usb_get_property;
504
505 ret = power_supply_register(dev->parent, &di->usb);
506 if (ret) {
507 dev_err(dev->parent, "failed to register ac power supply\n");
508 goto power_supply_fail2;
509 }
510
511 di->ac.name = "tps80031-ac";
512 di->ac.type = POWER_SUPPLY_TYPE_MAINS;
513 di->ac.properties = tps80031_ac_props;
514 di->ac.num_properties = ARRAY_SIZE(tps80031_ac_props);
515 di->ac.get_property = tps80031_ac_get_property;
516
517 ret = power_supply_register(dev->parent, &di->ac);
518 if (ret) {
519 dev_err(dev->parent, "failed to register ac power supply\n");
520 goto power_supply_fail1;
521 }
522
523 dev_set_drvdata(&pdev->dev, di);
524
525 ret = register_charging_state_callback(tps80031_battery_status, di);
526 if (ret < 0)
527 goto power_supply_fail0;
528
529 ret = request_threaded_irq(pdata->irq_base + TPS80031_INT_SYS_VLOW,
530 NULL, tps80031_sys_vlow,
531 IRQF_ONESHOT, "tps80031_sys_vlow", di);
532 if (ret < 0) {
533 dev_err(dev->parent, "request IRQ %d fail\n", pdata->irq_base);
534 goto power_supply_fail0;
535 }
536
537 ret = request_threaded_irq(pdata->irq_base + TPS80031_INT_CC_AUTOCAL,
538 NULL, tps80031_fg_calibrated, IRQF_ONESHOT,
539 "tps80031_fuel_gauge_calibration", di);
540 if (ret < 0) {
541 dev_err(dev->parent, "request IRQ %d fail\n", pdata->irq_base);
542 goto irq_fail2;
543 }
544 setup_timer(&di->battery_poll_timer,
545 battery_poll_timer_func, (unsigned long) di);
546 mod_timer(&di->battery_poll_timer,
547 jiffies + msecs_to_jiffies(BATTERY_POLL_PERIOD));
548
549 ret = tps80031_fg_start_gas_gauge(di);
550 if (ret < 0) {
551 dev_err(dev->parent, "failed to start fuel-gauge\n");
552 goto irq_fail1;
553 }
554 dev_info(dev->parent, "support ver. %s enabled\n", DRIVER_VERSION);
555
556 return ret;
557
558irq_fail1:
559 free_irq(pdata->irq_base + TPS80031_INT_CC_AUTOCAL, di);
560irq_fail2:
561 free_irq(pdata->irq_base + TPS80031_INT_SYS_VLOW, di);
562power_supply_fail0:
563 power_supply_unregister(&di->ac);
564power_supply_fail1:
565 power_supply_unregister(&di->usb);
566power_supply_fail2:
567 power_supply_unregister(&di->bat);
568 return ret;
569}
570
571static int tps80031_battery_remove(struct platform_device *pdev)
572{
573 struct tps80031_device_info *di = dev_get_drvdata(&pdev->dev);
574
575 power_supply_unregister(&di->bat);
576 power_supply_unregister(&di->usb);
577 power_supply_unregister(&di->ac);
578
579 return 0;
580}
581
582static struct platform_driver tps80031_battery_driver = {
583 .driver = {
584 .name = "tps80031-battery-gauge",
585 .owner = THIS_MODULE,
586 },
587 .probe = tps80031_battery_probe,
588 .remove = tps80031_battery_remove,
589};
590
591static int __init tps80031_battery_init(void)
592{
593 return platform_driver_register(&tps80031_battery_driver);
594}
595
596static void __exit tps80031_battery_exit(void)
597{
598 platform_driver_unregister(&tps80031_battery_driver);
599}
600
601module_init(tps80031_battery_init);
602module_exit(tps80031_battery_exit);
603
604MODULE_LICENSE("GPL");
605MODULE_AUTHOR("Syed Rafiuddin <srafiuddin@nvidia.com> ");
606MODULE_DESCRIPTION("tps80031 battery gauge driver");