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

Commit 4cc06eeb authored by Anirudh Ghayal's avatar Anirudh Ghayal
Browse files

power: smb1360: Add logic to reset FG at PON



If the FG is configured for shutdown at power-off
and remains in that state for long, it could impact
the SOC accuracy. To compensate for this, reset the
FG if the predicted voltage at PON is different
than the current voltage by a configurable threshold.

CRs-Fixed: 735604
Change-Id: I68573127bedbc4224a6c57b427f4be8ea5c2fe7e
Signed-off-by: default avatarAnirudh Ghayal <aghayal@codeaurora.org>
parent 1def2dee
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -127,6 +127,13 @@ Optional Properties:
- qcom,cool-bat-mv		Maximum cool battery target voltage in milli-volts.
- qcom,warm-bat-ma		Maximum warm battery charge current in milli-amps.
- qcom,cool-bat-ma		Maximum cool battery charge current in milli-amps.
- qcom,fg-reset-at-pon		This is a bool property which indicates if the
				FG reset at power-on is enabled.
- qcom,fg-reset-thresold-mv	This value indicates the volatge threshold to
				reset the FG. This value is compared against
				the difference between in predicted voltage and
				current voltage. If this value is not specified
				a default value of 50mV is used. Unit is in milli-volts.

Example:
	i2c@f9967000 {
@@ -176,5 +183,6 @@ Example:
			qcom,cool-bat-ma = <750>;

			qcom,otg-batt-curr-limit = <950>;
			qcom,fg-reset-at-pon;
		};
	};
+73 −0
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@
#define SHDW_FG_CURR_NOW		0x6B
#define SHDW_FG_BATT_TEMP		0x6D

#define VOLTAGE_PREDICTED_REG		0x80
#define CC_TO_SOC_COEFF			0xBA
#define NOMINAL_CAPACITY_REG		0xBC
#define ACTUAL_CAPACITY_REG		0xBE
@@ -232,6 +233,7 @@
#define MAX_8_BITS			255
#define JEITA_WORK_MS			3000

#define FG_RESET_THRESHOLD_MV		15
#define SMB1360_REV_1			0x01

enum {
@@ -321,6 +323,8 @@ struct smb1360_chip {
	int				fg_cc_to_cv_mv;
	int				fg_auto_recharge_soc;
	bool				empty_soc_disabled;
	int				fg_reset_threshold_mv;
	bool				fg_reset_at_pon;

	/* status tracking */
	bool				usb_present;
@@ -2711,6 +2715,65 @@ static int smb1360_fg_config(struct smb1360_chip *chip)
	int rc = 0, temp, fcc_mah;
	u8 reg = 0, reg2[2];

	if (chip->fg_reset_at_pon) {
		int v_predicted, v_now;

		rc = smb1360_enable_fg_access(chip);
		if (rc) {
			pr_err("Couldn't enable FG access rc=%d\n", rc);
			return rc;
		}

		rc = smb1360_read_bytes(chip, VOLTAGE_PREDICTED_REG, reg2, 2);
		if (rc) {
			pr_err("Failed to read VOLTAGE_PREDICTED rc=%d\n", rc);
			goto disable_fg_reset;
		}
		v_predicted = (reg2[1] << 8) | reg2[0];
		v_predicted = div_u64(v_predicted * 5000, 0x7FFF);

		rc = smb1360_read_bytes(chip, SHDW_FG_VTG_NOW, reg2, 2);
		if (rc) {
			pr_err("Failed to read SHDW_FG_VTG_NOW rc=%d\n", rc);
			goto disable_fg_reset;
		}
		v_now = (reg2[1] << 8) | reg2[0];
		v_now = div_u64(v_now * 5000, 0x7FFF);

		pr_debug("v_predicted=%d v_now=%d reset_threshold=%d\n",
			v_predicted, v_now, chip->fg_reset_threshold_mv);

		/*
		 * Reset FG if the predicted voltage is off wrt
		 * the real-time voltage.
		 */
		temp = abs(v_predicted - v_now);
		if (temp >= chip->fg_reset_threshold_mv) {
			pr_info("Reseting FG - v_delta=%d threshold=%d\n",
					temp, chip->fg_reset_threshold_mv);
			/* delay for the FG access to settle */
			msleep(1500);

			/* reset FG */
			rc = smb1360_masked_write(chip, CMD_I2C_REG,
					FG_RESET_BIT, FG_RESET_BIT);
			if (rc) {
				pr_err("Couldn't reset FG rc=%d\n", rc);
				goto disable_fg_reset;
			}

			/* un-reset FG */
			rc = smb1360_masked_write(chip, CMD_I2C_REG,
						FG_RESET_BIT, 0);
			if (rc) {
				pr_err("Couldn't un-reset FG rc=%d\n", rc);
				goto disable_fg_reset;
			}
		}
disable_fg_reset:
		smb1360_disable_fg_access(chip);
	}

	/*
	 * The below IRQ thresholds are not accessible in REV_1
	 * of SMB1360.
@@ -3703,6 +3766,16 @@ static int smb_parse_dt(struct smb1360_chip *chip)
	if (rc < 0)
		chip->fg_auto_recharge_soc = -EINVAL;

	if (of_property_read_bool(node, "qcom,fg-reset-at-pon")) {
		chip->fg_reset_at_pon = true;
		rc = of_property_read_u32(node, "qcom,fg-reset-thresold-mv",
						&chip->fg_reset_threshold_mv);
		if (rc) {
			pr_debug("FG reset voltage threshold not specified using 50mV\n");
			chip->fg_reset_threshold_mv = FG_RESET_THRESHOLD_MV;
		}
	}

	return 0;
}