diff options
| -rw-r--r-- | drivers/power/qcom-charger/qpnp-smb2.c | 7 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/smb-lib.c | 114 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/smb-lib.h | 1 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/smb-reg.h | 3 |
4 files changed, 81 insertions, 44 deletions
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 e93d03788f11..a869fc592474 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -883,25 +883,28 @@ 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 +915,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 +952,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 +1271,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 +1685,58 @@ 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) +{ + union power_supply_propval pval = {0, }; + 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); + 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; 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) |
