summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt6
-rw-r--r--drivers/power/supply/qcom/battery.c387
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c7
-rw-r--r--drivers/power/supply/qcom/smb-lib.c8
-rw-r--r--drivers/power/supply/qcom/smb-lib.h2
5 files changed, 359 insertions, 51 deletions
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
index f01eae10bf4f..30a26a8965bc 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
@@ -183,6 +183,12 @@ Charger specific properties:
Value type: bool
Definition: Boolean flag which when present enables sw compensation for jeita
+- qcom,fcc-stepping-enable
+ Usage: optional
+ Value type: bool
+ Definition: Boolean flag which when present enables stepwise change in FCC.
+ The default stepping rate is 100mA/sec.
+
=============================================
Second Level Nodes - SMB2 Charger Peripherals
=============================================
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index e068bec8b85e..6d5308b3dd0b 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -40,12 +40,14 @@
#define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER"
#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER"
#define USBIN_I_VOTER "USBIN_I_VOTER"
+#define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER"
struct pl_data {
int pl_mode;
int slave_pct;
int taper_pct;
int slave_fcc_ua;
+ int main_fcc_ua;
int restricted_current;
bool restricted_charging_enabled;
struct votable *fcc_votable;
@@ -59,6 +61,7 @@ struct pl_data {
struct work_struct pl_disable_forever_work;
struct delayed_work pl_taper_work;
struct delayed_work pl_awake_work;
+ struct delayed_work fcc_step_update_work;
struct power_supply *main_psy;
struct power_supply *pl_psy;
struct power_supply *batt_psy;
@@ -66,6 +69,13 @@ struct pl_data {
int charge_type;
int total_settled_ua;
int pl_settled_ua;
+ int fcc_step_update;
+ int main_step_fcc_dir;
+ int main_step_fcc_count;
+ int main_step_fcc_residual;
+ int parallel_step_fcc_dir;
+ int parallel_step_fcc_count;
+ int parallel_step_fcc_residual;
struct class qcom_batt_class;
struct wakeup_source *pl_ws;
struct notifier_block nb;
@@ -380,6 +390,10 @@ done:
* FCC *
**********/
#define EFFICIENCY_PCT 80
+#define FCC_STEP_SIZE_UA 100000
+#define FCC_STEP_UPDATE_DELAY_MS 1000
+#define STEP_UP 1
+#define STEP_DOWN -1
static void get_fcc_split(struct pl_data *chip, int total_ua,
int *master_ua, int *slave_ua)
{
@@ -432,6 +446,43 @@ static void get_fcc_split(struct pl_data *chip, int total_ua,
*slave_ua = (*slave_ua * chip->taper_pct) / 100;
}
+static void get_fcc_step_update_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_step_fcc_dir = (main_fcc_ua > pval.intval) ?
+ STEP_UP : STEP_DOWN;
+ chip->main_step_fcc_count = abs((main_fcc_ua - pval.intval) /
+ FCC_STEP_SIZE_UA);
+ chip->main_step_fcc_residual = (main_fcc_ua - pval.intval) %
+ FCC_STEP_SIZE_UA;
+
+ chip->parallel_step_fcc_dir = (parallel_fcc_ua > chip->slave_fcc_ua) ?
+ STEP_UP : STEP_DOWN;
+ chip->parallel_step_fcc_count = abs((parallel_fcc_ua -
+ chip->slave_fcc_ua) / FCC_STEP_SIZE_UA);
+ chip->parallel_step_fcc_residual = (parallel_fcc_ua -
+ chip->slave_fcc_ua) % FCC_STEP_SIZE_UA;
+
+ pr_debug("Main FCC Stepper parameters: main_step_direction: %d, main_step_count: %d, main_residual_fcc: %d\n",
+ chip->main_step_fcc_dir, chip->main_step_fcc_count,
+ chip->main_step_fcc_residual);
+ pr_debug("Parallel FCC Stepper parameters: parallel_step_direction: %d, parallel_step_count: %d, parallel_residual_fcc: %d\n",
+ chip->parallel_step_fcc_dir, chip->parallel_step_fcc_count,
+ chip->parallel_step_fcc_residual);
+}
+
static int pl_fcc_vote_callback(struct votable *votable, void *data,
int total_fcc_ua, const char *client)
{
@@ -445,80 +496,305 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data,
if (!chip->main_psy)
return 0;
+ if (!chip->batt_psy) {
+ chip->batt_psy = power_supply_get_by_name("battery");
+ if (!chip->batt_psy)
+ return 0;
+
+ rc = power_supply_get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't read FCC step update status, rc=%d\n",
+ rc);
+ return rc;
+ }
+ chip->fcc_step_update = pval.intval;
+ pr_debug("FCC Stepper %s\n",
+ pval.intval ? "enabled" : "disabled");
+ }
+
+ if (chip->fcc_step_update)
+ cancel_delayed_work_sync(&chip->fcc_step_update_work);
+
+
if (chip->pl_mode == POWER_SUPPLY_PL_NONE
|| get_effective_result_locked(chip->pl_disable_votable)) {
+ if (chip->fcc_step_update) {
+ vote(chip->pl_awake_votable, FCC_STEPPER_VOTER,
+ true, 0);
+ get_fcc_step_update_params(chip, total_fcc_ua, 0);
+ schedule_delayed_work(&chip->fcc_step_update_work, 0);
+
+ return 0;
+ }
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("Couldn't set main fcc, rc=%d\n", rc);
+
return rc;
}
if (chip->pl_mode != POWER_SUPPLY_PL_NONE) {
get_fcc_split(chip, total_fcc_ua,
&master_fcc_ua, &slave_fcc_ua);
+ if (chip->fcc_step_update) {
+ vote(chip->pl_awake_votable, FCC_STEPPER_VOTER,
+ true, 0);
+ get_fcc_step_update_params(chip, master_fcc_ua,
+ slave_fcc_ua);
+ schedule_delayed_work(&chip->fcc_step_update_work, 0);
+ } else {
+ /*
+ * If there is an increase in slave share
+ * (Also handles parallel enable case)
+ * Set Main ICL then slave FCC
+ * else
+ * (Also handles parallel disable case)
+ * 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;
+ }
- /*
- * If there is an increase in slave share
- * (Also handles parallel enable case)
- * Set Main ICL then slave FCC
- * else
- * (Also handles parallel disable case)
- * 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,
+ pval.intval = slave_fcc_ua;
+ rc = power_supply_set_property(chip->pl_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;
+ if (rc < 0) {
+ pr_err("Couldn't set parallel fcc, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ chip->slave_fcc_ua = slave_fcc_ua;
+ } else {
+ pval.intval = slave_fcc_ua;
+ rc = power_supply_set_property(chip->pl_psy,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ &pval);
+ if (rc < 0) {
+ pr_err("Couldn't set parallel fcc, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ 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;
+ }
}
+ }
+ }
+
+ pl_dbg(chip, PR_PARALLEL, "master_fcc=%d slave_fcc=%d distribution=(%d/%d)\n",
+ master_fcc_ua, slave_fcc_ua,
+ (master_fcc_ua * 100) / total_fcc_ua,
+ (slave_fcc_ua * 100) / total_fcc_ua);
+
+ return 0;
+}
+
+static void fcc_step_update_work(struct work_struct *work)
+{
+ struct pl_data *chip = container_of(work,
+ struct pl_data, fcc_step_update_work.work);
+ union power_supply_propval pval = {0, };
+ int reschedule_ms = 0, rc = 0;
+ int main_fcc = chip->main_fcc_ua;
+ int parallel_fcc = chip->slave_fcc_ua;
+
+ if (!chip->usb_psy) {
+ chip->usb_psy = power_supply_get_by_name("usb");
+ if (!chip->usb_psy) {
+ pr_err("Couldn't get usb psy\n");
+ return;
+ }
+ }
+
+ /* Check whether USB is present or not */
+ rc = power_supply_get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_PRESENT, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't get USB Present status, rc=%d\n", rc);
+ return;
+ }
+
+ /*
+ * If USB is not present, then disable parallel and
+ * Main FCC to the effective value of FCC votable and exit.
+ */
+ if (!pval.intval) {
+ /* Disable parallel */
+ parallel_fcc = 0;
+ pval.intval = 1;
+ rc = power_supply_set_property(chip->pl_psy,
+ POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
+ if (rc < 0)
+ pr_err("Couldn't change slave suspend state rc=%d\n",
+ rc);
+
+ 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);
+ return;
+ }
+
+ goto stepper_exit;
+ }
+
+ if (chip->main_step_fcc_count) {
+ main_fcc += (FCC_STEP_SIZE_UA * chip->main_step_fcc_dir);
+ chip->main_step_fcc_count--;
+ reschedule_ms = FCC_STEP_UPDATE_DELAY_MS;
+ } else if (chip->main_step_fcc_residual) {
+ main_fcc += chip->main_step_fcc_residual;
+ chip->main_step_fcc_residual = 0;
+ }
- pval.intval = slave_fcc_ua;
+ if (chip->parallel_step_fcc_count) {
+ parallel_fcc += (FCC_STEP_SIZE_UA *
+ chip->parallel_step_fcc_dir);
+ chip->parallel_step_fcc_count--;
+ reschedule_ms = FCC_STEP_UPDATE_DELAY_MS;
+ } else if (chip->parallel_step_fcc_residual) {
+ parallel_fcc += chip->parallel_step_fcc_residual;
+ chip->parallel_step_fcc_residual = 0;
+ }
+
+ if (chip->pl_mode == POWER_SUPPLY_PL_NONE ||
+ get_effective_result_locked(chip->pl_disable_votable)) {
+ /* Set Parallel FCC */
+ pval.intval = parallel_fcc;
+ rc = power_supply_set_property(chip->pl_psy,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't set parallel charger fcc, rc=%d\n",
+ rc);
+ return;
+ }
+
+ /* 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);
+ return;
+ }
+
+ if (parallel_fcc < MINIMUM_PARALLEL_FCC_UA) {
+ pval.intval = 1;
+ rc = power_supply_set_property(chip->pl_psy,
+ POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't change slave suspend state rc=%d\n",
+ rc);
+ return;
+ }
+ }
+ } else {
+ if (parallel_fcc < chip->slave_fcc_ua) {
+ pval.intval = parallel_fcc;
rc = power_supply_set_property(chip->pl_psy,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
&pval);
if (rc < 0) {
- pr_err("Couldn't set parallel fcc, rc=%d\n",
- rc);
- return rc;
+ pr_err("Couldn't set parallel charger fcc, rc=%d\n",
+ rc);
+ return;
}
- chip->slave_fcc_ua = slave_fcc_ua;
+ 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);
+ return;
+ }
} else {
- pval.intval = slave_fcc_ua;
- rc = power_supply_set_property(chip->pl_psy,
+ 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 parallel fcc, rc=%d\n",
- rc);
- return rc;
+ pr_err("Couldn't set main charger fcc, rc=%d\n",
+ rc);
+ return;
}
- chip->slave_fcc_ua = slave_fcc_ua;
-
- pval.intval = master_fcc_ua;
- rc = power_supply_set_property(chip->main_psy,
+ pval.intval = parallel_fcc;
+ rc = power_supply_set_property(chip->pl_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;
+ pr_err("Couldn't set parallel charger fcc, rc=%d\n",
+ rc);
+ return;
+ }
+ }
+
+ rc = power_supply_get_property(chip->pl_psy,
+ POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't get slave suspend status, rc=%d\n",
+ rc);
+ return;
+ }
+
+ /*
+ * Enable parallel charger only if it was disabled earlier and
+ * configured slave fcc is greater than or equal to 100mA.
+ */
+ if (pval.intval == 1 && parallel_fcc >= 100000) {
+ pval.intval = 0;
+ rc = power_supply_set_property(chip->pl_psy,
+ POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't change slave suspend state rc=%d\n",
+ rc);
+ return;
}
+
+ if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) ||
+ (chip->pl_mode ==
+ POWER_SUPPLY_PL_USBIN_USBIN_EXT))
+ split_settled(chip);
}
}
- pl_dbg(chip, PR_PARALLEL, "master_fcc=%d slave_fcc=%d distribution=(%d/%d)\n",
- master_fcc_ua, slave_fcc_ua,
- (master_fcc_ua * 100) / total_fcc_ua,
- (slave_fcc_ua * 100) / total_fcc_ua);
+stepper_exit:
+ chip->main_fcc_ua = main_fcc;
+ chip->slave_fcc_ua = parallel_fcc;
- return 0;
+ if (reschedule_ms) {
+ schedule_delayed_work(&chip->fcc_step_update_work,
+ msecs_to_jiffies(reschedule_ms));
+ pr_debug("Rescheduling FCC_STEPPER work\n");
+ } else {
+ vote(chip->pl_awake_votable, FCC_STEPPER_VOTER, false, 0);
+ }
}
#define PARALLEL_FLOAT_VOLTAGE_DELTA_UV 50000
@@ -660,6 +936,9 @@ static int pl_disable_vote_callback(struct votable *votable,
chip->total_settled_ua = 0;
chip->pl_settled_ua = 0;
+ /* Cancel FCC step change work */
+ cancel_delayed_work_sync(&chip->fcc_step_update_work);
+
if (!pl_disable) { /* enable */
/* keep system awake to talk to slave charger through i2c */
cancel_delayed_work_sync(&chip->pl_awake_work);
@@ -685,16 +964,19 @@ static int pl_disable_vote_callback(struct votable *votable,
* PARALLEL_PSY_VOTER keeps it disabled unless a pl_psy
* is seen.
*/
- pval.intval = 0;
- rc = power_supply_set_property(chip->pl_psy,
+ if (!chip->fcc_step_update) {
+ pval.intval = 0;
+ rc = power_supply_set_property(chip->pl_psy,
POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
- if (rc < 0)
- pr_err("Couldn't change slave suspend state rc=%d\n",
- rc);
+ if (rc < 0)
+ pr_err("Couldn't change slave suspend state rc=%d\n",
+ rc);
- if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
- || (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
- split_settled(chip);
+ if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) ||
+ (chip->pl_mode ==
+ POWER_SUPPLY_PL_USBIN_USBIN_EXT))
+ split_settled(chip);
+ }
/*
* we could have been enabled while in taper mode,
* start the taper work if so
@@ -715,15 +997,18 @@ static int pl_disable_vote_callback(struct votable *votable,
|| (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
split_settled(chip);
- /* pl_psy may be NULL while in the disable branch */
- if (chip->pl_psy) {
- pval.intval = 1;
- rc = power_supply_set_property(chip->pl_psy,
+ if (!chip->fcc_step_update) {
+ /* pl_psy may be NULL while in the disable branch */
+ if (chip->pl_psy) {
+ pval.intval = 1;
+ rc = power_supply_set_property(chip->pl_psy,
POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
- if (rc < 0)
- pr_err("Couldn't change slave suspend state rc=%d\n",
- rc);
+ if (rc < 0)
+ pr_err("Couldn't change slave suspend state rc=%d\n",
+ rc);
+ }
}
+
rerun_election(chip->fcc_votable);
rerun_election(chip->fv_votable);
@@ -1118,6 +1403,7 @@ int qcom_batt_init(void)
INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work);
INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work);
INIT_DELAYED_WORK(&chip->pl_awake_work, pl_awake_work);
+ INIT_DELAYED_WORK(&chip->fcc_step_update_work, fcc_step_update_work);
rc = pl_register_notifier(chip);
if (rc < 0) {
@@ -1172,6 +1458,7 @@ void qcom_batt_deinit(void)
cancel_delayed_work_sync(&chip->pl_taper_work);
cancel_work_sync(&chip->pl_disable_forever_work);
cancel_delayed_work_sync(&chip->pl_awake_work);
+ cancel_delayed_work_sync(&chip->fcc_step_update_work);
power_supply_unreg_notifier(&chip->nb);
destroy_votable(chip->pl_enable_votable_indirect);
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 02b1204789bf..8e57bf9d2c31 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -325,6 +325,9 @@ static int smb2_parse_dt(struct smb2 *chip)
if (rc < 0)
chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
+ chg->fcc_stepper_mode = of_property_read_bool(node,
+ "qcom,fcc-stepping-enable");
+
return 0;
}
@@ -941,6 +944,7 @@ static enum power_supply_property smb2_batt_props[] = {
POWER_SUPPLY_PROP_RERUN_AICL,
POWER_SUPPLY_PROP_DP_DM,
POWER_SUPPLY_PROP_CHARGE_COUNTER,
+ POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE,
};
static int smb2_batt_get_prop(struct power_supply *psy,
@@ -1049,6 +1053,9 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_COUNTER:
rc = smblib_get_prop_batt_charge_counter(chg, val);
break;
+ case POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE:
+ val->intval = chg->fcc_stepper_mode;
+ break;
default:
pr_err("batt power supply prop %d not supported\n", psp);
return -EINVAL;
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 8eee480e4380..e96523a4d43e 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -3360,7 +3360,8 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
rc = smblib_request_dpdm(chg, true);
if (rc < 0)
smblib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc);
-
+ if (chg->fcc_stepper_mode)
+ vote(chg->fcc_votable, FCC_STEPPER_VOTER, false, 0);
/* Schedule work to enable parallel charger */
vote(chg->awake_votable, PL_DELAY_VOTER, true, 0);
schedule_delayed_work(&chg->pl_enable_work,
@@ -3379,6 +3380,11 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
}
}
+ /* Force 1500mA FCC on removal */
+ if (chg->fcc_stepper_mode)
+ vote(chg->fcc_votable, FCC_STEPPER_VOTER,
+ true, 1500000);
+
rc = smblib_request_dpdm(chg, false);
if (rc < 0)
smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 0de99b9da7bd..4475ccc21a2a 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -67,6 +67,7 @@ enum print_reason {
#define WEAK_CHARGER_VOTER "WEAK_CHARGER_VOTER"
#define WBC_VOTER "WBC_VOTER"
#define OV_VOTER "OV_VOTER"
+#define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER"
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
@@ -346,6 +347,7 @@ struct smb_charger {
u8 float_cfg;
bool use_extcon;
bool otg_present;
+ bool fcc_stepper_mode;
/* workaround flag */
u32 wa_flags;