diff options
author | Ashay Jaiswal <ashayj@codeaurora.org> | 2017-05-18 15:28:31 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-05-23 23:22:42 -0700 |
commit | e697192c09fbc46a90fa9594783a83c4fa10bf7f (patch) | |
tree | afddf2985c4b105021056f1c7ae3f0cdeb8324ca /drivers/power | |
parent | 60be71604a84d2e047215cb702d6324379a353bb (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.c | 32 |
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); |