power: qpnp-charger: wake up upon fast charge after resuming
When state of charge based charge resume happens there is
a delay between enabling charging again in hardware and
the fast charge state being reached. During this time
the system may have gone to suspend and the necessary
information is not conveyed to userspace.
Fix this by enabling the fast charge interrupt as a
wakeup interrupt when the SOC based resume event occurs.
Disable it when within the fast charge interrupt handler.
Change-Id: I286b1c12dbf057de974afb4084d92c157f08eee4
CRs-Fixed: 606012
Signed-off-by: David Keitel <dkeitel@codeaurora.org>
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 1223fe0..e6fb163 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -217,6 +217,7 @@
struct qpnp_chg_irq {
int irq;
unsigned long disabled;
+ unsigned long wake_enable;
};
struct qpnp_chg_regulator {
@@ -531,6 +532,24 @@
}
}
+static void
+qpnp_chg_irq_wake_enable(struct qpnp_chg_irq *irq)
+{
+ if (!__test_and_set_bit(0, &irq->wake_enable)) {
+ pr_debug("number = %d\n", irq->irq);
+ enable_irq_wake(irq->irq);
+ }
+}
+
+static void
+qpnp_chg_irq_wake_disable(struct qpnp_chg_irq *irq)
+{
+ if (__test_and_clear_bit(0, &irq->wake_enable)) {
+ pr_debug("number = %d\n", irq->irq);
+ disable_irq_wake(irq->irq);
+ }
+}
+
#define USB_OTG_EN_BIT BIT(0)
static int
qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
@@ -1678,6 +1697,8 @@
u8 chgr_sts;
int rc;
+ qpnp_chg_irq_wake_disable(&chip->chg_fastchg);
+
rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
if (rc)
pr_err("failed to read interrupt sts %d\n", rc);
@@ -2148,6 +2169,7 @@
&& soc <= chip->soc_resume_limit) {
pr_debug("resuming charging at %d%% soc\n", soc);
chip->resuming_charging = true;
+ qpnp_chg_irq_wake_enable(&chip->chg_fastchg);
qpnp_chg_set_appropriate_vbatdet(chip);
qpnp_chg_charge_en(chip, !chip->charging_disabled);
}
@@ -3848,10 +3870,10 @@
return rc;
}
- enable_irq_wake(chip->chg_trklchg.irq);
- enable_irq_wake(chip->chg_failed.irq);
+ qpnp_chg_irq_wake_enable(&chip->chg_trklchg);
+ qpnp_chg_irq_wake_enable(&chip->chg_failed);
qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
- enable_irq_wake(chip->chg_vbatdet_lo.irq);
+ qpnp_chg_irq_wake_enable(&chip->chg_vbatdet_lo);
break;
case SMBB_BAT_IF_SUBTYPE:
@@ -3874,7 +3896,7 @@
return rc;
}
- enable_irq_wake(chip->batt_pres.irq);
+ qpnp_chg_irq_wake_enable(&chip->batt_pres);
chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
spmi_resource, "bat-temp-ok");
@@ -3893,7 +3915,7 @@
}
qpnp_chg_bat_if_batt_temp_irq_handler(0, chip);
- enable_irq_wake(chip->batt_temp_ok.irq);
+ qpnp_chg_irq_wake_enable(&chip->batt_temp_ok);
break;
case SMBB_BUCK_SUBTYPE:
@@ -3975,11 +3997,11 @@
return rc;
}
- enable_irq_wake(chip->usb_ocp.irq);
+ qpnp_chg_irq_wake_enable(&chip->usb_ocp);
}
- enable_irq_wake(chip->usbin_valid.irq);
- enable_irq_wake(chip->chg_gone.irq);
+ qpnp_chg_irq_wake_enable(&chip->usbin_valid);
+ qpnp_chg_irq_wake_enable(&chip->chg_gone);
break;
case SMBB_DC_CHGPTH_SUBTYPE:
chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
@@ -3998,7 +4020,7 @@
return rc;
}
- enable_irq_wake(chip->dcin_valid.irq);
+ qpnp_chg_irq_wake_enable(&chip->dcin_valid);
break;
}
}