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:08 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 17:53:11 -0500
commit34fb562a436ca50e13c05e7584c9d62f151052bf (patch)
tree43638f312ee6f5de4157bb397a503bdf5952f35a /drivers/usb/host/xhci-hub.c
parentb45b506911247008f694dcaf1d8220a4942ebc4f (diff)
USB: xhci: Refactor code to clear port change bits.
Refactor the code to clear the port change bits in the port status register. All port status change bits are write one to clear. Remove a redundant port status read that was supposed to unblock any posted writes. We read the port after the write to get the updated status for debugging, so the port read after that is unnecessary. 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.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index eac5b53aa9e7..5850e8bc30de 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -129,6 +129,36 @@ 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_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
133 u16 wIndex, u32 __iomem *addr, u32 port_status)
134{
135 char *port_change_bit;
136 u32 status;
137
138 switch (wValue) {
139 case USB_PORT_FEAT_C_RESET:
140 status = PORT_RC;
141 port_change_bit = "reset";
142 break;
143 case USB_PORT_FEAT_C_CONNECTION:
144 status = PORT_CSC;
145 port_change_bit = "connect";
146 break;
147 case USB_PORT_FEAT_C_OVER_CURRENT:
148 status = PORT_OCC;
149 port_change_bit = "over-current";
150 break;
151 default:
152 /* Should never happen */
153 return;
154 }
155 /* Change bits are all write 1 to clear */
156 xhci_writel(xhci, port_status | status, addr);
157 port_status = xhci_readl(xhci, addr);
158 xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n",
159 port_change_bit, wIndex, port_status);
160}
161
132int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, 162int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
133 u16 wIndex, char *buf, u16 wLength) 163 u16 wIndex, char *buf, u16 wLength)
134{ 164{
@@ -138,7 +168,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
138 u32 temp, status; 168 u32 temp, status;
139 int retval = 0; 169 int retval = 0;
140 u32 __iomem *addr; 170 u32 __iomem *addr;
141 char *port_change_bit;
142 171
143 ports = HCS_MAX_PORTS(xhci->hcs_params1); 172 ports = HCS_MAX_PORTS(xhci->hcs_params1);
144 173
@@ -229,26 +258,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
229 temp = xhci_port_state_to_neutral(temp); 258 temp = xhci_port_state_to_neutral(temp);
230 switch (wValue) { 259 switch (wValue) {
231 case USB_PORT_FEAT_C_RESET: 260 case USB_PORT_FEAT_C_RESET:
232 status = PORT_RC;
233 port_change_bit = "reset";
234 break;
235 case USB_PORT_FEAT_C_CONNECTION: 261 case USB_PORT_FEAT_C_CONNECTION:
236 status = PORT_CSC;
237 port_change_bit = "connect";
238 break;
239 case USB_PORT_FEAT_C_OVER_CURRENT: 262 case USB_PORT_FEAT_C_OVER_CURRENT:
240 status = PORT_OCC; 263 xhci_clear_port_change_bit(xhci, wValue, wIndex,
241 port_change_bit = "over-current"; 264 addr, temp);
242 break; 265 break;
243 default: 266 default:
244 goto error; 267 goto error;
245 } 268 }
246 /* Change bits are all write 1 to clear */
247 xhci_writel(xhci, temp | status, addr);
248 temp = xhci_readl(xhci, addr);
249 xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n",
250 port_change_bit, wIndex, temp);
251 temp = xhci_readl(xhci, addr); /* unblock any posted writes */
252 break; 269 break;
253 default: 270 default:
254error: 271error: