summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/usb_phy.c
diff options
context:
space:
mode:
authorSteve Lin <stlin@nvidia.com>2011-11-03 15:17:43 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:50:25 -0800
commit3bdfa6a904741e97671809ffabf3252f78ff12ed (patch)
tree84574926c6f692f022d1d89c747f0bf966291ef5 /arch/arm/mach-tegra/usb_phy.c
parentb011a32cd70698b13e8971069747010e74025d40 (diff)
arm: tegra: usb: enable ULPI CLK after STP is asserted in LP0 resume
1) Enabling ULPI CLK after MDM2AP_ACK is asserted 2) Driving linestate by GPIO before removing the ULPI data tristate Bug 889484 Reviewed-on: http://git-master/r/60104 (cherry picked from commit 795b9ddcedf3f6465c6a352005c8d8615a36e739) Change-Id: Idde92fec46cdb26bc336ffd2d12a2cfb65b3f2e9 Reviewed-on: http://git-master/r/66995 Reviewed-by: Steve Lin <stlin@nvidia.com> Tested-by: Steve Lin <stlin@nvidia.com> Rebase-Id: Re67fcacdd2b3efcbd99e9861fb6bc5e3a2f204aa
Diffstat (limited to 'arch/arm/mach-tegra/usb_phy.c')
-rw-r--r--arch/arm/mach-tegra/usb_phy.c61
1 files changed, 51 insertions, 10 deletions
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 349877074b93..fab702a5bd72 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -33,9 +33,13 @@
#include <mach/usb_phy.h>
#include <mach/iomap.h>
#include <mach/pinmux.h>
-
+#include "gpio-names.h"
#include "fuse.h"
+/* Modem hibernate test parameters */
+#define TRIGGER_BY_MDM2AP_ACK 1
+/* ------------------------------- */
+
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
#define USB_USBCMD 0x140
#define USB_USBCMD_RS (1 << 0)
@@ -1663,6 +1667,21 @@ static void ulpi_set_trimmer(void __iomem *base, u8 data, u8 sdn, u8 dir)
writel(val, base + ULPI_TIMING_CTRL_1);
}
+static inline void ulpi_pinmux_bypass(struct tegra_usb_phy *phy, bool enable)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+
+ if (enable)
+ val |= ULPI_OUTPUT_PINMUX_BYP;
+ else
+ val &= ~ULPI_OUTPUT_PINMUX_BYP;
+
+ writel(val, base + ULPI_TIMING_CTRL_0);
+}
+
static void ulpi_phy_restore_start(struct tegra_usb_phy *phy,
enum tegra_usb_phy_port_speed port_speed)
{
@@ -1822,7 +1841,7 @@ static int ulpi_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
return 0;
}
-static void null_phy_set_tristate(bool enable)
+static inline void null_phy_set_tristate(bool enable)
{
int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
@@ -1831,6 +1850,7 @@ static void null_phy_set_tristate(bool enable)
tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate);
tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate);
#else
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate);
tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate);
tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate);
tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate);
@@ -1839,7 +1859,6 @@ static void null_phy_set_tristate(bool enable)
tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate);
tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate);
tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate);
if (enable)
tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate);
@@ -1863,22 +1882,44 @@ static void null_phy_restore_end(struct tegra_usb_phy *phy)
unsigned long val;
void __iomem *base = phy->regs;
struct tegra_ulpi_config *config = phy->config;
+ int retry = 20000;
- if (config->phy_restore_end)
- config->phy_restore_end();
-
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_CLK_PADOUT_ENA;
+ /* disable ULPI pinmux bypass */
+ ulpi_pinmux_bypass(phy, false);
- udelay(500);
+ /* driving linestate using GPIO */
+ gpio_set_value(TEGRA_GPIO_PO1, 0);
+ gpio_set_value(TEGRA_GPIO_PO2, 0);
/* remove ULPI tristate except DIR */
null_phy_set_tristate(false);
- udelay(20);
+
+ if (config->phy_restore_end)
+ config->phy_restore_end();
+
+ while (retry) {
+#if TRIGGER_BY_MDM2AP_ACK
+ if (gpio_get_value(TEGRA_GPIO_PU5)) /* poll MDM2AP_ACK high */
+ break;
+#else
+ if (gpio_get_value(TEGRA_GPIO_PY3)) /* poll STP high */
+ break;
+#endif
+ retry--;
+ }
+
+ if (retry == 0)
+ pr_info("MDM2AP_ACK timeout\n");
/* enable ULPI CLK output pad */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
writel(val, base + ULPI_TIMING_CTRL_0);
+ /* enable ULPI pinmux bypass */
+ ulpi_pinmux_bypass(phy, true);
+ udelay(5);
+
/* remove DIR tristate */
tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, TEGRA_TRI_NORMAL);
#endif