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

Commit b051831f authored by Guru Das Srinagesh's avatar Guru Das Srinagesh
Browse files

power: smb5: Configure termination current thresholds



Add support to configure charge termination upper and lower thresholds
for ADC comparator. Since the charge termination can be based off analog
comparator in the charger peripheral, add support to configure the type
of source for termination.

Also expose the configured charge termination threshold (upper
in case of ADC comparator) through CHARGE_TERM_CURRENT property.

CRs-Fixed: 2255712
Change-Id: I5596877a9954b5a5e3c36e3f0b2c5159e03f6e61
Signed-off-by: default avatarGuru Das Srinagesh <gurus@codeaurora.org>
parent f24738ce
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -124,6 +124,27 @@ Charger specific properties:
		then charge inhibit will be disabled by default.
		Allowed values are: 50, 100, 200, 300.

- qcom,chg-term-src
  Usage:      optional
  Value type: <u32>
  Definition: Specify either the ADC or analog comparators to be used in order
		to set threshold values for charge termination current.
		0 - Unspecified
		1 - Select ADC comparator
		2 - Select ANALOG comparator

- qcom,chg-term-current-ma
  Usage:      optional
  Value type: <u32>
  Definition: When ADC comparator is selected as qcom,chg-term-src, this
		parameter should be set to the desired upper threshold.

- qcom,chg-term-base-current-ma
  Usage:      optional
  Value type: <u32>
  Definition: When ADC comparator is selected as qcom,chg-term-src, this
		parameter should be set to the desired lower threshold.

- qcom,auto-recharge-soc
  Usage:      optional
  Value type: <u32>
+94 −2
Original line number Diff line number Diff line
@@ -179,6 +179,9 @@ struct smb_dt_props {
	int			wd_bark_time;
	int			batt_profile_fcc_ua;
	int			batt_profile_fv_uv;
	int			term_current_src;
	int			term_current_thresh_hi_ma;
	int			term_current_thresh_lo_ma;
};

struct smb5 {
@@ -321,6 +324,18 @@ static int smb5_parse_dt(struct smb5 *chip)
	if (rc < 0)
		chg->otg_cl_ua = MICRO_1P5A;

	rc = of_property_read_u32(node, "qcom,chg-term-src",
			&chip->dt.term_current_src);
	if (rc < 0)
		chip->dt.term_current_src = ITERM_SRC_UNSPECIFIED;

	rc = of_property_read_u32(node, "qcom,chg-term-current-ma",
			&chip->dt.term_current_thresh_hi_ma);

	if (chip->dt.term_current_src == ITERM_SRC_ADC)
		rc = of_property_read_u32(node, "qcom,chg-term-base-current-ma",
				&chip->dt.term_current_thresh_lo_ma);

	if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
		chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
			GFP_KERNEL);
@@ -1028,6 +1043,7 @@ static enum power_supply_property smb5_batt_props[] = {
	POWER_SUPPLY_PROP_VOLTAGE_MAX,
	POWER_SUPPLY_PROP_CURRENT_NOW,
	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_TECHNOLOGY,
	POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
@@ -1111,6 +1127,9 @@ static int smb5_batt_get_prop(struct power_supply *psy,
		val->intval = get_client_vote(chg->fcc_votable,
					      BATT_PROFILE_VOTER);
		break;
	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
		rc = smblib_get_prop_batt_iterm(chg, val);
		break;
	case POWER_SUPPLY_PROP_TEMP:
		rc = smblib_get_prop_batt_temp(chg, val);
		break;
@@ -1445,6 +1464,71 @@ static int smb5_configure_micro_usb(struct smb_charger *chg)
	return rc;
}

static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip)
{
	int rc = 0;
	int raw_hi_thresh, raw_lo_thresh;
	struct smb_charger *chg = &chip->chg;

	if (chip->dt.term_current_thresh_hi_ma < -10000 ||
			chip->dt.term_current_thresh_hi_ma > 10000 ||
			chip->dt.term_current_thresh_lo_ma < -10000 ||
			chip->dt.term_current_thresh_lo_ma > 10000) {
		dev_err(chg->dev, "ITERM threshold out of range rc=%d\n", rc);
		return -EINVAL;
	}

	/*
	 * Conversion:
	 * raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000)
	 */

	if (chip->dt.term_current_thresh_hi_ma) {
		raw_hi_thresh = ((chip->dt.term_current_thresh_hi_ma *
						ADC_CHG_TERM_MASK) / 10000);
		raw_hi_thresh = sign_extend32(raw_hi_thresh, 15);

		rc = smblib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG,
				(u8 *)&raw_hi_thresh, 2);
		if (rc < 0) {
			dev_err(chg->dev, "Couldn't configure ITERM threshold HIGH rc=%d\n",
					rc);
			return rc;
		}
	}

	if (chip->dt.term_current_thresh_lo_ma) {
		raw_lo_thresh = ((chip->dt.term_current_thresh_lo_ma *
					ADC_CHG_TERM_MASK) / 10000);
		raw_lo_thresh = sign_extend32(raw_lo_thresh, 15);

		rc = smblib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG,
				(u8 *)&raw_lo_thresh, 2);
		if (rc < 0) {
			dev_err(chg->dev, "Couldn't configure ITERM threshold LOW rc=%d\n",
					rc);
			return rc;
		}
	}

	return rc;
}

