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 | |
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>
-rw-r--r-- | drivers/usb/otg/msm_otg.c | 64 | ||||
-rw-r--r-- | include/linux/usb/msm_hsusb_hw.h | 2 |
2 files changed, 56 insertions, 10 deletions
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 628ba7d943d..1cdda6c0523 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; |
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h index 7d1babbff07..6e97a2d3d39 100644 --- a/include/linux/usb/msm_hsusb_hw.h +++ b/include/linux/usb/msm_hsusb_hw.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #define USB_PORTSC (MSM_USB_BASE + 0x0184) | 24 | #define USB_PORTSC (MSM_USB_BASE + 0x0184) |
25 | #define USB_OTGSC (MSM_USB_BASE + 0x01A4) | 25 | #define USB_OTGSC (MSM_USB_BASE + 0x01A4) |
26 | #define USB_USBMODE (MSM_USB_BASE + 0x01A8) | 26 | #define USB_USBMODE (MSM_USB_BASE + 0x01A8) |
27 | #define USB_PHY_CTRL (MSM_USB_BASE + 0x0240) | ||
27 | 28 | ||
28 | #define USBCMD_RESET 2 | 29 | #define USBCMD_RESET 2 |
29 | #define USB_USBINTR (MSM_USB_BASE + 0x0148) | 30 | #define USB_USBINTR (MSM_USB_BASE + 0x0148) |
@@ -42,6 +43,7 @@ | |||
42 | 43 | ||
43 | #define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */ | 44 | #define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */ |
44 | #define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */ | 45 | #define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */ |
46 | #define PHY_RETEN (1 << 1) /* PHY retention enable/disable */ | ||
45 | 47 | ||
46 | /* OTG definitions */ | 48 | /* OTG definitions */ |
47 | #define OTGSC_INTSTS_MASK (0x7f << 16) | 49 | #define OTGSC_INTSTS_MASK (0x7f << 16) |