summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Lin <stlin@nvidia.com>2011-09-21 13:11:40 -0700
committerVarun Colbert <vcolbert@nvidia.com>2011-09-29 18:18:35 -0700
commita07bbdb6bd88bd0362607a43f31316383b0dbe3c (patch)
treea2ec4cbe551c48a5e02d98837077544a73866ef5
parentb8cd0a4bc63f8e8f3f44dfb82fc16f5eca858616 (diff)
arm: tegra: usb: fix null ULPI init for LP0tegra-14.ER1-android-3.2tegra-14.ER1-android-2.3
Changing null ULPI init sequence to avoid phy register program issue when exiting LP0. Bug 863224 Bug 860900 Bug 800318 Reviewed-on: http://git-master/r/53256 (cherry picked from commit 0beea798107fbe276568c3d67a3857f359ff5f53) Change-Id: I2a7bdac4e3f517c56c1505312db83b6535e77c58 Reviewed-on: http://git-master/r/55036 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/include/mach/usb_phy.h2
-rw-r--r--arch/arm/mach-tegra/usb_phy.c97
2 files changed, 58 insertions, 41 deletions
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
index d08e243238f5..0b794bb51964 100644
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -125,6 +125,8 @@ void tegra_usb_phy_preresume(struct tegra_usb_phy *phy, bool is_dpd);
void tegra_usb_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd);
+void tegra_ehci_pre_reset(struct tegra_usb_phy *phy, bool is_dpd);
+
void tegra_ehci_post_reset(struct tegra_usb_phy *phy, bool is_dpd);
void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index b3bcab65d4b3..b5d1a2afa79e 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -1846,11 +1846,18 @@ static int null_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
ulpi_phy_reset(base);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ /* remove ULPI PADS CLKEN reset */
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~ULPI_PADS_CLKEN_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(10);
+#endif
val = readl(base + ULPI_TIMING_CTRL_0);
val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
writel(val, base + ULPI_TIMING_CTRL_0);
- ulpi_set_host(base);
+ ulpi_set_tristate(false);
if (config->pre_phy_on && config->pre_phy_on())
return -EAGAIN;
@@ -1863,7 +1870,7 @@ static int null_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
/* set timming parameters */
val = readl(base + ULPI_TIMING_CTRL_0);
val |= ULPI_SHADOW_CLK_LOOPBACK_EN;
- val |= ULPI_SHADOW_CLK_SEL;
+ val &= ~ULPI_SHADOW_CLK_SEL;
val &= ~ULPI_LBK_PAD_EN;
val |= ULPI_SHADOW_CLK_DELAY(config->trimmer->shadow_clk_delay);
val |= ULPI_CLOCK_OUT_DELAY(config->trimmer->clock_out_delay);
@@ -1874,7 +1881,11 @@ static int null_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
udelay(10);
/* start internal 60MHz clock */
- val = ULPIS2S_PLLU_MASTER_BLASTER60;
+ val = readl(base + ULPIS2S_CTRL);
+ val |= ULPIS2S_ENA;
+ val |= ULPIS2S_SUPPORT_DISCONNECT;
+ val |= ULPIS2S_SPARE((phy->mode == TEGRA_USB_PHY_MODE_HOST) ? 3 : 1);
+ val |= ULPIS2S_PLLU_MASTER_BLASTER60;
writel(val, base + ULPIS2S_CTRL);
/* select ULPI_CORE_CLK_SEL to SHADOW_CLK */
@@ -1883,57 +1894,43 @@ static int null_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
writel(val, base + ULPI_TIMING_CTRL_0);
udelay(10);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* remove slave0 reset */
- val = readl(base + USB_SUSP_CTRL);
- val &= ~ULPIS2S_SLV0_RESET;
- writel(val, base + USB_SUSP_CTRL);
- udelay(10);
-#endif
/* enable ULPI null phy clock - can't set the trimmers before this */
val = readl(base + ULPI_TIMING_CTRL_0);
val |= ULPI_CLK_OUT_ENA;
writel(val, base + ULPI_TIMING_CTRL_0);
udelay(10);
- /* set trimmers */
+ if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ USB_PHY_CLK_VALID)) {
+ pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* set ULPI trimmers */
ulpi_set_trimmer(base, config->trimmer->data_trimmer,
config->trimmer->stpdirnxt_trimmer, 1);
+ ulpi_set_host(base);
+
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* remove various ULPIS2S resets */
+ /* remove slave0 reset */
val = readl(base + USB_SUSP_CTRL);
- val &= ~ULPIS2S_LINE_RESET;
- val &= ~ULPIS2S_SLV1_RESET;
- val &= ~ULPI_PADS_RESET;
- val &= ~ULPI_PADS_CLKEN_RESET;
+ val &= ~ULPIS2S_SLV0_RESET;
writel(val, base + USB_SUSP_CTRL);
-#endif
- val = readl(base + ULPIS2S_CTRL);
- val |= ULPIS2S_ENA;
- val |= ULPIS2S_SUPPORT_DISCONNECT;
- val |= ULPIS2S_SPARE((phy->mode == TEGRA_USB_PHY_MODE_HOST)? 3 : 1);
- writel(val, base + ULPIS2S_CTRL);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ /* remove slave1 and line reset */
val = readl(base + USB_SUSP_CTRL);
- val |= USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
- udelay(100);
- val = readl(base + USB_SUSP_CTRL);
- val &= ~USB_SUSP_CLR;
+ val &= ~ULPIS2S_SLV1_RESET;
+ val &= ~ULPIS2S_LINE_RESET;
+
+ /* remove ULPI PADS reset */
+ val &= ~ULPI_PADS_RESET;
writel(val, base + USB_SUSP_CTRL);
#endif
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
- USB_PHY_CLK_VALID)) {
- pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
- return -ETIMEDOUT;
- }
-
val = readl(base + ULPI_TIMING_CTRL_0);
val |= ULPI_CLK_PADOUT_ENA;
writel(val, base + ULPI_TIMING_CTRL_0);
+
udelay(10);
if (config->post_phy_on && config->post_phy_on())
@@ -1951,10 +1948,6 @@ static int null_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
if (config->pre_phy_off && config->pre_phy_off())
return -EAGAIN;
- val = readl(base + ULPI_TIMING_CTRL_0);
- val &= ~ULPI_CLK_PADOUT_ENA;
- writel(val, base + ULPI_TIMING_CTRL_0);
-
ulpi_set_tristate(true);
if (config->post_phy_off && config->post_phy_off())
@@ -1963,7 +1956,7 @@ static int null_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
return 0;
}
-static int null_phy_post_usbcmd_reset(struct tegra_usb_phy *phy, bool is_dpd)
+static int null_phy_pre_usbcmd_reset(struct tegra_usb_phy *phy, bool is_dpd)
{
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
unsigned long val;
@@ -1977,16 +1970,25 @@ static int null_phy_post_usbcmd_reset(struct tegra_usb_phy *phy, bool is_dpd)
val |= ULPIS2S_SLV0_RESET;
writel(val, base + USB_SUSP_CTRL);
udelay(10);
+#endif
+ return 0;
+}
+
+static int null_phy_post_usbcmd_reset(struct tegra_usb_phy *phy, bool is_dpd)
+{
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ unsigned long val;
+ void __iomem *base = phy->regs;
/* remove slave0 reset */
val = readl(base + USB_SUSP_CTRL);
val &= ~ULPIS2S_SLV0_RESET;
writel(val, base + USB_SUSP_CTRL);
- udelay(10);
val = readl(base + ULPIS2S_CTRL);
val &= ~ULPIS2S_SLV0_CLAMP_XMIT;
writel(val, base + ULPIS2S_CTRL);
+ udelay(10);
ulpi_set_host(base);
#endif
@@ -2402,6 +2404,19 @@ void tegra_usb_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd)
postresume[phy->usb_phy_type](phy, is_dpd);
}
+void tegra_ehci_pre_reset(struct tegra_usb_phy *phy, bool is_dpd)
+{
+ const tegra_phy_fp pre_reset[] = {
+ NULL,
+ NULL,
+ null_phy_pre_usbcmd_reset,
+ NULL,
+ };
+
+ if (pre_reset[phy->usb_phy_type])
+ pre_reset[phy->usb_phy_type](phy, is_dpd);
+}
+
void tegra_ehci_post_reset(struct tegra_usb_phy *phy, bool is_dpd)
{
const tegra_phy_fp post_reset[] = {