mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	For setting high speed in SD card, First CMD 6 (Switch) is send to check if card supports High Speed and Second command is send to switch card to high speed mode. In current inplementation, CMD 6 was sent only once to switch the card into HS mode without checking if card supports HS or not, which is not as per specification and also we are not setting the HS i.e. 50000000 but directly asking the card to switch to 26000000 which is incorrect as SD card supports either 25000000 or 50000000. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com> Reviewed-by: Jun Nie <jun.nie@linaro.org> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
		
			
				
	
	
		
			807 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			807 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/** @file
 | 
						|
*
 | 
						|
*  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
 | 
						|
*
 | 
						|
*  This program and the accompanying materials
 | 
						|
*  are licensed and made available under the terms and conditions of the BSD License
 | 
						|
*  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
*  http://opensource.org/licenses/bsd-license.php
 | 
						|
*
 | 
						|
*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
*
 | 
						|
**/
 | 
						|
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/TimerLib.h>
 | 
						|
 | 
						|
#include "Mmc.h"
 | 
						|
 | 
						|
typedef union {
 | 
						|
  UINT32 Raw;
 | 
						|
  OCR    Ocr;
 | 
						|
} OCR_RESPONSE;
 | 
						|
 | 
						|
#define MAX_RETRY_COUNT         1000
 | 
						|
#define CMD_RETRY_COUNT         20
 | 
						|
#define RCA_SHIFT_OFFSET        16
 | 
						|
#define EMMC_CARD_SIZE          512
 | 
						|
#define EMMC_ECSD_SIZE_OFFSET   53
 | 
						|
 | 
						|
#define EXTCSD_BUS_WIDTH        183
 | 
						|
#define EXTCSD_HS_TIMING        185
 | 
						|
 | 
						|
#define EMMC_TIMING_BACKWARD    0
 | 
						|
#define EMMC_TIMING_HS          1
 | 
						|
#define EMMC_TIMING_HS200       2
 | 
						|
#define EMMC_TIMING_HS400       3
 | 
						|
 | 
						|
#define EMMC_BUS_WIDTH_1BIT     0
 | 
						|
#define EMMC_BUS_WIDTH_4BIT     1
 | 
						|
#define EMMC_BUS_WIDTH_8BIT     2
 | 
						|
#define EMMC_BUS_WIDTH_DDR_4BIT 5
 | 
						|
#define EMMC_BUS_WIDTH_DDR_8BIT 6
 | 
						|
 | 
						|
#define EMMC_SWITCH_ERROR       (1 << 7)
 | 
						|
 | 
						|
#define SD_BUS_WIDTH_1BIT       (1 << 0)
 | 
						|
#define SD_BUS_WIDTH_4BIT       (1 << 2)
 | 
						|
 | 
						|
#define SD_CCC_SWITCH           (1 << 10)
 | 
						|
 | 
						|
#define DEVICE_STATE(x)         (((x) >> 9) & 0xf)
 | 
						|
typedef enum _EMMC_DEVICE_STATE {
 | 
						|
  EMMC_IDLE_STATE = 0,
 | 
						|
  EMMC_READY_STATE,
 | 
						|
  EMMC_IDENT_STATE,
 | 
						|
  EMMC_STBY_STATE,
 | 
						|
  EMMC_TRAN_STATE,
 | 
						|
  EMMC_DATA_STATE,
 | 
						|
  EMMC_RCV_STATE,
 | 
						|
  EMMC_PRG_STATE,
 | 
						|
  EMMC_DIS_STATE,
 | 
						|
  EMMC_BTST_STATE,
 | 
						|
  EMMC_SLP_STATE
 | 
						|
} EMMC_DEVICE_STATE;
 | 
						|
 | 
						|
