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

Commit be0ba9e9 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

power: qpnp-fg-gen4: Configure ESR FCC dynamically



Currently, ESR FCC is configured to be HW autonomous always. When
parallel charging is enabled, the battery charging current gets
split up between main and parallel chargers. For ESR pulse, FG
can request for a decrement in FCC whereas the main charger can
end up increasing it because of the aforementioned current split.

Fix this by moving to SW controlled mode with a fixed ESR FCC
decrement of 300 mA when parallel charging is enabled. While at
it, check for the presence of Qnovo enable status and charge pump
presence as those are also potential cases where this can happen.

Switch back to HW autonomous mode:
- When the device is charging but only through main charger and
not through parallel charger or charge pump and Qnovo is not
enabled.
- When the device is not charging.

Change-Id: I6ea912bd10691e1a175f982dda83ca59ea42409b
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 81899be2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -176,6 +176,7 @@

/* GEN4 bit definitions */
#define GEN4_ESR_FAST_CRG_IVAL_MASK		GENMASK(7, 4)
#define GEN4_ESR_FAST_CRG_IVAL_SHIFT		4
#define GEN4_ESR_FCC_300MA			0x0
#define GEN4_ESR_FCC_600MA			0x1
#define GEN4_ESR_FCC_1A				0x2
+86 −0
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ struct fg_gen4_chip {
	bool			esr_fast_calib;
	bool			esr_fast_calib_done;
	bool			esr_fast_cal_timer_expired;
	bool			esr_fcc_ctrl_en;
	bool			rslow_low;
};

@@ -1974,6 +1975,87 @@ static int fg_gen4_charge_full_update(struct fg_dev *fg)
	return rc;
}

static int fg_gen4_esr_fcc_config(struct fg_gen4_chip *chip)
{
	struct fg_dev *fg = &chip->fg;
	union power_supply_propval prop = {0, };
	int rc;
	bool parallel_en = false, cp_en = false, qnovo_en, esr_fcc_ctrl_en;
	u8 val, mask;

	if (is_parallel_charger_available(fg)) {
		rc = power_supply_get_property(fg->parallel_psy,
			POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop);
		if (rc < 0)
			pr_err_ratelimited("Error in reading charging_enabled from parallel_psy, rc=%d\n",
				rc);
		else
			parallel_en = prop.intval;
	}

	if (usb_psy_initialized(fg)) {
		rc = power_supply_get_property(fg->usb_psy,
			POWER_SUPPLY_PROP_SMB_EN_MODE, &prop);
		if (rc < 0) {
			pr_err("Couldn't read usb SMB_EN_MODE rc=%d\n", rc);
			return rc;
		}

		/*
		 * If SMB_EN_MODE is 1, then charge pump can get enabled for
		 * the charger inserted. However, whether the charge pump
		 * switching happens only if the conditions are met.
		 */
		cp_en = (prop.intval == 1);
	}

	qnovo_en = is_qnovo_en(fg);

	fg_dbg(fg, FG_POWER_SUPPLY, "chg_sts: %d par_en: %d cp_en: %d qnov_en: %d esr_fcc_ctrl_en: %d\n",
		fg->charge_status, parallel_en, cp_en, qnovo_en,
		chip->esr_fcc_ctrl_en);

	if (fg->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
			(parallel_en || qnovo_en || cp_en)) {
		if (chip->esr_fcc_ctrl_en)
			return 0;

		/*
		 * When parallel charging or Qnovo or Charge pump is enabled,
		 * configure ESR FCC to 300mA to trigger an ESR pulse. Without
		 * this, FG can request the main charger to increase FCC when it
		 * is supposed to decrease it.
		 */
		val = GEN4_ESR_FCC_300MA << GEN4_ESR_FAST_CRG_IVAL_SHIFT |
			ESR_FAST_CRG_CTL_EN_BIT;
		esr_fcc_ctrl_en = true;
	} else {
		if (!chip->esr_fcc_ctrl_en)
			return 0;

		/*
		 * If we're here, then it means either the device is not in
		 * charging state or parallel charging / Qnovo / Charge pump is
		 * disabled. Disable ESR fast charge current control in SW.
		 */
		val = GEN4_ESR_FCC_1A << GEN4_ESR_FAST_CRG_IVAL_SHIFT;
		esr_fcc_ctrl_en = false;
	}

	mask = GEN4_ESR_FAST_CRG_IVAL_MASK | ESR_FAST_CRG_CTL_EN_BIT;
	rc = fg_masked_write(fg, BATT_INFO_ESR_FAST_CRG_CFG(fg), mask, val);
	if (rc < 0) {
		pr_err("Error in writing to %04x, rc=%d\n",
			BATT_INFO_ESR_FAST_CRG_CFG(fg), rc);
		return rc;
	}

	chip->esr_fcc_ctrl_en = esr_fcc_ctrl_en;
	fg_dbg(fg, FG_STATUS, "esr_fcc_ctrl_en set to %d\n",
		chip->esr_fcc_ctrl_en);
	return 0;
}

/* All irq handlers below this */

static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data)
@@ -2699,6 +2781,10 @@ static void status_change_work(struct work_struct *work)
	if (rc < 0)
		pr_err("Error in adjusting recharge SOC, rc=%d\n", rc);

	rc = fg_gen4_esr_fcc_config(chip);
	if (rc < 0)
		pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc);

	ttf_update(chip->ttf, input_present);
	fg->prev_charge_status = fg->charge_status;
out: