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

Commit a7fb9d0e authored by Xiaozhe Shi's avatar Xiaozhe Shi
Browse files

power: qpnp-charger: resume charging correctly after EoC



Currently, there can be a race condition when charging ends at 99%
battery state of charge (SoC), but BMS does not immediately report
100%. This causes the charger to immediately resume charging because
SoC is below 100.

Fix this by recalculating the battery SoC in the BMS driver
immediately when getting a power supply notification from the
charger. Also have the charger check the BMS power supply status to
make sure that the BMS knows that the battery is not charging before
resuming charging.

Change-Id: I40388b6067ec1ec6d6433a6f6694e449f6fcb48f
Signed-off-by: default avatarXiaozhe Shi <xiaozhes@codeaurora.org>
parent 59ee9ab3
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ struct qpnp_bms_chip {
	struct mutex			vbat_monitor_mutex;
	struct mutex			soc_invalidation_mutex;
	struct mutex			last_soc_mutex;
	struct mutex			status_lock;

	bool				use_external_rsense;
	bool				use_ocv_thresholds;
@@ -297,6 +298,7 @@ static char *qpnp_bms_supplicants[] = {

static enum power_supply_property msm_bms_power_props[] = {
	POWER_SUPPLY_PROP_CAPACITY,
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_CURRENT_NOW,
	POWER_SUPPLY_PROP_RESISTANCE,
	POWER_SUPPLY_PROP_CHARGE_COUNTER,
@@ -3139,6 +3141,7 @@ static void battery_status_check(struct qpnp_bms_chip *chip)
{
	int status = get_battery_status(chip);

	mutex_lock(&chip->status_lock);
	if (chip->battery_status != status) {
		pr_debug("status = %d, shadow status = %d\n",
				status, chip->battery_status);
@@ -3155,6 +3158,7 @@ static void battery_status_check(struct qpnp_bms_chip *chip)
			pr_debug("battery full\n");
			enable_bms_irq(&chip->ocv_thr_irq);
			enable_bms_irq(&chip->sw_cc_thr_irq);
			recalculate_soc(chip);
		} else if (chip->battery_status
				== POWER_SUPPLY_STATUS_FULL) {
			pr_debug("battery not full any more\n");
@@ -3167,6 +3171,7 @@ static void battery_status_check(struct qpnp_bms_chip *chip)
		 * recalculation to update the SoC */
		schedule_work(&chip->recalc_work);
	}
	mutex_unlock(&chip->status_lock);
}

#define CALIB_WRKARND_DIG_MAJOR_MAX		0x03
@@ -3249,6 +3254,9 @@ static int qpnp_bms_power_get_property(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CAPACITY:
		val->intval = get_prop_bms_capacity(chip);
		break;
	case POWER_SUPPLY_PROP_STATUS:
		val->intval = chip->battery_status;
		break;
	case POWER_SUPPLY_PROP_CURRENT_NOW:
		val->intval = get_prop_bms_current_now(chip);
		break;
@@ -4034,6 +4042,7 @@ static int qpnp_bms_probe(struct spmi_device *spmi)
	mutex_init(&chip->vbat_monitor_mutex);
	mutex_init(&chip->soc_invalidation_mutex);
	mutex_init(&chip->last_soc_mutex);
	mutex_init(&chip->status_lock);
	init_waitqueue_head(&chip->bms_wait_queue);

	warm_reset = qpnp_pon_is_warm_reset();
+10 −6
Original line number Diff line number Diff line
@@ -1714,7 +1714,7 @@ static int
get_prop_capacity(struct qpnp_chg_chip *chip)
{
	union power_supply_propval ret = {0,};
	int battery_status, charger_in;
	int battery_status, bms_status, soc, charger_in;

	if (chip->use_default_batt_values || !get_prop_batt_present(chip))
		return DEFAULT_CAPACITY;
@@ -1722,28 +1722,32 @@ get_prop_capacity(struct qpnp_chg_chip *chip)
	if (chip->bms_psy) {
		chip->bms_psy->get_property(chip->bms_psy,
				POWER_SUPPLY_PROP_CAPACITY, &ret);
		soc = ret.intval;
		battery_status = get_prop_batt_status(chip);
		chip->bms_psy->get_property(chip->bms_psy,
				POWER_SUPPLY_PROP_STATUS, &ret);
		bms_status = ret.intval;
		charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
			qpnp_chg_is_dc_chg_plugged_in(chip);

		if (battery_status != POWER_SUPPLY_STATUS_CHARGING
				&& bms_status != POWER_SUPPLY_STATUS_CHARGING
				&& charger_in
				&& !chip->resuming_charging
				&& !chip->charging_disabled
				&& chip->soc_resume_limit
				&& ret.intval <= chip->soc_resume_limit) {
			pr_debug("resuming charging at %d%% soc\n",
					ret.intval);
				&& soc <= chip->soc_resume_limit) {
			pr_debug("resuming charging at %d%% soc\n", soc);
			chip->resuming_charging = true;
			qpnp_chg_set_appropriate_vbatdet(chip);
			qpnp_chg_charge_en(chip, !chip->charging_disabled);
		}
		if (ret.intval == 0) {
		if (soc == 0) {
			if (!qpnp_chg_is_usb_chg_plugged_in(chip)
				&& !qpnp_chg_is_usb_chg_plugged_in(chip))
				pr_warn_ratelimited("Battery 0, CHG absent\n");
		}
		return ret.intval;
		return soc;
	} else {
		pr_debug("No BMS supply registered return 50\n");
	}