1 /** @file 2 3 The EHCI register operation routines. 4 5 Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 17 #include "Ehci.h" 18 19 20 /** 21 Read EHCI capability register. 22 23 @param Ehc The EHCI device. 24 @param Offset Capability register address. 25 26 @return The register content read. 27 @retval If err, return 0xffff. 28 29 **/ 30 UINT32 31 EhcReadCapRegister ( 32 IN USB2_HC_DEV *Ehc, 33 IN UINT32 Offset 34 ) 35 { 36 UINT32 Data; 37 EFI_STATUS Status; 38 39 Status = Ehc->PciIo->Mem.Read ( 40 Ehc->PciIo, 41 EfiPciIoWidthUint32, 42 EHC_BAR_INDEX, 43 (UINT64) Offset, 44 1, 45 &Data 46 ); 47 48 if (EFI_ERROR (Status)) { 49 DEBUG ((EFI_D_ERROR, "EhcReadCapRegister: Pci Io read error - %r at %d\n", Status, Offset)); 50 Data = 0xFFFF; 51 } 52 53 return Data; 54 } 55 56 /** 57 Read EHCI debug port register. 58 59 @param Ehc The EHCI device. 60 @param Offset Debug port register offset. 61 62 @return The register content read. 63 @retval If err, return 0xffff. 64 65 **/ 66 UINT32 67 EhcReadDbgRegister ( 68 IN USB2_HC_DEV *Ehc, 69 IN UINT32 Offset 70 ) 71 { 72 UINT32 Data; 73 EFI_STATUS Status; 74 75 Status = Ehc->PciIo->Mem.Read ( 76 Ehc->PciIo, 77 EfiPciIoWidthUint32, 78 Ehc->DebugPortBarNum, 79 (UINT64) (Ehc->DebugPortOffset + Offset), 80 1, 81 &Data 82 ); 83 84 if (EFI_ERROR (Status)) { 85 DEBUG ((EFI_D_ERROR, "EhcReadDbgRegister: Pci Io read error - %r at %d\n", Status, Offset)); 86 Data = 0xFFFF; 87 } 88 89 return Data; 90 } 91 92 93 /** 94 Read EHCI Operation register. 95 96 @param Ehc The EHCI device. 97 @param Offset The operation register offset. 98 99 @return The register content read. 100 @retval If err, return 0xffff. 101 102 **/ 103 UINT32 104 EhcReadOpReg ( 105 IN USB2_HC_DEV *Ehc, 106 IN UINT32 Offset 107 ) 108 { 109 UINT32 Data; 110 EFI_STATUS Status; 111 112 ASSERT (Ehc->CapLen != 0); 113 114 Status = Ehc->PciIo->Mem.Read ( 115 Ehc->PciIo, 116 EfiPciIoWidthUint32, 117 EHC_BAR_INDEX, 118 (UINT64) (Ehc->CapLen + Offset), 119 1, 120 &Data 121 ); 122 123 if (EFI_ERROR (Status)) { 124 DEBUG ((EFI_D_ERROR, "EhcReadOpReg: Pci Io Read error - %r at %d\n", Status, Offset)); 125 Data = 0xFFFF; 126 } 127 128 return Data; 129 } 130 131 132 /** 133 Write the data to the EHCI operation register. 134 135 @param Ehc The EHCI device. 136 @param Offset EHCI operation register offset. 137 @param Data The data to write. 138 139 **/ 140 VOID 141 EhcWriteOpReg ( 142 IN USB2_HC_DEV *Ehc, 143 IN UINT32 Offset, 144 IN UINT32 Data 145 ) 146 { 147 EFI_STATUS Status; 148 149 ASSERT (Ehc->CapLen != 0); 150 151 Status = Ehc->PciIo->Mem.Write ( 152 Ehc->PciIo, 153 EfiPciIoWidthUint32, 154 EHC_BAR_INDEX, 155 (UINT64) (Ehc->CapLen + Offset), 156 1, 157 &Data 158 ); 159 160 if (EFI_ERROR (Status)) { 161 DEBUG ((EFI_D_ERROR, "EhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset)); 162 } 163 } 164 165 166 /** 167 Set one bit of the operational register while keeping other bits. 168 169 @param Ehc The EHCI device. 170 @param Offset The offset of the operational register. 171 @param Bit The bit mask of the register to set. 172 173 **/ 174 VOID 175 EhcSetOpRegBit ( 176 IN USB2_HC_DEV *Ehc, 177 IN UINT32 Offset, 178 IN UINT32 Bit 179 ) 180 { 181 UINT32 Data; 182 183 Data = EhcReadOpReg (Ehc, Offset); 184 Data |= Bit; 185 EhcWriteOpReg (Ehc, Offset, Data); 186 } 187 188 189 /** 190 Clear one bit of the operational register while keeping other bits. 191 192 @param Ehc The EHCI device. 193 @param Offset The offset of the operational register. 194 @param Bit The bit mask of the register to clear. 195 196 **/ 197 VOID 198 EhcClearOpRegBit ( 199 IN USB2_HC_DEV *Ehc, 200 IN UINT32 Offset, 201 IN UINT32 Bit 202 ) 203 { 204 UINT32 Data; 205 206 Data = EhcReadOpReg (Ehc, Offset); 207 Data &= ~Bit; 208 EhcWriteOpReg (Ehc, Offset, Data); 209 } 210 211 212 /** 213 Wait the operation register's bit as specified by Bit 214 to become set (or clear). 215 216 @param Ehc The EHCI device. 217 @param Offset The offset of the operation register. 218 @param Bit The bit of the register to wait for. 219 @param WaitToSet Wait the bit to set or clear. 220 @param Timeout The time to wait before abort (in millisecond). 221 222 @retval EFI_SUCCESS The bit successfully changed by host controller. 223 @retval EFI_TIMEOUT The time out occurred. 224 225 **/ 226 EFI_STATUS 227 EhcWaitOpRegBit ( 228 IN USB2_HC_DEV *Ehc, 229 IN UINT32 Offset, 230 IN UINT32 Bit, 231 IN BOOLEAN WaitToSet, 232 IN UINT32 Timeout 233 ) 234 { 235 UINT32 Index; 236 237 for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) { 238 if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) { 239 return EFI_SUCCESS; 240 } 241 242 gBS->Stall (EHC_SYNC_POLL_INTERVAL); 243 } 244 245 return EFI_TIMEOUT; 246 } 247 248 249 /** 250 Add support for UEFI Over Legacy (UoL) feature, stop 251 the legacy USB SMI support. 252 253 @param Ehc The EHCI device. 254 255 **/ 256 VOID 257 EhcClearLegacySupport ( 258 IN USB2_HC_DEV *Ehc 259 ) 260 { 261 UINT32 ExtendCap; 262 EFI_PCI_IO_PROTOCOL *PciIo; 263 UINT32 Value; 264 UINT32 TimeOut; 265 266 DEBUG ((EFI_D_INFO, "EhcClearLegacySupport: called to clear legacy support\n")); 267 268 PciIo = Ehc->PciIo; 269 ExtendCap = (Ehc->HcCapParams >> 8) & 0xFF; 270 271 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); 272 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value); 273 274 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); 275 Value |= (0x1 << 24); 276 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); 277 278 TimeOut = 40; 279 while (TimeOut-- != 0) { 280 gBS->Stall (500); 281 282 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); 283 284 if ((Value & 0x01010000) == 0x01000000) { 285 break; 286 } 287 } 288 289 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); 290 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value); 291 } 292 293 294 295 /** 296 Set door bell and wait it to be ACKed by host controller. 297 This function is used to synchronize with the hardware. 298 299 @param Ehc The EHCI device. 300 @param Timeout The time to wait before abort (in millisecond, ms). 301 302 @retval EFI_SUCCESS Synchronized with the hardware. 303 @retval EFI_TIMEOUT Time out happened while waiting door bell to set. 304 305 **/ 306 EFI_STATUS 307 EhcSetAndWaitDoorBell ( 308 IN USB2_HC_DEV *Ehc, 309 IN UINT32 Timeout 310 ) 311 { 312 EFI_STATUS Status; 313 UINT32 Data; 314 315 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_IAAD); 316 317 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_IAA, TRUE, Timeout); 318 319 // 320 // ACK the IAA bit in USBSTS register. Make sure other 321 // interrupt bits are not ACKed. These bits are WC (Write Clean). 322 // 323 Data = EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET); 324 Data &= ~USBSTS_INTACK_MASK; 325 Data |= USBSTS_IAA; 326 327 EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, Data); 328 329 return Status; 330 } 331 332 333 /** 334 Clear all the interrutp status bits, these bits 335 are Write-Clean. 336 337 @param Ehc The EHCI device. 338 339 **/ 340 VOID 341 EhcAckAllInterrupt ( 342 IN USB2_HC_DEV *Ehc 343 ) 344 { 345 EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, USBSTS_INTACK_MASK); 346 } 347 348 349 /** 350 Enable the periodic schedule then wait EHC to 351 actually enable it. 352 353 @param Ehc The EHCI device. 354 @param Timeout The time to wait before abort (in millisecond, ms). 355 356 @retval EFI_SUCCESS The periodical schedule is enabled. 357 @retval EFI_TIMEOUT Time out happened while enabling periodic schedule. 358 359 **/ 360 EFI_STATUS 361 EhcEnablePeriodSchd ( 362 IN USB2_HC_DEV *Ehc, 363 IN UINT32 Timeout 364 ) 365 { 366 EFI_STATUS Status; 367 368 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD); 369 370 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, TRUE, Timeout); 371 return Status; 372 } 373 374 375 /** 376 Disable periodic schedule. 377 378 @param Ehc The EHCI device. 379 @param Timeout Time to wait before abort (in millisecond, ms). 380 381 @retval EFI_SUCCESS Periodic schedule is disabled. 382 @retval EFI_DEVICE_ERROR Fail to disable periodic schedule. 383 384 **/ 385 EFI_STATUS 386 EhcDisablePeriodSchd ( 387 IN USB2_HC_DEV *Ehc, 388 IN UINT32 Timeout 389 ) 390 { 391 EFI_STATUS Status; 392 393 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD); 394 395 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, FALSE, Timeout); 396 return Status; 397 } 398 399 400 401 /** 402 Enable asynchrounous schedule. 403 404 @param Ehc The EHCI device. 405 @param Timeout Time to wait before abort. 406 407 @retval EFI_SUCCESS The EHCI asynchronous schedule is enabled. 408 @return Others Failed to enable the asynchronous scheudle. 409 410 **/ 411 EFI_STATUS 412 EhcEnableAsyncSchd ( 413 IN USB2_HC_DEV *Ehc, 414 IN UINT32 Timeout 415 ) 416 { 417 EFI_STATUS Status; 418 419 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC); 420 421 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, TRUE, Timeout); 422 return Status; 423 } 424 425 426 427 /** 428 Disable asynchrounous schedule. 429 430 @param Ehc The EHCI device. 431 @param Timeout Time to wait before abort (in millisecond, ms). 432 433 @retval EFI_SUCCESS The asynchronous schedule is disabled. 434 @return Others Failed to disable the asynchronous schedule. 435 436 **/ 437 EFI_STATUS 438 EhcDisableAsyncSchd ( 439 IN USB2_HC_DEV *Ehc, 440 IN UINT32 Timeout 441 ) 442 { 443 EFI_STATUS Status; 444 445 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC); 446 447 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, FALSE, Timeout); 448 return Status; 449 } 450 451 452 453 /** 454 Whether Ehc is halted. 455 456 @param Ehc The EHCI device. 457 458 @retval TRUE The controller is halted. 459 @retval FALSE It isn't halted. 460 461 **/ 462 BOOLEAN 463 EhcIsHalt ( 464 IN USB2_HC_DEV *Ehc 465 ) 466 { 467 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT); 468 } 469 470 471 /** 472 Whether system error occurred. 473 474 @param Ehc The EHCI device. 475 476 @return TRUE System error happened. 477 @return FALSE No system error. 478 479 **/ 480 BOOLEAN 481 EhcIsSysError ( 482 IN USB2_HC_DEV *Ehc 483 ) 484 { 485 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR); 486 } 487 488 489 /** 490 Reset the host controller. 491 492 @param Ehc The EHCI device. 493 @param Timeout Time to wait before abort (in millisecond, ms). 494 495 @retval EFI_SUCCESS The host controller is reset. 496 @return Others Failed to reset the host. 497 498 **/ 499 EFI_STATUS 500 EhcResetHC ( 501 IN USB2_HC_DEV *Ehc, 502 IN UINT32 Timeout 503 ) 504 { 505 EFI_STATUS Status; 506 507 // 508 // Host can only be reset when it is halt. If not so, halt it 509 // 510 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) { 511 Status = EhcHaltHC (Ehc, Timeout); 512 513 if (EFI_ERROR (Status)) { 514 return Status; 515 } 516 } 517 518 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET); 519 Status = EhcWaitOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET, FALSE, Timeout); 520 return Status; 521 } 522 523 524 /** 525 Halt the host controller. 526 527 @param Ehc The EHCI device. 528 @param Timeout Time to wait before abort. 529 530 @retval EFI_SUCCESS The EHCI is halt. 531 @retval EFI_TIMEOUT Failed to halt the controller before Timeout. 532 533 **/ 534 EFI_STATUS 535 EhcHaltHC ( 536 IN USB2_HC_DEV *Ehc, 537 IN UINT32 Timeout 538 ) 539 { 540 EFI_STATUS Status; 541 542 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN); 543 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, TRUE, Timeout); 544 return Status; 545 } 546 547 548 /** 549 Set the EHCI to run. 550 551 @param Ehc The EHCI device. 552 @param Timeout Time to wait before abort. 553 554 @retval EFI_SUCCESS The EHCI is running. 555 @return Others Failed to set the EHCI to run. 556 557 **/ 558 EFI_STATUS 559 EhcRunHC ( 560 IN USB2_HC_DEV *Ehc, 561 IN UINT32 Timeout 562 ) 563 { 564 EFI_STATUS Status; 565 566 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN); 567 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, FALSE, Timeout); 568 return Status; 569 } 570 571 572 /** 573 Initialize the HC hardware. 574 EHCI spec lists the five things to do to initialize the hardware: 575 1. Program CTRLDSSEGMENT 576 2. Set USBINTR to enable interrupts 577 3. Set periodic list base 578 4. Set USBCMD, interrupt threshold, frame list size etc 579 5. Write 1 to CONFIGFLAG to route all ports to EHCI 580 581 @param Ehc The EHCI device. 582 583 @return EFI_SUCCESS The EHCI has come out of halt state. 584 @return EFI_TIMEOUT Time out happened. 585 586 **/ 587 EFI_STATUS 588 EhcInitHC ( 589 IN USB2_HC_DEV *Ehc 590 ) 591 { 592 EFI_STATUS Status; 593 UINT32 Index; 594 UINT32 RegVal; 595 596 // This ASSERT crashes the BeagleBoard. There is some issue in the USB stack. 597 // This ASSERT needs to be removed so the BeagleBoard will boot. When we fix 598 // the USB stack we can put this ASSERT back in 599 // ASSERT (EhcIsHalt (Ehc)); 600 601 // 602 // Allocate the periodic frame and associated memeory 603 // management facilities if not already done. 604 // 605 if (Ehc->PeriodFrame != NULL) { 606 EhcFreeSched (Ehc); 607 } 608 609 Status = EhcInitSched (Ehc); 610 611 if (EFI_ERROR (Status)) { 612 return Status; 613 } 614 615 // 616 // 1. Clear USBINTR to disable all the interrupt. UEFI works by polling 617 // 618 EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0); 619 620 // 621 // 2. Start the Host Controller 622 // 623 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN); 624 625 // 626 // 3. Power up all ports if EHCI has Port Power Control (PPC) support 627 // 628 if (Ehc->HcStructParams & HCSP_PPC) { 629 for (Index = 0; Index < (UINT8) (Ehc->HcStructParams & HCSP_NPORTS); Index++) { 630 // 631 // Do not clear port status bits on initialization. Otherwise devices will 632 // not enumerate properly at startup. 633 // 634 RegVal = EhcReadOpReg(Ehc, (UINT32)(EHC_PORT_STAT_OFFSET + (4 * Index))); 635 RegVal &= ~PORTSC_CHANGE_MASK; 636 RegVal |= PORTSC_POWER; 637 EhcWriteOpReg (Ehc, (UINT32) (EHC_PORT_STAT_OFFSET + (4 * Index)), RegVal); 638 } 639 } 640 641 // 642 // Wait roothub port power stable 643 // 644 gBS->Stall (EHC_ROOT_PORT_RECOVERY_STALL); 645 646 // 647 // 4. Set all ports routing to EHC 648 // 649 EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); 650 651 Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT); 652 653 if (EFI_ERROR (Status)) { 654 DEBUG ((EFI_D_ERROR, "EhcInitHC: failed to enable period schedule\n")); 655 return Status; 656 } 657 658 Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT); 659 660 if (EFI_ERROR (Status)) { 661 DEBUG ((EFI_D_ERROR, "EhcInitHC: failed to enable async schedule\n")); 662 return Status; 663 } 664 665 return EFI_SUCCESS; 666 } 667