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

Commit 4316bfd9 authored by Lena Salman's avatar Lena Salman
Browse files

usb: ci13xxx_msm_hsic: Fix HSIC Connect sequence



With changes how gadget framework works and binding of composite
framework with UDC driver, it is required to handle different
events (STARTED and CONNECT) and perform correct operation to
handle below cases :
1. On boot up, HSIC Core needs to be in LPM.
2. On enabling HSIC composition, bring HSIC core out of LPM and do
connect signaling with HSIC host.

This change also ignores core_clk_always_on_workaround usage.

Change-Id: Ia3baa9295a741b044eab988ff6063fd8732499c3
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
Signed-off-by: default avatarLena Salman <esalman@codeaurora.org>
Signed-off-by: default avatarDov Levenglick <dovl@codeaurora.org>
parent 865bf777
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;