Loading drivers/power/supply/qcom/battery.c +57 −14 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ struct pl_data { struct votable *usb_icl_votable; struct votable *pl_enable_votable_indirect; struct votable *cp_ilim_votable; struct votable *cp_disable_votable; struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct work_struct pl_taper_work; Loading Loading @@ -128,6 +129,37 @@ enum { RESTRICT_CHG_CURRENT, FCC_STEPPING_IN_PROGRESS, }; /********* * HELPER* *********/ static bool is_cp_available(struct pl_data *chip) { if (!chip->cp_master_psy) chip->cp_master_psy = power_supply_get_by_name("charge_pump_master"); return !!chip->cp_master_psy; } static bool cp_ilim_boost_enabled(struct pl_data *chip) { union power_supply_propval pval = {-1, }; if (is_cp_available(chip)) power_supply_get_property(chip->cp_master_psy, POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE, &pval); return pval.intval == POWER_SUPPLY_PL_OUTPUT_VPH; } static void cp_configure_ilim(struct pl_data *chip, const char *voter, int ilim) { if (!chip->cp_ilim_votable) chip->cp_ilim_votable = find_votable("CP_ILIM"); if (!cp_ilim_boost_enabled(chip) && chip->cp_ilim_votable) vote(chip->cp_ilim_votable, voter, true, ilim); } /******* * ICL * Loading Loading @@ -489,10 +521,7 @@ static void get_main_fcc_config(struct pl_data *chip, int *total_fcc) union power_supply_propval pval = {0, }; int rc; if (!chip->cp_master_psy) chip->cp_master_psy = power_supply_get_by_name("charge_pump_master"); if (!chip->cp_master_psy) if (!is_cp_available(chip)) goto out; rc = power_supply_get_property(chip->cp_master_psy, Loading Loading @@ -668,6 +697,7 @@ 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; union power_supply_propval pval = {0, }; if (total_fcc_ua < 0) return 0; Loading @@ -675,8 +705,26 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, if (!chip->main_psy) return 0; if (!chip->cp_ilim_votable) chip->cp_ilim_votable = find_votable("CP_ILIM"); if (!chip->cp_disable_votable) chip->cp_disable_votable = find_votable("CP_DISABLE"); if (chip->cp_disable_votable) { if (cp_ilim_boost_enabled(chip)) { power_supply_get_property(chip->cp_master_psy, POWER_SUPPLY_PROP_MIN_ICL, &pval); /* * With ILIM boost feature ILIM configuration is * independent of battery FCC, disable CP if FCC/2 * falls below MIN_ICL supported by CP. */ 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); } } if (chip->pl_mode != POWER_SUPPLY_PL_NONE) { get_fcc_split(chip, total_fcc_ua, &master_fcc_ua, Loading Loading @@ -874,9 +922,7 @@ static void fcc_stepper_work(struct work_struct *work) chip->main_fcc_ua = main_fcc; chip->slave_fcc_ua = parallel_fcc; if (chip->cp_ilim_votable) vote(chip->cp_ilim_votable, FCC_VOTER, true, chip->main_fcc_ua / 2); cp_configure_ilim(chip, FCC_VOTER, chip->main_fcc_ua / 2); if (reschedule_ms) { schedule_delayed_work(&chip->fcc_stepper_work, Loading Loading @@ -993,8 +1039,7 @@ static int usb_icl_vote_callback(struct votable *votable, void *data, vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0); if (chip->cp_ilim_votable) vote(chip->cp_ilim_votable, ICL_CHANGE_VOTER, true, icl_ua); cp_configure_ilim(chip, ICL_CHANGE_VOTER, icl_ua); return 0; } Loading Loading @@ -1254,9 +1299,7 @@ static int pl_disable_vote_callback(struct votable *votable, return rc; } if (chip->cp_ilim_votable) vote(chip->cp_ilim_votable, FCC_VOTER, true, total_fcc_ua / 2); cp_configure_ilim(chip, FCC_VOTER, total_fcc_ua / 2); /* reset parallel FCC */ chip->slave_fcc_ua = 0; Loading drivers/power/supply/qcom/smb1390-charger-psy.c +66 −16 Original line number Diff line number Diff line Loading @@ -75,6 +75,9 @@ #define WINDOW_DETECTION_DELTA_X1P0 0 #define WINDOW_DETECTION_DELTA_X1P5 1 #define CORE_FTRIM_DIS_REG 0x1035 #define TR_DIS_ILIM_DET_BIT BIT(4) #define CORE_ATEST1_SEL_REG 0x10E2 #define ATEST1_OUTPUT_ENABLE_BIT BIT(7) #define ATEST1_SEL_MASK GENMASK(6, 0) Loading @@ -92,6 +95,7 @@ #define SOC_LEVEL_VOTER "SOC_LEVEL_VOTER" #define THERMAL_SUSPEND_DECIDEGC 1400 #define MAX_ILIM_UA 3200000 #define smb1390_dbg(chip, reason, fmt, ...) \ do { \ Loading Loading @@ -174,6 +178,7 @@ struct smb1390 { u32 min_ilim_ua; u32 max_temp_alarm_degc; u32 max_cutoff_soc; u32 pl_output_mode; }; struct smb_irq { Loading Loading @@ -262,12 +267,29 @@ static bool is_psy_voter_available(struct smb1390 *chip) static void cp_toggle_switcher(struct smb1390 *chip) { int rc; /* * Disable ILIM detection before toggling the switcher * to prevent any ILIM interrupt storm while toggling * the switcher. */ rc = regmap_update_bits(chip->regmap, CORE_FTRIM_DIS_REG, TR_DIS_ILIM_DET_BIT, TR_DIS_ILIM_DET_BIT); if (rc < 0) pr_err("Couldn't disable ILIM rc=%d\n", rc); vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, true, 0); /* Delay for toggling switcher */ usleep_range(20, 30); vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, false, 0); rc = regmap_update_bits(chip->regmap, CORE_FTRIM_DIS_REG, TR_DIS_ILIM_DET_BIT, 0); if (rc < 0) pr_err("Couldn't enable ILIM rc=%d\n", rc); } static int smb1390_get_cp_en_status(struct smb1390 *chip, int id, bool *enable) Loading Loading @@ -522,6 +544,7 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, return -EINVAL; } ilim_uA = min(ilim_uA, MAX_ILIM_UA); rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG, CFG_ILIM_MASK, DIV_ROUND_CLOSEST(max(ilim_uA, 500000) - 500000, 100000)); Loading Loading @@ -568,6 +591,9 @@ static int smb1390_notifier_cb(struct notifier_block *nb, return NOTIFY_OK; } #define ILIM_NR 10 #define ILIM_DR 8 #define ILIM_FACTOR(ilim) ((ilim * ILIM_NR) / ILIM_DR) static void smb1390_status_change_work(struct work_struct *work) { struct smb1390 *chip = container_of(work, struct smb1390, Loading Loading @@ -598,11 +624,6 @@ static void smb1390_status_change_work(struct work_struct *work) vote(chip->disable_votable, SRC_VOTER, false, 0); /* * ILIM is set based on the primary chargers AICL result. This * ensures VBUS does not collapse due to the current drawn via * MID. */ if (pval.intval == POWER_SUPPLY_CP_WIRELESS) { vote(chip->ilim_votable, ICL_VOTER, false, 0); rc = power_supply_get_property(chip->dc_psy, Loading @@ -612,15 +633,30 @@ static void smb1390_status_change_work(struct work_struct *work) else vote(chip->ilim_votable, WIRELESS_VOTER, true, pval.intval); } else { /* QC3 or PPS */ } else { vote(chip->ilim_votable, WIRELESS_VOTER, false, 0); if ((chip->pl_output_mode == POWER_SUPPLY_PL_OUTPUT_VPH) && (pval.intval == POWER_SUPPLY_CP_PPS)) { rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval); POWER_SUPPLY_PROP_PD_CURRENT_MAX, &pval); if (rc < 0) pr_err("Couldn't get usb icl rc=%d\n", rc); pr_err("Couldn't get PD CURRENT MAX rc=%d\n", rc); else vote(chip->ilim_votable, ICL_VOTER, true, pval.intval); vote(chip->ilim_votable, ICL_VOTER, true, ILIM_FACTOR(pval.intval)); } else { rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval); if (rc < 0) pr_err("Couldn't get usb aicl rc=%d\n", rc); else vote(chip->ilim_votable, ICL_VOTER, true, pval.intval); } } /* Loading Loading @@ -729,6 +765,8 @@ static enum power_supply_property smb1390_charge_pump_props[] = { POWER_SUPPLY_PROP_CP_IRQ_STATUS, POWER_SUPPLY_PROP_CP_ILIM, POWER_SUPPLY_PROP_CHIP_VERSION, POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE, POWER_SUPPLY_PROP_MIN_ICL, }; static int smb1390_get_prop(struct power_supply *psy, Loading Loading @@ -818,6 +856,12 @@ static int smb1390_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CHIP_VERSION: val->intval = chip->pmic_rev_id->rev4; break; case POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE: val->intval = chip->pl_output_mode; break; case POWER_SUPPLY_PROP_MIN_ICL: val->intval = chip->min_ilim_ua; break; default: smb1390_dbg(chip, PR_MISC, "charge pump power supply get prop %d not supported\n", prop); Loading Loading @@ -931,6 +975,10 @@ static int smb1390_parse_dt(struct smb1390 *chip) of_property_read_u32(chip->dev->of_node, "qcom,max-cutoff-soc", &chip->max_cutoff_soc); /* Default parallel output configuration is VPH connection */ 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); return 0; } Loading Loading @@ -963,9 +1011,11 @@ static int smb1390_create_votables(struct smb1390 *chip) /* * In case SMB1390 probe happens after FCC value has been configured, * update ilim vote to reflect FCC / 2 value. * update ilim vote to reflect FCC / 2 value, this is only applicable * when SMB1390 is directly connected to VBAT. */ if (chip->fcc_votable) if ((chip->pl_output_mode != POWER_SUPPLY_PL_OUTPUT_VPH) && chip->fcc_votable) vote(chip->ilim_votable, FCC_VOTER, true, get_effective_result(chip->fcc_votable) / 2); Loading Loading
drivers/power/supply/qcom/battery.c +57 −14 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ struct pl_data { struct votable *usb_icl_votable; struct votable *pl_enable_votable_indirect; struct votable *cp_ilim_votable; struct votable *cp_disable_votable; struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct work_struct pl_taper_work; Loading Loading @@ -128,6 +129,37 @@ enum { RESTRICT_CHG_CURRENT, FCC_STEPPING_IN_PROGRESS, }; /********* * HELPER* *********/ static bool is_cp_available(struct pl_data *chip) { if (!chip->cp_master_psy) chip->cp_master_psy = power_supply_get_by_name("charge_pump_master"); return !!chip->cp_master_psy; } static bool cp_ilim_boost_enabled(struct pl_data *chip) { union power_supply_propval pval = {-1, }; if (is_cp_available(chip)) power_supply_get_property(chip->cp_master_psy, POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE, &pval); return pval.intval == POWER_SUPPLY_PL_OUTPUT_VPH; } static void cp_configure_ilim(struct pl_data *chip, const char *voter, int ilim) { if (!chip->cp_ilim_votable) chip->cp_ilim_votable = find_votable("CP_ILIM"); if (!cp_ilim_boost_enabled(chip) && chip->cp_ilim_votable) vote(chip->cp_ilim_votable, voter, true, ilim); } /******* * ICL * Loading Loading @@ -489,10 +521,7 @@ static void get_main_fcc_config(struct pl_data *chip, int *total_fcc) union power_supply_propval pval = {0, }; int rc; if (!chip->cp_master_psy) chip->cp_master_psy = power_supply_get_by_name("charge_pump_master"); if (!chip->cp_master_psy) if (!is_cp_available(chip)) goto out; rc = power_supply_get_property(chip->cp_master_psy, Loading Loading @@ -668,6 +697,7 @@ 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; union power_supply_propval pval = {0, }; if (total_fcc_ua < 0) return 0; Loading @@ -675,8 +705,26 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, if (!chip->main_psy) return 0; if (!chip->cp_ilim_votable) chip->cp_ilim_votable = find_votable("CP_ILIM"); if (!chip->cp_disable_votable) chip->cp_disable_votable = find_votable("CP_DISABLE"); if (chip->cp_disable_votable) { if (cp_ilim_boost_enabled(chip)) { power_supply_get_property(chip->cp_master_psy, POWER_SUPPLY_PROP_MIN_ICL, &pval); /* * With ILIM boost feature ILIM configuration is * independent of battery FCC, disable CP if FCC/2 * falls below MIN_ICL supported by CP. */ 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); } } if (chip->pl_mode != POWER_SUPPLY_PL_NONE) { get_fcc_split(chip, total_fcc_ua, &master_fcc_ua, Loading Loading @@ -874,9 +922,7 @@ static void fcc_stepper_work(struct work_struct *work) chip->main_fcc_ua = main_fcc; chip->slave_fcc_ua = parallel_fcc; if (chip->cp_ilim_votable) vote(chip->cp_ilim_votable, FCC_VOTER, true, chip->main_fcc_ua / 2); cp_configure_ilim(chip, FCC_VOTER, chip->main_fcc_ua / 2); if (reschedule_ms) { schedule_delayed_work(&chip->fcc_stepper_work, Loading Loading @@ -993,8 +1039,7 @@ static int usb_icl_vote_callback(struct votable *votable, void *data, vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0); if (chip->cp_ilim_votable) vote(chip->cp_ilim_votable, ICL_CHANGE_VOTER, true, icl_ua); cp_configure_ilim(chip, ICL_CHANGE_VOTER, icl_ua); return 0; } Loading Loading @@ -1254,9 +1299,7 @@ static int pl_disable_vote_callback(struct votable *votable, return rc; } if (chip->cp_ilim_votable) vote(chip->cp_ilim_votable, FCC_VOTER, true, total_fcc_ua / 2); cp_configure_ilim(chip, FCC_VOTER, total_fcc_ua / 2); /* reset parallel FCC */ chip->slave_fcc_ua = 0; Loading
drivers/power/supply/qcom/smb1390-charger-psy.c +66 −16 Original line number Diff line number Diff line Loading @@ -75,6 +75,9 @@ #define WINDOW_DETECTION_DELTA_X1P0 0 #define WINDOW_DETECTION_DELTA_X1P5 1 #define CORE_FTRIM_DIS_REG 0x1035 #define TR_DIS_ILIM_DET_BIT BIT(4) #define CORE_ATEST1_SEL_REG 0x10E2 #define ATEST1_OUTPUT_ENABLE_BIT BIT(7) #define ATEST1_SEL_MASK GENMASK(6, 0) Loading @@ -92,6 +95,7 @@ #define SOC_LEVEL_VOTER "SOC_LEVEL_VOTER" #define THERMAL_SUSPEND_DECIDEGC 1400 #define MAX_ILIM_UA 3200000 #define smb1390_dbg(chip, reason, fmt, ...) \ do { \ Loading Loading @@ -174,6 +178,7 @@ struct smb1390 { u32 min_ilim_ua; u32 max_temp_alarm_degc; u32 max_cutoff_soc; u32 pl_output_mode; }; struct smb_irq { Loading Loading @@ -262,12 +267,29 @@ static bool is_psy_voter_available(struct smb1390 *chip) static void cp_toggle_switcher(struct smb1390 *chip) { int rc; /* * Disable ILIM detection before toggling the switcher * to prevent any ILIM interrupt storm while toggling * the switcher. */ rc = regmap_update_bits(chip->regmap, CORE_FTRIM_DIS_REG, TR_DIS_ILIM_DET_BIT, TR_DIS_ILIM_DET_BIT); if (rc < 0) pr_err("Couldn't disable ILIM rc=%d\n", rc); vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, true, 0); /* Delay for toggling switcher */ usleep_range(20, 30); vote(chip->disable_votable, SWITCHER_TOGGLE_VOTER, false, 0); rc = regmap_update_bits(chip->regmap, CORE_FTRIM_DIS_REG, TR_DIS_ILIM_DET_BIT, 0); if (rc < 0) pr_err("Couldn't enable ILIM rc=%d\n", rc); } static int smb1390_get_cp_en_status(struct smb1390 *chip, int id, bool *enable) Loading Loading @@ -522,6 +544,7 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, return -EINVAL; } ilim_uA = min(ilim_uA, MAX_ILIM_UA); rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG, CFG_ILIM_MASK, DIV_ROUND_CLOSEST(max(ilim_uA, 500000) - 500000, 100000)); Loading Loading @@ -568,6 +591,9 @@ static int smb1390_notifier_cb(struct notifier_block *nb, return NOTIFY_OK; } #define ILIM_NR 10 #define ILIM_DR 8 #define ILIM_FACTOR(ilim) ((ilim * ILIM_NR) / ILIM_DR) static void smb1390_status_change_work(struct work_struct *work) { struct smb1390 *chip = container_of(work, struct smb1390, Loading Loading @@ -598,11 +624,6 @@ static void smb1390_status_change_work(struct work_struct *work) vote(chip->disable_votable, SRC_VOTER, false, 0); /* * ILIM is set based on the primary chargers AICL result. This * ensures VBUS does not collapse due to the current drawn via * MID. */ if (pval.intval == POWER_SUPPLY_CP_WIRELESS) { vote(chip->ilim_votable, ICL_VOTER, false, 0); rc = power_supply_get_property(chip->dc_psy, Loading @@ -612,15 +633,30 @@ static void smb1390_status_change_work(struct work_struct *work) else vote(chip->ilim_votable, WIRELESS_VOTER, true, pval.intval); } else { /* QC3 or PPS */ } else { vote(chip->ilim_votable, WIRELESS_VOTER, false, 0); if ((chip->pl_output_mode == POWER_SUPPLY_PL_OUTPUT_VPH) && (pval.intval == POWER_SUPPLY_CP_PPS)) { rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval); POWER_SUPPLY_PROP_PD_CURRENT_MAX, &pval); if (rc < 0) pr_err("Couldn't get usb icl rc=%d\n", rc); pr_err("Couldn't get PD CURRENT MAX rc=%d\n", rc); else vote(chip->ilim_votable, ICL_VOTER, true, pval.intval); vote(chip->ilim_votable, ICL_VOTER, true, ILIM_FACTOR(pval.intval)); } else { rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval); if (rc < 0) pr_err("Couldn't get usb aicl rc=%d\n", rc); else vote(chip->ilim_votable, ICL_VOTER, true, pval.intval); } } /* Loading Loading @@ -729,6 +765,8 @@ static enum power_supply_property smb1390_charge_pump_props[] = { POWER_SUPPLY_PROP_CP_IRQ_STATUS, POWER_SUPPLY_PROP_CP_ILIM, POWER_SUPPLY_PROP_CHIP_VERSION, POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE, POWER_SUPPLY_PROP_MIN_ICL, }; static int smb1390_get_prop(struct power_supply *psy, Loading Loading @@ -818,6 +856,12 @@ static int smb1390_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CHIP_VERSION: val->intval = chip->pmic_rev_id->rev4; break; case POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE: val->intval = chip->pl_output_mode; break; case POWER_SUPPLY_PROP_MIN_ICL: val->intval = chip->min_ilim_ua; break; default: smb1390_dbg(chip, PR_MISC, "charge pump power supply get prop %d not supported\n", prop); Loading Loading @@ -931,6 +975,10 @@ static int smb1390_parse_dt(struct smb1390 *chip) of_property_read_u32(chip->dev->of_node, "qcom,max-cutoff-soc", &chip->max_cutoff_soc); /* Default parallel output configuration is VPH connection */ 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); return 0; } Loading Loading @@ -963,9 +1011,11 @@ static int smb1390_create_votables(struct smb1390 *chip) /* * In case SMB1390 probe happens after FCC value has been configured, * update ilim vote to reflect FCC / 2 value. * update ilim vote to reflect FCC / 2 value, this is only applicable * when SMB1390 is directly connected to VBAT. */ if (chip->fcc_votable) if ((chip->pl_output_mode != POWER_SUPPLY_PL_OUTPUT_VPH) && chip->fcc_votable) vote(chip->ilim_votable, FCC_VOTER, true, get_effective_result(chip->fcc_votable) / 2); Loading