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

Commit 04aebcbb authored by Pavankumar Kondeti's avatar Pavankumar Kondeti Committed by Greg Kroah-Hartman
Browse files

USB: OTG: msm: Add PHY suspend support for MSM8960

parent 11aa5c47
Loading
Loading
Loading
Loading
+54 −10
Original line number Diff line number Diff line
@@ -163,6 +163,32 @@ static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
	return rc;
}

#ifdef CONFIG_PM_SLEEP
#define USB_PHY_SUSP_DIG_VOL  500000
static int msm_hsusb_config_vddcx(int high)
{
	int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
	int min_vol;
	int ret;

	if (high)
		min_vol = USB_PHY_VDD_DIG_VOL_MIN;
	else
		min_vol = USB_PHY_SUSP_DIG_VOL;

	ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
	if (ret) {
		pr_err("%s: unable to set the voltage for regulator "
			"HSUSB_VDDCX\n", __func__);
		return ret;
	}

	pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);

	return ret;
}
#endif

static int msm_hsusb_ldo_set_mode(int on)
{
	int ret = 0;
@@ -434,27 +460,28 @@ static int msm_otg_suspend(struct msm_otg *motg)

	disable_irq(motg->irq);
	/*
	 * Chipidea 45-nm PHY suspend sequence:
	 *
	 * Interrupt Latch Register auto-clear feature is not present
	 * in all PHY versions. Latch register is clear on read type.
	 * Clear latch register to avoid spurious wakeup from
	 * low power mode (LPM).
	 */
	ulpi_read(otg, 0x14);

	/*
	 *
	 * PHY comparators are disabled when PHY enters into low power
	 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
	 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
	 * PHY comparators. This save significant amount of power.
	 */
	if (pdata->otg_control == OTG_PHY_CONTROL)
		ulpi_write(otg, 0x01, 0x30);

	/*
	 *
	 * PLL is not turned off when PHY enters into low power mode (LPM).
	 * Disable PLL for maximum power savings.
	 */

	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
		ulpi_read(otg, 0x14);
		if (pdata->otg_control == OTG_PHY_CONTROL)
			ulpi_write(otg, 0x01, 0x30);
		ulpi_write(otg, 0x08, 0x09);
	}

	/*
	 * PHY may take some time or even fail to enter into low power
@@ -485,6 +512,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
	 */
	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);

	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
			motg->pdata->otg_control == OTG_PMIC_CONTROL)
		writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);

	clk_disable(motg->pclk);
	clk_disable(motg->clk);
	if (motg->core_clk)
@@ -493,6 +524,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
	if (!IS_ERR(motg->pclk_src))
		clk_disable(motg->pclk_src);

	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
		msm_hsusb_ldo_set_mode(0);
		msm_hsusb_config_vddcx(0);
	}

	if (device_may_wakeup(otg->dev))
		enable_irq_wake(motg->irq);
	if (bus)
@@ -524,6 +561,13 @@ static int msm_otg_resume(struct msm_otg *motg)
	if (motg->core_clk)
		clk_enable(motg->core_clk);

	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
		msm_hsusb_ldo_set_mode(1);
		msm_hsusb_config_vddcx(1);
		writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
	}

	temp = readl(USB_USBCMD);
	temp &= ~ASYNC_INTR_CTRL;
	temp &= ~ULPI_STP_CTRL;
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#define USB_PORTSC           (MSM_USB_BASE + 0x0184)
#define USB_OTGSC            (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE          (MSM_USB_BASE + 0x01A8)
#define USB_PHY_CTRL         (MSM_USB_BASE + 0x0240)

#define USBCMD_RESET   2
#define USB_USBINTR          (MSM_USB_BASE + 0x0148)
@@ -42,6 +43,7 @@

#define ASYNC_INTR_CTRL         (1 << 29) /* Enable async interrupt */
#define ULPI_STP_CTRL           (1 << 30) /* Block communication with PHY */
#define PHY_RETEN               (1 << 1) /* PHY retention enable/disable */

/* OTG definitions */
#define OTGSC_INTSTS_MASK	(0x7f << 16)