Loading drivers/power/supply/qcom/battery.c +60 −17 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ struct pl_data { struct votable *cp_ilim_votable; struct votable *cp_disable_votable; struct votable *fcc_main_votable; struct votable *cp_slave_disable_votable; struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct work_struct pl_taper_work; Loading @@ -74,6 +75,7 @@ struct pl_data { struct power_supply *usb_psy; struct power_supply *dc_psy; struct power_supply *cp_master_psy; struct power_supply *cp_slave_psy; int charge_type; int total_settled_ua; int pl_settled_ua; Loading Loading @@ -803,7 +805,9 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, { struct pl_data *chip = data; int master_fcc_ua = total_fcc_ua, slave_fcc_ua = 0; int main_fcc_ua = 0, cp_fcc_ua = 0, fcc_thr_ua = 0, rc; union power_supply_propval pval = {0, }; bool is_cc_mode = false; if (total_fcc_ua < 0) return 0; Loading @@ -814,22 +818,65 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, if (!chip->cp_disable_votable) chip->cp_disable_votable = find_votable("CP_DISABLE"); if (chip->cp_disable_votable) { if (cp_get_parallel_mode(chip, PARALLEL_OUTPUT_MODE) == POWER_SUPPLY_PL_OUTPUT_VPH) { power_supply_get_property(chip->cp_master_psy, if (!chip->cp_master_psy) chip->cp_master_psy = power_supply_get_by_name("charge_pump_master"); if (!chip->cp_slave_psy) chip->cp_slave_psy = power_supply_get_by_name("cp_slave"); if (!chip->cp_slave_disable_votable) chip->cp_slave_disable_votable = find_votable("CP_SLAVE_DISABLE"); if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); if (chip->usb_psy) { rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_ADAPTER_CC_MODE, &pval); if (rc < 0) pr_err("Couldn't get PPS CC mode status rc=%d\n", rc); else is_cc_mode = pval.intval; } if (chip->cp_master_psy) { rc = power_supply_get_property(chip->cp_master_psy, POWER_SUPPLY_PROP_MIN_ICL, &pval); if (rc < 0) pr_err("Couldn't get MIN ICL threshold rc=%d\n", rc); else fcc_thr_ua = is_cc_mode ? (3 * pval.intval) : (4 * pval.intval); } if (chip->fcc_main_votable) main_fcc_ua = get_effective_result_locked(chip->fcc_main_votable); if (main_fcc_ua < 0) main_fcc_ua = 0; cp_fcc_ua = total_fcc_ua - main_fcc_ua; if (cp_fcc_ua > 0) { if (chip->cp_slave_psy && chip->cp_slave_disable_votable) { /* * With VPH output configuration ILIM is configured * independent of battery FCC, disable CP here if FCC/2 * falls below MIN_ICL supported by CP. * Disable Slave CP if FCC share * falls below threshold. */ vote(chip->cp_slave_disable_votable, FCC_VOTER, (cp_fcc_ua < fcc_thr_ua), 0); } if (chip->cp_disable_votable) { /* * Disable Master CP if FCC share * falls below 2 * min ICL threshold. */ if ((total_fcc_ua / 2) < pval.intval) vote(chip->cp_disable_votable, FCC_VOTER, true, 0); else vote(chip->cp_disable_votable, FCC_VOTER, false, 0); (cp_fcc_ua < (2 * pval.intval)), 0); } } Loading @@ -848,10 +895,6 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, rerun_election(chip->pl_disable_votable); /* When FCC changes, trigger psy changed event for CC mode */ if (!chip->cp_master_psy) chip->cp_master_psy = power_supply_get_by_name("charge_pump_master"); if (chip->cp_master_psy) power_supply_changed(chip->cp_master_psy); Loading drivers/power/supply/qcom/smb1390-charger-psy.c +56 −7 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ struct smb1390 { struct votable *cp_awake_votable; struct votable *slave_disable_votable; struct votable *usb_icl_votable; struct votable *fcc_main_votable; /* power supplies */ struct power_supply *cps_psy; Loading Loading @@ -876,13 +877,38 @@ static int smb1390_slave_disable_vote_cb(struct votable *votable, void *data, int disable, const char *client) { struct smb1390 *chip = data; int rc; int rc = 0, ilim_ua = 0; rc = smb1390_masked_write(chip, CORE_CONTROL1_REG, CMD_EN_SL_BIT, disable ? 0 : CMD_EN_SL_BIT); if (rc < 0) if (rc < 0) { pr_err("Couldn't %s slave rc=%d\n", disable ? "disable" : "enable", rc); return rc; } /* Re-distribute ILIM to Master CP when Slave is disabled */ if (disable && (chip->ilim_votable)) { ilim_ua = get_effective_result_locked(chip->ilim_votable); if (ilim_ua > MAX_ILIM_UA) ilim_ua = MAX_ILIM_UA; if (ilim_ua < 500000) { smb1390_dbg(chip, PR_INFO, "ILIM too low, not re-distributing, ilim=%duA\n", ilim_ua); return 0; } rc = smb1390_set_ilim(chip, DIV_ROUND_CLOSEST(ilim_ua - 500000, 100000)); if (rc < 0) { pr_err("Failed to set ILIM, rc=%d\n", rc); return rc; } smb1390_dbg(chip, PR_INFO, "Master ILIM set to %duA\n", ilim_ua); } return rc; } Loading @@ -893,6 +919,7 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, struct smb1390 *chip = data; union power_supply_propval pval = {0, }; int rc = 0; bool slave_enabled = false; if (!is_psy_voter_available(chip) || chip->suspended) return -EAGAIN; Loading @@ -911,7 +938,17 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, ilim_uA); vote(chip->disable_votable, ILIM_VOTER, true, 0); } else { /* Disable Slave CP if ILIM is < 2 * min ILIM */ if (is_cps_available(chip)) { vote(chip->slave_disable_votable, ILIM_VOTER, (ilim_uA < (2 * chip->min_ilim_ua)), 0); if (get_effective_result(chip->slave_disable_votable) == 0) slave_enabled = true; } if (slave_enabled) { ilim_uA /= 2; pval.intval = DIV_ROUND_CLOSEST(ilim_uA - 500000, 100000); Loading @@ -930,7 +967,8 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, return rc; } smb1390_dbg(chip, PR_INFO, "ILIM set to %duA\n", ilim_uA); smb1390_dbg(chip, PR_INFO, "ILIM set to %duA slave_enabled%d\n", ilim_uA, slave_enabled); vote(chip->disable_votable, ILIM_VOTER, false, 0); } Loading Loading @@ -1167,11 +1205,20 @@ static void smb1390_taper_work(struct work_struct *work) { struct smb1390 *chip = container_of(work, struct smb1390, taper_work); union power_supply_propval pval = {0, }; int rc, fcc_uA, delta_fcc_uA; int rc, fcc_uA, delta_fcc_uA, main_fcc_ua = 0; if (!is_psy_voter_available(chip)) goto out; if (!chip->fcc_main_votable) chip->fcc_main_votable = find_votable("FCC_MAIN"); if (chip->fcc_main_votable) main_fcc_ua = get_effective_result(chip->fcc_main_votable); if (main_fcc_ua < 0) main_fcc_ua = 0; chip->taper_entry_fv = get_effective_result(chip->fv_votable); while (true) { rc = power_supply_get_property(chip->batt_psy, Loading Loading @@ -1200,14 +1247,15 @@ static void smb1390_taper_work(struct work_struct *work) smb1390_dbg(chip, PR_INFO, "taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); rc = smb1390_validate_slave_chg_taper(chip, fcc_uA); rc = smb1390_validate_slave_chg_taper(chip, (fcc_uA - main_fcc_ua)); if (rc < 0) { pr_err("Couldn't Disable slave in Taper, rc=%d\n", rc); goto out; } if (fcc_uA < (chip->min_ilim_ua * 2)) { if ((fcc_uA - main_fcc_ua) < (chip->min_ilim_ua * 2)) { vote(chip->disable_votable, TAPER_END_VOTER, true, 0); /* Loading Loading @@ -1482,7 +1530,8 @@ static int smb1390_parse_dt(struct smb1390 *chip) of_property_read_u32(chip->dev->of_node, "qcom,parallel-input-mode", &chip->pl_input_mode); chip->cp_slave_thr_taper_ua = chip->min_ilim_ua * 3; chip->cp_slave_thr_taper_ua = smb1390_is_adapter_cc_mode(chip) ? (3 * chip->min_ilim_ua) : (4 * chip->min_ilim_ua); of_property_read_u32(chip->dev->of_node, "qcom,cp-slave-thr-taper-ua", &chip->cp_slave_thr_taper_ua); Loading Loading
drivers/power/supply/qcom/battery.c +60 −17 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ struct pl_data { struct votable *cp_ilim_votable; struct votable *cp_disable_votable; struct votable *fcc_main_votable; struct votable *cp_slave_disable_votable; struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct work_struct pl_taper_work; Loading @@ -74,6 +75,7 @@ struct pl_data { struct power_supply *usb_psy; struct power_supply *dc_psy; struct power_supply *cp_master_psy; struct power_supply *cp_slave_psy; int charge_type; int total_settled_ua; int pl_settled_ua; Loading Loading @@ -803,7 +805,9 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, { struct pl_data *chip = data; int master_fcc_ua = total_fcc_ua, slave_fcc_ua = 0; int main_fcc_ua = 0, cp_fcc_ua = 0, fcc_thr_ua = 0, rc; union power_supply_propval pval = {0, }; bool is_cc_mode = false; if (total_fcc_ua < 0) return 0; Loading @@ -814,22 +818,65 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, if (!chip->cp_disable_votable) chip->cp_disable_votable = find_votable("CP_DISABLE"); if (chip->cp_disable_votable) { if (cp_get_parallel_mode(chip, PARALLEL_OUTPUT_MODE) == POWER_SUPPLY_PL_OUTPUT_VPH) { power_supply_get_property(chip->cp_master_psy, if (!chip->cp_master_psy) chip->cp_master_psy = power_supply_get_by_name("charge_pump_master"); if (!chip->cp_slave_psy) chip->cp_slave_psy = power_supply_get_by_name("cp_slave"); if (!chip->cp_slave_disable_votable) chip->cp_slave_disable_votable = find_votable("CP_SLAVE_DISABLE"); if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); if (chip->usb_psy) { rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_ADAPTER_CC_MODE, &pval); if (rc < 0) pr_err("Couldn't get PPS CC mode status rc=%d\n", rc); else is_cc_mode = pval.intval; } if (chip->cp_master_psy) { rc = power_supply_get_property(chip->cp_master_psy, POWER_SUPPLY_PROP_MIN_ICL, &pval); if (rc < 0) pr_err("Couldn't get MIN ICL threshold rc=%d\n", rc); else fcc_thr_ua = is_cc_mode ? (3 * pval.intval) : (4 * pval.intval); } if (chip->fcc_main_votable) main_fcc_ua = get_effective_result_locked(chip->fcc_main_votable); if (main_fcc_ua < 0) main_fcc_ua = 0; cp_fcc_ua = total_fcc_ua - main_fcc_ua; if (cp_fcc_ua > 0) { if (chip->cp_slave_psy && chip->cp_slave_disable_votable) { /* * With VPH output configuration ILIM is configured * independent of battery FCC, disable CP here if FCC/2 * falls below MIN_ICL supported by CP. * Disable Slave CP if FCC share * falls below threshold. */ vote(chip->cp_slave_disable_votable, FCC_VOTER, (cp_fcc_ua < fcc_thr_ua), 0); } if (chip->cp_disable_votable) { /* * Disable Master CP if FCC share * falls below 2 * min ICL threshold. */ if ((total_fcc_ua / 2) < pval.intval) vote(chip->cp_disable_votable, FCC_VOTER, true, 0); else vote(chip->cp_disable_votable, FCC_VOTER, false, 0); (cp_fcc_ua < (2 * pval.intval)), 0); } } Loading @@ -848,10 +895,6 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, rerun_election(chip->pl_disable_votable); /* When FCC changes, trigger psy changed event for CC mode */ if (!chip->cp_master_psy) chip->cp_master_psy = power_supply_get_by_name("charge_pump_master"); if (chip->cp_master_psy) power_supply_changed(chip->cp_master_psy); Loading
drivers/power/supply/qcom/smb1390-charger-psy.c +56 −7 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ struct smb1390 { struct votable *cp_awake_votable; struct votable *slave_disable_votable; struct votable *usb_icl_votable; struct votable *fcc_main_votable; /* power supplies */ struct power_supply *cps_psy; Loading Loading @@ -876,13 +877,38 @@ static int smb1390_slave_disable_vote_cb(struct votable *votable, void *data, int disable, const char *client) { struct smb1390 *chip = data; int rc; int rc = 0, ilim_ua = 0; rc = smb1390_masked_write(chip, CORE_CONTROL1_REG, CMD_EN_SL_BIT, disable ? 0 : CMD_EN_SL_BIT); if (rc < 0) if (rc < 0) { pr_err("Couldn't %s slave rc=%d\n", disable ? "disable" : "enable", rc); return rc; } /* Re-distribute ILIM to Master CP when Slave is disabled */ if (disable && (chip->ilim_votable)) { ilim_ua = get_effective_result_locked(chip->ilim_votable); if (ilim_ua > MAX_ILIM_UA) ilim_ua = MAX_ILIM_UA; if (ilim_ua < 500000) { smb1390_dbg(chip, PR_INFO, "ILIM too low, not re-distributing, ilim=%duA\n", ilim_ua); return 0; } rc = smb1390_set_ilim(chip, DIV_ROUND_CLOSEST(ilim_ua - 500000, 100000)); if (rc < 0) { pr_err("Failed to set ILIM, rc=%d\n", rc); return rc; } smb1390_dbg(chip, PR_INFO, "Master ILIM set to %duA\n", ilim_ua); } return rc; } Loading @@ -893,6 +919,7 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, struct smb1390 *chip = data; union power_supply_propval pval = {0, }; int rc = 0; bool slave_enabled = false; if (!is_psy_voter_available(chip) || chip->suspended) return -EAGAIN; Loading @@ -911,7 +938,17 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, ilim_uA); vote(chip->disable_votable, ILIM_VOTER, true, 0); } else { /* Disable Slave CP if ILIM is < 2 * min ILIM */ if (is_cps_available(chip)) { vote(chip->slave_disable_votable, ILIM_VOTER, (ilim_uA < (2 * chip->min_ilim_ua)), 0); if (get_effective_result(chip->slave_disable_votable) == 0) slave_enabled = true; } if (slave_enabled) { ilim_uA /= 2; pval.intval = DIV_ROUND_CLOSEST(ilim_uA - 500000, 100000); Loading @@ -930,7 +967,8 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, return rc; } smb1390_dbg(chip, PR_INFO, "ILIM set to %duA\n", ilim_uA); smb1390_dbg(chip, PR_INFO, "ILIM set to %duA slave_enabled%d\n", ilim_uA, slave_enabled); vote(chip->disable_votable, ILIM_VOTER, false, 0); } Loading Loading @@ -1167,11 +1205,20 @@ static void smb1390_taper_work(struct work_struct *work) { struct smb1390 *chip = container_of(work, struct smb1390, taper_work); union power_supply_propval pval = {0, }; int rc, fcc_uA, delta_fcc_uA; int rc, fcc_uA, delta_fcc_uA, main_fcc_ua = 0; if (!is_psy_voter_available(chip)) goto out; if (!chip->fcc_main_votable) chip->fcc_main_votable = find_votable("FCC_MAIN"); if (chip->fcc_main_votable) main_fcc_ua = get_effective_result(chip->fcc_main_votable); if (main_fcc_ua < 0) main_fcc_ua = 0; chip->taper_entry_fv = get_effective_result(chip->fv_votable); while (true) { rc = power_supply_get_property(chip->batt_psy, Loading Loading @@ -1200,14 +1247,15 @@ static void smb1390_taper_work(struct work_struct *work) smb1390_dbg(chip, PR_INFO, "taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); rc = smb1390_validate_slave_chg_taper(chip, fcc_uA); rc = smb1390_validate_slave_chg_taper(chip, (fcc_uA - main_fcc_ua)); if (rc < 0) { pr_err("Couldn't Disable slave in Taper, rc=%d\n", rc); goto out; } if (fcc_uA < (chip->min_ilim_ua * 2)) { if ((fcc_uA - main_fcc_ua) < (chip->min_ilim_ua * 2)) { vote(chip->disable_votable, TAPER_END_VOTER, true, 0); /* Loading Loading @@ -1482,7 +1530,8 @@ static int smb1390_parse_dt(struct smb1390 *chip) of_property_read_u32(chip->dev->of_node, "qcom,parallel-input-mode", &chip->pl_input_mode); chip->cp_slave_thr_taper_ua = chip->min_ilim_ua * 3; chip->cp_slave_thr_taper_ua = smb1390_is_adapter_cc_mode(chip) ? (3 * chip->min_ilim_ua) : (4 * chip->min_ilim_ua); of_property_read_u32(chip->dev->of_node, "qcom,cp-slave-thr-taper-ua", &chip->cp_slave_thr_taper_ua); Loading