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

Commit 5a54d60d authored by Anirudh Ghayal's avatar Anirudh Ghayal Committed by Gerrit - the friendly Code Review server
Browse files

power: qpnp-smb5: Add VBAT and SOC based recharge support



After termination, charging can be restarted based on the battery
voltage (VBAT) or SOC. Add support to enable recharge based on
VBAT and SOC. Both the recharge schemes are mutually
exclusive, when both are enabled SOC based recharge takes
precedence.

Change-Id: I5368649853a7846651cab61bd241054636fa5776
Signed-off-by: default avatarAnirudh Ghayal <aghayal@codeaurora.org>
parent da3dee46
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -109,10 +109,18 @@ Charger specific properties:

- qcom,auto-recharge-soc
  Usage:      optional
  Value type: <empty>
  Definition: Specifies if automatic recharge needs to be based off battery
		SOC. If this property is not specified, then auto recharge will
		be based off battery voltage.
  Value type: <u32>
  Definition: Specifies the SOC threshold at which the charger will
		restart charging after termination. The value specified
		ranges from 0 - 100. The feature is enabled if this
		property is specified with a valid SOC value.

- qcom,auto-recharge-vbat-mv
  Usage:      optional
  Value type: <u32>
  Definition: Specifies the battery voltage threshold at which the charger
		will restart charging after termination. The value specified
		is in milli-volts.

- qcom,suspend-input-on-debug-batt
  Usage:      optional
+78 −7
Original line number Diff line number Diff line
@@ -158,7 +158,8 @@ struct smb_dt_props {
	int			chg_inhibit_thr_mv;
	bool			no_battery;
	bool			hvdcp_disable;
	bool			auto_recharge_soc;
	int			auto_recharge_soc;
	int			auto_recharge_vbat_mv;
	int			wd_bark_time;
	int			batt_profile_fcc_ua;
	int			batt_profile_fv_uv;
@@ -329,8 +330,23 @@ static int smb5_parse_dt(struct smb5 *chip)
		return -EINVAL;
	}

	chip->dt.auto_recharge_soc = of_property_read_bool(node,
						"qcom,auto-recharge-soc");
	chip->dt.auto_recharge_soc = -EINVAL;
	rc = of_property_read_u32(node, "qcom,auto-recharge-soc",
				&chip->dt.auto_recharge_soc);
	if (!rc && (chip->dt.auto_recharge_soc < 0 ||
			chip->dt.auto_recharge_soc > 100)) {
		pr_err("qcom,auto-recharge-soc is incorrect\n");
		return -EINVAL;
	}
	chg->auto_recharge_soc = chip->dt.auto_recharge_soc;

	chip->dt.auto_recharge_vbat_mv = -EINVAL;
	rc = of_property_read_u32(node, "qcom,auto-recharge-vbat-mv",
				&chip->dt.auto_recharge_vbat_mv);
	if (!rc && (chip->dt.auto_recharge_vbat_mv < 0)) {
		pr_err("qcom,auto-recharge-vbat-mv is incorrect\n");
		return -EINVAL;
	}

	chg->dcp_icl_ua = chip->dt.usb_icl_ua;

@@ -956,6 +972,7 @@ static enum power_supply_property smb5_batt_props[] = {
	POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
	POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
	POWER_SUPPLY_PROP_CHARGE_COUNTER,
	POWER_SUPPLY_PROP_RECHARGE_SOC,
};

