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

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

qpnp-fg-gen3: add support to configure ki coefficients during discharge



During medium and high discharging scenario, voltage mode
correction needs to be applied so that the battery SOC can
follow closely with the battery voltage. Add support for this
by configuring the ki coefficients for medium and high discharge
current during discharging.

Change-Id: I0a76e9e2f74c40b55e01f9dc106d31a148edefdf
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 54b2b24d
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -222,6 +222,36 @@ First Level Node - FG Gen3 device
	Definition: A boolean property that when defined holds SOC at 100% when
		    the battery is full.

- qcom,ki-coeff-soc-dischg:
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: Array of monotonic SOC threshold values to change the ki
		    coefficient for medium discharge current during discharge.
		    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:
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: Array of ki coefficient values for medium discharge current
		    during discharge. These values will be applied when the
		    monotonic SOC goes below the SOC threshold specified under
		    qcom,ki-coeff-soc-dischg. Array limit is set to 3. This
		    property should be specified if qcom,ki-coeff-soc-dischg
		    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:
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: Array of ki coefficient values for high discharge current
		    during discharge. These values will be applied when the
		    monotonic SOC goes below the SOC threshold specified under
		    qcom,ki-coeff-soc-dischg. Array limit is set to 3. This
		    property should be specified if qcom,ki-coeff-soc-dischg
		    is specified to make it fully functional. Value has no
		    unit. Allowed range is 0 to 62200 in micro units.

==========================================================
Second Level Nodes - Peripherals managed by FG Gen3 driver
==========================================================
@@ -252,6 +282,9 @@ pmicobalt_fg: qpnp,fg {
	qcom,pmic-revid = <&pmicobalt_revid>;
	io-channels = <&pmicobalt_rradc 3>;
	io-channel-names = "rradc_batt_id";
	qcom,ki-coeff-soc-dischg = <30 60 90>;
	qcom,ki-coeff-med-dischg = <800 1000 1400>;
	qcom,ki-coeff-hi-dischg = <1200 1500 2100>;
	status = "okay";

	qcom,fg-batt-soc@4000 {
+9 −0
Original line number Diff line number Diff line
@@ -61,6 +61,9 @@
#define BUCKET_COUNT			8
#define BUCKET_SOC_PCT			(256 / BUCKET_COUNT)

#define KI_COEFF_MAX			62200
#define KI_COEFF_SOC_LEVELS		3

/* Debug flag definitions */
enum fg_debug_flag {
	FG_IRQ			= BIT(0), /* Show interrupts */
@@ -139,6 +142,8 @@ enum fg_sram_param_id {
	FG_SRAM_CHG_TERM_CURR,
	FG_SRAM_DELTA_SOC_THR,
	FG_SRAM_RECHARGE_SOC_THR,
	FG_SRAM_KI_COEFF_MED_DISCHG,
	FG_SRAM_KI_COEFF_HI_DISCHG,
	FG_SRAM_MAX,
};

@@ -198,6 +203,9 @@ struct fg_dt_props {
	int	cl_min_cap_limit;
	int	jeita_hyst_temp;
	int	batt_temp_delta;
	int	ki_coeff_soc[KI_COEFF_SOC_LEVELS];
	int	ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS];
	int	ki_coeff_hi_dischg[KI_COEFF_SOC_LEVELS];
};

/* parameters from battery profile */
@@ -275,6 +283,7 @@ struct fg_chip {
	bool			fg_restarting;
	bool			charge_full;
	bool			recharge_soc_adjusted;
	bool			ki_coeff_dischg_en;
	struct completion	soc_update;
	struct completion	soc_ready;
	struct delayed_work	profile_load_work;
+158 −0
Original line number Diff line number Diff line
@@ -36,6 +36,12 @@
#define SYS_TERM_CURR_OFFSET		0
#define VBATT_FULL_WORD			7
#define VBATT_FULL_OFFSET		0
#define KI_COEFF_MED_DISCHG_WORD	9
#define KI_COEFF_MED_DISCHG_OFFSET	3
#define KI_COEFF_HI_DISCHG_WORD		10
#define KI_COEFF_HI_DISCHG_OFFSET	0
#define KI_COEFF_LOW_DISCHG_WORD	10
#define KI_COEFF_LOW_DISCHG_OFFSET	2
#define DELTA_SOC_THR_WORD		12
#define DELTA_SOC_THR_OFFSET		3
#define RECHARGE_SOC_THR_WORD		14
@@ -88,6 +94,12 @@
#define ALG_FLAGS_OFFSET		1

/* v2 SRAM address and offset in ascending order */
#define KI_COEFF_LOW_DISCHG_v2_WORD	9
#define KI_COEFF_LOW_DISCHG_v2_OFFSET	3
#define KI_COEFF_MED_DISCHG_v2_WORD	10
#define KI_COEFF_MED_DISCHG_v2_OFFSET	0
#define KI_COEFF_HI_DISCHG_v2_WORD	10
#define KI_COEFF_HI_DISCHG_v2_OFFSET	1
#define DELTA_SOC_THR_v2_WORD		13
#define DELTA_SOC_THR_v2_OFFSET		0
#define RECHARGE_SOC_THR_v2_WORD	14
@@ -173,6 +185,12 @@ static struct fg_sram_param pmicobalt_v1_sram_params[] = {
		ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
	PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
		ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
	PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD,
		KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 244141, 0,
		fg_encode_default, NULL),
	PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD,
		KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 244141, 0,
		fg_encode_default, NULL),
};

static struct fg_sram_param pmicobalt_v2_sram_params[] = {
@@ -222,6 +240,12 @@ static struct fg_sram_param pmicobalt_v2_sram_params[] = {
		ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
	PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
		ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
	PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_v2_WORD,
		KI_COEFF_MED_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
		fg_encode_default, NULL),
	PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_v2_WORD,
		KI_COEFF_HI_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
		fg_encode_default, NULL),
};

