summaryrefslogtreecommitdiffstats
path: root/drivers/power/sbs-battery.c
diff options
context:
space:
mode:
authorRhyland Klein <rklein@nvidia.com>2011-12-05 20:50:45 -0500
committerAnton Vorontsov <cbouatmailru@gmail.com>2012-01-05 20:22:12 -0500
commitc78f2b64963654419a8cd3b7e264251860e9f9eb (patch)
tree7705995811d4527753874d03264a0ba1301b8157 /drivers/power/sbs-battery.c
parentdaf22c3c4444e10a852a2f460f5cb1a43038bd53 (diff)
bq20z75: Rename to sbs-battery
This driver for the bq20z75 implemented the register spec defined by the SBS standard. As this is not unique to this the TI part this was originally written for, we can generalize this driver to show its support for any SBS compliant battery. Signed-off-by: Rhyland Klein <rklein@nvidia.com> Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
Diffstat (limited to 'drivers/power/sbs-battery.c')
-rw-r--r--drivers/power/sbs-battery.c871
1 files changed, 871 insertions, 0 deletions
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
new file mode 100644
index 000000000000..ce95ff791016
--- /dev/null
+++ b/drivers/power/sbs-battery.c
@@ -0,0 +1,871 @@
1/*
2 * Gas Gauge driver for TI's BQ20Z75
3 *
4 * Copyright (c) 2010, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/err.h>
25#include <linux/power_supply.h>
26#include <linux/i2c.h>
27#include <linux/slab.h>
28#include <linux/interrupt.h>
29#include <linux/gpio.h>
30
31#include <linux/power/bq20z75.h>
32
33enum {
34 REG_MANUFACTURER_DATA,
35 REG_TEMPERATURE,
36 REG_VOLTAGE,
37 REG_CURRENT,
38 REG_CAPACITY,
39 REG_TIME_TO_EMPTY,
40 REG_TIME_TO_FULL,
41 REG_STATUS,
42 REG_CYCLE_COUNT,
43 REG_SERIAL_NUMBER,
44 REG_REMAINING_CAPACITY,
45 REG_REMAINING_CAPACITY_CHARGE,
46 REG_FULL_CHARGE_CAPACITY,
47 REG_FULL_CHARGE_CAPACITY_CHARGE,
48 REG_DESIGN_CAPACITY,
49 REG_DESIGN_CAPACITY_CHARGE,
50 REG_DESIGN_VOLTAGE,
51};
52
53/* Battery Mode defines */
54#define BATTERY_MODE_OFFSET 0x03
55#define BATTERY_MODE_MASK 0x8000
56enum bq20z75_battery_mode {
57 BATTERY_MODE_AMPS,
58 BATTERY_MODE_WATTS
59};
60
61/* manufacturer access defines */
62#define MANUFACTURER_ACCESS_STATUS 0x0006
63#define MANUFACTURER_ACCESS_SLEEP 0x0011
64
65/* battery status value bits */
66#define BATTERY_DISCHARGING 0x40
67#define BATTERY_FULL_CHARGED 0x20
68#define BATTERY_FULL_DISCHARGED 0x10
69
70#define BQ20Z75_DATA(_psp, _addr, _min_value, _max_value) { \
71 .psp = _psp, \
72 .addr = _addr, \
73 .min_value = _min_value, \
74 .max_value = _max_value, \
75}
76
77static const struct bq20z75_device_data {
78 enum power_supply_property psp;
79 u8 addr;
80 int min_value;
81 int max_value;
82} bq20z75_data[] = {
83 [REG_MANUFACTURER_DATA] =
84 BQ20Z75_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
85 [REG_TEMPERATURE] =
86 BQ20Z75_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
87 [REG_VOLTAGE] =
88 BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
89 [REG_CURRENT] =
90 BQ20Z75_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768,
91 32767),
92 [REG_CAPACITY] =
93 BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
94 [REG_REMAINING_CAPACITY] =
95 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
96 [REG_REMAINING_CAPACITY_CHARGE] =
97 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
98 [REG_FULL_CHARGE_CAPACITY] =
99 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
100 [REG_FULL_CHARGE_CAPACITY_CHARGE] =
101 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535),
102 [REG_TIME_TO_EMPTY] =
103 BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0,
104 65535),
105 [REG_TIME_TO_FULL] =
106 BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0,
107 65535),
108 [REG_STATUS] =
109 BQ20Z75_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535),
110 [REG_CYCLE_COUNT] =
111 BQ20Z75_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535),
112 [REG_DESIGN_CAPACITY] =
113 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0,
114 65535),
115 [REG_DESIGN_CAPACITY_CHARGE] =
116 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0,
117 65535),
118 [REG_DESIGN_VOLTAGE] =
119 BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0,
120 65535),
121 [REG_SERIAL_NUMBER] =
122 BQ20Z75_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535),
123};
124
125static enum power_supply_property bq20z75_properties[] = {
126 POWER_SUPPLY_PROP_STATUS,
127 POWER_SUPPLY_PROP_HEALTH,
128 POWER_SUPPLY_PROP_PRESENT,
129 POWER_SUPPLY_PROP_TECHNOLOGY,
130 POWER_SUPPLY_PROP_CYCLE_COUNT,
131 POWER_SUPPLY_PROP_VOLTAGE_NOW,
132 POWER_SUPPLY_PROP_CURRENT_NOW,
133 POWER_SUPPLY_PROP_CAPACITY,
134 POWER_SUPPLY_PROP_TEMP,
135 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
136 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
137 POWER_SUPPLY_PROP_SERIAL_NUMBER,
138 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
139 POWER_SUPPLY_PROP_ENERGY_NOW,
140 POWER_SUPPLY_PROP_ENERGY_FULL,
141 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
142 POWER_SUPPLY_PROP_CHARGE_NOW,
143 POWER_SUPPLY_PROP_CHARGE_FULL,
144 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
145};
146
147struct bq20z75_info {
148 struct i2c_client *client;
149 struct power_supply power_supply;
150 struct bq20z75_platform_data *pdata;
151 bool is_present;
152 bool gpio_detect;
153 bool enable_detection;
154 int irq;
155 int last_state;
156 int poll_time;
157 struct delayed_work work;
158 int ignore_changes;
159};
160
161static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
162{
163 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
164 s32 ret = 0;
165 int retries = 1;
166
167 if (bq20z75_device->pdata)
168 retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1);
169
170 while (retries > 0) {
171 ret = i2c_smbus_read_word_data(client, address);
172 if (ret >= 0)
173 break;
174 retries--;
175 }
176
177 if (ret < 0) {
178 dev_dbg(&client->dev,
179 "%s: i2c read at address 0x%x failed\n",
180 __func__, address);
181 return ret;
182 }
183
184 return le16_to_cpu(ret);
185}
186
187static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
188 u16 value)
189{
190 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
191 s32 ret = 0;
192 int retries = 1;
193
194 if (bq20z75_device->pdata)
195 retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1);
196
197 while (retries > 0) {
198 ret = i2c_smbus_write_word_data(client, address,
199 le16_to_cpu(value));
200 if (ret >= 0)
201 break;
202 retries--;
203 }
204
205 if (ret < 0) {
206 dev_dbg(&client->dev,
207 "%s: i2c write to address 0x%x failed\n",
208 __func__, address);
209 return ret;
210 }
211
212 return 0;
213}
214
215static int bq20z75_get_battery_presence_and_health(
216 struct i2c_client *client, enum power_supply_property psp,
217 union power_supply_propval *val)
218{
219 s32 ret;
220 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
221
222 if (psp == POWER_SUPPLY_PROP_PRESENT &&
223 bq20z75_device->gpio_detect) {
224 ret = gpio_get_value(
225 bq20z75_device->pdata->battery_detect);
226 if (ret == bq20z75_device->pdata->battery_detect_present)
227 val->intval = 1;
228 else
229 val->intval = 0;
230 bq20z75_device->is_present = val->intval;
231 return ret;
232 }
233
234 /* Write to ManufacturerAccess with
235 * ManufacturerAccess command and then
236 * read the status */
237 ret = bq20z75_write_word_data(client,
238 bq20z75_data[REG_MANUFACTURER_DATA].addr,
239 MANUFACTURER_ACCESS_STATUS);
240 if (ret < 0) {
241 if (psp == POWER_SUPPLY_PROP_PRESENT)
242 val->intval = 0; /* battery removed */
243 return ret;
244 }
245
246 ret = bq20z75_read_word_data(client,
247 bq20z75_data[REG_MANUFACTURER_DATA].addr);
248 if (ret < 0)
249 return ret;
250
251 if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value ||
252 ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) {
253 val->intval = 0;
254 return 0;
255 }
256
257 /* Mask the upper nibble of 2nd byte and
258 * lower byte of response then
259 * shift the result by 8 to get status*/
260 ret &= 0x0F00;
261 ret >>= 8;
262 if (psp == POWER_SUPPLY_PROP_PRESENT) {
263 if (ret == 0x0F)
264 /* battery removed */
265 val->intval = 0;
266 else
267 val->intval = 1;
268 } else if (psp == POWER_SUPPLY_PROP_HEALTH) {
269 if (ret == 0x09)
270 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
271 else if (ret == 0x0B)
272 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
273 else if (ret == 0x0C)
274 val->intval = POWER_SUPPLY_HEALTH_DEAD;
275 else
276 val->intval = POWER_SUPPLY_HEALTH_GOOD;
277 }
278
279 return 0;
280}
281
282static int bq20z75_get_battery_property(struct i2c_client *client,
283 int reg_offset, enum power_supply_property psp,
284 union power_supply_propval *val)
285{
286 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
287 s32 ret;
288
289 ret = bq20z75_read_word_data(client,
290 bq20z75_data[reg_offset].addr);
291 if (ret < 0)
292 return ret;
293
294 /* returned values are 16 bit */
295 if (bq20z75_data[reg_offset].min_value < 0)
296 ret = (s16)ret;
297
298 if (ret >= bq20z75_data[reg_offset].min_value &&
299 ret <= bq20z75_data[reg_offset].max_value) {
300 val->intval = ret;
301 if (psp != POWER_SUPPLY_PROP_STATUS)
302 return 0;
303
304 if (ret & BATTERY_FULL_CHARGED)
305 val->intval = POWER_SUPPLY_STATUS_FULL;
306 else if (ret & BATTERY_FULL_DISCHARGED)
307 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
308 else if (ret & BATTERY_DISCHARGING)
309 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
310 else
311 val->intval = POWER_SUPPLY_STATUS_CHARGING;
312
313 if (bq20z75_device->poll_time == 0)
314 bq20z75_device->last_state = val->intval;
315 else if (bq20z75_device->last_state != val->intval) {
316 cancel_delayed_work_sync(&bq20z75_device->work);
317 power_supply_changed(&bq20z75_device->power_supply);
318 bq20z75_device->poll_time = 0;
319 }
320 } else {
321 if (psp == POWER_SUPPLY_PROP_STATUS)
322 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
323 else
324 val->intval = 0;
325 }
326
327 return 0;
328}
329
330static void bq20z75_unit_adjustment(struct i2c_client *client,
331 enum power_supply_property psp, union power_supply_propval *val)
332{
333#define BASE_UNIT_CONVERSION 1000
334#define BATTERY_MODE_CAP_MULT_WATT (10 * BASE_UNIT_CONVERSION)
335#define TIME_UNIT_CONVERSION 60
336#define TEMP_KELVIN_TO_CELSIUS 2731
337 switch (psp) {
338 case POWER_SUPPLY_PROP_ENERGY_NOW:
339 case POWER_SUPPLY_PROP_ENERGY_FULL:
340 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
341 /* bq20z75 provides energy in units of 10mWh.
342 * Convert to µWh
343 */
344 val->intval *= BATTERY_MODE_CAP_MULT_WATT;
345 break;
346
347 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
348 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
349 case POWER_SUPPLY_PROP_CURRENT_NOW:
350 case POWER_SUPPLY_PROP_CHARGE_NOW:
351 case POWER_SUPPLY_PROP_CHARGE_FULL:
352 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
353 val->intval *= BASE_UNIT_CONVERSION;
354 break;
355
356 case POWER_SUPPLY_PROP_TEMP:
357 /* bq20z75 provides battery temperature in 0.1K
358 * so convert it to 0.1°C
359 */
360 val->intval -= TEMP_KELVIN_TO_CELSIUS;
361 break;
362
363 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
364 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
365 /* bq20z75 provides time to empty and time to full in minutes.
366 * Convert to seconds
367 */
368 val->intval *= TIME_UNIT_CONVERSION;
369 break;
370
371 default:
372 dev_dbg(&client->dev,
373 "%s: no need for unit conversion %d\n", __func__, psp);
374 }
375}
376
377static enum bq20z75_battery_mode
378bq20z75_set_battery_mode(struct i2c_client *client,
379 enum bq20z75_battery_mode mode)
380{
381 int ret, original_val;
382
383 original_val = bq20z75_read_word_data(client, BATTERY_MODE_OFFSET);
384 if (original_val < 0)
385 return original_val;
386
387 if ((original_val & BATTERY_MODE_MASK) == mode)
388 return mode;
389
390 if (mode == BATTERY_MODE_AMPS)
391 ret = original_val & ~BATTERY_MODE_MASK;
392 else
393 ret = original_val | BATTERY_MODE_MASK;
394
395 ret = bq20z75_write_word_data(client, BATTERY_MODE_OFFSET, ret);
396 if (ret < 0)
397 return ret;
398
399 return original_val & BATTERY_MODE_MASK;
400}
401
402static int bq20z75_get_battery_capacity(struct i2c_client *client,
403 int reg_offset, enum power_supply_property psp,
404 union power_supply_propval *val)
405{
406 s32 ret;
407 enum bq20z75_battery_mode mode = BATTERY_MODE_WATTS;
408
409 if (power_supply_is_amp_property(psp))
410 mode = BATTERY_MODE_AMPS;
411
412 mode = bq20z75_set_battery_mode(client, mode);
413 if (mode < 0)
414 return mode;
415
416 ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr);
417 if (ret < 0)
418 return ret;
419
420 if (psp == POWER_SUPPLY_PROP_CAPACITY) {
421 /* bq20z75 spec says that this can be >100 %
422 * even if max value is 100 % */
423 val->intval = min(ret, 100);
424 } else
425 val->intval = ret;
426
427 ret = bq20z75_set_battery_mode(client, mode);
428 if (ret < 0)
429 return ret;
430
431 return 0;
432}
433
434static char bq20z75_serial[5];
435static int bq20z75_get_battery_serial_number(struct i2c_client *client,
436 union power_supply_propval *val)
437{
438 int ret;
439
440 ret = bq20z75_read_word_data(client,
441 bq20z75_data[REG_SERIAL_NUMBER].addr);
442 if (ret < 0)
443 return ret;
444
445 ret = sprintf(bq20z75_serial, "%04x", ret);
446 val->strval = bq20z75_serial;
447
448 return 0;
449}
450
451static int bq20z75_get_property_index(struct i2c_client *client,
452 enum power_supply_property psp)
453{
454 int count;
455 for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++)
456 if (psp == bq20z75_data[count].psp)
457 return count;
458
459 dev_warn(&client->dev,
460 "%s: Invalid Property - %d\n", __func__, psp);
461
462 return -EINVAL;
463}
464
465static int bq20z75_get_property(struct power_supply *psy,
466 enum power_supply_property psp,
467 union power_supply_propval *val)
468{
469 int ret = 0;
470 struct bq20z75_info *bq20z75_device = container_of(psy,
471 struct bq20z75_info, power_supply);
472 struct i2c_client *client = bq20z75_device->client;
473
474 switch (psp) {
475 case POWER_SUPPLY_PROP_PRESENT:
476 case POWER_SUPPLY_PROP_HEALTH:
477 ret = bq20z75_get_battery_presence_and_health(client, psp, val);
478 if (psp == POWER_SUPPLY_PROP_PRESENT)
479 return 0;
480 break;
481
482 case POWER_SUPPLY_PROP_TECHNOLOGY:
483 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
484 break;
485
486 case POWER_SUPPLY_PROP_ENERGY_NOW:
487 case POWER_SUPPLY_PROP_ENERGY_FULL:
488 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
489 case POWER_SUPPLY_PROP_CHARGE_NOW:
490 case POWER_SUPPLY_PROP_CHARGE_FULL:
491 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
492 case POWER_SUPPLY_PROP_CAPACITY:
493 ret = bq20z75_get_property_index(client, psp);
494 if (ret < 0)
495 break;
496
497 ret = bq20z75_get_battery_capacity(client, ret, psp, val);
498 break;
499
500 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
501 ret = bq20z75_get_battery_serial_number(client, val);
502 break;
503
504 case POWER_SUPPLY_PROP_STATUS:
505 case POWER_SUPPLY_PROP_CYCLE_COUNT:
506 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
507 case POWER_SUPPLY_PROP_CURRENT_NOW:
508 case POWER_SUPPLY_PROP_TEMP:
509 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
510 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
511 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
512 ret = bq20z75_get_property_index(client, psp);
513 if (ret < 0)
514 break;
515
516 ret = bq20z75_get_battery_property(client, ret, psp, val);
517 break;
518
519 default:
520 dev_err(&client->dev,
521 "%s: INVALID property\n", __func__);
522 return -EINVAL;
523 }
524
525 if (!bq20z75_device->enable_detection)
526 goto done;
527
528 if (!bq20z75_device->gpio_detect &&
529 bq20z75_device->is_present != (ret >= 0)) {
530 bq20z75_device->is_present = (ret >= 0);
531 power_supply_changed(&bq20z75_device->power_supply);
532 }
533
534done:
535 if (!ret) {
536 /* Convert units to match requirements for power supply class */
537 bq20z75_unit_adjustment(client, psp, val);
538 }
539
540 dev_dbg(&client->dev,
541 "%s: property = %d, value = %x\n", __func__, psp, val->intval);
542
543 if (ret && bq20z75_device->is_present)
544 return ret;
545
546 /* battery not present, so return NODATA for properties */
547 if (ret)
548 return -ENODATA;
549
550 return 0;
551}
552
553static irqreturn_t bq20z75_irq(int irq, void *devid)
554{
555 struct power_supply *battery = devid;
556
557 power_supply_changed(battery);
558
559 return IRQ_HANDLED;
560}
561
562static void bq20z75_external_power_changed(struct power_supply *psy)
563{
564 struct bq20z75_info *bq20z75_device;
565
566 bq20z75_device = container_of(psy, struct bq20z75_info, power_supply);
567
568 if (bq20z75_device->ignore_changes > 0) {
569 bq20z75_device->ignore_changes--;
570 return;
571 }
572
573 /* cancel outstanding work */
574 cancel_delayed_work_sync(&bq20z75_device->work);
575
576 schedule_delayed_work(&bq20z75_device->work, HZ);
577 bq20z75_device->poll_time = bq20z75_device->pdata->poll_retry_count;
578}
579
580static void bq20z75_delayed_work(struct work_struct *work)
581{
582 struct bq20z75_info *bq20z75_device;
583 s32 ret;
584
585 bq20z75_device = container_of(work, struct bq20z75_info, work.work);
586
587 ret = bq20z75_read_word_data(bq20z75_device->client,
588 bq20z75_data[REG_STATUS].addr);
589 /* if the read failed, give up on this work */
590 if (ret < 0) {
591 bq20z75_device->poll_time = 0;
592 return;
593 }
594
595 if (ret & BATTERY_FULL_CHARGED)
596 ret = POWER_SUPPLY_STATUS_FULL;
597 else if (ret & BATTERY_FULL_DISCHARGED)
598 ret = POWER_SUPPLY_STATUS_NOT_CHARGING;
599 else if (ret & BATTERY_DISCHARGING)
600 ret = POWER_SUPPLY_STATUS_DISCHARGING;
601 else
602 ret = POWER_SUPPLY_STATUS_CHARGING;
603
604 if (bq20z75_device->last_state != ret) {
605 bq20z75_device->poll_time = 0;
606 power_supply_changed(&bq20z75_device->power_supply);
607 return;
608 }
609 if (bq20z75_device->poll_time > 0) {
610 schedule_delayed_work(&bq20z75_device->work, HZ);
611 bq20z75_device->poll_time--;
612 return;
613 }
614}
615
616#if defined(CONFIG_OF)
617
618#include <linux/of_device.h>
619#include <linux/of_gpio.h>
620
621static const struct of_device_id bq20z75_dt_ids[] = {
622 { .compatible = "ti,bq20z75" },
623 { }
624};
625MODULE_DEVICE_TABLE(i2c, bq20z75_dt_ids);
626
627static struct bq20z75_platform_data *bq20z75_of_populate_pdata(
628 struct i2c_client *client)
629{
630 struct device_node *of_node = client->dev.of_node;
631 struct bq20z75_platform_data *pdata = client->dev.platform_data;
632 enum of_gpio_flags gpio_flags;
633 int rc;
634 u32 prop;
635
636 /* verify this driver matches this device */
637 if (!of_node)
638 return NULL;
639
640 /* if platform data is set, honor it */
641 if (pdata)
642 return pdata;
643
644 /* first make sure at least one property is set, otherwise
645 * it won't change behavior from running without pdata.
646 */
647 if (!of_get_property(of_node, "ti,i2c-retry-count", NULL) &&
648 !of_get_property(of_node, "ti,poll-retry-count", NULL) &&
649 !of_get_property(of_node, "ti,battery-detect-gpios", NULL))
650 goto of_out;
651
652 pdata = devm_kzalloc(&client->dev, sizeof(struct bq20z75_platform_data),
653 GFP_KERNEL);
654 if (!pdata)
655 goto of_out;
656
657 rc = of_property_read_u32(of_node, "ti,i2c-retry-count", &prop);
658 if (!rc)
659 pdata->i2c_retry_count = prop;
660
661 rc = of_property_read_u32(of_node, "ti,poll-retry-count", &prop);
662 if (!rc)
663 pdata->poll_retry_count = prop;
664
665 if (!of_get_property(of_node, "ti,battery-detect-gpios", NULL)) {
666 pdata->battery_detect = -1;
667 goto of_out;
668 }
669
670 pdata->battery_detect = of_get_named_gpio_flags(of_node,
671 "ti,battery-detect-gpios", 0, &gpio_flags);
672
673 if (gpio_flags & OF_GPIO_ACTIVE_LOW)
674 pdata->battery_detect_present = 0;
675 else
676 pdata->battery_detect_present = 1;
677
678of_out:
679 return pdata;
680}
681#else
682#define bq20z75_dt_ids NULL
683static struct bq20z75_platform_data *bq20z75_of_populate_pdata(
684 struct i2c_client *client)
685{
686 return client->dev.platform_data;
687}
688#endif
689
690static int __devinit bq20z75_probe(struct i2c_client *client,
691 const struct i2c_device_id *id)
692{
693 struct bq20z75_info *bq20z75_device;
694 struct bq20z75_platform_data *pdata = client->dev.platform_data;
695 int rc;
696 int irq;
697
698 bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL);
699 if (!bq20z75_device)
700 return -ENOMEM;
701
702 bq20z75_device->client = client;
703 bq20z75_device->enable_detection = false;
704 bq20z75_device->gpio_detect = false;
705 bq20z75_device->power_supply.name = "battery";
706 bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
707 bq20z75_device->power_supply.properties = bq20z75_properties;
708 bq20z75_device->power_supply.num_properties =
709 ARRAY_SIZE(bq20z75_properties);
710 bq20z75_device->power_supply.get_property = bq20z75_get_property;
711 /* ignore first notification of external change, it is generated
712 * from the power_supply_register call back
713 */
714 bq20z75_device->ignore_changes = 1;
715 bq20z75_device->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
716 bq20z75_device->power_supply.external_power_changed =
717 bq20z75_external_power_changed;
718
719 pdata = bq20z75_of_populate_pdata(client);
720
721 if (pdata) {
722 bq20z75_device->gpio_detect =
723 gpio_is_valid(pdata->battery_detect);
724 bq20z75_device->pdata = pdata;
725 }
726
727 i2c_set_clientdata(client, bq20z75_device);
728
729 if (!bq20z75_device->gpio_detect)
730 goto skip_gpio;
731
732 rc = gpio_request(pdata->battery_detect, dev_name(&client->dev));
733 if (rc) {
734 dev_warn(&client->dev, "Failed to request gpio: %d\n", rc);
735 bq20z75_device->gpio_detect = false;
736 goto skip_gpio;
737 }
738
739 rc = gpio_direction_input(pdata->battery_detect);
740 if (rc) {
741 dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc);
742 gpio_free(pdata->battery_detect);
743 bq20z75_device->gpio_detect = false;
744 goto skip_gpio;
745 }
746
747 irq = gpio_to_irq(pdata->battery_detect);
748 if (irq <= 0) {
749 dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
750 gpio_free(pdata->battery_detect);
751 bq20z75_device->gpio_detect = false;
752 goto skip_gpio;
753 }
754
755 rc = request_irq(irq, bq20z75_irq,
756 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
757 dev_name(&client->dev), &bq20z75_device->power_supply);
758 if (rc) {
759 dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
760 gpio_free(pdata->battery_detect);
761 bq20z75_device->gpio_detect = false;
762 goto skip_gpio;
763 }
764
765 bq20z75_device->irq = irq;
766
767skip_gpio:
768
769 rc = power_supply_register(&client->dev, &bq20z75_device->power_supply);
770 if (rc) {
771 dev_err(&client->dev,
772 "%s: Failed to register power supply\n", __func__);
773 goto exit_psupply;
774 }
775
776 dev_info(&client->dev,
777 "%s: battery gas gauge device registered\n", client->name);
778
779 INIT_DELAYED_WORK(&bq20z75_device->work, bq20z75_delayed_work);
780
781 bq20z75_device->enable_detection = true;
782
783 return 0;
784
785exit_psupply:
786 if (bq20z75_device->irq)
787 free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
788 if (bq20z75_device->gpio_detect)
789 gpio_free(pdata->battery_detect);
790
791 kfree(bq20z75_device);
792
793 return rc;
794}
795
796static int __devexit bq20z75_remove(struct i2c_client *client)
797{
798 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
799
800 if (bq20z75_device->irq)
801 free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
802 if (bq20z75_device->gpio_detect)
803 gpio_free(bq20z75_device->pdata->battery_detect);
804
805 power_supply_unregister(&bq20z75_device->power_supply);
806
807 cancel_delayed_work_sync(&bq20z75_device->work);
808
809 kfree(bq20z75_device);
810 bq20z75_device = NULL;
811
812 return 0;
813}
814
815#if defined CONFIG_PM
816static int bq20z75_suspend(struct i2c_client *client,
817 pm_message_t state)
818{
819 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
820 s32 ret;
821
822 if (bq20z75_device->poll_time > 0)
823 cancel_delayed_work_sync(&bq20z75_device->work);
824
825 /* write to manufacturer access with sleep command */
826 ret = bq20z75_write_word_data(client,
827 bq20z75_data[REG_MANUFACTURER_DATA].addr,
828 MANUFACTURER_ACCESS_SLEEP);
829 if (bq20z75_device->is_present && ret < 0)
830 return ret;
831
832 return 0;
833}
834#else
835#define bq20z75_suspend NULL
836#endif
837/* any smbus transaction will wake up bq20z75 */
838#define bq20z75_resume NULL
839
840static const struct i2c_device_id bq20z75_id[] = {
841 { "bq20z75", 0 },
842 {}
843};
844MODULE_DEVICE_TABLE(i2c, bq20z75_id);
845
846static struct i2c_driver bq20z75_battery_driver = {
847 .probe = bq20z75_probe,
848 .remove = __devexit_p(bq20z75_remove),
849 .suspend = bq20z75_suspend,
850 .resume = bq20z75_resume,
851 .id_table = bq20z75_id,
852 .driver = {
853 .name = "bq20z75-battery",
854 .of_match_table = bq20z75_dt_ids,
855 },
856};
857
858static int __init bq20z75_battery_init(void)
859{
860 return i2c_add_driver(&bq20z75_battery_driver);
861}
862module_init(bq20z75_battery_init);
863
864static void __exit bq20z75_battery_exit(void)
865{
866 i2c_del_driver(&bq20z75_battery_driver);
867}
868module_exit(bq20z75_battery_exit);
869
870MODULE_DESCRIPTION("BQ20z75 battery monitor driver");
871MODULE_LICENSE("GPL");