aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-hub.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-12-09 18:59:11 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 17:53:12 -0500
commit6219c047d3fe18dee4916d6898fc94f5a7ffd156 (patch)
tree31657ba6dd7268ec53a06652bc0b4e104d586ce2 /drivers/usb/host/xhci-hub.c
parent34fb562a436ca50e13c05e7584c9d62f151052bf (diff)
USB: xhci: Allow roothub ports to be disabled.
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>
Diffstat (limited to 'drivers/usb/host/xhci-hub.c')
-rw-r--r--drivers/usb/host/xhci-hub.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 5850e8bc30de..208b805b80eb 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -129,6 +129,16 @@ static u32 xhci_port_state_to_neutral(u32 state)
129 return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS); 129 return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS);
130} 130}
131 131
132static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
133 u32 __iomem *addr, u32 port_status)
134{
135 /* Write 1 to disable the port */
136 xhci_writel(xhci, port_status | PORT_PE, addr);
137 port_status = xhci_readl(xhci, addr);
138 xhci_dbg(xhci, "disable port, actual port %d status = 0x%x\n",
139 wIndex, port_status);
140}
141
132static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, 142static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
133 u16 wIndex, u32 __iomem *addr, u32 port_status) 143 u16 wIndex, u32 __iomem *addr, u32 port_status)
134{ 144{
@@ -148,6 +158,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
148 status = PORT_OCC; 158 status = PORT_OCC;
149 port_change_bit = "over-current"; 159 port_change_bit = "over-current";
150 break; 160 break;
161 case USB_PORT_FEAT_C_ENABLE:
162 status = PORT_PEC;
163 port_change_bit = "enable/disable";
164 break;
151 default: 165 default:
152 /* Should never happen */ 166 /* Should never happen */
153 return; 167 return;
@@ -260,9 +274,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
260 case USB_PORT_FEAT_C_RESET: 274 case USB_PORT_FEAT_C_RESET:
261 case USB_PORT_FEAT_C_CONNECTION: 275 case USB_PORT_FEAT_C_CONNECTION:
262 case USB_PORT_FEAT_C_OVER_CURRENT: 276 case USB_PORT_FEAT_C_OVER_CURRENT:
277 case USB_PORT_FEAT_C_ENABLE:
263 xhci_clear_port_change_bit(xhci, wValue, wIndex, 278 xhci_clear_port_change_bit(xhci, wValue, wIndex,
264 addr, temp); 279 addr, temp);
265 break; 280 break;
281 case USB_PORT_FEAT_ENABLE:
282 xhci_disable_port(xhci, wIndex, addr, temp);
283 break;
266 default: 284 default:
267 goto error; 285 goto error;
268 } 286 }