From 40af50ac19b45542698983089321ec4e28764496 Mon Sep 17 00:00:00 2001 From: Nicholas Troast Date: Fri, 23 Sep 2016 11:50:18 -0700 Subject: smb-lib: report not charging when battery is missing When the battery is missing from the device the battery power supply will still report that it is charging. Fix this by reporting the charge status as "not charging" when the battery is missing. Change-Id: I1150ccaa722109f3ea6a4a10e026709d3686e28b Signed-off-by: Nicholas Troast --- drivers/power/qcom-charger/smb-lib.c | 111 +++++++++++++++++++++-------------- drivers/power/qcom-charger/smb-reg.h | 3 +- 2 files changed, 70 insertions(+), 44 deletions(-) diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index e93d03788f11..9d2ed3f454bb 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -883,25 +883,29 @@ int smblib_get_prop_batt_capacity(struct smb_charger *chg, int smblib_get_prop_batt_status(struct smb_charger *chg, union power_supply_propval *val) { - int rc; - u8 stat; union power_supply_propval pval = {0, }; + bool usb_online, dc_online; + u8 stat; + int rc; - smblib_get_prop_input_suspend(chg, &pval); - if (pval.intval) { - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + + rc = smblib_get_prop_usb_online(chg, &pval); + if (rc < 0) { + dev_err(chg->dev, "Couldn't get usb online property rc=%d\n", + rc); return rc; } + usb_online = (bool)pval.intval; - rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat); + rc = smblib_get_prop_dc_online(chg, &pval); if (rc < 0) { - dev_err(chg->dev, "Couldn't read POWER_PATH_STATUS rc=%d\n", + dev_err(chg->dev, "Couldn't get dc online property rc=%d\n", rc); return rc; } + dc_online = (bool)pval.intval; - if (!(stat & (USE_USBIN_BIT | USE_DCIN_BIT)) || - !(stat & VALID_INPUT_POWER_SOURCE_BIT)) { + if (!usb_online && !dc_online) { val->intval = POWER_SUPPLY_STATUS_DISCHARGING; return rc; } @@ -912,16 +916,29 @@ int smblib_get_prop_batt_status(struct smb_charger *chg, rc); return rc; } - smblib_dbg(chg, PR_REGISTER, "BATTERY_CHARGER_STATUS_1 = 0x%02x\n", - stat); stat = stat & BATTERY_CHARGER_STATUS_MASK; - if (stat >= COMPLETED_CHARGE) - val->intval = POWER_SUPPLY_STATUS_FULL; - else + switch (stat) { + case TRICKLE_CHARGE: + case PRE_CHARGE: + case FAST_CHARGE: + case FULLON_CHARGE: + case TAPER_CHARGE: val->intval = POWER_SUPPLY_STATUS_CHARGING; + break; + case TERMINATE_CHARGE: + case INHIBIT_CHARGE: + val->intval = POWER_SUPPLY_STATUS_FULL; + break; + case DISABLE_CHARGE: + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + default: + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } - return rc; + return 0; } int smblib_get_prop_batt_charge_type(struct smb_charger *chg, @@ -936,8 +953,6 @@ int smblib_get_prop_batt_charge_type(struct smb_charger *chg, rc); return rc; } - smblib_dbg(chg, PR_REGISTER, "BATTERY_CHARGER_STATUS_1 = 0x%02x\n", - stat); switch (stat & BATTERY_CHARGER_STATUS_MASK) { case TRICKLE_CHARGE: @@ -1257,7 +1272,6 @@ int smblib_get_prop_usb_online(struct smb_charger *chg, val->intval = (stat & USE_USBIN_BIT) && (stat & VALID_INPUT_POWER_SOURCE_BIT); - return rc; } @@ -1672,43 +1686,54 @@ irqreturn_t smblib_handle_debug(int irq, void *data) return IRQ_HANDLED; } -irqreturn_t smblib_handle_chg_state_change(int irq, void *data) +static void smblib_pl_handle_chg_state_change(struct smb_charger *chg, u8 stat) { - struct smb_irq_data *irq_data = data; - struct smb_charger *chg = irq_data->parent_data; - union power_supply_propval pval = {0, }; - int rc; - - smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); + bool pl_enabled; if (chg->mode != PARALLEL_MASTER) - return IRQ_HANDLED; + return; - rc = smblib_get_prop_batt_charge_type(chg, &pval); - if (rc < 0) { - dev_err(chg->dev, "Couldn't get batt charge type rc=%d\n", rc); - return IRQ_HANDLED; + pl_enabled = !get_effective_result_locked(chg->pl_disable_votable); + switch (stat) { + case FAST_CHARGE: + case FULLON_CHARGE: + vote(chg->pl_disable_votable, CHG_STATE_VOTER, false, 0); + break; + case TAPER_CHARGE: + if (pl_enabled) { + cancel_delayed_work_sync(&chg->pl_taper_work); + schedule_delayed_work(&chg->pl_taper_work, 0); + } + break; + case TERMINATE_CHARGE: + case INHIBIT_CHARGE: + case DISABLE_CHARGE: + vote(chg->pl_disable_votable, TAPER_END_VOTER, false, 0); + break; + default: + break; } +} - if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) - vote(chg->pl_disable_votable, CHG_STATE_VOTER, false, 0); +irqreturn_t smblib_handle_chg_state_change(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + struct smb_charger *chg = irq_data->parent_data; + u8 stat; + int rc; - if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER - && !get_effective_result_locked(chg->pl_disable_votable)) { - cancel_delayed_work_sync(&chg->pl_taper_work); - schedule_delayed_work(&chg->pl_taper_work, 0); - } + smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); - rc = smblib_get_prop_batt_status(chg, &pval); + rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat); if (rc < 0) { - dev_err(chg->dev, "Couldn't get batt status type rc=%d\n", rc); + dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", + rc); return IRQ_HANDLED; } - if (pval.intval == POWER_SUPPLY_STATUS_FULL) { - power_supply_changed(chg->batt_psy); - vote(chg->pl_disable_votable, TAPER_END_VOTER, false, 0); - } + stat = stat & BATTERY_CHARGER_STATUS_MASK; + smblib_pl_handle_chg_state_change(chg, stat); + power_supply_changed(chg->batt_psy); return IRQ_HANDLED; } diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index c88d132fbf70..4a50d2fcbf97 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -41,8 +41,9 @@ enum { FAST_CHARGE, FULLON_CHARGE, TAPER_CHARGE, - COMPLETED_CHARGE, + TERMINATE_CHARGE, INHIBIT_CHARGE, + DISABLE_CHARGE, }; #define BATTERY_CHARGER_STATUS_2_REG (CHGR_BASE + 0x07) -- cgit v1.2.3 From 166e851cfda93ef05954816a04246b053955c472 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 4 Oct 2016 17:08:42 -0700 Subject: qpnp-smb2: smb-lib: add charge_done property Currently, charging status is shown as full for both the charge termination and inhibit cases. However, there is a need to know when the charge termination really happens. Add charge_done property to qpnp-smb2 driver so that the clients can read that property to distinguish termination and inhibit. Change-Id: If2bd750af412adf1eea7b913caed9a3eb3b763db Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/qcom-charger/qpnp-smb2.c | 7 +++++++ drivers/power/qcom-charger/smb-lib.c | 5 ++++- drivers/power/qcom-charger/smb-lib.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 522c89d3bb67..8fa4fe301676 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -605,6 +605,7 @@ static enum power_supply_property smb2_batt_props[] = { POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED, POWER_SUPPLY_PROP_STEP_CHARGING_STEP, + POWER_SUPPLY_PROP_CHARGE_DONE, }; static int smb2_batt_get_prop(struct power_supply *psy, @@ -662,6 +663,9 @@ static int smb2_batt_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; + case POWER_SUPPLY_PROP_CHARGE_DONE: + val->intval = chg->chg_done; + break; default: pr_err("batt power supply prop %d not supported\n", psp); return -EINVAL; @@ -692,6 +696,9 @@ static int smb2_batt_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CAPACITY: rc = smblib_set_prop_batt_capacity(chg, val); break; + case POWER_SUPPLY_PROP_CHARGE_DONE: + chg->chg_done = val->intval; + break; default: rc = -EINVAL; } diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 9d2ed3f454bb..a869fc592474 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -888,7 +888,6 @@ int smblib_get_prop_batt_status(struct smb_charger *chg, u8 stat; int rc; - rc = smblib_get_prop_usb_online(chg, &pval); if (rc < 0) { dev_err(chg->dev, "Couldn't get usb online property rc=%d\n", @@ -1717,6 +1716,7 @@ static void smblib_pl_handle_chg_state_change(struct smb_charger *chg, u8 stat) irqreturn_t smblib_handle_chg_state_change(int irq, void *data) { + union power_supply_propval pval = {0, }; struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; u8 stat; @@ -1733,6 +1733,9 @@ irqreturn_t smblib_handle_chg_state_change(int irq, void *data) stat = stat & BATTERY_CHARGER_STATUS_MASK; smblib_pl_handle_chg_state_change(chg, stat); + pval.intval = (stat == TERMINATE_CHARGE); + power_supply_set_property(chg->batt_psy, POWER_SUPPLY_PROP_CHARGE_DONE, + &pval); power_supply_changed(chg->batt_psy); return IRQ_HANDLED; } diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index f5d9dda8330a..1f2457e04ed6 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -163,6 +163,7 @@ struct smb_charger { bool step_chg_enabled; bool is_hdc; + bool chg_done; /* workaround flag */ u32 wa_flags; -- cgit v1.2.3