Loading drivers/usb/otg/msm_otg.c +54 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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) Loading @@ -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) Loading Loading @@ -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; Loading include/linux/usb/msm_hsusb_hw.h +2 −0 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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) Loading Loading
drivers/usb/otg/msm_otg.c +54 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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) Loading @@ -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) Loading Loading @@ -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; Loading
include/linux/usb/msm_hsusb_hw.h +2 −0 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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) Loading