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

Commit 8a1c1bab authored by Guru Das Srinagesh's avatar Guru Das Srinagesh
Browse files

power: smb5: Announce DCIN AICL done via PSY property



Add support for exposing whether or not DCIN AICL process has finished
executing via the DC PSY property AICL_DONE.

AICL is declared as done if there are no error conditions encountered
while doing the work. AICL status is set to not done when DC PSY is
detached, both from the DC plugin handler as well as after determining
DCIN AICL has hit max.  The latter case is to address the following edge
case scenario:

1. DCIN AICL work completes normally due to hitting max ICL
2. WLS voltage is decremented after being first incremented by
   userspace.
3. DCIN AICL rerun is triggered in 5 sec as a result of the voltage
   decrement. (The adaptor is still healthy and so ICL remains still at
   max.)
4. WLS detach occurs before expiry of 500 ms in the work, so even though
   DC plugin detach path clears AICL done, the DCIN AICL work re-sets it
   to done after waking up from the 500 ms sleep.

While at it, change criteria for decrementing DCIN ICL from exact
equality to a minimum check. This will make the logic more robust to any
DCIN UV storms. Also remove stale comment.

Change-Id: I787705ecb874356aa475bb98e6b596a020cc548e
Signed-off-by: default avatarGuru Das Srinagesh <gurus@codeaurora.org>
parent e24a3925
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1413,6 +1413,7 @@ static enum power_supply_property smb5_dc_props[] = {
	POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
	POWER_SUPPLY_PROP_REAL_TYPE,
	POWER_SUPPLY_PROP_DC_RESET,
	POWER_SUPPLY_PROP_AICL_DONE,
};

static int smb5_dc_get_prop(struct power_supply *psy,
@@ -1451,6 +1452,9 @@ static int smb5_dc_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_DC_RESET:
		val->intval = 0;
		break;
	case POWER_SUPPLY_PROP_AICL_DONE:
		val->intval = chg->dcin_aicl_done;
		break;
	default:
		return -EINVAL;
	}
+21 −7
Original line number Diff line number Diff line
@@ -3019,7 +3019,6 @@ int smblib_set_prop_voltage_wls_output(struct smb_charger *chg,
	 * to supply more current, so allow it to do so.
	 */
	if ((val->intval > 0) && (val->intval < chg->last_wls_vout)) {
		/* Rerun AICL once after 10 s */
		alarm_start_relative(&chg->dcin_aicl_alarm,
				ms_to_ktime(DCIN_AICL_RERUN_DELAY_MS));
	}
@@ -6046,6 +6045,7 @@ static void dcin_aicl(struct smb_charger *chg)
{
	int rc, icl, icl_save;
	int input_present;
	bool aicl_done = true;

	/*
	 * Hold awake votable to prevent pm_relax being called prior to
@@ -6058,11 +6058,16 @@ static void dcin_aicl(struct smb_charger *chg)

	rc = smblib_get_charge_param(chg, &chg->param.dc_icl, &icl);
	if (rc < 0)
		goto unlock;
		goto err;

	if (icl == chg->wls_icl_ua) {
		/* Upper limit reached; do nothing */
		smblib_dbg(chg, PR_WLS, "hit max ICL: stop\n");

		rc = smblib_is_input_present(chg, &input_present);
		if (rc < 0 || !(input_present & INPUT_PRESENT_DC))
			aicl_done = false;

		goto unlock;
	}

@@ -6071,7 +6076,7 @@ static void dcin_aicl(struct smb_charger *chg)

	rc = smblib_set_charge_param(chg, &chg->param.dc_icl, icl);
	if (rc < 0)
		goto unlock;
		goto err;

	mutex_unlock(&chg->dcin_aicl_lock);

@@ -6079,8 +6084,10 @@ static void dcin_aicl(struct smb_charger *chg)

	/* Check to see if DC is still present before and after sleep */
	rc = smblib_is_input_present(chg, &input_present);
	if (!(input_present & INPUT_PRESENT_DC) || rc < 0)
	if (rc < 0 || !(input_present & INPUT_PRESENT_DC)) {
		aicl_done = false;
		goto unvote;
	}

	/*
	 * Wait awhile to check for any DCIN_UVs (the UV handler reduces the
@@ -6090,14 +6097,16 @@ static void dcin_aicl(struct smb_charger *chg)
	msleep(500);

	rc = smblib_is_input_present(chg, &input_present);
	if (!(input_present & INPUT_PRESENT_DC) || rc < 0)
	if (rc < 0 || !(input_present & INPUT_PRESENT_DC)) {
		aicl_done = false;
		goto unvote;
	}

	mutex_lock(&chg->dcin_aicl_lock);

	rc = smblib_get_charge_param(chg, &chg->param.dc_icl, &icl);
	if (rc < 0)
		goto unlock;
		goto err;

	if (icl < icl_save) {
		smblib_dbg(chg, PR_WLS, "done: icl: %d mA\n", (icl / 1000));
@@ -6107,10 +6116,14 @@ static void dcin_aicl(struct smb_charger *chg)
	mutex_unlock(&chg->dcin_aicl_lock);

	goto increment;

err:
	aicl_done = false;
unlock:
	mutex_unlock(&chg->dcin_aicl_lock);
unvote:
	vote(chg->awake_votable, DCIN_AICL_VOTER, false, 0);
	chg->dcin_aicl_done = aicl_done;
}

static void dcin_aicl_work(struct work_struct *work)
@@ -6154,7 +6167,7 @@ static void dcin_icl_decrement(struct smb_charger *chg)
	/* Reduce ICL by 100 mA if 3 UVs happen in a row */
	if (ktime_us_delta(now, chg->dcin_uv_last_time) > (200 * 1000)) {
		chg->dcin_uv_count = 0;
	} else if (chg->dcin_uv_count == 3) {
	} else if (chg->dcin_uv_count >= 3) {
		icl -= DCIN_ICL_STEP_UA;

		smblib_dbg(chg, PR_WLS, "icl: %d mA\n", (icl / 1000));
@@ -6314,6 +6327,7 @@ irqreturn_t dc_plugin_irq_handler(int irq, void *data)
			vote(chg->fcc_votable, FCC_STEPPER_VOTER,
							true, 1500000);
		chg->last_wls_vout = 0;
		chg->dcin_aicl_done = false;
	}

	if (chg->dc_psy)
+1 −0
Original line number Diff line number Diff line
@@ -548,6 +548,7 @@ struct smb_charger {
	int			init_thermal_ua;
	u32			comp_clamp_level;
	int			wls_icl_ua;
	bool			dcin_aicl_done;

	/* workaround flag */
	u32			wa_flags;