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

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

power: qpnp-fg: Reconfigure SW_CC_SOC to reduce error



SW_CC_SOC can accumulate error during charging depending on
various conditions. Reset SW_CC_SOC to a full value during
charge termination and to a value calculated based on battery
SOC when the device enters from charging to discharging status.
This will keep SW_CC_SOC to have an accurate value.

While at it, simplify reading SW_CC_SOC by using sign extension
API to avoid confusion.

Change-Id: I64fd1719c704d51ea68b81cded50ef8e4dd4b605
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 16c74e13
Loading
Loading
Loading
Loading
+35 −10
Original line number Diff line number Diff line
@@ -3435,13 +3435,11 @@ fail:

#define CC_SOC_BASE_REG		0x5BC
#define CC_SOC_OFFSET		3
#define CC_SOC_MAGNITUDE_MASK	0x1FFFFFFF
#define CC_SOC_NEGATIVE_BIT	BIT(29)
static int fg_get_cc_soc(struct fg_chip *chip, int *cc_soc)
{
	int rc;
	u8 reg[4];
	unsigned int temp, magnitude;
	int temp;

	rc = fg_mem_read(chip, reg, CC_SOC_BASE_REG, 4, CC_SOC_OFFSET, 0);
	if (rc) {
@@ -3450,12 +3448,7 @@ static int fg_get_cc_soc(struct fg_chip *chip, int *cc_soc)
	}

	temp = reg[3] << 24 | reg[2] << 16 | reg[1] << 8 | reg[0];
	magnitude = temp & CC_SOC_MAGNITUDE_MASK;
	if (temp & CC_SOC_NEGATIVE_BIT)
		*cc_soc = -1 * (~magnitude + 1);
	else
		*cc_soc = magnitude;

	*cc_soc = sign_extend32(temp, 29);
	return 0;
}

@@ -3854,6 +3847,17 @@ static int fg_cap_learning_check(struct fg_chip *chip)
		}

		fg_cap_learning_stop(chip);
	} else if (chip->status == POWER_SUPPLY_STATUS_FULL) {
		if (chip->wa_flag & USE_CC_SOC_REG) {
			/* reset SW_CC_SOC register to 100% upon charge_full */
			rc = fg_mem_write(chip, (u8 *)&cc_pc_100,
				CC_SOC_BASE_REG, 4, CC_SOC_OFFSET, 0);
			if (rc)
				pr_err("Failed to reset CC_SOC_REG rc=%d\n",
								rc);
			else if (fg_debug_mask & FG_STATUS)
				pr_info("Reset SW_CC_SOC to full value\n");
		}
	}

fail:
@@ -3949,7 +3953,7 @@ static void status_change_work(struct work_struct *work)
				struct fg_chip,
				status_change_work);
	unsigned long current_time = 0;
	int cc_soc, rc, capacity = get_prop_capacity(chip);
	int cc_soc, batt_soc, rc, capacity = get_prop_capacity(chip);
	bool batt_missing = is_battery_missing(chip);

	if (batt_missing) {
@@ -4016,6 +4020,26 @@ static void status_change_work(struct work_struct *work)
	}

	if (chip->prev_status != chip->status && chip->last_sram_update_time) {
		/*
		 * Reset SW_CC_SOC to a value based off battery SOC when
		 * the device is discharging.
		 */
		if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) {
			batt_soc = get_battery_soc_raw(chip);
			if (!batt_soc)
				return;

			batt_soc = div64_s64((int64_t)batt_soc *
					FULL_PERCENT_28BIT, FULL_PERCENT_3B);
			rc = fg_mem_write(chip, (u8 *)&batt_soc,
				CC_SOC_BASE_REG, 4, CC_SOC_OFFSET, 0);
			if (rc)
				pr_err("Failed to reset CC_SOC_REG rc=%d\n",
									rc);
			else if (fg_debug_mask & FG_STATUS)
				pr_info("Reset SW_CC_SOC to %x\n", batt_soc);
		}

		/*
		 * Schedule the update_temp_work whenever there is a status
		 * change. This is essential for applying the slope limiter
@@ -4057,6 +4081,7 @@ static void status_change_work(struct work_struct *work)
					chip->sw_cc_soc_data.init_cc_soc);
		}
	}

	if ((chip->wa_flag & USE_CC_SOC_REG) && chip->bad_batt_detection_en
			&& chip->safety_timer_expired) {
		chip->sw_cc_soc_data.delta_soc =