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

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

Merge "usb: ci13xxx_msm_hsic: Fix HSIC Connect sequence"

parents 2833c110 4316bfd9
Loading
Loading
Loading
Loading
+48 −46
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ static int msm_hsic_phy_clk_reset(struct msm_hsic_per *mhsic)
{
	int ret;

	clk_enable(mhsic->alt_core_clk);
	ret = clk_reset(mhsic->core_clk, CLK_RESET_ASSERT);
	if (ret) {
		clk_disable(mhsic->alt_core_clk);
@@ -390,10 +391,12 @@ static int msm_hsic_suspend(struct msm_hsic_per *mhsic)
	}
	disable_irq(mhsic->irq);

	/* Don't try to put PHY into suspend if it is not in CONNECT state. */
	if (the_mhsic->connected) {
		/*
		 * PHY may take some time or even fail to enter into low power
	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
	 * in failure case.
		 * mode (LPM). Hence poll for 500 msec and reset the PHY and
		 * link in failure case.
		 */
		val = readl_relaxed(USB_PORTSC) | PORTSC_PHCD;
		writel_relaxed(val, USB_PORTSC);
@@ -411,11 +414,11 @@ static int msm_hsic_suspend(struct msm_hsic_per *mhsic)
		}

		/*
	 * PHY has capability to generate interrupt asynchronously in low
	 * power mode (LPM). This interrupt is level triggered. So USB IRQ
	 * line must be disabled till async interrupt enable bit is cleared
	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
	 * block data communication from PHY.
		 * PHY has capability to generate interrupt asynchronously in
		 * low power mode (LPM). This interrupt is level triggered. So
		 * USB IRQ line must be disabled till async interrupt enable bit
		 * is cleared in USBCMD register. Assert STP (ULPI interface
		 * STOP signal) to block data communication from PHY.
		 */
		writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
					ULPI_STP_CTRL, USB_USBCMD);
@@ -425,8 +428,11 @@ static int msm_hsic_suspend(struct msm_hsic_per *mhsic)
		 * clocks are turned OFF and VDD is allowed to minimize.
		 */
		mb();
	} else {
		dev_dbg(mhsic->dev, "%s SKIP PHY suspend\n", __func__);
	}

	if (!mhsic->pdata->core_clk_always_on_workaround || !mhsic->connected) {
	if (!mhsic->connected) {
		clk_disable_unprepare(mhsic->iface_clk);
		clk_disable_unprepare(mhsic->core_clk);
	}
@@ -469,7 +475,7 @@ static int msm_hsic_resume(struct msm_hsic_per *mhsic)
		dev_err(mhsic->dev,
			"unable to set nominal vddcx voltage (no VDD MIN)\n");

	if (!mhsic->pdata->core_clk_always_on_workaround || !mhsic->connected) {
	if (!mhsic->connected) {
		clk_prepare_enable(mhsic->iface_clk);
		clk_prepare_enable(mhsic->core_clk);
	}
@@ -643,7 +649,9 @@ static void ci13xxx_msm_hsic_notify_event(struct ci13xxx *udc, unsigned event)
		break;
	case CI13XXX_CONTROLLER_CONNECT_EVENT:
		dev_info(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
		msm_hsic_wakeup();
		/* bring HSIC core out of LPM */
		pm_runtime_get_sync(the_mhsic->dev);
		msm_hsic_start();
		the_mhsic->connected = true;
		break;
	case CI13XXX_CONTROLLER_SUSPEND_EVENT:
@@ -651,21 +659,15 @@ static void ci13xxx_msm_hsic_notify_event(struct ci13xxx *udc, unsigned event)
		queue_work(mhsic->wq, &mhsic->suspend_w);
		break;
	case CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT:
		dev_info(dev, "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
		dev_info(dev,
			 "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
		msm_hsic_wakeup();
		break;
	case CI13XXX_CONTROLLER_UDC_STARTED_EVENT:
		dev_info(dev, "CI13XXX_CONTROLLER_UDC_STARTED_EVENT received\n");
		/*
		 * UDC started, suspend the hsic device until it will be
		 * connected by a pullup (CI13XXX_CONTROLLER_CONNECT_EVENT)
		 * Before suspend, finish required configurations.
		 */
		hw_device_state(udc->ep0out.qh.dma);
		msm_hsic_start();
		usleep(10000);

		dev_info(dev,
			 "CI13XXX_CONTROLLER_UDC_STARTED_EVENT received\n");
		mhsic->connected = false;
		/* put HSIC core into LPM */
		pm_runtime_put_noidle(the_mhsic->dev);
		pm_runtime_suspend(the_mhsic->dev);
		break;