diff options
author | Steve Lin <stlin@nvidia.com> | 2011-11-03 15:17:43 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:50:25 -0800 |
commit | 3bdfa6a904741e97671809ffabf3252f78ff12ed (patch) | |
tree | 84574926c6f692f022d1d89c747f0bf966291ef5 /arch/arm/mach-tegra/usb_phy.c | |
parent | b011a32cd70698b13e8971069747010e74025d40 (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.c | 61 |
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 |