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

Commit 32a04bb1 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-qg: Use both charge & discharge tables for PON SOC"

parents 8900eef9 75e8aff4
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -393,19 +393,33 @@ static int qg_parse_battery_profile(struct qg_battery_data *battery)
	return rc;
}

int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging)
int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, u8 lookup)
{
	u8 table_index = charging ? TABLE_SOC_OCV1 : TABLE_SOC_OCV2;
	u8 table_index = 0;
	int soc_avg = 0, soc_charge = 0, soc_discharge = 0;

	if (!the_battery || !the_battery->profile) {
		pr_err("Battery profile not loaded\n");
		return -ENODEV;
	}

	*soc = interpolate_soc(&the_battery->profile[table_index],
	if (lookup == SOC_AVERAGE) {
		soc_charge = interpolate_soc(
				&the_battery->profile[TABLE_SOC_OCV1],
				batt_temp, UV_TO_DECIUV(ocv_uv));
		soc_discharge = interpolate_soc(
				&the_battery->profile[TABLE_SOC_OCV2],
				batt_temp, UV_TO_DECIUV(ocv_uv));
		soc_avg = (soc_charge + soc_discharge) / 2;
	} else {
		table_index = (lookup == SOC_CHARGE) ?
				TABLE_SOC_OCV1 : TABLE_SOC_OCV2;
		soc_avg = interpolate_soc(
				&the_battery->profile[table_index],
				batt_temp, UV_TO_DECIUV(ocv_uv));
	}

	*soc = CAP(0, 100, DIV_ROUND_CLOSEST(*soc, 100));
	*soc = CAP(0, 100, DIV_ROUND_CLOSEST(soc_avg, 100));

	return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -14,6 +14,6 @@

int qg_batterydata_init(struct device_node *node);
void qg_batterydata_exit(void);
int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging);
int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, u8 lookup);

#endif /* __QG_BATTERY_PROFILE_H__ */
+6 −0
Original line number Diff line number Diff line
@@ -45,4 +45,10 @@
#define CAP(min, max, value)			\
		((min > value) ? min : ((value > max) ? max : value))

enum soc_lookup {
	SOC_CHARGE,
	SOC_DISCHARGE,
	SOC_AVERAGE,
};

#endif /* __QG_DEFS_H__ */
+1 −1
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ int get_fifo_length(struct qpnp_qg *chip, u32 *fifo_length, bool rt)
	}

	if (rt) {
		*fifo_length &= COUNT_FIFO_RT_MASK;
		*fifo_length = reg & COUNT_FIFO_RT_MASK;
	} else {
		*fifo_length = (reg & FIFO_LENGTH_MASK) >> FIFO_LENGTH_SHIFT;
		*fifo_length += 1;
+37 −26
Original line number Diff line number Diff line
@@ -247,6 +247,20 @@ static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length)
		return rc;
	}

	/*
	 * If there is pending data from suspend, append the new FIFO
	 * data to it.
	 */
	if (chip->suspend_data) {
		j = chip->kdata.fifo_length; /* append the data */
		chip->suspend_data = false;
		qg_dbg(chip, QG_DEBUG_FIFO,
			"Pending suspend-data FIFO length=%d\n", j);
	} else {
		/* clear any old pending data */
		chip->kdata.fifo_length = 0;
	}

	for (i = 0; i < fifo_length * 2; i = i + 2, j++) {
		rc = qg_read(chip, chip->qg_base + QG_V_FIFO0_DATA0_REG + i,
					&v_fifo[i], 2);
@@ -280,7 +294,7 @@ static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length)
					chip->kdata.fifo[j].count);
	}

	chip->kdata.fifo_length = fifo_length;
	chip->kdata.fifo_length += fifo_length;
	chip->kdata.seq_no = chip->seq_no++ % U32_MAX;

	return rc;
@@ -1481,7 +1495,8 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
			pr_err("Failed to read good_ocv rc=%d\n", rc);
			use_pon_ocv = true;
		} else {
			rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
			rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp,
							SOC_AVERAGE);
			if (rc < 0) {
				pr_err("Failed to lookup SOC (GOOD_OCV) @ PON rc=%d\n",
					rc);
@@ -1534,7 +1549,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
			pr_err("Failed to read HW PON ocv rc=%d\n", rc);
			return rc;
		}
		rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
		rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, SOC_AVERAGE);
		if (rc < 0) {
			pr_err("Failed to lookup SOC @ PON rc=%d\n", rc);
			soc = 50;
@@ -2046,6 +2061,8 @@ static int process_suspend(struct qpnp_qg *chip)
	int rc;
	u32 fifo_rt_length = 0, sleep_fifo_length = 0;

	chip->suspend_data = false;

	/* ignore any suspend processing if we are charging */
	if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
		qg_dbg(chip, QG_DEBUG_PM, "Charging @ suspend - ignore processing\n");
@@ -2104,9 +2121,9 @@ static int process_suspend(struct qpnp_qg *chip)

static int process_resume(struct qpnp_qg *chip)
{
	int rc, batt_temp = 0;
	u8 status2 = 0, rt_status = 0;
	u32 ocv_uv = 0, soc = 0;
	u32 ocv_uv = 0;
	int rc, batt_temp = 0;

	rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1);
	if (rc < 0) {
@@ -2128,23 +2145,12 @@ static int process_resume(struct qpnp_qg *chip)

		chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
		chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
		 /* Clear suspend data as there has been a GOOD OCV */
		chip->suspend_data = false;
		rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
		if (rc < 0) {
			pr_err("Failed to lookup OCV, rc=%d\n", rc);
			return rc;
		qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n",
				ocv_uv);
	}
		chip->catch_up_soc = soc;
		/* update the SOC immediately */
		qg_scale_soc(chip, true);

		qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV soc=%d\n",
				ocv_uv, soc);
	}
	/*
	 * If the wakeup was not because of FIFO_DONE
	 * send the pending data collected during suspend.
	 */
	rc = qg_read(chip, chip->qg_base + QG_INT_LATCHED_STS_REG,
						&rt_status, 1);
	if (rc < 0) {
@@ -2153,17 +2159,22 @@ static int process_resume(struct qpnp_qg *chip)
	}
	rt_status &= FIFO_UPDATE_DONE_INT_LAT_STS_BIT;

	if (!rt_status && chip->suspend_data) {
	qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d\n",
				!!rt_status, chip->suspend_data,
				chip->kdata.param[QG_GOOD_OCV_UV].valid);
	/*
	 * If this is not a wakeup from FIFO-done,
	 * process the data immediately if - we have data from
	 * suspend or there is a good OCV.
	 */
	if (!rt_status && (chip->suspend_data ||
			chip->kdata.param[QG_GOOD_OCV_UV].valid)) {
		vote(chip->awake_votable, SUSPEND_DATA_VOTER, true, 0);
		/* signal the read thread */
		chip->data_ready = true;
		wake_up_interruptible(&chip->qg_wait_q);
	}

	qg_dbg(chip, QG_DEBUG_PM, "fifo_done rt_status=%d suspend_data=%d data_ready=%d\n",
			!!rt_status, chip->suspend_data, chip->data_ready);

		chip->suspend_data = false;
	}

	return rc;
}