arm: tegra: phy: enable wakeup event for usb phy
Rakesh Bodla [Tue, 4 Sep 2012 06:13:44 +0000 (11:13 +0530)]
If usb device already connected, should disable WKCN
in USB2D_PORTSC1, and enable WKDS in USB2D_PORTSC1,
during utmi phy power off. All the wakeup resource
should be cleared after the event happened.

Bug 1020021
Bug 1028429

Change-Id: I807ca76d4392318adf6adb808cb2bf290cd0d60c
Signed-off-by: Rakesh Bodla <rbodla@nvidia.com>
Reviewed-on: http://git-master/r/128547
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>

arch/arm/mach-tegra/tegra2_usb_phy.c
arch/arm/mach-tegra/tegra3_usb_phy.c

index 892e3ba..0292ebb 100644 (file)
@@ -613,13 +613,19 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy)
                        val &= ~USB_PHY_CLK_VALID_INT_ENB |
                                        USB_PHY_CLK_VALID_INT_STS;
                        writel(val , (base + USB_SUSP_CTRL));
-                       pr_info("%s: usb device plugged-in\n", __func__);
+
                        val = readl(base + USB_USBSTS);
                        if (!(val  & USB_USBSTS_PCI))
                                return IRQ_NONE;
+
                        val = readl(base + USB_PORTSC);
-                       val &= ~(USB_PORTSC_WKCN | USB_PORTSC_RWC_BITS);
+                       if (val & USB_PORTSC_CCS)
+                               val &= ~USB_PORTSC_WKCN;
+                       else
+                               val &= ~USB_PORTSC_WKDS;
+                       val &= ~USB_PORTSC_RWC_BITS;
                        writel(val , (base + USB_PORTSC));
+
                } else if (!phy->phy_clk_on) {
                        return IRQ_NONE;
                }
@@ -710,8 +716,12 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
                        enable_hotplug = (val & USB_ID_STATUS) ? false : true;
                }
                if (enable_hotplug) {
+                       /* Enable wakeup event of device plug-in/plug-out */
                        val = readl(base + USB_PORTSC);
-                       val |= USB_PORTSC_WKCN;
+                       if (val & USB_PORTSC_CCS)
+                               val |= USB_PORTSC_WKDS;
+                       else
+                               val |= USB_PORTSC_WKCN;
                        writel(val, base + USB_PORTSC);
 
                        val = readl(base + USB_SUSP_CTRL);
@@ -726,6 +736,7 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
                }
        }
 
+       /* Disable PHY clock */
        if (phy->inst == 2) {
                val = readl(base + USB_PORTSC);
                val |= USB_PORTSC_PHCD;
index 1020e5d..66637f2 100644 (file)
@@ -1246,15 +1246,26 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy)
                        val &= ~USB_PHY_CLK_VALID_INT_ENB |
                                        USB_PHY_CLK_VALID_INT_STS;
                        writel(val , (base + USB_SUSP_CTRL));
-                       pr_info("%s: usb device plugged-in\n", __func__);
-                       val = readl(base + USB_USBSTS);
-                       if (!(val  & USB_USBSTS_PCI)) {
-                               irq_status = IRQ_NONE;
-                               goto exit;
+
+                       /* In case of remote wakeup PHY clock will not up
+                          immediately, so should not access any controller
+                          register but normal plug-in/plug-out should be
+                          executed */
+                       if (!remote_wakeup) {
+                               val = readl(base + USB_USBSTS);
+                               if (!(val  & USB_USBSTS_PCI)) {
+                                       irq_status = IRQ_NONE;
+                                       goto exit;
+                               }
+
+                               val = readl(base + USB_PORTSC);
+                               if (val & USB_PORTSC_CCS)
+                                       val &= ~USB_PORTSC_WKCN;
+                               else
+                                       val &= ~USB_PORTSC_WKDS;
+                               val &= ~USB_PORTSC_RWC_BITS;
+                               writel(val , (base + USB_PORTSC));
                        }
-                       val = readl(base + USB_PORTSC);
-                       val &= ~(USB_PORTSC_WKCN | USB_PORTSC_RWC_BITS);
-                       writel(val , (base + USB_PORTSC));
                } else if (!phy->phy_clk_on) {
                        if (remote_wakeup)
                                irq_status = IRQ_HANDLED;
@@ -1476,8 +1487,12 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
                        enable_hotplug = (val & USB_ID_STATUS) ? false : true;
                }
                if (enable_hotplug) {
+                       /* Enable wakeup event of device plug-in/plug-out */
                        val = readl(base + USB_PORTSC);
-                       val |= USB_PORTSC_WKCN;
+                       if (val & USB_PORTSC_CCS)
+                               val |= USB_PORTSC_WKDS;
+                       else
+                               val |= USB_PORTSC_WKCN;
                        writel(val, base + USB_PORTSC);
 
                        val = readl(base + USB_SUSP_CTRL);
@@ -1491,6 +1506,7 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
                }
        }
 
+       /* Disable PHY clock */
        val = readl(base + HOSTPC1_DEVLC);
        val |= HOSTPC1_DEVLC_PHCD;
        writel(val, base + HOSTPC1_DEVLC);
@@ -1679,7 +1695,9 @@ static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
                        val = readl(base + USB_PORTSC);
                        udelay(1);
                        if (wait_time_us == 0) {
-                               PHY_DBG("%s PMC REMOTE WAKEUP FPR timeout val = 0x%x instance = %d\n", __func__, val, phy->inst);
+                               PHY_DBG("%s PMC REMOTE WAKEUP FPR timeout"
+                                       "val = 0x%lx instance = %d\n",
+                                       __func__, val, phy->inst);
                                utmip_phy_disable_pmc_bus_ctrl(phy);
                                utmi_phy_post_resume(phy);
                                return;