UINT32 mEmmcRcaCount = 0;
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EmmcGetDeviceState (
 | 
						|
  IN  MMC_HOST_INSTANCE    *MmcHostInstance,
 | 
						|
  OUT EMMC_DEVICE_STATE    *State
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MMC_HOST_PROTOCOL *Host;
 | 
						|
  EFI_STATUS Status;
 | 
						|
  UINT32     Data, RCA;
 | 
						|
 | 
						|
  if (State == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Host = MmcHostInstance->MmcHost;
 | 
						|
  RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
 | 
						|
  Status = Host->SendCommand (Host, MMC_CMD13, RCA);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  if (Data & EMMC_SWITCH_ERROR) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  *State = DEVICE_STATE(Data);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EmmcSetEXTCSD (
 | 
						|
  IN MMC_HOST_INSTANCE     *MmcHostInstance,
 | 
						|
  UINT32                   ExtCmdIndex,
 | 
						|
  UINT32                   Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MMC_HOST_PROTOCOL *Host;
 | 
						|
  EMMC_DEVICE_STATE     State;
 | 
						|
  EFI_STATUS Status;
 | 
						|
  UINT32     Argument;
 | 
						|
 | 
						|
  Host  = MmcHostInstance->MmcHost;
 | 
						|
  Argument = EMMC_CMD6_ARG_ACCESS(3) | EMMC_CMD6_ARG_INDEX(ExtCmdIndex) |
 | 
						|
             EMMC_CMD6_ARG_VALUE(Value) | EMMC_CMD6_ARG_CMD_SET(1);
 | 
						|
  Status = Host->SendCommand (Host, MMC_CMD6, Argument);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to send CMD6, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  // Make sure device exiting prog mode
 | 
						|
  do {
 | 
						|
    Status = EmmcGetDeviceState (MmcHostInstance, &State);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to get device state, Status=%r.\n", Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } while (State == EMMC_PRG_STATE);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EmmcIdentificationMode (
 | 
						|
  IN MMC_HOST_INSTANCE     *MmcHostInstance,
 | 
						|
  IN OCR_RESPONSE           Response
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MMC_HOST_PROTOCOL *Host;
 | 
						|
  EFI_BLOCK_IO_MEDIA    *Media;
 | 
						|
  EFI_STATUS Status;
 | 
						|
  EMMC_DEVICE_STATE     State;
 | 
						|
  UINT32     RCA;
 | 
						|
 | 
						|
  Host  = MmcHostInstance->MmcHost;
 | 
						|
  Media = MmcHostInstance->BlockIo.Media;
 | 
						|
 | 
						|
  // Fetch card identity register
 | 
						|
  Status = Host->SendCommand (Host, MMC_CMD2, 0);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to send CMD2, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CIDData));
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): CID retrieval error, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Assign a relative address value to the card
 | 
						|
  MmcHostInstance->CardInfo.RCA = ++mEmmcRcaCount; // TODO: might need a more sophisticated way of doing this
 | 
						|
  RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
 | 
						|
  Status = Host->SendCommand (Host, MMC_CMD3, RCA);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): RCA set error, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Fetch card specific data
 | 
						|
  Status = Host->SendCommand (Host, MMC_CMD9, RCA);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to send CMD9, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CSDData));
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): CSD retrieval error, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Select the card
 | 
						|
  Status = Host->SendCommand (Host, MMC_CMD7, RCA);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));
 | 
						|
  }
 | 
						|
 | 
						|
  if (MMC_HOST_HAS_SETIOS(Host)) {
 | 
						|
    // Set 1-bit bus width
 | 
						|
    Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Set 1-bit bus width for EXTCSD
 | 
						|
    Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Fetch ECSD
 | 
						|
  MmcHostInstance->CardInfo.ECSDData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ECSD)));
 | 
						|
  if (MmcHostInstance->CardInfo.ECSDData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  Status = Host->SendCommand (Host, MMC_CMD8, 0);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)MmcHostInstance->CardInfo.ECSDData);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
 | 
						|
    goto FreePageExit;
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure device exiting data mode
 | 
						|
  do {
 | 
						|
    Status = EmmcGetDeviceState (MmcHostInstance, &State);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status));
 | 
						|
      goto FreePageExit;
 | 
						|
    }
 | 
						|
  } while (State == EMMC_DATA_STATE);
 | 
						|
 | 
						|
  // Set up media
 | 
						|
  Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
 | 
						|
  Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
 | 
						|
  Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT;
 | 
						|
  Media->LogicalBlocksPerPhysicalBlock = 1;
 | 
						|
  Media->IoAlign = 4;
 | 
						|
  // Compute last block using bits [215:212] of the ECSD
 | 
						|
  Media->LastBlock = MmcHostInstance->CardInfo.ECSDData->SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
 | 
						|
  // Cards <2GB in size, but the model does.
 | 
						|
 | 
						|
  // Setup card type
 | 
						|
  MmcHostInstance->CardInfo.CardType = EMMC_CARD;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
