arm: tegra: usb_phy: fix hsic suspend issue on xmm
Vinayak Pane [Tue, 12 Jun 2012 01:08:14 +0000 (18:08 -0700)]
XMM modem fails at auto-suspend on hsic. Fixing this issue
by enabling PMC sleepwalk code conditionally and only at
phy-on and phy-off routines.

Bug 991709

Signed-off-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/109324
(cherry picked from commit 100f818a16ce97411a98ddb0e2c5c9e73a9e654a)

Change-Id: If6f92b8b36f856fa633cb411ac20dbe6e862890c
Reviewed-on: http://git-master/r/115612
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

arch/arm/mach-tegra/tegra3_usb_phy.c
arch/arm/mach-tegra/tegra_usb_phy.h

index afd61f4..6f8119f 100644 (file)
@@ -2009,6 +2009,7 @@ static void uhsic_phy_restore_start(struct tegra_usb_phy *phy)
        /* check whether we wake up from the remote resume */
        if (UHSIC_WALK_PTR_VAL & val) {
                phy->remote_wakeup = true;
+               pr_info("%s: uhsic remote wakeup detected\n", __func__);
        } else {
                if (!((UHSIC_STROBE_VAL_P0 | UHSIC_DATA_VAL_P0) & val)) {
                                uhsic_phy_disable_pmc_bus_ctrl(phy);
@@ -2210,6 +2211,15 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy)
        phy->phy_clk_on = true;
        phy->hw_accessible = true;
 
+       if (phy->pmc_sleepwalk) {
+               DBG("%s(%d) inst:[%d] restore phy\n", __func__, __LINE__,
+                                       phy->inst);
+               uhsic_phy_restore_start(phy);
+               usb_phy_bringup_host_controller(phy);
+               uhsic_phy_restore_end(phy);
+               phy->pmc_sleepwalk = false;
+       }
+
        return 0;
 }
 
@@ -2231,7 +2241,10 @@ static int uhsic_phy_power_off(struct tegra_usb_phy *phy)
        /* Disable interrupts */
        writel(0, base + USB_USBINTR);
 
-       uhsic_setup_pmc_wake_detect(phy);
+       if (phy->pmc_sleepwalk == false) {
+               uhsic_setup_pmc_wake_detect(phy);
+               phy->pmc_sleepwalk = true;
+       }
 
        val = readl(base + HOSTPC1_DEVLC);
        val |= HOSTPC1_DEVLC_PHCD;
@@ -2380,10 +2393,6 @@ int uhsic_phy_resume(struct tegra_usb_phy *phy)
 {
        DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
 
-       uhsic_phy_restore_start(phy);
-       usb_phy_bringup_host_controller(phy);
-       uhsic_phy_restore_end(phy);
-
        return 0;
 }
 
index fe190aa..ddc4bb4 100644 (file)
@@ -95,6 +95,7 @@ struct tegra_usb_phy {
        bool remote_wakeup;
        bool hw_accessible;
        bool ulpi_clk_padout_ena;
+       bool pmc_sleepwalk;
 };
 
 int usb_phy_reg_status_wait(void __iomem *reg, u32 mask,