ARM: tegra: usb_phy: Fix IDDQ_OVERRIDE programming
Rakesh Bodla [Thu, 14 Mar 2013 11:31:40 +0000 (16:31 +0530)]
Put UTMIPLL to IDDQ if all UTMIP USB2 controllers
are in reset or suspend states. Also, bring UTMIPLL
out of to IDDQ while controllers exiting reset or
suspend states.

Bug 1201974

Change-Id: I1696905601962e372b361a6473ec12a86b816124
Signed-off-by: Rakesh Bodla <rbodla@nvidia.com>
Reviewed-on: http://git-master/r/192639
Reviewed-by: Riham Haidar <rhaidar@nvidia.com>
Tested-by: Riham Haidar <rhaidar@nvidia.com>

arch/arm/mach-tegra/tegra11x_usb_phy.c
arch/arm/mach-tegra/tegra_usb_pad_ctrl.c

index 5918843..c15605f 100644 (file)
@@ -990,8 +990,6 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
                }
        }
 
-       utmi_phy_pad_disable();
-
        /* Disable PHY clock */
        val = readl(base + HOSTPC1_DEVLC);
        val |= HOSTPC1_DEVLC_PHCD;
@@ -1003,6 +1001,8 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
                writel(val, base + USB_SUSP_CTRL);
        }
 
+       utmi_phy_pad_disable();
+
        phy->phy_clk_on = false;
        phy->hw_accessible = false;
 
@@ -1016,6 +1016,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
 {
        unsigned long val;
        void __iomem *base = phy->regs;
+       void __iomem *clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
        void __iomem *padctl_base = IO_ADDRESS(TEGRA_XUSB_PADCTL_BASE);
 #endif
@@ -1117,14 +1118,21 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
        val &= ~UTMIP_RESET;
        writel(val, base + USB_SUSP_CTRL);
 
-       val = readl(base + HOSTPC1_DEVLC);
-       val &= ~HOSTPC1_DEVLC_PHCD;
-       writel(val, base + HOSTPC1_DEVLC);
+       /* Bring UTMIPLL out of IDDQ mode while exiting from reset/suspend */
+       val = readl(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       if (val & UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE) {
+               val &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+               writel(val, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       }
 
        if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL,
                USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500))
                pr_warn("%s: timeout waiting for phy to stabilize\n", __func__);
 
+       val = readl(base + HOSTPC1_DEVLC);
+       val &= ~HOSTPC1_DEVLC_PHCD;
+       writel(val, base + HOSTPC1_DEVLC);
+
        utmi_phy_enable_trking_data(phy);
 
        if (phy->inst == 2)
index 91081c5..bd77800 100644 (file)
@@ -26,15 +26,10 @@ int utmi_phy_pad_enable(void)
 {
        unsigned long val, flags;
        void __iomem *pad_base =  IO_ADDRESS(TEGRA_USB_BASE);
-       void __iomem *clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
 
        if (!utmi_pad_clk)
                utmi_pad_clk = clk_get_sys("utmip-pad", NULL);
 
-       val = readl(clk_base + UTMIPLL_HW_PWRDN_CFG0);
-       val &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
-       writel(val, clk_base + UTMIPLL_HW_PWRDN_CFG0);
-
        clk_enable(utmi_pad_clk);
 
        spin_lock_irqsave(&utmip_pad_lock, flags);
@@ -77,6 +72,8 @@ int utmi_phy_pad_disable(void)
                        UTMIP_HSDISCON_LEVEL_MSB);
                writel(val, pad_base + UTMIP_BIAS_CFG0);
 
+               /* Put UTMIPLL in IDDQ mode once all UTMIP ports
+                  are in reset/suspend */
                val = readl(clk_base + UTMIPLL_HW_PWRDN_CFG0);
                val |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
                writel(val, clk_base + UTMIPLL_HW_PWRDN_CFG0);