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

Commit 02881861 authored by Harry Yang's avatar Harry Yang
Browse files

battery: handle early/late suspend/resume of i2c bus



The i2c bus could suspend right after the parallel charger's suspend
i.e. no i2c access available during suspend_noirq stages. Similarly
on the resume path, there is no i2c access until resume() callback.

However the PMI can handle interrupts right before its own suspend_irq
and right after its own resume_irq. Those interrupts could invoke
transactions for parallel charger but that is either too late or very
early for any i2c transactions.

To fix this, hold a wakelock once parallel is enabled and release the
wakelock 5 seconds after parallel is disabled.

Change-Id: Id517b5afca090d7f3ccb31e640512bdb9f902377
Signed-off-by: default avatarHarry Yang <harryy@codeaurora.org>
parent 1cc4edf0
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct pl_data {
	struct delayed_work	status_change_work;
	struct work_struct	pl_disable_forever_work;
	struct work_struct	pl_taper_work;
	struct delayed_work	pl_awake_work;
	bool			taper_work_running;
	struct power_supply	*main_psy;
	struct power_supply	*pl_psy;
@@ -568,6 +569,14 @@ static void pl_disable_forever_work(struct work_struct *work)
		vote(chip->hvdcp_hw_inov_dis_votable, PL_VOTER, false, 0);
}

static void pl_awake_work(struct work_struct *work)
{
	struct pl_data *chip = container_of(work,
			struct pl_data, pl_awake_work.work);

	vote(chip->pl_awake_votable, PL_VOTER, false, 0);
}

static bool is_main_available(struct pl_data *chip)
{
	if (chip->main_psy)
@@ -595,6 +604,10 @@ static int pl_disable_vote_callback(struct votable *votable,
	total_fcc_ua = get_effective_result_locked(chip->fcc_votable);

	if (chip->pl_mode != POWER_SUPPLY_PL_NONE && !pl_disable) {
		/* keep system awake to talk to slave charger through i2c */
		cancel_delayed_work_sync(&chip->pl_awake_work);
		vote(chip->pl_awake_votable, PL_VOTER, true, 0);

		 /* enable parallel charging */
		rc = power_supply_get_property(chip->pl_psy,
				POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
@@ -698,6 +711,10 @@ static int pl_disable_vote_callback(struct votable *votable,
		}

		rerun_election(chip->fv_votable);

		cancel_delayed_work_sync(&chip->pl_awake_work);
		schedule_delayed_work(&chip->pl_awake_work,
						msecs_to_jiffies(5000));
	}

	pl_dbg(chip, PR_PARALLEL, "parallel charging %s\n",
@@ -1075,6 +1092,7 @@ int qcom_batt_init(void)
	INIT_DELAYED_WORK(&chip->status_change_work, status_change_work);
	INIT_WORK(&chip->pl_taper_work, pl_taper_work);
	INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work);
	INIT_DELAYED_WORK(&chip->pl_awake_work, pl_awake_work);

	rc = pl_register_notifier(chip);
	if (rc < 0) {
@@ -1128,6 +1146,7 @@ void qcom_batt_deinit(void)
	cancel_delayed_work_sync(&chip->status_change_work);
	cancel_work_sync(&chip->pl_taper_work);
	cancel_work_sync(&chip->pl_disable_forever_work);
	cancel_delayed_work_sync(&chip->pl_awake_work);

	power_supply_unreg_notifier(&chip->nb);
	destroy_votable(chip->pl_enable_votable_indirect);