aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/bq20z75.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/power/bq20z75.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/power/bq20z75.c')
-rw-r--r--drivers/power/bq20z75.c810
1 files changed, 810 insertions, 0 deletions
diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c
new file mode 100644
index 00000000000..32e5a8c5c3d
--- /dev/null
+++ b/drivers/power/bq20z75.c
@@ -0,0 +1,810 @@
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 plat_data;
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 retries = max(bq20z75_device->plat_data.i2c_retry_count + 1, 1);
168
169 while (retries > 0) {
170 ret = i2c_smbus_read_word_data(client, address);
171 if (ret >= 0)
172 break;
173 retries--;
174 }
175
176 if (ret < 0) {
177 dev_dbg(&client->dev,
178 "%s: i2c read at address 0x%x failed\n",
179 __func__, address);
180 return ret;
181 }
182
183 return le16_to_cpu(ret);
184}
185
186static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
187 u16 value)
188{
189 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
190 s32 ret = 0;
191 int retries = 1;
192
193 retries = max(bq20z75_device->plat_data.i2c_retry_count + 1, 1);
194
195 while (retries > 0) {
196 ret = i2c_smbus_write_word_data(client, address,
197 le16_to_cpu(value));
198 if (ret >= 0)
199 break;
200 retries--;
201 }
202
203 if (ret < 0) {
204 dev_dbg(&client->dev,
205 "%s: i2c write to address 0x%x failed\n",
206 __func__, address);
207 return ret;
208 }
209
210 return 0;
211}
212
213static int bq20z75_get_battery_presence_and_health(
214 struct i2c_client *client, enum power_supply_property psp,
215 union power_supply_propval *val)
216{
217 s32 ret;
218 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
219
220 if (psp == POWER_SUPPLY_PROP_PRESENT &&
221 bq20z75_device->gpio_detect) {
222 ret = gpio_get_value(
223 bq20z75_device->plat_data.battery_detect);
224 if (ret == bq20z75_device->plat_data.battery_detect_present)
225 val->intval = 1;
226 else
227 val->intval = 0;
228 bq20z75_device->is_present = val->intval;
229 return ret;
230 }
231
232 /* Write to ManufacturerAccess with
233 * ManufacturerAccess command and then
234 * read the status */
235 ret = bq20z75_write_word_data(client,
236 bq20z75_data[REG_MANUFACTURER_DATA].addr,
237 MANUFACTURER_ACCESS_STATUS);
238 if (ret < 0) {
239 if (psp == POWER_SUPPLY_PROP_PRESENT)
240 val->intval = 0; /* battery removed */
241 return ret;
242 }
243
244 ret = bq20z75_read_word_data(client,
245 bq20z75_data[REG_MANUFACTURER_DATA].addr);
246 if (ret < 0)
247 return ret;
248
249 if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value ||
250 ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) {
251 val->intval = 0;
252 return 0;
253 }
254
255 /* Mask the upper nibble of 2nd byte and
256 * lower byte of response then
257 * shift the result by 8 to get status*/
258 ret &= 0x0F00;
259 ret >>= 8;
260 if (psp == POWER_SUPPLY_PROP_PRESENT) {
261 if (ret == 0x0F)
262 /* battery removed */
263 val->intval = 0;
264 else
265 val->intval = 1;
266 } else if (psp == POWER_SUPPLY_PROP_HEALTH) {
267 if (ret == 0x09)
268 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
269 else if (ret == 0x0B)
270 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
271 else if (ret == 0x0C)
272 val->intval = POWER_SUPPLY_HEALTH_DEAD;
273 else
274 val->intval = POWER_SUPPLY_HEALTH_GOOD;
275 }
276
277 return 0;
278}
279
280static int bq20z75_get_battery_property(struct i2c_client *client,
281 int reg_offset, enum power_supply_property psp,
282 union power_supply_propval *val)
283{
284 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
285 s32 ret;
286
287 ret = bq20z75_read_word_data(client,
288 bq20z75_data[reg_offset].addr);
289 if (ret < 0)
290 return ret;
291
292 /* returned values are 16 bit */
293 if (bq20z75_data[reg_offset].min_value < 0)
294 ret = (s16)ret;
295
296 if (ret >= bq20z75_data[reg_offset].min_value &&
297 ret <= bq20z75_data[reg_offset].max_value) {
298 val->intval = ret;
299 if (psp != POWER_SUPPLY_PROP_STATUS)
300 return 0;
301
302 if (ret & BATTERY_FULL_CHARGED)
303 val->intval = POWER_SUPPLY_STATUS_FULL;
304 else if (ret & BATTERY_FULL_DISCHARGED)
305 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
306 else if (ret & BATTERY_DISCHARGING)
307 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
308 else
309 val->intval = POWER_SUPPLY_STATUS_CHARGING;
310
311 if (bq20z75_device->poll_time == 0)
312 bq20z75_device->last_state = val->intval;
313 else if (bq20z75_device->last_state != val->intval) {
314 cancel_delayed_work_sync(&bq20z75_device->work);
315 power_supply_changed(&bq20z75_device->power_supply);
316 bq20z75_device->poll_time = 0;
317 }
318 } else {
319 if (psp == POWER_SUPPLY_PROP_STATUS)
320 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
321 else
322 val->intval = 0;
323 }
324
325 return 0;
326}
327
328static void bq20z75_unit_adjustment(struct i2c_client *client,
329 enum power_supply_property psp, union power_supply_propval *val)
330{
331#define BASE_UNIT_CONVERSION 1000
332#define BATTERY_MODE_CAP_MULT_WATT (10 * BASE_UNIT_CONVERSION)
333#define TIME_UNIT_CONVERSION 60
334#define TEMP_KELVIN_TO_CELSIUS 2731
335 switch (psp) {
336 case POWER_SUPPLY_PROP_ENERGY_NOW:
337 case POWER_SUPPLY_PROP_ENERGY_FULL:
338 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
339 /* bq20z75 provides energy in units of 10mWh.
340 * Convert to µWh
341 */
342 val->intval *= BATTERY_MODE_CAP_MULT_WATT;
343 break;
344
345 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
346 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
347 case POWER_SUPPLY_PROP_CURRENT_NOW:
348 case POWER_SUPPLY_PROP_CHARGE_NOW:
349 case POWER_SUPPLY_PROP_CHARGE_FULL:
350 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
351 val->intval *= BASE_UNIT_CONVERSION;
352 break;
353
354 case POWER_SUPPLY_PROP_TEMP:
355 /* bq20z75 provides battery temperature in 0.1K
356 * so convert it to 0.1°C
357 */
358 val->intval -= TEMP_KELVIN_TO_CELSIUS;
359 break;
360
361 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
362 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
363 /* bq20z75 provides time to empty and time to full in minutes.
364 * Convert to seconds
365 */
366 val->intval *= TIME_UNIT_CONVERSION;
367 break;
368
369 default:
370 dev_dbg(&client->dev,
371 "%s: no need for unit conversion %d\n", __func__, psp);
372 }
373}
374
375static enum bq20z75_battery_mode
376bq20z75_set_battery_mode(struct i2c_client *client,
377 enum bq20z75_battery_mode mode)
378{
379 int ret, original_val;
380
381 original_val = bq20z75_read_word_data(client, BATTERY_MODE_OFFSET);
382 if (original_val < 0)
383 return original_val;
384
385 if ((original_val & BATTERY_MODE_MASK) == mode)
386 return mode;
387
388 if (mode == BATTERY_MODE_AMPS)
389 ret = original_val & ~BATTERY_MODE_MASK;
390 else
391 ret = original_val | BATTERY_MODE_MASK;
392
393 ret = bq20z75_write_word_data(client, BATTERY_MODE_OFFSET, ret);
394 if (ret < 0)
395 return ret;
396
397 return original_val & BATTERY_MODE_MASK;
398}
399
400static int bq20z75_get_battery_capacity(struct i2c_client *client,
401 int reg_offset, enum power_supply_property psp,
402 union power_supply_propval *val)
403{
404 s32 ret;
405 enum bq20z75_battery_mode mode = BATTERY_MODE_WATTS;
406
407 if (power_supply_is_amp_property(psp))
408 mode = BATTERY_MODE_AMPS;
409
410 mode = bq20z75_set_battery_mode(client, mode);
411 if (mode < 0)
412 return mode;
413
414 ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr);
415 if (ret < 0)
416 return ret;
417
418 if (psp == POWER_SUPPLY_PROP_CAPACITY) {
419 /* bq20z75 spec says that this can be >100 %
420 * even if max value is 100 % */
421 val->intval = min(ret, 100);
422 } else
423 val->intval = ret;
424
425 ret = bq20z75_set_battery_mode(client, mode);
426 if (ret < 0)
427 return ret;
428
429 return 0;
430}
431
432static char bq20z75_serial[5];
433static int bq20z75_get_battery_serial_number(struct i2c_client *client,
434 union power_supply_propval *val)
435{
436 int ret;
437
438 ret = bq20z75_read_word_data(client,
439 bq20z75_data[REG_SERIAL_NUMBER].addr);
440 if (ret < 0)
441 return ret;
442
443 ret = sprintf(bq20z75_serial, "%04x", ret);
444 val->strval = bq20z75_serial;
445
446 return 0;
447}
448
449static int bq20z75_get_property_index(struct i2c_client *client,
450 enum power_supply_property psp)
451{
452 int count;
453 for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++)
454 if (psp == bq20z75_data[count].psp)
455 return count;
456
457 dev_warn(&client->dev,
458 "%s: Invalid Property - %d\n", __func__, psp);
459
460 return -EINVAL;
461}
462
463static int bq20z75_get_property(struct power_supply *psy,
464 enum power_supply_property psp,
465 union power_supply_propval *val)
466{
467 int ret = 0;
468 struct bq20z75_info *bq20z75_device = container_of(psy,
469 struct bq20z75_info, power_supply);
470 struct i2c_client *client = bq20z75_device->client;
471
472 switch (psp) {
473 case POWER_SUPPLY_PROP_PRESENT:
474 case POWER_SUPPLY_PROP_HEALTH:
475 ret = bq20z75_get_battery_presence_and_health(client, psp, val);
476 if (psp == POWER_SUPPLY_PROP_PRESENT)
477 return 0;
478 break;
479
480 case POWER_SUPPLY_PROP_TECHNOLOGY:
481 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
482 break;
483
484 case POWER_SUPPLY_PROP_ENERGY_NOW:
485 case POWER_SUPPLY_PROP_ENERGY_FULL:
486 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
487 case POWER_SUPPLY_PROP_CHARGE_NOW:
488 case POWER_SUPPLY_PROP_CHARGE_FULL:
489 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
490 case POWER_SUPPLY_PROP_CAPACITY:
491 ret = bq20z75_get_property_index(client, psp);
492 if (ret < 0)
493 break;
494
495 ret = bq20z75_get_battery_capacity(client, ret, psp, val);
496 break;
497
498 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
499 ret = bq20z75_get_battery_serial_number(client, val);
500 break;
501
502 case POWER_SUPPLY_PROP_STATUS:
503 case POWER_SUPPLY_PROP_CYCLE_COUNT:
504 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
505 case POWER_SUPPLY_PROP_CURRENT_NOW:
506 case POWER_SUPPLY_PROP_TEMP:
507 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
508 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
509 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
510 ret = bq20z75_get_property_index(client, psp);
511 if (ret < 0)
512 break;
513
514 ret = bq20z75_get_battery_property(client, ret, psp, val);
515 break;
516
517 default:
518 dev_err(&client->dev,
519 "%s: INVALID property\n", __func__);
520 return -EINVAL;
521 }
522
523 if (!bq20z75_device->enable_detection)
524 goto done;
525
526 if (!bq20z75_device->gpio_detect &&
527 bq20z75_device->is_present != (ret >= 0)) {
528 bq20z75_device->is_present = (ret >= 0);
529 power_supply_changed(&bq20z75_device->power_supply);
530 }
531
532done:
533 if (!ret) {
534 /* Convert units to match requirements for power supply class */
535 bq20z75_unit_adjustment(client, psp, val);
536 }
537
538 dev_dbg(&client->dev,
539 "%s: property = %d, value = %x\n", __func__, psp, val->intval);
540
541 if (ret && bq20z75_device->is_present)
542 return ret;
543
544 /* battery not present, so return NODATA for properties */
545 if (ret)
546 return -ENODATA;
547
548 return 0;
549}
550
551static irqreturn_t bq20z75_irq(int irq, void *devid)
552{
553 struct power_supply *battery = devid;
554
555 power_supply_changed(battery);
556
557 return IRQ_HANDLED;
558}
559
560static void bq20z75_external_power_changed(struct power_supply *psy)
561{
562 struct bq20z75_info *bq20z75_device;
563
564 bq20z75_device = container_of(psy, struct bq20z75_info, power_supply);
565
566 if (bq20z75_device->ignore_changes > 0) {
567 bq20z75_device->ignore_changes--;
568 return;
569 }
570
571 /* cancel outstanding work */
572 cancel_delayed_work_sync(&bq20z75_device->work);
573
574 schedule_delayed_work(&bq20z75_device->work, HZ);
575 bq20z75_device->poll_time = bq20z75_device->plat_data.poll_retry_count;
576}
577
578static void bq20z75_delayed_work(struct work_struct *work)
579{
580 struct bq20z75_info *bq20z75_device;
581 s32 ret;
582
583 bq20z75_device = container_of(work, struct bq20z75_info, work.work);
584
585 ret = bq20z75_read_word_data(bq20z75_device->client,
586 bq20z75_data[REG_STATUS].addr);
587 /* if the read failed, give up on this work */
588 if (ret < 0) {
589 bq20z75_device->poll_time = 0;
590 return;
591 }
592
593 if (ret & BATTERY_FULL_CHARGED)
594 ret = POWER_SUPPLY_STATUS_FULL;
595 else if (ret & BATTERY_FULL_DISCHARGED)
596 ret = POWER_SUPPLY_STATUS_NOT_CHARGING;
597 else if (ret & BATTERY_DISCHARGING)
598 ret = POWER_SUPPLY_STATUS_DISCHARGING;
599 else
600 ret = POWER_SUPPLY_STATUS_CHARGING;
601
602 if (bq20z75_device->last_state != ret) {
603 bq20z75_device->poll_time = 0;
604 power_supply_changed(&bq20z75_device->power_supply);
605 return;
606 }
607 if (bq20z75_device->poll_time > 0) {
608 schedule_delayed_work(&bq20z75_device->work, HZ);
609 bq20z75_device->poll_time--;
610 return;
611 }
612}
613
614static int __devinit bq20z75_probe(struct i2c_client *client,
615 const struct i2c_device_id *id)
616{
617 struct bq20z75_info *bq20z75_device;
618 struct bq20z75_platform_data *pdata = client->dev.platform_data;
619 int rc;
620 int irq;
621
622 bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL);
623 if (!bq20z75_device)
624 return -ENOMEM;
625
626 bq20z75_device->client = client;
627 bq20z75_device->enable_detection = false;
628 bq20z75_device->gpio_detect = false;
629 bq20z75_device->power_supply.name = "battery";
630 bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
631 bq20z75_device->power_supply.properties = bq20z75_properties;
632 bq20z75_device->power_supply.num_properties =
633 ARRAY_SIZE(bq20z75_properties);
634 bq20z75_device->power_supply.get_property = bq20z75_get_property;
635 /* ignore first notification of external change, it is generated
636 * from the power_supply_register call back
637 */
638 bq20z75_device->ignore_changes = 1;
639 bq20z75_device->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
640 bq20z75_device->power_supply.external_power_changed =
641 bq20z75_external_power_changed;
642
643 if (pdata) {
644 bq20z75_device->gpio_detect =
645 gpio_is_valid(pdata->battery_detect);
646 memcpy(&bq20z75_device->plat_data, pdata, sizeof(struct bq20z75_platform_data));
647 }
648
649 i2c_set_clientdata(client, bq20z75_device);
650
651 /* Probing for the presence of the bq20z75 */
652 rc = bq20z75_read_word_data(client,
653 bq20z75_data[REG_SERIAL_NUMBER].addr);
654
655 if (rc < 0) {
656 dev_err(&client->dev,
657 "%s: bq20z75 is not responding\n", __func__);
658 rc = -ENODEV;
659 goto exit_mem_free;
660 }
661
662 if (!bq20z75_device->gpio_detect)
663 goto skip_gpio;
664
665 rc = gpio_request(pdata->battery_detect, dev_name(&client->dev));
666 if (rc) {
667 dev_warn(&client->dev, "Failed to request gpio: %d\n", rc);
668 bq20z75_device->gpio_detect = false;
669 goto skip_gpio;
670 }
671
672 rc = gpio_direction_input(pdata->battery_detect);
673 if (rc) {
674 dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc);
675 gpio_free(pdata->battery_detect);
676 bq20z75_device->gpio_detect = false;
677 goto skip_gpio;
678 }
679
680 irq = gpio_to_irq(pdata->battery_detect);
681 if (irq <= 0) {
682 dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
683 gpio_free(pdata->battery_detect);
684 bq20z75_device->gpio_detect = false;
685 goto skip_gpio;
686 }
687
688 rc = request_irq(irq, bq20z75_irq,
689 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
690 dev_name(&client->dev), &bq20z75_device->power_supply);
691 if (rc) {
692 dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
693 gpio_free(pdata->battery_detect);
694 bq20z75_device->gpio_detect = false;
695 goto skip_gpio;
696 }
697
698 bq20z75_device->irq = irq;
699
700skip_gpio:
701 rc = power_supply_register(&client->dev, &bq20z75_device->power_supply);
702 if (rc) {
703 dev_err(&client->dev,
704 "%s: Failed to register power supply\n", __func__);
705 goto exit_psupply;
706 }
707
708 dev_info(&client->dev,
709 "%s: battery gas gauge device registered\n", client->name);
710
711 INIT_DELAYED_WORK(&bq20z75_device->work, bq20z75_delayed_work);
712
713 bq20z75_device->enable_detection = true;
714
715 return 0;
716
717exit_psupply:
718 if (bq20z75_device->irq)
719 free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
720 if (bq20z75_device->gpio_detect)
721 gpio_free(pdata->battery_detect);
722
723exit_mem_free:
724 kfree(bq20z75_device);
725
726 return rc;
727}
728
729static int __devexit bq20z75_remove(struct i2c_client *client)
730{
731 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
732
733 if (bq20z75_device->irq)
734 free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
735 if (bq20z75_device->gpio_detect)
736 gpio_free(bq20z75_device->plat_data.battery_detect);
737
738 power_supply_unregister(&bq20z75_device->power_supply);
739
740 cancel_delayed_work_sync(&bq20z75_device->work);
741
742 kfree(bq20z75_device);
743 bq20z75_device = NULL;
744
745 return 0;
746}
747
748#if defined CONFIG_PM
749static int bq20z75_suspend(struct i2c_client *client,
750 pm_message_t state)
751{
752 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
753 s32 ret;
754
755 if (bq20z75_device->poll_time > 0)
756 cancel_delayed_work_sync(&bq20z75_device->work);
757
758 /* write to manufacturer access with sleep command */
759 ret = bq20z75_write_word_data(client,
760 bq20z75_data[REG_MANUFACTURER_DATA].addr,
761 MANUFACTURER_ACCESS_SLEEP);
762 if (bq20z75_device->is_present && ret < 0)
763 return ret;
764
765 return 0;
766}
767
768static int bq20z75_resume(struct i2c_client *client)
769{
770 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
771
772 schedule_delayed_work(&bq20z75_device->work, HZ);
773 return 0;
774}
775#else
776#define bq20z75_suspend NULL
777#define bq20z75_resume NULL
778#endif
779
780static const struct i2c_device_id bq20z75_id[] = {
781 { "bq20z75", 0 },
782 {}
783};
784MODULE_DEVICE_TABLE(i2c, bq20z75_id);
785
786static struct i2c_driver bq20z75_battery_driver = {
787 .probe = bq20z75_probe,
788 .remove = __devexit_p(bq20z75_remove),
789 .suspend = bq20z75_suspend,
790 .resume = bq20z75_resume,
791 .id_table = bq20z75_id,
792 .driver = {
793 .name = "bq20z75-battery",
794 },
795};
796
797static int __init bq20z75_battery_init(void)
798{
799 return i2c_add_driver(&bq20z75_battery_driver);
800}
801module_init(bq20z75_battery_init);
802
803static void __exit bq20z75_battery_exit(void)
804{
805 i2c_del_driver(&bq20z75_battery_driver);
806}
807module_exit(bq20z75_battery_exit);
808
809MODULE_DESCRIPTION("BQ20z75 battery monitor driver");
810MODULE_LICENSE("GPL");