FreePageExit:
 | 
						|
  FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD)));
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
InitializeEmmcDevice (
 | 
						|
  IN  MMC_HOST_INSTANCE   *MmcHostInstance
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MMC_HOST_PROTOCOL *Host;
 | 
						|
  EFI_STATUS Status = EFI_SUCCESS;
 | 
						|
  ECSD       *ECSDData;
 | 
						|
  UINT32     BusClockFreq, Idx, BusMode;
 | 
						|
  UINT32     TimingMode[4] = {EMMCHS52DDR1V2, EMMCHS52DDR1V8, EMMCHS52, EMMCHS26};
 | 
						|
 | 
						|
  Host  = MmcHostInstance->MmcHost;
 | 
						|
  ECSDData = MmcHostInstance->CardInfo.ECSDData;
 | 
						|
  if (ECSDData->DEVICE_TYPE == EMMCBACKWARD)
 | 
						|
    return EFI_SUCCESS;
 | 
						|
 | 
						|
  if (!MMC_HOST_HAS_SETIOS(Host)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_HS_TIMING, EMMC_TIMING_HS);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to switch high speed mode, Status:%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Idx = 0; Idx < 4; Idx++) {
 | 
						|
    switch (TimingMode[Idx]) {
 | 
						|
    case EMMCHS52DDR1V2:
 | 
						|
    case EMMCHS52DDR1V8:
 | 
						|
    case EMMCHS52:
 | 
						|
      BusClockFreq = 52000000;
 | 
						|
      break;
 | 
						|
    case EMMCHS26:
 | 
						|
      BusClockFreq = 26000000;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
    Status = Host->SetIos (Host, BusClockFreq, 8, TimingMode[Idx]);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      switch (TimingMode[Idx]) {
 | 
						|
      case EMMCHS52DDR1V2:
 | 
						|
      case EMMCHS52DDR1V8:
 | 
						|
        BusMode = EMMC_BUS_WIDTH_DDR_8BIT;
 | 
						|
        break;
 | 
						|
      case EMMCHS52:
 | 
						|
      case EMMCHS26:
 | 
						|
        BusMode = EMMC_BUS_WIDTH_8BIT;
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        return EFI_UNSUPPORTED;
 | 
						|
      }
 | 
						|
      Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, BusMode);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to set EXTCSD bus width, Status:%r\n", Status));
 | 
						|
      }
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
UINT32
 | 
						|
