qpnp: smb2: fix ICL recovery mechanism
ICL recovery mechanism is used by user space daemon
to recover from adapter collapse during voltage increment
event by reducing the USB ICL. There could be a situation
where nobody votes on usb_icl_votable and this could lead
to a negative ICL value.
Fix this by reading "HW_CURRENT_MAX" property to get ICL in
situations where usb_icl_votable is not voted by any client,
this ensures ICL reduction will always vote a valid ICL.
CRs-Fixed: 2048330
Change-Id: I8e53a945530c1685aaaba0537d16ac5fb11858df
Signed-off-by: Ashay Jaiswal <ashayj@codeaurora.org>
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index ba2250c..44eaea2 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -637,6 +637,7 @@
/* reset both usbin current and voltage votes */
vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
+ vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
cancel_delayed_work_sync(&chg->hvdcp_detect_work);
@@ -1941,6 +1942,7 @@
int smblib_dp_dm(struct smb_charger *chg, int val)
{
int target_icl_ua, rc = 0;
+ union power_supply_propval pval;
switch (val) {
case POWER_SUPPLY_DP_DM_DP_PULSE:
@@ -1958,10 +1960,35 @@
rc, chg->pulse_cnt);
break;
case POWER_SUPPLY_DP_DM_ICL_DOWN:
- chg->usb_icl_delta_ua -= 100000;
target_icl_ua = get_effective_result(chg->usb_icl_votable);
+ if (target_icl_ua < 0) {
+ /* no client vote, get the ICL from charger */
+ rc = power_supply_get_property(chg->usb_psy,
+ POWER_SUPPLY_PROP_HW_CURRENT_MAX,
+ &pval);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't get max current rc=%d\n",
+ rc);
+ return rc;
+ }
+ target_icl_ua = pval.intval;
+ }
+
+ /*
+ * Check if any other voter voted on USB_ICL in case of
+ * voter other than SW_QC3_VOTER reset and restart reduction
+ * again.
+ */
+ if (target_icl_ua != get_client_vote(chg->usb_icl_votable,
+ SW_QC3_VOTER))
+ chg->usb_icl_delta_ua = 0;
+
+ chg->usb_icl_delta_ua += 100000;
vote(chg->usb_icl_votable, SW_QC3_VOTER, true,
- target_icl_ua + chg->usb_icl_delta_ua);
+ target_icl_ua - 100000);
+ smblib_dbg(chg, PR_PARALLEL, "ICL DOWN ICL=%d reduction=%d\n",
+ target_icl_ua, chg->usb_icl_delta_ua);
break;
case POWER_SUPPLY_DP_DM_ICL_UP:
default:
@@ -3580,6 +3607,7 @@
vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
+ vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
/* reset hvdcp voters */
vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);