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

Commit 9ab0e566 authored by ChandanaKishori Chiluveru's avatar ChandanaKishori Chiluveru Committed by Manu Gautam
Browse files

USB: phy-msm-usb: Don't exit from low power mode during PM resume



With micro-A cable connected in host mode and upon system resume, USB is
exited from low power mode even if the wakeup source is not USB and enters
into low power mode again because there is nothing pending on USB side
to be done. This is unnecessary activity as there is nothing to be done at
USB side in pm resume. Whenever the wakeup is because of USB activity e.g.
micro-A cable connect or disconnect then this activity is handled by first
resuming the USB in the OTG driver.

Do not bring USB out of low power mode, we don't need to perform root hub
or port resume in ehci pm resume. Make this function nop and let the
OTG driver handle this where DP and DM line change can be taken care by
the aync_irq and phy_irq bring USB out of low power mode in case of host
cable disconnect and connect.

Enable both async and core irq when USB is entering into low power mode
and set both the irqs wakeup capable. Async irq is now mapped to DP and
core irq is mapped to DM lines. Hence when it is host bus suspend case,
DP or DM line transition can wakeup the target if target is in deep sleep
state.

Change-Id: If8e0584c12d4cb7273992a56c19778fe814b3404
Signed-off-by: default avatarChandanaKishori Chiluveru <cchilu@codeaurora.org>
parent f240f4c9
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ Required properties :
- interrupts: IRQ line
- interrupt-names: OTG interrupt name(s) referenced in interrupts above
            HSUSB OTG expects "core_irq" which is IRQ line from CORE and
            "async_irq" from HSPHY for asynchronous wakeup events in LPM.
            optional ones are described in next section.
- qcom,hsusb-otg-phy-type: PHY type can be one of
	    1 - Chipidea PHY (obsolete)
@@ -68,7 +69,6 @@ Required properties :

Optional properties :
- interrupt-names : Optional interrupt resource entries are:
    "async_irq" : Interrupt from HSPHY for asynchronous wakeup events in LPM.
    "pmic_id_irq" : Interrupt from PMIC for external ID pin notification.
    "phy_irq" : Interrupt from PHY. Used for ID detection.
- qcom,hsusb-otg-disable-reset: If present then core is RESET only during
+1 −20
Original line number Diff line number Diff line
@@ -233,28 +233,9 @@ static int ehci_msm_pm_suspend(struct device *dev)

static int ehci_msm_pm_resume(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	int ret;
	u32 portsc;

	dev_dbg(dev, "ehci-msm PM resume\n");
	if (!hcd->rh_registered)
		return 0;

	/* Notify OTG to bring hw out of LPM before restoring wakeup flags */
	ret = usb_phy_set_suspend(hcd->usb_phy, 0);
	if (ret)
		return ret;

	ehci_resume(hcd, false);
	portsc = readl_relaxed(USB_PORTSC);
	portsc &= ~PORT_RWC_BITS;
	portsc |= PORT_RESUME;
	writel_relaxed(portsc, USB_PORTSC);
	/* Resume root-hub to handle USB event if any else initiate LPM again */
	usb_hcd_resume_root_hub(hcd);

	return ret;
	return 0;
}
#endif

+23 −38
Original line number Diff line number Diff line
@@ -1169,7 +1169,6 @@ static int msm_otg_suspend(struct msm_otg *motg)
	if (atomic_read(&motg->in_lpm))
		return 0;

	motg->ui_enabled = 0;
	disable_irq(motg->irq);
	if (motg->phy_irq)
		disable_irq(motg->phy_irq);