CreateSwitchCmdArgument (
 | 
						|
  IN  UINT32 Mode,
 | 
						|
  IN  UINT8  Group,
 | 
						|
  IN  UINT8  Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32 Argument;
 | 
						|
 | 
						|
  Argument = Mode << 31 | 0x00FFFFFF;
 | 
						|
  Argument &= ~(0xF << (Group * 4));
 | 
						|
  Argument |= Value << (Group * 4);
 | 
						|
 | 
						|
  return Argument;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
InitializeSdMmcDevice (
 | 
						|
  IN  MMC_HOST_INSTANCE   *MmcHostInstance
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32        CmdArg;
 | 
						|
  UINT32        Response[4];
 | 
						|
  UINT32        Buffer[128];
 | 
						|
  UINT32        Speed;
 | 
						|
  UINTN         BlockSize;
 | 
						|
  UINTN         CardSize;
 | 
						|
  UINTN         NumBlocks;
 | 
						|
  BOOLEAN       CccSwitch;
 | 
						|
  SCR           Scr;
 | 
						|
  EFI_STATUS    Status;
 | 
						|
  EFI_MMC_HOST_PROTOCOL     *MmcHost;
 | 
						|
 | 
						|
  Speed = SD_DEFAULT_SPEED;
 | 
						|
  MmcHost = MmcHostInstance->MmcHost;
 | 
						|
 | 
						|
  // Send a command to get Card specific data
 | 
						|
  CmdArg = MmcHostInstance->CardInfo.RCA << 16;
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD9, CmdArg);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG((EFI_D_ERROR, "InitializeSdMmcDevice(MMC_CMD9): Error, Status=%r\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Read Response
 | 
						|
  Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CSD, Response);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG((EFI_D_ERROR, "InitializeSdMmcDevice(): Failed to receive CSD, Status=%r\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  PrintCSD (Response);
 | 
						|
  if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH) {
 | 
						|
    CccSwitch = TRUE;
 | 
						|
  } else {
 | 
						|
    CccSwitch = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
 | 
						|
    CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
 | 
						|
    NumBlocks = ((CardSize + 1) * 1024);
 | 
						|
    BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);
 | 
						|
  } else {
 | 
						|
    CardSize = MMC_CSD_GET_DEVICESIZE (Response);
 | 
						|
    NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT (Response) + 2));
 | 
						|
    BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);
 | 
						|
  }
 | 
						|
 | 
						|
  // For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
 | 
						|
  if (BlockSize > 512) {
 | 
						|
    NumBlocks = MultU64x32 (NumBlocks, BlockSize / 512);
 | 
						|
    BlockSize = 512;
 | 
						|
  }
 | 
						|
 | 
						|
  MmcHostInstance->BlockIo.Media->LastBlock    = (NumBlocks - 1);
 | 
						|
  MmcHostInstance->BlockIo.Media->BlockSize    = BlockSize;
 | 
						|
  MmcHostInstance->BlockIo.Media->ReadOnly     = MmcHost->IsReadOnly (MmcHost);
 | 
						|
  MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;
 | 
						|
  MmcHostInstance->BlockIo.Media->MediaId++;
 | 
						|
 | 
						|
  CmdArg = MmcHostInstance->CardInfo.RCA << 16;
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD7, CmdArg);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG((EFI_D_ERROR, "InitializeSdMmcDevice(MMC_CMD7): Error and Status = %r\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "%a (MMC_CMD55): Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "%a (MMC_CMD55): Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  if ((Response[0] & MMC_STATUS_APP_CMD) == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  /* SCR */
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status));
 | 
						|
    return Status;
 | 
						|
  } else {
 | 
						|
    Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    CopyMem (&Scr, Buffer, 8);
 | 
						|
    if (Scr.SD_SPEC == 2) {
 | 
						|
      if (Scr.SD_SPEC3 == 1) {
 | 
						|
	if (Scr.SD_SPEC4 == 1) {
 | 
						|
          DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 4.xx\n"));
 | 
						|
	} else {
 | 
						|
          DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 3.0x\n"));
 | 
						|
	}
 | 
						|
      } else {
 | 
						|
	if (Scr.SD_SPEC4 == 0) {
 | 
						|
          DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 2.0\n"));
 | 
						|
	} else {
 | 
						|
	  DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
 | 
						|
	}
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) {
 | 
						|
        if (Scr.SD_SPEC == 1) {
 | 
						|
	  DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.10\n"));
 | 
						|
	} else {
 | 
						|
	  DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.0\n"));
 | 
						|
	}
 | 
						|
      } else {
 | 
						|
        DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (CccSwitch) {
 | 
						|
    /* SD Switch, Mode:0, Group:0, Value:0 */
 | 
						|
    CmdArg = CreateSwitchCmdArgument(0, 0, 0);
 | 
						|
    Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
       return Status;
 | 
						|
    } else {
 | 
						|
      Status = MmcHost->ReadBlockData (MmcHost, 0, SWITCH_CMD_DATA_LENGTH, Buffer);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): ReadBlockData Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!(Buffer[3] & SD_HIGH_SPEED_SUPPORTED)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "%a : High Speed not supported by Card %r\n", __FUNCTION__, Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    Speed = SD_HIGH_SPEED;
 | 
						|
 | 
						|
    /* SD Switch, Mode:1, Group:0, Value:1 */
 | 
						|
    CmdArg = CreateSwitchCmdArgument(1, 0, 1);
 | 
						|
    Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
       return Status;
 | 
						|
    } else {
 | 
						|
      Status = MmcHost->ReadBlockData (MmcHost, 0, SWITCH_CMD_DATA_LENGTH, Buffer);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): ReadBlockData Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
 | 
						|
      if ((Buffer[4] & SWITCH_CMD_SUCCESS_MASK) != 0x01000000) {
 | 
						|
        DEBUG((DEBUG_ERROR, "Problem switching SD card into high-speed mode\n"));
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) {
 | 
						|
    CmdArg = MmcHostInstance->CardInfo.RCA << 16;
 | 
						|
    Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "%a (MMC_CMD55): Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    /* Width: 4 */
 | 
						|
    Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (MMC_HOST_HAS_SETIOS(MmcHost)) {
 | 
						|
    Status = MmcHost->SetIos (MmcHost, Speed, BUSWIDTH_4, EMMCBACKWARD);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "%a (SetIos): Error and Status = %r\n", __FUNCTION__, Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
MmcIdentificationMode (
 | 
						|
  IN MMC_HOST_INSTANCE     *MmcHostInstance
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  UINT32                  Response[4];
 | 
						|
  UINTN                   Timeout;
 | 
						|
  UINTN                   CmdArg;
 | 
						|
  BOOLEAN                 IsHCS;
 | 
						|
  EFI_MMC_HOST_PROTOCOL   *MmcHost;
 | 
						|
  OCR_RESPONSE            OcrResponse;
 | 
						|
 | 
						|
  MmcHost = MmcHostInstance->MmcHost;
 | 
						|
  CmdArg = 0;
 | 
						|
  IsHCS = FALSE;
 | 
						|
 | 
						|
  if (MmcHost == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // We can get into this function if we restart the identification mode
 | 
						|
  if (MmcHostInstance->State == MmcHwInitializationState) {
 | 
						|
    // Initialize the MMC Host HW
 | 
						|
    Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState, Status=%r.\n", Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD0, 0);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Status = MmcNotifyState (MmcHostInstance, MmcIdleState);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Send CMD1 to get OCR (MMC)
 | 
						|
  // This command only valid for MMC and eMMC
 | 
						|
  Timeout = MAX_RETRY_COUNT;
 | 
						|
  do {
 | 
						|
    Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB);
 | 
						|
    if (EFI_ERROR (Status))
 | 
						|
      break;
 | 
						|
    Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, (UINT32 *)&OcrResponse);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    Timeout--;
 | 
						|
  } while (!OcrResponse.Ocr.PowerUp && (Timeout > 0));
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    if (!OcrResponse.Ocr.PowerUp) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD1): Card initialisation failure, Status=%r.\n", Status));
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
    OcrResponse.Ocr.PowerUp = 0;
 | 
						|
    if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB) {
 | 
						|
      MmcHostInstance->CardInfo.OCRData.AccessMode = BIT1;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      MmcHostInstance->CardInfo.OCRData.AccessMode = 0x0;
 | 
						|
    }
 | 
						|
    // Check whether MMC or eMMC
 | 
						|
    if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB ||
 | 
						|
        OcrResponse.Raw == EMMC_CMD1_CAPACITY_LESS_THAN_2GB) {
 | 
						|
      return EmmcIdentificationMode (MmcHostInstance, OcrResponse);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Are we using SDIO ?
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD5, 0);
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported, Status=%r.\n", Status));
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
 | 
						|
  CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD8, CmdArg);
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));
 | 
						|
    IsHCS = TRUE;
 | 
						|
    Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R7, Response);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive response to CMD8, Status=%r.\n", Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    PrintResponseR1 (Response[0]);
 | 
						|
    // Check if it is valid response
 | 
						|
    if (Response[0] != CmdArg) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));
 | 
						|
  }
 | 
						|
 | 
						|
  // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.PowerUp == 1)
 | 
						|
  Timeout = MAX_RETRY_COUNT;
 | 
						|
  while (Timeout > 0) {
 | 
						|
    // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
 | 
						|
    Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, 0);
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      DEBUG ((EFI_D_INFO, "Card should be SD\n"));
 | 
						|
      if (IsHCS) {
 | 
						|
        MmcHostInstance->CardInfo.CardType = SD_CARD_2;
 | 
						|
      } else {
 | 
						|
        MmcHostInstance->CardInfo.CardType = SD_CARD;
 | 
						|
      }
 | 
						|
 | 
						|
      // Note: The first time CmdArg will be zero
 | 
						|
      CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];
 | 
						|
      if (IsHCS) {
 | 
						|
        CmdArg |= BIT30;
 | 
						|
      }
 | 
						|
      Status = MmcHost->SendCommand (MmcHost, MMC_ACMD41, CmdArg);
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
 | 
						|
          return Status;
 | 
						|
        }
 | 
						|
        ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      DEBUG ((EFI_D_INFO, "Card should be MMC\n"));
 | 
						|
      MmcHostInstance->CardInfo.CardType = MMC_CARD;
 | 
						|
 | 
						|
      Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, 0x800000);
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
 | 
						|
          return Status;
 | 
						|
        }
 | 
						|
        ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      if (!MmcHostInstance->CardInfo.OCRData.PowerUp) {
 | 
						|
        gBS->Stall (1);
 | 
						|
        Timeout--;
 | 
						|
      } else {
 | 
						|
        if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {
 | 
						|
          MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
 | 
						|
          DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
 | 
						|
        }
 | 
						|
        break;  // The MMC/SD card is ready. Continue the Identification Mode
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      gBS->Stall (1);
 | 
						|
      Timeout--;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Timeout == 0) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));
 | 
						|
    return EFI_NO_MEDIA;
 | 
						|
  } else {
 | 
						|
    PrintOCR (Response[0]);
 | 
						|
  }
 | 
						|
 | 
						|
  Status = MmcNotifyState (MmcHostInstance, MmcReadyState);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD2, 0);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CID, Response);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive CID, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  PrintCID (Response);
 | 
						|
 | 
						|
  Status = MmcHost->NotifyState (MmcHost, MmcIdentificationState);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Note, SD specifications say that "if the command execution causes a state change, it
 | 
						|
  // will be visible to the host in the response to the next command"
 | 
						|
  // The status returned for this CMD3 will be 2 - identification
 | 
						|
  //
 | 
						|
  CmdArg = 1;
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD3, CmdArg);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_RCA, Response);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive RCA, Status=%r.\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  PrintRCA (Response[0]);
 | 
						|
 | 
						|
  // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
 | 
						|
  if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {
 | 
						|
    MmcHostInstance->CardInfo.RCA = Response[0] >> 16;
 | 
						|
  } else {
 | 
						|
    MmcHostInstance->CardInfo.RCA = CmdArg;
 | 
						|
  }
 | 
						|
  Status = MmcNotifyState (MmcHostInstance, MmcStandByState);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
InitializeMmcDevice (
 | 
						|
  IN  MMC_HOST_INSTANCE   *MmcHostInstance
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_MMC_HOST_PROTOCOL   *MmcHost;
 | 
						|
  UINTN                   BlockCount;
 | 
						|
 | 
						|
  BlockCount = 1;
 | 
						|
  MmcHost = MmcHostInstance->MmcHost;
 | 
						|
 | 
						|
  Status = MmcIdentificationMode (MmcHostInstance);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error in Identification Mode, Status=%r\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error MmcTransferState, Status=%r\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
 | 
						|
    Status = InitializeSdMmcDevice (MmcHostInstance);
 | 
						|
  } else {
 | 
						|
    Status = InitializeEmmcDevice (MmcHostInstance);
 | 
						|
  }
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Set Block Length
 | 
						|
  Status = MmcHost->SendCommand (MmcHost, MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",
 | 
						|
                        MmcHostInstance->BlockIo.Media->BlockSize, Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Block Count (not used). Could return an error for SD card
 | 
						|
  if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {
 | 
						|
    Status = MmcHost->SendCommand (MmcHost, MMC_CMD23, BlockCount);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD23): Error, Status=%r\n", Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |