From 9e2a6b5541dd93a934d491b67056e8821bbd9c18 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Mon, 24 Apr 2017 14:06:54 -0700 Subject: [PATCH] qpnp-smb2: don't stomp over D+/D- during hard reset Currently when we are in hard reset, the driver requests to remove the float of D+/D- when VBUS drops and once VBUS is back, it requests to float D+/D- again. This behaviour ends up stomping over D+/D- lines leading to noncompliance with PD spec. Fix it by ensuring we only run the CC2 workaround while VBUS dips in hard reset. Change-Id: I2bb9364b890b3a227dd3ea3e0a34a415b600e21a Signed-off-by: Abhijeet Dharmapurikar --- drivers/power/supply/qcom/smb-lib.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index d73f45f4714d..cc83309d3c03 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -3152,12 +3152,28 @@ static void smblib_micro_usb_plugin(struct smb_charger *chg, bool vbus_rising) } } -static void smblib_typec_usb_plugin(struct smb_charger *chg, bool vbus_rising) +void smblib_usb_plugin_hard_reset_locked(struct smb_charger *chg) { + int rc; + u8 stat; + bool vbus_rising; + + rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc); + return; + } + + vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT); + if (vbus_rising) smblib_cc2_sink_removal_exit(chg); else smblib_cc2_sink_removal_enter(chg); + + power_supply_changed(chg->usb_psy); + smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n", + vbus_rising ? "attached" : "detached"); } #define PL_DELAY_MS 30000 @@ -3216,8 +3232,6 @@ void smblib_usb_plugin_locked(struct smb_charger *chg) if (chg->micro_usb_mode) smblib_micro_usb_plugin(chg, vbus_rising); - else - smblib_typec_usb_plugin(chg, vbus_rising); power_supply_changed(chg->usb_psy); smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n", @@ -3230,7 +3244,10 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) struct smb_charger *chg = irq_data->parent_data; mutex_lock(&chg->lock); - smblib_usb_plugin_locked(chg); + if (chg->pd_hard_reset) + smblib_usb_plugin_hard_reset_locked(chg); + else + smblib_usb_plugin_locked(chg); mutex_unlock(&chg->lock); return IRQ_HANDLED; }