Loading Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger-psy.txt +6 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,12 @@ Charger specific properties: If this value is not specified or is not one of the above then default value is 110. - qcom,max-cutoff-soc Usage: optional Value type: <u32> Definition: SOC beyond which SMB1390 is kept disabled. If this value is not specified then default value is 85%. ================================================ Second Level Nodes - SMB1390 Charger Peripherals ================================================ Loading drivers/power/supply/qcom/qpnp-smb5.c +4 −3 Original line number Diff line number Diff line Loading @@ -2740,7 +2740,6 @@ static int smb5_post_init(struct smb5 *chip) return rc; } rerun_election(chg->usb_irq_enable_votable); return 0; } Loading Loading @@ -3080,6 +3079,7 @@ static int smb5_request_interrupt(struct smb5 *chip, irq_data->storm_data = smb5_irqs[irq_index].storm_data; mutex_init(&irq_data->storm_data.storm_lock); smb5_irqs[irq_index].enabled = true; rc = devm_request_threaded_irq(chg->dev, irq, NULL, smb5_irqs[irq_index].handler, IRQF_ONESHOT, irq_name, irq_data); Loading Loading @@ -3113,8 +3113,6 @@ static int smb5_request_interrupts(struct smb5 *chip) return rc; } } if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq) chg->usb_icl_change_irq_enabled = true; /* * WDOG_SNARL_IRQ is required for SW Thermal Regulation WA. In case Loading @@ -3129,6 +3127,9 @@ static int smb5_request_interrupts(struct smb5 *chip) disable_irq_nosync(chg->irq_info[WDOG_SNARL_IRQ].irq); } vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); return rc; } Loading drivers/power/supply/qcom/smb1390-charger-psy.c +36 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ #define WIRELESS_VOTER "WIRELESS_VOTER" #define SRC_VOTER "SRC_VOTER" #define SWITCHER_TOGGLE_VOTER "SWITCHER_TOGGLE_VOTER" #define SOC_LEVEL_VOTER "SOC_LEVEL_VOTER" #define THERMAL_SUSPEND_DECIDEGC 1400 Loading Loading @@ -178,6 +179,7 @@ struct smb1390 { u32 debug_mask; u32 min_ilim_ua; u32 max_temp_alarm_degc; u32 max_cutoff_soc; }; struct smb_irq { Loading Loading @@ -459,6 +461,28 @@ static int smb1390_get_isns(struct smb1390 *chip, return rc; } static int smb1390_is_batt_soc_valid(struct smb1390 *chip) { int rc; union power_supply_propval pval = {0, }; if (!chip->batt_psy) goto out; rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CAPACITY, &pval); if (rc < 0) { pr_err("Couldn't get CAPACITY rc=%d\n", rc); goto out; } if (pval.intval >= chip->max_cutoff_soc) return false; out: return true; } /* voter callbacks */ static int smb1390_disable_vote_cb(struct votable *votable, void *data, int disable, const char *client) Loading Loading @@ -558,6 +582,9 @@ static void smb1390_status_change_work(struct work_struct *work) if (!is_psy_voter_available(chip)) goto out; vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_SMB_EN_MODE, &pval); if (rc < 0) { Loading Loading @@ -636,6 +663,7 @@ static void smb1390_status_change_work(struct work_struct *work) vote(chip->disable_votable, SRC_VOTER, true, 0); vote(chip->disable_votable, TAPER_END_VOTER, false, 0); vote(chip->fcc_votable, CP_VOTER, false, 0); vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0); } out: Loading Loading @@ -903,6 +931,10 @@ static int smb1390_parse_dt(struct smb1390 *chip) of_property_read_u32(chip->dev->of_node, "qcom,max-temp-alarm-degc", &chip->max_temp_alarm_degc); chip->max_cutoff_soc = 85; /* 85% */ of_property_read_u32(chip->dev->of_node, "qcom,max-cutoff-soc", &chip->max_cutoff_soc); return 0; } Loading @@ -929,6 +961,9 @@ static int smb1390_create_votables(struct smb1390 *chip) * traditional parallel charging if present */ vote(chip->disable_votable, USER_VOTER, true, 0); /* keep charge pump disabled if SOC is above threshold */ vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); /* * In case SMB1390 probe happens after FCC value has been configured, Loading Loading @@ -1193,6 +1228,7 @@ static int smb1390_remove(struct platform_device *pdev) /* explicitly disable charging */ vote(chip->disable_votable, USER_VOTER, true, 0); vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0); cancel_work(&chip->taper_work); cancel_work(&chip->status_change_work); wakeup_source_unregister(chip->cp_ws); Loading drivers/power/supply/qcom/smb5-lib.c +110 −38 Original line number Diff line number Diff line Loading @@ -727,14 +727,9 @@ int smblib_set_charge_param(struct smb_charger *chg, int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend) { int rc = 0; int irq = chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq; if (suspend && irq) { if (chg->usb_icl_change_irq_enabled) { disable_irq_nosync(irq); chg->usb_icl_change_irq_enabled = false; } } if (suspend) vote(chg->icl_irq_disable_votable, USB_SUSPEND_VOTER, true, 0); rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, suspend ? USBIN_SUSPEND_BIT : 0); Loading @@ -742,12 +737,9 @@ int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend) smblib_err(chg, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n", suspend ? "suspend" : "resume", rc); if (!suspend && irq) { if (!chg->usb_icl_change_irq_enabled) { enable_irq(irq); chg->usb_icl_change_irq_enabled = true; } } if (!suspend) vote(chg->icl_irq_disable_votable, USB_SUSPEND_VOTER, false, 0); return rc; } Loading Loading @@ -1135,6 +1127,10 @@ static void smblib_uusb_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, HVDCP2_ICL_VOTER, false, 0); vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER, false, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, HDC_IRQ_VOTER, false, 0); /* Remove SW thermal regulation WA votes */ vote(chg->usb_icl_votable, SW_THERM_REGULATION_VOTER, false, 0); Loading Loading @@ -1582,24 +1578,70 @@ static int smblib_chg_disable_vote_callback(struct votable *votable, void *data, return 0; } static int smblib_usb_irq_enable_vote_callback(struct votable *votable, void *data, int enable, const char *client) static int smblib_hdc_irq_disable_vote_callback(struct votable *votable, void *data, int disable, const char *client) { struct smb_charger *chg = data; if (!chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq || !chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq) if (!chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq) return 0; if (enable) { enable_irq(chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq); enable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); if (chg->irq_info[HIGH_DUTY_CYCLE_IRQ].enabled) { if (disable) disable_irq_nosync( chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); } else { if (!disable) enable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); } chg->irq_info[HIGH_DUTY_CYCLE_IRQ].enabled = !disable; return 0; } static int smblib_limited_irq_disable_vote_callback(struct votable *votable, void *data, int disable, const char *client) { struct smb_charger *chg = data; if (!chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq) return 0; if (chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].enabled) { if (disable) disable_irq_nosync( chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq); disable_irq_nosync(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); } else { if (!disable) enable_irq( chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq); } chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].enabled = !disable; return 0; } static int smblib_icl_irq_disable_vote_callback(struct votable *votable, void *data, int disable, const char *client) { struct smb_charger *chg = data; if (!chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq) return 0; if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].enabled) { if (disable) disable_irq_nosync( chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); } else { if (!disable) enable_irq(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); } chg->irq_info[USBIN_ICL_CHANGE_IRQ].enabled = !disable; return 0; } Loading Loading @@ -3984,7 +4026,10 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, update_sw_icl_max(chg, apsd->pst); if (chg->pd_active) { vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, false, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, false, 0); /* * Enforce 100mA for PD until the real vote comes in later. Loading @@ -4010,7 +4055,10 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, } } else { vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); sec_charger = chg->sec_pl_present ? POWER_SUPPLY_CHARGER_SEC_PL : Loading Loading @@ -4832,7 +4880,10 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, if (qc_charger) { /* enable HDC and ICL irq for QC2/3 charger */ vote(chg->usb_irq_enable_votable, QC_VOTER, true, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, false, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, false, 0); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, HVDCP_CURRENT_UA); } else { Loading Loading @@ -5232,8 +5283,10 @@ static void typec_src_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER, false, 0); /* reset usb irq voters */ vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); vote(chg->usb_irq_enable_votable, QC_VOTER, false, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, HDC_IRQ_VOTER, false, 0); /* reset parallel voters */ vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0); Loading Loading @@ -5594,8 +5647,7 @@ irqreturn_t high_duty_cycle_irq_handler(int irq, void *data) * the flag cleared in the delayed work queue, to avoid any IRQ * storming during the delays */ if (chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq) disable_irq_nosync(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); vote(chg->hdc_irq_disable_votable, HDC_IRQ_VOTER, true, 0); schedule_delayed_work(&chg->clear_hdc_work, msecs_to_jiffies(60)); Loading Loading @@ -5950,8 +6002,7 @@ static void clear_hdc_work(struct work_struct *work) clear_hdc_work.work); chg->is_hdc = 0; if (chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq) enable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); vote(chg->hdc_irq_disable_votable, HDC_IRQ_VOTER, false, 0); } static void smblib_icl_change_work(struct work_struct *work) Loading Loading @@ -6580,13 +6631,34 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } chg->usb_irq_enable_votable = create_votable("USB_IRQ_DISABLE", chg->limited_irq_disable_votable = create_votable( "USB_LIMITED_IRQ_DISABLE", VOTE_SET_ANY, smblib_limited_irq_disable_vote_callback, chg); if (IS_ERR(chg->limited_irq_disable_votable)) { rc = PTR_ERR(chg->limited_irq_disable_votable); chg->limited_irq_disable_votable = NULL; return rc; } chg->hdc_irq_disable_votable = create_votable("USB_HDC_IRQ_DISABLE", VOTE_SET_ANY, smblib_hdc_irq_disable_vote_callback, chg); if (IS_ERR(chg->hdc_irq_disable_votable)) { rc = PTR_ERR(chg->hdc_irq_disable_votable); chg->hdc_irq_disable_votable = NULL; return rc; } chg->icl_irq_disable_votable = create_votable("USB_ICL_IRQ_DISABLE", VOTE_SET_ANY, smblib_usb_irq_enable_vote_callback, smblib_icl_irq_disable_vote_callback, chg); if (IS_ERR(chg->usb_irq_enable_votable)) { rc = PTR_ERR(chg->usb_irq_enable_votable); chg->usb_irq_enable_votable = NULL; if (IS_ERR(chg->icl_irq_disable_votable)) { rc = PTR_ERR(chg->icl_irq_disable_votable); chg->icl_irq_disable_votable = NULL; return rc; } Loading drivers/power/supply/qcom/smb5-lib.h +7 −1 Original line number Diff line number Diff line Loading @@ -76,6 +76,9 @@ enum print_reason { #define THERMAL_THROTTLE_VOTER "THERMAL_THROTTLE_VOTER" #define VOUT_VOTER "VOUT_VOTER" #define DR_SWAP_VOTER "DR_SWAP_VOTER" #define USB_SUSPEND_VOTER "USB_SUSPEND_VOTER" #define CHARGER_TYPE_VOTER "CHARGER_TYPE_VOTER" #define HDC_IRQ_VOTER "HDC_IRQ_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -231,6 +234,7 @@ struct smb_irq_info { const struct storm_watch storm_data; struct smb_irq_data *irq_data; int irq; bool enabled; }; static const unsigned int smblib_extcon_cable[] = { Loading Loading @@ -405,9 +409,11 @@ struct smb_charger { struct votable *pl_disable_votable; struct votable *chg_disable_votable; struct votable *pl_enable_votable_indirect; struct votable *usb_irq_enable_votable; struct votable *cp_disable_votable; struct votable *smb_override_votable; struct votable *icl_irq_disable_votable; struct votable *limited_irq_disable_votable; struct votable *hdc_irq_disable_votable; /* work */ struct work_struct bms_update_work; Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger-psy.txt +6 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,12 @@ Charger specific properties: If this value is not specified or is not one of the above then default value is 110. - qcom,max-cutoff-soc Usage: optional Value type: <u32> Definition: SOC beyond which SMB1390 is kept disabled. If this value is not specified then default value is 85%. ================================================ Second Level Nodes - SMB1390 Charger Peripherals ================================================ Loading
drivers/power/supply/qcom/qpnp-smb5.c +4 −3 Original line number Diff line number Diff line Loading @@ -2740,7 +2740,6 @@ static int smb5_post_init(struct smb5 *chip) return rc; } rerun_election(chg->usb_irq_enable_votable); return 0; } Loading Loading @@ -3080,6 +3079,7 @@ static int smb5_request_interrupt(struct smb5 *chip, irq_data->storm_data = smb5_irqs[irq_index].storm_data; mutex_init(&irq_data->storm_data.storm_lock); smb5_irqs[irq_index].enabled = true; rc = devm_request_threaded_irq(chg->dev, irq, NULL, smb5_irqs[irq_index].handler, IRQF_ONESHOT, irq_name, irq_data); Loading Loading @@ -3113,8 +3113,6 @@ static int smb5_request_interrupts(struct smb5 *chip) return rc; } } if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq) chg->usb_icl_change_irq_enabled = true; /* * WDOG_SNARL_IRQ is required for SW Thermal Regulation WA. In case Loading @@ -3129,6 +3127,9 @@ static int smb5_request_interrupts(struct smb5 *chip) disable_irq_nosync(chg->irq_info[WDOG_SNARL_IRQ].irq); } vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); return rc; } Loading
drivers/power/supply/qcom/smb1390-charger-psy.c +36 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ #define WIRELESS_VOTER "WIRELESS_VOTER" #define SRC_VOTER "SRC_VOTER" #define SWITCHER_TOGGLE_VOTER "SWITCHER_TOGGLE_VOTER" #define SOC_LEVEL_VOTER "SOC_LEVEL_VOTER" #define THERMAL_SUSPEND_DECIDEGC 1400 Loading Loading @@ -178,6 +179,7 @@ struct smb1390 { u32 debug_mask; u32 min_ilim_ua; u32 max_temp_alarm_degc; u32 max_cutoff_soc; }; struct smb_irq { Loading Loading @@ -459,6 +461,28 @@ static int smb1390_get_isns(struct smb1390 *chip, return rc; } static int smb1390_is_batt_soc_valid(struct smb1390 *chip) { int rc; union power_supply_propval pval = {0, }; if (!chip->batt_psy) goto out; rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CAPACITY, &pval); if (rc < 0) { pr_err("Couldn't get CAPACITY rc=%d\n", rc); goto out; } if (pval.intval >= chip->max_cutoff_soc) return false; out: return true; } /* voter callbacks */ static int smb1390_disable_vote_cb(struct votable *votable, void *data, int disable, const char *client) Loading Loading @@ -558,6 +582,9 @@ static void smb1390_status_change_work(struct work_struct *work) if (!is_psy_voter_available(chip)) goto out; vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_SMB_EN_MODE, &pval); if (rc < 0) { Loading Loading @@ -636,6 +663,7 @@ static void smb1390_status_change_work(struct work_struct *work) vote(chip->disable_votable, SRC_VOTER, true, 0); vote(chip->disable_votable, TAPER_END_VOTER, false, 0); vote(chip->fcc_votable, CP_VOTER, false, 0); vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0); } out: Loading Loading @@ -903,6 +931,10 @@ static int smb1390_parse_dt(struct smb1390 *chip) of_property_read_u32(chip->dev->of_node, "qcom,max-temp-alarm-degc", &chip->max_temp_alarm_degc); chip->max_cutoff_soc = 85; /* 85% */ of_property_read_u32(chip->dev->of_node, "qcom,max-cutoff-soc", &chip->max_cutoff_soc); return 0; } Loading @@ -929,6 +961,9 @@ static int smb1390_create_votables(struct smb1390 *chip) * traditional parallel charging if present */ vote(chip->disable_votable, USER_VOTER, true, 0); /* keep charge pump disabled if SOC is above threshold */ vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); /* * In case SMB1390 probe happens after FCC value has been configured, Loading Loading @@ -1193,6 +1228,7 @@ static int smb1390_remove(struct platform_device *pdev) /* explicitly disable charging */ vote(chip->disable_votable, USER_VOTER, true, 0); vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0); cancel_work(&chip->taper_work); cancel_work(&chip->status_change_work); wakeup_source_unregister(chip->cp_ws); Loading
drivers/power/supply/qcom/smb5-lib.c +110 −38 Original line number Diff line number Diff line Loading @@ -727,14 +727,9 @@ int smblib_set_charge_param(struct smb_charger *chg, int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend) { int rc = 0; int irq = chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq; if (suspend && irq) { if (chg->usb_icl_change_irq_enabled) { disable_irq_nosync(irq); chg->usb_icl_change_irq_enabled = false; } } if (suspend) vote(chg->icl_irq_disable_votable, USB_SUSPEND_VOTER, true, 0); rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, suspend ? USBIN_SUSPEND_BIT : 0); Loading @@ -742,12 +737,9 @@ int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend) smblib_err(chg, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n", suspend ? "suspend" : "resume", rc); if (!suspend && irq) { if (!chg->usb_icl_change_irq_enabled) { enable_irq(irq); chg->usb_icl_change_irq_enabled = true; } } if (!suspend) vote(chg->icl_irq_disable_votable, USB_SUSPEND_VOTER, false, 0); return rc; } Loading Loading @@ -1135,6 +1127,10 @@ static void smblib_uusb_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, HVDCP2_ICL_VOTER, false, 0); vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER, false, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, HDC_IRQ_VOTER, false, 0); /* Remove SW thermal regulation WA votes */ vote(chg->usb_icl_votable, SW_THERM_REGULATION_VOTER, false, 0); Loading Loading @@ -1582,24 +1578,70 @@ static int smblib_chg_disable_vote_callback(struct votable *votable, void *data, return 0; } static int smblib_usb_irq_enable_vote_callback(struct votable *votable, void *data, int enable, const char *client) static int smblib_hdc_irq_disable_vote_callback(struct votable *votable, void *data, int disable, const char *client) { struct smb_charger *chg = data; if (!chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq || !chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq) if (!chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq) return 0; if (enable) { enable_irq(chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq); enable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); if (chg->irq_info[HIGH_DUTY_CYCLE_IRQ].enabled) { if (disable) disable_irq_nosync( chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); } else { if (!disable) enable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); } chg->irq_info[HIGH_DUTY_CYCLE_IRQ].enabled = !disable; return 0; } static int smblib_limited_irq_disable_vote_callback(struct votable *votable, void *data, int disable, const char *client) { struct smb_charger *chg = data; if (!chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq) return 0; if (chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].enabled) { if (disable) disable_irq_nosync( chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq); disable_irq_nosync(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); } else { if (!disable) enable_irq( chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].irq); } chg->irq_info[INPUT_CURRENT_LIMITING_IRQ].enabled = !disable; return 0; } static int smblib_icl_irq_disable_vote_callback(struct votable *votable, void *data, int disable, const char *client) { struct smb_charger *chg = data; if (!chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq) return 0; if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].enabled) { if (disable) disable_irq_nosync( chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); } else { if (!disable) enable_irq(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); } chg->irq_info[USBIN_ICL_CHANGE_IRQ].enabled = !disable; return 0; } Loading Loading @@ -3984,7 +4026,10 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, update_sw_icl_max(chg, apsd->pst); if (chg->pd_active) { vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, false, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, false, 0); /* * Enforce 100mA for PD until the real vote comes in later. Loading @@ -4010,7 +4055,10 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, } } else { vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); sec_charger = chg->sec_pl_present ? POWER_SUPPLY_CHARGER_SEC_PL : Loading Loading @@ -4832,7 +4880,10 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, if (qc_charger) { /* enable HDC and ICL irq for QC2/3 charger */ vote(chg->usb_irq_enable_votable, QC_VOTER, true, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, false, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, false, 0); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, HVDCP_CURRENT_UA); } else { Loading Loading @@ -5232,8 +5283,10 @@ static void typec_src_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER, false, 0); /* reset usb irq voters */ vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); vote(chg->usb_irq_enable_votable, QC_VOTER, false, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, CHARGER_TYPE_VOTER, true, 0); vote(chg->hdc_irq_disable_votable, HDC_IRQ_VOTER, false, 0); /* reset parallel voters */ vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0); Loading Loading @@ -5594,8 +5647,7 @@ irqreturn_t high_duty_cycle_irq_handler(int irq, void *data) * the flag cleared in the delayed work queue, to avoid any IRQ * storming during the delays */ if (chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq) disable_irq_nosync(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); vote(chg->hdc_irq_disable_votable, HDC_IRQ_VOTER, true, 0); schedule_delayed_work(&chg->clear_hdc_work, msecs_to_jiffies(60)); Loading Loading @@ -5950,8 +6002,7 @@ static void clear_hdc_work(struct work_struct *work) clear_hdc_work.work); chg->is_hdc = 0; if (chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq) enable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq); vote(chg->hdc_irq_disable_votable, HDC_IRQ_VOTER, false, 0); } static void smblib_icl_change_work(struct work_struct *work) Loading Loading @@ -6580,13 +6631,34 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } chg->usb_irq_enable_votable = create_votable("USB_IRQ_DISABLE", chg->limited_irq_disable_votable = create_votable( "USB_LIMITED_IRQ_DISABLE", VOTE_SET_ANY, smblib_limited_irq_disable_vote_callback, chg); if (IS_ERR(chg->limited_irq_disable_votable)) { rc = PTR_ERR(chg->limited_irq_disable_votable); chg->limited_irq_disable_votable = NULL; return rc; } chg->hdc_irq_disable_votable = create_votable("USB_HDC_IRQ_DISABLE", VOTE_SET_ANY, smblib_hdc_irq_disable_vote_callback, chg); if (IS_ERR(chg->hdc_irq_disable_votable)) { rc = PTR_ERR(chg->hdc_irq_disable_votable); chg->hdc_irq_disable_votable = NULL; return rc; } chg->icl_irq_disable_votable = create_votable("USB_ICL_IRQ_DISABLE", VOTE_SET_ANY, smblib_usb_irq_enable_vote_callback, smblib_icl_irq_disable_vote_callback, chg); if (IS_ERR(chg->usb_irq_enable_votable)) { rc = PTR_ERR(chg->usb_irq_enable_votable); chg->usb_irq_enable_votable = NULL; if (IS_ERR(chg->icl_irq_disable_votable)) { rc = PTR_ERR(chg->icl_irq_disable_votable); chg->icl_irq_disable_votable = NULL; return rc; } Loading
drivers/power/supply/qcom/smb5-lib.h +7 −1 Original line number Diff line number Diff line Loading @@ -76,6 +76,9 @@ enum print_reason { #define THERMAL_THROTTLE_VOTER "THERMAL_THROTTLE_VOTER" #define VOUT_VOTER "VOUT_VOTER" #define DR_SWAP_VOTER "DR_SWAP_VOTER" #define USB_SUSPEND_VOTER "USB_SUSPEND_VOTER" #define CHARGER_TYPE_VOTER "CHARGER_TYPE_VOTER" #define HDC_IRQ_VOTER "HDC_IRQ_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -231,6 +234,7 @@ struct smb_irq_info { const struct storm_watch storm_data; struct smb_irq_data *irq_data; int irq; bool enabled; }; static const unsigned int smblib_extcon_cable[] = { Loading Loading @@ -405,9 +409,11 @@ struct smb_charger { struct votable *pl_disable_votable; struct votable *chg_disable_votable; struct votable *pl_enable_votable_indirect; struct votable *usb_irq_enable_votable; struct votable *cp_disable_votable; struct votable *smb_override_votable; struct votable *icl_irq_disable_votable; struct votable *limited_irq_disable_votable; struct votable *hdc_irq_disable_votable; /* work */ struct work_struct bms_update_work; Loading