Loading arch/arm64/boot/dts/qcom/smb1390.dtsi +5 −5 Original line number Original line Diff line number Diff line Loading @@ -37,11 +37,11 @@ smb1390: qcom,smb1390@10 { status = "disabled"; status = "disabled"; qcom,core { qcom,core { interrupts = <0x10 0x0 IRQ_TYPE_EDGE_RISING>, interrupts = <0x10 0x0 IRQ_TYPE_EDGE_BOTH>, <0x10 0x1 IRQ_TYPE_EDGE_RISING>, <0x10 0x1 IRQ_TYPE_EDGE_BOTH>, <0x10 0x2 IRQ_TYPE_EDGE_RISING>, <0x10 0x2 IRQ_TYPE_EDGE_BOTH>, <0x10 0x3 IRQ_TYPE_EDGE_RISING>, <0x10 0x3 IRQ_TYPE_EDGE_BOTH>, <0x10 0x4 IRQ_TYPE_EDGE_RISING>, <0x10 0x4 IRQ_TYPE_EDGE_BOTH>, <0x10 0x5 IRQ_TYPE_EDGE_RISING>, <0x10 0x5 IRQ_TYPE_EDGE_RISING>, <0x10 0x6 IRQ_TYPE_EDGE_RISING>, <0x10 0x6 IRQ_TYPE_EDGE_RISING>, <0x10 0x7 IRQ_TYPE_EDGE_RISING>; <0x10 0x7 IRQ_TYPE_EDGE_RISING>; Loading drivers/power/supply/qcom/battery.c +60 −2 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,7 @@ #define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER" #define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER" #define ICL_LIMIT_VOTER "ICL_LIMIT_VOTER" #define ICL_LIMIT_VOTER "ICL_LIMIT_VOTER" #define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER" #define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER" #define FCC_VOTER "FCC_VOTER" struct pl_data { struct pl_data { int pl_mode; int pl_mode; Loading @@ -63,6 +64,7 @@ struct pl_data { struct votable *hvdcp_hw_inov_dis_votable; struct votable *hvdcp_hw_inov_dis_votable; struct votable *usb_icl_votable; struct votable *usb_icl_votable; struct votable *pl_enable_votable_indirect; struct votable *pl_enable_votable_indirect; struct votable *cp_ilim_votable; struct delayed_work status_change_work; struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct work_struct pl_disable_forever_work; struct work_struct pl_taper_work; struct work_struct pl_taper_work; Loading @@ -74,6 +76,7 @@ struct pl_data { struct power_supply *batt_psy; struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *usb_psy; struct power_supply *dc_psy; struct power_supply *dc_psy; struct power_supply *cp_master_psy; int charge_type; int charge_type; int total_settled_ua; int total_settled_ua; int pl_settled_ua; int pl_settled_ua; Loading @@ -91,6 +94,7 @@ struct pl_data { struct wakeup_source *pl_ws; struct wakeup_source *pl_ws; struct notifier_block nb; struct notifier_block nb; bool pl_disable; bool pl_disable; bool cp_disabled; int taper_entry_fv; int taper_entry_fv; int main_fcc_max; int main_fcc_max; }; }; Loading Loading @@ -481,6 +485,46 @@ static void get_fcc_split(struct pl_data *chip, int total_ua, } } } } 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) goto out; rc = power_supply_get_property(chip->cp_master_psy, POWER_SUPPLY_PROP_CP_SWITCHER_EN, &pval); if (rc < 0) { pr_err("Couldn't get switcher enable status, rc=%d\n", rc); goto out; } if (!pval.intval) { /* * To honor main charger upper FCC limit, on CP switcher * disable, skip fcc slewing as it will cause delay in limiting * the charge current flowing through main charger. */ if (!chip->cp_disabled) { chip->fcc_stepper_enable = false; pl_dbg(chip, PR_PARALLEL, "Disabling FCC slewing on CP Switcher disable\n"); } chip->cp_disabled = true; } else { chip->cp_disabled = false; pl_dbg(chip, PR_PARALLEL, "CP Switcher is enabled, don't limit main fcc\n"); return; } out: *total_fcc = min(*total_fcc, chip->main_fcc_max); } static void get_fcc_stepper_params(struct pl_data *chip, int main_fcc_ua, static void get_fcc_stepper_params(struct pl_data *chip, int main_fcc_ua, int parallel_fcc_ua) int parallel_fcc_ua) { { Loading Loading @@ -623,6 +667,9 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, if (!chip->main_psy) if (!chip->main_psy) return 0; return 0; if (!chip->cp_ilim_votable) chip->cp_ilim_votable = find_votable("CP_ILIM"); if (chip->pl_mode != POWER_SUPPLY_PL_NONE) { if (chip->pl_mode != POWER_SUPPLY_PL_NONE) { get_fcc_split(chip, total_fcc_ua, &master_fcc_ua, get_fcc_split(chip, total_fcc_ua, &master_fcc_ua, &slave_fcc_ua); &slave_fcc_ua); Loading Loading @@ -819,6 +866,10 @@ static void fcc_stepper_work(struct work_struct *work) chip->main_fcc_ua = main_fcc; chip->main_fcc_ua = main_fcc; chip->slave_fcc_ua = parallel_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); if (reschedule_ms) { if (reschedule_ms) { schedule_delayed_work(&chip->fcc_stepper_work, schedule_delayed_work(&chip->fcc_stepper_work, msecs_to_jiffies(reschedule_ms)); msecs_to_jiffies(reschedule_ms)); Loading Loading @@ -934,6 +985,9 @@ static int usb_icl_vote_callback(struct votable *votable, void *data, vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0); 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); return 0; return 0; } } Loading Loading @@ -1166,8 +1220,7 @@ static int pl_disable_vote_callback(struct votable *votable, (slave_fcc_ua * 100) / total_fcc_ua); (slave_fcc_ua * 100) / total_fcc_ua); } else { } else { if (chip->main_fcc_max) if (chip->main_fcc_max) total_fcc_ua = min(total_fcc_ua, get_main_fcc_config(chip, &total_fcc_ua); chip->main_fcc_max); if (!chip->fcc_stepper_enable) { if (!chip->fcc_stepper_enable) { if (IS_USBIN(chip->pl_mode)) if (IS_USBIN(chip->pl_mode)) Loading @@ -1193,6 +1246,10 @@ static int pl_disable_vote_callback(struct votable *votable, return rc; return rc; } } if (chip->cp_ilim_votable) vote(chip->cp_ilim_votable, FCC_VOTER, true, total_fcc_ua / 2); /* reset parallel FCC */ /* reset parallel FCC */ chip->slave_fcc_ua = 0; chip->slave_fcc_ua = 0; chip->total_settled_ua = 0; chip->total_settled_ua = 0; Loading Loading @@ -1684,6 +1741,7 @@ int qcom_batt_init(int smb_version) } } chip->pl_disable = true; chip->pl_disable = true; chip->cp_disabled = true; chip->qcom_batt_class.name = "qcom-battery", chip->qcom_batt_class.name = "qcom-battery", chip->qcom_batt_class.owner = THIS_MODULE, chip->qcom_batt_class.owner = THIS_MODULE, chip->qcom_batt_class.class_groups = batt_class_groups; chip->qcom_batt_class.class_groups = batt_class_groups; Loading drivers/power/supply/qcom/qpnp-smb5.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1435,6 +1435,9 @@ static int smb5_batt_set_prop(struct power_supply *psy, vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER, vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER, false, 0); false, 0); break; break; case POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE: chg->fcc_stepper_enable = val->intval; break; default: default: rc = -EINVAL; rc = -EINVAL; } } Loading drivers/power/supply/qcom/smb1390-charger-psy.c +79 −20 Original line number Original line Diff line number Diff line Loading @@ -84,6 +84,7 @@ #define CP_VOTER "CP_VOTER" #define CP_VOTER "CP_VOTER" #define USER_VOTER "USER_VOTER" #define USER_VOTER "USER_VOTER" #define ILIM_VOTER "ILIM_VOTER" #define ILIM_VOTER "ILIM_VOTER" #define TAPER_END_VOTER "TAPER_END_VOTER" #define FCC_VOTER "FCC_VOTER" #define FCC_VOTER "FCC_VOTER" #define ICL_VOTER "ICL_VOTER" #define ICL_VOTER "ICL_VOTER" #define WIRELESS_VOTER "WIRELESS_VOTER" #define WIRELESS_VOTER "WIRELESS_VOTER" Loading Loading @@ -129,6 +130,7 @@ struct smb1390 { struct votable *disable_votable; struct votable *disable_votable; struct votable *ilim_votable; struct votable *ilim_votable; struct votable *fcc_votable; struct votable *fcc_votable; struct votable *fv_votable; struct votable *cp_awake_votable; struct votable *cp_awake_votable; /* power supplies */ /* power supplies */ Loading @@ -142,6 +144,8 @@ struct smb1390 { bool taper_work_running; bool taper_work_running; struct smb1390_iio iio; struct smb1390_iio iio; int irq_status; int irq_status; int taper_entry_fv; bool switcher_disabled; }; }; struct smb_irq { struct smb_irq { Loading Loading @@ -211,6 +215,19 @@ static bool is_psy_voter_available(struct smb1390 *chip) } } } } if (!chip->fv_votable) { chip->fv_votable = find_votable("FV"); if (!chip->fv_votable) { pr_debug("Couldn't find FV votable\n"); return false; } } if (!chip->disable_votable) { pr_debug("Couldn't find CP DISABLE votable\n"); return false; } return true; return true; } } Loading Loading @@ -254,7 +271,8 @@ static int smb1390_get_cp_en_status(struct smb1390 *chip, int id, bool *enable) static irqreturn_t default_irq_handler(int irq, void *data) static irqreturn_t default_irq_handler(int irq, void *data) { { struct smb1390 *chip = data; struct smb1390 *chip = data; int i; int i, rc; bool enable; for (i = 0; i < NUM_IRQS; ++i) { for (i = 0; i < NUM_IRQS; ++i) { if (irq == chip->irqs[i]) { if (irq == chip->irqs[i]) { Loading @@ -263,8 +281,18 @@ static irqreturn_t default_irq_handler(int irq, void *data) } } } } rc = smb1390_get_cp_en_status(chip, SWITCHER_EN, &enable); if (!rc) { if (chip->switcher_disabled == enable) { chip->switcher_disabled = !chip->switcher_disabled; if (chip->fcc_votable) rerun_election(chip->fcc_votable); } } if (chip->cp_master_psy) if (chip->cp_master_psy) power_supply_changed(chip->cp_master_psy); power_supply_changed(chip->cp_master_psy); return IRQ_HANDLED; return IRQ_HANDLED; } } Loading Loading @@ -442,18 +470,20 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, return -EINVAL; return -EINVAL; } } rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG, CFG_ILIM_MASK, DIV_ROUND_CLOSEST(max(ilim_uA, 500000) - 500000, 100000)); if (rc < 0) { pr_err("Failed to write ILIM Register, rc=%d\n", rc); return rc; } /* ILIM less than 1A is not accurate; disable charging */ /* ILIM less than 1A is not accurate; disable charging */ if (ilim_uA < 1000000) { if (ilim_uA < 1000000) { pr_debug("ILIM %duA is too low to allow charging\n", ilim_uA); pr_debug("ILIM %duA is too low to allow charging\n", ilim_uA); vote(chip->disable_votable, ILIM_VOTER, true, 0); vote(chip->disable_votable, ILIM_VOTER, true, 0); } else { } else { pr_debug("setting ILIM to %duA\n", ilim_uA); pr_debug("ILIM set to %duA\n", ilim_uA); rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG, CFG_ILIM_MASK, DIV_ROUND_CLOSEST(ilim_uA - 500000, 100000)); if (rc < 0) pr_err("Failed to write ILIM Register, rc=%d\n", rc); if (rc >= 0) vote(chip->disable_votable, ILIM_VOTER, false, 0); vote(chip->disable_votable, ILIM_VOTER, false, 0); } } Loading Loading @@ -551,9 +581,13 @@ static void smb1390_status_change_work(struct work_struct *work) pval.intval); pval.intval); } } /* input current is always half the charge current */ /* vote(chip->ilim_votable, FCC_VOTER, true, * Remove SMB1390 Taper condition disable vote if float voltage get_effective_result(chip->fcc_votable) / 2); * increased in comparison to voltage at which it entered taper. */ if (chip->taper_entry_fv < get_effective_result(chip->fv_votable)) vote(chip->disable_votable, TAPER_END_VOTER, false, 0); /* /* * all votes that would result in disabling the charge pump have * all votes that would result in disabling the charge pump have Loading Loading @@ -581,6 +615,7 @@ static void smb1390_status_change_work(struct work_struct *work) } } } else { } else { vote(chip->disable_votable, SRC_VOTER, true, 0); 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->fcc_votable, CP_VOTER, false, 0); } } Loading @@ -598,11 +633,8 @@ static void smb1390_taper_work(struct work_struct *work) if (!is_psy_voter_available(chip)) if (!is_psy_voter_available(chip)) goto out; goto out; do { chip->taper_entry_fv = get_effective_result(chip->fv_votable); fcc_uA = get_effective_result(chip->fcc_votable) - 100000; while (true) { pr_debug("taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); rc = power_supply_get_property(chip->batt_psy, rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &pval); POWER_SUPPLY_PROP_CHARGE_TYPE, &pval); if (rc < 0) { if (rc < 0) { Loading @@ -610,12 +642,30 @@ static void smb1390_taper_work(struct work_struct *work) goto out; goto out; } } msleep(500); if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { } while (fcc_uA >= 2000000 fcc_uA = get_effective_result(chip->fcc_votable) && pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER); - 100000; pr_debug("taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); if (fcc_uA < 2000000) { vote(chip->disable_votable, TAPER_END_VOTER, true, 0); goto out; } } else if (get_effective_result(chip->fv_votable) > chip->taper_entry_fv) { pr_debug("Float voltage increased. Exiting taper\n"); goto out; } else { pr_debug("In fast charging. Wait for next taper\n"); } msleep(500); } out: out: pr_debug("taper work exit\n"); pr_debug("taper work exit\n"); vote(chip->fcc_votable, CP_VOTER, false, 0); chip->taper_work_running = false; chip->taper_work_running = false; } } Loading Loading @@ -817,6 +867,14 @@ static int smb1390_create_votables(struct smb1390 *chip) */ */ vote(chip->disable_votable, USER_VOTER, true, 0); vote(chip->disable_votable, USER_VOTER, true, 0); /* * In case SMB1390 probe happens after FCC value has been configured, * update ilim vote to reflect FCC / 2 value. */ if (chip->fcc_votable) vote(chip->ilim_votable, FCC_VOTER, true, get_effective_result(chip->fcc_votable) / 2); return 0; return 0; } } Loading Loading @@ -933,6 +991,7 @@ static int smb1390_probe(struct platform_device *pdev) chip->dev = &pdev->dev; chip->dev = &pdev->dev; spin_lock_init(&chip->status_change_lock); spin_lock_init(&chip->status_change_lock); mutex_init(&chip->die_chan_lock); mutex_init(&chip->die_chan_lock); chip->switcher_disabled = true; chip->regmap = dev_get_regmap(chip->dev->parent, NULL); chip->regmap = dev_get_regmap(chip->dev->parent, NULL); if (!chip->regmap) { if (!chip->regmap) { Loading drivers/power/supply/qcom/smb5-lib.c +15 −6 Original line number Original line Diff line number Diff line Loading @@ -2350,19 +2350,28 @@ static int smblib_update_thermal_readings(struct smb_charger *chg) } } if (chg->sec_chg_selected == POWER_SUPPLY_CHARGER_SEC_CP) { if (chg->sec_chg_selected == POWER_SUPPLY_CHARGER_SEC_CP) { rc = smblib_read_iio_channel(chg, chg->iio.smb_temp_chan, if (!chg->cp_psy) DIV_FACTOR_DECIDEGC, &chg->smb_temp); chg->cp_psy = if (rc < 0) { power_supply_get_by_name("charge_pump_master"); smblib_err(chg, "Couldn't read SMB TEMP channel, rc=%d\n", if (chg->cp_psy) { rc = power_supply_get_property(chg->cp_psy, POWER_SUPPLY_PROP_CP_DIE_TEMP, &pval); if (rc < 0) { smblib_err(chg, "Couldn't get smb1390 charger temp, rc=%d\n", rc); rc); return rc; return rc; } } chg->smb_temp = pval.intval; } else { smblib_dbg(chg, PR_MISC, "Coudln't find cp_psy\n"); chg->smb_temp = -ENODATA; } } else if (chg->pl.psy && chg->sec_chg_selected == } else if (chg->pl.psy && chg->sec_chg_selected == POWER_SUPPLY_CHARGER_SEC_PL) { POWER_SUPPLY_CHARGER_SEC_PL) { rc = power_supply_get_property(chg->pl.psy, rc = power_supply_get_property(chg->pl.psy, POWER_SUPPLY_PROP_CHARGER_TEMP, &pval); POWER_SUPPLY_PROP_CHARGER_TEMP, &pval); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't get smb charger temp, rc=%d\n", smblib_err(chg, "Couldn't get smb1355 charger temp, rc=%d\n", rc); rc); return rc; return rc; } } Loading Loading
arch/arm64/boot/dts/qcom/smb1390.dtsi +5 −5 Original line number Original line Diff line number Diff line Loading @@ -37,11 +37,11 @@ smb1390: qcom,smb1390@10 { status = "disabled"; status = "disabled"; qcom,core { qcom,core { interrupts = <0x10 0x0 IRQ_TYPE_EDGE_RISING>, interrupts = <0x10 0x0 IRQ_TYPE_EDGE_BOTH>, <0x10 0x1 IRQ_TYPE_EDGE_RISING>, <0x10 0x1 IRQ_TYPE_EDGE_BOTH>, <0x10 0x2 IRQ_TYPE_EDGE_RISING>, <0x10 0x2 IRQ_TYPE_EDGE_BOTH>, <0x10 0x3 IRQ_TYPE_EDGE_RISING>, <0x10 0x3 IRQ_TYPE_EDGE_BOTH>, <0x10 0x4 IRQ_TYPE_EDGE_RISING>, <0x10 0x4 IRQ_TYPE_EDGE_BOTH>, <0x10 0x5 IRQ_TYPE_EDGE_RISING>, <0x10 0x5 IRQ_TYPE_EDGE_RISING>, <0x10 0x6 IRQ_TYPE_EDGE_RISING>, <0x10 0x6 IRQ_TYPE_EDGE_RISING>, <0x10 0x7 IRQ_TYPE_EDGE_RISING>; <0x10 0x7 IRQ_TYPE_EDGE_RISING>; Loading
drivers/power/supply/qcom/battery.c +60 −2 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,7 @@ #define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER" #define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER" #define ICL_LIMIT_VOTER "ICL_LIMIT_VOTER" #define ICL_LIMIT_VOTER "ICL_LIMIT_VOTER" #define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER" #define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER" #define FCC_VOTER "FCC_VOTER" struct pl_data { struct pl_data { int pl_mode; int pl_mode; Loading @@ -63,6 +64,7 @@ struct pl_data { struct votable *hvdcp_hw_inov_dis_votable; struct votable *hvdcp_hw_inov_dis_votable; struct votable *usb_icl_votable; struct votable *usb_icl_votable; struct votable *pl_enable_votable_indirect; struct votable *pl_enable_votable_indirect; struct votable *cp_ilim_votable; struct delayed_work status_change_work; struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct work_struct pl_disable_forever_work; struct work_struct pl_taper_work; struct work_struct pl_taper_work; Loading @@ -74,6 +76,7 @@ struct pl_data { struct power_supply *batt_psy; struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *usb_psy; struct power_supply *dc_psy; struct power_supply *dc_psy; struct power_supply *cp_master_psy; int charge_type; int charge_type; int total_settled_ua; int total_settled_ua; int pl_settled_ua; int pl_settled_ua; Loading @@ -91,6 +94,7 @@ struct pl_data { struct wakeup_source *pl_ws; struct wakeup_source *pl_ws; struct notifier_block nb; struct notifier_block nb; bool pl_disable; bool pl_disable; bool cp_disabled; int taper_entry_fv; int taper_entry_fv; int main_fcc_max; int main_fcc_max; }; }; Loading Loading @@ -481,6 +485,46 @@ static void get_fcc_split(struct pl_data *chip, int total_ua, } } } } 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) goto out; rc = power_supply_get_property(chip->cp_master_psy, POWER_SUPPLY_PROP_CP_SWITCHER_EN, &pval); if (rc < 0) { pr_err("Couldn't get switcher enable status, rc=%d\n", rc); goto out; } if (!pval.intval) { /* * To honor main charger upper FCC limit, on CP switcher * disable, skip fcc slewing as it will cause delay in limiting * the charge current flowing through main charger. */ if (!chip->cp_disabled) { chip->fcc_stepper_enable = false; pl_dbg(chip, PR_PARALLEL, "Disabling FCC slewing on CP Switcher disable\n"); } chip->cp_disabled = true; } else { chip->cp_disabled = false; pl_dbg(chip, PR_PARALLEL, "CP Switcher is enabled, don't limit main fcc\n"); return; } out: *total_fcc = min(*total_fcc, chip->main_fcc_max); } static void get_fcc_stepper_params(struct pl_data *chip, int main_fcc_ua, static void get_fcc_stepper_params(struct pl_data *chip, int main_fcc_ua, int parallel_fcc_ua) int parallel_fcc_ua) { { Loading Loading @@ -623,6 +667,9 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, if (!chip->main_psy) if (!chip->main_psy) return 0; return 0; if (!chip->cp_ilim_votable) chip->cp_ilim_votable = find_votable("CP_ILIM"); if (chip->pl_mode != POWER_SUPPLY_PL_NONE) { if (chip->pl_mode != POWER_SUPPLY_PL_NONE) { get_fcc_split(chip, total_fcc_ua, &master_fcc_ua, get_fcc_split(chip, total_fcc_ua, &master_fcc_ua, &slave_fcc_ua); &slave_fcc_ua); Loading Loading @@ -819,6 +866,10 @@ static void fcc_stepper_work(struct work_struct *work) chip->main_fcc_ua = main_fcc; chip->main_fcc_ua = main_fcc; chip->slave_fcc_ua = parallel_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); if (reschedule_ms) { if (reschedule_ms) { schedule_delayed_work(&chip->fcc_stepper_work, schedule_delayed_work(&chip->fcc_stepper_work, msecs_to_jiffies(reschedule_ms)); msecs_to_jiffies(reschedule_ms)); Loading Loading @@ -934,6 +985,9 @@ static int usb_icl_vote_callback(struct votable *votable, void *data, vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0); 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); return 0; return 0; } } Loading Loading @@ -1166,8 +1220,7 @@ static int pl_disable_vote_callback(struct votable *votable, (slave_fcc_ua * 100) / total_fcc_ua); (slave_fcc_ua * 100) / total_fcc_ua); } else { } else { if (chip->main_fcc_max) if (chip->main_fcc_max) total_fcc_ua = min(total_fcc_ua, get_main_fcc_config(chip, &total_fcc_ua); chip->main_fcc_max); if (!chip->fcc_stepper_enable) { if (!chip->fcc_stepper_enable) { if (IS_USBIN(chip->pl_mode)) if (IS_USBIN(chip->pl_mode)) Loading @@ -1193,6 +1246,10 @@ static int pl_disable_vote_callback(struct votable *votable, return rc; return rc; } } if (chip->cp_ilim_votable) vote(chip->cp_ilim_votable, FCC_VOTER, true, total_fcc_ua / 2); /* reset parallel FCC */ /* reset parallel FCC */ chip->slave_fcc_ua = 0; chip->slave_fcc_ua = 0; chip->total_settled_ua = 0; chip->total_settled_ua = 0; Loading Loading @@ -1684,6 +1741,7 @@ int qcom_batt_init(int smb_version) } } chip->pl_disable = true; chip->pl_disable = true; chip->cp_disabled = true; chip->qcom_batt_class.name = "qcom-battery", chip->qcom_batt_class.name = "qcom-battery", chip->qcom_batt_class.owner = THIS_MODULE, chip->qcom_batt_class.owner = THIS_MODULE, chip->qcom_batt_class.class_groups = batt_class_groups; chip->qcom_batt_class.class_groups = batt_class_groups; Loading
drivers/power/supply/qcom/qpnp-smb5.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1435,6 +1435,9 @@ static int smb5_batt_set_prop(struct power_supply *psy, vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER, vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER, false, 0); false, 0); break; break; case POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE: chg->fcc_stepper_enable = val->intval; break; default: default: rc = -EINVAL; rc = -EINVAL; } } Loading
drivers/power/supply/qcom/smb1390-charger-psy.c +79 −20 Original line number Original line Diff line number Diff line Loading @@ -84,6 +84,7 @@ #define CP_VOTER "CP_VOTER" #define CP_VOTER "CP_VOTER" #define USER_VOTER "USER_VOTER" #define USER_VOTER "USER_VOTER" #define ILIM_VOTER "ILIM_VOTER" #define ILIM_VOTER "ILIM_VOTER" #define TAPER_END_VOTER "TAPER_END_VOTER" #define FCC_VOTER "FCC_VOTER" #define FCC_VOTER "FCC_VOTER" #define ICL_VOTER "ICL_VOTER" #define ICL_VOTER "ICL_VOTER" #define WIRELESS_VOTER "WIRELESS_VOTER" #define WIRELESS_VOTER "WIRELESS_VOTER" Loading Loading @@ -129,6 +130,7 @@ struct smb1390 { struct votable *disable_votable; struct votable *disable_votable; struct votable *ilim_votable; struct votable *ilim_votable; struct votable *fcc_votable; struct votable *fcc_votable; struct votable *fv_votable; struct votable *cp_awake_votable; struct votable *cp_awake_votable; /* power supplies */ /* power supplies */ Loading @@ -142,6 +144,8 @@ struct smb1390 { bool taper_work_running; bool taper_work_running; struct smb1390_iio iio; struct smb1390_iio iio; int irq_status; int irq_status; int taper_entry_fv; bool switcher_disabled; }; }; struct smb_irq { struct smb_irq { Loading Loading @@ -211,6 +215,19 @@ static bool is_psy_voter_available(struct smb1390 *chip) } } } } if (!chip->fv_votable) { chip->fv_votable = find_votable("FV"); if (!chip->fv_votable) { pr_debug("Couldn't find FV votable\n"); return false; } } if (!chip->disable_votable) { pr_debug("Couldn't find CP DISABLE votable\n"); return false; } return true; return true; } } Loading Loading @@ -254,7 +271,8 @@ static int smb1390_get_cp_en_status(struct smb1390 *chip, int id, bool *enable) static irqreturn_t default_irq_handler(int irq, void *data) static irqreturn_t default_irq_handler(int irq, void *data) { { struct smb1390 *chip = data; struct smb1390 *chip = data; int i; int i, rc; bool enable; for (i = 0; i < NUM_IRQS; ++i) { for (i = 0; i < NUM_IRQS; ++i) { if (irq == chip->irqs[i]) { if (irq == chip->irqs[i]) { Loading @@ -263,8 +281,18 @@ static irqreturn_t default_irq_handler(int irq, void *data) } } } } rc = smb1390_get_cp_en_status(chip, SWITCHER_EN, &enable); if (!rc) { if (chip->switcher_disabled == enable) { chip->switcher_disabled = !chip->switcher_disabled; if (chip->fcc_votable) rerun_election(chip->fcc_votable); } } if (chip->cp_master_psy) if (chip->cp_master_psy) power_supply_changed(chip->cp_master_psy); power_supply_changed(chip->cp_master_psy); return IRQ_HANDLED; return IRQ_HANDLED; } } Loading Loading @@ -442,18 +470,20 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data, return -EINVAL; return -EINVAL; } } rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG, CFG_ILIM_MASK, DIV_ROUND_CLOSEST(max(ilim_uA, 500000) - 500000, 100000)); if (rc < 0) { pr_err("Failed to write ILIM Register, rc=%d\n", rc); return rc; } /* ILIM less than 1A is not accurate; disable charging */ /* ILIM less than 1A is not accurate; disable charging */ if (ilim_uA < 1000000) { if (ilim_uA < 1000000) { pr_debug("ILIM %duA is too low to allow charging\n", ilim_uA); pr_debug("ILIM %duA is too low to allow charging\n", ilim_uA); vote(chip->disable_votable, ILIM_VOTER, true, 0); vote(chip->disable_votable, ILIM_VOTER, true, 0); } else { } else { pr_debug("setting ILIM to %duA\n", ilim_uA); pr_debug("ILIM set to %duA\n", ilim_uA); rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG, CFG_ILIM_MASK, DIV_ROUND_CLOSEST(ilim_uA - 500000, 100000)); if (rc < 0) pr_err("Failed to write ILIM Register, rc=%d\n", rc); if (rc >= 0) vote(chip->disable_votable, ILIM_VOTER, false, 0); vote(chip->disable_votable, ILIM_VOTER, false, 0); } } Loading Loading @@ -551,9 +581,13 @@ static void smb1390_status_change_work(struct work_struct *work) pval.intval); pval.intval); } } /* input current is always half the charge current */ /* vote(chip->ilim_votable, FCC_VOTER, true, * Remove SMB1390 Taper condition disable vote if float voltage get_effective_result(chip->fcc_votable) / 2); * increased in comparison to voltage at which it entered taper. */ if (chip->taper_entry_fv < get_effective_result(chip->fv_votable)) vote(chip->disable_votable, TAPER_END_VOTER, false, 0); /* /* * all votes that would result in disabling the charge pump have * all votes that would result in disabling the charge pump have Loading Loading @@ -581,6 +615,7 @@ static void smb1390_status_change_work(struct work_struct *work) } } } else { } else { vote(chip->disable_votable, SRC_VOTER, true, 0); 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->fcc_votable, CP_VOTER, false, 0); } } Loading @@ -598,11 +633,8 @@ static void smb1390_taper_work(struct work_struct *work) if (!is_psy_voter_available(chip)) if (!is_psy_voter_available(chip)) goto out; goto out; do { chip->taper_entry_fv = get_effective_result(chip->fv_votable); fcc_uA = get_effective_result(chip->fcc_votable) - 100000; while (true) { pr_debug("taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); rc = power_supply_get_property(chip->batt_psy, rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &pval); POWER_SUPPLY_PROP_CHARGE_TYPE, &pval); if (rc < 0) { if (rc < 0) { Loading @@ -610,12 +642,30 @@ static void smb1390_taper_work(struct work_struct *work) goto out; goto out; } } msleep(500); if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { } while (fcc_uA >= 2000000 fcc_uA = get_effective_result(chip->fcc_votable) && pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER); - 100000; pr_debug("taper work reducing FCC to %duA\n", fcc_uA); vote(chip->fcc_votable, CP_VOTER, true, fcc_uA); if (fcc_uA < 2000000) { vote(chip->disable_votable, TAPER_END_VOTER, true, 0); goto out; } } else if (get_effective_result(chip->fv_votable) > chip->taper_entry_fv) { pr_debug("Float voltage increased. Exiting taper\n"); goto out; } else { pr_debug("In fast charging. Wait for next taper\n"); } msleep(500); } out: out: pr_debug("taper work exit\n"); pr_debug("taper work exit\n"); vote(chip->fcc_votable, CP_VOTER, false, 0); chip->taper_work_running = false; chip->taper_work_running = false; } } Loading Loading @@ -817,6 +867,14 @@ static int smb1390_create_votables(struct smb1390 *chip) */ */ vote(chip->disable_votable, USER_VOTER, true, 0); vote(chip->disable_votable, USER_VOTER, true, 0); /* * In case SMB1390 probe happens after FCC value has been configured, * update ilim vote to reflect FCC / 2 value. */ if (chip->fcc_votable) vote(chip->ilim_votable, FCC_VOTER, true, get_effective_result(chip->fcc_votable) / 2); return 0; return 0; } } Loading Loading @@ -933,6 +991,7 @@ static int smb1390_probe(struct platform_device *pdev) chip->dev = &pdev->dev; chip->dev = &pdev->dev; spin_lock_init(&chip->status_change_lock); spin_lock_init(&chip->status_change_lock); mutex_init(&chip->die_chan_lock); mutex_init(&chip->die_chan_lock); chip->switcher_disabled = true; chip->regmap = dev_get_regmap(chip->dev->parent, NULL); chip->regmap = dev_get_regmap(chip->dev->parent, NULL); if (!chip->regmap) { if (!chip->regmap) { Loading
drivers/power/supply/qcom/smb5-lib.c +15 −6 Original line number Original line Diff line number Diff line Loading @@ -2350,19 +2350,28 @@ static int smblib_update_thermal_readings(struct smb_charger *chg) } } if (chg->sec_chg_selected == POWER_SUPPLY_CHARGER_SEC_CP) { if (chg->sec_chg_selected == POWER_SUPPLY_CHARGER_SEC_CP) { rc = smblib_read_iio_channel(chg, chg->iio.smb_temp_chan, if (!chg->cp_psy) DIV_FACTOR_DECIDEGC, &chg->smb_temp); chg->cp_psy = if (rc < 0) { power_supply_get_by_name("charge_pump_master"); smblib_err(chg, "Couldn't read SMB TEMP channel, rc=%d\n", if (chg->cp_psy) { rc = power_supply_get_property(chg->cp_psy, POWER_SUPPLY_PROP_CP_DIE_TEMP, &pval); if (rc < 0) { smblib_err(chg, "Couldn't get smb1390 charger temp, rc=%d\n", rc); rc); return rc; return rc; } } chg->smb_temp = pval.intval; } else { smblib_dbg(chg, PR_MISC, "Coudln't find cp_psy\n"); chg->smb_temp = -ENODATA; } } else if (chg->pl.psy && chg->sec_chg_selected == } else if (chg->pl.psy && chg->sec_chg_selected == POWER_SUPPLY_CHARGER_SEC_PL) { POWER_SUPPLY_CHARGER_SEC_PL) { rc = power_supply_get_property(chg->pl.psy, rc = power_supply_get_property(chg->pl.psy, POWER_SUPPLY_PROP_CHARGER_TEMP, &pval); POWER_SUPPLY_PROP_CHARGER_TEMP, &pval); if (rc < 0) { if (rc < 0) { smblib_err(chg, "Couldn't get smb charger temp, rc=%d\n", smblib_err(chg, "Couldn't get smb1355 charger temp, rc=%d\n", rc); rc); return rc; return rc; } } Loading