summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Connell <w14185@motorola.com>2011-04-25 14:17:13 -0500
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 00:47:45 -0700
commitf1c8ab6cfe0b05fbd7814a701eb7c2bf4c204bc2 (patch)
tree34e3c041223576d3d326788f4dc3f8ed46c263d0
parent60526475a111239e4781268ef0969f7d4159da9d (diff)
ARM: tegra: Verify PHY clock valid before clearing USB_SUSP_CLR bit
When enabling the external ULPI PHY, the clock from the PHY must be valid before the USB_SUSP_CLR bit is cleared in the USB2 controller interface register. If the clock from the PHY is not valid when this bit is cleared, the AHB clock to the host controller may be stopped, preventing any access to the host controller. Replace hard-coded delay with poll for USB_PHY_CLK_VALID bit. Signed-off-by: Nathan Connell <w14185@motorola.com> Change-Id: I24fa7575641f20ffdba7737776a81ba453f54395 Signed-off-by: Nathan Connell <w14185@motorola.com> Rebase-Id: R819c1a8f769f72aad2868ab78f4d31bd3b97c750
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c35
1 files changed, 11 insertions, 24 deletions
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 5da647bb8b16..7fc7c7f6094c 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -56,6 +56,7 @@
#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)
@@ -294,7 +295,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 = 2000;
+ unsigned long timeout = 2500;
do {
if ((readl(reg) & mask) == result)
return 0;
@@ -355,7 +356,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))
+ USB_PHY_CLK_VALID) < 0)
pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
}
@@ -610,7 +611,6 @@ 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_prepare_enable(phy->clk);
msleep(1);
@@ -637,15 +637,18 @@ 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);
- udelay(100);
+
+ 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__);
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);
@@ -660,24 +663,8 @@ 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 = usb_phy_io_write(phy->ulpi, 0xC0, 0x08);
+ ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
if (ret) {
pr_err("%s: ulpi write failed\n", __func__);
return ret;