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

Commit deeaec72 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy Committed by Harry Yang
Browse files

qpnp-fg-gen3: Adjust recharge voltage to help SOC masking



When SOC masking algorithm is enabled, a SOC of 100 will be shown
to the user when certain conditions are met. When the device
starts discharging after charge termination, auto recharge will
be triggered once the SOC or Vbatt goes below the threshold. When
the recharge is based on Vbatt, a fluctutation in Vbatt can cause
issues in SOC masking algorithm. To make it robust, adjust the
recharge voltage dynamically based on charging status and battery
SOC.

Add a device tree property to allow configuring auto recharge to
be based off SOC or battery voltage. This will help the user to
select auto recharge configuration easily.

Change-Id: I2d749806aa51b9fa747967b592b6622cc12bee65
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent fbf2537c
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -156,12 +156,12 @@ First Level Node - FG Gen3 device

- qcom,cycle-counter-en
	Usage:      optional
	Value type: <bool>
	Value type: <empty>
	Definition: Enables the cycle counter feature.

- qcom,fg-force-load-profile
	Usage:      optional
	Value type: <bool>
	Value type: <empty>
	Definition: If set, battery profile will be force loaded if the profile
		    loaded earlier by bootloader doesn't match with the profile
		    available in the device tree.
@@ -229,13 +229,13 @@ First Level Node - FG Gen3 device
	Definition: Battery temperature delta interrupt threshold. Possible
		    values are: 2, 4, 6 and 10. Unit is in Kelvin.

- qcom,hold-soc-while-full:
- qcom,hold-soc-while-full
	Usage:      optional
	Value type: <bool>
	Value type: <empty>
	Definition: A boolean property that when defined holds SOC at 100% when
		    the battery is full.

- qcom,ki-coeff-soc-dischg:
- qcom,ki-coeff-soc-dischg
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: Array of monotonic SOC threshold values to change the ki
@@ -243,7 +243,7 @@ First Level Node - FG Gen3 device
		    This should be defined in the ascending order and in the
		    range of 0-100. Array limit is set to 3.

- qcom,ki-coeff-med-dischg:
- qcom,ki-coeff-med-dischg
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: Array of ki coefficient values for medium discharge current
@@ -254,7 +254,7 @@ First Level Node - FG Gen3 device
		    is specified to make it fully functional. Value has no
		    unit. Allowed range is 0 to 62200 in micro units.

- qcom,ki-coeff-hi-dischg:
- qcom,ki-coeff-hi-dischg
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: Array of ki coefficient values for high discharge current
@@ -311,6 +311,15 @@ First Level Node - FG Gen3 device
		    148438 (14.84 %) will be used. Lowest possible value is
		    1954 (0.19 %).

- qcom,fg-auto-recharge-soc
	Usage:      optional
	Value type: <empty>
	Definition: A boolean property when defined will configure automatic
		    recharge SOC threshold. If not specified, automatic
		    recharge voltage threshold will be configured. This has
		    to be configured in conjunction with the charger side
		    configuration for proper functionality.

==========================================================
Second Level Nodes - Peripherals managed by FG Gen3 driver
==========================================================
+1 −0
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ enum wa_flags {
struct fg_dt_props {
	bool	force_load_profile;
	bool	hold_soc_while_full;
	bool	auto_recharge_soc;
	int	cutoff_volt_mv;
	int	empty_volt_mv;
	int	vbatt_low_thr_mv;
+80 −20
Original line number Diff line number Diff line
@@ -1407,6 +1407,36 @@ static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
	return 0;
}

static int fg_set_recharge_voltage(struct fg_chip *chip, int voltage_mv)
{
	u8 buf;
	int rc;

	if (chip->dt.auto_recharge_soc)
		return 0;

	/* This configuration is available only for pmicobalt v2.0 and above */
	if (chip->wa_flags & PMI8998_V1_REV_WA)
		return 0;

	fg_dbg(chip, FG_STATUS, "Setting recharge voltage to %dmV\n",
		voltage_mv);
	fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR, voltage_mv, &buf);
	rc = fg_sram_write(chip,
			chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word,
			chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte,
			&buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len,
			FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in writing recharge_vbatt_thr, rc=%d\n",
			rc);
		return rc;
	}

	return 0;
}

