diff options
author | Pavankumar Kondeti <pkondeti@codeaurora.org> | 2011-05-04 00:49:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-06 21:27:49 -0400 |
commit | 04aebcbb1b6dccadc8862b2765265f65a946db57 (patch) | |
tree | 33996708dc4e3fdfd1d8bc12157f2e22e54520ff /drivers/usb | |
parent | 11aa5c478e743712228ff2da881b85100800c1ee (diff) |
USB: OTG: msm: Add PHY suspend support for MSM8960
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/otg/msm_otg.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 628ba7d943da..1cdda6c05238 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c | |||
@@ -163,6 +163,32 @@ put_3p3: | |||
163 | return rc; | 163 | return rc; |
164 | } | 164 | } |
165 | 165 | ||
166 | #ifdef CONFIG_PM_SLEEP | ||
167 | #define USB_PHY_SUSP_DIG_VOL 500000 | ||
168 | static int msm_hsusb_config_vddcx(int high) | ||
169 | { | ||
170 | int max_vol = USB_PHY_VDD_DIG_VOL_MAX; | ||
171 | int min_vol; | ||
172 | int ret; | ||
173 | |||
174 | if (high) | ||
175 | min_vol = USB_PHY_VDD_DIG_VOL_MIN; | ||
176 | else | ||
177 | min_vol = USB_PHY_SUSP_DIG_VOL; | ||
178 | |||
179 | ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol); | ||
180 | if (ret) { | ||
181 | pr_err("%s: unable to set the voltage for regulator " | ||
182 | "HSUSB_VDDCX\n", __func__); | ||
183 | return ret; | ||
184 | } | ||
185 | |||
186 | pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol); | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | #endif | ||
191 | |||
166 | static int msm_hsusb_ldo_set_mode(int on) | 192 | static int msm_hsusb_ldo_set_mode(int on) |
167 | { | 193 | { |
168 | int ret = 0; | 194 | int ret = 0; |
@@ -434,27 +460,28 @@ static int msm_otg_suspend(struct msm_otg *motg) | |||
434 | 460 | ||
435 | disable_irq(motg->irq); | 461 | disable_irq(motg->irq); |
436 | /* | 462 | /* |
463 | * Chipidea 45-nm PHY suspend sequence: | ||
464 | * | ||
437 | * Interrupt Latch Register auto-clear feature is not present | 465 | * Interrupt Latch Register auto-clear feature is not present |
438 | * in all PHY versions. Latch register is clear on read type. | 466 | * in all PHY versions. Latch register is clear on read type. |
439 | * Clear latch register to avoid spurious wakeup from | 467 | * Clear latch register to avoid spurious wakeup from |
440 | * low power mode (LPM). | 468 | * low power mode (LPM). |
441 | */ | 469 | * |
442 | ulpi_read(otg, 0x14); | ||
443 | |||
444 | /* | ||
445 | * PHY comparators are disabled when PHY enters into low power | 470 | * PHY comparators are disabled when PHY enters into low power |
446 | * mode (LPM). Keep PHY comparators ON in LPM only when we expect | 471 | * mode (LPM). Keep PHY comparators ON in LPM only when we expect |
447 | * VBUS/Id notifications from USB PHY. Otherwise turn off USB | 472 | * VBUS/Id notifications from USB PHY. Otherwise turn off USB |
448 | * PHY comparators. This save significant amount of power. | 473 | * PHY comparators. This save significant amount of power. |
449 | */ | 474 | * |
450 | if (pdata->otg_control == OTG_PHY_CONTROL) | ||
451 | ulpi_write(otg, 0x01, 0x30); | ||
452 | |||
453 | /* | ||
454 | * PLL is not turned off when PHY enters into low power mode (LPM). | 475 | * PLL is not turned off when PHY enters into low power mode (LPM). |
455 | * Disable PLL for maximum power savings. | 476 | * Disable PLL for maximum power savings. |
456 | */ | 477 | */ |
457 | ulpi_write(otg, 0x08, 0x09); | 478 | |
479 | if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) { | ||
480 | ulpi_read(otg, 0x14); | ||
481 | if (pdata->otg_control == OTG_PHY_CONTROL) | ||
482 | ulpi_write(otg, 0x01, 0x30); | ||
483 | ulpi_write(otg, 0x08, 0x09); | ||
484 | } | ||
458 | 485 | ||
459 | /* | 486 | /* |
460 | * PHY may take some time or even fail to enter into low power | 487 | * 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) | |||
485 | */ | 512 | */ |
486 | writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); | 513 | writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); |
487 | 514 | ||
515 | if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && | ||
516 | motg->pdata->otg_control == OTG_PMIC_CONTROL) | ||
517 | writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL); | ||
518 | |||
488 | clk_disable(motg->pclk); | 519 | clk_disable(motg->pclk); |
489 | clk_disable(motg->clk); | 520 | clk_disable(motg->clk); |
490 | if (motg->core_clk) | 521 | if (motg->core_clk) |
@@ -493,6 +524,12 @@ static int msm_otg_suspend(struct msm_otg *motg) | |||
493 | if (!IS_ERR(motg->pclk_src)) | 524 | if (!IS_ERR(motg->pclk_src)) |
494 | clk_disable(motg->pclk_src); | 525 | clk_disable(motg->pclk_src); |
495 | 526 | ||
527 | if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && | ||
528 | motg->pdata->otg_control == OTG_PMIC_CONTROL) { | ||
529 | msm_hsusb_ldo_set_mode(0); | ||
530 | msm_hsusb_config_vddcx(0); | ||
531 | } | ||
532 | |||
496 | if (device_may_wakeup(otg->dev)) | 533 | if (device_may_wakeup(otg->dev)) |
497 | enable_irq_wake(motg->irq); | 534 | enable_irq_wake(motg->irq); |
498 | if (bus) | 535 | if (bus) |
@@ -524,6 +561,13 @@ static int msm_otg_resume(struct msm_otg *motg) | |||
524 | if (motg->core_clk) | 561 | if (motg->core_clk) |
525 | clk_enable(motg->core_clk); | 562 | clk_enable(motg->core_clk); |
526 | 563 | ||
564 | if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && | ||
565 | motg->pdata->otg_control == OTG_PMIC_CONTROL) { | ||
566 | msm_hsusb_ldo_set_mode(1); | ||
567 | msm_hsusb_config_vddcx(1); | ||
568 | writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL); | ||
569 | } | ||
570 | |||
527 | temp = readl(USB_USBCMD); | 571 | temp = readl(USB_USBCMD); |
528 | temp &= ~ASYNC_INTR_CTRL; | 572 | temp &= ~ASYNC_INTR_CTRL; |
529 | temp &= ~ULPI_STP_CTRL; | 573 | temp &= ~ULPI_STP_CTRL; |