diff options
| author | Rhyland Klein <rklein@nvidia.com> | 2011-02-28 19:55:28 -0500 |
|---|---|---|
| committer | Anton Vorontsov <cbouatmailru@gmail.com> | 2011-03-01 14:24:01 -0500 |
| commit | bb879101606dd7235d8f4ecd0f707b63281d0838 (patch) | |
| tree | 74aae7149b888a1e54f23608314f795ee992d47f | |
| parent | b5db7cde69f87178fb771970a2b512a452a9d680 (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.c | 160 | ||||
| -rw-r--r-- | include/linux/power/bq20z75.h | 37 |
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 | ||
| 29 | enum { | 33 | enum { |
| 30 | REG_MANUFACTURER_DATA, | 34 | REG_MANUFACTURER_DATA, |
| @@ -141,8 +145,13 @@ static enum power_supply_property bq20z75_properties[] = { | |||
| 141 | }; | 145 | }; |
| 142 | 146 | ||
| 143 | struct bq20z75_info { | 147 | struct 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 | ||
| 148 | static int bq20z75_read_word_data(struct i2c_client *client, u8 address) | 157 | static 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 | |||
| 487 | done: | ||
| 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 | ||
| 474 | static int bq20z75_probe(struct i2c_client *client, | 499 | static 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 | |||
| 508 | static 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 | |||
