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

Commit f36e99f6 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: qpnp-fg: add support for capacity learning feedback"

parents aeb76153 59ec167b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -119,6 +119,12 @@ Parent node optional properties:
					gauge driver attempt to learn the
					battery capacity when charging. Takes
					precedence over capacity-estimation-on.
- qcom,capacity-learning-feedback:	A boolean property to have the fuel
					gauge driver to feedback the learned
					capacity into the capacity learning
					algorithm. This has to be used only if
					the property "qcom,capacity-learning-on"
					is specified.
- qcom,cl-max-increment-deciperc:	The maximum percent that the capacity
					can rise as the result of a single
					charge cycle. This property corresponds
+52 −12
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ struct fg_learning_data {
	int64_t			cc_uah;
	int64_t			learned_cc_uah;
	bool			active;
	bool			feedback_on;
	struct mutex		learning_lock;
	ktime_t			time_stamp;
	/* configuration properties */
@@ -2717,6 +2718,11 @@ static enum alarmtimer_restart fg_cap_learning_alarm_cb(struct alarm *alarm,
}

#define FG_AGING_STORAGE_REG		0x5E4
#define ACTUAL_CAPACITY_REG		0x578
#define MAH_TO_SOC_CONV_REG		0x4A0
#define CC_SOC_COEFF_OFFSET		0
#define ACTUAL_CAPACITY_OFFSET		2
#define MAH_TO_SOC_CONV_CS_OFFSET	0
static void fg_cap_learning_load_data(struct fg_chip *chip)
{
	int16_t cc_mah;
@@ -2725,7 +2731,7 @@ static void fg_cap_learning_load_data(struct fg_chip *chip)

	rc = fg_mem_read(chip, (u8 *)&cc_mah, FG_AGING_STORAGE_REG, 2, 0, 0);
	if (rc) {
		pr_err("Failed to store aged capacity: %d\n", rc);
		pr_err("Failed to load aged capacity: %d\n", rc);
	} else {
		chip->learning_data.learned_cc_uah = cc_mah * 1000;
		if (fg_debug_mask & FG_AGING)
@@ -2739,7 +2745,9 @@ static void fg_cap_learning_load_data(struct fg_chip *chip)
static void fg_cap_learning_save_data(struct fg_chip *chip)
{
	int16_t cc_mah;
	int64_t cc_to_soc_coeff;
	int rc;
	u8 data[2];

	cc_mah = div64_s64(chip->learning_data.learned_cc_uah, 1000);

@@ -2750,6 +2758,31 @@ static void fg_cap_learning_save_data(struct fg_chip *chip)
		pr_info("learned capacity %lld uah (%d/0x%x uah) saved to sram\n",
				chip->learning_data.learned_cc_uah,
				cc_mah, cc_mah);

	if (chip->learning_data.feedback_on) {
		rc = fg_mem_write(chip, (u8 *)&cc_mah, ACTUAL_CAPACITY_REG, 2,
				ACTUAL_CAPACITY_OFFSET, 0);
		if (rc)
			pr_err("Failed to store actual capacity: %d\n", rc);

		rc = fg_mem_read(chip, (u8 *)&data, MAH_TO_SOC_CONV_REG, 2,
				MAH_TO_SOC_CONV_CS_OFFSET, 0);
		if (rc) {
			pr_err("Failed to read mah_to_soc_conv_cs: %d\n", rc);
		} else {
			cc_to_soc_coeff = div64_s64(half_float(data), cc_mah);
			half_float_to_buffer(cc_to_soc_coeff, data);
			rc = fg_mem_write(chip, (u8 *)data,
					FG_AGING_STORAGE_REG, 2,
					CC_SOC_COEFF_OFFSET, 0);
			if (rc)
				pr_err("Failed to write cc_soc_coeff_offset: %d\n",
					rc);
			else if (fg_debug_mask & FG_AGING)
				pr_info("new cc_soc_coeff %lld [%x %x] saved to sram\n",
					cc_to_soc_coeff, data[0], data[1]);
		}
	}
}

static void fg_cap_learning_post_process(struct fg_chip *chip)
@@ -2793,7 +2826,7 @@ static int fg_cap_learning_check(struct fg_chip *chip)
{
	u8 data[3];
	int rc = 0, battery_soc;
	int vbat_est_diff;
	int vbat_est_diff, vbat_est_thr_uv;

	mutex_lock(&chip->learning_data.learning_lock);
	if (chip->status == POWER_SUPPLY_STATUS_CHARGING
@@ -2809,17 +2842,19 @@ static int fg_cap_learning_check(struct fg_chip *chip)
			goto fail;

		fg_mem_lock(chip);
		if (!chip->learning_data.feedback_on) {
			vbat_est_diff = get_vbat_est_diff(chip);
		if (vbat_est_diff >= chip->learning_data.vbat_est_thr_uv &&
				chip->learning_data.vbat_est_thr_uv > 0) {
			vbat_est_thr_uv = chip->learning_data.vbat_est_thr_uv;
			if (vbat_est_diff >= vbat_est_thr_uv &&
					vbat_est_thr_uv > 0) {
				if (fg_debug_mask & FG_AGING)
					pr_info("vbat_est_diff (%d) < threshold (%d)\n",
					vbat_est_diff,
					chip->learning_data.vbat_est_thr_uv);
						vbat_est_diff, vbat_est_thr_uv);
				fg_mem_release(chip);
				fg_cap_learning_stop(chip);
				goto fail;
			}
		}
		battery_soc = get_battery_soc_raw(chip);
		if (fg_debug_mask & FG_AGING)
			pr_info("checking battery soc (%d vs %d)\n",
@@ -4211,6 +4246,11 @@ static int fg_of_init(struct fg_chip *chip)
		chip->batt_aging_mode = FG_AGING_ESR;
	else
		chip->batt_aging_mode = FG_AGING_NONE;
	if (chip->batt_aging_mode == FG_AGING_CC) {
		chip->learning_data.feedback_on = of_property_read_bool(
					chip->spmi->dev.of_node,
					"qcom,capacity-learning-feedback");
	}
	if (fg_debug_mask & FG_AGING)
		pr_info("battery aging mode: %d\n", chip->batt_aging_mode);