USB: xhci: Allow roothub ports to be disabled.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Wed, 9 Dec 2009 23:59:11 +0000 (15:59 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 2 Mar 2010 22:53:12 +0000 (14:53 -0800)
Add the hub emulation code to allow ports on an xHCI root hub to be
disabled.  Add the code to clear the port enabled/disabled bit, and clear
the port enabled/disabled change bit.  Like EHCI, the port cannot be
enabled by setting the port enabled/disabled bit.  Instead, a port is
enabled by the host controller after a reset.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/xhci-hub.c

index 5850e8bc30defe79904258ec185ffac2673797d7..208b805b80eb0151d5d5a4e614db8a8fa9ab17eb 100644 (file)
@@ -129,6 +129,16 @@ static u32 xhci_port_state_to_neutral(u32 state)
        return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS);
 }
 
+static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
+               u32 __iomem *addr, u32 port_status)
+{
+       /* Write 1 to disable the port */
+       xhci_writel(xhci, port_status | PORT_PE, addr);
+       port_status = xhci_readl(xhci, addr);
+       xhci_dbg(xhci, "disable port, actual port %d status  = 0x%x\n",
+                       wIndex, port_status);
+}
+
 static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
                u16 wIndex, u32 __iomem *addr, u32 port_status)
 {
@@ -148,6 +158,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
                status = PORT_OCC;
                port_change_bit = "over-current";
                break;
+       case USB_PORT_FEAT_C_ENABLE:
+               status = PORT_PEC;
+               port_change_bit = "enable/disable";
+               break;
        default:
                /* Should never happen */
                return;
@@ -260,9 +274,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                case USB_PORT_FEAT_C_RESET:
                case USB_PORT_FEAT_C_CONNECTION:
                case USB_PORT_FEAT_C_OVER_CURRENT:
+               case USB_PORT_FEAT_C_ENABLE:
                        xhci_clear_port_change_bit(xhci, wValue, wIndex,
                                        addr, temp);
                        break;
+               case USB_PORT_FEAT_ENABLE:
+                       xhci_disable_port(xhci, wIndex, addr, temp);
+                       break;
                default:
                        goto error;
                }