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>

authored by Rhyland Klein and committed by Anton Vorontsov a7d9ace4 a223246f

+21 -11
+21 -11
drivers/power/bq20z75.c
··· 171 171 } 172 172 173 173 if (ret < 0) { 174 - dev_warn(&client->dev, 174 + dev_dbg(&client->dev, 175 175 "%s: i2c read at address 0x%x failed\n", 176 176 __func__, address); 177 177 return ret; ··· 199 199 } 200 200 201 201 if (ret < 0) { 202 - dev_warn(&client->dev, 202 + dev_dbg(&client->dev, 203 203 "%s: i2c write to address 0x%x failed\n", 204 204 __func__, address); 205 205 return ret; ··· 223 223 val->intval = 1; 224 224 else 225 225 val->intval = 0; 226 + bq20z75_device->is_present = val->intval; 226 227 return ret; 227 228 } 228 229 ··· 233 232 ret = bq20z75_write_word_data(client, 234 233 bq20z75_data[REG_MANUFACTURER_DATA].addr, 235 234 MANUFACTURER_ACCESS_STATUS); 236 - if (ret < 0) 237 - return ret; 238 - 239 - 240 - ret = bq20z75_read_word_data(client, 241 - bq20z75_data[REG_MANUFACTURER_DATA].addr); 242 235 if (ret < 0) { 243 236 if (psp == POWER_SUPPLY_PROP_PRESENT) 244 237 val->intval = 0; /* battery removed */ 245 238 return ret; 246 239 } 240 + 241 + ret = bq20z75_read_word_data(client, 242 + bq20z75_data[REG_MANUFACTURER_DATA].addr); 243 + if (ret < 0) 244 + return ret; 247 245 248 246 if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value || 249 247 ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) { ··· 455 455 case POWER_SUPPLY_PROP_PRESENT: 456 456 case POWER_SUPPLY_PROP_HEALTH: 457 457 ret = bq20z75_get_battery_presence_and_health(client, psp, val); 458 + if (psp == POWER_SUPPLY_PROP_PRESENT) 459 + return 0; 458 460 break; 459 461 460 462 case POWER_SUPPLY_PROP_TECHNOLOGY: ··· 518 516 } 519 517 520 518 dev_dbg(&client->dev, 521 - "%s: property = %d, value = %d\n", __func__, psp, val->intval); 519 + "%s: property = %d, value = %x\n", __func__, psp, val->intval); 522 520 523 - return ret; 521 + if (ret && bq20z75_device->is_present) 522 + return ret; 523 + 524 + /* battery not present, so return NODATA for properties */ 525 + if (ret) 526 + return -ENODATA; 527 + 528 + return 0; 524 529 } 525 530 526 531 static irqreturn_t bq20z75_irq(int irq, void *devid) ··· 652 643 static int bq20z75_suspend(struct i2c_client *client, 653 644 pm_message_t state) 654 645 { 646 + struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); 655 647 s32 ret; 656 648 657 649 /* write to manufacturer access with sleep command */ 658 650 ret = bq20z75_write_word_data(client, 659 651 bq20z75_data[REG_MANUFACTURER_DATA].addr, 660 652 MANUFACTURER_ACCESS_SLEEP); 661 - if (ret < 0) 653 + if (bq20z75_device->is_present && ret < 0) 662 654 return ret; 663 655 664 656 return 0;