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

Commit 7e781e79 authored by Mayank Rana's avatar Mayank Rana
Browse files

dwc3-msm: Allow USB LPM with data role swap from dfp to ufp



Current code checks IN_P3 status (i.e. USB is into U3 or not) with
dwc3_prepare_suspend() API using in_host_mode or vbus_active flag.
With data role swap transition (e.g. dfp -> ufp case), in_host_mode
flag sets to false and vbus_active flag sets to true due to quick
calling of stop host and start peripheral mode from policy engine.
This results into USB doesn't go into LPM with stop host mode (i.e.
USB LPM is aborted due to vbus_active flag seen as true) which
results into no USB enumeration in start peripheral mode. Current
code doesn't perform block reset while stopping USB host mode
functionality. Hence to invoke USB core and PHYs related reset and
init functionality allow USB LPM by replacing vbus_active check with
in_device_mode flag which provides status of USB controller's data
role while going into USB LPM. Start peripheral mode brings USB
out of LPM which performs POR functionality.

Change-Id: I2bbb804bce5f910826ba30a3dda4317bbdb2e1f1
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 21a1b0f4
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -229,6 +229,7 @@ struct dwc3_msm {
	struct power_supply	*usb_psy;
	struct work_struct	vbus_draw_work;
	bool			in_host_mode;
	bool			in_device_mode;
	enum usb_device_speed	max_rh_port_speed;
	unsigned int		tx_fifo_size;
	bool			vbus_active;
@@ -2002,7 +2003,7 @@ static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc)
	unsigned long timeout;
	u32 reg = 0;

	if ((mdwc->in_host_mode || mdwc->vbus_active)
	if ((mdwc->in_host_mode || mdwc->in_device_mode)
			&& dwc3_msm_is_superspeed(mdwc) && !mdwc->in_restart) {
		if (!atomic_read(&mdwc->in_p3)) {
			dev_err(mdwc->dev, "Not in P3,aborting LPM sequence\n");
@@ -2265,7 +2266,8 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
	clk_disable_unprepare(mdwc->xo_clk);

	/* Perform controller power collapse */
	if (!mdwc->in_host_mode && (!mdwc->vbus_active || mdwc->in_restart)) {
	if (!mdwc->in_host_mode && (!mdwc->in_device_mode ||
					mdwc->in_restart)) {
		mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE;
		dev_dbg(mdwc->dev, "%s: power collapse\n", __func__);
		dwc3_msm_config_gdsc(mdwc, 0);
@@ -2307,7 +2309,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
	 * using HS_PHY_IRQ or SS_PHY_IRQ. Hence enable wakeup only in
	 * case of host bus suspend and device bus suspend.
	 */
	if (mdwc->vbus_active || mdwc->in_host_mode) {
	if (mdwc->in_device_mode || mdwc->in_host_mode) {
		if (mdwc->use_pdc_interrupts) {
			enable_usb_pdc_interrupt(mdwc, true);
		} else {
@@ -2320,6 +2322,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
	}

	dev_info(mdwc->dev, "DWC3 in low power mode\n");
	dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm));
	mutex_unlock(&mdwc->suspend_resume_mutex);
	return 0;
}
@@ -3898,6 +3901,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
		dwc3_msm_block_reset(mdwc, false);

		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
		mdwc->in_device_mode = true;
		usb_gadget_vbus_connect(&dwc->gadget);
#ifdef CONFIG_SMP
		mdwc->pm_qos_req_dma.type = PM_QOS_REQ_AFFINE_IRQ;
@@ -3916,6 +3920,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
		msm_dwc3_perf_vote_update(mdwc, false);
		pm_qos_remove_request(&mdwc->pm_qos_req_dma);

		mdwc->in_device_mode = false;
		usb_gadget_vbus_disconnect(&dwc->gadget);
		usb_phy_notify_disconnect(mdwc->hs_phy, USB_SPEED_HIGH);
		usb_phy_notify_disconnect(mdwc->ss_phy, USB_SPEED_SUPER);