Home | History | Annotate | Download | only in EhciDxe
      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