From d16d1f99f1ffe4f2653d72b72df8dd2f8141397c Mon Sep 17 00:00:00 2001 From: Yonghua Yan Date: Sat, 2 Jul 2022 02:54:04 +0800 Subject: [PATCH] Reset charging if it's halt When the battery charging is halt under chargable condition, reset the battery charging to recover it. Put the charger in HIZ mode if the battery is absent or OTG is enabled to prevent battery charging by boost power. Change-Id: I435bcb751d22ef2ac515aa15bb63e423dfdc4cb6 Signed-off-by: Yonghua Yan Reviewed-on: https://gerrit.mot.com/2320930 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key --- .../sgm4154x_charger_lite.c | 98 +++++++++++++------ .../sgm4154x_charger_lite.h | 6 ++ 2 files changed, 74 insertions(+), 30 deletions(-) diff --git a/drivers/power/sgm4154x_charger_lite/sgm4154x_charger_lite.c b/drivers/power/sgm4154x_charger_lite/sgm4154x_charger_lite.c index 45e0a44af930..6bfa5bcb67bd 100644 --- a/drivers/power/sgm4154x_charger_lite/sgm4154x_charger_lite.c +++ b/drivers/power/sgm4154x_charger_lite/sgm4154x_charger_lite.c @@ -220,6 +220,7 @@ static int sgm4154x_set_ichrg_curr(struct sgm4154x_device *sgm, int chrg_curr) else if ( chrg_curr > sgm->init_data.max_ichg) chrg_curr = sgm->init_data.max_ichg; + sgm->ichg = chrg_curr; pr_info("set ichg = %duA\n", chrg_curr); reg_val = chrg_curr / SGM4154x_ICHRG_CURRENT_STEP_uA; @@ -241,6 +242,7 @@ static int sgm4154x_set_chrg_volt(struct sgm4154x_device *sgm, int chrg_volt) else if (chrg_volt > sgm->init_data.max_vreg) chrg_volt = sgm->init_data.max_vreg; + sgm->vreg = chrg_volt; reg_val = (chrg_volt-SGM4154x_VREG_V_MIN_uV) / SGM4154x_VREG_V_STEP_uV; @@ -575,6 +577,8 @@ static int sgm4154x_set_input_curr_lim(struct sgm4154x_device *sgm, int iindpm) if (iindpm > sgm->init_data.ilim) iindpm = sgm->init_data.ilim; + sgm->ilim = iindpm; + if (iindpm < SGM4154x_IINDPM_I_MIN_uA) reg_val = 0; else if (iindpm >= SGM4154x_IINDPM_I_MAX_uA) @@ -692,6 +696,7 @@ static int sgm4154x_get_state(struct sgm4154x_device *sgm, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); if (!ret) state->ibus_limit = val.intval; + state->chrg_stat = chrg_stat & SGM4154x_CHG_STAT_MASK; } else if (sgm->use_ext_usb_psy) { state->chrg_type = 0; state->chrg_stat = 0; @@ -1328,7 +1333,10 @@ static void charger_detect_work_func(struct work_struct *work) } if (sgm->use_ext_usb_psy && sgm->usb) { - curr_in_limit = sgm->state.ibus_limit; + if (curr_in_limit < sgm->state.ibus_limit) + curr_in_limit = sgm->state.ibus_limit; + if (curr_in_limit > sgm->init_data.ilim) + curr_in_limit = sgm->init_data.ilim; if (prev_in_limit != curr_in_limit) { dev_info(sgm->dev, "Update: curr_in_limit = %d\n", curr_in_limit); @@ -2062,6 +2070,8 @@ static int sgm4154x_charger_get_chg_info(void *data, struct mmi_charger_info *ch struct sgm_mmi_charger *chg = data; struct sgm4154x_state state = chg->sgm->state; + sgm4154x_get_state(chg->sgm, &state); + chg->chg_info.chrg_mv = state.vbus_adc / 1000; chg->chg_info.chrg_ma = state.ibus_adc / 1000; chg->chg_info.chrg_type = get_charger_type(chg->sgm); @@ -2089,8 +2099,32 @@ static int sgm4154x_charger_config_charge(void *data, struct mmi_charger_cfg *co { int rc; u32 value; + bool chg_en; bool cfg_changed = false; struct sgm_mmi_charger *chg = data; + struct sgm4154x_state state = chg->sgm->state; + + if (!chg->sgm->batt_present || chg->sgm->otg_enabled) { + if (chg->sgm->client->irq && chg->sgm->irq_enabled) { + disable_irq_wake(chg->sgm->client->irq); + disable_irq(chg->sgm->client->irq); + chg->sgm->irq_enabled = false; + pr_warn("irq is disabled, bpd=%d, otg=%d\n", + chg->sgm->batt_present, chg->sgm->otg_enabled); + } + sgm4154x_set_hiz_en(chg->sgm, true); + goto check_st; + } else { + if (!chg->sgm->irq_enabled && chg->sgm->client->irq) { + sgm4154x_set_hiz_en(chg->sgm, false); + enable_irq_wake(chg->sgm->client->irq); + enable_irq(chg->sgm->client->irq); + chg->sgm->irq_enabled = true; + chg->chg_cfg.charger_suspend = false; + pr_warn("irq is enabled, bpd=%d, otg=%d\n", + chg->sgm->batt_present, chg->sgm->otg_enabled); + } + } /* configure the charger if changed */ if (config->target_fv != chg->chg_cfg.target_fv) { @@ -2178,6 +2212,25 @@ static int sgm4154x_charger_config_charge(void *data, struct mmi_charger_cfg *co msecs_to_jiffies(200)); } +check_st: + sgm4154x_get_state(chg->sgm, &state); + chg_en = sgm4154x_is_enabled_charging(chg->sgm); + if (chg->chg_info.chrg_present && !state.hiz_en && + chg_en && chg->sgm->ichg > 0 && + ((chg->batt_info.batt_mv + 50) * 1000) <= chg->sgm->vreg && + state.chrg_stat != SGM4154x_FAST_CHRG && + state.chrg_stat != SGM4154x_PRECHRG) { + sgm4154x_disable_charger(chg->sgm); + chg->chg_cfg.target_fv = -EINVAL; + chg->chg_cfg.target_fcc = -EINVAL; + chg->chg_cfg.charging_disable = true; + pr_info("Battery charging reconfigure triggered\n"); + } + + pr_info("chg_en:%d, ichg:%d, vchg:%d, ilim:%d, chg_st:0x%x, therm:%d, suspend:%d\n", + chg_en, chg->sgm->ichg, chg->sgm->vreg, chg->sgm->ilim, + state.chrg_stat, state.therm_stat, state.hiz_en); + return 0; } @@ -2272,6 +2325,7 @@ static void sgm4154x_charger_set_constraint(void *data, #define IBAT_OCP_MA (1500) #define PROTECT_DELAY_MS (60000) #define OTG_VBUS_MIN_MV (4600) +#define OTG_VBUS_MAX_MV (5600) static void sgm4154x_paired_battery_notify(void *data, struct mmi_battery_info *batt_info) { @@ -2296,48 +2350,33 @@ static void sgm4154x_paired_battery_notify(void *data, static struct timespec64 start = {0}; uint32_t elapsed_ms; static bool batt_protected = false; - bool otg_enabled = false; if (!batt_info || batt_info->batt_mv <= 0) { pr_warn("Invalid paired battery info\n"); return; } - memcpy(&chg->paired_batt_info, batt_info, sizeof(struct mmi_battery_info)); - batt_present = (chg->batt_info.batt_temp >= BPD_TEMP_THRE)? true : false; - if (!chg->chg_info.chrg_present && chg->chg_info.chrg_ma == 0 && - chg->chg_info.chrg_mv > OTG_VBUS_MIN_MV) { - otg_enabled = true; + chg->chg_info.chrg_mv > OTG_VBUS_MIN_MV && + chg->chg_info.chrg_mv < OTG_VBUS_MAX_MV && + (chg->batt_info.batt_ma < 0 || batt_info->batt_ma < 0)) { + chg->sgm->otg_enabled = true; + } else { + chg->sgm->otg_enabled = false; } + memcpy(&chg->paired_batt_info, batt_info, sizeof(struct mmi_battery_info)); + batt_present = (chg->batt_info.batt_temp >= BPD_TEMP_THRE)? true : false; if (batt_present) { rc = power_supply_get_property(chg->fg_psy, POWER_SUPPLY_PROP_PRESENT, &val); if (!rc && !val.intval) batt_present = false; } - if (!batt_present || otg_enabled) { - sgm4154x_set_hiz_en(chg->sgm, true); - if (chg->sgm->client->irq && chg->sgm->irq_enabled) { - disable_irq_wake(chg->sgm->client->irq); - disable_irq(chg->sgm->client->irq); - chg->sgm->irq_enabled = false; - pr_warn("irq is disabled, bpd=%d, otg=%d\n", - batt_present, otg_enabled); - } - if (!batt_present) - return; - } else { - if (!chg->sgm->irq_enabled && chg->sgm->client->irq) { - enable_irq_wake(chg->sgm->client->irq); - enable_irq(chg->sgm->client->irq); - chg->sgm->irq_enabled = true; - pr_warn("irq is enabled, bpd=%d, otg=%d\n", - batt_present, otg_enabled); - } - } + chg->sgm->batt_present = batt_present; + if (!chg->sgm->batt_present) + return; batt_ocv = chg->batt_info.batt_mv; batt_ocv -= (chg->batt_info.batt_ma * chg->batt_esr) / 1000; @@ -2462,9 +2501,8 @@ static void sgm4154x_paired_battery_notify(void *data, prev_low_load_en = low_load_en; } - pr_info("charger_present:%d, charger_suspend:%d, paired_ocv:%dmV, batt_ocv:%dmV\n", - chg->chg_info.chrg_present, chg->sgm->state.hiz_en, - paired_ocv, batt_ocv); + pr_info("charger_present:%d, paired_ocv:%dmV, batt_ocv:%dmV\n", + chg->chg_info.chrg_present, paired_ocv, batt_ocv); pr_info("delta_ocv:%dmV, delta_soc:%d, high_load:%d, low_load:%d, ichg:%duA\n", delta_ocv, delta_soc, high_load_en, low_load_en, paired_ichg); } diff --git a/drivers/power/sgm4154x_charger_lite/sgm4154x_charger_lite.h b/drivers/power/sgm4154x_charger_lite/sgm4154x_charger_lite.h index 9d87c9617e4f..6582cfc02302 100644 --- a/drivers/power/sgm4154x_charger_lite/sgm4154x_charger_lite.h +++ b/drivers/power/sgm4154x_charger_lite/sgm4154x_charger_lite.h @@ -338,6 +338,12 @@ struct sgm4154x_device { struct dentry *debug_root; + u32 ichg; /* charge current */ + u32 ilim; /* input current */ + u32 vreg; /* regulation voltage */ + + bool batt_present; + bool otg_enabled; bool irq_enabled; int high_load_en_gpio; int low_load_en_gpio;