aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/bq20z75.c
diff options
context:
space:
mode:
authorRhyland Klein <rklein@nvidia.com>2011-03-09 19:18:02 -0500
committerAnton Vorontsov <cbouatmailru@gmail.com>2011-03-16 09:40:58 -0400
commita7d9ace4eb3a6a3c3fcb12fb05510c1893808263 (patch)
tree2464cd8e7285165562ed004cc1996fd6681827cd /drivers/power/bq20z75.c
parenta223246f7280422f77c15b71455fe3362d3604b4 (diff)
bq20z75: Fix issues with present and suspend
There are a few issues found around the battery not being present. If the battery isn't present, then a few undesirable things happen. The first was excessive reporting of failed properties. This was fixed by instead returning ENODATA for all properties other than PRESENT if the battery isn't present. That way the callers can identify the difference between a failure and the battery not being there. The next issue was in the suspend logic. It was found that if the battery wasn't present, then it would return a failure, preventing the system from going into suspend. If there is no battery present, the io is expected to fail, so in that case, we shouldn't return the failure and just acknowledge that it was expected. I also found that when a gpio was used, i didn't maintain the internal is_present state properly. I added a set of that to fix that. Lastly, the code to see io's fail and figure out that the battery isn't present when not using a gpio had a problem. In that code, it looked for the read to fail and if it did, then handled it. The problem is that in function to get the property, it first writes a value and that write can fail, causing the code to never reach the logic after the read. Fix is to move the logic till after the write. Signed-off-by: Rhyland Klein <rklein@nvidia.com> Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
Diffstat (limited to 'drivers/power/bq20z75.c')
-rw-r--r--drivers/power/bq20z75.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c
index 8018e8cc7a74..5615c92bef66 100644
--- a/drivers/power/bq20z75.c
+++ b/drivers/power/bq20z75.c
@@ -171,7 +171,7 @@ static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
171 } 171 }
172 172
173 if (ret < 0) { 173 if (ret < 0) {
174 dev_warn(&client->dev, 174 dev_dbg(&client->dev,
175 "%s: i2c read at address 0x%x failed\n", 175 "%s: i2c read at address 0x%x failed\n",
176 __func__, address); 176 __func__, address);
177 return ret; 177 return ret;
@@ -199,7 +199,7 @@ static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
199 } 199 }
200 200
201 if (ret < 0) { 201 if (ret < 0) {
202 dev_warn(&client->dev, 202 dev_dbg(&client->dev,
203 "%s: i2c write to address 0x%x failed\n", 203 "%s: i2c write to address 0x%x failed\n",
204 __func__, address); 204 __func__, address);
205 return ret; 205 return ret;
@@ -223,6 +223,7 @@ static int bq20z75_get_battery_presence_and_health(
223 val->intval = 1; 223 val->intval = 1;
224 else 224 else
225 val->intval = 0; 225 val->intval = 0;
226 bq20z75_device->is_present = val->intval;
226 return ret; 227 return ret;
227 } 228 }
228 229
@@ -232,18 +233,17 @@ static int bq20z75_get_battery_presence_and_health(
232 ret = bq20z75_write_word_data(client, 233 ret = bq20z75_write_word_data(client,
233 bq20z75_data[REG_MANUFACTURER_DATA].addr, 234 bq20z75_data[REG_MANUFACTURER_DATA].addr,
234 MANUFACTURER_ACCESS_STATUS); 235 MANUFACTURER_ACCESS_STATUS);
235 if (ret < 0)
236 return ret;
237
238
239 ret = bq20z75_read_word_data(client,
240 bq20z75_data[REG_MANUFACTURER_DATA].addr);
241 if (ret < 0) { 236 if (ret < 0) {
242 if (psp == POWER_SUPPLY_PROP_PRESENT) 237 if (psp == POWER_SUPPLY_PROP_PRESENT)
243 val->intval = 0; /* battery removed */ 238 val->intval = 0; /* battery removed */
244 return ret; 239 return ret;
245 } 240 }
246 241
242 ret = bq20z75_read_word_data(client,
243 bq20z75_data[REG_MANUFACTURER_DATA].addr);
244 if (ret < 0)
245 return ret;
246
247 if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value || 247 if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value ||
248 ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) { 248 ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) {
249 val->intval = 0; 249 val->intval = 0;
@@ -455,6 +455,8 @@ static int bq20z75_get_property(struct power_supply *psy,
455 case POWER_SUPPLY_PROP_PRESENT: 455 case POWER_SUPPLY_PROP_PRESENT:
456 case POWER_SUPPLY_PROP_HEALTH: 456 case POWER_SUPPLY_PROP_HEALTH:
457 ret = bq20z75_get_battery_presence_and_health(client, psp, val); 457 ret = bq20z75_get_battery_presence_and_health(client, psp, val);
458 if (psp == POWER_SUPPLY_PROP_PRESENT)
459 return 0;
458 break; 460 break;
459 461
460 case POWER_SUPPLY_PROP_TECHNOLOGY: 462 case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -516,9 +518,16 @@ done:
516 } 518 }
517 519
518 dev_dbg(&client->dev, 520 dev_dbg(&client->dev,
519 "%s: property = %d, value = %d\n", __func__, psp, val->intval); 521 "%s: property = %d, value = %x\n", __func__, psp, val->intval);
522
523 if (ret && bq20z75_device->is_present)
524 return ret;
525
526 /* battery not present, so return NODATA for properties */
527 if (ret)
528 return -ENODATA;
520 529
521 return ret; 530 return 0;
522} 531}
523 532
524static irqreturn_t bq20z75_irq(int irq, void *devid) 533static irqreturn_t bq20z75_irq(int irq, void *devid)
@@ -643,13 +652,14 @@ static int __devexit bq20z75_remove(struct i2c_client *client)
643static int bq20z75_suspend(struct i2c_client *client, 652static int bq20z75_suspend(struct i2c_client *client,
644 pm_message_t state) 653 pm_message_t state)
645{ 654{
655 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
646 s32 ret; 656 s32 ret;
647 657
648 /* write to manufacturer access with sleep command */ 658 /* write to manufacturer access with sleep command */
649 ret = bq20z75_write_word_data(client, 659 ret = bq20z75_write_word_data(client,
650 bq20z75_data[REG_MANUFACTURER_DATA].addr, 660 bq20z75_data[REG_MANUFACTURER_DATA].addr,
651 MANUFACTURER_ACCESS_SLEEP); 661 MANUFACTURER_ACCESS_SLEEP);
652 if (ret < 0) 662 if (bq20z75_device->is_present && ret < 0)
653 return ret; 663 return ret;
654 664
655 return 0; 665 return 0;