summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorAshay Jaiswal <ashayj@codeaurora.org>2017-05-18 15:28:31 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2017-05-23 23:22:42 -0700
commite697192c09fbc46a90fa9594783a83c4fa10bf7f (patch)
treeafddf2985c4b105021056f1c7ae3f0cdeb8324ca /drivers/power
parent60be71604a84d2e047215cb702d6324379a353bb (diff)
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>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/supply/qcom/smb-lib.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 5a2af79eb568..c9ebe394c53b 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -638,6 +638,7 @@ static void smblib_uusb_removal(struct smb_charger *chg)
/* 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);
@@ -1985,6 +1986,7 @@ static int smblib_dm_pulse(struct smb_charger *chg)
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:
@@ -2002,10 +2004,35 @@ int smblib_dp_dm(struct smb_charger *chg, int val)
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:
@@ -3620,6 +3647,7 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
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);