Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b186b398 authored by Abhijeet Dharmapurikar's avatar Abhijeet Dharmapurikar
Browse files

smb-lib: do not disable parallel based only on main's settled current



Currently main charger ends up voting to disable parallel(USBIN_I_VOTER)
if the settled current is less than 1.4Amps. It could be that the
parallel path is drawing some current and the draw is higher than
1.4Amps.

Move this disabling to battery, where the parallel charger's input current
is taken in to consideration.

Also while voting to disable, make sure that the main's input is limited.
If there is more room for ICL to increase that means more power could be
drawn from the charger and so we must keep the parallel charging enabled.
If the ICL ceiling itself if 1.4Amps then disable parallel charging,
because even if ICL has room to increase it wont cross 1.4Amps.

The main's input limited state is set while AICL steps up - this
ensures that we keep parallel disabled while AICL is running and settled
is less than 1.4Amps.

When the charger is removed, the main's input limited status is unset,
however we want to keep the parallel charger disabled. In such situations
the main's settled current is 0mA - use this to vote for disabling
parallel charging.

For any ICL change vote request:
Disable parallel using USBIN_I_VOTER if requested current is less than
1.4Amps and to un-vote (i.e. when ICL vote is higher than 1.4Amps) rely
on event from AICL done or status_change delayed work.

Note that USBIN_I_VOTER is effective only for non-QC chargers. For QC
chargers USBIN_V_VOTER continues to keep charging enabled since parallel
need not be disabled is a lower current is requested with a QC charger.

Change-Id: I61d7cd161a87de2904470b2d870058a0fe199116
Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
parent 5404e350
Loading
Loading
Loading
Loading
+86 −15
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@
#define PL_VOTER			"PL_VOTER"
#define RESTRICT_CHG_VOTER		"RESTRICT_CHG_VOTER"
#define ICL_CHANGE_VOTER		"ICL_CHANGE_VOTER"
#define PL_INDIRECT_VOTER		"PL_INDIRECT_VOTER"
#define USBIN_I_VOTER			"USBIN_I_VOTER"

