Merge "dwc3: Handle USB spoof disconnect when EUD is enabled"

This commit is contained in:
qctecmdr 2020-04-07 18:49:51 -07:00 • committed by Gerrit - the friendly Code Review server
commit 651126b74a
3 changed files with 69 additions and 11 deletions

View file

@ -444,7 +444,9 @@ struct dwc3_msm {
bool in_device_mode;
enum usb_device_speed max_rh_port_speed;
unsigned int tx_fifo_size;
bool check_eud_state;
bool vbus_active;
bool eud_active;
bool suspend;
bool use_pdc_interrupts;
enum dwc3_id_state id_state;
@ -3149,6 +3151,39 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)
clear_bit(B_SUSPEND, &mdwc->inputs);
}
if (mdwc->check_eud_state) {
mdwc->hs_phy->flags &=
~(EUD_SPOOF_CONNECT | EUD_SPOOF_DISCONNECT);
dev_dbg(mdwc->dev, "eud: state:%d active:%d hs_phy_flags:0x%x\n",
mdwc->check_eud_state, mdwc->eud_active,
mdwc->hs_phy->flags);
if (mdwc->eud_active) {
mdwc->hs_phy->flags |= EUD_SPOOF_CONNECT;
dev_dbg(mdwc->dev, "EUD: XCVR: BSV set\n");
set_bit(B_SESS_VLD, &mdwc->inputs);
} else {
mdwc->hs_phy->flags |= EUD_SPOOF_DISCONNECT;
dev_dbg(mdwc->dev, "EUD: XCVR: BSV clear\n");
clear_bit(B_SESS_VLD, &mdwc->inputs);
}
mdwc->check_eud_state = false;
}
dev_dbg(mdwc->dev, "eud: state:%d active:%d hs_phy_flags:0x%x\n",
mdwc->check_eud_state, mdwc->eud_active, mdwc->hs_phy->flags);
/* handle case of USB cable disconnect after USB spoof disconnect */
if (!mdwc->vbus_active &&
(mdwc->hs_phy->flags & EUD_SPOOF_DISCONNECT)) {
mdwc->hs_phy->flags &= ~EUD_SPOOF_DISCONNECT;
mdwc->hs_phy->flags |= PHY_SUS_OVERRIDE;
usb_phy_set_suspend(mdwc->hs_phy, 1);
mdwc->hs_phy->flags &= ~PHY_SUS_OVERRIDE;
return;
}
queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0);
}
@ -3475,6 +3510,8 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
struct extcon_dev *edev = ptr;
struct extcon_nb *enb = container_of(nb, struct extcon_nb, vbus_nb);
struct dwc3_msm *mdwc = enb->mdwc;
char *eud_str;
const char *edev_name;
if (!edev || !mdwc)
return NOTIFY_DONE;
@ -3482,15 +3519,24 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
dwc = platform_get_drvdata(mdwc->dwc3);
dbg_event(0xFF, "extcon idx", enb->idx);
dev_dbg(mdwc->dev, "vbus:%ld event received\n", event);
edev_name = extcon_get_edev_name(edev);
dbg_log_string("edev:%s\n", edev_name);
if (mdwc->vbus_active == event)
return NOTIFY_DONE;
/* detect USB spoof disconnect/connect notification with EUD device */
eud_str = strnstr(edev_name, "eud", strlen(edev_name));
if (eud_str) {
if (mdwc->eud_active == event)
return NOTIFY_DONE;
mdwc->eud_active = event;
mdwc->check_eud_state = true;
} else {
if (mdwc->vbus_active == event)
return NOTIFY_DONE;
mdwc->vbus_active = event;
}
mdwc->ext_idx = enb->idx;
dev_dbg(mdwc->dev, "vbus:%ld event received\n", event);
mdwc->vbus_active = event;
if (dwc->dr_mode == USB_DR_MODE_OTG && !mdwc->in_restart)
queue_work(mdwc->dwc3_wq, &mdwc->resume_work);

View file

@ -341,7 +341,8 @@ static int msm_hsphy_init(struct usb_phy *uphy)
if (phy->eud_enable_reg && readl_relaxed(phy->eud_enable_reg)) {
dev_err(phy->phy.dev, "eud is enabled\n");
return 0;
ret = msm_hsphy_enable_power(phy, true);
return ret;
}
ret = msm_hsphy_enable_power(phy, true);
@ -460,11 +461,15 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend)
struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy);
if (phy->suspended && suspend) {
if (phy->phy.flags & PHY_SUS_OVERRIDE)
goto suspend;
dev_dbg(uphy->dev, "%s: USB PHY is already suspended\n",
__func__);
__func__);
return 0;
}
suspend:
if (suspend) { /* Bus suspend */
if (phy->cable_connected ||
(phy->phy.flags & PHY_HOST_MODE)) {
@ -480,9 +485,13 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend)
msm_hsphy_enable_clocks(phy, false);
} else {/* Cable disconnect */
mutex_lock(&phy->phy_lock);
dev_dbg(uphy->dev, "phy->flags:0x%x\n", phy->phy.flags);
if (!phy->dpdm_enable) {
msm_hsphy_enable_clocks(phy, false);
msm_hsphy_enable_power(phy, false);
if (!(phy->phy.flags & EUD_SPOOF_DISCONNECT)) {
dev_dbg(uphy->dev, "turning off clocks/ldo\n");
msm_hsphy_enable_clocks(phy, false);
msm_hsphy_enable_power(phy, false);
}
} else {
dev_dbg(uphy->dev, "dpdm reg still active. Keep clocks/ldo ON\n");
}

View file

@ -16,6 +16,9 @@
#define PHY_LANE_B BIT(3)
#define PHY_HSFS_MODE BIT(4)
#define PHY_LS_MODE BIT(5)
#define EUD_SPOOF_DISCONNECT BIT(6)
#define EUD_SPOOF_CONNECT BIT(7)
#define PHY_SUS_OVERRIDE BIT(8)
/*
* The following are bit fields describing the USB BAM options.