diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2009-12-09 18:59:11 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:53:12 -0500 |
commit | 6219c047d3fe18dee4916d6898fc94f5a7ffd156 (patch) | |
tree | 31657ba6dd7268ec53a06652bc0b4e104d586ce2 /drivers/usb/host/xhci-hub.c | |
parent | 34fb562a436ca50e13c05e7584c9d62f151052bf (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.c | 18 |
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 | ||
132 | static 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 | |||
132 | static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, | 142 | static 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 | } |