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

Commit e86c77ed authored by Mayank Rana's avatar Mayank Rana
Browse files

dwc3: Handle USB spoof disconnect when EUD is enabled



Due to dpdm regulator is not being used on newer platform as
ADSP firmware takes care of charger detection, there is no
way to detect USB cable disconnect vs USB spoof disconnect
when EUD is enabled. This change identifies USB spoof
disconnect and provides spoof disconnect related information
to USB PHY driver to avoid turning off PHY clocks and regulators.

Change-Id: I8f6b953e7196378b9786fe268a08cc1a0e2620d3
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 17c22334
Loading
Loading
Loading
Loading
+53 −7
Original line number Diff line number Diff line
@@ -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);

	/* 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);

+13 −4
Original line number Diff line number Diff line
@@ -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__);
		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) {
				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");
			}
+3 −0
Original line number Diff line number Diff line
@@ -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.