Loading drivers/power/supply/qcom/qpnp-smb5.c +2 −1 Original line number Diff line number Diff line Loading @@ -282,7 +282,8 @@ static int smb5_chg_config_init(struct smb5 *chip) break; case PMI632_SUBTYPE: chip->chg.smb_version = PMI632_SUBTYPE; chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA; chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA | CHG_TERMINATION_WA; if (pmic_rev_id->rev4 >= 2) chg->wa_flags |= MOISTURE_PROTECTION_WA; chg->param = smb5_pmi632_params; Loading drivers/power/supply/qcom/smb5-lib.c +165 −0 Original line number Diff line number Diff line Loading @@ -773,6 +773,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) struct storm_watch *wdata; cancel_delayed_work_sync(&chg->pl_enable_work); alarm_cancel(&chg->chg_termination_alarm); if (chg->wa_flags & BOOST_BACK_WA) { data = chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data; Loading @@ -793,6 +794,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA); vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); /* reconfigure allowed voltage for HVDCP */ rc = smblib_set_adapter_allowance(chg, Loading Loading @@ -1482,6 +1484,16 @@ int smblib_get_prop_batt_status(struct smb_charger *chg, break; } /* * If charge termination WA is active and has suspended charging, then * continue reporting charging status as FULL. */ if (is_client_vote_enabled(chg->usb_icl_votable, CHG_TERMINATION_VOTER)) { val->intval = POWER_SUPPLY_STATUS_FULL; return 0; } if (val->intval != POWER_SUPPLY_STATUS_CHARGING) return 0; Loading Loading @@ -1991,6 +2003,12 @@ int smblib_get_prop_usb_online(struct smb_charger *chg, return rc; } if (is_client_vote_enabled(chg->usb_icl_votable, CHG_TERMINATION_VOTER)) { rc = smblib_get_prop_usb_present(chg, val); return rc; } rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", Loading Loading @@ -2760,6 +2778,38 @@ irqreturn_t default_irq_handler(int irq, void *data) return IRQ_HANDLED; } #define CHG_TERM_WA_ENTRY_DELAY_MS 300000 /* 5 min */ #define CHG_TERM_WA_EXIT_DELAY_MS 60000 /* 1 min */ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status) { union power_supply_propval pval = {0, }; int rc = 0; rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval); if (rc < 0) { smblib_err(chg, "Couldn't read SOC value, rc=%d\n", rc); return; } /* * Post charge termination, switch to BSM mode triggers the risk of * over charging as BATFET opening may take some time post the necessity * of staying in supplemental mode, leading to unintended charging of * battery. Trigger the charge termination WA once charging is completed * to prevent overcharing. */ if ((batt_status == TERMINATE_CHARGE) && (pval.intval == 100)) { alarm_start_relative(&chg->chg_termination_alarm, ms_to_ktime(CHG_TERM_WA_ENTRY_DELAY_MS)); } else if (pval.intval < 100) { /* * Reset CC_SOC reference value for charge termination WA once * we exit the TERMINATE_CHARGE state and soc drops below 100% */ chg->cc_soc_ref = 0; } } irqreturn_t chg_state_change_irq_handler(int irq, void *data) { struct smb_irq_data *irq_data = data; Loading @@ -2777,6 +2827,10 @@ irqreturn_t chg_state_change_irq_handler(int irq, void *data) } stat = stat & BATTERY_CHARGER_STATUS_MASK; if (chg->wa_flags & CHG_TERMINATION_WA) smblib_eval_chg_termination(chg, stat); power_supply_changed(chg->batt_psy); return IRQ_HANDLED; } Loading Loading @@ -3468,6 +3522,7 @@ static void typec_src_removal(struct smb_charger *chg) } cancel_delayed_work_sync(&chg->pl_enable_work); alarm_cancel(&chg->chg_termination_alarm); /* reset input current limit voters */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, Loading @@ -3479,6 +3534,7 @@ static void typec_src_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); vote(chg->usb_icl_votable, OTG_VOTER, false, 0); vote(chg->usb_icl_votable, CTM_VOTER, false, 0); vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); /* reset usb irq voters */ vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); Loading Loading @@ -3995,6 +4051,12 @@ static void smblib_moisture_protection_work(struct work_struct *work) bool usb_plugged_in; u8 stat; /* * Hold awake votable to prevent pm_relax being called prior to * completion of this work. */ vote(chg->awake_votable, MOISTURE_VOTER, true, 0); /* * Disable 1% duty cycle on CC_ID pin and enable uUSB factory mode * detection to track any change on RID, as interrupts are disable. Loading Loading @@ -4057,6 +4119,7 @@ static void smblib_moisture_protection_work(struct work_struct *work) } out: vote(chg->awake_votable, MOISTURE_VOTER, false, 0); pm_relax(chg->dev); } Loading @@ -4076,6 +4139,93 @@ static enum alarmtimer_restart moisture_protection_alarm_cb(struct alarm *alarm, return ALARMTIMER_NORESTART; } static void smblib_chg_termination_work(struct work_struct *work) { struct smb_charger *chg = container_of(work, struct smb_charger, chg_termination_work); union power_supply_propval pval; int rc, delay = CHG_TERM_WA_ENTRY_DELAY_MS; /* * Hold awake votable to prevent pm_relax being called prior to * completion of this work. */ vote(chg->awake_votable, CHG_TERMINATION_VOTER, true, 0); rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0 || !pval.intval) goto out; rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval); if (rc < 0 || (pval.intval < 100)) { vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); goto out; } rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CHARGE_FULL, &pval); if (rc < 0) goto out; /* * On change in the value of learned capacity, re-initialize the * reference cc_soc value due to change in cc_soc characteristic value * at full capacity. Also, in case cc_soc_ref value is reset, * re-initialize it. */ if ((pval.intval != chg->charge_full_cc) || !chg->cc_soc_ref) { chg->charge_full_cc = pval.intval; rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CC_SOC, &pval); if (rc < 0) goto out; chg->cc_soc_ref = pval.intval; } else { rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CC_SOC, &pval); if (rc < 0) goto out; } /* * Suspend/Unsuspend USB input to keep cc_soc within the 0.5% to 0.75% * overshoot range of the cc_soc value at termination, to prevent * overcharging. */ if (pval.intval < DIV_ROUND_CLOSEST(chg->cc_soc_ref * 10050, 10000)) { vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); delay = CHG_TERM_WA_ENTRY_DELAY_MS; } else if (pval.intval > DIV_ROUND_CLOSEST(chg->cc_soc_ref * 10075, 10000)) { vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, true, 0); delay = CHG_TERM_WA_EXIT_DELAY_MS; } smblib_dbg(chg, PR_MISC, "Chg Term WA readings: cc_soc: %d, cc_soc_ref: %d, delay: %d\n", pval.intval, chg->cc_soc_ref, delay); alarm_start_relative(&chg->chg_termination_alarm, ms_to_ktime(delay)); out: vote(chg->awake_votable, CHG_TERMINATION_VOTER, false, 0); pm_relax(chg->dev); } static enum alarmtimer_restart chg_termination_alarm_cb(struct alarm *alarm, ktime_t now) { struct smb_charger *chg = container_of(alarm, struct smb_charger, chg_termination_alarm); smblib_dbg(chg, PR_MISC, "Charge termination WA alarm triggered %lld\n", ktime_to_ms(now)); /* Atomic context, cannot use voter */ pm_stay_awake(chg->dev); schedule_work(&chg->chg_termination_work); return ALARMTIMER_NORESTART; } #define JEITA_SOFT 0 #define JEITA_HARD 1 static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds, Loading Loading @@ -4288,6 +4438,19 @@ int smblib_init(struct smb_charger *chg) INIT_DELAYED_WORK(&chg->bb_removal_work, smblib_bb_removal_work); INIT_DELAYED_WORK(&chg->usbov_dbc_work, smblib_usbov_dbc_work); if (chg->wa_flags & CHG_TERMINATION_WA) { INIT_WORK(&chg->chg_termination_work, smblib_chg_termination_work); if (alarmtimer_get_rtcdev()) { alarm_init(&chg->chg_termination_alarm, ALARM_BOOTTIME, chg_termination_alarm_cb); } else { smblib_err(chg, "Couldn't get rtc device\n"); return -ENODEV; } } if (chg->moisture_protection_enabled && (chg->wa_flags & MOISTURE_PROTECTION_WA)) { INIT_WORK(&chg->moisture_protection_work, Loading Loading @@ -4368,9 +4531,11 @@ int smblib_deinit(struct smb_charger *chg) alarm_cancel(&chg->moisture_protection_alarm); cancel_work_sync(&chg->moisture_protection_work); } alarm_cancel(&chg->chg_termination_alarm); cancel_work_sync(&chg->bms_update_work); cancel_work_sync(&chg->jeita_update_work); cancel_work_sync(&chg->pl_update_work); cancel_work_sync(&chg->chg_termination_work); cancel_delayed_work_sync(&chg->clear_hdc_work); cancel_delayed_work_sync(&chg->icl_change_work); cancel_delayed_work_sync(&chg->pl_enable_work); Loading drivers/power/supply/qcom/smb5-lib.h +6 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ enum print_reason { #define MOISTURE_VOTER "MOISTURE_VOTER" #define USBOV_DBC_VOTER "USBOV_DBC_VOTER" #define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER" #define CHG_TERMINATION_VOTER "CHG_TERMINATION_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -104,6 +105,7 @@ enum { WEAK_ADAPTER_WA = BIT(1), MOISTURE_PROTECTION_WA = BIT(2), USBIN_OV_WA = BIT(3), CHG_TERMINATION_WA = BIT(4), }; enum { Loading Loading @@ -345,6 +347,7 @@ struct smb_charger { struct work_struct pl_update_work; struct work_struct jeita_update_work; struct work_struct moisture_protection_work; struct work_struct chg_termination_work; struct delayed_work ps_change_timeout_work; struct delayed_work clear_hdc_work; struct delayed_work icl_change_work; Loading @@ -355,6 +358,7 @@ struct smb_charger { /* alarm */ struct alarm moisture_protection_alarm; struct alarm chg_termination_alarm; /* pd */ int voltage_min_uv; Loading Loading @@ -407,6 +411,8 @@ struct smb_charger { bool moisture_present; bool moisture_protection_enabled; bool fcc_stepper_enable; int charge_full_cc; int cc_soc_ref; /* workaround flag */ u32 wa_flags; Loading Loading
drivers/power/supply/qcom/qpnp-smb5.c +2 −1 Original line number Diff line number Diff line Loading @@ -282,7 +282,8 @@ static int smb5_chg_config_init(struct smb5 *chip) break; case PMI632_SUBTYPE: chip->chg.smb_version = PMI632_SUBTYPE; chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA; chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA | CHG_TERMINATION_WA; if (pmic_rev_id->rev4 >= 2) chg->wa_flags |= MOISTURE_PROTECTION_WA; chg->param = smb5_pmi632_params; Loading
drivers/power/supply/qcom/smb5-lib.c +165 −0 Original line number Diff line number Diff line Loading @@ -773,6 +773,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) struct storm_watch *wdata; cancel_delayed_work_sync(&chg->pl_enable_work); alarm_cancel(&chg->chg_termination_alarm); if (chg->wa_flags & BOOST_BACK_WA) { data = chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data; Loading @@ -793,6 +794,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA); vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); /* reconfigure allowed voltage for HVDCP */ rc = smblib_set_adapter_allowance(chg, Loading Loading @@ -1482,6 +1484,16 @@ int smblib_get_prop_batt_status(struct smb_charger *chg, break; } /* * If charge termination WA is active and has suspended charging, then * continue reporting charging status as FULL. */ if (is_client_vote_enabled(chg->usb_icl_votable, CHG_TERMINATION_VOTER)) { val->intval = POWER_SUPPLY_STATUS_FULL; return 0; } if (val->intval != POWER_SUPPLY_STATUS_CHARGING) return 0; Loading Loading @@ -1991,6 +2003,12 @@ int smblib_get_prop_usb_online(struct smb_charger *chg, return rc; } if (is_client_vote_enabled(chg->usb_icl_votable, CHG_TERMINATION_VOTER)) { rc = smblib_get_prop_usb_present(chg, val); return rc; } rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", Loading Loading @@ -2760,6 +2778,38 @@ irqreturn_t default_irq_handler(int irq, void *data) return IRQ_HANDLED; } #define CHG_TERM_WA_ENTRY_DELAY_MS 300000 /* 5 min */ #define CHG_TERM_WA_EXIT_DELAY_MS 60000 /* 1 min */ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status) { union power_supply_propval pval = {0, }; int rc = 0; rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval); if (rc < 0) { smblib_err(chg, "Couldn't read SOC value, rc=%d\n", rc); return; } /* * Post charge termination, switch to BSM mode triggers the risk of * over charging as BATFET opening may take some time post the necessity * of staying in supplemental mode, leading to unintended charging of * battery. Trigger the charge termination WA once charging is completed * to prevent overcharing. */ if ((batt_status == TERMINATE_CHARGE) && (pval.intval == 100)) { alarm_start_relative(&chg->chg_termination_alarm, ms_to_ktime(CHG_TERM_WA_ENTRY_DELAY_MS)); } else if (pval.intval < 100) { /* * Reset CC_SOC reference value for charge termination WA once * we exit the TERMINATE_CHARGE state and soc drops below 100% */ chg->cc_soc_ref = 0; } } irqreturn_t chg_state_change_irq_handler(int irq, void *data) { struct smb_irq_data *irq_data = data; Loading @@ -2777,6 +2827,10 @@ irqreturn_t chg_state_change_irq_handler(int irq, void *data) } stat = stat & BATTERY_CHARGER_STATUS_MASK; if (chg->wa_flags & CHG_TERMINATION_WA) smblib_eval_chg_termination(chg, stat); power_supply_changed(chg->batt_psy); return IRQ_HANDLED; } Loading Loading @@ -3468,6 +3522,7 @@ static void typec_src_removal(struct smb_charger *chg) } cancel_delayed_work_sync(&chg->pl_enable_work); alarm_cancel(&chg->chg_termination_alarm); /* reset input current limit voters */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, Loading @@ -3479,6 +3534,7 @@ static void typec_src_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); vote(chg->usb_icl_votable, OTG_VOTER, false, 0); vote(chg->usb_icl_votable, CTM_VOTER, false, 0); vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); /* reset usb irq voters */ vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); Loading Loading @@ -3995,6 +4051,12 @@ static void smblib_moisture_protection_work(struct work_struct *work) bool usb_plugged_in; u8 stat; /* * Hold awake votable to prevent pm_relax being called prior to * completion of this work. */ vote(chg->awake_votable, MOISTURE_VOTER, true, 0); /* * Disable 1% duty cycle on CC_ID pin and enable uUSB factory mode * detection to track any change on RID, as interrupts are disable. Loading Loading @@ -4057,6 +4119,7 @@ static void smblib_moisture_protection_work(struct work_struct *work) } out: vote(chg->awake_votable, MOISTURE_VOTER, false, 0); pm_relax(chg->dev); } Loading @@ -4076,6 +4139,93 @@ static enum alarmtimer_restart moisture_protection_alarm_cb(struct alarm *alarm, return ALARMTIMER_NORESTART; } static void smblib_chg_termination_work(struct work_struct *work) { struct smb_charger *chg = container_of(work, struct smb_charger, chg_termination_work); union power_supply_propval pval; int rc, delay = CHG_TERM_WA_ENTRY_DELAY_MS; /* * Hold awake votable to prevent pm_relax being called prior to * completion of this work. */ vote(chg->awake_votable, CHG_TERMINATION_VOTER, true, 0); rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0 || !pval.intval) goto out; rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval); if (rc < 0 || (pval.intval < 100)) { vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); goto out; } rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CHARGE_FULL, &pval); if (rc < 0) goto out; /* * On change in the value of learned capacity, re-initialize the * reference cc_soc value due to change in cc_soc characteristic value * at full capacity. Also, in case cc_soc_ref value is reset, * re-initialize it. */ if ((pval.intval != chg->charge_full_cc) || !chg->cc_soc_ref) { chg->charge_full_cc = pval.intval; rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CC_SOC, &pval); if (rc < 0) goto out; chg->cc_soc_ref = pval.intval; } else { rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CC_SOC, &pval); if (rc < 0) goto out; } /* * Suspend/Unsuspend USB input to keep cc_soc within the 0.5% to 0.75% * overshoot range of the cc_soc value at termination, to prevent * overcharging. */ if (pval.intval < DIV_ROUND_CLOSEST(chg->cc_soc_ref * 10050, 10000)) { vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); delay = CHG_TERM_WA_ENTRY_DELAY_MS; } else if (pval.intval > DIV_ROUND_CLOSEST(chg->cc_soc_ref * 10075, 10000)) { vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, true, 0); delay = CHG_TERM_WA_EXIT_DELAY_MS; } smblib_dbg(chg, PR_MISC, "Chg Term WA readings: cc_soc: %d, cc_soc_ref: %d, delay: %d\n", pval.intval, chg->cc_soc_ref, delay); alarm_start_relative(&chg->chg_termination_alarm, ms_to_ktime(delay)); out: vote(chg->awake_votable, CHG_TERMINATION_VOTER, false, 0); pm_relax(chg->dev); } static enum alarmtimer_restart chg_termination_alarm_cb(struct alarm *alarm, ktime_t now) { struct smb_charger *chg = container_of(alarm, struct smb_charger, chg_termination_alarm); smblib_dbg(chg, PR_MISC, "Charge termination WA alarm triggered %lld\n", ktime_to_ms(now)); /* Atomic context, cannot use voter */ pm_stay_awake(chg->dev); schedule_work(&chg->chg_termination_work); return ALARMTIMER_NORESTART; } #define JEITA_SOFT 0 #define JEITA_HARD 1 static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds, Loading Loading @@ -4288,6 +4438,19 @@ int smblib_init(struct smb_charger *chg) INIT_DELAYED_WORK(&chg->bb_removal_work, smblib_bb_removal_work); INIT_DELAYED_WORK(&chg->usbov_dbc_work, smblib_usbov_dbc_work); if (chg->wa_flags & CHG_TERMINATION_WA) { INIT_WORK(&chg->chg_termination_work, smblib_chg_termination_work); if (alarmtimer_get_rtcdev()) { alarm_init(&chg->chg_termination_alarm, ALARM_BOOTTIME, chg_termination_alarm_cb); } else { smblib_err(chg, "Couldn't get rtc device\n"); return -ENODEV; } } if (chg->moisture_protection_enabled && (chg->wa_flags & MOISTURE_PROTECTION_WA)) { INIT_WORK(&chg->moisture_protection_work, Loading Loading @@ -4368,9 +4531,11 @@ int smblib_deinit(struct smb_charger *chg) alarm_cancel(&chg->moisture_protection_alarm); cancel_work_sync(&chg->moisture_protection_work); } alarm_cancel(&chg->chg_termination_alarm); cancel_work_sync(&chg->bms_update_work); cancel_work_sync(&chg->jeita_update_work); cancel_work_sync(&chg->pl_update_work); cancel_work_sync(&chg->chg_termination_work); cancel_delayed_work_sync(&chg->clear_hdc_work); cancel_delayed_work_sync(&chg->icl_change_work); cancel_delayed_work_sync(&chg->pl_enable_work); Loading
drivers/power/supply/qcom/smb5-lib.h +6 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ enum print_reason { #define MOISTURE_VOTER "MOISTURE_VOTER" #define USBOV_DBC_VOTER "USBOV_DBC_VOTER" #define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER" #define CHG_TERMINATION_VOTER "CHG_TERMINATION_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -104,6 +105,7 @@ enum { WEAK_ADAPTER_WA = BIT(1), MOISTURE_PROTECTION_WA = BIT(2), USBIN_OV_WA = BIT(3), CHG_TERMINATION_WA = BIT(4), }; enum { Loading Loading @@ -345,6 +347,7 @@ struct smb_charger { struct work_struct pl_update_work; struct work_struct jeita_update_work; struct work_struct moisture_protection_work; struct work_struct chg_termination_work; struct delayed_work ps_change_timeout_work; struct delayed_work clear_hdc_work; struct delayed_work icl_change_work; Loading @@ -355,6 +358,7 @@ struct smb_charger { /* alarm */ struct alarm moisture_protection_alarm; struct alarm chg_termination_alarm; /* pd */ int voltage_min_uv; Loading Loading @@ -407,6 +411,8 @@ struct smb_charger { bool moisture_present; bool moisture_protection_enabled; bool fcc_stepper_enable; int charge_full_cc; int cc_soc_ref; /* workaround flag */ u32 wa_flags; Loading