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

Commit 2b61cf6a authored by Vamshi Krishna B V's avatar Vamshi Krishna B V
Browse files

power: qcom: Add linearize soc feature to QG driver



If linearize soc is defined, scale the soc from 100% after discharge
or recharge event is triggered for better User experience.

CRs-Fixed: 2190528
Change-Id: Iacc4ceb65049893fed2971f43e5e7c7d264dc440
Signed-off-by: default avatarVamshi Krishna B V <vbv@codeaurora.org>
parent 2585580d
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -156,6 +156,14 @@ First Level Node - QGAUGE device
	Definition: A boolean property that when defined holds SOC at 100% when
		    the battery is full until recharge starts.

- qcom,linearize-soc
	Usage:      optional
	Value type: <empty>
	Definition: A boolean property that when defined linearizes SOC when
		    the SOC drops after charge termination monotonically to
		    improve the user experience. This is applicable only if
		    "qcom,hold-soc-while-full" is specified.

==========================================================
Second Level Nodes - Peripherals managed by QGAUGE driver
==========================================================
+1 −1
Original line number Diff line number Diff line
@@ -163,7 +163,7 @@ static long qg_battery_data_ioctl(struct file *file, unsigned int cmd,
		}
		break;
	case BPIOCXVAR:
		if (bp.table_index < TABLE_Z1 || bp.table_index > TABLE_MAX) {
		if (bp.table_index < TABLE_Z1 || bp.table_index >= TABLE_MAX) {
			pr_err("Invalid table index %d for VAR lookup\n",
					bp.table_index);
			rc = -EINVAL;
+2 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ struct qg_dt {
	int			rbat_conn_mohm;
	int			ignore_shutdown_soc_secs;
	bool			hold_soc_while_full;
	bool			linearize_soc;
};

struct qpnp_qg {
@@ -102,6 +103,7 @@ struct qpnp_qg {

	/* soc params */
	int			catch_up_soc;
	int			maint_soc;
	int			msoc;
	int			pon_soc;
	struct alarm		alarm_timer;
+55 −28
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#define pr_fmt(fmt)	"QG-K: %s: " fmt, __func__

#include <linux/alarmtimer.h>
#include <linux/module.h>
#include <linux/power_supply.h>
#include <uapi/linux/qg.h>
#include "qg-sdam.h"
@@ -23,27 +24,45 @@

#define DEFAULT_UPDATE_TIME_MS			64000
#define SOC_SCALE_HYST_MS			2000
static void get_next_update_time(struct qpnp_qg *chip, int *time_ms)
#define SOC_SCALE_LOW_TEMP_THRESHOLD		100

static int qg_delta_soc_interval_ms = 20000;
module_param_named(
	delta_soc_interval_ms, qg_delta_soc_interval_ms, int, 0600
);

static void get_next_update_time(struct qpnp_qg *chip)
{
	int rc = 0, full_time_ms = 0, rt_time_ms = 0;
	int soc_points = 0, batt_temp = 0;
	int min_delta_soc_interval_ms = qg_delta_soc_interval_ms;
	int rc = 0, rt_time_ms = 0, full_time_ms = DEFAULT_UPDATE_TIME_MS;

	*time_ms = DEFAULT_UPDATE_TIME_MS;
	get_fifo_done_time(chip, false, &full_time_ms);
	get_fifo_done_time(chip, true, &rt_time_ms);

	rc = get_fifo_done_time(chip, false, &full_time_ms);
	if (rc < 0)
		return;
	full_time_ms = CAP(0, DEFAULT_UPDATE_TIME_MS,
				full_time_ms - rt_time_ms);

	soc_points = abs(chip->msoc - chip->catch_up_soc);
	if (chip->maint_soc > 0)
		soc_points = max(abs(chip->msoc - chip->maint_soc), soc_points);
	soc_points /= chip->dt.delta_soc;

	rc = get_fifo_done_time(chip, true, &rt_time_ms);
	/* Lower the delta soc interval by half at cold */
	rc = qg_get_battery_temp(chip, &batt_temp);
	if (rc < 0)
		return;
		pr_err("Failed to read battery temperature rc=%d\n", rc);

	*time_ms = full_time_ms - rt_time_ms;
	if (batt_temp < SOC_SCALE_LOW_TEMP_THRESHOLD)
		min_delta_soc_interval_ms = min_delta_soc_interval_ms / 2;

	if (*time_ms < 0)
		*time_ms = 0;
	chip->next_wakeup_ms = (full_time_ms / (soc_points + 1))
					- SOC_SCALE_HYST_MS;
	chip->next_wakeup_ms = max(chip->next_wakeup_ms,
				min_delta_soc_interval_ms);

	qg_dbg(chip, QG_DEBUG_SOC, "SOC scale next-update-time %d secs\n",
					*time_ms / 1000);
	qg_dbg(chip, QG_DEBUG_SOC, "fifo_full_time=%d secs fifo_real_time=%d secs soc_scale_points=%d\n",
			full_time_ms / 1000, rt_time_ms / 1000, soc_points);
}

static bool is_scaling_required(struct qpnp_qg *chip)
@@ -51,6 +70,10 @@ static bool is_scaling_required(struct qpnp_qg *chip)
	if (!chip->profile_loaded)
		return false;

	if (chip->maint_soc > 0 &&
		(abs(chip->maint_soc - chip->msoc) >= chip->dt.delta_soc))
		return true;

	if ((abs(chip->catch_up_soc - chip->msoc) < chip->dt.delta_soc) &&
		chip->catch_up_soc != 0 && chip->catch_up_soc != 100)
		return false;
@@ -75,25 +98,36 @@ static void update_msoc(struct qpnp_qg *chip)
		/* SOC increased */
		if (is_usb_present(chip)) /* Increment if USB is present */
			chip->msoc += chip->dt.delta_soc;
	} else {
	} else if (chip->catch_up_soc < chip->msoc) {
		/* SOC dropped */
		chip->msoc -= chip->dt.delta_soc;
	}
	chip->msoc = CAP(0, 100, chip->msoc);

	if (chip->maint_soc > 0 && chip->msoc < chip->maint_soc) {
		chip->maint_soc -= chip->dt.delta_soc;
		chip->maint_soc = CAP(0, 100, chip->maint_soc);
	}

	/* maint_soc dropped below msoc, skip using it */
	if (chip->maint_soc <= chip->msoc)
		chip->maint_soc = -EINVAL;

	/* update the SOC register */
	rc = qg_write_monotonic_soc(chip, chip->msoc);
	if (rc < 0)
		pr_err("Failed to update MSOC register rc=%d\n", rc);

	/* update SDAM with the new MSOC */
	chip->sdam_data[SDAM_SOC] = chip->msoc;
	rc = qg_sdam_write(SDAM_SOC, chip->msoc);
	if (rc < 0)
		pr_err("Failed to update SDAM with MSOC rc=%d\n", rc);

	qg_dbg(chip, QG_DEBUG_SOC,
		"SOC scale: Update msoc=%d catch_up_soc=%d delta_soc=%d\n",
		chip->msoc, chip->catch_up_soc, chip->dt.delta_soc);
		"SOC scale: Update maint_soc=%d msoc=%d catch_up_soc=%d delta_soc=%d\n",
				chip->maint_soc, chip->msoc,
				chip->catch_up_soc, chip->dt.delta_soc);
}

static void scale_soc_stop(struct qpnp_qg *chip)
@@ -155,8 +189,7 @@ static enum alarmtimer_restart

int qg_scale_soc(struct qpnp_qg *chip, bool force_soc)
{
	int soc_points = 0;
	int rc = 0, time_ms = 0;
	int rc = 0;

	mutex_lock(&chip->soc_lock);

@@ -183,13 +216,7 @@ int qg_scale_soc(struct qpnp_qg *chip, bool force_soc)
	update_msoc(chip);

	if (is_scaling_required(chip)) {
		get_next_update_time(chip, &time_ms);
		soc_points = abs(chip->msoc - chip->catch_up_soc)
					/ chip->dt.delta_soc;
		chip->next_wakeup_ms = (time_ms / (soc_points + 1))
					- SOC_SCALE_HYST_MS;
		if (chip->next_wakeup_ms < 0)
			chip->next_wakeup_ms = 1; /* wake up immediately */
		get_next_update_time(chip);
		alarm_start_relative(&chip->alarm_timer,
					ms_to_ktime(chip->next_wakeup_ms));
	} else {
@@ -198,9 +225,9 @@ int qg_scale_soc(struct qpnp_qg *chip, bool force_soc)
	}

	qg_dbg(chip, QG_DEBUG_SOC,
		"SOC scale: msoc=%d catch_up_soc=%d delta_soc=%d soc_points=%d next_wakeup=%d sec\n",
		"SOC scale: msoc=%d catch_up_soc=%d delta_soc=%d next_wakeup=%d sec\n",
			chip->msoc, chip->catch_up_soc, chip->dt.delta_soc,
			soc_points, chip->next_wakeup_ms / 1000);
			chip->next_wakeup_ms / 1000);

done_psy:
	power_supply_changed(chip->qg_psy);
+26 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/power_supply.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
#include <uapi/linux/qg.h>
@@ -22,6 +23,7 @@
#include "qg-core.h"
#include "qg-reg.h"
#include "qg-defs.h"
#include "qg-util.h"

static inline bool is_sticky_register(u32 addr)
{
@@ -290,3 +292,27 @@ int qg_write_monotonic_soc(struct qpnp_qg *chip, int msoc)

	return rc;
}

int qg_get_battery_temp(struct qpnp_qg *chip, int *temp)
{
	int rc = 0;
	struct qpnp_vadc_result result;

	if (chip->battery_missing) {
		*temp = 250;
		return 0;
	}

	rc = qpnp_vadc_read(chip->vadc_dev, VADC_BAT_THERM_PU2, &result);
	if (rc) {
		pr_err("Failed reading adc channel=%d, rc=%d\n",
					VADC_BAT_THERM_PU2, rc);
		return rc;
	}
	pr_debug("batt_temp = %lld meas = 0x%llx\n",
			result.physical, result.measurement);

	*temp = (int)result.physical;

	return rc;
}
Loading