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