diff options
author | James Wylder <james.wylder@motorola.com> | 2011-04-07 16:02:19 -0500 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:37:08 -0800 |
commit | 1b83c0bb641be978f0b03c170123063b99cfaf1b (patch) | |
tree | 560fcaaf04a6bcbba3b5e9bbdc3c2f21750f8ed2 | |
parent | d2c9810cc6c0c68d1b15eb041a9b5852183a6077 (diff) |
ARM: tegra: resolve ulpi disconnect issue
Correct phy start-up sequence.
Put the phy in low power mode.
Tristate ulpi interface when USB controller is resuming
Change-Id: I1b326c16b56b9fd2d424afb8cf0888da6c9e245e
Signed-off-by: James Wylder <james.wylder@motorola.com>
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index 1d042af637e1..70746eee4e5b 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -54,7 +54,6 @@ #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) #define USB_SUSP_CLR (1 << 5) -#define USB_CLKEN (1 << 6) #define USB_PHY_CLK_VALID (1 << 7) #define UTMIP_RESET (1 << 11) #define UHSIC_RESET (1 << 11) @@ -293,7 +292,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy) static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result) { - unsigned long timeout = 2500; + unsigned long timeout = 2000; do { if ((readl(reg) & mask) == result) return 0; @@ -354,7 +353,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) } if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, - USB_PHY_CLK_VALID) < 0) + USB_PHY_CLK_VALID)) pr_err("%s: timeout waiting for phy to stabilize\n", __func__); } @@ -376,8 +375,6 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) val = readl(base + UTMIP_TX_CFG0); val &= ~UTMIP_FS_PREABMLE_J; - if (phy->instance == 2) - val |= UTMIP_HS_DISCON_DISABLE; writel(val, base + UTMIP_TX_CFG0); val = readl(base + UTMIP_HSRX_CFG0); @@ -609,6 +606,7 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) unsigned long val; void __iomem *base = phy->regs; struct tegra_ulpi_config *config = phy->config; + unsigned long timeout = 2000; clk_enable(phy->clk); msleep(1); @@ -635,18 +633,15 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) val = readl(base + USB_SUSP_CTRL); val |= USB_SUSP_CLR; writel(val, base + USB_SUSP_CTRL); - - if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, - USB_PHY_CLK_VALID) < 0) - pr_err("%s: timeout waiting for phy to stabilize\n", __func__); - - if (utmi_wait_register(base + USB_SUSP_CTRL, USB_CLKEN, USB_CLKEN) < 0) - pr_err("%s: timeout waiting for AHB clock\n", __func__); + udelay(100); val = readl(base + USB_SUSP_CTRL); val &= ~USB_SUSP_CLR; writel(val, base + USB_SUSP_CTRL); + 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__); + val = 0; writel(val, base + ULPI_TIMING_CTRL_1); @@ -661,8 +656,24 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) val |= ULPI_DIR_TRIMMER_LOAD; writel(val, base + ULPI_TIMING_CTRL_1); + val = 0; + val |= ULPI_WAKEUP; + val |= ULPI_RD_WR; + writel(val, base + ULPI_VIEWPORT); + + + do { + if ((readl(base + ULPI_VIEWPORT) & ULPI_WAKEUP)) + udelay(1); + else + break; + timeout--; + } while (timeout); + if (!timeout) + pr_err("%s: timeout on ULPI Wakeup\n", __func__); + /* Fix VbusInvalid due to floating VBUS */ - ret = otg_io_write(phy->ulpi, 0x40, 0x08); + ret = otg_io_write(phy->ulpi, 0xC0, 0x08); if (ret) { pr_err("%s: ulpi write failed\n", __func__); return ret; |