summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Wylder <james.wylder@motorola.com>2011-04-07 16:02:19 -0500
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:37:08 -0800
commit1b83c0bb641be978f0b03c170123063b99cfaf1b (patch)
tree560fcaaf04a6bcbba3b5e9bbdc3c2f21750f8ed2
parentd2c9810cc6c0c68d1b15eb041a9b5852183a6077 (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.c37
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;