static int smb5_batt_get_prop(struct power_supply *psy,
@@ -1045,6 +1062,9 @@ static int smb5_batt_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
		rc = smblib_get_prop_batt_charge_counter(chg, val);
		break;
	case POWER_SUPPLY_PROP_RECHARGE_SOC:
		val->intval = chg->auto_recharge_soc;
		break;
	default:
		pr_err("batt power supply prop %d not supported\n", psp);
		return -EINVAL;
@@ -1555,14 +1575,65 @@ static int smb5_init_hw(struct smb5 *chip)
		return rc;
	}

	rc = smblib_masked_write(chg, CHGR_CFG2_REG,
			SOC_BASED_RECHG_BIT,
			chip->dt.auto_recharge_soc ? SOC_BASED_RECHG_BIT : 0);
	rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
				(chip->dt.auto_recharge_vbat_mv != -EINVAL) ?
				VBAT_BASED_RECHG_BIT : 0);
	if (rc < 0) {
		dev_err(chg->dev, "Couldn't configure VBAT-rechg CHG_CFG2_REG rc=%d\n",
			rc);
		return rc;
	}

	/* program the auto-recharge VBAT threshold */
	if (chip->dt.auto_recharge_vbat_mv != -EINVAL) {
		u32 temp = VBAT_TO_VRAW_ADC(chip->dt.auto_recharge_vbat_mv);

		temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8);
		rc = smblib_batch_write(chg,
			CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG, (u8 *)&temp, 2);
		if (rc < 0) {
			dev_err(chg->dev, "Couldn't configure ADC_RECHARGE_THRESHOLD REG rc=%d\n",
				rc);
			return rc;
		}
		/* Program the sample count for VBAT based recharge to 3 */
		rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
					NO_OF_SAMPLE_FOR_RCHG,
					2 << NO_OF_SAMPLE_FOR_RCHG_SHIFT);
		if (rc < 0) {
		dev_err(chg->dev, "Couldn't configure FG_UPDATE_CFG2_SEL_REG rc=%d\n",
			dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
				rc);
			return rc;
		}
	}

	rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
				(chip->dt.auto_recharge_soc != -EINVAL) ?
				SOC_BASED_RECHG_BIT : VBAT_BASED_RECHG_BIT);
	if (rc < 0) {
		dev_err(chg->dev, "Couldn't configure SOC-rechg CHG_CFG2_REG rc=%d\n",
			rc);
		return rc;
	}

	/* program the auto-recharge threshold */
	if (chip->dt.auto_recharge_soc != -EINVAL) {
		rc = smblib_write(chg, CHARGE_RCHG_SOC_THRESHOLD_CFG_REG,
				(chip->dt.auto_recharge_soc * 255) / 100);
		if (rc < 0) {
			dev_err(chg->dev, "Couldn't configure CHG_RCHG_SOC_REG rc=%d\n",
				rc);
			return rc;
		}
		/* Program the sample count for SOC based recharge to 1 */
		rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
						NO_OF_SAMPLE_FOR_RCHG, 0);
		if (rc < 0) {
			dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
				rc);
			return rc;
		}
	}

	if (chg->sw_jeita_enabled) {
		rc = smblib_disable_hw_jeita(chg, true);
+6 −2
Original line number Diff line number Diff line
@@ -62,11 +62,15 @@ int smblib_write(struct smb_charger *chg, u16 addr, u8 val)
	return regmap_write(chg->regmap, addr, val);
}

int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val)
int smblib_batch_write(struct smb_charger *chg, u16 addr, u8 *val,
			int count)
{
	return regmap_bulk_write(chg->regmap, addr, val, count);
}

int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val)
{
	return regmap_update_bits(chg->regmap, addr, mask, val);

}

int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
+5 −0
Original line number Diff line number Diff line
@@ -70,6 +70,8 @@ enum print_reason {
#define BOOST_BACK_STORM_COUNT	3
#define WEAK_CHG_STORM_COUNT	8

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

enum smb_mode {
	PARALLEL_MASTER = 0,
	PARALLEL_SLAVE,
@@ -344,6 +346,7 @@ struct smb_charger {
	bool			use_extcon;
	bool			otg_present;
	int			hw_max_icl_ua;
	int			auto_recharge_soc;

	/* workaround flag */
	u32			wa_flags;
@@ -372,6 +375,8 @@ struct smb_charger {
int smblib_read(struct smb_charger *chg, u16 addr, u8 *val);
int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val);
int smblib_write(struct smb_charger *chg, u16 addr, u8 val);
int smblib_batch_write(struct smb_charger *chg, u16 addr, u8 *val, int count);
int smblib_batch_read(struct smb_charger *chg, u16 addr, u8 *val, int count);

int smblib_get_charge_param(struct smb_charger *chg,
			    struct smb_chg_param *param, int *val_u);
+13 −1
Original line number Diff line number Diff line
@@ -66,11 +66,17 @@ enum {
#define CHARGING_ENABLE_CMD_BIT			BIT(0)

#define CHGR_CFG2_REG				(CHGR_BASE + 0x51)
#define SOC_BASED_RECHG_BIT			BIT(1)
#define RECHG_MASK				GENMASK(2, 1)
#define VBAT_BASED_RECHG_BIT			BIT(2)
#define SOC_BASED_RECHG_BIT			GENMASK(2, 1)
#define CHARGER_INHIBIT_BIT			BIT(0)

#define CHGR_FAST_CHARGE_CURRENT_CFG_REG	(CHGR_BASE + 0x61)

#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)

#define CHGR_FLOAT_VOLTAGE_CFG_REG		(CHGR_BASE + 0x70)

#define CHARGE_INHIBIT_THRESHOLD_CFG_REG	(CHGR_BASE + 0x72)
@@ -80,6 +86,12 @@ enum {
#define INHIBIT_ANALOG_VFLT_MINUS_200MV		2
#define INHIBIT_ANALOG_VFLT_MINUS_300MV		3

#define CHARGE_RCHG_SOC_THRESHOLD_CFG_REG	(CHGR_BASE + 0x7D)

#define CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG	(CHGR_BASE + 0x7E)

#define CHGR_ADC_RECHARGE_THRESHOLD_LSB_REG	(CHGR_BASE + 0x7F)

#define JEITA_EN_CFG_REG			(CHGR_BASE + 0x90)
#define JEITA_EN_HOT_SL_FCV_BIT			BIT(3)
#define JEITA_EN_COLD_SL_FCV_BIT		BIT(2)