diff options
author | Abhishek Shukla <abhisheks@nvidia.com> | 2012-07-27 13:04:18 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-08-01 17:39:00 -0700 |
commit | 50008402a6f093e48dee05fc88bc54750b97ae25 (patch) | |
tree | 36f1a8d1cb72e9063be233e9d5e725471e75e025 /arch/arm/mach-tegra/tegra3_usb_phy.c | |
parent | ce9fc97cf95c463dff8156dffd5632e5336e4adc (diff) |
ARM: tegra: usb_phy: Fix fake remote wakeup
1. Move hsic line value detectors power on config to the beginning of
the sequence before enabling interrupt on hsic line wake event. This
avoids any fake event caused by any glitches introduced by this
switching.
2. Clear any prior interrupts for the line wake event before enabling
interrupt for the line wake event. This also clears any fake events
generated because of any glitches.
3. Fix wake event type to NONE in the disable routine during resume
interrupt.
Bug 1019619
Bug 1018416
Signed-off-by: Abhishek Shukla <abhisheks@nvidia.com>
Change-Id: I934fa2514897c4c23bc62ff8365f6fffe7915bd0
Reviewed-on: http://git-master/r/116699
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra3_usb_phy.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra3_usb_phy.c | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index f164b409d29b..ac87111dbd7d 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -1869,6 +1869,30 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_PWR; writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG); + /* Make sure nothing is happening on the line with respect to PMC */ + val = readl(pmc_base + PMC_UTMIP_UHSIC_FAKE); + val &= ~UHSIC_STROBE_VAL; + val &= ~UHSIC_DATA_VAL; + writel(val, pmc_base + PMC_UTMIP_UHSIC_FAKE); + + /* Clear walk enable */ + val = readl(pmc_base + PMC_SLEEPWALK_CFG); + val &= ~UHSIC_LINEVAL_WALK_EN; + writel(val, pmc_base + PMC_SLEEPWALK_CFG); + + /* Make sure wake value for line is none */ + val = readl(pmc_base + PMC_SLEEP_CFG); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); + val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); + writel(val, pmc_base + PMC_SLEEP_CFG); + + /* turn on pad detectors */ + val = readl(pmc_base + PMC_USB_AO); + val &= ~(STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); + writel(val, pmc_base + PMC_USB_AO); + + /* Add small delay before usb detectors provide stable line values */ + udelay(1); /* Enable which type of event can trigger a walk, * in this case usb_line_wake */ @@ -1885,19 +1909,16 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_DATA_RPD_A; val &= ~UHSIC_STROBE_RPD_A; val |= UHSIC_STROBE_RPU_A; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_B; val |= UHSIC_DATA_RPU_B; val &= ~UHSIC_STROBE_RPU_B; val |= UHSIC_STROBE_RPD_B; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_C; val |= UHSIC_DATA_RPU_C; val &= ~UHSIC_STROBE_RPU_C; val |= UHSIC_STROBE_RPD_C; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_D; val |= UHSIC_DATA_RPU_D; @@ -1905,19 +1926,21 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_STROBE_RPD_D; writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); - /* turn on pad detectors */ - val = readl(pmc_base + PMC_USB_AO); - val &= ~(STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); - writel(val, pmc_base + PMC_USB_AO); - /* Add small delay before usb detectors provide stable line values */ - udelay(1); - phy->remote_wakeup = false; - /* Turn over pad configuration to PMC for line wake events*/ + /* Setting Wake event*/ val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(~0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_SD10); + writel(val, pmc_base + PMC_SLEEP_CFG); + + /* Clear the walk pointers and wake alarm */ + val = readl(pmc_base + PMC_TRIGGERS); + val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; + writel(val, pmc_base + PMC_TRIGGERS); + + /* Turn over pad configuration to PMC for line wake events*/ + val = readl(pmc_base + PMC_SLEEP_CFG); val |= UHSIC_MASTER_ENABLE; writel(val, pmc_base + PMC_SLEEP_CFG); @@ -1936,14 +1959,10 @@ static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) DBG("%s (%d)\n", __func__, __LINE__); val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(0x0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); writel(val, pmc_base + PMC_SLEEP_CFG); - val = readl(pmc_base + PMC_TRIGGERS); - val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; - writel(val, pmc_base + PMC_TRIGGERS); - val = readl(base + UHSIC_PMC_WAKEUP0); val &= ~EVENT_INT_ENB; writel(val, base + UHSIC_PMC_WAKEUP0); @@ -1958,6 +1977,10 @@ static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) val |= (STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); writel(val, pmc_base + PMC_USB_AO); + val = readl(pmc_base + PMC_TRIGGERS); + val |= (UHSIC_CLR_WALK_PTR_P0 | UHSIC_CLR_WAKE_ALARM_P0); + writel(val, pmc_base + PMC_TRIGGERS); + phy->remote_wakeup = false; } @@ -1972,12 +1995,12 @@ static bool uhsic_phy_remotewake_detected(struct tegra_usb_phy *phy) val = readl(pmc_base + UTMIP_UHSIC_STATUS); if (UHSIC_WAKE_ALARM & val) { val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(0x0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); writel(val, pmc_base + PMC_SLEEP_CFG); val = readl(pmc_base + PMC_TRIGGERS); - val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; + val |= UHSIC_CLR_WAKE_ALARM_P0; writel(val, pmc_base + PMC_TRIGGERS); val = readl(base + UHSIC_PMC_WAKEUP0); |