diff options
author | Suresh Mangipudi <smangipudi@nvidia.com> | 2011-08-17 11:19:37 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-08-18 16:40:41 -0700 |
commit | 6dfe92801cf0d4ff34068abeac79413f65ecc70a (patch) | |
tree | d5c16f6444d5681a50caa7f6ca24a953cf97b68f /arch/arm/mach-tegra | |
parent | 53ccd798bc1172b7021c8929ca7ebc39244ade09 (diff) |
usb: ehci: tegra: Add SE0 delay for 2LS bit time
Make sure SE0 is driven for 2LS bit time end of resume, so that host
does not see any false disconnect.
Bug 860452
Change-Id: I2651e3977acb068b66284b15d168808e1ccd0277
Reviewed-on: http://git-master/r/47464
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 79 |
1 files changed, 62 insertions, 17 deletions
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index edcd8d788cc4..040211fca6e5 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -126,15 +126,6 @@ #define UTMIP_FS_PREABMLE_J (1 << 19) #define UTMIP_HS_DISCON_DISABLE (1 << 8) -#define UTMIP_MISC_CFG0 0x824 -#define UTMIP_DPDM_OBSERVE (1 << 26) -#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27) -#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf) -#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe) -#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd) -#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc) -#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) - #define UTMIP_MISC_CFG1 0x828 #define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18) #define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6) @@ -284,9 +275,6 @@ #define UTMIP_FS_PREABMLE_J (1 << 19) #define UTMIP_HS_DISCON_DISABLE (1 << 8) -#define UTMIP_MISC_CFG0 0x824 -#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) - #define UTMIP_MISC_CFG1 0x828 #define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18) #define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6) @@ -473,6 +461,18 @@ #endif /* Common registers */ +#define UTMIP_MISC_CFG0 0x824 +#define UTMIP_DPDM_OBSERVE (1 << 26) +#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27) +#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf) +#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe) +#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd) +#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc) +#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) +#define FORCE_PULLDN_DM (1 << 8) +#define FORCE_PULLDN_DP (1 << 9) +#define COMB_TERMS (1 << 0) +#define ALWAYS_FREE_RUNNING_TERMS (1 << 1) #define ULPIS2S_CTRL 0x418 #define ULPIS2S_ENA (1 << 0) @@ -1127,9 +1127,8 @@ static void utmip_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val = readl(pmc_base + PMC_SLEEP_CFG); val &= ~UTMIP_WAKE_VAL(inst, ~0); val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_FSJ); - val |= UTMIP_MASTER_ENABLE(inst); + val |= UTMIP_MASTER_ENABLE(inst) | UTMIP_FSLS_USE_PMC(inst); writel(val, pmc_base + PMC_SLEEP_CFG); - } #endif @@ -1213,10 +1212,20 @@ static int utmi_phy_preresume(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; + void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); + unsigned int inst = phy->instance; +#ifdef CONFIG_ARCH_TEGRA_2x_SOC val = readl(base + UTMIP_TX_CFG0); val |= UTMIP_HS_DISCON_DISABLE; writel(val, base + UTMIP_TX_CFG0); +#else + /* Disable PMC master mode by clearing MASTER_EN */ + val = readl(pmc_base + PMC_SLEEP_CFG); + val &= ~(UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst) | + UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst)); + writel(val, pmc_base + PMC_SLEEP_CFG); +#endif return 0; } @@ -1226,10 +1235,32 @@ static int utmi_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd) unsigned long val; void __iomem *base = phy->regs; +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + /* Change the UTMIP OBS bus to drive SE0 */ + val = readl(base + UTMIP_MISC_CFG0); + val &= ~UTMIP_DPDM_OBSERVE_SEL(~0); + val |= UTMIP_DPDM_OBSERVE_SEL_FS_SE0; + writel(val, base + UTMIP_MISC_CFG0); + + /* Wait for 3us(2 LS bit times) */ + udelay (3); + + /* Release UTMIP OBS bus */ + val = readl(base + UTMIP_MISC_CFG0); + val &= ~UTMIP_DPDM_OBSERVE; + writel(val, base + UTMIP_MISC_CFG0); + + /* Release DP/DM pulldown for Host mode */ + val = readl(base + UTMIP_MISC_CFG0); + val &= ~(FORCE_PULLDN_DM | FORCE_PULLDN_DP | + COMB_TERMS | ALWAYS_FREE_RUNNING_TERMS); + writel(val, base + UTMIP_MISC_CFG0); + +#else val = readl(base + UTMIP_TX_CFG0); val &= ~UTMIP_HS_DISCON_DISABLE; writel(val, base + UTMIP_TX_CFG0); - +#endif return 0; } @@ -1262,16 +1293,30 @@ static int uhsic_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd) static void utmi_phy_restore_start(struct tegra_usb_phy *phy, enum tegra_usb_phy_port_speed port_speed) { -#ifdef CONFIG_ARCH_TEGRA_2x_SOC unsigned long val; void __iomem *base = phy->regs; +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + /* Force DP/DM pulldown active for Host mode */ + val = readl(base + UTMIP_MISC_CFG0); + val |= FORCE_PULLDN_DM | FORCE_PULLDN_DP | + COMB_TERMS | ALWAYS_FREE_RUNNING_TERMS; + writel(val, base + UTMIP_MISC_CFG0); +#endif + val = readl(base + UTMIP_MISC_CFG0); val &= ~UTMIP_DPDM_OBSERVE_SEL(~0); +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) + val |= UTMIP_DPDM_OBSERVE_SEL_FS_J; + else + val |= UTMIP_DPDM_OBSERVE_SEL_FS_K; +#else if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) val |= UTMIP_DPDM_OBSERVE_SEL_FS_K; else val |= UTMIP_DPDM_OBSERVE_SEL_FS_J; +#endif writel(val, base + UTMIP_MISC_CFG0); udelay(1); @@ -1279,7 +1324,7 @@ static void utmi_phy_restore_start(struct tegra_usb_phy *phy, val |= UTMIP_DPDM_OBSERVE; writel(val, base + UTMIP_MISC_CFG0); udelay(10); -#endif + } static void utmi_phy_restore_end(struct tegra_usb_phy *phy) |