static struct fg_alg_flag pmicobalt_v1_alg_flags[] = {
@@ -1124,6 +1148,60 @@ out:
	mutex_unlock(&chip->cl.lock);
}

#define KI_COEFF_MED_DISCHG_DEFAULT	1500
#define KI_COEFF_HI_DISCHG_DEFAULT	2200
static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
{
	int rc, i, msoc;
	int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
	int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
	u8 val;

	if (!chip->ki_coeff_dischg_en)
		return 0;

	rc = fg_get_prop_capacity(chip, &msoc);
	if (rc < 0) {
		pr_err("Error in getting capacity, rc=%d\n", rc);
		return rc;
	}

	if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) {
		for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
			if (msoc < chip->dt.ki_coeff_soc[i]) {
				ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
				ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
			}
		}
	}

	fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
	rc = fg_sram_write(chip,
			chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
			chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val,
			chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len,
			FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in writing ki_coeff_med, rc=%d\n", rc);
		return rc;
	}

	fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val);
	rc = fg_sram_write(chip,
			chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word,
			chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val,
			chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len,
			FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc);
		return rc;
	}

	fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
		ki_coeff_med, ki_coeff_hi);
	return 0;
}

static int fg_charge_full_update(struct fg_chip *chip)
{
	union power_supply_propval prop = {0, };
@@ -1298,6 +1376,7 @@ static void status_change_work(struct work_struct *work)
		schedule_work(&chip->cycle_count_work);

	fg_cap_learning_update(chip);

	rc = fg_charge_full_update(chip);
	if (rc < 0)
		pr_err("Error in charge_full_update, rc=%d\n", rc);
@@ -1306,6 +1385,9 @@ 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_adjust_ki_coeff_dischg(chip);
	if (rc < 0)
		pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
out:
	pm_relax(chip->dev);
}
@@ -2138,6 +2220,10 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
	if (rc < 0)
		pr_err("Error in charge_full_update, rc=%d\n", rc);

	rc = fg_adjust_ki_coeff_dischg(chip);
	if (rc < 0)
		pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);

	return IRQ_HANDLED;
}

@@ -2298,6 +2384,73 @@ static int fg_register_interrupts(struct fg_chip *chip)
	return 0;
}

static int fg_parse_ki_coefficients(struct fg_chip *chip)
{
	struct device_node *node = chip->dev->of_node;
	int rc, i;

	rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-soc-dischg",
		sizeof(u32));
	if (rc != KI_COEFF_SOC_LEVELS)
		return 0;

	rc = of_property_read_u32_array(node, "qcom,ki-coeff-soc-dischg",
			chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
	if (rc < 0) {
		pr_err("Error in reading ki-coeff-soc-dischg, rc=%d\n",
			rc);
		return rc;
	}

	rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-med-dischg",
		sizeof(u32));
	if (rc != KI_COEFF_SOC_LEVELS)
		return 0;

	rc = of_property_read_u32_array(node, "qcom,ki-coeff-med-dischg",
			chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
	if (rc < 0) {
		pr_err("Error in reading ki-coeff-med-dischg, rc=%d\n",
			rc);
		return rc;
	}

	rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-hi-dischg",
		sizeof(u32));
	if (rc != KI_COEFF_SOC_LEVELS)
		return 0;

	rc = of_property_read_u32_array(node, "qcom,ki-coeff-hi-dischg",
			chip->dt.ki_coeff_hi_dischg, KI_COEFF_SOC_LEVELS);
	if (rc < 0) {
		pr_err("Error in reading ki-coeff-hi-dischg, rc=%d\n",
			rc);
		return rc;
	}

	for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
		if (chip->dt.ki_coeff_soc[i] < 0 ||
			chip->dt.ki_coeff_soc[i] > FULL_CAPACITY) {
			pr_err("Error in ki_coeff_soc_dischg values\n");
			return -EINVAL;
		}

		if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
			chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
			pr_err("Error in ki_coeff_med_dischg values\n");
			return -EINVAL;
		}

		if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
			chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
			pr_err("Error in ki_coeff_med_dischg values\n");
			return -EINVAL;
		}
	}
	chip->ki_coeff_dischg_en = true;
	return 0;
}

#define DEFAULT_CUTOFF_VOLT_MV		3200
#define DEFAULT_EMPTY_VOLT_MV		3100
#define DEFAULT_CHG_TERM_CURR_MA	100
@@ -2562,6 +2715,11 @@ static int fg_parse_dt(struct fg_chip *chip)

	chip->dt.hold_soc_while_full = of_property_read_bool(node,
					"qcom,hold-soc-while-full");

	rc = fg_parse_ki_coefficients(chip);
	if (rc < 0)
		pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);

	return 0;
}