Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.20 623 lines 17 kB view raw
1/* 2 * Copyright (C) 2001-2004 by David Brownell 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the 6 * Free Software Foundation; either version 2 of the License, or (at your 7 * option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software Foundation, 16 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19/* this file is part of ehci-hcd.c */ 20 21/*-------------------------------------------------------------------------*/ 22 23/* 24 * EHCI Root Hub ... the nonsharable stuff 25 * 26 * Registers don't need cpu_to_le32, that happens transparently 27 */ 28 29/*-------------------------------------------------------------------------*/ 30 31#ifdef CONFIG_PM 32 33static int ehci_bus_suspend (struct usb_hcd *hcd) 34{ 35 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 36 int port; 37 int mask; 38 39 if (time_before (jiffies, ehci->next_statechange)) 40 msleep(5); 41 42 port = HCS_N_PORTS (ehci->hcs_params); 43 spin_lock_irq (&ehci->lock); 44 45 /* stop schedules, clean any completed work */ 46 if (HC_IS_RUNNING(hcd->state)) { 47 ehci_quiesce (ehci); 48 hcd->state = HC_STATE_QUIESCING; 49 } 50 ehci->command = readl (&ehci->regs->command); 51 if (ehci->reclaim) 52 ehci->reclaim_ready = 1; 53 ehci_work(ehci); 54 55 /* Unlike other USB host controller types, EHCI doesn't have 56 * any notion of "global" or bus-wide suspend. The driver has 57 * to manually suspend all the active unsuspended ports, and 58 * then manually resume them in the bus_resume() routine. 59 */ 60 ehci->bus_suspended = 0; 61 while (port--) { 62 u32 __iomem *reg = &ehci->regs->port_status [port]; 63 u32 t1 = readl (reg) & ~PORT_RWC_BITS; 64 u32 t2 = t1; 65 66 /* keep track of which ports we suspend */ 67 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) && 68 !(t1 & PORT_SUSPEND)) { 69 t2 |= PORT_SUSPEND; 70 set_bit(port, &ehci->bus_suspended); 71 } 72 73 /* enable remote wakeup on all ports */ 74 if (device_may_wakeup(&hcd->self.root_hub->dev)) 75 t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; 76 else 77 t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); 78 79 if (t1 != t2) { 80 ehci_vdbg (ehci, "port %d, %08x -> %08x\n", 81 port + 1, t1, t2); 82 writel (t2, reg); 83 } 84 } 85 86 /* turn off now-idle HC */ 87 del_timer_sync (&ehci->watchdog); 88 ehci_halt (ehci); 89 hcd->state = HC_STATE_SUSPENDED; 90 91 /* allow remote wakeup */ 92 mask = INTR_MASK; 93 if (!device_may_wakeup(&hcd->self.root_hub->dev)) 94 mask &= ~STS_PCD; 95 writel(mask, &ehci->regs->intr_enable); 96 readl(&ehci->regs->intr_enable); 97 98 ehci->next_statechange = jiffies + msecs_to_jiffies(10); 99 spin_unlock_irq (&ehci->lock); 100 return 0; 101} 102 103 104/* caller has locked the root hub, and should reset/reinit on error */ 105static int ehci_bus_resume (struct usb_hcd *hcd) 106{ 107 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 108 u32 temp; 109 int i; 110 111 if (time_before (jiffies, ehci->next_statechange)) 112 msleep(5); 113 spin_lock_irq (&ehci->lock); 114 115 /* Ideally and we've got a real resume here, and no port's power 116 * was lost. (For PCI, that means Vaux was maintained.) But we 117 * could instead be restoring a swsusp snapshot -- so that BIOS was 118 * the last user of the controller, not reset/pm hardware keeping 119 * state we gave to it. 120 */ 121 temp = readl(&ehci->regs->intr_enable); 122 ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss"); 123 124 /* at least some APM implementations will try to deliver 125 * IRQs right away, so delay them until we're ready. 126 */ 127 writel(0, &ehci->regs->intr_enable); 128 129 /* re-init operational registers */ 130 writel(0, &ehci->regs->segment); 131 writel(ehci->periodic_dma, &ehci->regs->frame_list); 132 writel((u32) ehci->async->qh_dma, &ehci->regs->async_next); 133 134 /* restore CMD_RUN, framelist size, and irq threshold */ 135 writel (ehci->command, &ehci->regs->command); 136 137 /* manually resume the ports we suspended during bus_suspend() */ 138 i = HCS_N_PORTS (ehci->hcs_params); 139 while (i--) { 140 temp = readl (&ehci->regs->port_status [i]); 141 temp &= ~(PORT_RWC_BITS 142 | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); 143 if (test_bit(i, &ehci->bus_suspended) && 144 (temp & PORT_SUSPEND)) { 145 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); 146 temp |= PORT_RESUME; 147 } 148 writel (temp, &ehci->regs->port_status [i]); 149 } 150 i = HCS_N_PORTS (ehci->hcs_params); 151 mdelay (20); 152 while (i--) { 153 temp = readl (&ehci->regs->port_status [i]); 154 if (test_bit(i, &ehci->bus_suspended) && 155 (temp & PORT_SUSPEND)) { 156 temp &= ~(PORT_RWC_BITS | PORT_RESUME); 157 writel (temp, &ehci->regs->port_status [i]); 158 ehci_vdbg (ehci, "resumed port %d\n", i + 1); 159 } 160 } 161 (void) readl (&ehci->regs->command); 162 163 /* maybe re-activate the schedule(s) */ 164 temp = 0; 165 if (ehci->async->qh_next.qh) 166 temp |= CMD_ASE; 167 if (ehci->periodic_sched) 168 temp |= CMD_PSE; 169 if (temp) { 170 ehci->command |= temp; 171 writel (ehci->command, &ehci->regs->command); 172 } 173 174 ehci->next_statechange = jiffies + msecs_to_jiffies(5); 175 hcd->state = HC_STATE_RUNNING; 176 177 /* Now we can safely re-enable irqs */ 178 writel(INTR_MASK, &ehci->regs->intr_enable); 179 180 spin_unlock_irq (&ehci->lock); 181 return 0; 182} 183 184#else 185 186#define ehci_bus_suspend NULL 187#define ehci_bus_resume NULL 188 189#endif /* CONFIG_PM */ 190 191/*-------------------------------------------------------------------------*/ 192 193static int check_reset_complete ( 194 struct ehci_hcd *ehci, 195 int index, 196 int port_status 197) { 198 if (!(port_status & PORT_CONNECT)) { 199 ehci->reset_done [index] = 0; 200 return port_status; 201 } 202 203 /* if reset finished and it's still not enabled -- handoff */ 204 if (!(port_status & PORT_PE)) { 205 206 /* with integrated TT, there's nobody to hand it to! */ 207 if (ehci_is_TDI(ehci)) { 208 ehci_dbg (ehci, 209 "Failed to enable port %d on root hub TT\n", 210 index+1); 211 return port_status; 212 } 213 214 ehci_dbg (ehci, "port %d full speed --> companion\n", 215 index + 1); 216 217 // what happens if HCS_N_CC(params) == 0 ? 218 port_status |= PORT_OWNER; 219 port_status &= ~PORT_RWC_BITS; 220 writel (port_status, &ehci->regs->port_status [index]); 221 222 } else 223 ehci_dbg (ehci, "port %d high speed\n", index + 1); 224 225 return port_status; 226} 227 228/*-------------------------------------------------------------------------*/ 229 230 231/* build "status change" packet (one or two bytes) from HC registers */ 232 233static int 234ehci_hub_status_data (struct usb_hcd *hcd, char *buf) 235{ 236 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 237 u32 temp, status = 0; 238 u32 mask; 239 int ports, i, retval = 1; 240 unsigned long flags; 241 242 /* if !USB_SUSPEND, root hub timers won't get shut down ... */ 243 if (!HC_IS_RUNNING(hcd->state)) 244 return 0; 245 246 /* init status to no-changes */ 247 buf [0] = 0; 248 ports = HCS_N_PORTS (ehci->hcs_params); 249 if (ports > 7) { 250 buf [1] = 0; 251 retval++; 252 } 253 254 /* Some boards (mostly VIA?) report bogus overcurrent indications, 255 * causing massive log spam unless we completely ignore them. It 256 * may be relevant that VIA VT8235 controlers, where PORT_POWER is 257 * always set, seem to clear PORT_OCC and PORT_CSC when writing to 258 * PORT_POWER; that's surprising, but maybe within-spec. 259 */ 260 if (!ignore_oc) 261 mask = PORT_CSC | PORT_PEC | PORT_OCC; 262 else 263 mask = PORT_CSC | PORT_PEC; 264 // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND 265 266 /* no hub change reports (bit 0) for now (power, ...) */ 267 268 /* port N changes (bit N)? */ 269 spin_lock_irqsave (&ehci->lock, flags); 270 for (i = 0; i < ports; i++) { 271 temp = readl (&ehci->regs->port_status [i]); 272 if (temp & PORT_OWNER) { 273 /* don't report this in GetPortStatus */ 274 if (temp & PORT_CSC) { 275 temp &= ~PORT_RWC_BITS; 276 temp |= PORT_CSC; 277 writel (temp, &ehci->regs->port_status [i]); 278 } 279 continue; 280 } 281 if (!(temp & PORT_CONNECT)) 282 ehci->reset_done [i] = 0; 283 if ((temp & mask) != 0 284 || ((temp & PORT_RESUME) != 0 285 && time_after (jiffies, 286 ehci->reset_done [i]))) { 287 if (i < 7) 288 buf [0] |= 1 << (i + 1); 289 else 290 buf [1] |= 1 << (i - 7); 291 status = STS_PCD; 292 } 293 } 294 /* FIXME autosuspend idle root hubs */ 295 spin_unlock_irqrestore (&ehci->lock, flags); 296 return status ? retval : 0; 297} 298 299/*-------------------------------------------------------------------------*/ 300 301static void 302ehci_hub_descriptor ( 303 struct ehci_hcd *ehci, 304 struct usb_hub_descriptor *desc 305) { 306 int ports = HCS_N_PORTS (ehci->hcs_params); 307 u16 temp; 308 309 desc->bDescriptorType = 0x29; 310 desc->bPwrOn2PwrGood = 10; /* ehci 1.0, 2.3.9 says 20ms max */ 311 desc->bHubContrCurrent = 0; 312 313 desc->bNbrPorts = ports; 314 temp = 1 + (ports / 8); 315 desc->bDescLength = 7 + 2 * temp; 316 317 /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ 318 memset (&desc->bitmap [0], 0, temp); 319 memset (&desc->bitmap [temp], 0xff, temp); 320 321 temp = 0x0008; /* per-port overcurrent reporting */ 322 if (HCS_PPC (ehci->hcs_params)) 323 temp |= 0x0001; /* per-port power control */ 324 else 325 temp |= 0x0002; /* no power switching */ 326#if 0 327// re-enable when we support USB_PORT_FEAT_INDICATOR below. 328 if (HCS_INDICATOR (ehci->hcs_params)) 329 temp |= 0x0080; /* per-port indicators (LEDs) */ 330#endif 331 desc->wHubCharacteristics = (__force __u16)cpu_to_le16 (temp); 332} 333 334/*-------------------------------------------------------------------------*/ 335 336#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) 337 338static int ehci_hub_control ( 339 struct usb_hcd *hcd, 340 u16 typeReq, 341 u16 wValue, 342 u16 wIndex, 343 char *buf, 344 u16 wLength 345) { 346 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 347 int ports = HCS_N_PORTS (ehci->hcs_params); 348 u32 temp, status; 349 unsigned long flags; 350 int retval = 0; 351 unsigned selector; 352 353 /* 354 * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. 355 * HCS_INDICATOR may say we can change LEDs to off/amber/green. 356 * (track current state ourselves) ... blink for diagnostics, 357 * power, "this is the one", etc. EHCI spec supports this. 358 */ 359 360 spin_lock_irqsave (&ehci->lock, flags); 361 switch (typeReq) { 362 case ClearHubFeature: 363 switch (wValue) { 364 case C_HUB_LOCAL_POWER: 365 case C_HUB_OVER_CURRENT: 366 /* no hub-wide feature/status flags */ 367 break; 368 default: 369 goto error; 370 } 371 break; 372 case ClearPortFeature: 373 if (!wIndex || wIndex > ports) 374 goto error; 375 wIndex--; 376 temp = readl (&ehci->regs->port_status [wIndex]); 377 if (temp & PORT_OWNER) 378 break; 379 380 switch (wValue) { 381 case USB_PORT_FEAT_ENABLE: 382 writel (temp & ~PORT_PE, 383 &ehci->regs->port_status [wIndex]); 384 break; 385 case USB_PORT_FEAT_C_ENABLE: 386 writel((temp & ~PORT_RWC_BITS) | PORT_PEC, 387 &ehci->regs->port_status [wIndex]); 388 break; 389 case USB_PORT_FEAT_SUSPEND: 390 if (temp & PORT_RESET) 391 goto error; 392 if (ehci->no_selective_suspend) 393 break; 394 if (temp & PORT_SUSPEND) { 395 if ((temp & PORT_PE) == 0) 396 goto error; 397 /* resume signaling for 20 msec */ 398 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 399 writel (temp | PORT_RESUME, 400 &ehci->regs->port_status [wIndex]); 401 ehci->reset_done [wIndex] = jiffies 402 + msecs_to_jiffies (20); 403 } 404 break; 405 case USB_PORT_FEAT_C_SUSPEND: 406 /* we auto-clear this feature */ 407 break; 408 case USB_PORT_FEAT_POWER: 409 if (HCS_PPC (ehci->hcs_params)) 410 writel (temp & ~(PORT_RWC_BITS | PORT_POWER), 411 &ehci->regs->port_status [wIndex]); 412 break; 413 case USB_PORT_FEAT_C_CONNECTION: 414 writel((temp & ~PORT_RWC_BITS) | PORT_CSC, 415 &ehci->regs->port_status [wIndex]); 416 break; 417 case USB_PORT_FEAT_C_OVER_CURRENT: 418 writel((temp & ~PORT_RWC_BITS) | PORT_OCC, 419 &ehci->regs->port_status [wIndex]); 420 break; 421 case USB_PORT_FEAT_C_RESET: 422 /* GetPortStatus clears reset */ 423 break; 424 default: 425 goto error; 426 } 427 readl (&ehci->regs->command); /* unblock posted write */ 428 break; 429 case GetHubDescriptor: 430 ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) 431 buf); 432 break; 433 case GetHubStatus: 434 /* no hub-wide feature/status flags */ 435 memset (buf, 0, 4); 436 //cpu_to_le32s ((u32 *) buf); 437 break; 438 case GetPortStatus: 439 if (!wIndex || wIndex > ports) 440 goto error; 441 wIndex--; 442 status = 0; 443 temp = readl (&ehci->regs->port_status [wIndex]); 444 445 // wPortChange bits 446 if (temp & PORT_CSC) 447 status |= 1 << USB_PORT_FEAT_C_CONNECTION; 448 if (temp & PORT_PEC) 449 status |= 1 << USB_PORT_FEAT_C_ENABLE; 450 if ((temp & PORT_OCC) && !ignore_oc) 451 status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; 452 453 /* whoever resumes must GetPortStatus to complete it!! */ 454 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 460 /* stop resume signaling */ 461 temp = readl (&ehci->regs->port_status [wIndex]); 462 writel (temp & ~(PORT_RWC_BITS | PORT_RESUME), 463 &ehci->regs->port_status [wIndex]); 464 retval = handshake ( 465 &ehci->regs->port_status [wIndex], 466 PORT_RESUME, 0, 2000 /* 2msec */); 467 if (retval != 0) { 468 ehci_err (ehci, "port %d resume error %d\n", 469 wIndex + 1, retval); 470 goto error; 471 } 472 temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); 473 } 474 475 /* whoever resets must GetPortStatus to complete it!! */ 476 if ((temp & PORT_RESET) 477 && time_after (jiffies, 478 ehci->reset_done [wIndex])) { 479 status |= 1 << USB_PORT_FEAT_C_RESET; 480 ehci->reset_done [wIndex] = 0; 481 482 /* force reset to complete */ 483 writel (temp & ~(PORT_RWC_BITS | PORT_RESET), 484 &ehci->regs->port_status [wIndex]); 485 /* REVISIT: some hardware needs 550+ usec to clear 486 * this bit; seems too long to spin routinely... 487 */ 488 retval = handshake ( 489 &ehci->regs->port_status [wIndex], 490 PORT_RESET, 0, 750); 491 if (retval != 0) { 492 ehci_err (ehci, "port %d reset error %d\n", 493 wIndex + 1, retval); 494 goto error; 495 } 496 497 /* see what we found out */ 498 temp = check_reset_complete (ehci, wIndex, 499 readl (&ehci->regs->port_status [wIndex])); 500 } 501 502 // don't show wPortStatus if it's owned by a companion hc 503 if (!(temp & PORT_OWNER)) { 504 if (temp & PORT_CONNECT) { 505 status |= 1 << USB_PORT_FEAT_CONNECTION; 506 // status may be from integrated TT 507 status |= ehci_port_speed(ehci, temp); 508 } 509 if (temp & PORT_PE) 510 status |= 1 << USB_PORT_FEAT_ENABLE; 511 if (temp & (PORT_SUSPEND|PORT_RESUME)) 512 status |= 1 << USB_PORT_FEAT_SUSPEND; 513 if (temp & PORT_OC) 514 status |= 1 << USB_PORT_FEAT_OVER_CURRENT; 515 if (temp & PORT_RESET) 516 status |= 1 << USB_PORT_FEAT_RESET; 517 if (temp & PORT_POWER) 518 status |= 1 << USB_PORT_FEAT_POWER; 519 } 520 521#ifndef EHCI_VERBOSE_DEBUG 522 if (status & ~0xffff) /* only if wPortChange is interesting */ 523#endif 524 dbg_port (ehci, "GetStatus", wIndex + 1, temp); 525 // we "know" this alignment is good, caller used kmalloc()... 526 *((__le32 *) buf) = cpu_to_le32 (status); 527 break; 528 case SetHubFeature: 529 switch (wValue) { 530 case C_HUB_LOCAL_POWER: 531 case C_HUB_OVER_CURRENT: 532 /* no hub-wide feature/status flags */ 533 break; 534 default: 535 goto error; 536 } 537 break; 538 case SetPortFeature: 539 selector = wIndex >> 8; 540 wIndex &= 0xff; 541 if (!wIndex || wIndex > ports) 542 goto error; 543 wIndex--; 544 temp = readl (&ehci->regs->port_status [wIndex]); 545 if (temp & PORT_OWNER) 546 break; 547 548 temp &= ~PORT_RWC_BITS; 549 switch (wValue) { 550 case USB_PORT_FEAT_SUSPEND: 551 if (ehci->no_selective_suspend) 552 break; 553 if ((temp & PORT_PE) == 0 554 || (temp & PORT_RESET) != 0) 555 goto error; 556 if (device_may_wakeup(&hcd->self.root_hub->dev)) 557 temp |= PORT_WAKE_BITS; 558 writel (temp | PORT_SUSPEND, 559 &ehci->regs->port_status [wIndex]); 560 break; 561 case USB_PORT_FEAT_POWER: 562 if (HCS_PPC (ehci->hcs_params)) 563 writel (temp | PORT_POWER, 564 &ehci->regs->port_status [wIndex]); 565 break; 566 case USB_PORT_FEAT_RESET: 567 if (temp & PORT_RESUME) 568 goto error; 569 /* line status bits may report this as low speed, 570 * which can be fine if this root hub has a 571 * transaction translator built in. 572 */ 573 if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT 574 && !ehci_is_TDI(ehci) 575 && PORT_USB11 (temp)) { 576 ehci_dbg (ehci, 577 "port %d low speed --> companion\n", 578 wIndex + 1); 579 temp |= PORT_OWNER; 580 } else { 581 ehci_vdbg (ehci, "port %d reset\n", wIndex + 1); 582 temp |= PORT_RESET; 583 temp &= ~PORT_PE; 584 585 /* 586 * caller must wait, then call GetPortStatus 587 * usb 2.0 spec says 50 ms resets on root 588 */ 589 ehci->reset_done [wIndex] = jiffies 590 + msecs_to_jiffies (50); 591 } 592 writel (temp, &ehci->regs->port_status [wIndex]); 593 break; 594 595 /* For downstream facing ports (these): one hub port is put 596 * into test mode according to USB2 11.24.2.13, then the hub 597 * must be reset (which for root hub now means rmmod+modprobe, 598 * or else system reboot). See EHCI 2.3.9 and 4.14 for info 599 * about the EHCI-specific stuff. 600 */ 601 case USB_PORT_FEAT_TEST: 602 if (!selector || selector > 5) 603 goto error; 604 ehci_quiesce(ehci); 605 ehci_halt(ehci); 606 temp |= selector << 16; 607 writel (temp, &ehci->regs->port_status [wIndex]); 608 break; 609 610 default: 611 goto error; 612 } 613 readl (&ehci->regs->command); /* unblock posted writes */ 614 break; 615 616 default: 617error: 618 /* "stall" on error */ 619 retval = -EPIPE; 620 } 621 spin_unlock_irqrestore (&ehci->lock, flags); 622 return retval; 623}