@@ -1210,7 +1209,6 @@ lpm_start:
			sm_work_busy) {
		msm_otg_dbg_log_event(phy, "LPM ENTER ABORTED",
				motg->inputs, motg->chg_type);
		motg->ui_enabled = 1;
		enable_irq(motg->irq);
		if (motg->phy_irq)
			enable_irq(motg->phy_irq);
@@ -1428,9 +1426,7 @@ phcd_retry:
	}

	if (device_may_wakeup(phy->dev)) {
		if (motg->async_irq)
		enable_irq_wake(motg->async_irq);
		else
		enable_irq_wake(motg->irq);

		if (motg->phy_irq)
@@ -1457,17 +1453,12 @@ phcd_retry:
	atomic_set(&motg->in_lpm, 1);
	wake_up(&motg->host_suspend_wait);

	/* Enable ASYNC IRQ (if present) during LPM */
	if (motg->async_irq)
	/* Enable ASYNC IRQ during LPM */
	enable_irq(motg->async_irq);
	if (motg->phy_irq)
		enable_irq(motg->phy_irq);

	/* XO shutdown during idle , non wakeable irqs must be disabled */
	if (device_bus_suspend || host_bus_suspend || !motg->async_irq) {
		motg->ui_enabled = 1;
	enable_irq(motg->irq);
	}
	wake_unlock(&motg->wlock);

	dev_dbg(phy->dev, "LPM caps = %lu flags = %lu\n",
@@ -1479,7 +1470,6 @@ phcd_retry:
	return 0;

phy_suspend_fail:
	motg->ui_enabled = 1;
	enable_irq(motg->irq);
	if (motg->phy_irq)
		enable_irq(motg->phy_irq);
@@ -1507,10 +1497,7 @@ static int msm_otg_resume(struct msm_otg *motg)
		return 0;
	}

	if (motg->ui_enabled) {
		motg->ui_enabled = 0;
	disable_irq(motg->irq);
	}
	wake_lock(&motg->wlock);

	/*
@@ -1631,9 +1618,7 @@ skip_phy_resume:
	}

	if (device_may_wakeup(phy->dev)) {
		if (motg->async_irq)
		disable_irq_wake(motg->async_irq);
		else
		disable_irq_wake(motg->irq);

		if (motg->phy_irq)
@@ -1662,11 +1647,9 @@ skip_phy_resume:
		enable_irq(motg->async_int);
		motg->async_int = 0;
	}
	motg->ui_enabled = 1;
	enable_irq(motg->irq);

	/* If ASYNC IRQ is present then keep it enabled only during LPM */
	if (motg->async_irq)
	/* Enable ASYNC_IRQ only during LPM */
	disable_irq(motg->async_irq);

	if (motg->phy_irq_pending) {
@@ -2868,6 +2851,10 @@ static irqreturn_t msm_otg_irq(int irq, void *data)
		pr_debug("OTG IRQ: %d in LPM\n", irq);
		msm_otg_dbg_log_event(&motg->phy, "OTG IRQ IS IN LPM",
				irq, otg->phy->state);
		/*Ignore interrupt if one interrupt already seen in LPM*/
		if (motg->async_int)
			return IRQ_HANDLED;

		disable_irq_nosync(irq);
		motg->async_int = irq;
		if (!atomic_read(&motg->pm_suspended)) {
@@ -4424,8 +4411,9 @@ static int msm_otg_probe(struct platform_device *pdev)

	motg->async_irq = platform_get_irq_byname(pdev, "async_irq");
	if (motg->async_irq < 0) {
		dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n");
		dev_err(&pdev->dev, "platform_get_irq for async_int failed\n");
		motg->async_irq = 0;
		goto free_regs;
	}

	if (motg->xo_clk) {
@@ -4563,7 +4551,6 @@ static int msm_otg_probe(struct platform_device *pdev)
		}
	}

	if (motg->async_irq) {
	ret = request_irq(motg->async_irq, msm_otg_irq,
				IRQF_TRIGGER_RISING, "msm_otg", motg);
	if (ret) {
@@ -4571,7 +4558,6 @@ static int msm_otg_probe(struct platform_device *pdev)
		goto free_phy_irq;
	}
	disable_irq(motg->async_irq);
	}

	if (pdata->otg_control == OTG_PHY_CONTROL && pdata->mpm_otgsessvld_int)
		msm_mpm_enable_pin(pdata->mpm_otgsessvld_int, 1);
@@ -4769,7 +4755,6 @@ remove_cdev:
remove_phy:
	usb_remove_phy(&motg->phy);
free_async_irq:
	if (motg->async_irq)
	free_irq(motg->async_irq, motg);
free_phy_irq:
	if (motg->phy_irq)
+0 −2
Original line number Diff line number Diff line
@@ -370,7 +370,6 @@ struct msm_otg_platform_data {
 * @bus_clks_enabled: indicates pcnoc/snoc/bimc clocks are on or not.
 * @chg_check_timer: The timer used to implement the workaround to detect
 *               very slow plug in of wall charger.
 * @ui_enabled: USB Intterupt is enabled or disabled.
 * @is_ext_chg_dcp: To indicate whether charger detected by external entity
		SMB hardware is DCP charger or not.
 * @pm_done: It is used to increment the pm counter using pm_runtime_get_sync.
@@ -513,7 +512,6 @@ struct msm_otg {
	enum usb_ext_chg_status ext_chg_active;
	struct completion ext_chg_wait;
	struct pinctrl *phy_pinctrl;
	int ui_enabled;
	bool is_ext_chg_dcp;
	bool pm_done;
	struct qpnp_vadc_chip	*vadc_dev;