From e750de624e23fc8a8a6916c537394cbf3b38486c Mon Sep 17 00:00:00 2001 From: Jay Cheng Date: Fri, 7 Jan 2011 02:03:46 -0500 Subject: [PATCH] usb: ehci: tegra: continues driving FS-J during resume To prevent USB glitch. Also only program PTC bits when resume from LP0 Change-Id: Iced668e33f986828d3a483b411055948b5b257e1 Signed-off-by: Jay Cheng --- drivers/usb/host/ehci-tegra.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 0e9b6458da84..2341904808bc 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -253,6 +253,7 @@ static int tegra_usb_resume(struct usb_hcd *hcd) struct tegra_ehci_context *context = &tegra->context; struct ehci_regs __iomem *hw = tegra->ehci->regs; unsigned long val; + int lp0_resume = 0; set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); tegra_ehci_power_up(ehci_to_hcd(tegra->ehci)); @@ -264,6 +265,13 @@ static int tegra_usb_resume(struct usb_hcd *hcd) goto restart; } + tegra_ehci_phy_restore_start(tegra->phy); + + /* Check if the phy resume from LP0. When the phy resume from LP0 + * USB register will be reset. */ + if (!readl(&hw->async_next)) + lp0_resume = 1; + /* Restore register context */ writel(TEGRA_USB_USBMODE_HOST, &hw->reserved[19]); writel(context->otgsc, &hw->reserved[18]); @@ -278,17 +286,19 @@ static int tegra_usb_resume(struct usb_hcd *hcd) writel(val, &hw->port_status[0]); udelay(10); - /* Program the field PTC in PORTSC based on the saved speed mode */ - val = readl(&hw->port_status[0]); - val &= ~(TEGRA_USB_PORTSC1_PTC(~0)); - if (context->port_speed == TEGRA_USB_PHY_PORT_HIGH) - val |= TEGRA_USB_PORTSC1_PTC(5); - else if (context->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) - val |= TEGRA_USB_PORTSC1_PTC(6); - else if (context->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) - val |= TEGRA_USB_PORTSC1_PTC(7); - writel(val, &hw->port_status[0]); - udelay(10); + if (lp0_resume) { + /* Program the field PTC in PORTSC based on the saved speed mode */ + val = readl(&hw->port_status[0]); + val &= ~(TEGRA_USB_PORTSC1_PTC(~0)); + if (context->port_speed == TEGRA_USB_PHY_PORT_HIGH) + val |= TEGRA_USB_PORTSC1_PTC(5); + else if (context->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) + val |= TEGRA_USB_PORTSC1_PTC(6); + else if (context->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) + val |= TEGRA_USB_PORTSC1_PTC(7); + writel(val, &hw->port_status[0]); + udelay(10); + } /* Disable test mode by setting PTC field to NORMAL_OP */ val = readl(&hw->port_status[0]); @@ -330,9 +340,11 @@ static int tegra_usb_resume(struct usb_hcd *hcd) } } + tegra_ehci_phy_restore_end(tegra->phy); return 0; restart: + tegra_ehci_phy_restore_end(tegra->phy); tegra_ehci_restart(hcd); return 0; } -- 2.34.1