Home | History | Annotate | Download | only in SdMmcPciHcDxe
      1 /** @file
      2   This file provides some helper functions which are specific for SD card device.
      3 
      4   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "SdMmcPciHcDxe.h"
     16 
     17 /**
     18   Send command GO_IDLE_STATE to the device to make it go to Idle State.
     19 
     20   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
     21 
     22   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
     23   @param[in] Slot           The slot number of the SD card to send the command to.
     24 
     25   @retval EFI_SUCCESS       The SD device is reset correctly.
     26   @retval Others            The device reset fails.
     27 
     28 **/
     29 EFI_STATUS
     30 SdCardReset (
     31   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
     32   IN UINT8                              Slot
     33   )
     34 {
     35   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
     36   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
     37   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
     38   EFI_STATUS                            Status;
     39 
     40   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
     41   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
     42   ZeroMem (&Packet, sizeof (Packet));
     43 
     44   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
     45   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
     46   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
     47 
     48   SdMmcCmdBlk.CommandIndex = SD_GO_IDLE_STATE;
     49   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBc;
     50 
     51   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
     52 
     53   return Status;
     54 }
     55 
     56 /**
     57   Send command SEND_IF_COND to the device to inquiry the SD Memory Card interface
     58   condition.
     59 
     60   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
     61 
     62   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
     63   @param[in] Slot           The slot number of the SD card to send the command to.
     64   @param[in] SupplyVoltage  The supplied voltage by the host.
     65   @param[in] CheckPattern   The check pattern to be sent to the device.
     66 
     67   @retval EFI_SUCCESS       The operation is done correctly.
     68   @retval Others            The operation fails.
     69 
     70 **/
     71 EFI_STATUS
     72 SdCardVoltageCheck (
     73   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
     74   IN UINT8                              Slot,
     75   IN UINT8                              SupplyVoltage,
     76   IN UINT8                              CheckPattern
     77   )
     78 {
     79   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
     80   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
     81   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
     82   EFI_STATUS                            Status;
     83 
     84   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
     85   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
     86   ZeroMem (&Packet, sizeof (Packet));
     87 
     88   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
     89   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
     90   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
     91 
     92   SdMmcCmdBlk.CommandIndex = SD_SEND_IF_COND;
     93   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
     94   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR7;
     95   SdMmcCmdBlk.CommandArgument = (SupplyVoltage << 8) | CheckPattern;
     96 
     97   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
     98 
     99   if (!EFI_ERROR (Status)) {
    100     if (SdMmcStatusBlk.Resp0 != SdMmcCmdBlk.CommandArgument) {
    101       return EFI_DEVICE_ERROR;
    102     }
    103   }
    104 
    105   return Status;
    106 }
    107 
    108 /**
    109   Send command SDIO_SEND_OP_COND to the device to see whether it is SDIO device.
    110 
    111   Refer to SDIO Simplified Spec 3 Section 3.2 for details.
    112 
    113   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    114   @param[in] Slot           The slot number of the SD card to send the command to.
    115   @param[in] VoltageWindow  The supply voltage window.
    116   @param[in] S18R           The boolean to show if it should switch to 1.8v.
    117 
    118   @retval EFI_SUCCESS       The operation is done correctly.
    119   @retval Others            The operation fails.
    120 
    121 **/
    122 EFI_STATUS
    123 SdioSendOpCond (
    124   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    125   IN UINT8                              Slot,
    126   IN UINT32                             VoltageWindow,
    127   IN BOOLEAN                            S18R
    128   )
    129 {
    130   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    131   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    132   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    133   EFI_STATUS                            Status;
    134   UINT32                                Switch;
    135 
    136   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    137   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    138   ZeroMem (&Packet, sizeof (Packet));
    139 
    140   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    141   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    142   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    143 
    144   SdMmcCmdBlk.CommandIndex = SDIO_SEND_OP_COND;
    145   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
    146   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR4;
    147 
    148   Switch = S18R ? BIT24 : 0;
    149 
    150   SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch;
    151 
    152   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    153 
    154   return Status;
    155 }
    156 
    157 /**
    158   Send command SD_SEND_OP_COND to the device to see whether it is SDIO device.
    159 
    160   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    161 
    162   @param[in]  PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    163   @param[in]  Slot           The slot number of the SD card to send the command to.
    164   @param[in]  Rca            The relative device address of addressed device.
    165   @param[in]  VoltageWindow  The supply voltage window.
    166   @param[in]  S18R           The boolean to show if it should switch to 1.8v.
    167   @param[in]  Xpc            The boolean to show if it should provide 0.36w power control.
    168   @param[in]  Hcs            The boolean to show if it support host capacity info.
    169   @param[out] Ocr            The buffer to store returned OCR register value.
    170 
    171   @retval EFI_SUCCESS        The operation is done correctly.
    172   @retval Others             The operation fails.
    173 
    174 **/
    175 EFI_STATUS
    176 SdCardSendOpCond (
    177   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
    178   IN     UINT8                          Slot,
    179   IN     UINT16                         Rca,
    180   IN     UINT32                         VoltageWindow,
    181   IN     BOOLEAN                        S18R,
    182   IN     BOOLEAN                        Xpc,
    183   IN     BOOLEAN                        Hcs,
    184      OUT UINT32                         *Ocr
    185   )
    186 {
    187   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    188   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    189   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    190   EFI_STATUS                            Status;
    191   UINT32                                Switch;
    192   UINT32                                MaxPower;
    193   UINT32                                HostCapacity;
    194 
    195   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    196   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    197   ZeroMem (&Packet, sizeof (Packet));
    198 
    199   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    200   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    201   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    202 
    203   SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
    204   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
    205   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    206   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
    207 
    208   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    209   if (EFI_ERROR (Status)) {
    210     return Status;
    211   }
    212 
    213   SdMmcCmdBlk.CommandIndex = SD_SEND_OP_COND;
    214   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
    215   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR3;
    216 
    217   Switch       = S18R ? BIT24 : 0;
    218   MaxPower     = Xpc ? BIT28 : 0;
    219   HostCapacity = Hcs ? BIT30 : 0;
    220 
    221   SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch | MaxPower | HostCapacity;
    222 
    223   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    224   if (!EFI_ERROR (Status)) {
    225     //
    226     // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
    227     //
    228     *Ocr = SdMmcStatusBlk.Resp0;
    229   }
    230 
    231   return Status;
    232 }
    233 
    234 /**
    235   Broadcast command ALL_SEND_CID to the bus to ask all the SD devices to send the
    236   data of their CID registers.
    237 
    238   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    239 
    240   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    241   @param[in] Slot           The slot number of the SD card to send the command to.
    242 
    243   @retval EFI_SUCCESS       The operation is done correctly.
    244   @retval Others            The operation fails.
    245 
    246 **/
    247 EFI_STATUS
    248 SdCardAllSendCid (
    249   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    250   IN UINT8                              Slot
    251   )
    252 {
    253   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    254   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    255   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    256   EFI_STATUS                            Status;
    257 
    258   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    259   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    260   ZeroMem (&Packet, sizeof (Packet));
    261 
    262   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    263   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    264   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    265 
    266   SdMmcCmdBlk.CommandIndex = SD_ALL_SEND_CID;
    267   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
    268   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
    269 
    270   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    271 
    272   return Status;
    273 }
    274 
    275 /**
    276   Send command SET_RELATIVE_ADDR to the SD device to assign a Relative device
    277   Address (RCA).
    278 
    279   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    280 
    281   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    282   @param[in]  Slot          The slot number of the SD card to send the command to.
    283   @param[out] Rca           The relative device address to assign.
    284 
    285   @retval EFI_SUCCESS       The operation is done correctly.
    286   @retval Others            The operation fails.
    287 
    288 **/
    289 EFI_STATUS
    290 SdCardSetRca (
    291   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
    292   IN     UINT8                          Slot,
    293      OUT UINT16                         *Rca
    294   )
    295 {
    296   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    297   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    298   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    299   EFI_STATUS                            Status;
    300 
    301   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    302   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    303   ZeroMem (&Packet, sizeof (Packet));
    304 
    305   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    306   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    307   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    308 
    309   SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;
    310   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
    311   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6;
    312 
    313   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    314   if (!EFI_ERROR (Status)) {
    315     *Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16);
    316   }
    317 
    318   return Status;
    319 }
    320 
    321 /**
    322   Send command SEND_CSD to the SD device to get the data of the CSD register.
    323 
    324   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    325 
    326   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    327   @param[in]  Slot          The slot number of the SD card to send the command to.
    328   @param[in]  Rca           The relative device address of selected device.
    329   @param[out] Csd           The buffer to store the content of the CSD register.
    330                             Note the caller should ignore the lowest byte of this
    331                             buffer as the content of this byte is meaningless even
    332                             if the operation succeeds.
    333 
    334   @retval EFI_SUCCESS       The operation is done correctly.
    335   @retval Others            The operation fails.
    336 
    337 **/
    338 EFI_STATUS
    339 SdCardGetCsd (
    340   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
    341   IN     UINT8                          Slot,
    342   IN     UINT16                         Rca,
    343      OUT SD_CSD                         *Csd
    344   )
    345 {
    346   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    347   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    348   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    349   EFI_STATUS                            Status;
    350 
    351   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    352   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    353   ZeroMem (&Packet, sizeof (Packet));
    354 
    355   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    356   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    357   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    358 
    359   SdMmcCmdBlk.CommandIndex = SD_SEND_CSD;
    360   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
    361   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
    362   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
    363 
    364   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    365   if (!EFI_ERROR (Status)) {
    366     //
    367     // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
    368     //
    369     CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1);
    370   }
    371 
    372   return Status;
    373 }
    374 
    375 /**
    376   Send command SEND_CSD to the SD device to get the data of the CSD register.
    377 
    378   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    379 
    380   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    381   @param[in]  Slot          The slot number of the SD card to send the command to.
    382   @param[in]  Rca           The relative device address of selected device.
    383   @param[out] Scr           The buffer to store the content of the SCR register.
    384 
    385   @retval EFI_SUCCESS       The operation is done correctly.
    386   @retval Others            The operation fails.
    387 
    388 **/
    389 EFI_STATUS
    390 SdCardGetScr (
    391   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
    392   IN     UINT8                          Slot,
    393   IN     UINT16                         Rca,
    394      OUT SD_SCR                         *Scr
    395   )
    396 {
    397   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    398   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    399   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    400   EFI_STATUS                            Status;
    401 
    402   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    403   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    404   ZeroMem (&Packet, sizeof (Packet));
    405 
    406   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    407   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    408   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    409 
    410   SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
    411   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
    412   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    413   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
    414 
    415   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    416   if (EFI_ERROR (Status)) {
    417     return Status;
    418   }
    419 
    420   SdMmcCmdBlk.CommandIndex = SD_SEND_SCR;
    421   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
    422   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    423 
    424   Packet.InDataBuffer     = Scr;
    425   Packet.InTransferLength = sizeof (SD_SCR);
    426 
    427   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    428 
    429   return Status;
    430 }
    431 
    432 /**
    433   Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.
    434 
    435   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    436 
    437   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    438   @param[in]  Slot          The slot number of the SD card to send the command to.
    439   @param[in]  Rca           The relative device address of selected device.
    440 
    441   @retval EFI_SUCCESS       The operation is done correctly.
    442   @retval Others            The operation fails.
    443 
    444 **/
    445 EFI_STATUS
    446 SdCardSelect (
    447   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    448   IN UINT8                              Slot,
    449   IN UINT16                             Rca
    450   )
    451 {
    452   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    453   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    454   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    455   EFI_STATUS                            Status;
    456 
    457   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    458   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    459   ZeroMem (&Packet, sizeof (Packet));
    460 
    461   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    462   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    463   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    464 
    465   SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;
    466   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
    467   if (Rca != 0) {
    468     SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
    469   }
    470   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
    471 
    472   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    473 
    474   return Status;
    475 }
    476 
    477 /**
    478   Send command VOLTAGE_SWITCH to the SD device to switch the voltage of the device.
    479 
    480   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    481 
    482   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    483   @param[in]  Slot          The slot number of the SD card to send the command to.
    484 
    485   @retval EFI_SUCCESS       The operation is done correctly.
    486   @retval Others            The operation fails.
    487 
    488 **/
    489 EFI_STATUS
    490 SdCardVoltageSwitch (
    491   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    492   IN UINT8                              Slot
    493   )
    494 {
    495   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    496   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    497   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    498   EFI_STATUS                            Status;
    499 
    500   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    501   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    502   ZeroMem (&Packet, sizeof (Packet));
    503 
    504   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    505   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    506   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    507 
    508   SdMmcCmdBlk.CommandIndex = SD_VOLTAGE_SWITCH;
    509   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
    510   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    511   SdMmcCmdBlk.CommandArgument = 0;
    512 
    513   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    514 
    515   return Status;
    516 }
    517 
    518 /**
    519   Send command SET_BUS_WIDTH to the SD device to set the bus width.
    520 
    521   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    522 
    523   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    524   @param[in] Slot           The slot number of the SD card to send the command to.
    525   @param[in] Rca            The relative device address of addressed device.
    526   @param[in] BusWidth       The bus width to be set, it could be 1 or 4.
    527 
    528   @retval EFI_SUCCESS       The operation is done correctly.
    529   @retval Others            The operation fails.
    530 
    531 **/
    532 EFI_STATUS
    533 SdCardSetBusWidth (
    534   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    535   IN UINT8                              Slot,
    536   IN UINT16                             Rca,
    537   IN UINT8                              BusWidth
    538   )
    539 {
    540   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    541   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    542   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    543   EFI_STATUS                            Status;
    544   UINT8                                 Value;
    545 
    546   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    547   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    548   ZeroMem (&Packet, sizeof (Packet));
    549 
    550   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    551   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    552   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    553 
    554   SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
    555   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
    556   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    557   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
    558 
    559   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    560   if (EFI_ERROR (Status)) {
    561     return Status;
    562   }
    563 
    564   SdMmcCmdBlk.CommandIndex = SD_SET_BUS_WIDTH;
    565   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
    566   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    567 
    568   if (BusWidth == 1) {
    569     Value = 0;
    570   } else if (BusWidth == 4) {
    571     Value = 2;
    572   } else {
    573     return EFI_INVALID_PARAMETER;
    574   }
    575 
    576   SdMmcCmdBlk.CommandArgument = Value & 0x3;
    577 
    578   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    579   return Status;
    580 }
    581 
    582 /**
    583   Send command SWITCH_FUNC to the SD device to check switchable function or switch card function.
    584 
    585   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    586 
    587   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    588   @param[in]  Slot          The slot number of the SD card to send the command to.
    589   @param[in]  AccessMode    The value for access mode group.
    590   @param[in]  CommandSystem The value for command set group.
    591   @param[in]  DriveStrength The value for drive length group.
    592   @param[in]  PowerLimit    The value for power limit group.
    593   @param[in]  Mode          Switch or check function.
    594   @param[out] SwitchResp    The return switch function status.
    595 
    596   @retval EFI_SUCCESS       The operation is done correctly.
    597   @retval Others            The operation fails.
    598 
    599 **/
    600 EFI_STATUS
    601 SdCardSwitch (
    602   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
    603   IN     UINT8                          Slot,
    604   IN     UINT8                          AccessMode,
    605   IN     UINT8                          CommandSystem,
    606   IN     UINT8                          DriveStrength,
    607   IN     UINT8                          PowerLimit,
    608   IN     BOOLEAN                        Mode,
    609      OUT UINT8                          *SwitchResp
    610   )
    611 {
    612   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    613   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    614   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    615   EFI_STATUS                            Status;
    616   UINT32                                ModeValue;
    617 
    618   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    619   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    620   ZeroMem (&Packet, sizeof (Packet));
    621 
    622   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    623   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    624   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    625 
    626   SdMmcCmdBlk.CommandIndex = SD_SWITCH_FUNC;
    627   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
    628   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    629 
    630   ModeValue = Mode ? BIT31 : 0;
    631   SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \
    632                                 ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
    633                                 ModeValue;
    634 
    635   Packet.InDataBuffer     = SwitchResp;
    636   Packet.InTransferLength = 64;
    637 
    638   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    639 
    640   return Status;
    641 }
    642 
    643 /**
    644   Send command SEND_STATUS to the addressed SD device to get its status register.
    645 
    646   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    647 
    648   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    649   @param[in]  Slot          The slot number of the SD card to send the command to.
    650   @param[in]  Rca           The relative device address of addressed device.
    651   @param[out] DevStatus     The returned device status.
    652 
    653   @retval EFI_SUCCESS       The operation is done correctly.
    654   @retval Others            The operation fails.
    655 
    656 **/
    657 EFI_STATUS
    658 SdCardSendStatus (
    659   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
    660   IN     UINT8                          Slot,
    661   IN     UINT16                         Rca,
    662      OUT UINT32                         *DevStatus
    663   )
    664 {
    665   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    666   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    667   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    668   EFI_STATUS                            Status;
    669 
    670   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    671   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    672   ZeroMem (&Packet, sizeof (Packet));
    673 
    674   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    675   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    676   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    677 
    678   SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS;
    679   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
    680   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    681   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
    682 
    683   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    684   if (!EFI_ERROR (Status)) {
    685     *DevStatus = SdMmcStatusBlk.Resp0;
    686   }
    687 
    688   return Status;
    689 }
    690 
    691 /**
    692   Send command SEND_TUNING_BLOCK to the SD device for HS200 optimal sampling point
    693   detection.
    694 
    695   It may be sent up to 40 times until the host finishes the tuning procedure.
    696 
    697   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
    698 
    699   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    700   @param[in] Slot           The slot number of the SD card to send the command to.
    701 
    702   @retval EFI_SUCCESS       The operation is done correctly.
    703   @retval Others            The operation fails.
    704 
    705 **/
    706 EFI_STATUS
    707 SdCardSendTuningBlk (
    708   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    709   IN UINT8                              Slot
    710   )
    711 {
    712   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
    713   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
    714   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
    715   EFI_STATUS                            Status;
    716   UINT8                                 TuningBlock[64];
    717 
    718   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
    719   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
    720   ZeroMem (&Packet, sizeof (Packet));
    721 
    722   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
    723   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
    724   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
    725 
    726   SdMmcCmdBlk.CommandIndex = SD_SEND_TUNING_BLOCK;
    727   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
    728   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
    729   SdMmcCmdBlk.CommandArgument = 0;
    730 
    731   Packet.InDataBuffer     = TuningBlock;
    732   Packet.InTransferLength = sizeof (TuningBlock);
    733 
    734   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
    735 
    736   return Status;
    737 }
    738 
    739 /**
    740   Tunning the sampling point of SDR104 or SDR50 bus speed mode.
    741 
    742   Command SD_SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the
    743   tuning procedure.
    744 
    745   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and
    746   SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.
    747 
    748   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
    749   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    750   @param[in] Slot           The slot number of the SD card to send the command to.
    751 
    752   @retval EFI_SUCCESS       The operation is done correctly.
    753   @retval Others            The operation fails.
    754 
    755 **/
    756 EFI_STATUS
    757 SdCardTuningClock (
    758   IN EFI_PCI_IO_PROTOCOL                *PciIo,
    759   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    760   IN UINT8                              Slot
    761   )
    762 {
    763   EFI_STATUS          Status;
    764   UINT8               HostCtrl2;
    765   UINT8               Retry;
    766 
    767   //
    768   // Notify the host that the sampling clock tuning procedure starts.
    769   //
    770   HostCtrl2 = BIT6;
    771   Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
    772   if (EFI_ERROR (Status)) {
    773     return Status;
    774   }
    775   //
    776   // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
    777   //
    778   Retry = 0;
    779   do {
    780     Status = SdCardSendTuningBlk (PassThru, Slot);
    781     if (EFI_ERROR (Status)) {
    782       DEBUG ((DEBUG_ERROR, "SdCardSendTuningBlk: Send tuning block fails with %r\n", Status));
    783       return Status;
    784     }
    785 
    786     Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
    787     if (EFI_ERROR (Status)) {
    788       return Status;
    789     }
    790 
    791     if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {
    792       break;
    793     }
    794     if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
    795       return EFI_SUCCESS;
    796     }
    797   } while (++Retry < 40);
    798 
    799   DEBUG ((DEBUG_ERROR, "SdCardTuningClock: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));
    800   //
    801   // Abort the tuning procedure and reset the tuning circuit.
    802   //
    803   HostCtrl2 = (UINT8)~(BIT6 | BIT7);
    804   Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
    805   if (EFI_ERROR (Status)) {
    806     return Status;
    807   }
    808   return EFI_DEVICE_ERROR;
    809 }
    810 
    811 /**
    812   Switch the bus width to specified width.
    813 
    814   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and
    815   SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.
    816 
    817   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
    818   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    819   @param[in] Slot           The slot number of the SD card to send the command to.
    820   @param[in] Rca            The relative device address to be assigned.
    821   @param[in] BusWidth       The bus width to be set, it could be 4 or 8.
    822 
    823   @retval EFI_SUCCESS       The operation is done correctly.
    824   @retval Others            The operation fails.
    825 
    826 **/
    827 EFI_STATUS
    828 SdCardSwitchBusWidth (
    829   IN EFI_PCI_IO_PROTOCOL                *PciIo,
    830   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    831   IN UINT8                              Slot,
    832   IN UINT16                             Rca,
    833   IN UINT8                              BusWidth
    834   )
    835 {
    836   EFI_STATUS          Status;
    837   UINT32              DevStatus;
    838 
    839   Status = SdCardSetBusWidth (PassThru, Slot, Rca, BusWidth);
    840   if (EFI_ERROR (Status)) {
    841     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status));
    842     return Status;
    843   }
    844 
    845   Status = SdCardSendStatus (PassThru, Slot, Rca, &DevStatus);
    846   if (EFI_ERROR (Status)) {
    847     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Send status fails with %r\n", Status));
    848     return Status;
    849   }
    850   //
    851   // Check the switch operation is really successful or not.
    852   //
    853   if ((DevStatus >> 16) != 0) {
    854     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));
    855     return EFI_DEVICE_ERROR;
    856   }
    857 
    858   Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);
    859 
    860   return Status;
    861 }
    862 
    863 /**
    864   Switch the high speed timing according to request.
    865 
    866   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and
    867   SD Host Controller Simplified Spec 3.0 section Figure 2-29 for details.
    868 
    869   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
    870   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
    871   @param[in] Slot           The slot number of the SD card to send the command to.
    872   @param[in] Rca            The relative device address to be assigned.
    873   @param[in] S18A           The boolean to show if it's a UHS-I SD card.
    874 
    875   @retval EFI_SUCCESS       The operation is done correctly.
    876   @retval Others            The operation fails.
    877 
    878 **/
    879 EFI_STATUS
    880 SdCardSetBusMode (
    881   IN EFI_PCI_IO_PROTOCOL                *PciIo,
    882   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
    883   IN UINT8                              Slot,
    884   IN UINT16                             Rca,
    885   IN BOOLEAN                            S18A
    886   )
    887 {
    888   EFI_STATUS                   Status;
    889   SD_MMC_HC_SLOT_CAP           *Capability;
    890   UINT32                       ClockFreq;
    891   UINT8                        BusWidth;
    892   UINT8                        AccessMode;
    893   UINT8                        HostCtrl1;
    894   UINT8                        HostCtrl2;
    895   UINT8                        SwitchResp[64];
    896   SD_MMC_HC_PRIVATE_DATA       *Private;
    897 
    898   Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
    899 
    900   Capability = &Private->Capability[Slot];
    901 
    902   Status = SdCardSelect (PassThru, Slot, Rca);
    903   if (EFI_ERROR (Status)) {
    904     return Status;
    905   }
    906 
    907   BusWidth = 4;
    908 
    909   Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);
    910   if (EFI_ERROR (Status)) {
    911     return Status;
    912   }
    913   //
    914   // Get the supported bus speed from SWITCH cmd return data group #1.
    915   //
    916   Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);
    917   if (EFI_ERROR (Status)) {
    918     return Status;
    919   }
    920   //
    921   // Calculate supported bus speed/bus width/clock frequency by host and device capability.
    922   //
    923   ClockFreq = 0;
    924   if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
    925     ClockFreq = 208;
    926     AccessMode = 3;
    927   } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
    928     ClockFreq = 100;
    929     AccessMode = 2;
    930   } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
    931     ClockFreq = 50;
    932     AccessMode = 4;
    933   } else if ((SwitchResp[13] & BIT1) != 0) {
    934     ClockFreq = 50;
    935     AccessMode = 1;
    936   } else {
    937     ClockFreq = 25;
    938     AccessMode = 0;
    939   }
    940 
    941   Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);
    942   if (EFI_ERROR (Status)) {
    943     return Status;
    944   }
    945 
    946   if ((SwitchResp[16] & 0xF) != AccessMode) {
    947     DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n", AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
    948     return EFI_DEVICE_ERROR;
    949   }
    950 
    951   DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
    952 
    953   //
    954   // Set to Hight Speed timing
    955   //
    956   if (AccessMode == 1) {
    957     HostCtrl1 = BIT2;
    958     Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
    959     if (EFI_ERROR (Status)) {
    960       return Status;
    961     }
    962   }
    963 
    964   HostCtrl2 = (UINT8)~0x7;
    965   Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
    966   if (EFI_ERROR (Status)) {
    967     return Status;
    968   }
    969   HostCtrl2 = AccessMode;
    970   Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
    971   if (EFI_ERROR (Status)) {
    972     return Status;
    973   }
    974 
    975   Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability);
    976   if (EFI_ERROR (Status)) {
    977     return Status;
    978   }
    979 
    980   if ((AccessMode == 3) || ((AccessMode == 2) && (Capability->TuningSDR50 != 0))) {
    981     Status = SdCardTuningClock (PciIo, PassThru, Slot);
    982     if (EFI_ERROR (Status)) {
    983       return Status;
    984     }
    985   }
    986 
    987   return Status;
    988 }
    989 
    990 /**
    991   Execute SD device identification procedure.
    992 
    993   Refer to SD Physical Layer Simplified Spec 4.1 Section 3.6 for details.
    994 
    995   @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
    996   @param[in] Slot           The slot number of the SD card to send the command to.
    997 
    998   @retval EFI_SUCCESS       There is a SD card.
    999   @retval Others            There is not a SD card.
   1000 
   1001 **/
   1002 EFI_STATUS
   1003 SdCardIdentification (
   1004   IN SD_MMC_HC_PRIVATE_DATA             *Private,
   1005   IN UINT8                              Slot
   1006   )
   1007 {
   1008   EFI_STATUS                     Status;
   1009   EFI_PCI_IO_PROTOCOL            *PciIo;
   1010   EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru;
   1011   UINT32                         Ocr;
   1012   UINT16                         Rca;
   1013   BOOLEAN                        Xpc;
   1014   BOOLEAN                        S18r;
   1015   UINT64                         MaxCurrent;
   1016   UINT16                         ControllerVer;
   1017   UINT8                          PowerCtrl;
   1018   UINT32                         PresentState;
   1019   UINT8                          HostCtrl2;
   1020 
   1021   PciIo    = Private->PciIo;
   1022   PassThru = &Private->PassThru;
   1023   //
   1024   // 1. Send Cmd0 to the device
   1025   //
   1026   Status = SdCardReset (PassThru, Slot);
   1027   if (EFI_ERROR (Status)) {
   1028     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd0 fails with %r\n", Status));
   1029     return Status;
   1030   }
   1031   //
   1032   // 2. Send Cmd8 to the device
   1033   //
   1034   Status = SdCardVoltageCheck (PassThru, Slot, 0x1, 0xFF);
   1035   if (EFI_ERROR (Status)) {
   1036     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd8 fails with %r\n", Status));
   1037     return Status;
   1038   }
   1039   //
   1040   // 3. Send SDIO Cmd5 to the device to the SDIO device OCR register.
   1041   //
   1042   Status = SdioSendOpCond (PassThru, Slot, 0, FALSE);
   1043   if (!EFI_ERROR (Status)) {
   1044     DEBUG ((DEBUG_INFO, "SdCardIdentification: Found SDIO device, ignore it as we don't support\n"));
   1045     return EFI_DEVICE_ERROR;
   1046   }
   1047   //
   1048   // 4. Send Acmd41 with voltage window 0 to the device
   1049   //
   1050   Status = SdCardSendOpCond (PassThru, Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);
   1051   if (EFI_ERROR (Status)) {
   1052     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing SdCardSendOpCond fails with %r\n", Status));
   1053     return EFI_DEVICE_ERROR;
   1054   }
   1055 
   1056   if (Private->Capability[Slot].Voltage33 != 0) {
   1057     //
   1058     // Support 3.3V
   1059     //
   1060     MaxCurrent = ((UINT32)Private->MaxCurrent[Slot] & 0xFF) * 4;
   1061   } else if (Private->Capability[Slot].Voltage30 != 0) {
   1062     //
   1063     // Support 3.0V
   1064     //
   1065     MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 8) & 0xFF) * 4;
   1066   } else if (Private->Capability[Slot].Voltage18 != 0) {
   1067     //
   1068     // Support 1.8V
   1069     //
   1070     MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 16) & 0xFF) * 4;
   1071   } else {
   1072     ASSERT (FALSE);
   1073     return EFI_DEVICE_ERROR;
   1074   }
   1075 
   1076   if (MaxCurrent >= 150) {
   1077     Xpc = TRUE;
   1078   } else {
   1079     Xpc = FALSE;
   1080   }
   1081 
   1082   Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
   1083   if (EFI_ERROR (Status)) {
   1084     return Status;
   1085   }
   1086 
   1087   if ((ControllerVer & 0xFF) == 2) {
   1088     S18r = TRUE;
   1089   } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
   1090     S18r = FALSE;
   1091   } else {
   1092     ASSERT (FALSE);
   1093     return EFI_UNSUPPORTED;
   1094   }
   1095   //
   1096   // 5. Repeatly send Acmd41 with supply voltage window to the device.
   1097   //    Note here we only support the cards complied with SD physical
   1098   //    layer simplified spec version 2.0 and version 3.0 and above.
   1099   //
   1100   do {
   1101     Status = SdCardSendOpCond (PassThru, Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);
   1102     if (EFI_ERROR (Status)) {
   1103       DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));
   1104       return EFI_DEVICE_ERROR;
   1105     }
   1106   } while ((Ocr & BIT31) == 0);
   1107 
   1108   //
   1109   // 6. If the S18A bit is set and the Host Controller supports 1.8V signaling
   1110   //    (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
   1111   //    Capabilities register), switch its voltage to 1.8V.
   1112   //
   1113   if ((Private->Capability[Slot].Sdr50 != 0 ||
   1114        Private->Capability[Slot].Sdr104 != 0 ||
   1115        Private->Capability[Slot].Ddr50 != 0) &&
   1116        ((Ocr & BIT24) != 0)) {
   1117     Status = SdCardVoltageSwitch (PassThru, Slot);
   1118     if (EFI_ERROR (Status)) {
   1119       DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardVoltageSwitch fails with %r\n", Status));
   1120       Status = EFI_DEVICE_ERROR;
   1121       goto Error;
   1122     } else {
   1123       Status = SdMmcHcStopClock (PciIo, Slot);
   1124       if (EFI_ERROR (Status)) {
   1125         Status = EFI_DEVICE_ERROR;
   1126         goto Error;
   1127       }
   1128 
   1129       SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
   1130       if (((PresentState >> 20) & 0xF) != 0) {
   1131         DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x\n", PresentState));
   1132         Status = EFI_DEVICE_ERROR;
   1133         goto Error;
   1134       }
   1135       HostCtrl2  = BIT3;
   1136       SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
   1137 
   1138       gBS->Stall (5000);
   1139 
   1140       SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
   1141       if ((HostCtrl2 & BIT3) == 0) {
   1142         DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with HostCtrl2 = 0x%x\n", HostCtrl2));
   1143         Status = EFI_DEVICE_ERROR;
   1144         goto Error;
   1145       }
   1146 
   1147       SdMmcHcInitClockFreq (PciIo, Slot, Private->Capability[Slot]);
   1148 
   1149       gBS->Stall (1000);
   1150 
   1151       SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
   1152       if (((PresentState >> 20) & 0xF) != 0xF) {
   1153         DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x, It should be 0xF\n", PresentState));
   1154         Status = EFI_DEVICE_ERROR;
   1155         goto Error;
   1156       }
   1157     }
   1158     DEBUG ((DEBUG_INFO, "SdCardIdentification: Switch to 1.8v signal voltage success\n"));
   1159   }
   1160 
   1161   Status = SdCardAllSendCid (PassThru, Slot);
   1162   if (EFI_ERROR (Status)) {
   1163     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardAllSendCid fails with %r\n", Status));
   1164     return Status;
   1165   }
   1166 
   1167   Status = SdCardSetRca (PassThru, Slot, &Rca);
   1168   if (EFI_ERROR (Status)) {
   1169     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardSetRca fails with %r\n", Status));
   1170     return Status;
   1171   }
   1172   //
   1173   // Enter Data Tranfer Mode.
   1174   //
   1175   DEBUG ((DEBUG_INFO, "SdCardIdentification: Found a SD device at slot [%d]\n", Slot));
   1176   Private->Slot[Slot].CardType = SdCardType;
   1177 
   1178   Status = SdCardSetBusMode (PciIo, PassThru, Slot, Rca, ((Ocr & BIT24) != 0));
   1179 
   1180   return Status;
   1181 
   1182 Error:
   1183   //
   1184   // Set SD Bus Power = 0
   1185   //
   1186   PowerCtrl = (UINT8)~BIT0;
   1187   Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_POWER_CTRL, sizeof (PowerCtrl), &PowerCtrl);
   1188   return EFI_DEVICE_ERROR;
   1189 }
   1190 
   1191