#define AUTO_RECHG_VOLT_LOW_LIMIT_MV	3700
static int fg_charge_full_update(struct fg_chip *chip)
{
	union power_supply_propval prop = {0, };
@@ -1454,18 +1484,46 @@ static int fg_charge_full_update(struct fg_chip *chip)
		return rc;
	}

	fg_dbg(chip, FG_STATUS, "msoc: %d bsoc: %x health: %d status: %d\n",
		msoc, bsoc, chip->health, chip->charge_status);
	if (chip->charge_done) {
		if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD)
	fg_dbg(chip, FG_STATUS, "msoc: %d bsoc: %x health: %d status: %d full: %d\n",
		msoc, bsoc, chip->health, chip->charge_status,
		chip->charge_full);
	if (chip->charge_done && !chip->charge_full) {
		if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD) {
			fg_dbg(chip, FG_STATUS, "Setting charge_full to true\n");
			chip->charge_full = true;
		else
			/*
			 * Lower the recharge voltage so that VBAT_LT_RECHG
			 * signal will not be asserted soon.
			 */
			rc = fg_set_recharge_voltage(chip,
					AUTO_RECHG_VOLT_LOW_LIMIT_MV);
			if (rc < 0) {
				pr_err("Error in reducing recharge voltage, rc=%d\n",
					rc);
				return rc;
			}
		} else {
			fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
				msoc);
	} else if ((bsoc >> 8) <= recharge_soc) {
		}
	} else if ((bsoc >> 8) <= recharge_soc && chip->charge_full) {
		fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d\n",
			bsoc >> 8, recharge_soc);
		chip->charge_full = false;
		/*
		 * Raise the recharge voltage so that VBAT_LT_RECHG signal
		 * will be asserted soon as battery SOC had dropped below
		 * the recharge SOC threshold.
		 */
		rc = fg_set_recharge_voltage(chip,
					chip->dt.recharge_volt_thr_mv);
		if (rc < 0) {
			pr_err("Error in setting recharge voltage, rc=%d\n",
				rc);
			return rc;
		}
	} else {
		return 0;
	}

	if (!chip->charge_full)
@@ -1570,13 +1628,16 @@ static int fg_rconn_config(struct fg_chip *chip)

static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc)
{
	u8 buf[4];
	u8 buf;
	int rc;

	fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, buf);
	if (!chip->dt.auto_recharge_soc)
		return 0;

	fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, &buf);
	rc = fg_sram_write(chip,
			chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
			chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, buf,
			chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, &buf,
			chip->sp[FG_SRAM_RECHARGE_SOC_THR].len, FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in writing recharge_soc_thr, rc=%d\n", rc);
@@ -1590,6 +1651,9 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip)
{
	int rc, msoc, recharge_soc, new_recharge_soc = 0;

	if (!chip->dt.auto_recharge_soc)
		return 0;

	recharge_soc = chip->dt.recharge_soc_thr;
	/*
	 * If the input is present and charging had been terminated, adjust
@@ -2816,18 +2880,11 @@ static int fg_hw_init(struct fg_chip *chip)
		}
	}

	/* This configuration is available only for pmicobalt v2.0 and above */
	if (!(chip->wa_flags & PMI8998_V1_REV_WA) &&
			chip->dt.recharge_volt_thr_mv > 0) {
		fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR,
			chip->dt.recharge_volt_thr_mv, buf);
		rc = fg_sram_write(chip,
				chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word,
				chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte,
				buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len,
				FG_IMA_DEFAULT);
	if (chip->dt.recharge_volt_thr_mv > 0) {
		rc = fg_set_recharge_voltage(chip,
			chip->dt.recharge_volt_thr_mv);
		if (rc < 0) {
			pr_err("Error in writing recharge_vbatt_thr, rc=%d\n",
			pr_err("Error in setting recharge_voltage, rc=%d\n",
				rc);
			return rc;
		}
@@ -3545,6 +3602,9 @@ static int fg_parse_dt(struct fg_chip *chip)
	else
		chip->dt.recharge_volt_thr_mv = temp;

	chip->dt.auto_recharge_soc = of_property_read_bool(node,
					"qcom,fg-auto-recharge-soc");

	rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp);
	if (rc < 0)
		chip->dt.rsense_sel = SRC_SEL_BATFET_SMB;