Loading drivers/usb/dwc3/dwc3-msm.c +53 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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; Loading @@ -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); /* 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); Loading drivers/usb/phy/phy-msm-snps-hs.c +13 −4 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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__); return 0; } suspend: if (suspend) { /* Bus suspend */ if (phy->cable_connected || (phy->phy.flags & PHY_HOST_MODE)) { Loading @@ -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) { 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"); } Loading include/linux/usb/dwc3-msm.h +3 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading
drivers/usb/dwc3/dwc3-msm.c +53 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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; Loading @@ -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); /* 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); Loading
drivers/usb/phy/phy-msm-snps-hs.c +13 −4 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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__); return 0; } suspend: if (suspend) { /* Bus suspend */ if (phy->cable_connected || (phy->phy.flags & PHY_HOST_MODE)) { Loading @@ -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) { 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"); } Loading
include/linux/usb/dwc3-msm.h +3 −0 Original line number Diff line number Diff line Loading @@ -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. Loading