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

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

Merge "qpnp-fg-gen3: configure ESR timers dynamically based on charge termination"

parents ce69ced9 784bd5bb
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -145,22 +145,30 @@ First Level Node - FG Gen3 device

- qcom,fg-esr-timer-charging
	Usage:      optional
	Value type: <u32>
	Value type: <prop-encoded-array>
	Definition: Number of cycles between ESR pulses while the battery is
		    charging.
		    charging. Array of 2 elements if specified.
		    Element 0 - Retry value for timer
		    Element 1 - Maximum value for timer

- qcom,fg-esr-timer-awake
	Usage:      optional
	Value type: <u32>
	Value type: <prop-encoded-array>
	Definition: Number of cycles between ESR pulses while the system is
		    awake and the battery is discharging.
		    awake and the battery is discharging. Array of 2 elements
		    if specified.
		    Element 0 - Retry value for timer
		    Element 1 - Maximum value for timer

- qcom,fg-esr-timer-asleep
	Usage:      optional
	Value type: <u32>
	Value type: <prop-encoded-array>
	Definition: Number of cycles between ESR pulses while the system is
		    asleep and the battery is discharging. This option requires
		    qcom,fg-esr-timer-awake to be defined.
		    qcom,fg-esr-timer-awake to be defined. Array of 2 elements
		    if specified.
		    Element 0 - Retry value for timer
		    Element 1 - Maximum value for timer

- qcom,fg-esr-pulse-thresh-ma
	Usage:      optional
+3 −2
Original line number Diff line number Diff line
@@ -270,8 +270,9 @@
			io-channels = <&pmi8998_rradc 0>;
			io-channel-names = "rradc_batt_id";
			qcom,rradc-base = <0x4500>;
			qcom,fg-esr-timer-awake = <96>;
			qcom,fg-esr-timer-asleep = <256>;
			qcom,fg-esr-timer-awake = <96 96>;
			qcom,fg-esr-timer-asleep = <256 256>;
			qcom,fg-esr-timer-charging = <0 96>;
			qcom,cycle-counter-en;
			status = "okay";

+10 −3
Original line number Diff line number Diff line
@@ -219,6 +219,12 @@ enum slope_limit_status {
	SLOPE_LIMIT_NUM_COEFFS,
};

enum esr_timer_config {
	TIMER_RETRY = 0,
	TIMER_MAX,
	NUM_ESR_TIMERS,
};

/* DT parameters for FG device */
struct fg_dt_props {
	bool	force_load_profile;
@@ -234,9 +240,9 @@ struct fg_dt_props {
	int	recharge_soc_thr;
	int	recharge_volt_thr_mv;
	int	rsense_sel;
	int	esr_timer_charging;
	int	esr_timer_awake;
	int	esr_timer_asleep;
	int	esr_timer_charging[NUM_ESR_TIMERS];
	int	esr_timer_awake[NUM_ESR_TIMERS];
	int	esr_timer_asleep[NUM_ESR_TIMERS];
	int	rconn_mohms;
	int	esr_clamp_mohms;
	int	cl_start_soc;
@@ -385,6 +391,7 @@ struct fg_chip {
	int			maint_soc;
	int			delta_soc;
	int			last_msoc;
	int			esr_timer_charging_default[NUM_ESR_TIMERS];
	enum slope_limit_status	slope_limit_sts;
	bool			profile_available;
	bool			profile_loaded;
+142 −94
Original line number Diff line number Diff line
@@ -1025,12 +1025,15 @@ static inline void get_esr_meas_current(int curr_ma, u8 *val)
	*val <<= ESR_PULL_DOWN_IVAL_SHIFT;
}

static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
				int flags)
static int fg_set_esr_timer(struct fg_chip *chip, int cycles_init,
				int cycles_max, bool charging, int flags)
{
	u8 buf[2];
	int rc, timer_max, timer_init;

	if (cycles_init < 0 || cycles_max < 0)
		return 0;

	if (charging) {
		timer_max = FG_SRAM_ESR_TIMER_CHG_MAX;
		timer_init = FG_SRAM_ESR_TIMER_CHG_INIT;
@@ -1039,7 +1042,7 @@ static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
		timer_init = FG_SRAM_ESR_TIMER_DISCHG_INIT;
	}

	fg_encode(chip->sp, timer_max, cycles, buf);
	fg_encode(chip->sp, timer_max, cycles_max, buf);
	rc = fg_sram_write(chip,
			chip->sp[timer_max].addr_word,
			chip->sp[timer_max].addr_byte, buf,
@@ -1050,7 +1053,7 @@ static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
		return rc;
	}

	fg_encode(chip->sp, timer_init, cycles, buf);
	fg_encode(chip->sp, timer_init, cycles_init, buf);
	rc = fg_sram_write(chip,
			chip->sp[timer_init].addr_word,
			chip->sp[timer_init].addr_byte, buf,
@@ -1061,6 +1064,8 @@ static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
		return rc;
	}

	fg_dbg(chip, FG_STATUS, "esr_%s_timer set to %d/%d\n",
		charging ? "charging" : "discharging", cycles_init, cycles_max);
	return 0;
}

@@ -2039,6 +2044,50 @@ static int fg_esr_fcc_config(struct fg_chip *chip)
	return 0;
}

