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

Commit 89bf4e6b authored by Pratham Pratap's avatar Pratham Pratap Committed by Gerrit - the friendly Code Review server
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>
Signed-off-by: default avatarPratham Pratap <prathampratap@codeaurora.org>
parent 74acccef
Loading
Loading
Loading
Loading
+59 −10
Original line number Original line Diff line number Diff line
@@ -311,7 +311,9 @@ struct dwc3_msm {
	bool			in_device_mode;
	bool			in_device_mode;
	enum usb_device_speed	max_rh_port_speed;
	enum usb_device_speed	max_rh_port_speed;
	unsigned int		tx_fifo_size;
	unsigned int		tx_fifo_size;
	bool			check_eud_state;
	bool			vbus_active;
	bool			vbus_active;
	bool			eud_active;
	bool			suspend;
	bool			suspend;
	bool			use_pdc_interrupts;
	bool			use_pdc_interrupts;
	enum dwc3_id_state	id_state;
	enum dwc3_id_state	id_state;
@@ -2846,8 +2848,13 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)
	}
	}


	if (mdwc->vbus_active && !mdwc->in_restart) {
	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");
			dev_dbg(mdwc->dev, "XCVR: BSV set\n");
			set_bit(B_SESS_VLD, &mdwc->inputs);
			set_bit(B_SESS_VLD, &mdwc->inputs);
		}
	} else {
	} else {
		dev_dbg(mdwc->dev, "XCVR: BSV clear\n");
		dev_dbg(mdwc->dev, "XCVR: BSV clear\n");
		clear_bit(B_SESS_VLD, &mdwc->inputs);
		clear_bit(B_SESS_VLD, &mdwc->inputs);
@@ -2861,6 +2868,39 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)
		clear_bit(B_SUSPEND, &mdwc->inputs);
		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);
	queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0);
}
}


@@ -3226,6 +3266,8 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
	struct extcon_dev *edev = ptr;
	struct extcon_dev *edev = ptr;
	struct extcon_nb *enb = container_of(nb, struct extcon_nb, vbus_nb);
	struct extcon_nb *enb = container_of(nb, struct extcon_nb, vbus_nb);
	struct dwc3_msm *mdwc = enb->mdwc;
	struct dwc3_msm *mdwc = enb->mdwc;
	char *eud_str;
	const char *edev_name;


	if (!edev || !mdwc)
	if (!edev || !mdwc)
		return NOTIFY_DONE;
		return NOTIFY_DONE;
@@ -3233,15 +3275,22 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
	dwc = platform_get_drvdata(mdwc->dwc3);
	dwc = platform_get_drvdata(mdwc->dwc3);


	dbg_event(0xFF, "extcon idx", enb->idx);
	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)
		if (mdwc->vbus_active == event)
			return NOTIFY_DONE;
			return NOTIFY_DONE;

	mdwc->ext_idx = enb->idx;

	dev_dbg(mdwc->dev, "vbus:%ld event received\n", event);

		mdwc->vbus_active = event;
		mdwc->vbus_active = event;
	}


	if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_CDP &&
	if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_CDP &&
			mdwc->vbus_active) {
			mdwc->vbus_active) {
+15 −6
Original line number Original line Diff line number Diff line
@@ -624,11 +624,15 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
	u32 linestate = 0, intr_mask = 0;
	u32 linestate = 0, intr_mask = 0;


	if (qphy->suspended == suspend) {
	if (qphy->suspended == suspend) {
		if (qphy->phy.flags & PHY_SUS_OVERRIDE)
			goto suspend;

		dev_dbg(phy->dev, "%s: USB PHY is already suspended\n",
		dev_dbg(phy->dev, "%s: USB PHY is already suspended\n",
								__func__);
								__func__);
		return 0;
		return 0;
	}
	}


suspend:
	if (suspend) {
	if (suspend) {
		/* Bus suspend case */
		/* Bus suspend case */
		if (qphy->cable_connected) {
		if (qphy->cable_connected) {
@@ -673,12 +677,17 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
			qusb_phy_enable_clocks(qphy, false);
			qusb_phy_enable_clocks(qphy, false);
		} else { /* Cable disconnect case */
		} else { /* Cable disconnect case */
			/* Disable all interrupts */
			/* 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,
				writel_relaxed(0x00,
					qphy->base + qphy->phy_reg[INTR_CTRL]);
					qphy->base + qphy->phy_reg[INTR_CTRL]);
				qusb_phy_reset(qphy);
				qusb_phy_reset(qphy);
				qusb_phy_enable_clocks(qphy, false);
				qusb_phy_enable_clocks(qphy, false);
				qusb_phy_disable_power(qphy);
				qusb_phy_disable_power(qphy);
			}
			}
		}
		qphy->suspended = true;
		qphy->suspended = true;
	} else {
	} else {
		/* Bus resume case */
		/* Bus resume case */
+3 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,9 @@
#define PHY_HSFS_MODE		BIT(8)
#define PHY_HSFS_MODE		BIT(8)
#define PHY_LS_MODE		BIT(9)
#define PHY_LS_MODE		BIT(9)
#define PHY_USB_DP_CONCURRENT_MODE	BIT(10)
#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 {
enum usb_phy_interface {
	USBPHY_INTERFACE_MODE_UNKNOWN,
	USBPHY_INTERFACE_MODE_UNKNOWN,