Home | History | Annotate | Download | only in SDControllerDxe
      1 /** @file
      2 
      3 The SD host controller driver model and HC protocol routines.
      4 
      5 Copyright (c) 2013-2015 Intel Corporation.
      6 
      7 This program and the accompanying materials
      8 are licensed and made available under the terms and conditions of the BSD License
      9 which accompanies this distribution.  The full text of the license may be found at
     10 http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 
     18 
     19 #include "SDController.h"
     20 
     21 
     22 EFI_DRIVER_BINDING_PROTOCOL gSDControllerDriverBinding = {
     23   SDControllerSupported,
     24   SDControllerStart,
     25   SDControllerStop,
     26   0x20,
     27   NULL,
     28   NULL
     29 };
     30 
     31 
     32 EFI_SD_HOST_IO_PROTOCOL  mSDHostIo = {
     33   EFI_SD_HOST_IO_PROTOCOL_REVISION_01,
     34   {
     35     0, // HighSpeedSupport
     36     0, // V18Support
     37     0, // V30Support
     38     0, // V33Support
     39     0, // Reserved0
     40     0, // BusWidth4
     41     0, // BusWidth8
     42     0, // Reserved1
     43     0, // Reserved1
     44     (512 * 1024) //BoundarySize
     45   },
     46   SendCommand,
     47   SetClockFrequency,
     48   SetBusWidth,
     49   SetHostVoltage,
     50   ResetSDHost,
     51   EnableAutoStopCmd,
     52   DetectCardAndInitHost,
     53   SetBlockLength,
     54   SetHighSpeedMode,
     55   SetDDRMode
     56 };
     57 
     58 /**
     59   Find sdclk_freq_sel and upr_sdclk_freq_sel bits
     60   for Clock Control Register (CLK_CTL)Offset 2Ch when using 8bit or 10bit
     61   divided clock mode.
     62 
     63   @param  BaseClockFreg        Base Clock Frequency in Hz For SD Clock in the
     64                                Capabilities register.
     65   @param  TargetFreq           Target Frequency in Hz to reach.
     66   @param  Is8BitMode           True if 8-bit Divided Clock Mode else 10bit mode.
     67   @param  Bits                 sdclk_freq_sel and upr_sdclk_freq_sel bits for
     68                                TargetFreq.
     69 
     70   @return EFI_SUCCESS          // Bits setup.
     71   @return EFI_UNSUPPORTED      // Cannot divide base clock to reach target clock.
     72 **/
     73 EFI_STATUS
     74 DividedClockModeBits (
     75   IN CONST UINTN                          BaseClockFreg,
     76   IN CONST UINTN                          TargetFreq,
     77   IN CONST BOOLEAN                        Is8BitMode,
     78   OUT UINT16                              *Bits
     79   )
     80 {
     81   UINTN                             N;
     82   UINTN                             CurrFreq;
     83 
     84  *Bits = 0;
     85   CurrFreq = BaseClockFreg;
     86   N = 0;
     87   //
     88   // N == 0 same for 8bit & 10bit mode i.e. BaseClockFreg of controller.
     89   //
     90   if (TargetFreq < CurrFreq) {
     91     if (Is8BitMode) {
     92       N = 1;
     93       do {
     94         //
     95         // N values for 8bit mode when N > 0.
     96         //  Bit[15:8] SDCLK Frequency Select at offset 2Ch
     97         //    80h - base clock divided by 256
     98         //    40h - base clock divided by 128
     99         //    20h - base clock divided by 64
    100         //    10h - base clock divided by 32
    101         //    08h - base clock divided by 16
    102         //    04h - base clock divided by 8
    103         //    02h - base clock divided by 4
    104         //    01h - base clock divided by 2
    105         //
    106         CurrFreq = BaseClockFreg / (2 * N);
    107         if (TargetFreq >= CurrFreq) {
    108           break;
    109         }
    110         N *= 2;
    111         if (N > V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL) {
    112           return EFI_UNSUPPORTED;
    113         }
    114       } while (TRUE);
    115     } else {
    116       N = 1;
    117       CurrFreq = BaseClockFreg / (2 * N);
    118       //
    119       // (try N = 0 or 1 first since don't want divide by 0).
    120       //
    121       if (TargetFreq < CurrFreq) {
    122         //
    123         // If still no match then calculate it for 10bit.
    124         // N values for 10bit mode.
    125         // N 1/2N Divided Clock (Duty 50%).
    126         // from Spec "The length of divider is extended to 10 bits and all
    127         // divider values shall be supported.
    128         //
    129         N = (BaseClockFreg / TargetFreq) / 2;
    130 
    131         //
    132         // Can only be N or N+1;
    133         //
    134         CurrFreq = BaseClockFreg / (2 * N);
    135         if (TargetFreq < CurrFreq) {
    136           N++;
    137           CurrFreq = BaseClockFreg / (2 * N);
    138         }
    139 
    140         if (N > V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL) {
    141           return EFI_UNSUPPORTED;
    142         }
    143 
    144         //
    145         // Set upper bits of SDCLK Frequency Select (bits 7:6 of reg 0x2c).
    146         //
    147         *Bits |= ((UINT16) ((N >> 2) & B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK));
    148       }
    149     }
    150   }
    151 
    152   //
    153   // Set lower bits of SDCLK Frequency Select (bits 15:8 of reg 0x2c).
    154   //
    155   *Bits |= ((UINT16) ((UINT8) N) << 8);
    156   DEBUG (
    157     (EFI_D_INFO,
    158     "SDIO:DividedClockModeBits: %dbit mode Want %dHz Got %dHz bits = %04x\r\n",
    159     (Is8BitMode) ? 8 : 10,
    160     TargetFreq,
    161     CurrFreq,
    162     (UINTN) *Bits
    163      ));
    164 
    165   return EFI_SUCCESS;
    166 }
    167 
    168 /**
    169   Print type of error and command index
    170 
    171   @param  CommandIndex         Command index to set the command index field of command register.
    172   @param  ErrorCode            Error interrupt status read from host controller
    173 
    174   @return EFI_DEVICE_ERROR
    175   @return EFI_TIMEOUT
    176   @return EFI_CRC_ERROR
    177 
    178 **/
    179 EFI_STATUS
    180 GetErrorReason (
    181   IN  UINT16    CommandIndex,
    182   IN  UINT16    ErrorCode
    183   )
    184 {
    185   EFI_STATUS    Status;
    186 
    187   Status = EFI_DEVICE_ERROR;
    188 
    189   DEBUG((EFI_D_ERROR, "[%2d] -- ", CommandIndex));
    190 
    191   if (ErrorCode & BIT0) {
    192     Status = EFI_TIMEOUT;
    193     DEBUG((EFI_D_ERROR, "Command Timeout Erro"));
    194   }
    195 
    196   if (ErrorCode & BIT1) {
    197     Status = EFI_CRC_ERROR;
    198     DEBUG((EFI_D_ERROR, "Command CRC Error"));
    199   }
    200 
    201   if (ErrorCode & BIT2) {
    202     DEBUG((EFI_D_ERROR, "Command End Bit Error"));
    203   }
    204 
    205   if (ErrorCode & BIT3) {
    206     DEBUG((EFI_D_ERROR, "Command Index Error"));
    207   }
    208   if (ErrorCode & BIT4) {
    209     Status = EFI_TIMEOUT;
    210     DEBUG((EFI_D_ERROR, "Data Timeout Error"));
    211   }
    212 
    213   if (ErrorCode & BIT5) {
    214     Status = EFI_CRC_ERROR;
    215     DEBUG((EFI_D_ERROR, "Data CRC Error"));
    216   }
    217 
    218   if (ErrorCode & BIT6) {
    219     DEBUG((EFI_D_ERROR, "Data End Bit Error"));
    220   }
    221 
    222   if (ErrorCode & BIT7) {
    223     DEBUG((EFI_D_ERROR, "Current Limit Error"));
    224   }
    225 
    226   if (ErrorCode & BIT8) {
    227     DEBUG((EFI_D_ERROR, "Auto CMD12 Error"));
    228   }
    229 
    230   if (ErrorCode & BIT9) {
    231     DEBUG((EFI_D_ERROR, "ADMA Error"));
    232   }
    233 
    234   DEBUG((EFI_D_ERROR, "\n"));
    235 
    236   return Status;
    237 }
    238 /**
    239   Enable/Disable High Speed transfer mode
    240 
    241   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
    242   @param  Enable                TRUE to Enable, FALSE to Disable
    243 
    244   @return EFI_SUCCESS
    245 **/
    246 EFI_STATUS
    247 SetHighSpeedMode (
    248   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
    249   IN  BOOLEAN                    Enable
    250   )
    251 {
    252   UINT32                 Data;
    253   SDHOST_DATA            *SDHostData;
    254   EFI_PCI_IO_PROTOCOL    *PciIo;
    255 
    256   SDHostData = SDHOST_DATA_FROM_THIS (This);
    257   PciIo      = SDHostData->PciIo;
    258 
    259   PciIo->Mem.Read (
    260                PciIo,
    261                EfiPciIoWidthUint8,
    262                0,
    263                (UINT64)MMIO_HOSTCTL,
    264                1,
    265                &Data
    266                );
    267 
    268   if (Enable) {
    269     if (PcdGetBool(PcdSdHciQuirkNoHiSpd)) {
    270       DEBUG ((EFI_D_INFO, "SDIO: Quirk never set High Speed Enable bit\r\n"));
    271       return EFI_SUCCESS;
    272     }
    273     DEBUG ((EFI_D_INFO, "Enable High Speed transfer mode ... \r\n"));
    274     Data |= BIT2;
    275   } else {
    276     Data &= ~BIT2;
    277   }
    278   PciIo->Mem.Write (
    279                PciIo,
    280                EfiPciIoWidthUint8,
    281                0,
    282               (UINT64)MMIO_HOSTCTL,
    283                1,
    284                &Data
    285               );
    286   return EFI_SUCCESS;
    287 }
    288 EFI_STATUS
    289 EFIAPI
    290 SetDDRMode (
    291   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
    292   IN  BOOLEAN                    Enable
    293   )
    294 {
    295   UINT16                 Data;
    296   SDHOST_DATA            *SDHostData;
    297   EFI_PCI_IO_PROTOCOL    *PciIo;
    298   SDHostData = SDHOST_DATA_FROM_THIS (This);
    299   PciIo      = SDHostData->PciIo;
    300   PciIo->Mem.Read (
    301                PciIo,
    302                EfiPciIoWidthUint16,
    303                0,
    304                (UINT64)MMIO_HOSTCTL2,
    305                1,
    306                &Data
    307                );
    308   Data &= 0xFFF0;
    309   if (Enable) {
    310     Data |= 0x0004; // Enable DDR50 by default, later should enable other mode like HS200/400
    311     Data |= BIT3;   // Enable 1.8V Signaling
    312   }
    313   PciIo->Mem.Write (
    314                PciIo,
    315                EfiPciIoWidthUint16,
    316                0,
    317               (UINT64)MMIO_HOSTCTL2,
    318                1,
    319                &Data
    320               );
    321   return EFI_SUCCESS;
    322 }
    323 /**
    324   Power on/off the LED associated with the slot
    325 
    326   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
    327   @param  Enable                TRUE to set LED on, FALSE to set LED off
    328 
    329   @return EFI_SUCCESS
    330 **/
    331 EFI_STATUS
    332 HostLEDEnable (
    333   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
    334   IN  BOOLEAN                    Enable
    335   )
    336 {
    337   SDHOST_DATA            *SDHostData;
    338   EFI_PCI_IO_PROTOCOL    *PciIo;
    339   UINT32                 Data;
    340 
    341   SDHostData = SDHOST_DATA_FROM_THIS (This);
    342   PciIo      = SDHostData->PciIo;
    343 
    344   PciIo->Mem.Read (
    345                PciIo,
    346                EfiPciIoWidthUint8,
    347                0,
    348                (UINT64)MMIO_HOSTCTL,
    349                1,
    350                &Data
    351                );
    352 
    353   if (Enable) {
    354     //
    355     //LED On
    356     //
    357     Data |= BIT0;
    358   } else {
    359     //
    360     //LED Off
    361     //
    362     Data &= ~BIT0;
    363   }
    364 
    365   PciIo->Mem.Write (
    366                PciIo,
    367                EfiPciIoWidthUint8,
    368                0,
    369                (UINT64)MMIO_HOSTCTL,
    370                1,
    371                &Data
    372                );
    373 
    374   return EFI_SUCCESS;
    375 }
    376 
    377 
    378 /**
    379   The main function used to send the command to the card inserted into the SD host slot.
    380   It will assemble the arguments to set the command register and wait for the command
    381   and transfer completed until timeout. Then it will read the response register to fill
    382   the ResponseData.
    383 
    384   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
    385   @param  CommandIndex          The command index to set the command index field of command register.
    386   @param  Argument              Command argument to set the argument field of command register.
    387   @param  DataType              TRANSFER_TYPE, indicates no data, data in or data out.
    388   @param  Buffer                Contains the data read from / write to the device.
    389   @param  BufferSize            The size of the buffer.
    390   @param  ResponseType          RESPONSE_TYPE.
    391   @param  TimeOut               Time out value in 1 ms unit.
    392   @param  ResponseData          Depending on the ResponseType, such as CSD or card status.
    393 
    394   @retval EFI_SUCCESS
    395   @retval EFI_INVALID_PARAMETER
    396   @retval EFI_OUT_OF_RESOURCES
    397   @retval EFI_TIMEOUT
    398   @retval EFI_DEVICE_ERROR
    399 
    400 **/
    401 
    402 EFI_STATUS
    403 EFIAPI
    404 SendCommand (
    405   IN   EFI_SD_HOST_IO_PROTOCOL    *This,
    406   IN   UINT16                     CommandIndex,
    407   IN   UINT32                     Argument,
    408   IN   TRANSFER_TYPE              DataType,
    409   IN   UINT8                      *Buffer, OPTIONAL
    410   IN   UINT32                     BufferSize,
    411   IN   RESPONSE_TYPE              ResponseType,
    412   IN   UINT32                     TimeOut,
    413   OUT  UINT32                     *ResponseData OPTIONAL
    414   )
    415 /*++
    416 
    417   Routine Description:
    418     The main function used to send the command to the card inserted into the SD host
    419     slot.
    420     It will assemble the arguments to set the command register and wait for the command
    421     and transfer completed until timeout. Then it will read the response register to fill
    422     the ResponseData
    423 
    424   Arguments:
    425     This           - Pointer to EFI_SD_HOST_IO_PROTOCOL
    426     CommandIndex   - The command index to set the command index field of command register
    427     Argument       - Command argument to set the argument field of command register
    428     DataType       - TRANSFER_TYPE, indicates no data, data in or data out
    429     Buffer         - Contains the data read from / write to the device
    430     BufferSize     - The size of the buffer
    431     ResponseType   - RESPONSE_TYPE
    432     TimeOut        - Time out value in 1 ms unit
    433     ResponseData   - Depending on the ResponseType, such as CSD or card status
    434 
    435   Returns:
    436     EFI_SUCCESS
    437     EFI_INVALID_PARAMETER
    438     EFI_OUT_OF_RESOURCES
    439     EFI_TIMEOUT
    440     EFI_DEVICE_ERROR
    441 
    442 --*/
    443 {
    444   EFI_STATUS            Status;
    445   SDHOST_DATA           *SDHostData;
    446   EFI_PCI_IO_PROTOCOL   *PciIo;
    447   UINT32                ResponseDataCount;
    448   UINT32                Data;
    449   UINT64                Data64;
    450   UINT8                 Index;
    451   INTN                  TimeOut2;
    452   BOOLEAN               AutoCMD12Enable = FALSE;
    453 
    454 
    455   Status             = EFI_SUCCESS;
    456   ResponseDataCount  = 1;
    457   SDHostData         = SDHOST_DATA_FROM_THIS (This);
    458   PciIo              = SDHostData->PciIo;
    459   AutoCMD12Enable    =  (CommandIndex & AUTO_CMD12_ENABLE) ? TRUE : FALSE;
    460   CommandIndex       = CommandIndex & CMD_INDEX_MASK;
    461 
    462   if (Buffer != NULL && DataType == NoData) {
    463     Status = EFI_INVALID_PARAMETER;
    464     DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
    465     goto Exit;
    466   }
    467 
    468   if (((UINTN)Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN)NULL) {
    469     Status = EFI_INVALID_PARAMETER;
    470     DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
    471     goto Exit;
    472   }
    473 
    474   DEBUG ((EFI_D_INFO, "SendCommand: Command Index = %d \r\n", CommandIndex));
    475   //
    476   TimeOut2 = 1000; // 10 ms
    477   do {
    478     PciIo->Mem.Read (
    479                  PciIo,
    480                  EfiPciIoWidthUint32,
    481                  0,
    482                  (UINT64)MMIO_PSTATE,
    483                  1,
    484                  &Data
    485                  );
    486      gBS->Stall (10);
    487   }while ((TimeOut2-- > 0) && (Data & BIT0));
    488   TimeOut2 = 1000; // 10 ms
    489   do {
    490     PciIo->Mem.Read (
    491                  PciIo,
    492                  EfiPciIoWidthUint32,
    493                  0,
    494                  (UINT64)MMIO_PSTATE,
    495                  1,
    496                  &Data
    497                  );
    498     gBS->Stall (10);
    499   }while ((TimeOut2-- > 0) && (Data & BIT1));
    500   //Clear status bits
    501   //
    502   Data = 0xFFFF;
    503   PciIo->Mem.Write (
    504                PciIo,
    505                EfiPciIoWidthUint16,
    506                0,
    507                (UINT64)MMIO_NINTSTS,
    508                1,
    509                &Data
    510                );
    511 
    512   Data = 0xFFFF;
    513   PciIo->Mem.Write (
    514                PciIo,
    515                EfiPciIoWidthUint16,
    516                0,
    517                (UINT64)MMIO_ERINTSTS,
    518                1,
    519                &Data
    520                );
    521 
    522 
    523   if (Buffer != NULL) {
    524      PciIo->Mem.Write (
    525                   PciIo,
    526                   EfiPciIoWidthUint32,
    527                   0,
    528                   (UINT64)MMIO_DMAADR,
    529                   1,
    530                   &Buffer
    531                   );
    532 
    533      PciIo->Mem.Read (
    534                   PciIo,
    535                   EfiPciIoWidthUint16,
    536                   0,
    537                   (UINT64)MMIO_BLKSZ,
    538                   1,
    539                   &Data
    540                   );
    541      Data &= ~(0xFFF);
    542      if (BufferSize <= SDHostData->BlockLength) {
    543        Data |= (BufferSize | 0x7000);
    544      } else {
    545        Data |= (SDHostData->BlockLength | 0x7000);
    546      }
    547 
    548 
    549      PciIo->Mem.Write (
    550                   PciIo,
    551                   EfiPciIoWidthUint16,
    552                   0,
    553                   (UINT64)MMIO_BLKSZ,
    554                   1,
    555                   &Data
    556                   );
    557      if (BufferSize <= SDHostData->BlockLength) {
    558        Data = 1;
    559      } else {
    560        Data = BufferSize / SDHostData->BlockLength;
    561      }
    562      PciIo->Mem.Write (
    563                   PciIo,
    564                   EfiPciIoWidthUint16,
    565                   0,
    566                   (UINT64)MMIO_BLKCNT,
    567                   1,
    568                   &Data
    569                   );
    570 
    571   } else {
    572     Data = 0;
    573     PciIo->Mem.Write (
    574                   PciIo,
    575                   EfiPciIoWidthUint16,
    576                   0,
    577                   (UINT64)MMIO_BLKSZ,
    578                   1,
    579                   &Data
    580                   );
    581     PciIo->Mem.Write (
    582                   PciIo,
    583                   EfiPciIoWidthUint16,
    584                   0,
    585                   (UINT64)MMIO_BLKCNT,
    586                   1,
    587                   &Data
    588                   );
    589   }
    590 
    591   //
    592   //Argument
    593   //
    594   Data = Argument;
    595   PciIo->Mem.Write (
    596                PciIo,
    597                EfiPciIoWidthUint32,
    598                0,
    599                (UINT64)MMIO_CMDARG,
    600                1,
    601                &Data
    602                );
    603 
    604 
    605   PciIo->Mem.Read (
    606                PciIo,
    607                EfiPciIoWidthUint16,
    608                0,
    609                (UINT64)MMIO_XFRMODE,
    610                1,
    611                &Data
    612                );
    613 
    614 
    615   DEBUG ((EFI_D_INFO, "Transfer mode read  = 0x%x \r\n", (Data & 0xFFFF)));
    616   //
    617   //BIT0 - DMA Enable
    618   //BIT2 - Auto Cmd12
    619   //
    620   if (DataType == InData) {
    621     Data |= BIT4 | BIT0;
    622   } else if (DataType == OutData){
    623     Data &= ~BIT4;
    624     Data |= BIT0;
    625   } else {
    626     Data &= ~(BIT4 | BIT0);
    627   }
    628 
    629   if (BufferSize <= SDHostData->BlockLength) {
    630     Data &= ~ (BIT5 | BIT1 | BIT2);
    631     Data |= BIT1; // Enable block count always
    632   } else {
    633      if (SDHostData->IsAutoStopCmd && AutoCMD12Enable) {
    634       Data |= (BIT5 | BIT1 | BIT2);
    635      } else {
    636       Data |= (BIT5 | BIT1);
    637      }
    638   }
    639 
    640   DEBUG ((EFI_D_INFO, "Transfer mode write = 0x%x \r\n", (Data & 0xffff)));
    641   PciIo->Mem.Write (
    642                PciIo,
    643                EfiPciIoWidthUint16,
    644                0,
    645                (UINT64)MMIO_XFRMODE,
    646                1,
    647                &Data
    648                );
    649   //
    650   //Command
    651   //
    652   //ResponseTypeSelect    IndexCheck    CRCCheck    ResponseType
    653   //  00                     0            0           NoResponse
    654   //  01                     0            1           R2
    655   //  10                     0            0           R3, R4
    656   //  10                     1            1           R1, R5, R6, R7
    657   //  11                     1            1           R1b, R5b
    658   //
    659   switch (ResponseType) {
    660     case ResponseNo:
    661       Data = (CommandIndex << 8);
    662       ResponseDataCount = 0;
    663       break;
    664 
    665     case ResponseR1:
    666     case ResponseR5:
    667     case ResponseR6:
    668     case ResponseR7:
    669       Data = (CommandIndex << 8) | BIT1 | BIT4| BIT3;
    670       ResponseDataCount = 1;
    671       break;
    672 
    673     case ResponseR1b:
    674     case ResponseR5b:
    675       Data = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3;
    676       ResponseDataCount = 1;
    677       break;
    678 
    679     case ResponseR2:
    680       Data = (CommandIndex << 8) | BIT0 | BIT3;
    681       ResponseDataCount = 4;
    682       break;
    683 
    684     case ResponseR3:
    685     case ResponseR4:
    686       Data = (CommandIndex << 8) | BIT1;
    687       ResponseDataCount = 1;
    688       break;
    689 
    690     default:
    691       ASSERT (0);
    692       Status = EFI_INVALID_PARAMETER;
    693       DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
    694       goto Exit;
    695   }
    696 
    697   if (DataType != NoData) {
    698     Data |= BIT5;
    699   }
    700 
    701   HostLEDEnable (This, TRUE);
    702 
    703 
    704   PciIo->Mem.Write (
    705                PciIo,
    706                EfiPciIoWidthUint16,
    707                0,
    708                (UINT64)MMIO_SDCMD,
    709                1,
    710                &Data
    711                );
    712 
    713 
    714   Data = 0;
    715   do {
    716     PciIo->Mem.Read (
    717                  PciIo,
    718                  EfiPciIoWidthUint16,
    719                  0,
    720                  (UINT64)MMIO_ERINTSTS,
    721                  1,
    722                  &Data
    723                  );
    724 
    725     if ((Data & 0x07FF) != 0) {
    726       Status = GetErrorReason (CommandIndex, (UINT16)Data);
    727       DEBUG ((EFI_D_ERROR, "SendCommand: Error happens \r\n"));
    728       goto Exit;
    729     }
    730 
    731     PciIo->Mem.Read (
    732                  PciIo,
    733                  EfiPciIoWidthUint16,
    734                  0,
    735                  (UINT64)MMIO_NINTSTS,
    736                  1,
    737                  &Data
    738                  );
    739 
    740     if ((Data & BIT0) == BIT0) {
    741        //
    742        //Command completed, can read response
    743        //
    744        if (DataType == NoData) {
    745          break;
    746        } else {
    747          //
    748          //Transfer completed
    749          //
    750          if ((Data & BIT1) == BIT1) {
    751            break;
    752          }
    753        }
    754     }
    755 
    756     gBS->Stall (1 * 1000);
    757 
    758     TimeOut --;
    759 
    760   } while (TimeOut > 0);
    761 
    762   if (TimeOut == 0) {
    763     Status = EFI_TIMEOUT;
    764     DEBUG ((EFI_D_ERROR, "SendCommand: Time out \r\n"));
    765     goto Exit;
    766   }
    767 
    768   if (ResponseData != NULL) {
    769     PciIo->Mem.Read (
    770                  PciIo,
    771                  EfiPciIoWidthUint32,
    772                  0,
    773                  (UINT64)MMIO_RESP,
    774                  ResponseDataCount,
    775                  ResponseData
    776                  );
    777     if (ResponseType == ResponseR2) {
    778       //
    779       // Adjustment for R2 response
    780       //
    781       Data = 1;
    782       for (Index = 0; Index < ResponseDataCount; Index++) {
    783         Data64 = LShiftU64(*ResponseData, 8);
    784         *ResponseData = (UINT32)((Data64 & 0xFFFFFFFF) | Data);
    785         Data =  (UINT32)RShiftU64 (Data64, 32);
    786         ResponseData++;
    787       }
    788     }
    789   }
    790 
    791 Exit:
    792   HostLEDEnable (This, FALSE);
    793   return Status;
    794 }
    795 
    796 /**
    797   Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.
    798   It depends on the max frequency the host can support, divider, and host speed mode.
    799 
    800   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
    801   @param  MaxFrequency          Max frequency in HZ.
    802 
    803   @retval EFI_SUCCESS
    804   @retval EFI_TIMEOUT
    805 
    806 **/
    807 EFI_STATUS
    808 EFIAPI
    809 SetClockFrequency (
    810   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
    811   IN  UINT32                     MaxFrequency
    812   )
    813 {
    814   UINT32                 Data;
    815   UINT16                 FreqSelBits;
    816   EFI_STATUS             Status;
    817   SDHOST_DATA            *SDHostData;
    818   EFI_PCI_IO_PROTOCOL    *PciIo;
    819   UINT32                 TimeOutCount;
    820   UINT32                 Revision;
    821 
    822   SDHostData = SDHOST_DATA_FROM_THIS (This);
    823   PciIo      = SDHostData->PciIo;
    824   Data = 0;
    825   PciIo->Mem.Write (
    826                PciIo,
    827                EfiPciIoWidthUint16,
    828                0,
    829                (UINT64)MMIO_CLKCTL,
    830                1,
    831                &Data
    832                );
    833 
    834   PciIo->Mem.Read (
    835                 PciIo,
    836                 EfiPciIoWidthUint8,
    837                 0,
    838                 (UINT64)MMIO_CTRLRVER,
    839                 1,
    840                 &Revision
    841                 );
    842   Revision &= 0x000000FF;
    843 
    844   Status = DividedClockModeBits (
    845              SDHostData->BaseClockInMHz * 1000 * 1000,
    846              MaxFrequency,
    847              (Revision < SDHCI_SPEC_300),
    848              &FreqSelBits
    849              );
    850 
    851   if (EFI_ERROR (Status)) {
    852     //
    853     // Cannot reach MaxFrequency with SDHostData->BaseClockInMHz.
    854     //
    855     ASSERT_EFI_ERROR (Status);
    856     return Status;
    857   }
    858 
    859   Data = 0;
    860 
    861   //
    862   //Enable internal clock and Stop Clock Enable
    863   //
    864   Data = BIT0;
    865   PciIo->Mem.Write (
    866                PciIo,
    867                EfiPciIoWidthUint16,
    868                0,
    869                (UINT64)MMIO_CLKCTL,
    870                1,
    871                &Data
    872                );
    873 
    874   TimeOutCount = TIME_OUT_1S;
    875   do {
    876     PciIo->Mem.Read (
    877                  PciIo,
    878                  EfiPciIoWidthUint16,
    879                  0,
    880                  (UINT64)MMIO_CLKCTL,
    881                  1,
    882                  &Data
    883                  );
    884     gBS->Stall (1 * 1000);
    885     TimeOutCount --;
    886     if (TimeOutCount == 0) {
    887       DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));
    888       return EFI_TIMEOUT;
    889     }
    890   } while ((Data & BIT1) != BIT1);
    891 
    892   DEBUG ((EFI_D_INFO, "Base Clock In MHz: %d\r\n", SDHostData->BaseClockInMHz));
    893 
    894   Data = (BIT0 | ((UINT32) FreqSelBits));
    895   DEBUG ((EFI_D_INFO, "Data write to MMIO_CLKCTL: 0x%04x \r\n", Data));
    896   PciIo->Mem.Write (
    897                PciIo,
    898                EfiPciIoWidthUint16,
    899                0,
    900                (UINT64)MMIO_CLKCTL,
    901                1,
    902                &Data
    903                );
    904 
    905   TimeOutCount = TIME_OUT_1S;
    906   do {
    907     PciIo->Mem.Read (
    908                  PciIo,
    909                  EfiPciIoWidthUint16,
    910                  0,
    911                  (UINT64)MMIO_CLKCTL,
    912                  1,
    913                  &Data
    914                  );
    915     gBS->Stall (1 * 1000);
    916     TimeOutCount --;
    917     if (TimeOutCount == 0) {
    918       DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));
    919       return EFI_TIMEOUT;
    920     }
    921   } while ((Data & BIT1) != BIT1);
    922   gBS->Stall (20 * 1000);
    923   Data |= BIT2;
    924   PciIo->Mem.Write (
    925                PciIo,
    926                EfiPciIoWidthUint16,
    927                0,
    928                (UINT64)MMIO_CLKCTL,
    929                1,
    930                &Data
    931                );
    932 
    933   return EFI_SUCCESS;
    934 }
    935 
    936 /**
    937   Set bus width of the host controller
    938 
    939   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
    940   @param  BusWidth              Bus width in 1, 4, 8 bits.
    941 
    942   @retval EFI_SUCCESS
    943   @retval EFI_INVALID_PARAMETER
    944 
    945 **/
    946 EFI_STATUS
    947 EFIAPI
    948 SetBusWidth (
    949   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
    950   IN  UINT32                     BusWidth
    951   )
    952 {
    953   SDHOST_DATA            *SDHostData;
    954   EFI_PCI_IO_PROTOCOL    *PciIo;
    955   UINT8                  Data;
    956 
    957   SDHostData = SDHOST_DATA_FROM_THIS (This);
    958 
    959 
    960   if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) {
    961     DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));
    962     return EFI_INVALID_PARAMETER;
    963   }
    964 
    965   if ((SDHostData->SDHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) {
    966      DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));
    967      return EFI_INVALID_PARAMETER;
    968   }
    969 
    970   PciIo      = SDHostData->PciIo;
    971 
    972   PciIo->Mem.Read (
    973                PciIo,
    974                EfiPciIoWidthUint8,
    975                0,
    976                (UINT64)MMIO_HOSTCTL,
    977                1,
    978                &Data
    979                );
    980   //
    981   // BIT5 8-bit MMC Support (MMC8):
    982   // If set, IOH supports 8-bit MMC. When cleared, IOH does not support this feature
    983   //
    984   if (BusWidth == 8) {
    985     DEBUG ((EFI_D_INFO, "Bus Width is 8-bit ... \r\n"));
    986     Data |= BIT5;
    987   } else if (BusWidth == 4) {
    988     DEBUG ((EFI_D_INFO, "Bus Width is 4-bit ... \r\n"));
    989     Data &= ~BIT5;
    990     Data |= BIT1;
    991   } else {
    992     DEBUG ((EFI_D_INFO, "Bus Width is 1-bit ... \r\n"));
    993     Data &= ~BIT5;
    994     Data &= ~BIT1;
    995   }
    996 
    997   PciIo->Mem.Write (
    998                PciIo,
    999                EfiPciIoWidthUint8,
   1000                0,
   1001                (UINT64)MMIO_HOSTCTL,
   1002                1,
   1003                &Data
   1004                );
   1005 
   1006   return EFI_SUCCESS;
   1007 }
   1008 
   1009 
   1010 /**
   1011   Set voltage which could supported by the host controller.
   1012   Support 0(Power off the host), 1.8V, 3.0V, 3.3V
   1013 
   1014   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
   1015   @param  Voltage               Units in 0.1 V.
   1016 
   1017   @retval EFI_SUCCESS
   1018   @retval EFI_INVALID_PARAMETER
   1019 
   1020 **/
   1021 EFI_STATUS
   1022 EFIAPI
   1023 SetHostVoltage (
   1024   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
   1025   IN  UINT32                     Voltage
   1026   )
   1027 {
   1028   SDHOST_DATA            *SDHostData;
   1029   EFI_PCI_IO_PROTOCOL    *PciIo;
   1030   UINT8                  Data;
   1031   EFI_STATUS             Status;
   1032 
   1033   SDHostData = SDHOST_DATA_FROM_THIS (This);
   1034   PciIo      = SDHostData->PciIo;
   1035   Status     = EFI_SUCCESS;
   1036 
   1037   PciIo->Mem.Read (
   1038                PciIo,
   1039                EfiPciIoWidthUint8,
   1040                0,
   1041                (UINT64)MMIO_PWRCTL,
   1042                1,
   1043                &Data
   1044                );
   1045 
   1046   if (Voltage == 0) {
   1047     //
   1048     //Power Off the host
   1049     //
   1050     Data &= ~BIT0;
   1051   } else if (Voltage <= 18 && This->HostCapability.V18Support) {
   1052      //
   1053      //1.8V
   1054      //
   1055      Data |= (BIT1 | BIT3 | BIT0);
   1056   } else if (Voltage > 18 &&  Voltage <= 30 && This->HostCapability.V30Support) {
   1057      //
   1058      //3.0V
   1059      //
   1060      Data |= (BIT2 | BIT3 | BIT0);
   1061   } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) {
   1062      //
   1063      //3.3V
   1064      //
   1065      Data |= (BIT1 | BIT2 | BIT3 | BIT0);
   1066   } else {
   1067      Status = EFI_UNSUPPORTED;
   1068      goto Exit;
   1069   }
   1070 
   1071   PciIo->Mem.Write (
   1072                PciIo,
   1073                EfiPciIoWidthUint8,
   1074                0,
   1075                (UINT64)MMIO_PWRCTL,
   1076                1,
   1077                &Data
   1078                );
   1079   gBS->Stall (10 * 1000);
   1080 
   1081 Exit:
   1082   return Status;
   1083 }
   1084 
   1085 
   1086 
   1087 /**
   1088   Reset the host controller.
   1089 
   1090   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
   1091   @param  ResetAll              TRUE to reset all.
   1092 
   1093   @retval EFI_SUCCESS
   1094   @retval EFI_TIMEOUT
   1095 
   1096 **/
   1097 EFI_STATUS
   1098 EFIAPI
   1099 ResetSDHost (
   1100   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
   1101   IN  RESET_TYPE                 ResetType
   1102   )
   1103 {
   1104   SDHOST_DATA            *SDHostData;
   1105   EFI_PCI_IO_PROTOCOL    *PciIo;
   1106   UINT32                 Data;
   1107   UINT16                 ErrStatus;
   1108   UINT32                 Mask;
   1109   UINT32                 TimeOutCount;
   1110   UINT16                 SaveClkCtl;
   1111   UINT16                 ZeroClkCtl;
   1112 
   1113   SDHostData = SDHOST_DATA_FROM_THIS (This);
   1114   PciIo      = SDHostData->PciIo;
   1115   Mask       = 0;
   1116   ErrStatus  = 0;
   1117 
   1118   if (ResetType == Reset_Auto) {
   1119     PciIo->Mem.Read (
   1120                  PciIo,
   1121                  EfiPciIoWidthUint16,
   1122                  0,
   1123                  (UINT64)MMIO_ERINTSTS,
   1124                  1,
   1125                  &ErrStatus
   1126                  );
   1127     if ((ErrStatus & 0xF) != 0) {
   1128       //
   1129       //Command Line
   1130       //
   1131       Mask |= BIT1;
   1132     }
   1133     if ((ErrStatus & 0x70) != 0) {
   1134       //
   1135       //Data Line
   1136       //
   1137       Mask |= BIT2;
   1138     }
   1139   }
   1140 
   1141 
   1142   if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) {
   1143     Mask |= BIT2;
   1144   }
   1145   if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) {
   1146     Mask |= BIT1;
   1147   }
   1148   if (ResetType == Reset_All) {
   1149     Mask = BIT0;
   1150   }
   1151 
   1152   if (Mask == 0) {
   1153     return EFI_SUCCESS;
   1154   }
   1155 
   1156   //
   1157   // To improve SD stability, we zero the MMIO_CLKCTL register and
   1158   // stall for 50 microseconds before reseting the controller.  We
   1159   // restore the register setting following the reset operation.
   1160   //
   1161   PciIo->Mem.Read (
   1162                PciIo,
   1163                EfiPciIoWidthUint16,
   1164                0,
   1165                (UINT64)MMIO_CLKCTL,
   1166                1,
   1167                &SaveClkCtl
   1168                );
   1169 
   1170   ZeroClkCtl = (UINT16) 0;
   1171   PciIo->Mem.Write (
   1172                PciIo,
   1173                EfiPciIoWidthUint16,
   1174                0,
   1175                (UINT64)MMIO_CLKCTL,
   1176                1,
   1177                &ZeroClkCtl
   1178                );
   1179 
   1180   gBS->Stall (50);
   1181 
   1182   //
   1183   // Reset the SD host controller
   1184   //
   1185   PciIo->Mem.Write (
   1186                PciIo,
   1187                EfiPciIoWidthUint8,
   1188                0,
   1189                (UINT64)MMIO_SWRST,
   1190                1,
   1191                &Mask
   1192                );
   1193 
   1194   Data          = 0;
   1195   TimeOutCount  = TIME_OUT_1S;
   1196   do {
   1197 
   1198     gBS->Stall (1 * 1000);
   1199 
   1200     TimeOutCount --;
   1201 
   1202     PciIo->Mem.Read (
   1203                  PciIo,
   1204                  EfiPciIoWidthUint8,
   1205                  0,
   1206                  (UINT64)MMIO_SWRST,
   1207                  1,
   1208                  &Data
   1209                  );
   1210     if ((Data & Mask) == 0) {
   1211       break;
   1212     }
   1213   } while (TimeOutCount > 0);
   1214 
   1215   //
   1216   // We now restore the MMIO_CLKCTL register which we set to 0 above.
   1217   //
   1218   PciIo->Mem.Write (
   1219                PciIo,
   1220                EfiPciIoWidthUint16,
   1221                0,
   1222                (UINT64)MMIO_CLKCTL,
   1223                1,
   1224                &SaveClkCtl
   1225                );
   1226 
   1227   if (TimeOutCount == 0) {
   1228     DEBUG ((EFI_D_ERROR, "ResetSDHost: Time out \r\n"));
   1229     return EFI_TIMEOUT;
   1230   }
   1231 
   1232   return EFI_SUCCESS;
   1233 }
   1234 
   1235 
   1236 /**
   1237   Enable auto stop on the host controller.
   1238 
   1239   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
   1240   @param  Enable                TRUE to enable, FALSE to disable.
   1241 
   1242   @retval EFI_SUCCESS
   1243   @retval EFI_TIMEOUT
   1244 
   1245 **/
   1246 EFI_STATUS
   1247 EFIAPI
   1248 EnableAutoStopCmd (
   1249   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
   1250   IN  BOOLEAN                    Enable
   1251   )
   1252 {
   1253   SDHOST_DATA            *SDHostData;
   1254 
   1255   SDHostData = SDHOST_DATA_FROM_THIS (This);
   1256 
   1257   SDHostData->IsAutoStopCmd = Enable;
   1258 
   1259   return EFI_SUCCESS;
   1260 }
   1261 
   1262 /**
   1263   Set the Block length on the host controller.
   1264 
   1265   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
   1266   @param  BlockLength           card supportes block length.
   1267 
   1268   @retval EFI_SUCCESS
   1269   @retval EFI_TIMEOUT
   1270 
   1271 **/
   1272 EFI_STATUS
   1273 EFIAPI
   1274 SetBlockLength (
   1275   IN  EFI_SD_HOST_IO_PROTOCOL    *This,
   1276   IN  UINT32                     BlockLength
   1277   )
   1278 {
   1279   SDHOST_DATA            *SDHostData;
   1280 
   1281   SDHostData = SDHOST_DATA_FROM_THIS (This);
   1282 
   1283   DEBUG ((EFI_D_INFO, "Block length on the host controller: %d \r\n", BlockLength));
   1284   SDHostData->BlockLength = BlockLength;
   1285 
   1286   return EFI_SUCCESS;
   1287 }
   1288 
   1289 
   1290 /**
   1291   Find whether these is a card inserted into the slot. If so init the host.
   1292   If not, return EFI_NOT_FOUND.
   1293 
   1294   @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
   1295 
   1296   @retval EFI_SUCCESS
   1297   @retval EFI_NOT_FOUND
   1298 
   1299 **/
   1300 EFI_STATUS
   1301 EFIAPI
   1302 DetectCardAndInitHost (
   1303   IN  EFI_SD_HOST_IO_PROTOCOL    *This
   1304   )
   1305 {
   1306   SDHOST_DATA            *SDHostData;
   1307   EFI_PCI_IO_PROTOCOL    *PciIo;
   1308   UINT32                 Data;
   1309   EFI_STATUS             Status;
   1310   UINT8                  Voltages[] = { 33, 30, 18 };
   1311   UINTN                  Loop;
   1312 
   1313   SDHostData = SDHOST_DATA_FROM_THIS (This);
   1314   PciIo      = SDHostData->PciIo;
   1315   Status     = EFI_NOT_FOUND;
   1316 
   1317   Data = 0;
   1318   PciIo->Mem.Read (
   1319                PciIo,
   1320                EfiPciIoWidthUint32,
   1321                0,
   1322                (UINT64)MMIO_PSTATE,
   1323                1,
   1324                &Data
   1325                );
   1326 
   1327   if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) {
   1328     //
   1329     // Has no card inserted
   1330     //
   1331     DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: No Cards \r\n"));
   1332     Status =  EFI_NOT_FOUND;
   1333     goto Exit;
   1334   }
   1335   DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: Find Cards \r\n"));
   1336 
   1337   Status =  EFI_NOT_FOUND;
   1338   for (Loop = 0; Loop < sizeof (Voltages); Loop++) {
   1339     DEBUG ((
   1340       EFI_D_INFO,
   1341       "DetectCardAndInitHost: SetHostVoltage %d.%dV \r\n",
   1342       Voltages[Loop] / 10,
   1343       Voltages[Loop] % 10
   1344       ));
   1345     Status = SetHostVoltage (This, Voltages[Loop]);
   1346     if (EFI_ERROR (Status)) {
   1347       DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [failed]\n"));
   1348     } else {
   1349       DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [success]\n"));
   1350       break;
   1351     }
   1352   }
   1353   if (EFI_ERROR (Status)) {
   1354     DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set voltage \r\n"));
   1355     goto Exit;
   1356   }
   1357 
   1358   Status = SetClockFrequency (This, FREQUENCY_OD);
   1359   if (EFI_ERROR (Status)) {
   1360     DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set frequency \r\n"));
   1361     goto Exit;
   1362   }
   1363   SetBusWidth (This, 1);
   1364 
   1365   //
   1366   //Enable normal status change
   1367   //
   1368 
   1369   Data = (BIT0 | BIT1);
   1370 
   1371   PciIo->Mem.Write (
   1372                PciIo,
   1373                EfiPciIoWidthUint16,
   1374                0,
   1375                (UINT64)MMIO_NINTEN,
   1376                1,
   1377                &Data
   1378                );
   1379 
   1380   //
   1381   //Enable error status change
   1382   //
   1383   PciIo->Mem.Read (
   1384                PciIo,
   1385                EfiPciIoWidthUint16,
   1386                0,
   1387                (UINT64)MMIO_ERINTEN,
   1388                1,
   1389                &Data
   1390                );
   1391 
   1392   Data |= (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8);
   1393 
   1394   PciIo->Mem.Write (
   1395                PciIo,
   1396                EfiPciIoWidthUint16,
   1397                0,
   1398                (UINT64)MMIO_ERINTEN,
   1399                1,
   1400                &Data
   1401                );
   1402 
   1403   //
   1404   //Data transfer Timeout control
   1405   //
   1406   Data = 0x0E;
   1407 
   1408   PciIo->Mem.Write (
   1409                PciIo,
   1410                EfiPciIoWidthUint8,
   1411                0,
   1412                (UINT64)MMIO_TOCTL,
   1413                1,
   1414                &Data
   1415                );
   1416   //
   1417   //Set Default Bus width as 1 bit
   1418   //
   1419 
   1420 Exit:
   1421   return Status;
   1422 
   1423 }
   1424 
   1425 /**
   1426   Entry point for EFI drivers.
   1427 
   1428   @param  ImageHandle      EFI_HANDLE.
   1429   @param  SystemTable      EFI_SYSTEM_TABLE.
   1430 
   1431   @retval EFI_SUCCESS      Driver is successfully loaded.
   1432   @return Others           Failed.
   1433 
   1434 **/
   1435 EFI_STATUS
   1436 EFIAPI
   1437 InitializeSDController (
   1438   IN EFI_HANDLE           ImageHandle,
   1439   IN EFI_SYSTEM_TABLE     *SystemTable
   1440   )
   1441 {
   1442   return EfiLibInstallDriverBindingComponentName2 (
   1443            ImageHandle,
   1444            SystemTable,
   1445            &gSDControllerDriverBinding,
   1446            ImageHandle,
   1447            &gSDControllerName,
   1448            &gSDControllerName2
   1449            );
   1450 }
   1451 
   1452 
   1453 /**
   1454   Test to see if this driver supports ControllerHandle. Any
   1455   ControllerHandle that has SDHostIoProtocol installed will be supported.
   1456 
   1457   @param  This                 Protocol instance pointer.
   1458   @param  Controller           Handle of device to test.
   1459   @param  RemainingDevicePath  Not used.
   1460 
   1461   @return EFI_SUCCESS          This driver supports this device.
   1462   @return EFI_UNSUPPORTED      This driver does not support this device.
   1463 
   1464 **/
   1465 EFI_STATUS
   1466 EFIAPI
   1467 SDControllerSupported (
   1468   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
   1469   IN EFI_HANDLE                      Controller,
   1470   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
   1471   )
   1472 {
   1473   EFI_STATUS            OpenStatus;
   1474   EFI_STATUS            Status;
   1475   EFI_PCI_IO_PROTOCOL   *PciIo;
   1476   PCI_CLASSC            PciClass;
   1477   EFI_SD_HOST_IO_PROTOCOL   *SdHostIo;
   1478   Status = gBS->OpenProtocol (
   1479                   Controller,
   1480                   &gEfiSDHostIoProtocolGuid,
   1481                   (VOID **)&SdHostIo,
   1482                   This->DriverBindingHandle,
   1483                   Controller,
   1484                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1485                   );
   1486   if (!EFI_ERROR (Status)) {
   1487     DEBUG (( DEBUG_INFO, "SdHost controller is already started\n"));
   1488     return EFI_ALREADY_STARTED;
   1489   }
   1490 
   1491   //
   1492   // Test whether there is PCI IO Protocol attached on the controller handle.
   1493   //
   1494   OpenStatus = gBS->OpenProtocol (
   1495                       Controller,
   1496                       &gEfiPciIoProtocolGuid,
   1497                       (VOID **) &PciIo,
   1498                       This->DriverBindingHandle,
   1499                       Controller,
   1500                       EFI_OPEN_PROTOCOL_BY_DRIVER
   1501                       );
   1502 
   1503   if (EFI_ERROR (OpenStatus)) {
   1504     return OpenStatus;
   1505   }
   1506 
   1507   Status = PciIo->Pci.Read (
   1508                         PciIo,
   1509                         EfiPciIoWidthUint8,
   1510                         PCI_CLASSCODE_OFFSET,
   1511                         sizeof (PCI_CLASSC) / sizeof (UINT8),
   1512                         &PciClass
   1513                         );
   1514 
   1515   if (EFI_ERROR (Status)) {
   1516     Status = EFI_UNSUPPORTED;
   1517     goto ON_EXIT;
   1518   }
   1519 
   1520   //
   1521   // Test whether the controller belongs to SD type
   1522   //
   1523   if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) ||
   1524       (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) ||
   1525       ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA))
   1526       ) {
   1527 
   1528     Status = EFI_UNSUPPORTED;
   1529   }
   1530 
   1531 ON_EXIT:
   1532   gBS->CloseProtocol (
   1533          Controller,
   1534          &gEfiPciIoProtocolGuid,
   1535          This->DriverBindingHandle,
   1536          Controller
   1537          );
   1538 
   1539   return Status;
   1540 }
   1541 /**
   1542   Starting the SD Host Controller Driver.
   1543 
   1544   @param  This                 Protocol instance pointer.
   1545   @param  Controller           Handle of device to test.
   1546   @param  RemainingDevicePath  Not used.
   1547 
   1548   @retval EFI_SUCCESS          This driver supports this device.
   1549   @retval EFI_UNSUPPORTED      This driver does not support this device.
   1550   @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error.
   1551                                EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
   1552 
   1553 **/
   1554 EFI_STATUS
   1555 EFIAPI
   1556 SDControllerStart (
   1557   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
   1558   IN EFI_HANDLE                      Controller,
   1559   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
   1560   )
   1561 {
   1562   EFI_STATUS            Status;
   1563   EFI_PCI_IO_PROTOCOL   *PciIo;
   1564   SDHOST_DATA           *SDHostData;
   1565   UINT32                Data;
   1566 
   1567 
   1568   SDHostData = NULL;
   1569   Data       = 0;
   1570 
   1571   //
   1572   // Open PCI I/O Protocol and save pointer to open protocol
   1573   // in private data area.
   1574   //
   1575   Status = gBS->OpenProtocol (
   1576                   Controller,
   1577                   &gEfiPciIoProtocolGuid,
   1578                   (VOID **) &PciIo,
   1579                   This->DriverBindingHandle,
   1580                   Controller,
   1581                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1582                   );
   1583 
   1584   if (EFI_ERROR (Status)) {
   1585     goto Exit;
   1586   }
   1587 
   1588   //
   1589   // Enable the SD Host Controller MMIO space
   1590   //
   1591   Status = PciIo->Attributes (
   1592                     PciIo,
   1593                     EfiPciIoAttributeOperationEnable,
   1594                     EFI_PCI_DEVICE_ENABLE,
   1595                     NULL
   1596                     );
   1597   if (EFI_ERROR (Status)) {
   1598     Status = EFI_OUT_OF_RESOURCES;
   1599     goto Exit;
   1600   }
   1601 
   1602 
   1603   SDHostData = (SDHOST_DATA*)AllocateZeroPool(sizeof (SDHOST_DATA));
   1604   if (SDHostData == NULL) {
   1605     Status =  EFI_OUT_OF_RESOURCES;
   1606     goto Exit;
   1607   }
   1608 
   1609   SDHostData->Signature   = SDHOST_DATA_SIGNATURE;
   1610   SDHostData->PciIo       = PciIo;
   1611 
   1612   CopyMem (&SDHostData->SDHostIo, &mSDHostIo, sizeof (EFI_SD_HOST_IO_PROTOCOL));
   1613 
   1614   ResetSDHost (&SDHostData->SDHostIo, Reset_All);
   1615 
   1616   PciIo->Mem.Read (
   1617               PciIo,
   1618               EfiPciIoWidthUint16,
   1619               0,
   1620               (UINT64)MMIO_CTRLRVER,
   1621               1,
   1622               &Data
   1623               );
   1624   SDHostData->SDHostIo.HostCapability.HostVersion = Data & 0xFF;
   1625   DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: HostVersion 0x%x \r\n", SDHostData->SDHostIo.HostCapability.HostVersion));
   1626 
   1627   PciIo->Mem.Read (
   1628                PciIo,
   1629                EfiPciIoWidthUint32,
   1630                0,
   1631                (UINT64)MMIO_CAP,
   1632                1,
   1633                &Data
   1634                );
   1635   DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MMIO_CAP 0x%x \r\n", Data));
   1636   if ((Data & BIT18) != 0) {
   1637     SDHostData->SDHostIo.HostCapability.BusWidth8 = TRUE;
   1638   }
   1639 
   1640   if ((Data & BIT21) != 0) {
   1641     SDHostData->SDHostIo.HostCapability.HighSpeedSupport = TRUE;
   1642   }
   1643 
   1644   if ((Data & BIT24) != 0) {
   1645     SDHostData->SDHostIo.HostCapability.V33Support = TRUE;
   1646   }
   1647 
   1648   if ((Data & BIT25) != 0) {
   1649     SDHostData->SDHostIo.HostCapability.V30Support = TRUE;
   1650   }
   1651 
   1652   if ((Data & BIT26) != 0) {
   1653     SDHostData->SDHostIo.HostCapability.V18Support = TRUE;
   1654   }
   1655 
   1656   SDHostData->SDHostIo.HostCapability.BusWidth4 = TRUE;
   1657 
   1658   if(SDHostData->SDHostIo.HostCapability.HostVersion < SDHCI_SPEC_300) {
   1659 
   1660 
   1661 
   1662       SDHostData->BaseClockInMHz = (Data >> 8) & 0x3F;
   1663    }
   1664    else {
   1665       SDHostData->BaseClockInMHz = (Data >> 8) & 0xFF;
   1666 
   1667    }
   1668 
   1669   SDHostData->BlockLength = 512 << ((Data >> 16) & 0x03);
   1670   DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: BlockLength 0x%x \r\n", SDHostData->BlockLength));
   1671   SDHostData->IsAutoStopCmd  = TRUE;
   1672 
   1673   Status = gBS->InstallProtocolInterface (
   1674                   &Controller,
   1675                   &gEfiSDHostIoProtocolGuid,
   1676                   EFI_NATIVE_INTERFACE,
   1677                   &SDHostData->SDHostIo
   1678                   );
   1679   if (EFI_ERROR (Status)) {
   1680     goto Exit;
   1681   }
   1682 
   1683   //
   1684   // Install the component name protocol
   1685   //
   1686   SDHostData->ControllerNameTable = NULL;
   1687 
   1688   AddUnicodeString2 (
   1689     "eng",
   1690     gSDControllerName.SupportedLanguages,
   1691     &SDHostData->ControllerNameTable,
   1692     L"SD Host Controller",
   1693     TRUE
   1694     );
   1695   AddUnicodeString2 (
   1696     "en",
   1697     gSDControllerName2.SupportedLanguages,
   1698     &SDHostData->ControllerNameTable,
   1699     L"SD Host Controller",
   1700     FALSE
   1701     );
   1702 
   1703 Exit:
   1704   if (EFI_ERROR (Status)) {
   1705     if (SDHostData != NULL) {
   1706       FreePool (SDHostData);
   1707     }
   1708   }
   1709 
   1710   return Status;
   1711 }
   1712 
   1713 
   1714 /**
   1715   Stop this driver on ControllerHandle. Support stoping any child handles
   1716   created by this driver.
   1717 
   1718   @param  This                 Protocol instance pointer.
   1719   @param  Controller           Handle of device to stop driver on.
   1720   @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.
   1721   @param  ChildHandleBuffer    List of handles for the children we need to stop.
   1722 
   1723   @return EFI_SUCCESS
   1724   @return others
   1725 
   1726 **/
   1727 EFI_STATUS
   1728 EFIAPI
   1729 SDControllerStop (
   1730   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
   1731   IN EFI_HANDLE                      Controller,
   1732   IN UINTN                           NumberOfChildren,
   1733   IN EFI_HANDLE                      *ChildHandleBuffer
   1734   )
   1735 {
   1736   EFI_STATUS               Status;
   1737   EFI_SD_HOST_IO_PROTOCOL  *SDHostIo;
   1738   SDHOST_DATA              *SDHostData;
   1739 
   1740   Status = gBS->OpenProtocol (
   1741                   Controller,
   1742                   &gEfiSDHostIoProtocolGuid,
   1743                   (VOID **) &SDHostIo,
   1744                   This->DriverBindingHandle,
   1745                   Controller,
   1746                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1747                   );
   1748 
   1749   //
   1750   // Test whether the Controller handler passed in is a valid
   1751   // Usb controller handle that should be supported, if not,
   1752   // return the error status directly
   1753   //
   1754   if (EFI_ERROR (Status)) {
   1755     return Status;
   1756   }
   1757 
   1758   SetHostVoltage (SDHostIo, 0);
   1759 
   1760   SDHostData  = SDHOST_DATA_FROM_THIS(SDHostIo);
   1761 
   1762   //
   1763   // Uninstall Block I/O protocol from the device handle
   1764   //
   1765   Status = gBS->UninstallProtocolInterface (
   1766                   Controller,
   1767                   &gEfiSDHostIoProtocolGuid,
   1768                   SDHostIo
   1769                   );
   1770   if (EFI_ERROR (Status)) {
   1771     return Status;
   1772   }
   1773 
   1774   FreeUnicodeStringTable (SDHostData->ControllerNameTable);
   1775 
   1776   FreePool (SDHostData);
   1777 
   1778   gBS->CloseProtocol (
   1779          Controller,
   1780          &gEfiPciIoProtocolGuid,
   1781          This->DriverBindingHandle,
   1782          Controller
   1783          );
   1784 
   1785   return EFI_SUCCESS;
   1786 }
   1787 
   1788 
   1789 
   1790