Loading drivers/power/supply/qcom/battery.c +56 −71 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ #define ICL_LIMIT_VOTER "ICL_LIMIT_VOTER" #define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER" #define FCC_VOTER "FCC_VOTER" #define MAIN_FCC_VOTER "MAIN_FCC_VOTER" struct pl_data { int pl_mode; Loading @@ -67,6 +68,7 @@ struct pl_data { struct votable *pl_enable_votable_indirect; struct votable *cp_ilim_votable; struct votable *cp_disable_votable; struct votable *fcc_main_votable; struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct work_struct pl_taper_work; Loading Loading @@ -560,17 +562,9 @@ static void get_fcc_stepper_params(struct pl_data *chip, int main_fcc_ua, int parallel_fcc_ua) { union power_supply_propval pval = {0, }; int rc; /* Read current FCC of main charger */ rc = power_supply_get_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Couldn't get main charger current fcc, rc=%d\n", rc); return; } chip->main_fcc_ua = pval.intval; chip->main_fcc_ua = get_effective_result(chip->fcc_main_votable); chip->main_step_fcc_dir = (main_fcc_ua > pval.intval) ? STEP_UP : STEP_DOWN; chip->main_step_fcc_count = abs((main_fcc_ua - pval.intval) / Loading Loading @@ -690,6 +684,31 @@ static void pl_taper_work(struct work_struct *work) vote(chip->pl_awake_votable, TAPER_END_VOTER, false, 0); } static bool is_main_available(struct pl_data *chip) { if (chip->main_psy) return true; chip->main_psy = power_supply_get_by_name("main"); return !!chip->main_psy; } static int pl_fcc_main_vote_callback(struct votable *votable, void *data, int fcc_main_ua, const char *client) { struct pl_data *chip = data; union power_supply_propval pval = {0,}; if (!is_main_available(chip)) return 0; pval.intval = fcc_main_ua; return power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); } static int pl_fcc_vote_callback(struct votable *votable, void *data, int total_fcc_ua, const char *client) { Loading Loading @@ -738,6 +757,13 @@ 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); return 0; } Loading Loading @@ -794,14 +820,7 @@ static void fcc_stepper_work(struct work_struct *work) } main_fcc = get_effective_result_locked(chip->fcc_votable); pval.intval = main_fcc; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Couldn't set main charger fcc, rc=%d\n", rc); goto out; } vote(chip->fcc_main_votable, FCC_STEPPER_VOTER, true, main_fcc); goto stepper_exit; } Loading Loading @@ -862,22 +881,10 @@ static void fcc_stepper_work(struct work_struct *work) } /* Set main FCC */ pval.intval = main_fcc; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Couldn't set main charger fcc, rc=%d\n", rc); goto out; } vote(chip->fcc_main_votable, FCC_STEPPER_VOTER, true, main_fcc); } else { /* Set main FCC */ pval.intval = main_fcc; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Couldn't set main charger fcc, rc=%d\n", rc); goto out; } vote(chip->fcc_main_votable, FCC_STEPPER_VOTER, true, main_fcc); /* Set parallel FCC */ if (chip->pl_psy) { Loading Loading @@ -1063,16 +1070,6 @@ static void pl_awake_work(struct work_struct *work) vote(chip->pl_awake_votable, PL_VOTER, false, 0); } static bool is_main_available(struct pl_data *chip) { if (chip->main_psy) return true; chip->main_psy = power_supply_get_by_name("main"); return !!chip->main_psy; } static bool is_batt_available(struct pl_data *chip) { if (!chip->batt_psy) Loading Loading @@ -1184,16 +1181,8 @@ static int pl_disable_vote_callback(struct votable *votable, * Set slave ICL then main FCC. */ if (slave_fcc_ua > chip->slave_fcc_ua) { pval.intval = master_fcc_ua; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Could not set main fcc, rc=%d\n", rc); return rc; } vote(chip->fcc_main_votable, MAIN_FCC_VOTER, true, master_fcc_ua); pval.intval = slave_fcc_ua; rc = power_supply_set_property(chip->pl_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, Loading @@ -1217,16 +1206,8 @@ static int pl_disable_vote_callback(struct votable *votable, } chip->slave_fcc_ua = slave_fcc_ua; pval.intval = master_fcc_ua; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Could not set main fcc, rc=%d\n", rc); return rc; } vote(chip->fcc_main_votable, MAIN_FCC_VOTER, true, master_fcc_ua); } /* Loading Loading @@ -1288,15 +1269,8 @@ static int pl_disable_vote_callback(struct votable *votable, } /* main psy gets all share */ pval.intval = total_fcc_ua; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Could not set main fcc, rc=%d\n", rc); return rc; } vote(chip->fcc_main_votable, MAIN_FCC_VOTER, true, total_fcc_ua); cp_configure_ilim(chip, FCC_VOTER, total_fcc_ua / 2); /* reset parallel FCC */ Loading Loading @@ -1711,13 +1685,22 @@ int qcom_batt_init(int smb_version) if (!chip->pl_ws) goto cleanup; chip->fcc_main_votable = create_votable("FCC_MAIN", VOTE_MIN, pl_fcc_main_vote_callback, chip); if (IS_ERR(chip->fcc_main_votable)) { rc = PTR_ERR(chip->fcc_main_votable); chip->fcc_main_votable = NULL; goto release_wakeup_source; } chip->fcc_votable = create_votable("FCC", VOTE_MIN, pl_fcc_vote_callback, chip); if (IS_ERR(chip->fcc_votable)) { rc = PTR_ERR(chip->fcc_votable); chip->fcc_votable = NULL; goto release_wakeup_source; goto destroy_votable; } chip->fv_votable = create_votable("FV", VOTE_MIN, Loading Loading @@ -1813,6 +1796,7 @@ int qcom_batt_init(int smb_version) destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); destroy_votable(chip->fcc_main_votable); destroy_votable(chip->usb_icl_votable); release_wakeup_source: wakeup_source_unregister(chip->pl_ws); Loading Loading @@ -1840,6 +1824,7 @@ void qcom_batt_deinit(void) destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); destroy_votable(chip->fcc_main_votable); wakeup_source_unregister(chip->pl_ws); the_chip = NULL; kfree(chip); Loading drivers/power/supply/qcom/qpnp-smb5.c +72 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,11 @@ enum { SMB_THERM, }; static const struct clamp_config clamp_levels[] = { { {0x11C6, 0x11F9, 0x13F1}, {0x60, 0x2E, 0x90} }, { {0x11C6, 0x11F9, 0x13F1}, {0x60, 0x2B, 0x9C} }, }; #define PMI632_MAX_ICL_UA 3000000 #define PM6150_MAX_FCC_UA 3000000 static int smb5_chg_config_init(struct smb5 *chip) Loading Loading @@ -612,6 +617,33 @@ static int smb5_parse_dt(struct smb5 *chip) return 0; } static int smb5_set_prop_comp_clamp_level(struct smb_charger *chg, const union power_supply_propval *val) { int rc = 0, i; struct clamp_config clamp_config; enum comp_clamp_levels level; level = val->intval; if (level >= MAX_CLAMP_LEVEL) { pr_err("Invalid comp clamp level=%d\n", val->intval); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(clamp_config.reg); i++) { rc = smblib_write(chg, clamp_levels[level].reg[i], clamp_levels[level].val[i]); if (rc < 0) dev_err(chg->dev, "Failed to configure comp clamp settings for reg=0x%04x rc=%d\n", clamp_levels[level].reg[i], rc); } chg->comp_clamp_level = val->intval; return rc; } /************************ * USB PSY REGISTRATION * ************************/ Loading Loading @@ -643,6 +675,7 @@ static enum power_supply_property smb5_usb_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT, POWER_SUPPLY_PROP_SMB_EN_MODE, POWER_SUPPLY_PROP_SMB_EN_REASON, POWER_SUPPLY_PROP_ADAPTER_CC_MODE, POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_MOISTURE_DETECTED, POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED, Loading Loading @@ -820,6 +853,9 @@ static int smb5_usb_get_prop(struct power_supply *psy, val->intval = get_client_vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER); break; case POWER_SUPPLY_PROP_ADAPTER_CC_MODE: val->intval = chg->adapter_cc_mode; break; default: pr_err("get prop %d is not supported in usb\n", psp); rc = -EINVAL; Loading Loading @@ -906,6 +942,9 @@ static int smb5_usb_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT: smblib_set_prop_usb_voltage_max_limit(chg, val); break; case POWER_SUPPLY_PROP_ADAPTER_CC_MODE: chg->adapter_cc_mode = val->intval; break; default: pr_err("set prop %d is not supported\n", psp); rc = -EINVAL; Loading @@ -923,6 +962,7 @@ static int smb5_usb_prop_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: case POWER_SUPPLY_PROP_THERM_ICL_LIMIT: case POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT: case POWER_SUPPLY_PROP_ADAPTER_CC_MODE: return 1; default: break; Loading Loading @@ -1074,6 +1114,9 @@ static enum power_supply_property smb5_usb_main_props[] = { POWER_SUPPLY_PROP_TOGGLE_STAT, POWER_SUPPLY_PROP_MAIN_FCC_MAX, POWER_SUPPLY_PROP_IRQ_STATUS, POWER_SUPPLY_PROP_FORCE_MAIN_FCC, POWER_SUPPLY_PROP_FORCE_MAIN_ICL, POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL, }; static int smb5_usb_main_get_prop(struct power_supply *psy, Loading Loading @@ -1122,6 +1165,17 @@ static int smb5_usb_main_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_IRQ_STATUS: rc = smblib_get_irq_status(chg, val); break; case POWER_SUPPLY_PROP_FORCE_MAIN_FCC: rc = smblib_get_charge_param(chg, &chg->param.fcc, &val->intval); break; case POWER_SUPPLY_PROP_FORCE_MAIN_ICL: rc = smblib_get_charge_param(chg, &chg->param.usb_icl, &val->intval); break; case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL: val->intval = chg->comp_clamp_level; break; default: pr_debug("get prop %d is not supported in usb-main\n", psp); rc = -EINVAL; Loading Loading @@ -1192,6 +1246,17 @@ static int smb5_usb_main_set_prop(struct power_supply *psy, chg->main_fcc_max = val->intval; rerun_election(chg->fcc_votable); break; case POWER_SUPPLY_PROP_FORCE_MAIN_FCC: vote_override(chg->fcc_main_votable, CC_MODE_VOTER, (val->intval < 0) ? false : true, val->intval); break; case POWER_SUPPLY_PROP_FORCE_MAIN_ICL: vote_override(chg->usb_icl_votable, CC_MODE_VOTER, (val->intval < 0) ? false : true, val->intval); break; case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL: rc = smb5_set_prop_comp_clamp_level(chg, val); break; default: pr_err("set prop %d is not supported\n", psp); rc = -EINVAL; Loading @@ -1209,6 +1274,9 @@ static int smb5_usb_main_prop_is_writeable(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_TOGGLE_STAT: case POWER_SUPPLY_PROP_MAIN_FCC_MAX: case POWER_SUPPLY_PROP_FORCE_MAIN_FCC: case POWER_SUPPLY_PROP_FORCE_MAIN_ICL: case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL: rc = 1; break; default: Loading Loading @@ -1399,6 +1467,7 @@ static enum power_supply_property smb5_batt_props[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_QNOVO, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TECHNOLOGY, Loading Loading @@ -1493,6 +1562,9 @@ static int smb5_batt_get_prop(struct power_supply *psy, val->intval = get_client_vote(chg->fcc_votable, BATT_PROFILE_VOTER); break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: val->intval = get_effective_result(chg->fcc_votable); break; case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: rc = smblib_get_prop_batt_iterm(chg, val); break; Loading drivers/power/supply/qcom/smb1390-charger-psy.c +117 −9 Original line number Diff line number Diff line Loading @@ -103,11 +103,15 @@ #define SWITCHER_TOGGLE_VOTER "SWITCHER_TOGGLE_VOTER" #define SOC_LEVEL_VOTER "SOC_LEVEL_VOTER" #define HW_DISABLE_VOTER "HW_DISABLE_VOTER" #define CC_MODE_VOTER "CC_MODE_VOTER" #define CP_MASTER 0 #define CP_SLAVE 1 #define THERMAL_SUSPEND_DECIDEGC 1400 #define MAX_ILIM_UA 3200000 #define MAX_ILIM_DUAL_CP_UA 6400000 #define CC_MODE_TAPER_DELTA_UA 200000 #define DEFAULT_TAPER_DELTA_UA 100000 #define smb1390_dbg(chip, reason, fmt, ...) \ do { \ Loading Loading @@ -202,6 +206,8 @@ struct smb1390 { u32 pl_output_mode; u32 cp_role; enum isns_mode current_capability; bool batt_soc_validated; int cp_slave_thr_taper_ua; }; struct smb_cfg { Loading Loading @@ -356,6 +362,28 @@ static int smb1390_isns_mode_control(struct smb1390 *chip, enum isns_mode mode) return rc; } static bool smb1390_is_adapter_cc_mode(struct smb1390 *chip) { int rc; union power_supply_propval pval = {0, }; if (!chip->usb_psy) { chip->usb_psy = power_supply_get_by_name("usb"); if (!chip->usb_psy) return false; } 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); return false; } return pval.intval; } static bool is_cps_available(struct smb1390 *chip) { if (!chip->cps_psy) Loading Loading @@ -697,6 +725,30 @@ static int smb1390_get_isns_slave(struct smb1390 *chip, return rc; } static int smb1390_get_cp_ilim(struct smb1390 *chip, union power_supply_propval *val) { int rc = 0, status; if (is_cps_available(chip)) { if (!chip->ilim_votable) { chip->ilim_votable = find_votable("CP_ILIM"); if (!chip->ilim_votable) return -EINVAL; } val->intval = get_effective_result(chip->ilim_votable); } else { rc = smb1390_read(chip, CORE_FTRIM_ILIM_REG, &status); if (!rc) val->intval = ((status & CFG_ILIM_MASK) * 100000) + 500000; } return rc; } static int smb1390_is_batt_soc_valid(struct smb1390 *chip) { int rc; Loading Loading @@ -825,7 +877,8 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, return -EINVAL; } ilim_uA = min(ilim_uA, MAX_ILIM_UA); ilim_uA = min(ilim_uA, (is_cps_available(chip) ? MAX_ILIM_DUAL_CP_UA : MAX_ILIM_UA)); /* ILIM less than min_ilim_ua, disable charging */ if (ilim_uA < chip->min_ilim_ua) { smb1390_dbg(chip, PR_INFO, "ILIM %duA is too low to allow charging\n", Loading Loading @@ -926,6 +979,7 @@ static void smb1390_status_change_work(struct work_struct *work) if (!is_psy_voter_available(chip)) goto out; if (!smb1390_is_adapter_cc_mode(chip)) vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); Loading @@ -944,7 +998,14 @@ static void smb1390_status_change_work(struct work_struct *work) goto out; } /* Check for SOC threshold only once before enabling CP */ vote(chip->disable_votable, SRC_VOTER, false, 0); if (!chip->batt_soc_validated) { vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); chip->batt_soc_validated = true; } if (pval.intval == POWER_SUPPLY_CP_WIRELESS) { vote(chip->ilim_votable, ICL_VOTER, false, 0); Loading Loading @@ -1014,10 +1075,12 @@ static void smb1390_status_change_work(struct work_struct *work) } } } else { chip->batt_soc_validated = false; 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); vote_override(chip->ilim_votable, CC_MODE_VOTER, false, 0); } out: Loading @@ -1025,11 +1088,39 @@ static void smb1390_status_change_work(struct work_struct *work) chip->status_change_running = false; } static int smb1390_validate_slave_chg_taper(struct smb1390 *chip, int fcc_uA) { int rc = 0; u8 mask; /* * In Collapse mode, while in Taper, Disable the slave SMB1390 * when FCC drops below a specified threshold. */ if (fcc_uA < (chip->cp_slave_thr_taper_ua) && is_cps_available(chip)) { mask = CMD_EN_SWITCHER_BIT | CMD_EN_SL_BIT; rc = smb1390_masked_write(chip, CORE_CONTROL1_REG, mask, CMD_EN_SWITCHER_BIT); if (rc < 0) return rc; /* * Set ILIM of master SMB1390 to Max value = 3.2A once slave is * disabled to prevent ILIM irq storm. */ smb1390_dbg(chip, PR_INFO, "Set Master ILIM to MAX, post Slave disable in taper, fcc=%d\n", fcc_uA); vote_override(chip->ilim_votable, CC_MODE_VOTER, true, MAX_ILIM_DUAL_CP_UA); } return rc; } 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; int rc, fcc_uA, delta_fcc_uA; if (!is_psy_voter_available(chip)) goto out; Loading @@ -1053,11 +1144,21 @@ static void smb1390_taper_work(struct work_struct *work) } if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { delta_fcc_uA = (smb1390_is_adapter_cc_mode(chip) ? CC_MODE_TAPER_DELTA_UA : DEFAULT_TAPER_DELTA_UA); fcc_uA = get_effective_result(chip->fcc_votable) - 100000; - delta_fcc_uA; 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); 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)) { vote(chip->disable_votable, TAPER_END_VOTER, Loading Loading @@ -1174,10 +1275,7 @@ static int smb1390_get_prop(struct power_supply *psy, val->intval |= status; break; case POWER_SUPPLY_PROP_CP_ILIM: rc = smb1390_read(chip, CORE_FTRIM_ILIM_REG, &status); if (!rc) val->intval = ((status & CFG_ILIM_MASK) * 100000) + 500000; rc = smb1390_get_cp_ilim(chip, val); break; case POWER_SUPPLY_PROP_CHIP_VERSION: val->intval = chip->pmic_rev_id->rev4; Loading Loading @@ -1215,6 +1313,11 @@ static int smb1390_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CP_IRQ_STATUS: chip->irq_status = val->intval; break; case POWER_SUPPLY_PROP_CP_ILIM: if (chip->ilim_votable) vote_override(chip->ilim_votable, CC_MODE_VOTER, true, val->intval); break; default: smb1390_dbg(chip, PR_MISC, "charge pump power supply set prop %d not supported\n", prop); Loading @@ -1233,6 +1336,7 @@ static int smb1390_prop_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_CP_IRQ_STATUS: case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX: case POWER_SUPPLY_PROP_CURRENT_CAPABILITY: case POWER_SUPPLY_PROP_CP_ILIM: return 1; default: break; Loading Loading @@ -1307,6 +1411,10 @@ static int smb1390_parse_dt(struct smb1390 *chip) chip->pl_output_mode = POWER_SUPPLY_PL_OUTPUT_VPH; of_property_read_u32(chip->dev->of_node, "qcom,parallel-output-mode", &chip->pl_output_mode); chip->cp_slave_thr_taper_ua = chip->min_ilim_ua * 3; of_property_read_u32(chip->dev->of_node, "qcom,cp-slave-thr-taper-ua", &chip->cp_slave_thr_taper_ua); return 0; } Loading drivers/power/supply/qcom/smb5-lib.c +13 −0 Original line number Diff line number Diff line Loading @@ -5483,6 +5483,12 @@ static void typec_src_removal(struct smb_charger *chg) chg->voltage_max_uv = MICRO_5V; chg->usbin_forced_max_uv = 0; /* Reset CC mode votes */ vote(chg->fcc_main_votable, MAIN_FCC_VOTER, false, 0); chg->adapter_cc_mode = 0; vote_override(chg->fcc_votable, CC_MODE_VOTER, false, 0); vote_override(chg->usb_icl_votable, CC_MODE_VOTER, false, 0); /* write back the default FLOAT charger configuration */ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, (u8)FLOAT_OPTIONS_MASK, chg->float_cfg); Loading Loading @@ -6786,6 +6792,13 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } chg->fcc_main_votable = find_votable("FCC_MAIN"); if (chg->fcc_main_votable == NULL) { rc = -EINVAL; smblib_err(chg, "Couldn't find FCC Main votable rc=%d\n", rc); return rc; } chg->fv_votable = find_votable("FV"); if (chg->fv_votable == NULL) { rc = -EINVAL; Loading drivers/power/supply/qcom/smb5-lib.h +18 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ enum print_reason { #define CHARGER_TYPE_VOTER "CHARGER_TYPE_VOTER" #define HDC_IRQ_VOTER "HDC_IRQ_VOTER" #define DETACH_DETECT_VOTER "DETACH_DETECT_VOTER" #define CC_MODE_VOTER "CC_MODE_VOTER" #define MAIN_FCC_VOTER "MAIN_FCC_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -229,6 +231,17 @@ enum chg_term_config_src { ITERM_SRC_ANALOG }; enum comp_clamp_levels { CLAMP_LEVEL_DEFAULT = 0, CLAMP_LEVEL_1, MAX_CLAMP_LEVEL, }; struct clamp_config { u16 reg[3]; u16 val[3]; }; struct smb_irq_info { const char *name; const irq_handler_t handler; Loading Loading @@ -398,6 +411,9 @@ struct smb_charger { /* parallel charging */ struct parallel_params pl; /* CC Mode */ int adapter_cc_mode; /* regulators */ struct smb_regulator *vbus_vreg; struct smb_regulator *vconn_vreg; Loading @@ -406,6 +422,7 @@ struct smb_charger { /* votables */ struct votable *dc_suspend_votable; struct votable *fcc_votable; struct votable *fcc_main_votable; struct votable *fv_votable; struct votable *usb_icl_votable; struct votable *awake_votable; Loading Loading @@ -526,6 +543,7 @@ struct smb_charger { int dr_mode; int usbin_forced_max_uv; int init_thermal_ua; u32 comp_clamp_level; /* workaround flag */ u32 wa_flags; Loading Loading
drivers/power/supply/qcom/battery.c +56 −71 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ #define ICL_LIMIT_VOTER "ICL_LIMIT_VOTER" #define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER" #define FCC_VOTER "FCC_VOTER" #define MAIN_FCC_VOTER "MAIN_FCC_VOTER" struct pl_data { int pl_mode; Loading @@ -67,6 +68,7 @@ struct pl_data { struct votable *pl_enable_votable_indirect; struct votable *cp_ilim_votable; struct votable *cp_disable_votable; struct votable *fcc_main_votable; struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct work_struct pl_taper_work; Loading Loading @@ -560,17 +562,9 @@ static void get_fcc_stepper_params(struct pl_data *chip, int main_fcc_ua, int parallel_fcc_ua) { union power_supply_propval pval = {0, }; int rc; /* Read current FCC of main charger */ rc = power_supply_get_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Couldn't get main charger current fcc, rc=%d\n", rc); return; } chip->main_fcc_ua = pval.intval; chip->main_fcc_ua = get_effective_result(chip->fcc_main_votable); chip->main_step_fcc_dir = (main_fcc_ua > pval.intval) ? STEP_UP : STEP_DOWN; chip->main_step_fcc_count = abs((main_fcc_ua - pval.intval) / Loading Loading @@ -690,6 +684,31 @@ static void pl_taper_work(struct work_struct *work) vote(chip->pl_awake_votable, TAPER_END_VOTER, false, 0); } static bool is_main_available(struct pl_data *chip) { if (chip->main_psy) return true; chip->main_psy = power_supply_get_by_name("main"); return !!chip->main_psy; } static int pl_fcc_main_vote_callback(struct votable *votable, void *data, int fcc_main_ua, const char *client) { struct pl_data *chip = data; union power_supply_propval pval = {0,}; if (!is_main_available(chip)) return 0; pval.intval = fcc_main_ua; return power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); } static int pl_fcc_vote_callback(struct votable *votable, void *data, int total_fcc_ua, const char *client) { Loading Loading @@ -738,6 +757,13 @@ 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); return 0; } Loading Loading @@ -794,14 +820,7 @@ static void fcc_stepper_work(struct work_struct *work) } main_fcc = get_effective_result_locked(chip->fcc_votable); pval.intval = main_fcc; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Couldn't set main charger fcc, rc=%d\n", rc); goto out; } vote(chip->fcc_main_votable, FCC_STEPPER_VOTER, true, main_fcc); goto stepper_exit; } Loading Loading @@ -862,22 +881,10 @@ static void fcc_stepper_work(struct work_struct *work) } /* Set main FCC */ pval.intval = main_fcc; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Couldn't set main charger fcc, rc=%d\n", rc); goto out; } vote(chip->fcc_main_votable, FCC_STEPPER_VOTER, true, main_fcc); } else { /* Set main FCC */ pval.intval = main_fcc; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Couldn't set main charger fcc, rc=%d\n", rc); goto out; } vote(chip->fcc_main_votable, FCC_STEPPER_VOTER, true, main_fcc); /* Set parallel FCC */ if (chip->pl_psy) { Loading Loading @@ -1063,16 +1070,6 @@ static void pl_awake_work(struct work_struct *work) vote(chip->pl_awake_votable, PL_VOTER, false, 0); } static bool is_main_available(struct pl_data *chip) { if (chip->main_psy) return true; chip->main_psy = power_supply_get_by_name("main"); return !!chip->main_psy; } static bool is_batt_available(struct pl_data *chip) { if (!chip->batt_psy) Loading Loading @@ -1184,16 +1181,8 @@ static int pl_disable_vote_callback(struct votable *votable, * Set slave ICL then main FCC. */ if (slave_fcc_ua > chip->slave_fcc_ua) { pval.intval = master_fcc_ua; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Could not set main fcc, rc=%d\n", rc); return rc; } vote(chip->fcc_main_votable, MAIN_FCC_VOTER, true, master_fcc_ua); pval.intval = slave_fcc_ua; rc = power_supply_set_property(chip->pl_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, Loading @@ -1217,16 +1206,8 @@ static int pl_disable_vote_callback(struct votable *votable, } chip->slave_fcc_ua = slave_fcc_ua; pval.intval = master_fcc_ua; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Could not set main fcc, rc=%d\n", rc); return rc; } vote(chip->fcc_main_votable, MAIN_FCC_VOTER, true, master_fcc_ua); } /* Loading Loading @@ -1288,15 +1269,8 @@ static int pl_disable_vote_callback(struct votable *votable, } /* main psy gets all share */ pval.intval = total_fcc_ua; rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); if (rc < 0) { pr_err("Could not set main fcc, rc=%d\n", rc); return rc; } vote(chip->fcc_main_votable, MAIN_FCC_VOTER, true, total_fcc_ua); cp_configure_ilim(chip, FCC_VOTER, total_fcc_ua / 2); /* reset parallel FCC */ Loading Loading @@ -1711,13 +1685,22 @@ int qcom_batt_init(int smb_version) if (!chip->pl_ws) goto cleanup; chip->fcc_main_votable = create_votable("FCC_MAIN", VOTE_MIN, pl_fcc_main_vote_callback, chip); if (IS_ERR(chip->fcc_main_votable)) { rc = PTR_ERR(chip->fcc_main_votable); chip->fcc_main_votable = NULL; goto release_wakeup_source; } chip->fcc_votable = create_votable("FCC", VOTE_MIN, pl_fcc_vote_callback, chip); if (IS_ERR(chip->fcc_votable)) { rc = PTR_ERR(chip->fcc_votable); chip->fcc_votable = NULL; goto release_wakeup_source; goto destroy_votable; } chip->fv_votable = create_votable("FV", VOTE_MIN, Loading Loading @@ -1813,6 +1796,7 @@ int qcom_batt_init(int smb_version) destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); destroy_votable(chip->fcc_main_votable); destroy_votable(chip->usb_icl_votable); release_wakeup_source: wakeup_source_unregister(chip->pl_ws); Loading Loading @@ -1840,6 +1824,7 @@ void qcom_batt_deinit(void) destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); destroy_votable(chip->fcc_main_votable); wakeup_source_unregister(chip->pl_ws); the_chip = NULL; kfree(chip); Loading
drivers/power/supply/qcom/qpnp-smb5.c +72 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,11 @@ enum { SMB_THERM, }; static const struct clamp_config clamp_levels[] = { { {0x11C6, 0x11F9, 0x13F1}, {0x60, 0x2E, 0x90} }, { {0x11C6, 0x11F9, 0x13F1}, {0x60, 0x2B, 0x9C} }, }; #define PMI632_MAX_ICL_UA 3000000 #define PM6150_MAX_FCC_UA 3000000 static int smb5_chg_config_init(struct smb5 *chip) Loading Loading @@ -612,6 +617,33 @@ static int smb5_parse_dt(struct smb5 *chip) return 0; } static int smb5_set_prop_comp_clamp_level(struct smb_charger *chg, const union power_supply_propval *val) { int rc = 0, i; struct clamp_config clamp_config; enum comp_clamp_levels level; level = val->intval; if (level >= MAX_CLAMP_LEVEL) { pr_err("Invalid comp clamp level=%d\n", val->intval); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(clamp_config.reg); i++) { rc = smblib_write(chg, clamp_levels[level].reg[i], clamp_levels[level].val[i]); if (rc < 0) dev_err(chg->dev, "Failed to configure comp clamp settings for reg=0x%04x rc=%d\n", clamp_levels[level].reg[i], rc); } chg->comp_clamp_level = val->intval; return rc; } /************************ * USB PSY REGISTRATION * ************************/ Loading Loading @@ -643,6 +675,7 @@ static enum power_supply_property smb5_usb_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT, POWER_SUPPLY_PROP_SMB_EN_MODE, POWER_SUPPLY_PROP_SMB_EN_REASON, POWER_SUPPLY_PROP_ADAPTER_CC_MODE, POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_MOISTURE_DETECTED, POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED, Loading Loading @@ -820,6 +853,9 @@ static int smb5_usb_get_prop(struct power_supply *psy, val->intval = get_client_vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER); break; case POWER_SUPPLY_PROP_ADAPTER_CC_MODE: val->intval = chg->adapter_cc_mode; break; default: pr_err("get prop %d is not supported in usb\n", psp); rc = -EINVAL; Loading Loading @@ -906,6 +942,9 @@ static int smb5_usb_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT: smblib_set_prop_usb_voltage_max_limit(chg, val); break; case POWER_SUPPLY_PROP_ADAPTER_CC_MODE: chg->adapter_cc_mode = val->intval; break; default: pr_err("set prop %d is not supported\n", psp); rc = -EINVAL; Loading @@ -923,6 +962,7 @@ static int smb5_usb_prop_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: case POWER_SUPPLY_PROP_THERM_ICL_LIMIT: case POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT: case POWER_SUPPLY_PROP_ADAPTER_CC_MODE: return 1; default: break; Loading Loading @@ -1074,6 +1114,9 @@ static enum power_supply_property smb5_usb_main_props[] = { POWER_SUPPLY_PROP_TOGGLE_STAT, POWER_SUPPLY_PROP_MAIN_FCC_MAX, POWER_SUPPLY_PROP_IRQ_STATUS, POWER_SUPPLY_PROP_FORCE_MAIN_FCC, POWER_SUPPLY_PROP_FORCE_MAIN_ICL, POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL, }; static int smb5_usb_main_get_prop(struct power_supply *psy, Loading Loading @@ -1122,6 +1165,17 @@ static int smb5_usb_main_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_IRQ_STATUS: rc = smblib_get_irq_status(chg, val); break; case POWER_SUPPLY_PROP_FORCE_MAIN_FCC: rc = smblib_get_charge_param(chg, &chg->param.fcc, &val->intval); break; case POWER_SUPPLY_PROP_FORCE_MAIN_ICL: rc = smblib_get_charge_param(chg, &chg->param.usb_icl, &val->intval); break; case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL: val->intval = chg->comp_clamp_level; break; default: pr_debug("get prop %d is not supported in usb-main\n", psp); rc = -EINVAL; Loading Loading @@ -1192,6 +1246,17 @@ static int smb5_usb_main_set_prop(struct power_supply *psy, chg->main_fcc_max = val->intval; rerun_election(chg->fcc_votable); break; case POWER_SUPPLY_PROP_FORCE_MAIN_FCC: vote_override(chg->fcc_main_votable, CC_MODE_VOTER, (val->intval < 0) ? false : true, val->intval); break; case POWER_SUPPLY_PROP_FORCE_MAIN_ICL: vote_override(chg->usb_icl_votable, CC_MODE_VOTER, (val->intval < 0) ? false : true, val->intval); break; case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL: rc = smb5_set_prop_comp_clamp_level(chg, val); break; default: pr_err("set prop %d is not supported\n", psp); rc = -EINVAL; Loading @@ -1209,6 +1274,9 @@ static int smb5_usb_main_prop_is_writeable(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_TOGGLE_STAT: case POWER_SUPPLY_PROP_MAIN_FCC_MAX: case POWER_SUPPLY_PROP_FORCE_MAIN_FCC: case POWER_SUPPLY_PROP_FORCE_MAIN_ICL: case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL: rc = 1; break; default: Loading Loading @@ -1399,6 +1467,7 @@ static enum power_supply_property smb5_batt_props[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_QNOVO, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TECHNOLOGY, Loading Loading @@ -1493,6 +1562,9 @@ static int smb5_batt_get_prop(struct power_supply *psy, val->intval = get_client_vote(chg->fcc_votable, BATT_PROFILE_VOTER); break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: val->intval = get_effective_result(chg->fcc_votable); break; case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: rc = smblib_get_prop_batt_iterm(chg, val); break; Loading
drivers/power/supply/qcom/smb1390-charger-psy.c +117 −9 Original line number Diff line number Diff line Loading @@ -103,11 +103,15 @@ #define SWITCHER_TOGGLE_VOTER "SWITCHER_TOGGLE_VOTER" #define SOC_LEVEL_VOTER "SOC_LEVEL_VOTER" #define HW_DISABLE_VOTER "HW_DISABLE_VOTER" #define CC_MODE_VOTER "CC_MODE_VOTER" #define CP_MASTER 0 #define CP_SLAVE 1 #define THERMAL_SUSPEND_DECIDEGC 1400 #define MAX_ILIM_UA 3200000 #define MAX_ILIM_DUAL_CP_UA 6400000 #define CC_MODE_TAPER_DELTA_UA 200000 #define DEFAULT_TAPER_DELTA_UA 100000 #define smb1390_dbg(chip, reason, fmt, ...) \ do { \ Loading Loading @@ -202,6 +206,8 @@ struct smb1390 { u32 pl_output_mode; u32 cp_role; enum isns_mode current_capability; bool batt_soc_validated; int cp_slave_thr_taper_ua; }; struct smb_cfg { Loading Loading @@ -356,6 +362,28 @@ static int smb1390_isns_mode_control(struct smb1390 *chip, enum isns_mode mode) return rc; } static bool smb1390_is_adapter_cc_mode(struct smb1390 *chip) { int rc; union power_supply_propval pval = {0, }; if (!chip->usb_psy) { chip->usb_psy = power_supply_get_by_name("usb"); if (!chip->usb_psy) return false; } 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); return false; } return pval.intval; } static bool is_cps_available(struct smb1390 *chip) { if (!chip->cps_psy) Loading Loading @@ -697,6 +725,30 @@ static int smb1390_get_isns_slave(struct smb1390 *chip, return rc; } static int smb1390_get_cp_ilim(struct smb1390 *chip, union power_supply_propval *val) { int rc = 0, status; if (is_cps_available(chip)) { if (!chip->ilim_votable) { chip->ilim_votable = find_votable("CP_ILIM"); if (!chip->ilim_votable) return -EINVAL; } val->intval = get_effective_result(chip->ilim_votable); } else { rc = smb1390_read(chip, CORE_FTRIM_ILIM_REG, &status); if (!rc) val->intval = ((status & CFG_ILIM_MASK) * 100000) + 500000; } return rc; } static int smb1390_is_batt_soc_valid(struct smb1390 *chip) { int rc; Loading Loading @@ -825,7 +877,8 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, return -EINVAL; } ilim_uA = min(ilim_uA, MAX_ILIM_UA); ilim_uA = min(ilim_uA, (is_cps_available(chip) ? MAX_ILIM_DUAL_CP_UA : MAX_ILIM_UA)); /* ILIM less than min_ilim_ua, disable charging */ if (ilim_uA < chip->min_ilim_ua) { smb1390_dbg(chip, PR_INFO, "ILIM %duA is too low to allow charging\n", Loading Loading @@ -926,6 +979,7 @@ static void smb1390_status_change_work(struct work_struct *work) if (!is_psy_voter_available(chip)) goto out; if (!smb1390_is_adapter_cc_mode(chip)) vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); Loading @@ -944,7 +998,14 @@ static void smb1390_status_change_work(struct work_struct *work) goto out; } /* Check for SOC threshold only once before enabling CP */ vote(chip->disable_votable, SRC_VOTER, false, 0); if (!chip->batt_soc_validated) { vote(chip->disable_votable, SOC_LEVEL_VOTER, smb1390_is_batt_soc_valid(chip) ? false : true, 0); chip->batt_soc_validated = true; } if (pval.intval == POWER_SUPPLY_CP_WIRELESS) { vote(chip->ilim_votable, ICL_VOTER, false, 0); Loading Loading @@ -1014,10 +1075,12 @@ static void smb1390_status_change_work(struct work_struct *work) } } } else { chip->batt_soc_validated = false; 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); vote_override(chip->ilim_votable, CC_MODE_VOTER, false, 0); } out: Loading @@ -1025,11 +1088,39 @@ static void smb1390_status_change_work(struct work_struct *work) chip->status_change_running = false; } static int smb1390_validate_slave_chg_taper(struct smb1390 *chip, int fcc_uA) { int rc = 0; u8 mask; /* * In Collapse mode, while in Taper, Disable the slave SMB1390 * when FCC drops below a specified threshold. */ if (fcc_uA < (chip->cp_slave_thr_taper_ua) && is_cps_available(chip)) { mask = CMD_EN_SWITCHER_BIT | CMD_EN_SL_BIT; rc = smb1390_masked_write(chip, CORE_CONTROL1_REG, mask, CMD_EN_SWITCHER_BIT); if (rc < 0) return rc; /* * Set ILIM of master SMB1390 to Max value = 3.2A once slave is * disabled to prevent ILIM irq storm. */ smb1390_dbg(chip, PR_INFO, "Set Master ILIM to MAX, post Slave disable in taper, fcc=%d\n", fcc_uA); vote_override(chip->ilim_votable, CC_MODE_VOTER, true, MAX_ILIM_DUAL_CP_UA); } return rc; } 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; int rc, fcc_uA, delta_fcc_uA; if (!is_psy_voter_available(chip)) goto out; Loading @@ -1053,11 +1144,21 @@ static void smb1390_taper_work(struct work_struct *work) } if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { delta_fcc_uA = (smb1390_is_adapter_cc_mode(chip) ? CC_MODE_TAPER_DELTA_UA : DEFAULT_TAPER_DELTA_UA); fcc_uA = get_effective_result(chip->fcc_votable) - 100000; - delta_fcc_uA; 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); 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)) { vote(chip->disable_votable, TAPER_END_VOTER, Loading Loading @@ -1174,10 +1275,7 @@ static int smb1390_get_prop(struct power_supply *psy, val->intval |= status; break; case POWER_SUPPLY_PROP_CP_ILIM: rc = smb1390_read(chip, CORE_FTRIM_ILIM_REG, &status); if (!rc) val->intval = ((status & CFG_ILIM_MASK) * 100000) + 500000; rc = smb1390_get_cp_ilim(chip, val); break; case POWER_SUPPLY_PROP_CHIP_VERSION: val->intval = chip->pmic_rev_id->rev4; Loading Loading @@ -1215,6 +1313,11 @@ static int smb1390_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CP_IRQ_STATUS: chip->irq_status = val->intval; break; case POWER_SUPPLY_PROP_CP_ILIM: if (chip->ilim_votable) vote_override(chip->ilim_votable, CC_MODE_VOTER, true, val->intval); break; default: smb1390_dbg(chip, PR_MISC, "charge pump power supply set prop %d not supported\n", prop); Loading @@ -1233,6 +1336,7 @@ static int smb1390_prop_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_CP_IRQ_STATUS: case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX: case POWER_SUPPLY_PROP_CURRENT_CAPABILITY: case POWER_SUPPLY_PROP_CP_ILIM: return 1; default: break; Loading Loading @@ -1307,6 +1411,10 @@ static int smb1390_parse_dt(struct smb1390 *chip) chip->pl_output_mode = POWER_SUPPLY_PL_OUTPUT_VPH; of_property_read_u32(chip->dev->of_node, "qcom,parallel-output-mode", &chip->pl_output_mode); chip->cp_slave_thr_taper_ua = chip->min_ilim_ua * 3; of_property_read_u32(chip->dev->of_node, "qcom,cp-slave-thr-taper-ua", &chip->cp_slave_thr_taper_ua); return 0; } Loading
drivers/power/supply/qcom/smb5-lib.c +13 −0 Original line number Diff line number Diff line Loading @@ -5483,6 +5483,12 @@ static void typec_src_removal(struct smb_charger *chg) chg->voltage_max_uv = MICRO_5V; chg->usbin_forced_max_uv = 0; /* Reset CC mode votes */ vote(chg->fcc_main_votable, MAIN_FCC_VOTER, false, 0); chg->adapter_cc_mode = 0; vote_override(chg->fcc_votable, CC_MODE_VOTER, false, 0); vote_override(chg->usb_icl_votable, CC_MODE_VOTER, false, 0); /* write back the default FLOAT charger configuration */ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG, (u8)FLOAT_OPTIONS_MASK, chg->float_cfg); Loading Loading @@ -6786,6 +6792,13 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } chg->fcc_main_votable = find_votable("FCC_MAIN"); if (chg->fcc_main_votable == NULL) { rc = -EINVAL; smblib_err(chg, "Couldn't find FCC Main votable rc=%d\n", rc); return rc; } chg->fv_votable = find_votable("FV"); if (chg->fv_votable == NULL) { rc = -EINVAL; Loading
drivers/power/supply/qcom/smb5-lib.h +18 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ enum print_reason { #define CHARGER_TYPE_VOTER "CHARGER_TYPE_VOTER" #define HDC_IRQ_VOTER "HDC_IRQ_VOTER" #define DETACH_DETECT_VOTER "DETACH_DETECT_VOTER" #define CC_MODE_VOTER "CC_MODE_VOTER" #define MAIN_FCC_VOTER "MAIN_FCC_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 Loading Loading @@ -229,6 +231,17 @@ enum chg_term_config_src { ITERM_SRC_ANALOG }; enum comp_clamp_levels { CLAMP_LEVEL_DEFAULT = 0, CLAMP_LEVEL_1, MAX_CLAMP_LEVEL, }; struct clamp_config { u16 reg[3]; u16 val[3]; }; struct smb_irq_info { const char *name; const irq_handler_t handler; Loading Loading @@ -398,6 +411,9 @@ struct smb_charger { /* parallel charging */ struct parallel_params pl; /* CC Mode */ int adapter_cc_mode; /* regulators */ struct smb_regulator *vbus_vreg; struct smb_regulator *vconn_vreg; Loading @@ -406,6 +422,7 @@ struct smb_charger { /* votables */ struct votable *dc_suspend_votable; struct votable *fcc_votable; struct votable *fcc_main_votable; struct votable *fv_votable; struct votable *usb_icl_votable; struct votable *awake_votable; Loading Loading @@ -526,6 +543,7 @@ struct smb_charger { int dr_mode; int usbin_forced_max_uv; int init_thermal_ua; u32 comp_clamp_level; /* workaround flag */ u32 wa_flags; Loading