Loading drivers/usb/dwc3/dwc3-msm.c +59 −10 Original line number Diff line number Diff line Loading @@ -311,7 +311,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 @@ -2855,8 +2857,13 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc) } if (mdwc->vbus_active && !mdwc->in_restart) { if (mdwc->hs_phy->flags & EUD_SPOOF_DISCONNECT) { dev_dbg(mdwc->dev, "XCVR:EUD: BSV clear\n"); clear_bit(B_SESS_VLD, &mdwc->inputs); } else { dev_dbg(mdwc->dev, "XCVR: BSV set\n"); set_bit(B_SESS_VLD, &mdwc->inputs); } } else { dev_dbg(mdwc->dev, "XCVR: BSV clear\n"); clear_bit(B_SESS_VLD, &mdwc->inputs); Loading @@ -2870,6 +2877,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 @@ -3235,6 +3275,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 @@ -3242,15 +3284,22 @@ 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->ext_idx = enb->idx; dev_dbg(mdwc->dev, "vbus:%ld event received\n", event); mdwc->vbus_active = event; } if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_CDP && mdwc->vbus_active) { Loading drivers/usb/phy/phy-msm-qusb-v2.c +15 −6 Original line number Diff line number Diff line Loading @@ -650,11 +650,15 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) u32 linestate = 0, intr_mask = 0; if (qphy->suspended == suspend) { if (qphy->phy.flags & PHY_SUS_OVERRIDE) goto suspend; dev_dbg(phy->dev, "%s: USB PHY is already suspended\n", __func__); return 0; } suspend: if (suspend) { /* Bus suspend case */ if (qphy->cable_connected) { Loading Loading @@ -699,12 +703,17 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) qusb_phy_enable_clocks(qphy, false); } else { /* Cable disconnect case */ /* Disable all interrupts */ dev_dbg(phy->dev, "%s: phy->flags:0x%x\n", __func__, qphy->phy.flags); if (!(qphy->phy.flags & EUD_SPOOF_DISCONNECT)) { dev_dbg(phy->dev, "turning off clocks/ldo\n"); writel_relaxed(0x00, qphy->base + qphy->phy_reg[INTR_CTRL]); qusb_phy_reset(qphy); qusb_phy_enable_clocks(qphy, false); qusb_phy_disable_power(qphy); } } qphy->suspended = true; } else { /* Bus resume case */ Loading include/linux/usb/phy.h +3 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,9 @@ #define PHY_HSFS_MODE BIT(8) #define PHY_LS_MODE BIT(9) #define PHY_USB_DP_CONCURRENT_MODE BIT(10) #define EUD_SPOOF_DISCONNECT BIT(11) #define EUD_SPOOF_CONNECT BIT(12) #define PHY_SUS_OVERRIDE BIT(13) enum usb_phy_interface { USBPHY_INTERFACE_MODE_UNKNOWN, Loading Loading
drivers/usb/dwc3/dwc3-msm.c +59 −10 Original line number Diff line number Diff line Loading @@ -311,7 +311,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 @@ -2855,8 +2857,13 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc) } if (mdwc->vbus_active && !mdwc->in_restart) { if (mdwc->hs_phy->flags & EUD_SPOOF_DISCONNECT) { dev_dbg(mdwc->dev, "XCVR:EUD: BSV clear\n"); clear_bit(B_SESS_VLD, &mdwc->inputs); } else { dev_dbg(mdwc->dev, "XCVR: BSV set\n"); set_bit(B_SESS_VLD, &mdwc->inputs); } } else { dev_dbg(mdwc->dev, "XCVR: BSV clear\n"); clear_bit(B_SESS_VLD, &mdwc->inputs); Loading @@ -2870,6 +2877,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 @@ -3235,6 +3275,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 @@ -3242,15 +3284,22 @@ 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->ext_idx = enb->idx; dev_dbg(mdwc->dev, "vbus:%ld event received\n", event); mdwc->vbus_active = event; } if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_CDP && mdwc->vbus_active) { Loading
drivers/usb/phy/phy-msm-qusb-v2.c +15 −6 Original line number Diff line number Diff line Loading @@ -650,11 +650,15 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) u32 linestate = 0, intr_mask = 0; if (qphy->suspended == suspend) { if (qphy->phy.flags & PHY_SUS_OVERRIDE) goto suspend; dev_dbg(phy->dev, "%s: USB PHY is already suspended\n", __func__); return 0; } suspend: if (suspend) { /* Bus suspend case */ if (qphy->cable_connected) { Loading Loading @@ -699,12 +703,17 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) qusb_phy_enable_clocks(qphy, false); } else { /* Cable disconnect case */ /* Disable all interrupts */ dev_dbg(phy->dev, "%s: phy->flags:0x%x\n", __func__, qphy->phy.flags); if (!(qphy->phy.flags & EUD_SPOOF_DISCONNECT)) { dev_dbg(phy->dev, "turning off clocks/ldo\n"); writel_relaxed(0x00, qphy->base + qphy->phy_reg[INTR_CTRL]); qusb_phy_reset(qphy); qusb_phy_enable_clocks(qphy, false); qusb_phy_disable_power(qphy); } } qphy->suspended = true; } else { /* Bus resume case */ Loading
include/linux/usb/phy.h +3 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,9 @@ #define PHY_HSFS_MODE BIT(8) #define PHY_LS_MODE BIT(9) #define PHY_USB_DP_CONCURRENT_MODE BIT(10) #define EUD_SPOOF_DISCONNECT BIT(11) #define EUD_SPOOF_CONNECT BIT(12) #define PHY_SUS_OVERRIDE BIT(13) enum usb_phy_interface { USBPHY_INTERFACE_MODE_UNKNOWN, Loading