usb: ehci: tegra: fix hsic enum failure
Vinayak Pane [Thu, 31 May 2012 00:14:18 +0000 (17:14 -0700)]
HSIC device enumeration is broken after usb common
phy changes. Setting correct hsic config in port_power
and repairing wIndex in hub_control.

Bug 991485

Change-Id: Ic2873879070cba8a06fb2cadc40d6c46158f71e9
Signed-off-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/105513
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

arch/arm/mach-tegra/tegra2_usb_phy.c
arch/arm/mach-tegra/tegra3_usb_phy.c
arch/arm/mach-tegra/usb_phy.c
drivers/usb/host/ehci-tegra.c

index 7b18333..f0d5ebd 100644 (file)
@@ -1177,6 +1177,9 @@ static int uhsic_phy_bus_port_power(struct tegra_usb_phy *phy)
        val &= ~USB_USBCMD_RS;
        writel(val, base + USB_USBCMD);
 
+       if (phy->pdata->ops && phy->pdata->ops->port_power)
+               phy->pdata->ops->port_power();
+
        if (usb_phy_reg_status_wait(base + UHSIC_STAT_CFG0,
                        UHSIC_CONNECT_DETECT, UHSIC_CONNECT_DETECT, 2000)) {
                pr_err("%s: timeout waiting for UHSIC_CONNECT_DETECT\n",
index 8ada255..ce2d54b 100644 (file)
@@ -1925,9 +1925,6 @@ int uhsic_phy_bus_port_power(struct tegra_usb_phy *phy)
        void __iomem *base = phy->regs;
 
        DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-       val = readl(base + UHSIC_STAT_CFG0);
-       val &= ~UHSIC_CONNECT_DETECT;
-       writel(val, base + UHSIC_STAT_CFG0);
 
        val = readl(base + USB_USBMODE);
        val |= USB_USBMODE_HOST;
@@ -1952,13 +1949,10 @@ int uhsic_phy_bus_port_power(struct tegra_usb_phy *phy)
 
        val = readl(base + UHSIC_PADS_CFG1);
        val &= ~UHSIC_RPD_STROBE;
-       /* safe to enable RPU on STROBE at all times during idle */
-       val |= UHSIC_RPU_STROBE;
        writel(val, base + UHSIC_PADS_CFG1);
 
-       val = readl(base + USB_USBCMD);
-       val &= ~USB_USBCMD_RS;
-       writel(val, base + USB_USBCMD);
+       if (phy->pdata->ops && phy->pdata->ops->port_power)
+               phy->pdata->ops->port_power();
 
        if (usb_phy_reg_status_wait(base + UHSIC_STAT_CFG0,
                        UHSIC_CONNECT_DETECT, UHSIC_CONNECT_DETECT, 25000)) {
index bfb9aba..dfbd621 100644 (file)
@@ -622,9 +622,6 @@ int tegra_usb_phy_port_power(struct tegra_usb_phy *phy)
        if (phy->ops && phy->ops->port_power)
                status = phy->ops->port_power(phy);
 
-       if (phy->pdata->ops && phy->pdata->ops->port_power)
-               phy->pdata->ops->port_power();
-
        return status;
 }
 int tegra_usb_phy_bus_reset(struct tegra_usb_phy *phy)
index 98f3d51..c8d5485 100644 (file)
@@ -201,7 +201,6 @@ static int tegra_ehci_hub_control(
 {
        struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       unsigned long   flags;
        int     retval = 0;
        u32 __iomem     *status_reg;
 
@@ -254,20 +253,23 @@ static int tegra_ehci_hub_control(
        retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
 
        /* do tegra phy specific actions based on the type request */
-       if (!retval) {
-               switch (typeReq) {
-               case SetPortFeature:
-                       if (wValue == USB_PORT_FEAT_SUSPEND) {
-                               /* Need a 4ms delay for controller to suspend */
-                               mdelay(4);
-                               tegra_usb_phy_post_suspend(tegra->phy);
-                       } else if (wValue == USB_PORT_FEAT_RESET) {
-                               if (ehci->reset_done[0] && wIndex == 0)
-                                       tegra_usb_phy_bus_reset(tegra->phy);
-                       } else if (wValue == USB_PORT_FEAT_POWER) {
-                               if (wIndex == 1)
-                                       tegra_usb_phy_port_power(tegra->phy);
-                       }
+       if (!retval && (typeReq == SetPortFeature)) {
+               wIndex--;
+
+               switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       /* Need a 4ms delay for controller to suspend */
+                       mdelay(4);
+                       tegra_usb_phy_post_suspend(tegra->phy);
+                       break;
+               case USB_PORT_FEAT_RESET:
+                       if (ehci->reset_done[0] && wIndex == 0)
+                               tegra_usb_phy_bus_reset(tegra->phy);
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       if (wIndex == 0)
+                               tegra_usb_phy_port_power(tegra->phy);
+               default:
                        break;
                case ClearPortFeature:
                        if (wValue == USB_PORT_FEAT_SUSPEND) {