aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r--drivers/usb/host/ehci-hub.c324
1 files changed, 226 insertions, 98 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index bfe5f307cba6..0d83c6df1a3b 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -47,7 +47,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
47 ehci_quiesce (ehci); 47 ehci_quiesce (ehci);
48 hcd->state = HC_STATE_QUIESCING; 48 hcd->state = HC_STATE_QUIESCING;
49 } 49 }
50 ehci->command = readl (&ehci->regs->command); 50 ehci->command = ehci_readl(ehci, &ehci->regs->command);
51 if (ehci->reclaim) 51 if (ehci->reclaim)
52 ehci->reclaim_ready = 1; 52 ehci->reclaim_ready = 1;
53 ehci_work(ehci); 53 ehci_work(ehci);
@@ -60,7 +60,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
60 ehci->bus_suspended = 0; 60 ehci->bus_suspended = 0;
61 while (port--) { 61 while (port--) {
62 u32 __iomem *reg = &ehci->regs->port_status [port]; 62 u32 __iomem *reg = &ehci->regs->port_status [port];
63 u32 t1 = readl (reg) & ~PORT_RWC_BITS; 63 u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
64 u32 t2 = t1; 64 u32 t2 = t1;
65 65
66 /* keep track of which ports we suspend */ 66 /* keep track of which ports we suspend */
@@ -79,7 +79,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
79 if (t1 != t2) { 79 if (t1 != t2) {
80 ehci_vdbg (ehci, "port %d, %08x -> %08x\n", 80 ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
81 port + 1, t1, t2); 81 port + 1, t1, t2);
82 writel (t2, reg); 82 ehci_writel(ehci, t2, reg);
83 } 83 }
84 } 84 }
85 85
@@ -92,8 +92,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
92 mask = INTR_MASK; 92 mask = INTR_MASK;
93 if (!device_may_wakeup(&hcd->self.root_hub->dev)) 93 if (!device_may_wakeup(&hcd->self.root_hub->dev))
94 mask &= ~STS_PCD; 94 mask &= ~STS_PCD;
95 writel(mask, &ehci->regs->intr_enable); 95 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
96 readl(&ehci->regs->intr_enable); 96 ehci_readl(ehci, &ehci->regs->intr_enable);
97 97
98 ehci->next_statechange = jiffies + msecs_to_jiffies(10); 98 ehci->next_statechange = jiffies + msecs_to_jiffies(10);
99 spin_unlock_irq (&ehci->lock); 99 spin_unlock_irq (&ehci->lock);
@@ -118,26 +118,26 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
118 * the last user of the controller, not reset/pm hardware keeping 118 * the last user of the controller, not reset/pm hardware keeping
119 * state we gave to it. 119 * state we gave to it.
120 */ 120 */
121 temp = readl(&ehci->regs->intr_enable); 121 temp = ehci_readl(ehci, &ehci->regs->intr_enable);
122 ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss"); 122 ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
123 123
124 /* at least some APM implementations will try to deliver 124 /* at least some APM implementations will try to deliver
125 * IRQs right away, so delay them until we're ready. 125 * IRQs right away, so delay them until we're ready.
126 */ 126 */
127 writel(0, &ehci->regs->intr_enable); 127 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
128 128
129 /* re-init operational registers */ 129 /* re-init operational registers */
130 writel(0, &ehci->regs->segment); 130 ehci_writel(ehci, 0, &ehci->regs->segment);
131 writel(ehci->periodic_dma, &ehci->regs->frame_list); 131 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
132 writel((u32) ehci->async->qh_dma, &ehci->regs->async_next); 132 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
133 133
134 /* restore CMD_RUN, framelist size, and irq threshold */ 134 /* restore CMD_RUN, framelist size, and irq threshold */
135 writel (ehci->command, &ehci->regs->command); 135 ehci_writel(ehci, ehci->command, &ehci->regs->command);
136 136
137 /* manually resume the ports we suspended during bus_suspend() */ 137 /* manually resume the ports we suspended during bus_suspend() */
138 i = HCS_N_PORTS (ehci->hcs_params); 138 i = HCS_N_PORTS (ehci->hcs_params);
139 while (i--) { 139 while (i--) {
140 temp = readl (&ehci->regs->port_status [i]); 140 temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
141 temp &= ~(PORT_RWC_BITS 141 temp &= ~(PORT_RWC_BITS
142 | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); 142 | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
143 if (test_bit(i, &ehci->bus_suspended) && 143 if (test_bit(i, &ehci->bus_suspended) &&
@@ -145,20 +145,20 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
145 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); 145 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
146 temp |= PORT_RESUME; 146 temp |= PORT_RESUME;
147 } 147 }
148 writel (temp, &ehci->regs->port_status [i]); 148 ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
149 } 149 }
150 i = HCS_N_PORTS (ehci->hcs_params); 150 i = HCS_N_PORTS (ehci->hcs_params);
151 mdelay (20); 151 mdelay (20);
152 while (i--) { 152 while (i--) {
153 temp = readl (&ehci->regs->port_status [i]); 153 temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
154 if (test_bit(i, &ehci->bus_suspended) && 154 if (test_bit(i, &ehci->bus_suspended) &&
155 (temp & PORT_SUSPEND)) { 155 (temp & PORT_SUSPEND)) {
156 temp &= ~(PORT_RWC_BITS | PORT_RESUME); 156 temp &= ~(PORT_RWC_BITS | PORT_RESUME);
157 writel (temp, &ehci->regs->port_status [i]); 157 ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
158 ehci_vdbg (ehci, "resumed port %d\n", i + 1); 158 ehci_vdbg (ehci, "resumed port %d\n", i + 1);
159 } 159 }
160 } 160 }
161 (void) readl (&ehci->regs->command); 161 (void) ehci_readl(ehci, &ehci->regs->command);
162 162
163 /* maybe re-activate the schedule(s) */ 163 /* maybe re-activate the schedule(s) */
164 temp = 0; 164 temp = 0;
@@ -168,14 +168,14 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
168 temp |= CMD_PSE; 168 temp |= CMD_PSE;
169 if (temp) { 169 if (temp) {
170 ehci->command |= temp; 170 ehci->command |= temp;
171 writel (ehci->command, &ehci->regs->command); 171 ehci_writel(ehci, ehci->command, &ehci->regs->command);
172 } 172 }
173 173
174 ehci->next_statechange = jiffies + msecs_to_jiffies(5); 174 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
175 hcd->state = HC_STATE_RUNNING; 175 hcd->state = HC_STATE_RUNNING;
176 176
177 /* Now we can safely re-enable irqs */ 177 /* Now we can safely re-enable irqs */
178 writel(INTR_MASK, &ehci->regs->intr_enable); 178 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
179 179
180 spin_unlock_irq (&ehci->lock); 180 spin_unlock_irq (&ehci->lock);
181 return 0; 181 return 0;
@@ -190,9 +190,107 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
190 190
191/*-------------------------------------------------------------------------*/ 191/*-------------------------------------------------------------------------*/
192 192
193/* Display the ports dedicated to the companion controller */
194static ssize_t show_companion(struct class_device *class_dev, char *buf)
195{
196 struct ehci_hcd *ehci;
197 int nports, index, n;
198 int count = PAGE_SIZE;
199 char *ptr = buf;
200
201 ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev)));
202 nports = HCS_N_PORTS(ehci->hcs_params);
203
204 for (index = 0; index < nports; ++index) {
205 if (test_bit(index, &ehci->companion_ports)) {
206 n = scnprintf(ptr, count, "%d\n", index + 1);
207 ptr += n;
208 count -= n;
209 }
210 }
211 return ptr - buf;
212}
213
214/*
215 * Dedicate or undedicate a port to the companion controller.
216 * Syntax is "[-]portnum", where a leading '-' sign means
217 * return control of the port to the EHCI controller.
218 */
219static ssize_t store_companion(struct class_device *class_dev,
220 const char *buf, size_t count)
221{
222 struct ehci_hcd *ehci;
223 int portnum, new_owner, try;
224 u32 __iomem *status_reg;
225 u32 port_status;
226
227 ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev)));
228 new_owner = PORT_OWNER; /* Owned by companion */
229 if (sscanf(buf, "%d", &portnum) != 1)
230 return -EINVAL;
231 if (portnum < 0) {
232 portnum = - portnum;
233 new_owner = 0; /* Owned by EHCI */
234 }
235 if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
236 return -ENOENT;
237 status_reg = &ehci->regs->port_status[--portnum];
238 if (new_owner)
239 set_bit(portnum, &ehci->companion_ports);
240 else
241 clear_bit(portnum, &ehci->companion_ports);
242
243 /*
244 * The controller won't set the OWNER bit if the port is
245 * enabled, so this loop will sometimes require at least two
246 * iterations: one to disable the port and one to set OWNER.
247 */
248
249 for (try = 4; try > 0; --try) {
250 spin_lock_irq(&ehci->lock);
251 port_status = ehci_readl(ehci, status_reg);
252 if ((port_status & PORT_OWNER) == new_owner
253 || (port_status & (PORT_OWNER | PORT_CONNECT))
254 == 0)
255 try = 0;
256 else {
257 port_status ^= PORT_OWNER;
258 port_status &= ~(PORT_PE | PORT_RWC_BITS);
259 ehci_writel(ehci, port_status, status_reg);
260 }
261 spin_unlock_irq(&ehci->lock);
262 if (try > 1)
263 msleep(5);
264 }
265 return count;
266}
267static CLASS_DEVICE_ATTR(companion, 0644, show_companion, store_companion);
268
269static inline void create_companion_file(struct ehci_hcd *ehci)
270{
271 int i;
272
273 /* with integrated TT there is no companion! */
274 if (!ehci_is_TDI(ehci))
275 i = class_device_create_file(ehci_to_hcd(ehci)->self.class_dev,
276 &class_device_attr_companion);
277}
278
279static inline void remove_companion_file(struct ehci_hcd *ehci)
280{
281 /* with integrated TT there is no companion! */
282 if (!ehci_is_TDI(ehci))
283 class_device_remove_file(ehci_to_hcd(ehci)->self.class_dev,
284 &class_device_attr_companion);
285}
286
287
288/*-------------------------------------------------------------------------*/
289
193static int check_reset_complete ( 290static int check_reset_complete (
194 struct ehci_hcd *ehci, 291 struct ehci_hcd *ehci,
195 int index, 292 int index,
293 u32 __iomem *status_reg,
196 int port_status 294 int port_status
197) { 295) {
198 if (!(port_status & PORT_CONNECT)) { 296 if (!(port_status & PORT_CONNECT)) {
@@ -217,7 +315,7 @@ static int check_reset_complete (
217 // what happens if HCS_N_CC(params) == 0 ? 315 // what happens if HCS_N_CC(params) == 0 ?
218 port_status |= PORT_OWNER; 316 port_status |= PORT_OWNER;
219 port_status &= ~PORT_RWC_BITS; 317 port_status &= ~PORT_RWC_BITS;
220 writel (port_status, &ehci->regs->port_status [index]); 318 ehci_writel(ehci, port_status, status_reg);
221 319
222 } else 320 } else
223 ehci_dbg (ehci, "port %d high speed\n", index + 1); 321 ehci_dbg (ehci, "port %d high speed\n", index + 1);
@@ -268,22 +366,21 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
268 /* port N changes (bit N)? */ 366 /* port N changes (bit N)? */
269 spin_lock_irqsave (&ehci->lock, flags); 367 spin_lock_irqsave (&ehci->lock, flags);
270 for (i = 0; i < ports; i++) { 368 for (i = 0; i < ports; i++) {
271 temp = readl (&ehci->regs->port_status [i]); 369 temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
272 if (temp & PORT_OWNER) { 370
273 /* don't report this in GetPortStatus */ 371 /*
274 if (temp & PORT_CSC) { 372 * Return status information even for ports with OWNER set.
275 temp &= ~PORT_RWC_BITS; 373 * Otherwise khubd wouldn't see the disconnect event when a
276 temp |= PORT_CSC; 374 * high-speed device is switched over to the companion
277 writel (temp, &ehci->regs->port_status [i]); 375 * controller by the user.
278 } 376 */
279 continue; 377
280 }
281 if (!(temp & PORT_CONNECT)) 378 if (!(temp & PORT_CONNECT))
282 ehci->reset_done [i] = 0; 379 ehci->reset_done [i] = 0;
283 if ((temp & mask) != 0 380 if ((temp & mask) != 0
284 || ((temp & PORT_RESUME) != 0 381 || ((temp & PORT_RESUME) != 0
285 && time_after (jiffies, 382 && time_after_eq(jiffies,
286 ehci->reset_done [i]))) { 383 ehci->reset_done[i]))) {
287 if (i < 7) 384 if (i < 7)
288 buf [0] |= 1 << (i + 1); 385 buf [0] |= 1 << (i + 1);
289 else 386 else
@@ -345,6 +442,7 @@ static int ehci_hub_control (
345) { 442) {
346 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 443 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
347 int ports = HCS_N_PORTS (ehci->hcs_params); 444 int ports = HCS_N_PORTS (ehci->hcs_params);
445 u32 __iomem *status_reg = &ehci->regs->port_status[wIndex - 1];
348 u32 temp, status; 446 u32 temp, status;
349 unsigned long flags; 447 unsigned long flags;
350 int retval = 0; 448 int retval = 0;
@@ -373,18 +471,22 @@ static int ehci_hub_control (
373 if (!wIndex || wIndex > ports) 471 if (!wIndex || wIndex > ports)
374 goto error; 472 goto error;
375 wIndex--; 473 wIndex--;
376 temp = readl (&ehci->regs->port_status [wIndex]); 474 temp = ehci_readl(ehci, status_reg);
377 if (temp & PORT_OWNER) 475
378 break; 476 /*
477 * Even if OWNER is set, so the port is owned by the
478 * companion controller, khubd needs to be able to clear
479 * the port-change status bits (especially
480 * USB_PORT_FEAT_C_CONNECTION).
481 */
379 482
380 switch (wValue) { 483 switch (wValue) {
381 case USB_PORT_FEAT_ENABLE: 484 case USB_PORT_FEAT_ENABLE:
382 writel (temp & ~PORT_PE, 485 ehci_writel(ehci, temp & ~PORT_PE, status_reg);
383 &ehci->regs->port_status [wIndex]);
384 break; 486 break;
385 case USB_PORT_FEAT_C_ENABLE: 487 case USB_PORT_FEAT_C_ENABLE:
386 writel((temp & ~PORT_RWC_BITS) | PORT_PEC, 488 ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC,
387 &ehci->regs->port_status [wIndex]); 489 status_reg);
388 break; 490 break;
389 case USB_PORT_FEAT_SUSPEND: 491 case USB_PORT_FEAT_SUSPEND:
390 if (temp & PORT_RESET) 492 if (temp & PORT_RESET)
@@ -396,8 +498,8 @@ static int ehci_hub_control (
396 goto error; 498 goto error;
397 /* resume signaling for 20 msec */ 499 /* resume signaling for 20 msec */
398 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 500 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
399 writel (temp | PORT_RESUME, 501 ehci_writel(ehci, temp | PORT_RESUME,
400 &ehci->regs->port_status [wIndex]); 502 status_reg);
401 ehci->reset_done [wIndex] = jiffies 503 ehci->reset_done [wIndex] = jiffies
402 + msecs_to_jiffies (20); 504 + msecs_to_jiffies (20);
403 } 505 }
@@ -407,16 +509,17 @@ static int ehci_hub_control (
407 break; 509 break;
408 case USB_PORT_FEAT_POWER: 510 case USB_PORT_FEAT_POWER:
409 if (HCS_PPC (ehci->hcs_params)) 511 if (HCS_PPC (ehci->hcs_params))
410 writel (temp & ~(PORT_RWC_BITS | PORT_POWER), 512 ehci_writel(ehci,
411 &ehci->regs->port_status [wIndex]); 513 temp & ~(PORT_RWC_BITS | PORT_POWER),
514 status_reg);
412 break; 515 break;
413 case USB_PORT_FEAT_C_CONNECTION: 516 case USB_PORT_FEAT_C_CONNECTION:
414 writel((temp & ~PORT_RWC_BITS) | PORT_CSC, 517 ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC,
415 &ehci->regs->port_status [wIndex]); 518 status_reg);
416 break; 519 break;
417 case USB_PORT_FEAT_C_OVER_CURRENT: 520 case USB_PORT_FEAT_C_OVER_CURRENT:
418 writel((temp & ~PORT_RWC_BITS) | PORT_OCC, 521 ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC,
419 &ehci->regs->port_status [wIndex]); 522 status_reg);
420 break; 523 break;
421 case USB_PORT_FEAT_C_RESET: 524 case USB_PORT_FEAT_C_RESET:
422 /* GetPortStatus clears reset */ 525 /* GetPortStatus clears reset */
@@ -424,7 +527,7 @@ static int ehci_hub_control (
424 default: 527 default:
425 goto error; 528 goto error;
426 } 529 }
427 readl (&ehci->regs->command); /* unblock posted write */ 530 ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */
428 break; 531 break;
429 case GetHubDescriptor: 532 case GetHubDescriptor:
430 ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) 533 ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
@@ -440,7 +543,7 @@ static int ehci_hub_control (
440 goto error; 543 goto error;
441 wIndex--; 544 wIndex--;
442 status = 0; 545 status = 0;
443 temp = readl (&ehci->regs->port_status [wIndex]); 546 temp = ehci_readl(ehci, status_reg);
444 547
445 // wPortChange bits 548 // wPortChange bits
446 if (temp & PORT_CSC) 549 if (temp & PORT_CSC)
@@ -451,42 +554,55 @@ static int ehci_hub_control (
451 status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; 554 status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
452 555
453 /* whoever resumes must GetPortStatus to complete it!! */ 556 /* whoever resumes must GetPortStatus to complete it!! */
454 if ((temp & PORT_RESUME) 557 if (temp & PORT_RESUME) {
455 && time_after (jiffies,
456 ehci->reset_done [wIndex])) {
457 status |= 1 << USB_PORT_FEAT_C_SUSPEND;
458 ehci->reset_done [wIndex] = 0;
459 558
460 /* stop resume signaling */ 559 /* Remote Wakeup received? */
461 temp = readl (&ehci->regs->port_status [wIndex]); 560 if (!ehci->reset_done[wIndex]) {
462 writel (temp & ~(PORT_RWC_BITS | PORT_RESUME), 561 /* resume signaling for 20 msec */
463 &ehci->regs->port_status [wIndex]); 562 ehci->reset_done[wIndex] = jiffies
464 retval = handshake ( 563 + msecs_to_jiffies(20);
465 &ehci->regs->port_status [wIndex], 564 /* check the port again */
466 PORT_RESUME, 0, 2000 /* 2msec */); 565 mod_timer(&ehci_to_hcd(ehci)->rh_timer,
467 if (retval != 0) { 566 ehci->reset_done[wIndex]);
468 ehci_err (ehci, "port %d resume error %d\n", 567 }
469 wIndex + 1, retval); 568
470 goto error; 569 /* resume completed? */
570 else if (time_after_eq(jiffies,
571 ehci->reset_done[wIndex])) {
572 status |= 1 << USB_PORT_FEAT_C_SUSPEND;
573 ehci->reset_done[wIndex] = 0;
574
575 /* stop resume signaling */
576 temp = ehci_readl(ehci, status_reg);
577 ehci_writel(ehci,
578 temp & ~(PORT_RWC_BITS | PORT_RESUME),
579 status_reg);
580 retval = handshake(ehci, status_reg,
581 PORT_RESUME, 0, 2000 /* 2msec */);
582 if (retval != 0) {
583 ehci_err(ehci,
584 "port %d resume error %d\n",
585 wIndex + 1, retval);
586 goto error;
587 }
588 temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
471 } 589 }
472 temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
473 } 590 }
474 591
475 /* whoever resets must GetPortStatus to complete it!! */ 592 /* whoever resets must GetPortStatus to complete it!! */
476 if ((temp & PORT_RESET) 593 if ((temp & PORT_RESET)
477 && time_after (jiffies, 594 && time_after_eq(jiffies,
478 ehci->reset_done [wIndex])) { 595 ehci->reset_done[wIndex])) {
479 status |= 1 << USB_PORT_FEAT_C_RESET; 596 status |= 1 << USB_PORT_FEAT_C_RESET;
480 ehci->reset_done [wIndex] = 0; 597 ehci->reset_done [wIndex] = 0;
481 598
482 /* force reset to complete */ 599 /* force reset to complete */
483 writel (temp & ~(PORT_RWC_BITS | PORT_RESET), 600 ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
484 &ehci->regs->port_status [wIndex]); 601 status_reg);
485 /* REVISIT: some hardware needs 550+ usec to clear 602 /* REVISIT: some hardware needs 550+ usec to clear
486 * this bit; seems too long to spin routinely... 603 * this bit; seems too long to spin routinely...
487 */ 604 */
488 retval = handshake ( 605 retval = handshake(ehci, status_reg,
489 &ehci->regs->port_status [wIndex],
490 PORT_RESET, 0, 750); 606 PORT_RESET, 0, 750);
491 if (retval != 0) { 607 if (retval != 0) {
492 ehci_err (ehci, "port %d reset error %d\n", 608 ehci_err (ehci, "port %d reset error %d\n",
@@ -495,28 +611,41 @@ static int ehci_hub_control (
495 } 611 }
496 612
497 /* see what we found out */ 613 /* see what we found out */
498 temp = check_reset_complete (ehci, wIndex, 614 temp = check_reset_complete (ehci, wIndex, status_reg,
499 readl (&ehci->regs->port_status [wIndex])); 615 ehci_readl(ehci, status_reg));
500 } 616 }
501 617
502 // don't show wPortStatus if it's owned by a companion hc 618 /* transfer dedicated ports to the companion hc */
503 if (!(temp & PORT_OWNER)) { 619 if ((temp & PORT_CONNECT) &&
504 if (temp & PORT_CONNECT) { 620 test_bit(wIndex, &ehci->companion_ports)) {
505 status |= 1 << USB_PORT_FEAT_CONNECTION; 621 temp &= ~PORT_RWC_BITS;
506 // status may be from integrated TT 622 temp |= PORT_OWNER;
507 status |= ehci_port_speed(ehci, temp); 623 ehci_writel(ehci, temp, status_reg);
508 } 624 ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1);
509 if (temp & PORT_PE) 625 temp = ehci_readl(ehci, status_reg);
510 status |= 1 << USB_PORT_FEAT_ENABLE; 626 }
511 if (temp & (PORT_SUSPEND|PORT_RESUME)) 627
512 status |= 1 << USB_PORT_FEAT_SUSPEND; 628 /*
513 if (temp & PORT_OC) 629 * Even if OWNER is set, there's no harm letting khubd
514 status |= 1 << USB_PORT_FEAT_OVER_CURRENT; 630 * see the wPortStatus values (they should all be 0 except
515 if (temp & PORT_RESET) 631 * for PORT_POWER anyway).
516 status |= 1 << USB_PORT_FEAT_RESET; 632 */
517 if (temp & PORT_POWER) 633
518 status |= 1 << USB_PORT_FEAT_POWER; 634 if (temp & PORT_CONNECT) {
635 status |= 1 << USB_PORT_FEAT_CONNECTION;
636 // status may be from integrated TT
637 status |= ehci_port_speed(ehci, temp);
519 } 638 }
639 if (temp & PORT_PE)
640 status |= 1 << USB_PORT_FEAT_ENABLE;
641 if (temp & (PORT_SUSPEND|PORT_RESUME))
642 status |= 1 << USB_PORT_FEAT_SUSPEND;
643 if (temp & PORT_OC)
644 status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
645 if (temp & PORT_RESET)
646 status |= 1 << USB_PORT_FEAT_RESET;
647 if (temp & PORT_POWER)
648 status |= 1 << USB_PORT_FEAT_POWER;
520 649
521#ifndef EHCI_VERBOSE_DEBUG 650#ifndef EHCI_VERBOSE_DEBUG
522 if (status & ~0xffff) /* only if wPortChange is interesting */ 651 if (status & ~0xffff) /* only if wPortChange is interesting */
@@ -541,7 +670,7 @@ static int ehci_hub_control (
541 if (!wIndex || wIndex > ports) 670 if (!wIndex || wIndex > ports)
542 goto error; 671 goto error;
543 wIndex--; 672 wIndex--;
544 temp = readl (&ehci->regs->port_status [wIndex]); 673 temp = ehci_readl(ehci, status_reg);
545 if (temp & PORT_OWNER) 674 if (temp & PORT_OWNER)
546 break; 675 break;
547 676
@@ -555,13 +684,12 @@ static int ehci_hub_control (
555 goto error; 684 goto error;
556 if (device_may_wakeup(&hcd->self.root_hub->dev)) 685 if (device_may_wakeup(&hcd->self.root_hub->dev))
557 temp |= PORT_WAKE_BITS; 686 temp |= PORT_WAKE_BITS;
558 writel (temp | PORT_SUSPEND, 687 ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
559 &ehci->regs->port_status [wIndex]);
560 break; 688 break;
561 case USB_PORT_FEAT_POWER: 689 case USB_PORT_FEAT_POWER:
562 if (HCS_PPC (ehci->hcs_params)) 690 if (HCS_PPC (ehci->hcs_params))
563 writel (temp | PORT_POWER, 691 ehci_writel(ehci, temp | PORT_POWER,
564 &ehci->regs->port_status [wIndex]); 692 status_reg);
565 break; 693 break;
566 case USB_PORT_FEAT_RESET: 694 case USB_PORT_FEAT_RESET:
567 if (temp & PORT_RESUME) 695 if (temp & PORT_RESUME)
@@ -589,7 +717,7 @@ static int ehci_hub_control (
589 ehci->reset_done [wIndex] = jiffies 717 ehci->reset_done [wIndex] = jiffies
590 + msecs_to_jiffies (50); 718 + msecs_to_jiffies (50);
591 } 719 }
592 writel (temp, &ehci->regs->port_status [wIndex]); 720 ehci_writel(ehci, temp, status_reg);
593 break; 721 break;
594 722
595 /* For downstream facing ports (these): one hub port is put 723 /* For downstream facing ports (these): one hub port is put
@@ -604,13 +732,13 @@ static int ehci_hub_control (
604 ehci_quiesce(ehci); 732 ehci_quiesce(ehci);
605 ehci_halt(ehci); 733 ehci_halt(ehci);
606 temp |= selector << 16; 734 temp |= selector << 16;
607 writel (temp, &ehci->regs->port_status [wIndex]); 735 ehci_writel(ehci, temp, status_reg);
608 break; 736 break;
609 737
610 default: 738 default:
611 goto error; 739 goto error;
612 } 740 }
613 readl (&ehci->regs->command); /* unblock posted writes */ 741 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
614 break; 742 break;
615 743
616 default: 744 default: