1/** @file 2 3 The EHCI register operation routines. 4 5Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR> 6This program and the accompanying materials 7are licensed and made available under the terms and conditions of the BSD License 8which accompanies this distribution. The full text of the license may be found at 9http://opensource.org/licenses/bsd-license.php 10 11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12WITHOUT 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**/ 30UINT32 31EhcReadCapRegister ( 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**/ 66UINT32 67EhcReadDbgRegister ( 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**/ 103UINT32 104EhcReadOpReg ( 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**/ 140VOID 141EhcWriteOpReg ( 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**/ 174VOID 175EhcSetOpRegBit ( 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**/ 197VOID 198EhcClearOpRegBit ( 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**/ 226EFI_STATUS 227EhcWaitOpRegBit ( 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**/ 256VOID 257EhcClearLegacySupport ( 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**/ 306EFI_STATUS 307EhcSetAndWaitDoorBell ( 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**/ 340VOID 341EhcAckAllInterrupt ( 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**/ 360EFI_STATUS 361EhcEnablePeriodSchd ( 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**/ 385EFI_STATUS 386EhcDisablePeriodSchd ( 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**/ 411EFI_STATUS 412EhcEnableAsyncSchd ( 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**/ 437EFI_STATUS 438EhcDisableAsyncSchd ( 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**/ 462BOOLEAN 463EhcIsHalt ( 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**/ 480BOOLEAN 481EhcIsSysError ( 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**/ 499EFI_STATUS 500EhcResetHC ( 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**/ 534EFI_STATUS 535EhcHaltHC ( 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**/ 558EFI_STATUS 559EhcRunHC ( 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**/ 587EFI_STATUS 588EhcInitHC ( 589 IN USB2_HC_DEV *Ehc 590 ) 591{ 592 EFI_STATUS Status; 593 UINT32 Index; 594 595 // This ASSERT crashes the BeagleBoard. There is some issue in the USB stack. 596 // This ASSERT needs to be removed so the BeagleBoard will boot. When we fix 597 // the USB stack we can put this ASSERT back in 598 // ASSERT (EhcIsHalt (Ehc)); 599 600 // 601 // Allocate the periodic frame and associated memeory 602 // management facilities if not already done. 603 // 604 if (Ehc->PeriodFrame != NULL) { 605 EhcFreeSched (Ehc); 606 } 607 608 Status = EhcInitSched (Ehc); 609 610 if (EFI_ERROR (Status)) { 611 return Status; 612 } 613 614 // 615 // 1. Clear USBINTR to disable all the interrupt. UEFI works by polling 616 // 617 EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0); 618 619 // 620 // 2. Start the Host Controller 621 // 622 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN); 623 624 // 625 // 3. Power up all ports if EHCI has Port Power Control (PPC) support 626 // 627 if (Ehc->HcStructParams & HCSP_PPC) { 628 for (Index = 0; Index < (UINT8) (Ehc->HcStructParams & HCSP_NPORTS); Index++) { 629 EhcSetOpRegBit (Ehc, (UINT32) (EHC_PORT_STAT_OFFSET + (4 * Index)), PORTSC_POWER); 630 } 631 } 632 633 // 634 // Wait roothub port power stable 635 // 636 gBS->Stall (EHC_ROOT_PORT_RECOVERY_STALL); 637 638 // 639 // 4. Set all ports routing to EHC 640 // 641 EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); 642 643 Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT); 644 645 if (EFI_ERROR (Status)) { 646 DEBUG ((EFI_D_ERROR, "EhcInitHC: failed to enable period schedule\n")); 647 return Status; 648 } 649 650 Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT); 651 652 if (EFI_ERROR (Status)) { 653 DEBUG ((EFI_D_ERROR, "EhcInitHC: failed to enable async schedule\n")); 654 return Status; 655 } 656 657 return EFI_SUCCESS; 658} 659