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

Commit 588bf4eb authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: phy-msm-usb: Improve the PHY suspend sequence"

parents 29b31d57 50319b7a
Loading
Loading
Loading
Loading
+64 −18
Original line number Original line Diff line number Diff line
@@ -1191,9 +1191,12 @@ static irqreturn_t msm_otg_phy_irq_handler(int irq, void *data)
	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}


#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
#define PHY_SUSPEND_TIMEOUT_USEC (5 * 1000)
#define PHY_DEVICE_BUS_SUSPEND_TIMEOUT_USEC 100
#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)
#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)


#define PHY_SUSPEND_RETRIES_MAX 3

#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM_SLEEP
static int msm_otg_suspend(struct msm_otg *motg)
static int msm_otg_suspend(struct msm_otg *motg)
{
{
@@ -1206,9 +1209,9 @@ static int msm_otg_suspend(struct msm_otg *motg)
	u32 cmd_val;
	u32 cmd_val;
	u32 portsc, config2;
	u32 portsc, config2;
	u32 func_ctrl;
	u32 func_ctrl;
	int phcd_retry_cnt = 0;
	int phcd_retry_cnt = 0, ret;
	unsigned phy_suspend_timeout;


phcd_retry:
	cnt = 0;
	cnt = 0;


	if (atomic_read(&motg->in_lpm))
	if (atomic_read(&motg->in_lpm))
@@ -1226,6 +1229,7 @@ phcd_retry:


	motg->ui_enabled = 0;
	motg->ui_enabled = 0;
	disable_irq(motg->irq);
	disable_irq(motg->irq);
lpm_start:
	host_bus_suspend = !test_bit(MHL, &motg->inputs) && phy->otg->host &&
	host_bus_suspend = !test_bit(MHL, &motg->inputs) && phy->otg->host &&
		!test_bit(ID, &motg->inputs);
		!test_bit(ID, &motg->inputs);
	device_bus_suspend = phy->otg->gadget && test_bit(ID, &motg->inputs) &&
	device_bus_suspend = phy->otg->gadget && test_bit(ID, &motg->inputs) &&
@@ -1277,16 +1281,39 @@ phcd_retry:
						ULPI_CLR(ULPI_IFC_CTRL));
						ULPI_CLR(ULPI_IFC_CTRL));
	}
	}


	/* Set the PHCD bit, only if it is not set by the controller.
	/*
	 * PHY may take some time or even fail to enter into low power
	 * PHY suspend sequence as mentioned in the databook.
	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
	 *
	 * in failure case.
	 * Device bus suspend: The controller may abort PHY suspend if
	 * there is an incoming reset or resume from the host. If PHCD
	 * is not set within 100 usec. Abort the LPM sequence.
	 *
	 * Host bus suspend: If the peripheral is attached, PHY is already
	 * put into suspend along with the peripheral bus suspend. poll for
	 * PHCD upto 5 msec. If the peripheral is not attached i.e entering
	 * LPM with Micro-A cable, set the PHCD and poll for it for 5 msec.
	 *
	 * No cable connected: Set the PHCD to suspend the PHY. Poll for PHCD
	 * upto 5 msec.
	 *
	 * The controller aborts PHY suspend only in device bus suspend case.
	 * In other cases, it is observed that PHCD may not get set within
	 * the timeout. If so, set the PHCD again and poll for it before
	 * reset recovery.
	 */
	 */

phcd_retry:
	if (device_bus_suspend)
		phy_suspend_timeout = PHY_DEVICE_BUS_SUSPEND_TIMEOUT_USEC;
	else
		phy_suspend_timeout = PHY_SUSPEND_TIMEOUT_USEC;

	cnt = 0;
	portsc = readl_relaxed(USB_PORTSC);
	portsc = readl_relaxed(USB_PORTSC);
	if (!(portsc & PORTSC_PHCD)) {
	if (!(portsc & PORTSC_PHCD)) {
		writel_relaxed(portsc | PORTSC_PHCD,
		writel_relaxed(portsc | PORTSC_PHCD,
				USB_PORTSC);
				USB_PORTSC);
		while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
		while (cnt < phy_suspend_timeout) {
			if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
			if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
				break;
				break;
			udelay(1);
			udelay(1);
@@ -1294,16 +1321,29 @@ phcd_retry:
		}
		}
	}
	}


	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
	if (cnt >= phy_suspend_timeout) {
		dev_err(phy->dev, "Unable to suspend PHY\n");
		if (phcd_retry_cnt > PHY_SUSPEND_RETRIES_MAX) {
			dev_err(phy->dev, "PHY suspend failed\n");
			ret = -EBUSY;
			goto phy_suspend_fail;
		}

		if (device_bus_suspend) {
			dev_dbg(phy->dev, "PHY suspend aborted\n");
			ret = -EBUSY;
			goto phy_suspend_fail;
		} else {
			if (phcd_retry_cnt++ < PHY_SUSPEND_RETRIES_MAX) {
				dev_dbg(phy->dev, "PHY suspend retry\n");
				goto phcd_retry;
			} else {
				dev_err(phy->dev, "reset attempt during PHY suspend\n");
				phcd_retry_cnt++;
				motg->reset_counter = 0;
				motg->reset_counter = 0;
				msm_otg_reset(phy);
				msm_otg_reset(phy);
		motg->ui_enabled = 1;
				goto lpm_start;
		enable_irq(motg->irq);
			}
		if (phcd_retry_cnt++ < 3)
		}
			goto phcd_retry;
		else
			return -EBUSY;
	}
	}


	/*
	/*
@@ -1484,6 +1524,11 @@ phcd_retry:
	dev_info(phy->dev, "USB in low power mode\n");
	dev_info(phy->dev, "USB in low power mode\n");


	return 0;
	return 0;

phy_suspend_fail:
	motg->ui_enabled = 1;
	enable_irq(motg->irq);
	return ret;
}
}


static int msm_otg_resume(struct msm_otg *motg)
static int msm_otg_resume(struct msm_otg *motg)
@@ -3258,6 +3303,7 @@ static void msm_otg_sm_work(struct work_struct *w)
			if (motg->caps & ALLOW_LPM_ON_DEV_SUSPEND) {
			if (motg->caps & ALLOW_LPM_ON_DEV_SUSPEND) {
				pm_runtime_put_noidle(otg->phy->dev);
				pm_runtime_put_noidle(otg->phy->dev);
				pm_runtime_suspend(otg->phy->dev);
				pm_runtime_suspend(otg->phy->dev);
				motg->pm_done = 1;
			}
			}
		} else if (test_bit(ID_C, &motg->inputs)) {
		} else if (test_bit(ID_C, &motg->inputs)) {
			msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
			msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);