static int smb5_configure_iterm_thresholds(struct smb5 *chip)
{
	int rc = 0;

	switch (chip->dt.term_current_src) {
	case ITERM_SRC_ADC:
		rc = smb5_configure_iterm_thresholds_adc(chip);
		break;
	default:
		break;
	}

	return rc;
}

static int smb5_init_hw(struct smb5 *chip)
{
	struct smb_charger *chg = &chip->chg;
@@ -1617,6 +1701,14 @@ static int smb5_init_hw(struct smb5 *chip)
		return rc;
	}

	/* set termination current threshold values */
	rc = smb5_configure_iterm_thresholds(chip);
	if (rc < 0) {
		pr_err("Couldn't configure ITERM thresholds rc=%d\n",
				rc);
		return rc;
	}

	/* configure float charger options */
	switch (chip->dt.float_option) {
	case FLOAT_DCP:
+39 −0
Original line number Diff line number Diff line
@@ -1472,6 +1472,45 @@ int smblib_get_prop_batt_current_now(struct smb_charger *chg,
	return rc;
}

int smblib_get_prop_batt_iterm(struct smb_charger *chg,
		union power_supply_propval *val)
{
	int rc, temp;
	u8 stat;

	/*
	 * Currently, only ADC comparator-based termination is supported,
	 * hence read only the threshold corresponding to ADC source.
	 * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0.
	 */
	rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n",
				rc);
		return rc;
	}

	if (stat & CHGR_ITERM_USE_ANALOG_BIT) {
		val->intval = -EINVAL;
		return 0;
	}

	rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG,
			(u8 *)&temp, 2);

	if (rc < 0) {
		smblib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n",
				rc);
		return rc;
	}

	temp = sign_extend32(temp, 15);
	temp = DIV_ROUND_CLOSEST(temp * 10000, ADC_CHG_TERM_MASK);
	val->intval = temp;

	return rc;
}

int smblib_get_prop_batt_temp(struct smb_charger *chg,
			      union power_supply_propval *val)
{
+10 −0
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ enum print_reason {

#define VBAT_TO_VRAW_ADC(v)		div_u64((u64)v * 1000000UL, 194637UL)

#define ADC_CHG_TERM_MASK	32767

enum smb_mode {
	PARALLEL_MASTER = 0,
	PARALLEL_SLAVE,
@@ -184,6 +186,12 @@ enum float_options {
	SUSPEND_INPUT		= 4,
};

enum chg_term_config_src {
	ITERM_SRC_UNSPECIFIED,
	ITERM_SRC_ADC,
	ITERM_SRC_ANALOG
};

struct smb_irq_info {
	const char			*name;
	const irq_handler_t		handler;
@@ -472,6 +480,8 @@ int smblib_get_prop_batt_voltage_now(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_batt_current_now(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_batt_iterm(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_batt_temp(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_batt_charge_counter(struct smb_charger *chg,
+9 −0
Original line number Diff line number Diff line
@@ -73,6 +73,11 @@ enum {

#define CHGR_FAST_CHARGE_CURRENT_CFG_REG	(CHGR_BASE + 0x61)

#define CHGR_ADC_ITERM_UP_THD_MSB_REG		(CHGR_BASE + 0x67)
#define CHGR_ADC_ITERM_UP_THD_LSB_REG		(CHGR_BASE + 0x68)
#define CHGR_ADC_ITERM_LO_THD_MSB_REG		(CHGR_BASE + 0x69)
#define CHGR_ADC_ITERM_LO_THD_LSB_REG		(CHGR_BASE + 0x6A)

#define CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG	(CHGR_BASE + 0x6B)
#define NO_OF_SAMPLE_FOR_RCHG_SHIFT		2
#define NO_OF_SAMPLE_FOR_RCHG			GENMASK(3, 2)
@@ -102,6 +107,10 @@ enum {
#define JEITA_CCCOMP_CFG_COLD_REG		(CHGR_BASE + 0x93)

#define CHGR_JEITA_THRESHOLD_BASE_REG(i)	(CHGR_BASE + 0x94 + (i * 4))

#define CHGR_ENG_CHARGING_CFG_REG		(CHGR_BASE + 0xC0)
#define CHGR_ITERM_USE_ANALOG_BIT		BIT(3)

/********************************
 *  DCDC Peripheral Registers  *
 ********************************/