struct pl_data {
	int			pl_mode;
@@ -52,7 +54,8 @@ struct pl_data {
	struct votable		*pl_awake_votable;
	struct votable		*hvdcp_hw_inov_dis_votable;
	struct votable		*usb_icl_votable;
	struct work_struct	status_change_work;
	struct votable		*pl_enable_votable_indirect;
	struct delayed_work	status_change_work;
	struct work_struct	pl_disable_forever_work;
	struct delayed_work	pl_taper_work;
	struct power_supply	*main_psy;
@@ -490,6 +493,7 @@ static int pl_fv_vote_callback(struct votable *votable, void *data,
}

#define ICL_STEP_UA	25000
#define PL_DELAY_MS     3000
static int usb_icl_vote_callback(struct votable *votable, void *data,
			int icl_ua, const char *client)
{
@@ -511,6 +515,21 @@ static int usb_icl_vote_callback(struct votable *votable, void *data,
	 */
	vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, true, 0);

	/*
	 * if (ICL < 1400)
	 *	disable parallel charger using USBIN_I_VOTER
	 * else
	 *	instead of re-enabling here rely on status_changed_work
	 *	(triggered via AICL completed or scheduled from here to
	 *	unvote USBIN_I_VOTER) the status_changed_work enables
	 *	USBIN_I_VOTER based on settled current.
	 */
	if (icl_ua <= 1400000)
		vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
	else
		schedule_delayed_work(&chip->status_change_work,
						msecs_to_jiffies(PL_DELAY_MS));

	/* rerun AICL */
	/* get the settled current */
	rc = power_supply_get_property(chip->main_psy,
@@ -642,6 +661,16 @@ static int pl_disable_vote_callback(struct votable *votable,
	return 0;
}

static int pl_enable_indirect_vote_callback(struct votable *votable,
			void *data, int pl_enable, const char *client)
{
	struct pl_data *chip = data;

	vote(chip->pl_disable_votable, PL_INDIRECT_VOTER, !pl_enable, 0);

	return 0;
}

static int pl_awake_vote_callback(struct votable *votable,
			void *data, int awake, const char *client)
{
@@ -774,12 +803,12 @@ static void handle_settled_icl_change(struct pl_data *chip)
	union power_supply_propval pval = {0, };
	int new_total_settled_ua;
	int rc;
	int main_settled_ua;
	int main_limited;
	int total_current_ua;

	if (get_effective_result(chip->pl_disable_votable))
		return;
	total_current_ua = get_effective_result_locked(chip->usb_icl_votable);

	if (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN
			|| chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT) {
	/*
	 * call aicl split only when USBIN_USBIN and enabled
	 * and if aicl changed
@@ -791,8 +820,37 @@ static void handle_settled_icl_change(struct pl_data *chip)
		pr_err("Couldn't get aicl settled value rc=%d\n", rc);
		return;
	}
	main_settled_ua = pval.intval;

		new_total_settled_ua = pval.intval + chip->pl_settled_ua;
	rc = power_supply_get_property(chip->batt_psy,
			       POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
			       &pval);
	if (rc < 0) {
		pr_err("Couldn't get aicl settled value rc=%d\n", rc);
		return;
	}
	main_limited = pval.intval;

	if ((main_limited && (main_settled_ua + chip->pl_settled_ua) < 1400000)
			|| (main_settled_ua == 0)
			|| ((total_current_ua >= 0) &&
				(total_current_ua <= 1400000)))
		vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
	else
		vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, true, 0);


	if (get_effective_result(chip->pl_disable_votable))
		return;

	if (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN
			|| chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT) {
		/*
		 * call aicl split only when USBIN_USBIN and enabled
		 * and if settled current has changed by more than 300mA
		 */

		new_total_settled_ua = main_settled_ua + chip->pl_settled_ua;
		pl_dbg(chip, PR_PARALLEL,
			"total_settled_ua=%d settled_ua=%d new_total_settled_ua=%d\n",
			chip->total_settled_ua, pval.intval,
@@ -839,7 +897,7 @@ static void handle_parallel_in_taper(struct pl_data *chip)
static void status_change_work(struct work_struct *work)
{
	struct pl_data *chip = container_of(work,
			struct pl_data, status_change_work);
			struct pl_data, status_change_work.work);

	if (!chip->main_psy && is_main_available(chip)) {
		/*
@@ -877,7 +935,7 @@ static int pl_notifier_call(struct notifier_block *nb,
	if ((strcmp(psy->desc->name, "parallel") == 0)
	    || (strcmp(psy->desc->name, "battery") == 0)
	    || (strcmp(psy->desc->name, "main") == 0))
		schedule_work(&chip->status_change_work);
		schedule_delayed_work(&chip->status_change_work, 0);

	return NOTIFY_OK;
}
@@ -898,7 +956,7 @@ static int pl_register_notifier(struct pl_data *chip)

static int pl_determine_initial_status(struct pl_data *chip)
{
	status_change_work(&chip->status_change_work);
	status_change_work(&chip->status_change_work.work);
	return 0;
}

@@ -967,7 +1025,18 @@ int qcom_batt_init(void)
		goto destroy_votable;
	}

	INIT_WORK(&chip->status_change_work, status_change_work);
	chip->pl_enable_votable_indirect = create_votable("PL_ENABLE_INDIRECT",
					VOTE_SET_ANY,
					pl_enable_indirect_vote_callback,
					chip);
	if (IS_ERR(chip->pl_enable_votable_indirect)) {
		rc = PTR_ERR(chip->pl_enable_votable_indirect);
		return rc;
	}

	vote(chip->pl_disable_votable, PL_INDIRECT_VOTER, true, 0);

	INIT_DELAYED_WORK(&chip->status_change_work, status_change_work);
	INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work);
	INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work);

@@ -1000,6 +1069,7 @@ int qcom_batt_init(void)
unreg_notifier:
	power_supply_unreg_notifier(&chip->nb);
destroy_votable:
	destroy_votable(chip->pl_enable_votable_indirect);
	destroy_votable(chip->pl_awake_votable);
	destroy_votable(chip->pl_disable_votable);
	destroy_votable(chip->fv_votable);
@@ -1019,11 +1089,12 @@ void qcom_batt_deinit(void)
	if (chip == NULL)
		return;

	cancel_work_sync(&chip->status_change_work);
	cancel_delayed_work_sync(&chip->status_change_work);
	cancel_delayed_work_sync(&chip->pl_taper_work);
	cancel_work_sync(&chip->pl_disable_forever_work);

	power_supply_unreg_notifier(&chip->nb);
	destroy_votable(chip->pl_enable_votable_indirect);
	destroy_votable(chip->pl_awake_votable);
	destroy_votable(chip->pl_disable_votable);
	destroy_votable(chip->fv_votable);
+10 −23
Original line number Diff line number Diff line
@@ -1047,16 +1047,6 @@ static int smblib_chg_disable_vote_callback(struct votable *votable, void *data,
	return 0;
}

static int smblib_pl_enable_indirect_vote_callback(struct votable *votable,
			void *data, int chg_enable, const char *client)
{
	struct smb_charger *chg = data;

	vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, !chg_enable, 0);

	return 0;
}

static int smblib_hvdcp_enable_vote_callback(struct votable *votable,
			void *data,
			int hvdcp_enable, const char *client)
@@ -4218,8 +4208,6 @@ static void smblib_icl_change_work(struct work_struct *work)
	}

	power_supply_changed(chg->usb_main_psy);
	vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
				settled_ua >= USB_WEAK_INPUT_UA, 0);

	smblib_dbg(chg, PR_INTERRUPT, "icl_settled=%d\n", settled_ua);
}
@@ -4315,7 +4303,16 @@ static int smblib_create_votables(struct smb_charger *chg)
		smblib_err(chg, "Couldn't find votable PL_DISABLE rc=%d\n", rc);
		return rc;
	}
	vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0);

	chg->pl_enable_votable_indirect = find_votable("PL_ENABLE_INDIRECT");
	if (chg->pl_enable_votable_indirect == NULL) {
		rc = -EINVAL;
		smblib_err(chg,
			"Couldn't find votable PL_ENABLE_INDIRECT rc=%d\n",
			rc);
		return rc;
	}

	vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);

	chg->dc_suspend_votable = create_votable("DC_SUSPEND", VOTE_SET_ANY,
@@ -4365,14 +4362,6 @@ static int smblib_create_votables(struct smb_charger *chg)
		return rc;
	}

	chg->pl_enable_votable_indirect = create_votable("PL_ENABLE_INDIRECT",
					VOTE_SET_ANY,
					smblib_pl_enable_indirect_vote_callback,
					chg);
	if (IS_ERR(chg->pl_enable_votable_indirect)) {
		rc = PTR_ERR(chg->pl_enable_votable_indirect);
		return rc;
	}

	chg->hvdcp_disable_votable_indirect = create_votable(
				"HVDCP_DISABLE_INDIRECT",
@@ -4448,8 +4437,6 @@ static void smblib_destroy_votables(struct smb_charger *chg)
		destroy_votable(chg->awake_votable);
	if (chg->chg_disable_votable)
		destroy_votable(chg->chg_disable_votable);
	if (chg->pl_enable_votable_indirect)
		destroy_votable(chg->pl_enable_votable_indirect);
	if (chg->apsd_disable_votable)
		destroy_votable(chg->apsd_disable_votable);
	if (chg->hvdcp_hw_inov_dis_votable)
+1 −2
Original line number Diff line number Diff line
@@ -36,9 +36,7 @@ enum print_reason {
#define PL_USBIN_USBIN_VOTER		"PL_USBIN_USBIN_VOTER"
#define USB_PSY_VOTER			"USB_PSY_VOTER"
#define PL_TAPER_WORK_RUNNING_VOTER	"PL_TAPER_WORK_RUNNING_VOTER"
#define PL_INDIRECT_VOTER		"PL_INDIRECT_VOTER"
#define PL_QNOVO_VOTER			"PL_QNOVO_VOTER"
#define USBIN_I_VOTER			"USBIN_I_VOTER"
#define USBIN_V_VOTER			"USBIN_V_VOTER"
#define CHG_STATE_VOTER			"CHG_STATE_VOTER"
#define TYPEC_SRC_VOTER			"TYPEC_SRC_VOTER"
@@ -65,6 +63,7 @@ enum print_reason {
#define QNOVO_VOTER			"QNOVO_VOTER"
#define BATT_PROFILE_VOTER		"BATT_PROFILE_VOTER"
#define OTG_DELAY_VOTER			"OTG_DELAY_VOTER"
#define USBIN_I_VOTER			"USBIN_I_VOTER"

#define VCONN_MAX_ATTEMPTS	3
#define OTG_MAX_ATTEMPTS	3