static int fg_esr_timer_config(struct fg_chip *chip, bool sleep)
{
	int rc, cycles_init, cycles_max;
	bool end_of_charge = false;

	end_of_charge = is_input_present(chip) && chip->charge_done;
	fg_dbg(chip, FG_STATUS, "sleep: %d eoc: %d\n", sleep, end_of_charge);

	/* ESR discharging timer configuration */
	cycles_init = sleep ? chip->dt.esr_timer_asleep[TIMER_RETRY] :
			chip->dt.esr_timer_awake[TIMER_RETRY];
	if (end_of_charge)
		cycles_init = 0;

	cycles_max = sleep ? chip->dt.esr_timer_asleep[TIMER_MAX] :
			chip->dt.esr_timer_awake[TIMER_MAX];

	rc = fg_set_esr_timer(chip, cycles_init, cycles_max, false,
		sleep ? FG_IMA_NO_WLOCK : FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in setting ESR timer, rc=%d\n", rc);
		return rc;
	}

	/* ESR charging timer configuration */
	cycles_init = cycles_max = -EINVAL;
	if (end_of_charge || sleep) {
		cycles_init = chip->dt.esr_timer_charging[TIMER_RETRY];
		cycles_max = chip->dt.esr_timer_charging[TIMER_MAX];
	} else if (is_input_present(chip)) {
		cycles_init = chip->esr_timer_charging_default[TIMER_RETRY];
		cycles_max = chip->esr_timer_charging_default[TIMER_MAX];
	}

	rc = fg_set_esr_timer(chip, cycles_init, cycles_max, true,
		sleep ? FG_IMA_NO_WLOCK : FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in setting ESR timer, rc=%d\n", rc);
		return rc;
	}

	return 0;
}

static void fg_batt_avg_update(struct fg_chip *chip)
{
	if (chip->charge_status == chip->prev_charge_status)
@@ -2112,6 +2161,10 @@ static void status_change_work(struct work_struct *work)
	if (rc < 0)
		pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc);

	rc = fg_esr_timer_config(chip, false);
	if (rc < 0)
		pr_err("Error in configuring ESR timer, rc=%d\n", rc);

	rc = fg_get_battery_temp(chip, &batt_temp);
	if (!rc) {
		rc = fg_slope_limit_config(chip, batt_temp);
@@ -3115,6 +3168,8 @@ static const struct power_supply_desc fg_psy_desc = {

/* INIT FUNCTIONS STAY HERE */

#define DEFAULT_ESR_CHG_TIMER_RETRY	8
#define DEFAULT_ESR_CHG_TIMER_MAX	16
static int fg_hw_init(struct fg_chip *chip)
{
	int rc;
@@ -3283,23 +3338,30 @@ static int fg_hw_init(struct fg_chip *chip)
		return rc;
	}

	if (chip->dt.esr_timer_charging > 0) {
		rc = fg_set_esr_timer(chip, chip->dt.esr_timer_charging, true,
				      FG_IMA_DEFAULT);
	if (chip->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE) {
		chip->esr_timer_charging_default[TIMER_RETRY] =
			DEFAULT_ESR_CHG_TIMER_RETRY;
		chip->esr_timer_charging_default[TIMER_MAX] =
			DEFAULT_ESR_CHG_TIMER_MAX;
	} else {
		/* We don't need this for pm660 at present */
		chip->esr_timer_charging_default[TIMER_RETRY] = -EINVAL;
		chip->esr_timer_charging_default[TIMER_MAX] = -EINVAL;
	}

	rc = fg_set_esr_timer(chip, chip->dt.esr_timer_charging[TIMER_RETRY],
		chip->dt.esr_timer_charging[TIMER_MAX], true, FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in setting ESR timer, rc=%d\n", rc);
		return rc;
	}
	}

	if (chip->dt.esr_timer_awake > 0) {
		rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
				      FG_IMA_DEFAULT);
	rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake[TIMER_RETRY],
		chip->dt.esr_timer_awake[TIMER_MAX], false, FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("Error in setting ESR timer, rc=%d\n", rc);
		return rc;
	}
	}

	if (chip->cyc_ctr.en)
		restore_cycle_counter(chip);
@@ -3778,6 +3840,32 @@ static int fg_register_interrupts(struct fg_chip *chip)
	return 0;
}

static int fg_parse_dt_property_u32_array(struct device_node *node,
				const char *prop_name, int *buf, int len)
{
	int rc;

	rc = of_property_count_elems_of_size(node, prop_name, sizeof(u32));
	if (rc < 0) {
		if (rc == -EINVAL)
			return 0;
		else
			return rc;
	} else if (rc != len) {
		pr_err("Incorrect length %d for %s, rc=%d\n", len, prop_name,
			rc);
		return -EINVAL;
	}

	rc = of_property_read_u32_array(node, prop_name, buf, len);
	if (rc < 0) {
		pr_err("Error in reading %s, rc=%d\n", prop_name, rc);
		return rc;
	}

	return 0;
}

