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

Commit 43e07248 authored by Ashay Jaiswal's avatar Ashay Jaiswal
Browse files

power: qpnp-linear-charger: disable vbatdet irq based recharge



It is observed that VBAT_DET irq gets triggered just after 100% SOC
due to fluctuation in battery voltage after charging is disabled
causing multiple enabling/disabling of charging.

Add an option to disable VBAT_DET irq and VBAT_DET based recharge
and only use resume_soc based recharge.

The properties which enable this feature are:
1. "qcom,force-bms-active-on-charger": This BMS property ensures that
BMS FSM remains active as long as charger is present. This ensures
that post EOC charging starts when SOC < resume_soc.
2. "qcom,disable-vbatdet-based-recharge": This charger property disables
VBAT_DET irq and always keeps VBAT_DET comparator overriden to low.

When VBAT_DET comparator is overriden to 0, recharge doesnot depend on
battery voltage. The driver will then charge/recharge based on either
charger insertion or BMS reporting a SOC equal/lower than resume soc
threshold.

Thic configuration is not enabled by default.

CRs-Fixed: 679886
Change-Id: Ia7e419285e87669c16c9d055a714a82e59271f35
Signed-off-by: default avatarAshay Jaiswal <ashayj@codeaurora.org>
parent 30bb37f3
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -80,6 +80,13 @@ Parent node optional properties:
					If not specified charger driver
					depends on BMSfor end-of-charge
					detection.
- qcom,disable-vbatdet-based-recharge   If specified disable VBATDET irq
					and charging can only be resumed
					if charger is re-inserted or SOC
					falls below resume SOC.
					This property should always be used
					along with the BMS property:
					"qcom,disable-suspend-on-usb".
- qcom,use-external-charger		If specifed the LBC module will
					be disabled and the driver will not
					register. It also enables BID for
+2 −0
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ Parent node Optional properties
			the fifo_update_done interrupt. Possible values- 0 to 8
- qcom,force-s3-on-suspend : Bool property to force the BMS into S3 (sleep) state
			while entering into system suspend.
- qcom,force-bms-active-on-charger: Bool property to keep BMS FSM active
				if charger is present.
- qcom,report-charger-eoc : Bool property to indicate if BMS needs to indicate
			EOC to charger.
- qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
+26 −11
Original line number Diff line number Diff line
@@ -266,6 +266,8 @@ struct vddtrim_map vddtrim_map[] = {
 * @cfg_float_charge:		enable float charging
 * @charger_disabled:		maintain USB path state.
 * @cfg_charger_detect_eoc:	charger can detect end of charging
 * @cfg_disable_vbatdet_based_recharge:	keep VBATDET comparator overriden to
 *				low and VBATDET irq disabled.
 * @cfg_safe_current:		battery safety current setting
 * @cfg_hot_batt_p:		hot battery threshold setting
 * @cfg_cold_batt_p:		eold battery threshold setting
@@ -323,6 +325,7 @@ struct qpnp_lbc_chip {
	unsigned int			cfg_max_voltage_mv;
	unsigned int			cfg_min_voltage_mv;
	unsigned int			cfg_charger_detect_eoc;
	unsigned int			cfg_disable_vbatdet_based_recharge;
	unsigned int			cfg_batt_weak_voltage_uv;
	unsigned int			cfg_warm_bat_mv;
	unsigned int			cfg_cool_bat_mv;
@@ -1145,6 +1148,7 @@ static int get_prop_capacity(struct qpnp_lbc_chip *chip)
				&& ret.intval <= chip->cfg_soc_resume_limit) {
			pr_debug("resuming charging at %d%% soc\n",
					ret.intval);
			if (!chip->cfg_disable_vbatdet_based_recharge)
				qpnp_lbc_vbatdet_override(chip, OVERRIDE_0);
			qpnp_lbc_charger_enable(chip, SOC, 1);
		}
@@ -1419,11 +1423,7 @@ static int qpnp_batt_power_set_property(struct power_supply *psy,
		if (val->intval == POWER_SUPPLY_STATUS_FULL &&
				!chip->cfg_float_charge) {
			mutex_lock(&chip->chg_enable_lock);
			/* No override for VBAT_DET_LO comp */
			rc = qpnp_lbc_vbatdet_override(chip, OVERRIDE_NONE);
			if (rc)
				pr_err("Failed to override VBAT_DET rc=%d\n",
						rc);

			/* Disable charging */
			rc = qpnp_lbc_charger_enable(chip, SOC, 0);
			if (rc)
@@ -1437,8 +1437,17 @@ static int qpnp_batt_power_set_property(struct power_supply *psy,
			 * To enable charging when VBAT falls below VBAT_DET
			 * and device stays suspended after EOC.
			 */
			if (!chip->cfg_disable_vbatdet_based_recharge) {
				/* No override for VBAT_DET_LO comp */
				rc = qpnp_lbc_vbatdet_override(chip,
							OVERRIDE_NONE);
				if (rc)
					pr_err("Failed to override VBAT_DET rc=%d\n",
							rc);
				else
					qpnp_lbc_enable_irq(chip,
						&chip->irqs[CHG_VBAT_DET_LO]);
			}

			mutex_unlock(&chip->chg_enable_lock);
		}
@@ -1916,6 +1925,10 @@ static int qpnp_charger_read_dt_props(struct qpnp_lbc_chip *chip)
			of_property_read_bool(chip->spmi->dev.of_node,
					"qcom,charger-detect-eoc");

	/* Get the vbatdet disable property */
	chip->cfg_disable_vbatdet_based_recharge =
			of_property_read_bool(chip->spmi->dev.of_node,
					"qcom,disable-vbatdet-based-recharge");
	/* Disable charging when faking battery values */
	if (chip->cfg_use_fake_battery)
		chip->cfg_charging_disabled = true;
@@ -1972,6 +1985,7 @@ static irqreturn_t qpnp_lbc_usbin_valid_irq_handler(int irq, void *_chip)
			 * Override VBAT_DET comparator to start charging
			 * even if VBAT > VBAT_DET.
			 */
			if (!chip->cfg_disable_vbatdet_based_recharge)
				qpnp_lbc_vbatdet_override(chip, OVERRIDE_0);

			/*
@@ -2294,10 +2308,11 @@ static int qpnp_lbc_get_irqs(struct qpnp_lbc_chip *chip, u8 subtype,
	case LBC_CHGR_SUBTYPE:
		SPMI_GET_IRQ_RESOURCE(chip, rc, spmi_resource,
						CHG_FAST_CHG, fast-chg-on);
		SPMI_GET_IRQ_RESOURCE(chip, rc, spmi_resource,
						CHG_VBAT_DET_LO, vbat-det-lo);
		SPMI_GET_IRQ_RESOURCE(chip, rc, spmi_resource,
						CHG_FAILED, chg-failed);
		if (!chip->cfg_disable_vbatdet_based_recharge)
			SPMI_GET_IRQ_RESOURCE(chip, rc, spmi_resource,
						CHG_VBAT_DET_LO, vbat-det-lo);
		if (chip->cfg_charger_detect_eoc)
			SPMI_GET_IRQ_RESOURCE(chip, rc, spmi_resource,
						CHG_DONE, chg-done);
+37 −6
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ struct bms_wakeup_source {

struct bms_dt_cfg {
	bool				cfg_report_charger_eoc;
	bool				cfg_force_bms_active_on_charger;
	bool				cfg_force_s3_on_suspend;
	bool				cfg_ignore_shutdown_soc;
	bool				cfg_use_voltage_soc;
@@ -233,6 +234,7 @@ struct qpnp_bms_chip {
	struct bms_irq			fsm_state_change_irq;
	struct power_supply		bms_psy;
	struct power_supply		*batt_psy;
	struct power_supply		*usb_psy;
};

static struct qpnp_bms_chip *the_chip;
@@ -417,6 +419,21 @@ static int calculate_delta_time(unsigned long *time_stamp, int *delta_time_s)
	return 0;
}

static bool is_charger_present(struct qpnp_bms_chip *chip)
{
	union power_supply_propval ret = {0,};

	if (chip->usb_psy == NULL)
		chip->usb_psy = power_supply_get_by_name("usb");
	if (chip->usb_psy) {
		chip->usb_psy->get_property(chip->usb_psy,
					POWER_SUPPLY_PROP_PRESENT, &ret);
		return ret.intval;
	}

	return false;
}

static bool is_battery_charging(struct qpnp_bms_chip *chip)
{
	union power_supply_propval ret = {0,};
@@ -2971,7 +2988,9 @@ static int parse_bms_dt_properties(struct qpnp_bms_chip *chip)
			chip->spmi->dev.of_node, "qcom,report-charger-eoc");
	chip->dt.cfg_disable_bms = of_property_read_bool(
			chip->spmi->dev.of_node, "qcom,disable-bms");

	chip->dt.cfg_force_bms_active_on_charger = of_property_read_bool(
			chip->spmi->dev.of_node,
			"qcom,force-bms-active-on-charger");
	pr_debug("v_cutoff_uv=%d, max_v=%d\n", chip->dt.cfg_v_cutoff_uv,
					chip->dt.cfg_max_voltage_uv);
	pr_debug("r_conn=%d shutdown_soc_valid_limit=%d\n",
@@ -2981,10 +3000,11 @@ static int parse_bms_dt_properties(struct qpnp_bms_chip *chip)
				chip->dt.cfg_ignore_shutdown_soc,
				chip->dt.cfg_use_voltage_soc,
				chip->dt.cfg_low_soc_fifo_length);
	pr_debug("force-s3-on-suspend=%d report-charger-eoc=%d disable-bms=%d\n",
	pr_debug("force-s3-on-suspend=%d report-charger-eoc=%d disable-bms=%d disable-suspend-on-usb=%d\n",
			chip->dt.cfg_force_s3_on_suspend,
			chip->dt.cfg_report_charger_eoc,
			chip->dt.cfg_disable_bms);
			chip->dt.cfg_disable_bms,
			chip->dt.cfg_force_bms_active_on_charger);

	return 0;
}
@@ -3378,15 +3398,26 @@ static int bms_suspend(struct device *dev)
	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
	bool battery_charging = is_battery_charging(chip);
	bool hi_power_state = is_hi_power_state_requested(chip);
	bool charger_present = is_charger_present(chip);
	bool bms_suspend_config;

	/*
	 * Keep BMS FSM active if 'cfg_force_bms_active_on_charger' property
	 * is present and charger inserted. This ensures that recharge
	 * starts once battery SOC falls below resume_soc.
	 */
	bms_suspend_config = chip->dt.cfg_force_bms_active_on_charger
						&& charger_present;

	chip->apply_suspend_config = false;
	if (!battery_charging && !hi_power_state)
	if (!battery_charging && !hi_power_state && !bms_suspend_config)
		chip->apply_suspend_config = true;

	pr_debug("battery_charging=%d power_state=%s hi_power_state=0x%x apply_suspend_config=%d\n",
	pr_debug("battery_charging=%d power_state=%s hi_power_state=0x%x apply_suspend_config=%d bms_suspend_config=%d usb_present=%d\n",
			battery_charging, hi_power_state ? "hi" : "low",
				chip->hi_power_state,
				chip->apply_suspend_config);
				chip->apply_suspend_config, bms_suspend_config,
				charger_present);

	if (chip->apply_suspend_config) {
		if (chip->dt.cfg_force_s3_on_suspend) {