1 /* 2 * Copyright (c) 2001-2002 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 33 static int ehci_hub_suspend (struct usb_hcd *hcd) 34 { 35 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 36 int port; 37 38 if (time_before (jiffies, ehci->next_statechange)) 39 msleep(5); 40 41 port = HCS_N_PORTS (ehci->hcs_params); 42 spin_lock_irq (&ehci->lock); 43 44 /* stop schedules, clean any completed work */ 45 if (HC_IS_RUNNING(hcd->state)) { 46 ehci_quiesce (ehci); 47 hcd->state = HC_STATE_QUIESCING; 48 } 49 ehci->command = readl (&ehci->regs->command); 50 if (ehci->reclaim) 51 ehci->reclaim_ready = 1; 52 ehci_work(ehci, NULL); 53 54 /* suspend any active/unsuspended ports, maybe allow wakeup */ 55 while (port--) { 56 u32 __iomem *reg = &ehci->regs->port_status [port]; 57 u32 t1 = readl (reg); 58 u32 t2 = t1; 59 60 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) 61 t2 |= PORT_SUSPEND; 62 if (hcd->remote_wakeup) 63 t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; 64 else 65 t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); 66 67 if (t1 != t2) { 68 ehci_vdbg (ehci, "port %d, %08x -> %08x\n", 69 port + 1, t1, t2); 70 writel (t2, reg); 71 } 72 } 73 74 /* turn off now-idle HC */ 75 ehci_halt (ehci); 76 hcd->state = HC_STATE_SUSPENDED; 77 78 ehci->next_statechange = jiffies + msecs_to_jiffies(10); 79 spin_unlock_irq (&ehci->lock); 80 return 0; 81 } 82 83 84 /* caller has locked the root hub, and should reset/reinit on error */ 85 static int ehci_hub_resume (struct usb_hcd *hcd) 86 { 87 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 88 u32 temp; 89 int i; 90 int intr_enable; 91 92 if (time_before (jiffies, ehci->next_statechange)) 93 msleep(5); 94 spin_lock_irq (&ehci->lock); 95 96 /* re-init operational registers in case we lost power */ 97 if (readl (&ehci->regs->intr_enable) == 0) { 98 /* at least some APM implementations will try to deliver 99 * IRQs right away, so delay them until we're ready. 100 */ 101 intr_enable = 1; 102 writel (0, &ehci->regs->segment); 103 writel (ehci->periodic_dma, &ehci->regs->frame_list); 104 writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); 105 } else 106 intr_enable = 0; 107 ehci_dbg(ehci, "resume root hub%s\n", 108 intr_enable ? " after power loss" : ""); 109 110 /* restore CMD_RUN, framelist size, and irq threshold */ 111 writel (ehci->command, &ehci->regs->command); 112 113 /* take ports out of suspend */ 114 i = HCS_N_PORTS (ehci->hcs_params); 115 while (i--) { 116 temp = readl (&ehci->regs->port_status [i]); 117 temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); 118 if (temp & PORT_SUSPEND) { 119 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); 120 temp |= PORT_RESUME; 121 } 122 writel (temp, &ehci->regs->port_status [i]); 123 } 124 i = HCS_N_PORTS (ehci->hcs_params); 125 mdelay (20); 126 while (i--) { 127 temp = readl (&ehci->regs->port_status [i]); 128 if ((temp & PORT_SUSPEND) == 0) 129 continue; 130 temp &= ~PORT_RESUME; 131 writel (temp, &ehci->regs->port_status [i]); 132 ehci_vdbg (ehci, "resumed port %d\n", i + 1); 133 } 134 (void) readl (&ehci->regs->command); 135 136 /* maybe re-activate the schedule(s) */ 137 temp = 0; 138 if (ehci->async->qh_next.qh) 139 temp |= CMD_ASE; 140 if (ehci->periodic_sched) 141 temp |= CMD_PSE; 142 if (temp) { 143 ehci->command |= temp; 144 writel (ehci->command, &ehci->regs->command); 145 } 146 147 ehci->next_statechange = jiffies + msecs_to_jiffies(5); 148 hcd->state = HC_STATE_RUNNING; 149 150 /* Now we can safely re-enable irqs */ 151 if (intr_enable) 152 writel (INTR_MASK, &ehci->regs->intr_enable); 153 154 spin_unlock_irq (&ehci->lock); 155 return 0; 156 } 157 158 #else 159 160 #define ehci_hub_suspend NULL 161 #define ehci_hub_resume NULL 162 163 #endif /* CONFIG_PM */ 164 165 /*-------------------------------------------------------------------------*/ 166 167 static int check_reset_complete ( 168 struct ehci_hcd *ehci, 169 int index, 170 int port_status 171 ) { 172 if (!(port_status & PORT_CONNECT)) { 173 ehci->reset_done [index] = 0; 174 return port_status; 175 } 176 177 /* if reset finished and it's still not enabled -- handoff */ 178 if (!(port_status & PORT_PE)) { 179 180 /* with integrated TT, there's nobody to hand it to! */ 181 if (ehci_is_TDI(ehci)) { 182 ehci_dbg (ehci, 183 "Failed to enable port %d on root hub TT\n", 184 index+1); 185 return port_status; 186 } 187 188 ehci_dbg (ehci, "port %d full speed --> companion\n", 189 index + 1); 190 191 // what happens if HCS_N_CC(params) == 0 ? 192 port_status |= PORT_OWNER; 193 writel (port_status, &ehci->regs->port_status [index]); 194 195 } else 196 ehci_dbg (ehci, "port %d high speed\n", index + 1); 197 198 return port_status; 199 } 200 201 /*-------------------------------------------------------------------------*/ 202 203 204 /* build "status change" packet (one or two bytes) from HC registers */ 205 206 static int 207 ehci_hub_status_data (struct usb_hcd *hcd, char *buf) 208 { 209 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 210 u32 temp, status = 0; 211 int ports, i, retval = 1; 212 unsigned long flags; 213 214 /* if !USB_SUSPEND, root hub timers won't get shut down ... */ 215 if (!HC_IS_RUNNING(hcd->state)) 216 return 0; 217 218 /* init status to no-changes */ 219 buf [0] = 0; 220 ports = HCS_N_PORTS (ehci->hcs_params); 221 if (ports > 7) { 222 buf [1] = 0; 223 retval++; 224 } 225 226 /* no hub change reports (bit 0) for now (power, ...) */ 227 228 /* port N changes (bit N)? */ 229 spin_lock_irqsave (&ehci->lock, flags); 230 for (i = 0; i < ports; i++) { 231 temp = readl (&ehci->regs->port_status [i]); 232 if (temp & PORT_OWNER) { 233 /* don't report this in GetPortStatus */ 234 if (temp & PORT_CSC) { 235 temp &= ~PORT_CSC; 236 writel (temp, &ehci->regs->port_status [i]); 237 } 238 continue; 239 } 240 if (!(temp & PORT_CONNECT)) 241 ehci->reset_done [i] = 0; 242 if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0 243 // PORT_STAT_C_SUSPEND? 244 || ((temp & PORT_RESUME) != 0 245 && time_after (jiffies, 246 ehci->reset_done [i]))) { 247 if (i < 7) 248 buf [0] |= 1 << (i + 1); 249 else 250 buf [1] |= 1 << (i - 7); 251 status = STS_PCD; 252 } 253 } 254 /* FIXME autosuspend idle root hubs */ 255 spin_unlock_irqrestore (&ehci->lock, flags); 256 return status ? retval : 0; 257 } 258 259 /*-------------------------------------------------------------------------*/ 260 261 static void 262 ehci_hub_descriptor ( 263 struct ehci_hcd *ehci, 264 struct usb_hub_descriptor *desc 265 ) { 266 int ports = HCS_N_PORTS (ehci->hcs_params); 267 u16 temp; 268 269 desc->bDescriptorType = 0x29; 270 desc->bPwrOn2PwrGood = 10; /* ehci 1.0, 2.3.9 says 20ms max */ 271 desc->bHubContrCurrent = 0; 272 273 desc->bNbrPorts = ports; 274 temp = 1 + (ports / 8); 275 desc->bDescLength = 7 + 2 * temp; 276 277 /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ 278 memset (&desc->bitmap [0], 0, temp); 279 memset (&desc->bitmap [temp], 0xff, temp); 280 281 temp = 0x0008; /* per-port overcurrent reporting */ 282 if (HCS_PPC (ehci->hcs_params)) 283 temp |= 0x0001; /* per-port power control */ 284 #if 0 285 // re-enable when we support USB_PORT_FEAT_INDICATOR below. 286 if (HCS_INDICATOR (ehci->hcs_params)) 287 temp |= 0x0080; /* per-port indicators (LEDs) */ 288 #endif 289 desc->wHubCharacteristics = (__force __u16)cpu_to_le16 (temp); 290 } 291 292 /*-------------------------------------------------------------------------*/ 293 294 #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) 295 296 static int ehci_hub_control ( 297 struct usb_hcd *hcd, 298 u16 typeReq, 299 u16 wValue, 300 u16 wIndex, 301 char *buf, 302 u16 wLength 303 ) { 304 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 305 int ports = HCS_N_PORTS (ehci->hcs_params); 306 u32 temp, status; 307 unsigned long flags; 308 int retval = 0; 309 310 /* 311 * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. 312 * HCS_INDICATOR may say we can change LEDs to off/amber/green. 313 * (track current state ourselves) ... blink for diagnostics, 314 * power, "this is the one", etc. EHCI spec supports this. 315 */ 316 317 spin_lock_irqsave (&ehci->lock, flags); 318 switch (typeReq) { 319 case ClearHubFeature: 320 switch (wValue) { 321 case C_HUB_LOCAL_POWER: 322 case C_HUB_OVER_CURRENT: 323 /* no hub-wide feature/status flags */ 324 break; 325 default: 326 goto error; 327 } 328 break; 329 case ClearPortFeature: 330 if (!wIndex || wIndex > ports) 331 goto error; 332 wIndex--; 333 temp = readl (&ehci->regs->port_status [wIndex]); 334 if (temp & PORT_OWNER) 335 break; 336 337 switch (wValue) { 338 case USB_PORT_FEAT_ENABLE: 339 writel (temp & ~PORT_PE, 340 &ehci->regs->port_status [wIndex]); 341 break; 342 case USB_PORT_FEAT_C_ENABLE: 343 writel (temp | PORT_PEC, 344 &ehci->regs->port_status [wIndex]); 345 break; 346 case USB_PORT_FEAT_SUSPEND: 347 if (temp & PORT_RESET) 348 goto error; 349 if (temp & PORT_SUSPEND) { 350 if ((temp & PORT_PE) == 0) 351 goto error; 352 /* resume signaling for 20 msec */ 353 writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME, 354 &ehci->regs->port_status [wIndex]); 355 ehci->reset_done [wIndex] = jiffies 356 + msecs_to_jiffies (20); 357 } 358 break; 359 case USB_PORT_FEAT_C_SUSPEND: 360 /* we auto-clear this feature */ 361 break; 362 case USB_PORT_FEAT_POWER: 363 if (HCS_PPC (ehci->hcs_params)) 364 writel (temp & ~PORT_POWER, 365 &ehci->regs->port_status [wIndex]); 366 break; 367 case USB_PORT_FEAT_C_CONNECTION: 368 writel (temp | PORT_CSC, 369 &ehci->regs->port_status [wIndex]); 370 break; 371 case USB_PORT_FEAT_C_OVER_CURRENT: 372 writel (temp | PORT_OCC, 373 &ehci->regs->port_status [wIndex]); 374 break; 375 case USB_PORT_FEAT_C_RESET: 376 /* GetPortStatus clears reset */ 377 break; 378 default: 379 goto error; 380 } 381 readl (&ehci->regs->command); /* unblock posted write */ 382 break; 383 case GetHubDescriptor: 384 ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) 385 buf); 386 break; 387 case GetHubStatus: 388 /* no hub-wide feature/status flags */ 389 memset (buf, 0, 4); 390 //cpu_to_le32s ((u32 *) buf); 391 break; 392 case GetPortStatus: 393 if (!wIndex || wIndex > ports) 394 goto error; 395 wIndex--; 396 status = 0; 397 temp = readl (&ehci->regs->port_status [wIndex]); 398 399 // wPortChange bits 400 if (temp & PORT_CSC) 401 status |= 1 << USB_PORT_FEAT_C_CONNECTION; 402 if (temp & PORT_PEC) 403 status |= 1 << USB_PORT_FEAT_C_ENABLE; 404 if (temp & PORT_OCC) 405 status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; 406 407 /* whoever resumes must GetPortStatus to complete it!! */ 408 if ((temp & PORT_RESUME) 409 && time_after (jiffies, 410 ehci->reset_done [wIndex])) { 411 status |= 1 << USB_PORT_FEAT_C_SUSPEND; 412 ehci->reset_done [wIndex] = 0; 413 414 /* stop resume signaling */ 415 temp = readl (&ehci->regs->port_status [wIndex]); 416 writel (temp & ~PORT_RESUME, 417 &ehci->regs->port_status [wIndex]); 418 retval = handshake ( 419 &ehci->regs->port_status [wIndex], 420 PORT_RESUME, 0, 2000 /* 2msec */); 421 if (retval != 0) { 422 ehci_err (ehci, "port %d resume error %d\n", 423 wIndex + 1, retval); 424 goto error; 425 } 426 temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); 427 } 428 429 /* whoever resets must GetPortStatus to complete it!! */ 430 if ((temp & PORT_RESET) 431 && time_after (jiffies, 432 ehci->reset_done [wIndex])) { 433 status |= 1 << USB_PORT_FEAT_C_RESET; 434 ehci->reset_done [wIndex] = 0; 435 436 /* force reset to complete */ 437 writel (temp & ~PORT_RESET, 438 &ehci->regs->port_status [wIndex]); 439 retval = handshake ( 440 &ehci->regs->port_status [wIndex], 441 PORT_RESET, 0, 500); 442 if (retval != 0) { 443 ehci_err (ehci, "port %d reset error %d\n", 444 wIndex + 1, retval); 445 goto error; 446 } 447 448 /* see what we found out */ 449 temp = check_reset_complete (ehci, wIndex, 450 readl (&ehci->regs->port_status [wIndex])); 451 } 452 453 // don't show wPortStatus if it's owned by a companion hc 454 if (!(temp & PORT_OWNER)) { 455 if (temp & PORT_CONNECT) { 456 status |= 1 << USB_PORT_FEAT_CONNECTION; 457 // status may be from integrated TT 458 status |= ehci_port_speed(ehci, temp); 459 } 460 if (temp & PORT_PE) 461 status |= 1 << USB_PORT_FEAT_ENABLE; 462 if (temp & (PORT_SUSPEND|PORT_RESUME)) 463 status |= 1 << USB_PORT_FEAT_SUSPEND; 464 if (temp & PORT_OC) 465 status |= 1 << USB_PORT_FEAT_OVER_CURRENT; 466 if (temp & PORT_RESET) 467 status |= 1 << USB_PORT_FEAT_RESET; 468 if (temp & PORT_POWER) 469 status |= 1 << USB_PORT_FEAT_POWER; 470 } 471 472 #ifndef EHCI_VERBOSE_DEBUG 473 if (status & ~0xffff) /* only if wPortChange is interesting */ 474 #endif 475 dbg_port (ehci, "GetStatus", wIndex + 1, temp); 476 // we "know" this alignment is good, caller used kmalloc()... 477 *((__le32 *) buf) = cpu_to_le32 (status); 478 break; 479 case SetHubFeature: 480 switch (wValue) { 481 case C_HUB_LOCAL_POWER: 482 case C_HUB_OVER_CURRENT: 483 /* no hub-wide feature/status flags */ 484 break; 485 default: 486 goto error; 487 } 488 break; 489 case SetPortFeature: 490 if (!wIndex || wIndex > ports) 491 goto error; 492 wIndex--; 493 temp = readl (&ehci->regs->port_status [wIndex]); 494 if (temp & PORT_OWNER) 495 break; 496 497 switch (wValue) { 498 case USB_PORT_FEAT_SUSPEND: 499 if ((temp & PORT_PE) == 0 500 || (temp & PORT_RESET) != 0) 501 goto error; 502 if (hcd->remote_wakeup) 503 temp |= PORT_WAKE_BITS; 504 writel (temp | PORT_SUSPEND, 505 &ehci->regs->port_status [wIndex]); 506 break; 507 case USB_PORT_FEAT_POWER: 508 if (HCS_PPC (ehci->hcs_params)) 509 writel (temp | PORT_POWER, 510 &ehci->regs->port_status [wIndex]); 511 break; 512 case USB_PORT_FEAT_RESET: 513 if (temp & PORT_RESUME) 514 goto error; 515 /* line status bits may report this as low speed, 516 * which can be fine if this root hub has a 517 * transaction translator built in. 518 */ 519 if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT 520 && !ehci_is_TDI(ehci) 521 && PORT_USB11 (temp)) { 522 ehci_dbg (ehci, 523 "port %d low speed --> companion\n", 524 wIndex + 1); 525 temp |= PORT_OWNER; 526 } else { 527 ehci_vdbg (ehci, "port %d reset\n", wIndex + 1); 528 temp |= PORT_RESET; 529 temp &= ~PORT_PE; 530 531 /* 532 * caller must wait, then call GetPortStatus 533 * usb 2.0 spec says 50 ms resets on root 534 */ 535 ehci->reset_done [wIndex] = jiffies 536 + msecs_to_jiffies (50); 537 } 538 writel (temp, &ehci->regs->port_status [wIndex]); 539 break; 540 default: 541 goto error; 542 } 543 readl (&ehci->regs->command); /* unblock posted writes */ 544 break; 545 546 default: 547 error: 548 /* "stall" on error */ 549 retval = -EPIPE; 550 } 551 spin_unlock_irqrestore (&ehci->lock, flags); 552 return retval; 553 } 554