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