static int fg_parse_slope_limit_coefficients(struct fg_chip *chip)
{
	struct device_node *node = chip->dev->of_node;
@@ -3788,17 +3876,10 @@ static int fg_parse_slope_limit_coefficients(struct fg_chip *chip)
	if (rc < 0)
		return 0;

	rc = of_property_count_elems_of_size(node, "qcom,slope-limit-coeffs",
			sizeof(u32));
	if (rc != SLOPE_LIMIT_NUM_COEFFS)
		return -EINVAL;

	rc = of_property_read_u32_array(node, "qcom,slope-limit-coeffs",
	rc = fg_parse_dt_property_u32_array(node, "qcom,slope-limit-coeffs",
		chip->dt.slope_limit_coeffs, SLOPE_LIMIT_NUM_COEFFS);
	if (rc < 0) {
		pr_err("Error in reading qcom,slope-limit-coeffs, rc=%d\n", rc);
	if (rc < 0)
		return rc;
	}

	for (i = 0; i < SLOPE_LIMIT_NUM_COEFFS; i++) {
		if (chip->dt.slope_limit_coeffs[i] > SLOPE_LIMIT_COEFF_MAX ||
@@ -3817,44 +3898,20 @@ 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",
	rc = fg_parse_dt_property_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);
	if (rc < 0)
		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",
	rc = fg_parse_dt_property_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);
	if (rc < 0)
		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",
	rc = fg_parse_dt_property_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);
	if (rc < 0)
		return rc;
	}

	for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
		if (chip->dt.ki_coeff_soc[i] < 0 ||
@@ -4099,23 +4156,26 @@ static int fg_parse_dt(struct fg_chip *chip)
				rc);
	}

	rc = of_property_read_u32(node, "qcom,fg-esr-timer-charging", &temp);
	if (rc < 0)
		chip->dt.esr_timer_charging = -EINVAL;
	else
		chip->dt.esr_timer_charging = temp;
	rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-timer-charging",
		chip->dt.esr_timer_charging, NUM_ESR_TIMERS);
	if (rc < 0) {
		chip->dt.esr_timer_charging[TIMER_RETRY] = -EINVAL;
		chip->dt.esr_timer_charging[TIMER_MAX] = -EINVAL;
	}

	rc = of_property_read_u32(node, "qcom,fg-esr-timer-awake", &temp);
	if (rc < 0)
		chip->dt.esr_timer_awake = -EINVAL;
	else
		chip->dt.esr_timer_awake = temp;
	rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-timer-awake",
		chip->dt.esr_timer_awake, NUM_ESR_TIMERS);
	if (rc < 0) {
		chip->dt.esr_timer_awake[TIMER_RETRY] = -EINVAL;
		chip->dt.esr_timer_awake[TIMER_MAX] = -EINVAL;
	}

	rc = of_property_read_u32(node, "qcom,fg-esr-timer-asleep", &temp);
	if (rc < 0)
		chip->dt.esr_timer_asleep = -EINVAL;
	else
		chip->dt.esr_timer_asleep = temp;
	rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-timer-asleep",
		chip->dt.esr_timer_asleep, NUM_ESR_TIMERS);
	if (rc < 0) {
		chip->dt.esr_timer_asleep[TIMER_RETRY] = -EINVAL;
		chip->dt.esr_timer_asleep[TIMER_MAX] = -EINVAL;
	}

	chip->cyc_ctr.en = of_property_read_bool(node, "qcom,cycle-counter-en");
	if (chip->cyc_ctr.en)
@@ -4453,15 +4513,9 @@ static int fg_gen3_suspend(struct device *dev)
	struct fg_chip *chip = dev_get_drvdata(dev);
	int rc;

	if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
		rc = fg_set_esr_timer(chip, chip->dt.esr_timer_asleep, false,
				      FG_IMA_NO_WLOCK);
		if (rc < 0) {
			pr_err("Error in setting ESR timer during suspend, rc=%d\n",
			       rc);
			return rc;
		}
	}
	rc = fg_esr_timer_config(chip, true);
	if (rc < 0)
		pr_err("Error in configuring ESR timer, rc=%d\n", rc);

	cancel_delayed_work_sync(&chip->batt_avg_work);
	if (fg_sram_dump)
@@ -4474,15 +4528,9 @@ static int fg_gen3_resume(struct device *dev)
	struct fg_chip *chip = dev_get_drvdata(dev);
	int rc;

	if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
		rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
				      FG_IMA_DEFAULT);
		if (rc < 0) {
			pr_err("Error in setting ESR timer during resume, rc=%d\n",
			       rc);
			return rc;
		}
	}
	rc = fg_esr_timer_config(chip, false);
	if (rc < 0)
		pr_err("Error in configuring ESR timer, rc=%d\n", rc);

	fg_circ_buf_clr(&chip->ibatt_circ_buf);
	fg_circ_buf_clr(&chip->vbatt_circ_buf);