Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c05576dc authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

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

parents 596e11f6 89bf4e6b
Loading
Loading
Loading
Loading
+59 −10
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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);
}

@@ -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;
@@ -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) {
+15 −6
Original line number Diff line number Diff line
@@ -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) {
@@ -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 */
+3 −0
Original line number Diff line number Diff line
@@ -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,