aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRhyland Klein <rklein@nvidia.com>2011-02-28 19:55:28 -0500
committerAnton Vorontsov <cbouatmailru@gmail.com>2011-03-01 14:24:01 -0500
commitbb879101606dd7235d8f4ecd0f707b63281d0838 (patch)
tree74aae7149b888a1e54f23608314f795ee992d47f
parentb5db7cde69f87178fb771970a2b512a452a9d680 (diff)
bq20z75: Add optional battery detect gpio
Adding support for an optional gpio for battery detection. This is passed in through the i2c platform data. It also accepts another field, battery_detect_present to signify the gpio state which means the battery is present, either 0 (low) or 1 (high). Signed-off-by: Rhyland Klein <rklein@nvidia.com> Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
-rw-r--r--drivers/power/bq20z75.c160
-rw-r--r--include/linux/power/bq20z75.h37
2 files changed, 166 insertions, 31 deletions
diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c
index 4141775e5ff6..a51e98d74d34 100644
--- a/drivers/power/bq20z75.c
+++ b/drivers/power/bq20z75.c
@@ -25,6 +25,10 @@
25#include <linux/power_supply.h> 25#include <linux/power_supply.h>
26#include <linux/i2c.h> 26#include <linux/i2c.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/interrupt.h>
29#include <linux/gpio.h>
30
31#include <linux/power/bq20z75.h>
28 32
29enum { 33enum {
30 REG_MANUFACTURER_DATA, 34 REG_MANUFACTURER_DATA,
@@ -141,8 +145,13 @@ static enum power_supply_property bq20z75_properties[] = {
141}; 145};
142 146
143struct bq20z75_info { 147struct bq20z75_info {
144 struct i2c_client *client; 148 struct i2c_client *client;
145 struct power_supply power_supply; 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;
146}; 155};
147 156
148static int bq20z75_read_word_data(struct i2c_client *client, u8 address) 157static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
@@ -179,6 +188,18 @@ static int bq20z75_get_battery_presence_and_health(
179 union power_supply_propval *val) 188 union power_supply_propval *val)
180{ 189{
181 s32 ret; 190 s32 ret;
191 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
192
193 if (psp == POWER_SUPPLY_PROP_PRESENT &&
194 bq20z75_device->gpio_detect) {
195 ret = gpio_get_value(
196 bq20z75_device->pdata->battery_detect);
197 if (ret == bq20z75_device->pdata->battery_detect_present)
198 val->intval = 1;
199 else
200 val->intval = 0;
201 return ret;
202 }
182 203
183 /* Write to ManufacturerAccess with 204 /* Write to ManufacturerAccess with
184 * ManufacturerAccess command and then 205 * ManufacturerAccess command and then
@@ -192,8 +213,11 @@ static int bq20z75_get_battery_presence_and_health(
192 213
193 ret = bq20z75_read_word_data(client, 214 ret = bq20z75_read_word_data(client,
194 bq20z75_data[REG_MANUFACTURER_DATA].addr); 215 bq20z75_data[REG_MANUFACTURER_DATA].addr);
195 if (ret < 0) 216 if (ret < 0) {
217 if (psp == POWER_SUPPLY_PROP_PRESENT)
218 val->intval = 0; /* battery removed */
196 return ret; 219 return ret;
220 }
197 221
198 if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value || 222 if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value ||
199 ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) { 223 ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) {
@@ -397,8 +421,7 @@ static int bq20z75_get_property(struct power_supply *psy,
397 enum power_supply_property psp, 421 enum power_supply_property psp,
398 union power_supply_propval *val) 422 union power_supply_propval *val)
399{ 423{
400 int ps_index; 424 int ret = 0;
401 int ret;
402 struct bq20z75_info *bq20z75_device = container_of(psy, 425 struct bq20z75_info *bq20z75_device = container_of(psy,
403 struct bq20z75_info, power_supply); 426 struct bq20z75_info, power_supply);
404 struct i2c_client *client = bq20z75_device->client; 427 struct i2c_client *client = bq20z75_device->client;
@@ -407,8 +430,6 @@ static int bq20z75_get_property(struct power_supply *psy,
407 case POWER_SUPPLY_PROP_PRESENT: 430 case POWER_SUPPLY_PROP_PRESENT:
408 case POWER_SUPPLY_PROP_HEALTH: 431 case POWER_SUPPLY_PROP_HEALTH:
409 ret = bq20z75_get_battery_presence_and_health(client, psp, val); 432 ret = bq20z75_get_battery_presence_and_health(client, psp, val);
410 if (ret)
411 return ret;
412 break; 433 break;
413 434
414 case POWER_SUPPLY_PROP_TECHNOLOGY: 435 case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -422,20 +443,15 @@ static int bq20z75_get_property(struct power_supply *psy,
422 case POWER_SUPPLY_PROP_CHARGE_FULL: 443 case POWER_SUPPLY_PROP_CHARGE_FULL:
423 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 444 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
424 case POWER_SUPPLY_PROP_CAPACITY: 445 case POWER_SUPPLY_PROP_CAPACITY:
425 ps_index = bq20z75_get_property_index(client, psp); 446 ret = bq20z75_get_property_index(client, psp);
426 if (ps_index < 0) 447 if (ret < 0)
427 return ps_index; 448 break;
428
429 ret = bq20z75_get_battery_capacity(client, ps_index, psp, val);
430 if (ret)
431 return ret;
432 449
450 ret = bq20z75_get_battery_capacity(client, ret, psp, val);
433 break; 451 break;
434 452
435 case POWER_SUPPLY_PROP_SERIAL_NUMBER: 453 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
436 ret = bq20z75_get_battery_serial_number(client, val); 454 ret = bq20z75_get_battery_serial_number(client, val);
437 if (ret)
438 return ret;
439 break; 455 break;
440 456
441 case POWER_SUPPLY_PROP_STATUS: 457 case POWER_SUPPLY_PROP_STATUS:
@@ -446,14 +462,11 @@ static int bq20z75_get_property(struct power_supply *psy,
446 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 462 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
447 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: 463 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
448 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 464 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
449 ps_index = bq20z75_get_property_index(client, psp); 465 ret = bq20z75_get_property_index(client, psp);
450 if (ps_index < 0) 466 if (ret < 0)
451 return ps_index; 467 break;
452
453 ret = bq20z75_get_battery_property(client, ps_index, psp, val);
454 if (ret)
455 return ret;
456 468
469 ret = bq20z75_get_battery_property(client, ret, psp, val);
457 break; 470 break;
458 471
459 default: 472 default:
@@ -462,26 +475,51 @@ static int bq20z75_get_property(struct power_supply *psy,
462 return -EINVAL; 475 return -EINVAL;
463 } 476 }
464 477
465 /* Convert units to match requirements for power supply class */ 478 if (!bq20z75_device->enable_detection)
466 bq20z75_unit_adjustment(client, psp, val); 479 goto done;
480
481 if (!bq20z75_device->gpio_detect &&
482 bq20z75_device->is_present != (ret >= 0)) {
483 bq20z75_device->is_present = (ret >= 0);
484 power_supply_changed(&bq20z75_device->power_supply);
485 }
486
487done:
488 if (!ret) {
489 /* Convert units to match requirements for power supply class */
490 bq20z75_unit_adjustment(client, psp, val);
491 }
467 492
468 dev_dbg(&client->dev, 493 dev_dbg(&client->dev,
469 "%s: property = %d, value = %d\n", __func__, psp, val->intval); 494 "%s: property = %d, value = %d\n", __func__, psp, val->intval);
470 495
471 return 0; 496 return ret;
472} 497}
473 498
474static int bq20z75_probe(struct i2c_client *client, 499static irqreturn_t bq20z75_irq(int irq, void *devid)
500{
501 struct power_supply *battery = devid;
502
503 power_supply_changed(battery);
504
505 return IRQ_HANDLED;
506}
507
508static int __devinit bq20z75_probe(struct i2c_client *client,
475 const struct i2c_device_id *id) 509 const struct i2c_device_id *id)
476{ 510{
477 struct bq20z75_info *bq20z75_device; 511 struct bq20z75_info *bq20z75_device;
512 struct bq20z75_platform_data *pdata = client->dev.platform_data;
478 int rc; 513 int rc;
514 int irq;
479 515
480