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

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

power: qpnp-fg-gen4: Add support for rapid SOC reduction



In certain cases, battery state of charge (SOC) can stay higher
than 0 when the battery voltage drops below the cutoff voltage.
Userspace initiates a shutdown only when SOC hits 0. To avoid a
potential under voltage lockout and help with graceful shutdown,
add support for rapid SOC reduction on detecting this condition.

Change-Id: I9a23e67afee68060bd1127699205973a61c3d09d
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 565581c1
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -351,6 +351,13 @@ First Level Node - FG Gen4 device
		    property "qcom,slope-limit-temp-threshold" to make dynamic
		    slope limit adjustment functional.

- qcom,rapid-soc-dec-en
	Usage:      optional
	Value type: <empty>
	Definition: A boolean property that when defined enables rapid SOC
		    decrease when the battery SOC is low but not converging to
		    zero with battery voltage dropping rapidly below Vcutoff.

==========================================================
Second Level Nodes - Peripherals managed by FG Gen4 driver
==========================================================
+83 −10
Original line number Diff line number Diff line
@@ -176,6 +176,7 @@ struct fg_dt_props {
	bool	force_load_profile;
	bool	hold_soc_while_full;
	bool	linearize_soc;
	bool	rapid_soc_dec_en;
	int	cutoff_volt_mv;
	int	empty_volt_mv;
	int	cutoff_curr_ma;
@@ -234,6 +235,7 @@ struct fg_gen4_chip {
	bool			esr_fast_cal_timer_expired;
	bool			esr_fcc_ctrl_en;
	bool			rslow_low;
	bool			rapid_soc_dec_en;
};

struct bias_config {
@@ -1083,7 +1085,7 @@ static int fg_gen4_slope_limit_config(struct fg_gen4_chip *chip, int batt_temp)
	int rc;
	u8 buf;

	if (!chip->slope_limit_en)
	if (!chip->slope_limit_en || chip->rapid_soc_dec_en)
		return 0;

	if (fg->charge_status == POWER_SUPPLY_STATUS_CHARGING ||
@@ -1119,6 +1121,50 @@ static int fg_gen4_slope_limit_config(struct fg_gen4_chip *chip, int batt_temp)
	return 0;
}

static int fg_gen4_configure_cutoff_current(struct fg_dev *fg, int current_ma)
{
	int rc;
	u8 buf[2];

	fg_encode(fg->sp, FG_SRAM_CUTOFF_CURR, current_ma, buf);
	rc = fg_sram_write(fg, fg->sp[FG_SRAM_CUTOFF_CURR].addr_word,
			fg->sp[FG_SRAM_CUTOFF_CURR].addr_byte, buf,
			fg->sp[FG_SRAM_CUTOFF_CURR].len, FG_IMA_DEFAULT);
	if (rc < 0)
		pr_err("Error in writing cutoff_curr, rc=%d\n", rc);

	return rc;
}

#define SLOPE_LIMIT_DEFAULT	5738
#define CUTOFF_CURRENT_MAX	15999
static int fg_gen4_rapid_soc_config(struct fg_gen4_chip *chip, bool en)
{
	struct fg_dev *fg = &chip->fg;
	int rc, slope_limit_coeff, cutoff_curr_ma;
	u8 buf;

	slope_limit_coeff = en ? SLOPE_LIMIT_COEFF_MAX : SLOPE_LIMIT_DEFAULT;
	fg_encode(fg->sp, FG_SRAM_SLOPE_LIMIT, slope_limit_coeff, &buf);
	rc = fg_sram_write(fg, fg->sp[FG_SRAM_SLOPE_LIMIT].addr_word,
			fg->sp[FG_SRAM_SLOPE_LIMIT].addr_byte, &buf,
			fg->sp[FG_SRAM_SLOPE_LIMIT].len, FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in configuring slope_limit coefficient, rc=%d\n",
			rc);
		return rc;
	}

	cutoff_curr_ma = en ? CUTOFF_CURRENT_MAX : chip->dt.cutoff_curr_ma;
	rc = fg_gen4_configure_cutoff_current(fg, cutoff_curr_ma);
	if (rc < 0)
		return rc;

	fg_dbg(fg, FG_STATUS, "Configured slope limit coeff %d cutoff current %d mA\n",
		slope_limit_coeff, cutoff_curr_ma);
	return 0;
}

static int fg_gen4_get_batt_profile(struct fg_dev *fg)
{
	struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg);
@@ -2160,13 +2206,34 @@ static irqreturn_t fg_delta_esr_irq_handler(int irq, void *data)
static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
{
	struct fg_dev *fg = data;
	int rc, vbatt_mv;
	struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg);
	int rc, vbatt_mv, msoc_raw;

	rc = fg_get_battery_voltage(fg, &vbatt_mv);
	if (rc < 0)
		return IRQ_HANDLED;

	fg_dbg(fg, FG_IRQ, "irq %d triggered vbatt_mv: %d\n", irq, vbatt_mv);
	vbatt_mv /= 1000;
	rc = fg_get_msoc_raw(fg, &msoc_raw);
	if (rc < 0)
		return IRQ_HANDLED;

	fg_dbg(fg, FG_IRQ, "irq %d triggered vbatt_mv: %d msoc_raw:%d\n", irq,
		vbatt_mv, msoc_raw);

	if (chip->dt.rapid_soc_dec_en && vbatt_mv < chip->dt.cutoff_volt_mv) {
		/*
		 * Set this flag so that slope limiter coefficient cannot be
		 * configured during rapid SOC decrease.
		 */
		chip->rapid_soc_dec_en = true;

		rc = fg_gen4_rapid_soc_config(chip, true);
		if (rc < 0)
			pr_err("Error in configuring for rapid SOC reduction rc:%d\n",
				rc);
	}

	if (batt_psy_initialized(fg))
		power_supply_changed(fg->batt_psy);

@@ -3476,14 +3543,9 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip)
		return rc;
	}

	fg_encode(fg->sp, FG_SRAM_CUTOFF_CURR, chip->dt.cutoff_curr_ma, buf);
	rc = fg_sram_write(fg, fg->sp[FG_SRAM_CUTOFF_CURR].addr_word,
			fg->sp[FG_SRAM_CUTOFF_CURR].addr_byte, buf,
			fg->sp[FG_SRAM_CUTOFF_CURR].len, FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in writing cutoff_curr, rc=%d\n", rc);
	rc = fg_gen4_configure_cutoff_current(fg, chip->dt.cutoff_curr_ma);
	if (rc < 0)
		return rc;
	}

	fg_encode(fg->sp, FG_SRAM_SYS_TERM_CURR, chip->dt.sys_term_curr_ma,
		buf);
@@ -4204,6 +4266,8 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip)
	if (rc < 0)
		return rc;

	chip->dt.rapid_soc_dec_en = of_property_read_bool(node,
					"qcom,rapid-soc-dec-en");
	return 0;
}

@@ -4416,6 +4480,15 @@ static void fg_gen4_shutdown(struct platform_device *pdev)
	struct fg_dev *fg = &chip->fg;
	int rc, bsoc;

	fg_unregister_interrupts(fg, chip, FG_GEN4_IRQ_MAX);

	if (chip->rapid_soc_dec_en) {
		rc = fg_gen4_rapid_soc_config(chip, false);
		if (rc < 0)
			pr_err("Error in reverting rapid SOC decrease config rc:%d\n",
				rc);
	}

	rc = fg_get_sram_prop(fg, FG_SRAM_BATT_SOC, &bsoc);
	if (rc < 0) {
		pr_err("Error in getting BATT_SOC, rc=%d\n", rc);