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

Commit bfcf674d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qcom: battery: Raise parallel FCC above 500mA minimum"

parents 4d250f36 a796cf75
Loading
Loading
Loading
Loading
+132 −108
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#define ICL_CHANGE_VOTER		"ICL_CHANGE_VOTER"
#define PL_INDIRECT_VOTER		"PL_INDIRECT_VOTER"
#define USBIN_I_VOTER			"USBIN_I_VOTER"
#define FCC_CHANGE_VOTER		"FCC_CHANGE_VOTER"

struct pl_data {
	int			pl_mode;
@@ -288,69 +289,11 @@ static struct class_attribute pl_attributes[] = {
	__ATTR_NULL,
};

/***********
 *  TAPER  *
 ************/
#define MINIMUM_PARALLEL_FCC_UA		500000
#define PL_TAPER_WORK_DELAY_MS		100
#define TAPER_RESIDUAL_PCT		75
static void pl_taper_work(struct work_struct *work)
{
	struct pl_data *chip = container_of(work, struct pl_data,
						pl_taper_work.work);
	union power_supply_propval pval = {0, };
	int rc;

	/* exit immediately if parallel is disabled */
	if (get_effective_result(chip->pl_disable_votable)) {
		pl_dbg(chip, PR_PARALLEL, "terminating parallel not in progress\n");
		goto done;
	}

	pl_dbg(chip, PR_PARALLEL, "entering parallel taper work slave_fcc = %d\n",
			chip->slave_fcc_ua);
	if (chip->slave_fcc_ua < MINIMUM_PARALLEL_FCC_UA) {
		pl_dbg(chip, PR_PARALLEL, "terminating parallel's share lower than 500mA\n");
		vote(chip->pl_disable_votable, TAPER_END_VOTER, true, 0);
		goto done;
	}

	rc = power_supply_get_property(chip->batt_psy,
			       POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
	if (rc < 0) {
		pr_err("Couldn't get batt charge type rc=%d\n", rc);
		goto done;
	}

	chip->charge_type = pval.intval;
	if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) {
		pl_dbg(chip, PR_PARALLEL, "master is taper charging; reducing slave FCC\n");

		vote(chip->pl_awake_votable, TAPER_END_VOTER, true, 0);
		/* Reduce the taper percent by 25 percent */
		chip->taper_pct = chip->taper_pct * TAPER_RESIDUAL_PCT / 100;
		rerun_election(chip->fcc_votable);
		pl_dbg(chip, PR_PARALLEL, "taper entry scheduling work after %d ms\n",
				PL_TAPER_WORK_DELAY_MS);
		schedule_delayed_work(&chip->pl_taper_work,
				msecs_to_jiffies(PL_TAPER_WORK_DELAY_MS));
		return;
	}

	/*
	 * Master back to Fast Charge, get out of this round of taper reduction
	 */
	pl_dbg(chip, PR_PARALLEL, "master is fast charging; waiting for next taper\n");

done:
	vote(chip->pl_awake_votable, TAPER_END_VOTER, false, 0);
}

/*********
 *  FCC  *
 **********/
#define EFFICIENCY_PCT	80
static void split_fcc(struct pl_data *chip, int total_ua,
static void get_fcc_split(struct pl_data *chip, int total_ua,
			int *master_ua, int *slave_ua)
{
	int rc, effective_total_ua, slave_limited_ua, hw_cc_delta_ua = 0,
@@ -389,7 +332,7 @@ static void split_fcc(struct pl_data *chip, int total_ua,
	effective_total_ua = max(0, total_ua + hw_cc_delta_ua);
	slave_limited_ua = min(effective_total_ua, bcl_ua);
	*slave_ua = (slave_limited_ua * chip->slave_pct) / 100;
	*slave_ua = (*slave_ua * chip->taper_pct) / 100;

	/*
	 * In USBIN_USBIN configuration with internal rsense parallel
	 * charger's current goes through main charger's BATFET, keep
@@ -399,14 +342,75 @@ static void split_fcc(struct pl_data *chip, int total_ua,
		*master_ua = max(0, total_ua);
	else
		*master_ua = max(0, total_ua - *slave_ua);

	/* further reduce slave's share in accordance with taper reductions */
	*slave_ua = (*slave_ua * chip->taper_pct) / 100;
}

#define MINIMUM_PARALLEL_FCC_UA		500000
#define PL_TAPER_WORK_DELAY_MS		100
#define TAPER_RESIDUAL_PCT		90
static void pl_taper_work(struct work_struct *work)
{
	struct pl_data *chip = container_of(work, struct pl_data,
						pl_taper_work.work);
	union power_supply_propval pval = {0, };
	int total_fcc_ua, master_fcc_ua, slave_fcc_ua;
	int rc;

	/* exit immediately if parallel is disabled */
	if (get_effective_result(chip->pl_disable_votable)) {
		pl_dbg(chip, PR_PARALLEL, "terminating parallel not in progress\n");
		goto done;
	}

	total_fcc_ua = get_effective_result_locked(chip->fcc_votable);
	get_fcc_split(chip, total_fcc_ua, &master_fcc_ua, &slave_fcc_ua);
	if (slave_fcc_ua < MINIMUM_PARALLEL_FCC_UA) {
		pl_dbg(chip, PR_PARALLEL, "terminating parallel's share lower than 500mA\n");
		vote(chip->pl_disable_votable, TAPER_END_VOTER, true, 0);
		goto done;
	}

	pl_dbg(chip, PR_PARALLEL, "entering parallel taper work slave_fcc = %d\n",
		slave_fcc_ua);

	rc = power_supply_get_property(chip->batt_psy,
			       POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
	if (rc < 0) {
		pr_err("Couldn't get batt charge type rc=%d\n", rc);
		goto done;
	}

	chip->charge_type = pval.intval;
	if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) {
		pl_dbg(chip, PR_PARALLEL, "master is taper charging; reducing slave FCC\n");

		vote(chip->pl_awake_votable, TAPER_END_VOTER, true, 0);
		/* Reduce the taper percent by 10 percent */
		chip->taper_pct = chip->taper_pct * TAPER_RESIDUAL_PCT / 100;
		rerun_election(chip->fcc_votable);
		pl_dbg(chip, PR_PARALLEL, "taper entry scheduling work after %d ms\n",
				PL_TAPER_WORK_DELAY_MS);
		schedule_delayed_work(&chip->pl_taper_work,
				msecs_to_jiffies(PL_TAPER_WORK_DELAY_MS));
		return;
	}

	/*
	 * Master back to Fast Charge, get out of this round of taper reduction
	 */
	pl_dbg(chip, PR_PARALLEL, "master is fast charging; waiting for next taper\n");

done:
	vote(chip->pl_awake_votable, TAPER_END_VOTER, false, 0);
}

static int pl_fcc_vote_callback(struct votable *votable, void *data,
			int total_fcc_ua, const char *client)
{
	struct pl_data *chip = data;
	union power_supply_propval pval = {0, };
	int rc, master_fcc_ua = total_fcc_ua, slave_fcc_ua = 0;
	int master_fcc_ua = total_fcc_ua, slave_fcc_ua = 0;

	if (total_fcc_ua < 0)
		return 0;
@@ -414,41 +418,23 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data,
	if (!chip->main_psy)
		return 0;

	if (chip->pl_mode == POWER_SUPPLY_PL_NONE
	    || get_effective_result_locked(chip->pl_disable_votable)) {
		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) {
		split_fcc(chip, total_fcc_ua, &master_fcc_ua, &slave_fcc_ua);

		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;
		}
		get_fcc_split(chip, total_fcc_ua, &master_fcc_ua,
				&slave_fcc_ua);

		if (slave_fcc_ua > 500000) {
			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->pl_disable_votable, FCC_CHANGE_VOTER,
							false, 0);
		} else {
			chip->slave_fcc_ua = 0;
			vote(chip->pl_disable_votable, FCC_CHANGE_VOTER,
							true, 0);
		}
	}

	rerun_election(chip->pl_disable_votable);

	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,
@@ -577,18 +563,34 @@ static void pl_disable_forever_work(struct work_struct *work)
		vote(chip->hvdcp_hw_inov_dis_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 int pl_disable_vote_callback(struct votable *votable,
		void *data, int pl_disable, const char *client)
{
	struct pl_data *chip = data;
	union power_supply_propval pval = {0, };
	int master_fcc_ua, total_fcc_ua, slave_fcc_ua;
	int rc;

	chip->taper_pct = 100;
	chip->total_settled_ua = 0;
	chip->pl_settled_ua = 0;

	if (!pl_disable) { /* enable */
	if (!is_main_available(chip))
		return -ENODEV;

	total_fcc_ua = get_effective_result_locked(chip->fcc_votable);

	if (chip->pl_mode != POWER_SUPPLY_PL_NONE && !pl_disable) {
		 /* enable parallel charging */
		rc = power_supply_get_property(chip->pl_psy,
				POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
		if (rc == -ENODEV) {
@@ -602,7 +604,30 @@ static int pl_disable_vote_callback(struct votable *votable,
		}

		rerun_election(chip->fv_votable);
		rerun_election(chip->fcc_votable);

		get_fcc_split(chip, total_fcc_ua, &master_fcc_ua,
				&slave_fcc_ua);

		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;
		}

		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;
		}

		/*
		 * Enable will be called with a valid pl_psy always. The
		 * PARALLEL_PSY_VOTER keeps it disabled unless a pl_psy
@@ -647,7 +672,17 @@ static int pl_disable_vote_callback(struct votable *votable,
				pr_err("Couldn't change slave suspend state rc=%d\n",
					rc);
		}
		rerun_election(chip->fcc_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;
		}

		rerun_election(chip->fv_votable);
	}

@@ -681,16 +716,6 @@ static int pl_awake_vote_callback(struct votable *votable,
	return 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)
@@ -835,6 +860,7 @@ static void handle_settled_icl_change(struct pl_data *chip)
	else
		vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, true, 0);

	rerun_election(chip->fcc_votable);

	if (get_effective_result(chip->pl_disable_votable))
		return;
@@ -856,8 +882,6 @@ static void handle_settled_icl_change(struct pl_data *chip)
		if (abs(new_total_settled_ua - chip->total_settled_ua)
						> MIN_ICL_CHANGE_DELTA_UA)
			split_settled(chip);
	} else {
		rerun_election(chip->fcc_votable);
	}
}

+1 −0
Original line number Diff line number Diff line
@@ -3705,6 +3705,7 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)

	/* reset parallel voters */
	vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);
	vote(chg->pl_disable_votable, FCC_CHANGE_VOTER, false, 0);
	vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
	vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
	vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ enum print_reason {
#define USBIN_I_VOTER			"USBIN_I_VOTER"
#define WEAK_CHARGER_VOTER		"WEAK_CHARGER_VOTER"
#define OTG_VOTER			"OTG_VOTER"
#define FCC_CHANGE_VOTER		"FCC_CHANGE_VOTER"

#define VCONN_MAX_ATTEMPTS	3
#define OTG_MAX_ATTEMPTS	3