]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Omap35xxPkg/MMCHSDxe/MMCHS.c
ARM Packages: Fixed line endings
[mirror_edk2.git] / Omap35xxPkg / MMCHSDxe / MMCHS.c
index 61bf215f7ea4cbe685cfebab8ea623d7042bcac6..7d4e22f5246aad7fb22c06cb32229475718aa28f 100644 (file)
-/** @file
-  MMC/SD Card driver for OMAP 35xx (SDIO not supported)
-
-  This driver always produces a BlockIo protocol but it starts off with no Media
-  present. A TimerCallBack detects when media is inserted or removed and after 
-  a media change event a call to BlockIo ReadBlocks/WriteBlocks will cause the 
-  media to be detected (or removed) and the BlockIo Media structure will get
-  updated. No MMC/SD Card harward registers are updated until the first BlockIo
-  ReadBlocks/WriteBlocks after media has been insterted (booting with a card 
-  plugged in counts as an insertion event). 
-
-  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
-  
-  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 <Uefi.h>
-
-#include "MMCHS.h"
-
-EFI_BLOCK_IO_MEDIA gMMCHSMedia = {
-  SIGNATURE_32('s','d','i','o'),            // MediaId
-  TRUE,                                     // RemovableMedia
-  FALSE,                                    // MediaPresent
-  FALSE,                                    // LogicalPartition
-  FALSE,                                    // ReadOnly
-  FALSE,                                    // WriteCaching
-  512,                                      // BlockSize
-  4,                                        // IoAlign
-  0,                                        // Pad
-  0                                         // LastBlock
-};
-
-typedef struct {
-  VENDOR_DEVICE_PATH  Mmc;
-  EFI_DEVICE_PATH     End;
-} MMCHS_DEVICE_PATH;
-
-MMCHS_DEVICE_PATH gMmcHsDevicePath = {
-  {
-    HARDWARE_DEVICE_PATH,
-    HW_VENDOR_DP,
-    (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
-    (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
-    0xb615f1f5, 0x5088, 0x43cd, 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00 
-  },
-  {
-    END_DEVICE_PATH_TYPE,
-    END_ENTIRE_DEVICE_PATH_SUBTYPE,
-    sizeof (EFI_DEVICE_PATH_PROTOCOL),
-    0
-  }
-};
-
-CARD_INFO                  gCardInfo;
-EMBEDDED_EXTERNAL_DEVICE   *gTPS65950;
-EFI_EVENT                  gTimerEvent;
-BOOLEAN                    gMediaChange = FALSE;
-
-//
-// Internal Functions
-//
-
-
-VOID
-ParseCardCIDData (
-  UINT32 Response0, 
-  UINT32 Response1, 
-  UINT32 Response2,
-  UINT32 Response3
-  )
-{
-  gCardInfo.CIDData.MDT = ((Response0 >> 8) & 0xFFF);
-  gCardInfo.CIDData.PSN = (((Response0 >> 24) & 0xFF) | ((Response1 & 0xFFFFFF) << 8));
-  gCardInfo.CIDData.PRV = ((Response1 >> 24) & 0xFF);
-  gCardInfo.CIDData.PNM[4] = ((Response2) & 0xFF);
-  gCardInfo.CIDData.PNM[3] = ((Response2 >> 8) & 0xFF);
-  gCardInfo.CIDData.PNM[2] = ((Response2 >> 16) & 0xFF);
-  gCardInfo.CIDData.PNM[1] = ((Response2 >> 24) & 0xFF);
-  gCardInfo.CIDData.PNM[0] = ((Response3) & 0xFF);
-  gCardInfo.CIDData.OID = ((Response3 >> 8) & 0xFFFF);
-  gCardInfo.CIDData.MID = ((Response3 >> 24) & 0xFF);
-}
-
-
-VOID
-UpdateMMCHSClkFrequency (
-  UINTN NewCLKD
-  )
-{
-  //Set Clock enable to 0x0 to not provide the clock to the card
-  MmioAnd32 (MMCHS_SYSCTL, ~CEN);
-
-  //Set new clock frequency.
-  MmioAndThenOr32 (MMCHS_SYSCTL, ~CLKD_MASK, NewCLKD << 6); 
-
-  //Poll till Internal Clock Stable
-  while ((MmioRead32 (MMCHS_SYSCTL) & ICS_MASK) != ICS);
-
-  //Set Clock enable to 0x1 to provide the clock to the card
-  MmioOr32 (MMCHS_SYSCTL, CEN);
-}
-
-
-EFI_STATUS
-SendCmd (
-  UINTN Cmd,
-  UINTN CmdInterruptEnableVal,
-  UINTN CmdArgument
-  )
-{
-  UINTN MmcStatus;
-  UINTN RetryCount = 0;
-
-  //Check if command line is in use or not. Poll till command line is available.
-  while ((MmioRead32 (MMCHS_PSTATE) & DATI_MASK) == DATI_NOT_ALLOWED);
-
-  //Provide the block size.
-  MmioWrite32 (MMCHS_BLK, BLEN_512BYTES);
-
-  //Setting Data timeout counter value to max value.
-  MmioAndThenOr32 (MMCHS_SYSCTL, ~DTO_MASK, DTO_VAL);
-
-  //Clear Status register.
-  MmioWrite32 (MMCHS_STAT, 0xFFFFFFFF);
-
-  //Set command argument register
-  MmioWrite32 (MMCHS_ARG, CmdArgument);
-
-  //Enable interrupt enable events to occur
-  MmioWrite32 (MMCHS_IE, CmdInterruptEnableVal);
-
-  //Send a command
-  MmioWrite32 (MMCHS_CMD, Cmd);
-
-  //Check for the command status.
-  while (RetryCount < MAX_RETRY_COUNT) {
-    do {
-      MmcStatus = MmioRead32 (MMCHS_STAT);
-    } while (MmcStatus == 0);
-
-    //Read status of command response
-    if ((MmcStatus & ERRI) != 0) {
-
-      //Perform soft-reset for mmci_cmd line.
-      MmioOr32 (MMCHS_SYSCTL, SRC);
-      while ((MmioRead32 (MMCHS_SYSCTL) & SRC));
-
-      DEBUG ((EFI_D_INFO, "MmcStatus: %x\n", MmcStatus));
-      return EFI_DEVICE_ERROR;
-    }
-
-    //Check if command is completed.
-    if ((MmcStatus & CC) == CC) {
-      MmioWrite32 (MMCHS_STAT, CC);
-      break;
-    }
-
-    RetryCount++;
-  }
-
-  if (RetryCount == MAX_RETRY_COUNT) {
-    return EFI_TIMEOUT;
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-VOID
-GetBlockInformation (
-  UINTN *BlockSize,
-  UINTN *NumBlocks
-  )
-{
-  CSD_SDV2 *CsdSDV2Data;
-  UINTN    CardSize;
-
-  if (gCardInfo.CardType == SD_CARD_2_HIGH) {
-    CsdSDV2Data = (CSD_SDV2 *)&gCardInfo.CSDData;
-
-    //Populate BlockSize.
-    *BlockSize = (0x1UL << CsdSDV2Data->READ_BL_LEN);
-
-    //Calculate Total number of blocks.
-    CardSize = CsdSDV2Data->C_SIZELow16 | (CsdSDV2Data->C_SIZEHigh6 << 2);
-    *NumBlocks = ((CardSize + 1) * 1024);
-  } else {
-    //Populate BlockSize.
-    *BlockSize = (0x1UL << gCardInfo.CSDData.READ_BL_LEN);
-
-    //Calculate Total number of blocks.
-    CardSize = gCardInfo.CSDData.C_SIZELow2 | (gCardInfo.CSDData.C_SIZEHigh10 << 2);
-    *NumBlocks = (CardSize + 1) * (1 << (gCardInfo.CSDData.C_SIZE_MULT + 2));
-  }
-
-  //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
-  if (*BlockSize > 512) {
-    *NumBlocks = MultU64x32(*NumBlocks, *BlockSize/2);
-    *BlockSize = 512;
-  }
-
-  DEBUG ((EFI_D_INFO, "Card type: %x, BlockSize: %x, NumBlocks: %x\n", gCardInfo.CardType, *BlockSize, *NumBlocks));
-}
-
-
-VOID
-CalculateCardCLKD (
-  UINTN *ClockFrequencySelect
-  )
-{
-  UINT8    MaxDataTransferRate;
-  UINTN    TransferRateValue = 0;
-  UINTN    TimeValue = 0 ;
-  UINTN    Frequency = 0;
-
-  MaxDataTransferRate = gCardInfo.CSDData.TRAN_SPEED;
-
-  //Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED)
-  switch (MaxDataTransferRate & 0x7) {
-    case 0:
-      TransferRateValue = 100 * 1000;
-      break;
-
-    case 1:
-      TransferRateValue = 1 * 1000 * 1000;
-      break;
-
-    case 2:
-      TransferRateValue = 10 * 1000 * 1000;
-      break;
-
-    case 3:
-      TransferRateValue = 100 * 1000 * 1000;
-      break;
-
-    default:
-      DEBUG((EFI_D_ERROR, "Invalid parameter.\n"));
-      ASSERT(FALSE);
-  }
-
-  //Calculate Time value (Bits 6:3 of TRAN_SPEED)
-  switch ((MaxDataTransferRate >> 3) & 0xF) {
-    case 1:
-      TimeValue = 10;
-      break;
-
-    case 2:
-      TimeValue = 12;
-      break;
-
-    case 3:
-      TimeValue = 13;
-      break;
-
-    case 4:
-      TimeValue = 15;
-      break;
-
-    case 5:
-      TimeValue = 20;
-      break;
-
-    case 6:
-      TimeValue = 25;
-      break;
-
-    case 7:
-      TimeValue = 30;
-      break;
-
-    case 8:
-      TimeValue = 35;
-      break;
-
-    case 9:
-      TimeValue = 40;
-      break;
-
-    case 10:
-      TimeValue = 45;
-      break;
-
-    case 11:
-      TimeValue = 50;
-      break;
-
-    case 12:
-      TimeValue = 55;
-      break;
-
-    case 13:
-      TimeValue = 60;
-      break;
-
-    case 14:
-      TimeValue = 70;
-      break;
-
-    case 15:
-      TimeValue = 80;
-      break;
-
-    default:
-      DEBUG((EFI_D_ERROR, "Invalid parameter.\n"));
-      ASSERT(FALSE);
-  }
-
-  Frequency = TransferRateValue * TimeValue/10;
-
-  //Calculate Clock divider value to program in MMCHS_SYSCTL[CLKD] field.
-  *ClockFrequencySelect = ((MMC_REFERENCE_CLK/Frequency) + 1);
-
-  DEBUG ((EFI_D_INFO, "MaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", MaxDataTransferRate, Frequency/1000, *ClockFrequencySelect));
-}
-
-
-VOID
-GetCardConfigurationData (
-  VOID
-  )
-{
-  UINTN  BlockSize;
-  UINTN  NumBlocks;
-  UINTN  ClockFrequencySelect;
-
-  //Calculate BlockSize and Total number of blocks in the detected card.
-  GetBlockInformation(&BlockSize, &NumBlocks);
-  gCardInfo.BlockSize = BlockSize;
-  gCardInfo.NumBlocks = NumBlocks;
-
-  //Calculate Card clock divider value.
-  CalculateCardCLKD(&ClockFrequencySelect);
-  gCardInfo.ClockFrequencySelect = ClockFrequencySelect;
-}
-
-
-EFI_STATUS
-InitializeMMCHS (
-  VOID
-  )
-{
-  UINT8      Data = 0;
-  EFI_STATUS Status;
-
-  //Select Device group to belong to P1 device group in Power IC.
-  Data = DEV_GRP_P1;
-  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEV_GRP), 1, &Data);
-  ASSERT_EFI_ERROR(Status);
-
-  //Configure voltage regulator for MMC1 in Power IC to output 3.0 voltage.
-  Data = VSEL_3_00V;
-  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEDICATED_REG), 1, &Data);
-  ASSERT_EFI_ERROR(Status);
-  
-  //After ramping up voltage, set VDDS stable bit to indicate that voltage level is stable.
-  MmioOr32 (CONTROL_PBIAS_LITE, (PBIASLITEVMODE0 | PBIASLITEPWRDNZ0 | PBIASSPEEDCTRL0 | PBIASLITEVMODE1 | PBIASLITEWRDNZ1));
-
-  // Enable WP GPIO
-  MmioAndThenOr32 (GPIO1_BASE + GPIO_OE, ~BIT23, BIT23);
-
-  // Enable Card Detect
-  Data = CARD_DETECT_ENABLE;
-  gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, TPS65950_GPIO_CTRL), 1, &Data);
-
-
-  return Status;
-}
-
-
-EFI_STATUS
-PerformCardIdenfication (
-  VOID
-  )
-{
-  EFI_STATUS Status;
-  UINTN      CmdArgument = 0;
-  UINTN      Response = 0;
-  UINTN      RetryCount = 0;
-  BOOLEAN    SDCmd8Supported = FALSE;
-
-  //Enable interrupts.
-  MmioWrite32 (MMCHS_IE, (BADA_EN | CERR_EN | DEB_EN | DCRC_EN | DTO_EN | CIE_EN |
-    CEB_EN | CCRC_EN | CTO_EN | BRR_EN | BWR_EN | TC_EN | CC_EN));
-
-  //Controller INIT procedure start.
-  MmioOr32 (MMCHS_CON, INIT);
-  MmioWrite32 (MMCHS_CMD, 0x00000000);
-  while (!(MmioRead32 (MMCHS_STAT) & CC));
-
-  //Wait for 1 ms
-  gBS->Stall(1000);
-
-  //Set CC bit to 0x1 to clear the flag
-  MmioOr32 (MMCHS_STAT, CC);
-
-  //Retry INIT procedure.
-  MmioWrite32 (MMCHS_CMD, 0x00000000);
-  while (!(MmioRead32 (MMCHS_STAT) & CC));
-
-  //End initialization sequence
-  MmioAnd32 (MMCHS_CON, ~INIT);
-
-  MmioOr32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_ON));
-
-  //Change clock frequency to 400KHz to fit protocol
-  UpdateMMCHSClkFrequency(CLKD_400KHZ);
-
-  MmioOr32 (MMCHS_CON, OD);
-
-  //Send CMD0 command.
-  Status = SendCmd (CMD0, CMD0_INT_EN, CmdArgument);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((EFI_D_ERROR, "Cmd0 fails.\n"));
-    return Status;
-  }
-
-  DEBUG ((EFI_D_INFO, "CMD0 response: %x\n", MmioRead32 (MMCHS_RSP10)));
-
-  //Send CMD5 command. 
-  Status = SendCmd (CMD5, CMD5_INT_EN, CmdArgument);
-  if (Status == EFI_SUCCESS) {
-    DEBUG ((EFI_D_ERROR, "CMD5 Success. SDIO card. Follow SDIO card specification.\n"));
-    DEBUG ((EFI_D_INFO, "CMD5 response: %x\n", MmioRead32 (MMCHS_RSP10)));
-    //NOTE: Returning unsupported error for now. Need to implement SDIO specification.
-    return EFI_UNSUPPORTED; 
-  } else {
-    DEBUG ((EFI_D_INFO, "CMD5 fails. Not an SDIO card.\n"));
-  }
-
-  MmioOr32 (MMCHS_SYSCTL, SRC);
-  gBS->Stall(1000);
-  while ((MmioRead32 (MMCHS_SYSCTL) & SRC));
-
-  //Send CMD8 command. (New v2.00 command for Voltage check)
-  //Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass.
-  //MMC & SD1.1 card will fail this command.
-  CmdArgument = CMD8_ARG;
-  Status = SendCmd (CMD8, CMD8_INT_EN, CmdArgument);
-  if (Status == EFI_SUCCESS) {
-    Response = MmioRead32 (MMCHS_RSP10);
-    DEBUG ((EFI_D_INFO, "CMD8 success. CMD8 response: %x\n", Response));
-    if (Response != CmdArgument) {
-      return EFI_DEVICE_ERROR;
-    }
-    DEBUG ((EFI_D_INFO, "Card is SD2.0\n"));
-    SDCmd8Supported = TRUE; //Supports high capacity.
-  } else {
-    DEBUG ((EFI_D_INFO, "CMD8 fails. Not an SD2.0 card.\n"));
-  }
-
-  MmioOr32 (MMCHS_SYSCTL, SRC);
-  gBS->Stall(1000);
-  while ((MmioRead32 (MMCHS_SYSCTL) & SRC));
-
-  //Poll till card is busy
-  while (RetryCount < MAX_RETRY_COUNT) {
-    //Send CMD55 command. 
-    CmdArgument = 0;
-    Status = SendCmd (CMD55, CMD55_INT_EN, CmdArgument);
-    if (Status == EFI_SUCCESS) {
-      DEBUG ((EFI_D_INFO, "CMD55 success. CMD55 response: %x\n", MmioRead32 (MMCHS_RSP10)));
-      gCardInfo.CardType = SD_CARD;
-    } else {
-      DEBUG ((EFI_D_INFO, "CMD55 fails.\n"));
-      gCardInfo.CardType = MMC_CARD;
-    }
-
-    //Send appropriate command for the card type which got detected.
-    if (gCardInfo.CardType == SD_CARD) {
-      CmdArgument = ((UINTN *) &(gCardInfo.OCRData))[0];
-
-      //Set HCS bit.
-      if (SDCmd8Supported) {
-        CmdArgument |= HCS;
-      }
-
-      Status = SendCmd (ACMD41, ACMD41_INT_EN, CmdArgument);
-      if (EFI_ERROR(Status)) {
-        DEBUG ((EFI_D_INFO, "ACMD41 fails.\n"));
-        return Status;
-      }
-      ((UINT32 *) &(gCardInfo.OCRData))[0] = MmioRead32 (MMCHS_RSP10);
-      DEBUG ((EFI_D_INFO, "SD card detected. ACMD41 OCR: %x\n", ((UINT32 *) &(gCardInfo.OCRData))[0]));
-    } else if (gCardInfo.CardType == MMC_CARD) {
-      CmdArgument = 0;
-      Status = SendCmd (CMD1, CMD1_INT_EN, CmdArgument);
-      if (EFI_ERROR(Status)) {
-        DEBUG ((EFI_D_INFO, "CMD1 fails.\n"));
-        return Status;
-      }
-      Response = MmioRead32 (MMCHS_RSP10);
-      DEBUG ((EFI_D_INFO, "MMC card detected.. CMD1 response: %x\n", Response));
-
-      //NOTE: For now, I am skipping this since I only have an SD card.
-      //Compare card OCR and host OCR (Section 22.6.1.3.2.4)
-      return EFI_UNSUPPORTED; //For now, MMC is not supported.
-    }
-
-    //Poll the card until it is out of its power-up sequence.
-    if (gCardInfo.OCRData.Busy == 1) {
-
-      if (SDCmd8Supported) {
-        gCardInfo.CardType = SD_CARD_2;
-      }
-
-      //Card is ready. Check CCS (Card capacity status) bit (bit#30).
-      //SD 2.0 standard card will response with CCS 0, SD high capacity card will respond with CCS 1.
-      if (gCardInfo.OCRData.AccessMode & BIT1) {
-        gCardInfo.CardType = SD_CARD_2_HIGH;
-        DEBUG ((EFI_D_INFO, "High capacity card.\n"));
-      } else {
-        DEBUG ((EFI_D_INFO, "Standard capacity card.\n"));
-      }
-
-      break;
-    }
-
-    gBS->Stall(1000);
-    RetryCount++;
-  }
-
-  if (RetryCount == MAX_RETRY_COUNT) {
-    DEBUG ((EFI_D_ERROR, "Timeout error. RetryCount: %d\n", RetryCount));
-    return EFI_TIMEOUT;
-  }
-
-  //Read CID data.
-  CmdArgument = 0;
-  Status = SendCmd (CMD2, CMD2_INT_EN, CmdArgument);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((EFI_D_ERROR, "CMD2 fails. Status: %x\n", Status));
-    return Status;
-  }
-
-  DEBUG ((EFI_D_INFO, "CMD2 response: %x %x %x %x\n", MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76)));
-
-  //Parse CID register data.
-  ParseCardCIDData(MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76));
-
-  //Read RCA
-  CmdArgument = 0;
-  Status = SendCmd (CMD3, CMD3_INT_EN, CmdArgument);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((EFI_D_ERROR, "CMD3 fails. Status: %x\n", Status));
-    return Status;
-  }
-
-  //Set RCA for the detected card. RCA is CMD3 response.
-  gCardInfo.RCA = (MmioRead32 (MMCHS_RSP10) >> 16);
-  DEBUG ((EFI_D_INFO, "CMD3 response: RCA %x\n", gCardInfo.RCA));
-
-  //MMC Bus setting change after card identification.
-  MmioAnd32 (MMCHS_CON, ~OD);
-  MmioOr32 (MMCHS_HCTL, SDVS_3_0_V);
-  UpdateMMCHSClkFrequency(CLKD_400KHZ); //Set the clock frequency to 400KHz.
-
-  return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-GetCardSpecificData (
-  VOID
-  )
-{
-  EFI_STATUS Status;
-  UINTN      CmdArgument;
-
-  //Send CMD9 to retrieve CSD.
-  CmdArgument = gCardInfo.RCA << 16;
-  Status = SendCmd (CMD9, CMD9_INT_EN, CmdArgument);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((EFI_D_ERROR, "CMD9 fails. Status: %x\n", Status));
-    return Status;
-  }
-
-  //Populate 128-bit CSD register data.
-  ((UINT32 *)&(gCardInfo.CSDData))[0] = MmioRead32 (MMCHS_RSP10);
-  ((UINT32 *)&(gCardInfo.CSDData))[1] = MmioRead32 (MMCHS_RSP32);
-  ((UINT32 *)&(gCardInfo.CSDData))[2] = MmioRead32 (MMCHS_RSP54);
-  ((UINT32 *)&(gCardInfo.CSDData))[3] = MmioRead32 (MMCHS_RSP76);
-
-  DEBUG ((EFI_D_INFO, "CMD9 response: %x %x %x %x\n", MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76)));
-
-  //Calculate total number of blocks and max. data transfer rate supported by the detected card.
-  GetCardConfigurationData();
-
-  //Change MMCHS clock frequency to what detected card can support.
-  UpdateMMCHSClkFrequency(gCardInfo.ClockFrequencySelect);
-
-  return Status;
-}
-
-
-EFI_STATUS
-PerformCardConfiguration (
-  VOID
-  )
-{
-  UINTN      CmdArgument = 0;
-  EFI_STATUS Status;
-
-  //Send CMD7
-  CmdArgument = gCardInfo.RCA << 16;
-  Status = SendCmd (CMD7, CMD7_INT_EN, CmdArgument);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((EFI_D_ERROR, "CMD7 fails. Status: %x\n", Status));
-    return Status;
-  }
-
-  //Send CMD16 to set the block length
-  CmdArgument = gCardInfo.BlockSize;
-  Status = SendCmd (CMD16, CMD16_INT_EN, CmdArgument);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((EFI_D_ERROR, "CMD16 fails. Status: %x\n", Status));
-    return Status;
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-ReadBlockData (
-  IN  EFI_BLOCK_IO_PROTOCOL       *This,
-  OUT VOID                        *Buffer
-  )
-{
-  UINTN MmcStatus;
-  UINTN *DataBuffer = Buffer;
-  UINTN DataSize = This->Media->BlockSize/4;
-  UINTN Count;
-  UINTN RetryCount = 0;
-
-  //Check controller status to make sure there is no error.
-  while (RetryCount < MAX_RETRY_COUNT) {
-    do {
-      //Read Status.
-      MmcStatus = MmioRead32 (MMCHS_STAT);
-    } while(MmcStatus == 0);
-
-    //Check if Buffer read ready (BRR) bit is set?
-    if (MmcStatus & BRR) {
-
-      //Clear BRR bit
-      MmioOr32 (MMCHS_STAT, BRR);
-
-      //Read block worth of data.
-      for (Count = 0; Count < DataSize; Count++) {
-        *DataBuffer++ = MmioRead32 (MMCHS_DATA);
-      }
-      break;
-    }
-    RetryCount++;
-  }
-
-  if (RetryCount == MAX_RETRY_COUNT) {
-    return EFI_TIMEOUT;
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-WriteBlockData (
-  IN  EFI_BLOCK_IO_PROTOCOL       *This,
-  OUT VOID                        *Buffer
-  )
-{
-  UINTN MmcStatus;
-  UINTN *DataBuffer = Buffer;
-  UINTN DataSize = This->Media->BlockSize/4;
-  UINTN Count;
-  UINTN RetryCount = 0;
-
-  //Check controller status to make sure there is no error.
-  while (RetryCount < MAX_RETRY_COUNT) {
-    do {
-      //Read Status.
-      MmcStatus = MmioRead32 (MMCHS_STAT);
-    } while(MmcStatus == 0);
-
-    //Check if Buffer write ready (BWR) bit is set?
-    if (MmcStatus & BWR) {
-
-      //Clear BWR bit
-      MmioOr32 (MMCHS_STAT, BWR);
-
-      //Write block worth of data.
-      for (Count = 0; Count < DataSize; Count++) {
-        MmioWrite32 (MMCHS_DATA, *DataBuffer++);
-      }
-
-      break;
-    }
-    RetryCount++;
-  }
-
-  if (RetryCount == MAX_RETRY_COUNT) {
-    return EFI_TIMEOUT;
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-TransferBlockData (
-  IN  EFI_BLOCK_IO_PROTOCOL       *This,
-  OUT VOID                        *Buffer,
-  IN  OPERATION_TYPE              OperationType
-  )
-{
-  EFI_STATUS Status;
-  UINTN      MmcStatus;
-  UINTN      RetryCount = 0;
-
-  //Read or Write data.
-  if (OperationType == READ) {
-    Status = ReadBlockData(This, Buffer);
-    if (EFI_ERROR(Status)) {
-      DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n"));
-      return Status;
-    }
-  } else if (OperationType == WRITE) {
-    Status = WriteBlockData(This, Buffer);
-    if (EFI_ERROR(Status)) {
-      DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n"));
-      return Status;
-    }
-  }
-
-  //Check for the Transfer completion.
-  while (RetryCount < MAX_RETRY_COUNT) {
-    //Read Status
-    do {
-      MmcStatus = MmioRead32 (MMCHS_STAT);
-    } while (MmcStatus == 0);
-
-    //Check if Transfer complete (TC) bit is set?
-    if (MmcStatus & TC) {
-      break;
-    } else {
-      DEBUG ((EFI_D_ERROR, "MmcStatus for TC: %x\n", MmcStatus));
-      //Check if DEB, DCRC or DTO interrupt occured.
-      if ((MmcStatus & DEB) | (MmcStatus & DCRC) | (MmcStatus & DTO)) {
-        //There was an error during the data transfer.
-
-        //Set SRD bit to 1 and wait until it return to 0x0.
-        MmioOr32 (MMCHS_SYSCTL, SRD);
-        while((MmioRead32 (MMCHS_SYSCTL) & SRD) != 0x0);
-
-        return EFI_DEVICE_ERROR;
-      }
-    }
-    RetryCount++;
-  } 
-
-  if (RetryCount == MAX_RETRY_COUNT) {
-    DEBUG ((EFI_D_ERROR, "TransferBlockData timed out.\n"));
-    return EFI_TIMEOUT;
-  }
-
-  return EFI_SUCCESS;
-}
-
-BOOLEAN
-CardPresent (
-  VOID
-  )
-{
-  EFI_STATUS  Status;
-  UINT8       Data;
-
-  //
-  // Card detect is a GPIO0 on the TPS65950
-  //
-  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATAIN1), 1, &Data);
-  if (EFI_ERROR (Status)) {
-    return FALSE;
-  }
-
-  if ((Data & CARD_DETECT_BIT) == CARD_DETECT_BIT) {
-    // No Card present
-    return FALSE;
-  } else {
-    return TRUE;
-  }
-}
-
-EFI_STATUS
-DetectCard (
-  VOID
-  )
-{
-  EFI_STATUS    Status;
-
-  if (!CardPresent ()) {
-    return EFI_NO_MEDIA;
-  }
-
-  //Initialize MMC host controller clocks.
-  Status = InitializeMMCHS ();
-  if (EFI_ERROR(Status)) {
-    DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status));
-    return Status;
-  }
-
-  //Software reset of the MMCHS host controller.
-  MmioWrite32 (MMCHS_SYSCONFIG, SOFTRESET);
-  gBS->Stall(1000);
-  while ((MmioRead32 (MMCHS_SYSSTATUS) & RESETDONE_MASK) != RESETDONE);
-
-  //Soft reset for all.
-  MmioWrite32 (MMCHS_SYSCTL, SRA);
-  gBS->Stall(1000);
-  while ((MmioRead32 (MMCHS_SYSCTL) & SRA) != 0x0);
-
-  //Voltage capabilities initialization. Activate VS18 and VS30.
-  MmioOr32 (MMCHS_CAPA, (VS30 | VS18));
-
-  //Wakeup configuration
-  MmioOr32 (MMCHS_SYSCONFIG, ENAWAKEUP);
-  MmioOr32 (MMCHS_HCTL, IWE);
-
-  //MMCHS Controller default initialization
-  MmioOr32 (MMCHS_CON, (OD | DW8_1_4_BIT | CEATA_OFF));
-
-  MmioWrite32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_OFF));
-
-  //Enable internal clock
-  MmioOr32 (MMCHS_SYSCTL, ICE);
-
-  //Set the clock frequency to 80KHz.
-  UpdateMMCHSClkFrequency (CLKD_80KHZ);
-
-  //Enable SD bus power.
-  MmioOr32 (MMCHS_HCTL, (SDBP_ON));
-
-  //Poll till SD bus power bit is set.
-  while ((MmioRead32 (MMCHS_HCTL) & SDBP_MASK) != SDBP_ON);
-
-  //Card idenfication
-  Status = PerformCardIdenfication ();
-  if (EFI_ERROR(Status)) {
-    DEBUG ((EFI_D_ERROR, "No MMC/SD card detected.\n"));
-    return Status;
-  }
-  
-  //Get CSD (Card specific data) for the detected card.
-  Status = GetCardSpecificData();
-  if (EFI_ERROR(Status)) {
-    return Status;
-  }
-  
-  //Configure the card in data transfer mode.
-  Status = PerformCardConfiguration();
-  if (EFI_ERROR(Status)) {
-    return Status;
-  }
-
-  //Patch the Media structure.
-  gMMCHSMedia.LastBlock    = (gCardInfo.NumBlocks - 1);
-  gMMCHSMedia.BlockSize    = gCardInfo.BlockSize;
-  gMMCHSMedia.ReadOnly     = (MmioRead32 (GPIO1_BASE + GPIO_DATAIN) & BIT23) == BIT23;
-  gMMCHSMedia.MediaPresent = TRUE; 
-  gMMCHSMedia.MediaId++; 
-  gMediaChange = FALSE;
-
-  return Status;
-}
-
-
-EFI_STATUS
-SdReadWrite (
-  IN EFI_BLOCK_IO_PROTOCOL    *This,
-  IN  UINTN                   Lba, 
-  OUT VOID                    *Buffer, 
-  IN  UINTN                   BufferSize,
-  IN  OPERATION_TYPE          OperationType
-  )
-{
-  EFI_STATUS Status = EFI_SUCCESS;
-  UINTN      RetryCount = 0;
-  UINTN      NumBlocks;
-  UINTN      Cmd = 0;
-  UINTN      CmdInterruptEnable = 0;
-  UINTN      CmdArgument = 0;
+/** @file\r
+  MMC/SD Card driver for OMAP 35xx (SDIO not supported)\r
+\r
+  This driver always produces a BlockIo protocol but it starts off with no Media\r
+  present. A TimerCallBack detects when media is inserted or removed and after \r
+  a media change event a call to BlockIo ReadBlocks/WriteBlocks will cause the \r
+  media to be detected (or removed) and the BlockIo Media structure will get\r
+  updated. No MMC/SD Card harward registers are updated until the first BlockIo\r
+  ReadBlocks/WriteBlocks after media has been insterted (booting with a card \r
+  plugged in counts as an insertion event). \r
+\r
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+  \r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "MMCHS.h"\r
+\r
+EFI_BLOCK_IO_MEDIA gMMCHSMedia = {\r
+  SIGNATURE_32('s','d','i','o'),            // MediaId\r
+  TRUE,                                     // RemovableMedia\r
+  FALSE,                                    // MediaPresent\r
+  FALSE,                                    // LogicalPartition\r
+  FALSE,                                    // ReadOnly\r
+  FALSE,                                    // WriteCaching\r
+  512,                                      // BlockSize\r
+  4,                                        // IoAlign\r
+  0,                                        // Pad\r
+  0                                         // LastBlock\r
+};\r
+\r
+typedef struct {\r
+  VENDOR_DEVICE_PATH  Mmc;\r
+  EFI_DEVICE_PATH     End;\r
+} MMCHS_DEVICE_PATH;\r
+\r
+MMCHS_DEVICE_PATH gMmcHsDevicePath = {\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_VENDOR_DP,\r
+    (UINT8)(sizeof(VENDOR_DEVICE_PATH)),\r
+    (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),\r
+    0xb615f1f5, 0x5088, 0x43cd, 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00 \r
+  },\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    sizeof (EFI_DEVICE_PATH_PROTOCOL),\r
+    0\r
+  }\r
+};\r
+\r
+CARD_INFO                  gCardInfo;\r
+EMBEDDED_EXTERNAL_DEVICE   *gTPS65950;\r
+EFI_EVENT                  gTimerEvent;\r
+BOOLEAN                    gMediaChange = FALSE;\r
+\r
+//\r
+// Internal Functions\r
+//\r
+\r
+\r
+VOID\r
+ParseCardCIDData (\r
+  UINT32 Response0, \r
+  UINT32 Response1, \r
+  UINT32 Response2,\r
+  UINT32 Response3\r
+  )\r
+{\r
+  gCardInfo.CIDData.MDT = ((Response0 >> 8) & 0xFFF);\r
+  gCardInfo.CIDData.PSN = (((Response0 >> 24) & 0xFF) | ((Response1 & 0xFFFFFF) << 8));\r
+  gCardInfo.CIDData.PRV = ((Response1 >> 24) & 0xFF);\r
+  gCardInfo.CIDData.PNM[4] = ((Response2) & 0xFF);\r
+  gCardInfo.CIDData.PNM[3] = ((Response2 >> 8) & 0xFF);\r
+  gCardInfo.CIDData.PNM[2] = ((Response2 >> 16) & 0xFF);\r
+  gCardInfo.CIDData.PNM[1] = ((Response2 >> 24) & 0xFF);\r
+  gCardInfo.CIDData.PNM[0] = ((Response3) & 0xFF);\r
+  gCardInfo.CIDData.OID = ((Response3 >> 8) & 0xFFFF);\r
+  gCardInfo.CIDData.MID = ((Response3 >> 24) & 0xFF);\r
+}\r
+\r
+\r
+VOID\r
+UpdateMMCHSClkFrequency (\r
+  UINTN NewCLKD\r
+  )\r
+{\r
+  //Set Clock enable to 0x0 to not provide the clock to the card\r
+  MmioAnd32 (MMCHS_SYSCTL, ~CEN);\r
+\r
+  //Set new clock frequency.\r
+  MmioAndThenOr32 (MMCHS_SYSCTL, ~CLKD_MASK, NewCLKD << 6); \r
+\r
+  //Poll till Internal Clock Stable\r
+  while ((MmioRead32 (MMCHS_SYSCTL) & ICS_MASK) != ICS);\r
+\r
+  //Set Clock enable to 0x1 to provide the clock to the card\r
+  MmioOr32 (MMCHS_SYSCTL, CEN);\r
+}\r
+\r
+\r
+EFI_STATUS\r
+SendCmd (\r
+  UINTN Cmd,\r
+  UINTN CmdInterruptEnableVal,\r
+  UINTN CmdArgument\r
+  )\r
+{\r
+  UINTN MmcStatus;\r
+  UINTN RetryCount = 0;\r
+\r
+  //Check if command line is in use or not. Poll till command line is available.\r
+  while ((MmioRead32 (MMCHS_PSTATE) & DATI_MASK) == DATI_NOT_ALLOWED);\r
+\r
+  //Provide the block size.\r
+  MmioWrite32 (MMCHS_BLK, BLEN_512BYTES);\r
+\r
+  //Setting Data timeout counter value to max value.\r
+  MmioAndThenOr32 (MMCHS_SYSCTL, ~DTO_MASK, DTO_VAL);\r
+\r
+  //Clear Status register.\r
+  MmioWrite32 (MMCHS_STAT, 0xFFFFFFFF);\r
+\r
+  //Set command argument register\r
+  MmioWrite32 (MMCHS_ARG, CmdArgument);\r
+\r
+  //Enable interrupt enable events to occur\r
+  MmioWrite32 (MMCHS_IE, CmdInterruptEnableVal);\r
+\r
+  //Send a command\r
+  MmioWrite32 (MMCHS_CMD, Cmd);\r
+\r
+  //Check for the command status.\r
+  while (RetryCount < MAX_RETRY_COUNT) {\r
+    do {\r
+      MmcStatus = MmioRead32 (MMCHS_STAT);\r
+    } while (MmcStatus == 0);\r
+\r
+    //Read status of command response\r
+    if ((MmcStatus & ERRI) != 0) {\r
+\r
+      //Perform soft-reset for mmci_cmd line.\r
+      MmioOr32 (MMCHS_SYSCTL, SRC);\r
+      while ((MmioRead32 (MMCHS_SYSCTL) & SRC));\r
+\r
+      DEBUG ((EFI_D_INFO, "MmcStatus: %x\n", MmcStatus));\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+\r
+    //Check if command is completed.\r
+    if ((MmcStatus & CC) == CC) {\r
+      MmioWrite32 (MMCHS_STAT, CC);\r
+      break;\r
+    }\r
+\r
+    RetryCount++;\r
+  }\r
+\r
+  if (RetryCount == MAX_RETRY_COUNT) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+VOID\r
+GetBlockInformation (\r
+  UINTN *BlockSize,\r
+  UINTN *NumBlocks\r
+  )\r
+{\r
+  CSD_SDV2 *CsdSDV2Data;\r
+  UINTN    CardSize;\r
+\r
+  if (gCardInfo.CardType == SD_CARD_2_HIGH) {\r
+    CsdSDV2Data = (CSD_SDV2 *)&gCardInfo.CSDData;\r
+\r
+    //Populate BlockSize.\r
+    *BlockSize = (0x1UL << CsdSDV2Data->READ_BL_LEN);\r
+\r
+    //Calculate Total number of blocks.\r
+    CardSize = CsdSDV2Data->C_SIZELow16 | (CsdSDV2Data->C_SIZEHigh6 << 2);\r
+    *NumBlocks = ((CardSize + 1) * 1024);\r
+  } else {\r
+    //Populate BlockSize.\r
+    *BlockSize = (0x1UL << gCardInfo.CSDData.READ_BL_LEN);\r
+\r
+    //Calculate Total number of blocks.\r
+    CardSize = gCardInfo.CSDData.C_SIZELow2 | (gCardInfo.CSDData.C_SIZEHigh10 << 2);\r
+    *NumBlocks = (CardSize + 1) * (1 << (gCardInfo.CSDData.C_SIZE_MULT + 2));\r
+  }\r
+\r
+  //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.\r
+  if (*BlockSize > 512) {\r
+    *NumBlocks = MultU64x32(*NumBlocks, *BlockSize/2);\r
+    *BlockSize = 512;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "Card type: %x, BlockSize: %x, NumBlocks: %x\n", gCardInfo.CardType, *BlockSize, *NumBlocks));\r
+}\r
+\r
+\r
+VOID\r
+CalculateCardCLKD (\r
+  UINTN *ClockFrequencySelect\r
+  )\r
+{\r
+  UINT8    MaxDataTransferRate;\r
+  UINTN    TransferRateValue = 0;\r
+  UINTN    TimeValue = 0 ;\r
+  UINTN    Frequency = 0;\r
+\r
+  MaxDataTransferRate = gCardInfo.CSDData.TRAN_SPEED;\r
+\r
+  // For SD Cards  we would need to send CMD6 to set\r
+  // speeds abouve 25MHz. High Speed mode 50 MHz and up\r
+\r
+  //Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED)\r
+  switch (MaxDataTransferRate & 0x7) {\r
+    case 0:\r
+      TransferRateValue = 100 * 1000;\r
+      break;\r
+\r
+    case 1:\r
+      TransferRateValue = 1 * 1000 * 1000;\r
+      break;\r
+\r
+    case 2:\r
+      TransferRateValue = 10 * 1000 * 1000;\r
+      break;\r
+\r
+    case 3:\r
+      TransferRateValue = 100 * 1000 * 1000;\r
+      break;\r
+\r
+    default:\r
+      DEBUG((EFI_D_ERROR, "Invalid parameter.\n"));\r
+      ASSERT(FALSE);\r
+  }\r
+\r
+  //Calculate Time value (Bits 6:3 of TRAN_SPEED)\r
+  switch ((MaxDataTransferRate >> 3) & 0xF) {\r
+    case 1:\r
+      TimeValue = 10;\r
+      break;\r
+\r
+    case 2:\r
+      TimeValue = 12;\r
+      break;\r
+\r
+    case 3:\r
+      TimeValue = 13;\r
+      break;\r
+\r
+    case 4:\r
+      TimeValue = 15;\r
+      break;\r
+\r
+    case 5:\r
+      TimeValue = 20;\r
+      break;\r
+\r
+    case 6:\r
+      TimeValue = 25;\r
+      break;\r
+\r
+    case 7:\r
+      TimeValue = 30;\r
+      break;\r
+\r
+    case 8:\r
+      TimeValue = 35;\r
+      break;\r
+\r
+    case 9:\r
+      TimeValue = 40;\r
+      break;\r
+\r
+    case 10:\r
+      TimeValue = 45;\r
+      break;\r
+\r
+    case 11:\r
+      TimeValue = 50;\r
+      break;\r
+\r
+    case 12:\r
+      TimeValue = 55;\r
+      break;\r
+\r
+    case 13:\r
+      TimeValue = 60;\r
+      break;\r
+\r
+    case 14:\r
+      TimeValue = 70;\r
+      break;\r
+\r
+    case 15:\r
+      TimeValue = 80;\r
+      break;\r
+\r
+    default:\r
+      DEBUG((EFI_D_ERROR, "Invalid parameter.\n"));\r
+      ASSERT(FALSE);\r
+  }\r
+\r
+  Frequency = TransferRateValue * TimeValue/10;\r
+\r
+  //Calculate Clock divider value to program in MMCHS_SYSCTL[CLKD] field.\r
+  *ClockFrequencySelect = ((MMC_REFERENCE_CLK/Frequency) + 1);\r
+\r
+  DEBUG ((EFI_D_INFO, "MaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", MaxDataTransferRate, Frequency/1000, *ClockFrequencySelect));\r
+}\r
+\r
+\r
+VOID\r
+GetCardConfigurationData (\r
+  VOID\r
+  )\r
+{\r
+  UINTN  BlockSize;\r
+  UINTN  NumBlocks;\r
+  UINTN  ClockFrequencySelect;\r
+\r
+  //Calculate BlockSize and Total number of blocks in the detected card.\r
+  GetBlockInformation(&BlockSize, &NumBlocks);\r
+  gCardInfo.BlockSize = BlockSize;\r
+  gCardInfo.NumBlocks = NumBlocks;\r
+\r
+  //Calculate Card clock divider value.\r
+  CalculateCardCLKD(&ClockFrequencySelect);\r
+  gCardInfo.ClockFrequencySelect = ClockFrequencySelect;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+InitializeMMCHS (\r
+  VOID\r
+  )\r
+{\r
+  UINT8      Data = 0;\r
+  EFI_STATUS Status;\r
+\r
+  //Select Device group to belong to P1 device group in Power IC.\r
+  Data = DEV_GRP_P1;\r
+  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEV_GRP), 1, &Data);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //Configure voltage regulator for MMC1 in Power IC to output 3.0 voltage.\r
+  Data = VSEL_3_00V;\r
+  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEDICATED_REG), 1, &Data);\r
+  ASSERT_EFI_ERROR(Status);\r
+  \r
+  //After ramping up voltage, set VDDS stable bit to indicate that voltage level is stable.\r
+  MmioOr32 (CONTROL_PBIAS_LITE, (PBIASLITEVMODE0 | PBIASLITEPWRDNZ0 | PBIASSPEEDCTRL0 | PBIASLITEVMODE1 | PBIASLITEWRDNZ1));\r
+\r
+  // Enable WP GPIO\r
+  MmioAndThenOr32 (GPIO1_BASE + GPIO_OE, ~BIT23, BIT23);\r
+\r
+  // Enable Card Detect\r
+  Data = CARD_DETECT_ENABLE;\r
+  gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, TPS65950_GPIO_CTRL), 1, &Data);\r
+\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+PerformCardIdenfication (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN      CmdArgument = 0;\r
+  UINTN      Response = 0;\r
+  UINTN      RetryCount = 0;\r
+  BOOLEAN    SDCmd8Supported = FALSE;\r
+\r
+  //Enable interrupts.\r
+  MmioWrite32 (MMCHS_IE, (BADA_EN | CERR_EN | DEB_EN | DCRC_EN | DTO_EN | CIE_EN |\r
+    CEB_EN | CCRC_EN | CTO_EN | BRR_EN | BWR_EN | TC_EN | CC_EN));\r
+\r
+  //Controller INIT procedure start.\r
+  MmioOr32 (MMCHS_CON, INIT);\r
+  MmioWrite32 (MMCHS_CMD, 0x00000000);\r
+  while (!(MmioRead32 (MMCHS_STAT) & CC));\r
+\r
+  //Wait for 1 ms\r
+  gBS->Stall(1000);\r
+\r
+  //Set CC bit to 0x1 to clear the flag\r
+  MmioOr32 (MMCHS_STAT, CC);\r
+\r
+  //Retry INIT procedure.\r
+  MmioWrite32 (MMCHS_CMD, 0x00000000);\r
+  while (!(MmioRead32 (MMCHS_STAT) & CC));\r
+\r
+  //End initialization sequence\r
+  MmioAnd32 (MMCHS_CON, ~INIT);\r
+\r
+  MmioOr32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_ON));\r
+\r
+  //Change clock frequency to 400KHz to fit protocol\r
+  UpdateMMCHSClkFrequency(CLKD_400KHZ);\r
+\r
+  MmioOr32 (MMCHS_CON, OD);\r
+\r
+  //Send CMD0 command.\r
+  Status = SendCmd (CMD0, CMD0_INT_EN, CmdArgument);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Cmd0 fails.\n"));\r
+    return Status;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "CMD0 response: %x\n", MmioRead32 (MMCHS_RSP10)));\r
+\r
+  //Send CMD5 command. \r
+  Status = SendCmd (CMD5, CMD5_INT_EN, CmdArgument);\r
+  if (Status == EFI_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "CMD5 Success. SDIO card. Follow SDIO card specification.\n"));\r
+    DEBUG ((EFI_D_INFO, "CMD5 response: %x\n", MmioRead32 (MMCHS_RSP10)));\r
+    //NOTE: Returning unsupported error for now. Need to implement SDIO specification.\r
+    return EFI_UNSUPPORTED; \r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "CMD5 fails. Not an SDIO card.\n"));\r
+  }\r
+\r
+  MmioOr32 (MMCHS_SYSCTL, SRC);\r
+  gBS->Stall(1000);\r
+  while ((MmioRead32 (MMCHS_SYSCTL) & SRC));\r
+\r
+  //Send CMD8 command. (New v2.00 command for Voltage check)\r
+  //Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass.\r
+  //MMC & SD1.1 card will fail this command.\r
+  CmdArgument = CMD8_ARG;\r
+  Status = SendCmd (CMD8, CMD8_INT_EN, CmdArgument);\r
+  if (Status == EFI_SUCCESS) {\r
+    Response = MmioRead32 (MMCHS_RSP10);\r
+    DEBUG ((EFI_D_INFO, "CMD8 success. CMD8 response: %x\n", Response));\r
+    if (Response != CmdArgument) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    DEBUG ((EFI_D_INFO, "Card is SD2.0\n"));\r
+    SDCmd8Supported = TRUE; //Supports high capacity.\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "CMD8 fails. Not an SD2.0 card.\n"));\r
+  }\r
+\r
+  MmioOr32 (MMCHS_SYSCTL, SRC);\r
+  gBS->Stall(1000);\r
+  while ((MmioRead32 (MMCHS_SYSCTL) & SRC));\r
+\r
+  //Poll till card is busy\r
+  while (RetryCount < MAX_RETRY_COUNT) {\r
+    //Send CMD55 command. \r
+    CmdArgument = 0;\r
+    Status = SendCmd (CMD55, CMD55_INT_EN, CmdArgument);\r
+    if (Status == EFI_SUCCESS) {\r
+      DEBUG ((EFI_D_INFO, "CMD55 success. CMD55 response: %x\n", MmioRead32 (MMCHS_RSP10)));\r
+      gCardInfo.CardType = SD_CARD;\r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "CMD55 fails.\n"));\r
+      gCardInfo.CardType = MMC_CARD;\r
+    }\r
+\r
+    //Send appropriate command for the card type which got detected.\r
+    if (gCardInfo.CardType == SD_CARD) {\r
+      CmdArgument = ((UINTN *) &(gCardInfo.OCRData))[0];\r
+\r
+      //Set HCS bit.\r
+      if (SDCmd8Supported) {\r
+        CmdArgument |= HCS;\r
+      }\r
+\r
+      Status = SendCmd (ACMD41, ACMD41_INT_EN, CmdArgument);\r
+      if (EFI_ERROR(Status)) {\r
+        DEBUG ((EFI_D_INFO, "ACMD41 fails.\n"));\r
+        return Status;\r
+      }\r
+      ((UINT32 *) &(gCardInfo.OCRData))[0] = MmioRead32 (MMCHS_RSP10);\r
+      DEBUG ((EFI_D_INFO, "SD card detected. ACMD41 OCR: %x\n", ((UINT32 *) &(gCardInfo.OCRData))[0]));\r
+    } else if (gCardInfo.CardType == MMC_CARD) {\r
+      CmdArgument = 0;\r
+      Status = SendCmd (CMD1, CMD1_INT_EN, CmdArgument);\r
+      if (EFI_ERROR(Status)) {\r
+        DEBUG ((EFI_D_INFO, "CMD1 fails.\n"));\r
+        return Status;\r
+      }\r
+      Response = MmioRead32 (MMCHS_RSP10);\r
+      DEBUG ((EFI_D_INFO, "MMC card detected.. CMD1 response: %x\n", Response));\r
+\r
+      //NOTE: For now, I am skipping this since I only have an SD card.\r
+      //Compare card OCR and host OCR (Section 22.6.1.3.2.4)\r
+      return EFI_UNSUPPORTED; //For now, MMC is not supported.\r
+    }\r
+\r
+    //Poll the card until it is out of its power-up sequence.\r
+    if (gCardInfo.OCRData.Busy == 1) {\r
+\r
+      if (SDCmd8Supported) {\r
+        gCardInfo.CardType = SD_CARD_2;\r
+      }\r
+\r
+      //Card is ready. Check CCS (Card capacity status) bit (bit#30).\r
+      //SD 2.0 standard card will response with CCS 0, SD high capacity card will respond with CCS 1.\r
+      if (gCardInfo.OCRData.AccessMode & BIT1) {\r
+        gCardInfo.CardType = SD_CARD_2_HIGH;\r
+        DEBUG ((EFI_D_INFO, "High capacity card.\n"));\r
+      } else {\r
+        DEBUG ((EFI_D_INFO, "Standard capacity card.\n"));\r
+      }\r
+\r
+      break;\r
+    }\r
+\r
+    gBS->Stall(1000);\r
+    RetryCount++;\r
+  }\r
+\r
+  if (RetryCount == MAX_RETRY_COUNT) {\r
+    DEBUG ((EFI_D_ERROR, "Timeout error. RetryCount: %d\n", RetryCount));\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  //Read CID data.\r
+  CmdArgument = 0;\r
+  Status = SendCmd (CMD2, CMD2_INT_EN, CmdArgument);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "CMD2 fails. Status: %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "CMD2 response: %x %x %x %x\n", MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76)));\r
+\r
+  //Parse CID register data.\r
+  ParseCardCIDData(MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76));\r
+\r
+  //Read RCA\r
+  CmdArgument = 0;\r
+  Status = SendCmd (CMD3, CMD3_INT_EN, CmdArgument);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "CMD3 fails. Status: %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //Set RCA for the detected card. RCA is CMD3 response.\r
+  gCardInfo.RCA = (MmioRead32 (MMCHS_RSP10) >> 16);\r
+  DEBUG ((EFI_D_INFO, "CMD3 response: RCA %x\n", gCardInfo.RCA));\r
+\r
+  //MMC Bus setting change after card identification.\r
+  MmioAnd32 (MMCHS_CON, ~OD);\r
+  MmioOr32 (MMCHS_HCTL, SDVS_3_0_V);\r
+  UpdateMMCHSClkFrequency(CLKD_400KHZ); //Set the clock frequency to 400KHz.\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+GetCardSpecificData (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN      CmdArgument;\r
+\r
+  //Send CMD9 to retrieve CSD.\r
+  CmdArgument = gCardInfo.RCA << 16;\r
+  Status = SendCmd (CMD9, CMD9_INT_EN, CmdArgument);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "CMD9 fails. Status: %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //Populate 128-bit CSD register data.\r
+  ((UINT32 *)&(gCardInfo.CSDData))[0] = MmioRead32 (MMCHS_RSP10);\r
+  ((UINT32 *)&(gCardInfo.CSDData))[1] = MmioRead32 (MMCHS_RSP32);\r
+  ((UINT32 *)&(gCardInfo.CSDData))[2] = MmioRead32 (MMCHS_RSP54);\r
+  ((UINT32 *)&(gCardInfo.CSDData))[3] = MmioRead32 (MMCHS_RSP76);\r
+\r
+  DEBUG ((EFI_D_INFO, "CMD9 response: %x %x %x %x\n", MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76)));\r
+\r
+  //Calculate total number of blocks and max. data transfer rate supported by the detected card.\r
+  GetCardConfigurationData();\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+PerformCardConfiguration (\r
+  VOID\r
+  )\r
+{\r
+  UINTN      CmdArgument = 0;\r
+  EFI_STATUS Status;\r
+\r
+  //Send CMD7\r
+  CmdArgument = gCardInfo.RCA << 16;\r
+  Status = SendCmd (CMD7, CMD7_INT_EN, CmdArgument);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "CMD7 fails. Status: %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  if ((gCardInfo.CardType != UNKNOWN_CARD) && (gCardInfo.CardType != MMC_CARD)) {\r
+    // We could read SCR register, but SD Card Phys spec stats any SD Card shall\r
+    // set SCR.SD_BUS_WIDTHS to support 4-bit mode, so why bother?\r
\r
+    // Send ACMD6 (application specific commands must be prefixed with CMD55)\r
+    Status = SendCmd (CMD55, CMD55_INT_EN, CmdArgument);\r
+    if (!EFI_ERROR (Status)) {\r
+      // set device into 4-bit data bus mode\r
+      Status = SendCmd (ACMD6, ACMD6_INT_EN, 0x2);\r
+      if (!EFI_ERROR (Status)) {\r
+        // Set host controler into 4-bit mode\r
+        MmioOr32 (MMCHS_HCTL, DTW_4_BIT);\r
+        DEBUG ((EFI_D_INFO, "SD Memory Card set to 4-bit mode\n"));\r
+      }\r
+    }\r
+  }\r
+\r
+  //Send CMD16 to set the block length\r
+  CmdArgument = gCardInfo.BlockSize;\r
+  Status = SendCmd (CMD16, CMD16_INT_EN, CmdArgument);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "CMD16 fails. Status: %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //Change MMCHS clock frequency to what detected card can support.\r
+  UpdateMMCHSClkFrequency(gCardInfo.ClockFrequencySelect);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+ReadBlockData (\r
+  IN  EFI_BLOCK_IO_PROTOCOL       *This,\r
+  OUT VOID                        *Buffer\r
+  )\r
+{\r
+  UINTN MmcStatus;\r
+  UINTN *DataBuffer = Buffer;\r
+  UINTN DataSize = This->Media->BlockSize/4;\r
+  UINTN Count;\r
+  UINTN RetryCount = 0;\r
+\r
+  //Check controller status to make sure there is no error.\r
+  while (RetryCount < MAX_RETRY_COUNT) {\r
+    do {\r
+      //Read Status.\r
+      MmcStatus = MmioRead32 (MMCHS_STAT);\r
+    } while(MmcStatus == 0);\r
+\r
+    //Check if Buffer read ready (BRR) bit is set?\r
+    if (MmcStatus & BRR) {\r
+\r
+      //Clear BRR bit\r
+      MmioOr32 (MMCHS_STAT, BRR);\r
+\r
+      //Read block worth of data.\r
+      for (Count = 0; Count < DataSize; Count++) {\r
+        *DataBuffer++ = MmioRead32 (MMCHS_DATA);\r
+      }\r
+      break;\r
+    }\r
+    RetryCount++;\r
+  }\r
+\r
+  if (RetryCount == MAX_RETRY_COUNT) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+WriteBlockData (\r
+  IN  EFI_BLOCK_IO_PROTOCOL       *This,\r
+  OUT VOID                        *Buffer\r
+  )\r
+{\r
+  UINTN MmcStatus;\r
+  UINTN *DataBuffer = Buffer;\r
+  UINTN DataSize = This->Media->BlockSize/4;\r
+  UINTN Count;\r
+  UINTN RetryCount = 0;\r
+\r
+  //Check controller status to make sure there is no error.\r
+  while (RetryCount < MAX_RETRY_COUNT) {\r
+    do {\r
+      //Read Status.\r
+      MmcStatus = MmioRead32 (MMCHS_STAT);\r
+    } while(MmcStatus == 0);\r
+\r
+    //Check if Buffer write ready (BWR) bit is set?\r
+    if (MmcStatus & BWR) {\r
+\r
+      //Clear BWR bit\r
+      MmioOr32 (MMCHS_STAT, BWR);\r
+\r
+      //Write block worth of data.\r
+      for (Count = 0; Count < DataSize; Count++) {\r
+        MmioWrite32 (MMCHS_DATA, *DataBuffer++);\r
+      }\r
+\r
+      break;\r
+    }\r
+    RetryCount++;\r
+  }\r
+\r
+  if (RetryCount == MAX_RETRY_COUNT) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DmaBlocks (\r
+  IN EFI_BLOCK_IO_PROTOCOL        *This,\r
+  IN  UINTN                       Lba,\r
+  IN OUT VOID                     *Buffer,\r
+  IN  UINTN                       BlockCount,\r
+  IN  OPERATION_TYPE              OperationType\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINTN                 DmaSize = 0;\r
+  UINTN                 Cmd = 0;\r
+  UINTN                 CmdInterruptEnable;\r
+  UINTN                 CmdArgument;\r
+  VOID                  *BufferMap;\r
+  EFI_PHYSICAL_ADDRESS  BufferAddress;\r
+  OMAP_DMA4             Dma4;\r
+  DMA_MAP_OPERATION     DmaOperation;\r
+  EFI_STATUS            MmcStatus;\r
+  UINTN                 RetryCount = 0;\r
+\r
+CpuDeadLoop ();\r
+  // Map passed in buffer for DMA xfer\r
+  DmaSize = BlockCount * This->Media->BlockSize;\r
+  Status = DmaMap (DmaOperation, Buffer, &DmaSize, &BufferAddress, &BufferMap);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  ZeroMem (&DmaOperation, sizeof (DMA_MAP_OPERATION));\r
+  \r
+\r
+  Dma4.DataType = 2;                      // DMA4_CSDPi[1:0]   32-bit elements from MMCHS_DATA\r
+\r
+  Dma4.SourceEndiansim = 0;               // DMA4_CSDPi[21]    \r
+\r
+  Dma4.DestinationEndianism = 0;          // DMA4_CSDPi[19]\r
+\r
+  Dma4.SourcePacked = 0;                  // DMA4_CSDPi[6]\r
+\r
+  Dma4.DestinationPacked = 0;             // DMA4_CSDPi[13]\r
+\r
+  Dma4.NumberOfElementPerFrame = This->Media->BlockSize/4; // DMA4_CENi  (TRM 4K is optimum value)  \r
+\r
+  Dma4.NumberOfFramePerTransferBlock = BlockCount;         // DMA4_CFNi    \r
+\r
+  Dma4.ReadPriority = 0;                  // DMA4_CCRi[6]      Low priority read  \r
+\r
+  Dma4.WritePriority = 0;                 // DMA4_CCRi[23]     Prefetech disabled\r
+\r
+\r
+  //Populate the command information based on the operation type.\r
+  if (OperationType == READ) {\r
+    Cmd = CMD18; //Multiple block read\r
+    CmdInterruptEnable = CMD18_INT_EN;\r
+    DmaOperation = MapOperationBusMasterCommonBuffer;\r
+\r
+    Dma4.ReadPortAccessType =0 ;            // DMA4_CSDPi[8:7]   Can not burst MMCHS_DATA reg\r
+\r
+    Dma4.WritePortAccessType = 3;           // DMA4_CSDPi[15:14] Memory burst 16x32\r
+\r
+    Dma4.WriteMode = 1;                     // DMA4_CSDPi[17:16] Write posted\r
+\r
+    \r
+\r
+    Dma4.SourceStartAddress = MMCHS_DATA;                   // DMA4_CSSAi\r
+\r
+    Dma4.DestinationStartAddress = (UINT32)BufferAddress;   // DMA4_CDSAi\r
+\r
+    Dma4.SourceElementIndex = 1;                            // DMA4_CSEi\r
+\r
+    Dma4.SourceFrameIndex = 0x200;                          // DMA4_CSFi\r
+\r
+    Dma4.DestinationElementIndex = 1;                       // DMA4_CDEi\r
+\r
+    Dma4.DestinationFrameIndex = 0;                         // DMA4_CDFi\r
+\r
+\r
+\r
+    Dma4.ReadPortAccessMode = 0;            // DMA4_CCRi[13:12]  Always read MMCHS_DATA\r
+\r
+    Dma4.WritePortAccessMode = 1;           // DMA4_CCRi[15:14]  Post increment memory address\r
+\r
+    Dma4.ReadRequestNumber = 0x1e;          // DMA4_CCRi[4:0]    Syncro with MMCA_DMA_RX (61)  \r
+\r
+    Dma4.WriteRequestNumber = 1;            // DMA4_CCRi[20:19]  Syncro upper 0x3e == 62 (one based)\r
+\r
+  } else if (OperationType == WRITE) { \r
+    Cmd = CMD25; //Multiple block write\r
+    CmdInterruptEnable = CMD25_INT_EN;\r
+    DmaOperation = MapOperationBusMasterRead;\r
+\r
+    Dma4.ReadPortAccessType = 3;            // DMA4_CSDPi[8:7]   Memory burst 16x32\r
+\r
+    Dma4.WritePortAccessType = 0;           // DMA4_CSDPi[15:14] Can not burst MMCHS_DATA reg\r
+\r
+    Dma4.WriteMode = 1;                     // DMA4_CSDPi[17:16] Write posted ???\r
+\r
+    \r
+\r
+    Dma4.SourceStartAddress = (UINT32)BufferAddress;        // DMA4_CSSAi\r
+\r
+    Dma4.DestinationStartAddress = MMCHS_DATA;              // DMA4_CDSAi\r
+\r
+    Dma4.SourceElementIndex = 1;                            // DMA4_CSEi\r
+\r
+    Dma4.SourceFrameIndex = 0x200;                          // DMA4_CSFi\r
+\r
+    Dma4.DestinationElementIndex = 1;                       // DMA4_CDEi\r
+\r
+    Dma4.DestinationFrameIndex = 0;                         // DMA4_CDFi\r
+\r
+\r
+\r
+    Dma4.ReadPortAccessMode = 1;            // DMA4_CCRi[13:12]  Post increment memory address\r
+\r
+    Dma4.WritePortAccessMode = 0;           // DMA4_CCRi[15:14]  Always write MMCHS_DATA\r
+\r
+    Dma4.ReadRequestNumber = 0x1d;          // DMA4_CCRi[4:0]    Syncro with MMCA_DMA_TX (60)  \r
+\r
+    Dma4.WriteRequestNumber = 1;            // DMA4_CCRi[20:19]  Syncro upper 0x3d == 61 (one based)\r
+\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+\r
+  EnableDmaChannel (2, &Dma4);\r
+  \r
+\r
+  //Set command argument based on the card access mode (Byte mode or Block mode)\r
+  if (gCardInfo.OCRData.AccessMode & BIT1) {\r
+    CmdArgument = Lba;\r
+  } else {\r
+    CmdArgument = Lba * This->Media->BlockSize;\r
+  }\r
+\r
+  //Send Command.\r
+  Status = SendCmd (Cmd, CmdInterruptEnable, CmdArgument);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+    //Check for the Transfer completion.\r
+  while (RetryCount < MAX_RETRY_COUNT) {\r
+    //Read Status\r
+    do {\r
+      MmcStatus = MmioRead32 (MMCHS_STAT);\r
+    } while (MmcStatus == 0);\r
+\r
+    //Check if Transfer complete (TC) bit is set?\r
+    if (MmcStatus & TC) {\r
+      break;\r
+    } else {\r
+      DEBUG ((EFI_D_ERROR, "MmcStatus for TC: %x\n", MmcStatus));\r
+      //Check if DEB, DCRC or DTO interrupt occured.\r
+      if ((MmcStatus & DEB) | (MmcStatus & DCRC) | (MmcStatus & DTO)) {\r
+        //There was an error during the data transfer.\r
+\r
+        //Set SRD bit to 1 and wait until it return to 0x0.\r
+        MmioOr32 (MMCHS_SYSCTL, SRD);\r
+        while((MmioRead32 (MMCHS_SYSCTL) & SRD) != 0x0);\r
+\r
+        DisableDmaChannel (2, DMA4_CSR_BLOCK, DMA4_CSR_ERR);\r
+        DmaUnmap (BufferMap);\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+    }\r
+    RetryCount++;\r
+  } \r
+\r
+  DisableDmaChannel (2, DMA4_CSR_BLOCK, DMA4_CSR_ERR);\r
+  Status = DmaUnmap (BufferMap);\r
+\r
+  if (RetryCount == MAX_RETRY_COUNT) {\r
+    DEBUG ((EFI_D_ERROR, "TransferBlockData timed out.\n"));\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+TransferBlock (\r
+  IN EFI_BLOCK_IO_PROTOCOL        *This,\r
+  IN  UINTN                       Lba,\r
+  IN OUT VOID                     *Buffer,\r
+  IN  OPERATION_TYPE              OperationType\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN      MmcStatus;\r
+  UINTN      RetryCount = 0;\r
+  UINTN      Cmd = 0;\r
+  UINTN      CmdInterruptEnable = 0;\r
+  UINTN      CmdArgument = 0;\r
+\r
+\r
+  //Populate the command information based on the operation type.\r
+  if (OperationType == READ) {\r
+    Cmd = CMD17; //Single block read\r
+    CmdInterruptEnable = CMD18_INT_EN;\r
+  } else if (OperationType == WRITE) { \r
+    Cmd = CMD24; //Single block write\r
+    CmdInterruptEnable = CMD24_INT_EN;\r
+  }\r
+\r
+  //Set command argument based on the card access mode (Byte mode or Block mode)\r
+  if (gCardInfo.OCRData.AccessMode & BIT1) {\r
+    CmdArgument = Lba;\r
+  } else {\r
+    CmdArgument = Lba * This->Media->BlockSize;\r
+  }\r
+\r
+  //Send Command.\r
+  Status = SendCmd (Cmd, CmdInterruptEnable, CmdArgument);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //Read or Write data.\r
+  if (OperationType == READ) {\r
+    Status = ReadBlockData (This, Buffer);\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n"));\r
+      return Status;\r
+    }\r
+  } else if (OperationType == WRITE) {\r
+    Status = WriteBlockData (This, Buffer);\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n"));\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //Check for the Transfer completion.\r
+  while (RetryCount < MAX_RETRY_COUNT) {\r
+    //Read Status\r
+    do {\r
+      MmcStatus = MmioRead32 (MMCHS_STAT);\r
+    } while (MmcStatus == 0);\r
+\r
+    //Check if Transfer complete (TC) bit is set?\r
+    if (MmcStatus & TC) {\r
+      break;\r
+    } else {\r
+      DEBUG ((EFI_D_ERROR, "MmcStatus for TC: %x\n", MmcStatus));\r
+      //Check if DEB, DCRC or DTO interrupt occured.\r
+      if ((MmcStatus & DEB) | (MmcStatus & DCRC) | (MmcStatus & DTO)) {\r
+        //There was an error during the data transfer.\r
+\r
+        //Set SRD bit to 1 and wait until it return to 0x0.\r
+        MmioOr32 (MMCHS_SYSCTL, SRD);\r
+        while((MmioRead32 (MMCHS_SYSCTL) & SRD) != 0x0);\r
+\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+    }\r
+    RetryCount++;\r
+  } \r
+\r
+  if (RetryCount == MAX_RETRY_COUNT) {\r
+    DEBUG ((EFI_D_ERROR, "TransferBlockData timed out.\n"));\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+CardPresent (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       Data;\r
+\r
+  //\r
+  // Card detect is a GPIO0 on the TPS65950\r
+  //\r
+  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATAIN1), 1, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((Data & CARD_DETECT_BIT) == CARD_DETECT_BIT) {\r
+    // No Card present\r
+    return FALSE;\r
+  } else {\r
+    return TRUE;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+DetectCard (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  if (!CardPresent ()) {\r
+    return EFI_NO_MEDIA;\r
+  }\r
+\r
+  //Initialize MMC host controller clocks.\r
+  Status = InitializeMMCHS ();\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //Software reset of the MMCHS host controller.\r
+  MmioWrite32 (MMCHS_SYSCONFIG, SOFTRESET);\r
+  gBS->Stall(1000);\r
+  while ((MmioRead32 (MMCHS_SYSSTATUS) & RESETDONE_MASK) != RESETDONE);\r
+\r
+  //Soft reset for all.\r
+  MmioWrite32 (MMCHS_SYSCTL, SRA);\r
+  gBS->Stall(1000);\r
+  while ((MmioRead32 (MMCHS_SYSCTL) & SRA) != 0x0);\r
+\r
+  //Voltage capabilities initialization. Activate VS18 and VS30.\r
+  MmioOr32 (MMCHS_CAPA, (VS30 | VS18));\r
+\r
+  //Wakeup configuration\r
+  MmioOr32 (MMCHS_SYSCONFIG, ENAWAKEUP);\r
+  MmioOr32 (MMCHS_HCTL, IWE);\r
+\r
+  //MMCHS Controller default initialization\r
+  MmioOr32 (MMCHS_CON, (OD | DW8_1_4_BIT | CEATA_OFF));\r
+\r
+  MmioWrite32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_OFF));\r
+\r
+  //Enable internal clock\r
+  MmioOr32 (MMCHS_SYSCTL, ICE);\r
+\r
+  //Set the clock frequency to 80KHz.\r
+  UpdateMMCHSClkFrequency (CLKD_80KHZ);\r
+\r
+  //Enable SD bus power.\r
+  MmioOr32 (MMCHS_HCTL, (SDBP_ON));\r
+\r
+  //Poll till SD bus power bit is set.\r
+  while ((MmioRead32 (MMCHS_HCTL) & SDBP_MASK) != SDBP_ON);\r
+\r
+  //Card idenfication\r
+  Status = PerformCardIdenfication ();\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "No MMC/SD card detected.\n"));\r
+    return Status;\r
+  }\r
+  \r
+  //Get CSD (Card specific data) for the detected card.\r
+  Status = GetCardSpecificData();\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  //Configure the card in data transfer mode.\r
+  Status = PerformCardConfiguration();\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //Patch the Media structure.\r
+  gMMCHSMedia.LastBlock    = (gCardInfo.NumBlocks - 1);\r
+  gMMCHSMedia.BlockSize    = gCardInfo.BlockSize;\r
+  gMMCHSMedia.ReadOnly     = (MmioRead32 (GPIO1_BASE + GPIO_DATAIN) & BIT23) == BIT23;\r
+  gMMCHSMedia.MediaPresent = TRUE; \r
+  gMMCHSMedia.MediaId++; \r
+\r
+  DEBUG ((EFI_D_INFO, "SD Card Media Change on Handle 0x%08x\n", gImageHandle));\r
+\r
+  return Status;\r
+}\r
+\r
+#define MAX_MMCHS_TRANSFER_SIZE  0x4000\r
+\r
+EFI_STATUS\r
+SdReadWrite (\r
+  IN EFI_BLOCK_IO_PROTOCOL    *This,\r
+  IN  UINTN                   Lba, \r
+  OUT VOID                    *Buffer, \r
+  IN  UINTN                   BufferSize,\r
+  IN  OPERATION_TYPE          OperationType\r
+  )\r
+{\r
+  EFI_STATUS Status = EFI_SUCCESS;\r
+  UINTN      RetryCount = 0;\r
+  UINTN      BlockCount;\r
+  UINTN      BytesToBeTranferedThisPass = 0;\r
+  UINTN      BytesRemainingToBeTransfered;\r
   EFI_TPL    OldTpl;\r
-  BOOLEAN    MediaPresentLastTime;\r
+\r
   BOOLEAN    Update;\r
-
-  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-
-
-  if (Buffer == NULL) {
-    Status = EFI_INVALID_PARAMETER;
-    goto Done;
-  }
-  
-  Update               = FALSE;
-  MediaPresentLastTime = gMMCHSMedia.MediaPresent;
-
-  if (gMediaChange) {
-    Status = DetectCard  ();
-    if (EFI_ERROR (Status)) {
-      // We detected a removal
-      gMMCHSMedia.MediaPresent = FALSE;
-      gMMCHSMedia.LastBlock    = 0;
-      gMMCHSMedia.BlockSize    = 512;  // Should be zero but there is a bug in DiskIo
-      gMMCHSMedia.ReadOnly     = FALSE; 
-    } else {
-      Update = TRUE;
-    }
-    gMediaChange             = FALSE;
-  } else if (!gMMCHSMedia.MediaPresent) {
-    Status = EFI_NO_MEDIA;
-    goto Done;
-  }
-
-  if ((MediaPresentLastTime != gMMCHSMedia.MediaPresent) || Update) {
+\r
+\r
+  \r
+  Update               = FALSE;\r
+\r
+  if (gMediaChange) {\r
+    Update = TRUE;\r
+    Status = DetectCard  ();\r
+    if (EFI_ERROR (Status)) {\r
+      // We detected a removal\r
+      gMMCHSMedia.MediaPresent = FALSE;\r
+      gMMCHSMedia.LastBlock    = 0;\r
+      gMMCHSMedia.BlockSize    = 512;  // Should be zero but there is a bug in DiskIo\r
+      gMMCHSMedia.ReadOnly     = FALSE; \r
+    }\r
+    gMediaChange             = FALSE;\r
+  } else if (!gMMCHSMedia.MediaPresent) {\r
+    Status = EFI_NO_MEDIA;\r
+    goto Done;\r
+  }\r
+\r
+  if (Update) {\r
+    DEBUG ((EFI_D_INFO, "SD Card ReinstallProtocolInterface ()\n"));\r
     gBS->ReinstallProtocolInterface (\r
           gImageHandle,\r
           &gEfiBlockIoProtocolGuid,\r
           &gBlockIo,\r
           &gBlockIo\r
           );\r
-  }
-
-  if (EFI_ERROR (Status)) {
-    goto Done;
-  }
-
-   if (Lba > This->Media->LastBlock) {
-    Status = EFI_INVALID_PARAMETER;
-    goto Done;
-  }
-  
-  if ((BufferSize % This->Media->BlockSize) != 0) {
-    Status = EFI_BAD_BUFFER_SIZE;
-    goto Done;
-  }
-
-  //Check if the data lines are not in use.
-  while ((RetryCount++ < MAX_RETRY_COUNT) && ((MmioRead32 (MMCHS_PSTATE) & DATI_MASK) != DATI_ALLOWED));
-  if (RetryCount == MAX_RETRY_COUNT) {
-    Status = EFI_TIMEOUT;
-    goto Done;
-  }
-
-  //Populate the command information based on the operation type.
-  if (OperationType == READ) {
-    Cmd = CMD17; //Single block read
-    CmdInterruptEnable = CMD17_INT_EN;
-  } else if (OperationType == WRITE) { 
-    Cmd = CMD24; //Single block write
-    CmdInterruptEnable = CMD24_INT_EN;
-  }
-
-  //Calculate total number of blocks its going to read.
-  NumBlocks = (BufferSize + (This->Media->BlockSize - 1))/This->Media->BlockSize;
-
-  //Set command argument based on the card access mode (Byte mode or Block mode)
-  if (gCardInfo.OCRData.AccessMode & BIT1) {
-    CmdArgument = (UINTN)Lba;
-  } else {
-    CmdArgument = (UINTN)Lba * This->Media->BlockSize;
-  }
-
-  while(NumBlocks) {
-    //Send Command.
-    Status = SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status));
-      goto Done;
-    }
-
-    //Transfer a block worth of data.
-    Status = TransferBlockData(This, Buffer, OperationType);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
-      goto Done;
-    }
-
-    //Adjust command argument.
-    if (gCardInfo.OCRData.AccessMode & BIT1) {
-      CmdArgument++; //Increase BlockIndex by one.
-    } else {
-      CmdArgument += This->Media->BlockSize; //Increase BlockIndex by BlockSize
-    }
-
-    //Adjust Buffer.
-    Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
-    NumBlocks--;
-  }
-
-Done:\r
+    return EFI_MEDIA_CHANGED;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  }\r
+\r
+  if (Lba > This->Media->LastBlock) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  }\r
+  \r
+  if ((BufferSize % This->Media->BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+    goto Done;\r
+  }\r
+\r
+  //Check if the data lines are not in use.\r
+  while ((RetryCount++ < MAX_RETRY_COUNT) && ((MmioRead32 (MMCHS_PSTATE) & DATI_MASK) != DATI_ALLOWED));\r
+  if (RetryCount == MAX_RETRY_COUNT) {\r
+    Status = EFI_TIMEOUT;\r
+    goto Done;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  BytesRemainingToBeTransfered = BufferSize;\r
+  while (BytesRemainingToBeTransfered > 0) {\r
+\r
+    if (gMediaChange) {\r
+      Status = EFI_NO_MEDIA;\r
+      DEBUG ((EFI_D_INFO, "SdReadWrite() EFI_NO_MEDIA due to gMediaChange\n"));\r
+      goto DoneRestoreTPL;\r
+    }\r
+\r
+    // Turn OFF DMA path until it is debugged\r
+    // BytesToBeTranferedThisPass = (BytesToBeTranferedThisPass >= MAX_MMCHS_TRANSFER_SIZE) ? MAX_MMCHS_TRANSFER_SIZE : BytesRemainingToBeTransfered;\r
+    BytesToBeTranferedThisPass   = This->Media->BlockSize;\r
+\r
+    BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;\r
+\r
+    if (BlockCount > 1) {\r
+      Status = DmaBlocks (This, Lba, Buffer, BlockCount, OperationType);\r
+    } else {\r
+      //Transfer a block worth of data.\r
+      Status = TransferBlock (This, Lba, Buffer, OperationType);\r
+    }\r
+\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));\r
+      goto DoneRestoreTPL;\r
+    }\r
+\r
+    BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;\r
+    Lba    += BlockCount;\r
+    Buffer = (UINT8 *)Buffer + This->Media->BlockSize;\r
+  }\r
+\r
+DoneRestoreTPL:\r
+\r
   gBS->RestoreTPL (OldTpl);\r
+\r
+Done:\r
+\r
   return Status;\r
-}
-
-
+\r
+}\r
+\r
+\r
 /**\r
+\r
   Reset the Block Device.\r
 \r
+\r
+\r
   @param  This                 Indicates a pointer to the calling context.\r
+\r
   @param  ExtendedVerification Driver may perform diagnostics on reset.\r
 \r
+\r
+\r
   @retval EFI_SUCCESS          The device was reset.\r
+\r
   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could\r
+\r
                                not be reset.\r
 \r
-**/
-EFI_STATUS
-EFIAPI
-MMCHSReset (
-  IN EFI_BLOCK_IO_PROTOCOL          *This,
-  IN BOOLEAN                        ExtendedVerification
-  )
-{
-  return EFI_SUCCESS; 
-}
-
-
+\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MMCHSReset (\r
+  IN EFI_BLOCK_IO_PROTOCOL          *This,\r
+  IN BOOLEAN                        ExtendedVerification\r
+  )\r
+{\r
+  return EFI_SUCCESS; \r
+}\r
+\r
+\r
 /**\r
+\r
   Read BufferSize bytes from Lba into Buffer.\r
 \r
+\r
+\r
   @param  This       Indicates a pointer to the calling context.\r
+\r
   @param  MediaId    Id of the media, changes every time the media is replaced.\r
+\r
   @param  Lba        The starting Logical Block Address to read from\r
+\r
   @param  BufferSize Size of Buffer, must be a multiple of device block size.\r
+\r
   @param  Buffer     A pointer to the destination buffer for the data. The caller is\r
+\r
                      responsible for either having implicit or explicit ownership of the buffer.\r
 \r
+\r
+\r
   @retval EFI_SUCCESS           The data was read correctly from the device.\r
+\r
   @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.\r
+\r
   @retval EFI_NO_MEDIA          There is no media in the device.\r
+\r
   @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.\r
+\r
   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
+\r
   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+\r
                                 or the buffer is not on proper alignment.\r
-EFI_STATUS
-
-**/
-EFI_STATUS
-EFIAPI
-MMCHSReadBlocks (
-  IN EFI_BLOCK_IO_PROTOCOL          *This,
-  IN UINT32                         MediaId,
-  IN EFI_LBA                        Lba,
-  IN UINTN                          BufferSize,
-  OUT VOID                          *Buffer
-  )
-{
-  EFI_STATUS Status;
-
-  //Perform Read operation.
-  Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);
-
+\r
+EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MMCHSReadBlocks (\r
+  IN EFI_BLOCK_IO_PROTOCOL          *This,\r
+  IN UINT32                         MediaId,\r
+  IN EFI_LBA                        Lba,\r
+  IN UINTN                          BufferSize,\r
+  OUT VOID                          *Buffer\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //Perform Read operation.\r
+  Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);\r
+\r
   return Status;\r
-}
-
-
+\r
+}\r
+\r
+\r
 /**\r
+\r
   Write BufferSize bytes from Lba into Buffer.\r
 \r
+\r
+\r
   @param  This       Indicates a pointer to the calling context.\r
+\r
   @param  MediaId    The media ID that the write request is for.\r
+\r
   @param  Lba        The starting logical block address to be written. The caller is\r
+\r
                      responsible for writing to only legitimate locations.\r
+\r
   @param  BufferSize Size of Buffer, must be a multiple of device block size.\r
+\r
   @param  Buffer     A pointer to the source buffer for the data.\r
 \r
+\r
+\r
   @retval EFI_SUCCESS           The data was written correctly to the device.\r
+\r
   @retval EFI_WRITE_PROTECTED   The device can not be written to.\r
+\r
   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.\r
+\r
   @retval EFI_NO_MEDIA          There is no media in the device.\r
+\r
   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.\r
+\r
   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
+\r
   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+\r
                                 or the buffer is not on proper alignment.\r
 \r
-**/
-EFI_STATUS
-EFIAPI
-MMCHSWriteBlocks (
-  IN EFI_BLOCK_IO_PROTOCOL          *This,
-  IN UINT32                         MediaId,
-  IN EFI_LBA                        Lba,
-  IN UINTN                          BufferSize,
-  IN VOID                           *Buffer
-  )
-{
-  EFI_STATUS  Status;
-
-  //Perform write operation.
-  Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, WRITE);
+\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MMCHSWriteBlocks (\r
+  IN EFI_BLOCK_IO_PROTOCOL          *This,\r
+  IN UINT32                         MediaId,\r
+  IN EFI_LBA                        Lba,\r
+  IN UINTN                          BufferSize,\r
+  IN VOID                           *Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //Perform write operation.\r
+  Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, WRITE);\r
+\r
 \r
   return Status;\r
-}
-
-
+\r
+}\r
+\r
+\r
 /**\r
+\r
   Flush the Block Device.\r
 \r
+\r
+\r
   @param  This              Indicates a pointer to the calling context.\r
 \r
+\r
+\r
   @retval EFI_SUCCESS       All outstanding data was written to the device\r
+\r
   @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data\r
+\r
   @retval EFI_NO_MEDIA      There is no media in the device.\r
 \r
-**/
-EFI_STATUS
-EFIAPI
-MMCHSFlushBlocks (
-  IN EFI_BLOCK_IO_PROTOCOL  *This
-  )
-{
-  return EFI_SUCCESS;
-}
-
-
-EFI_BLOCK_IO_PROTOCOL gBlockIo = {
-  EFI_BLOCK_IO_INTERFACE_REVISION,   // Revision
-  &gMMCHSMedia,                      // *Media
-  MMCHSReset,                        // Reset
-  MMCHSReadBlocks,                   // ReadBlocks
-  MMCHSWriteBlocks,                  // WriteBlocks
-  MMCHSFlushBlocks                   // FlushBlocks
-};
-
-
+\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MMCHSFlushBlocks (\r
+  IN EFI_BLOCK_IO_PROTOCOL  *This\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_BLOCK_IO_PROTOCOL gBlockIo = {\r
+  EFI_BLOCK_IO_INTERFACE_REVISION,   // Revision\r
+  &gMMCHSMedia,                      // *Media\r
+  MMCHSReset,                        // Reset\r
+  MMCHSReadBlocks,                   // ReadBlocks\r
+  MMCHSWriteBlocks,                  // WriteBlocks\r
+  MMCHSFlushBlocks                   // FlushBlocks\r
+};\r
+\r
+\r
 /**\r
+\r
   Timer callback to convert card present hardware into a boolean that indicates\r
+\r
   a media change event has happened. If you just check the GPIO you could see \r
+\r
   card 1 and then check again after card 1 was removed and card 2 was inserted\r
+\r
   and you would still see media present. Thus you need the timer tick to catch\r
+\r
   the toggle event.\r
 \r
+\r
+\r
   @param  Event                 Event whose notification function is being invoked.\r
+\r
   @param  Context               The pointer to the notification function's context,\r
+\r
                                 which is implementation-dependent. Not used.\r
 \r
-**/
-VOID
-EFIAPI
-TimerCallback (
-  IN  EFI_EVENT   Event,
-  IN  VOID        *Context
-  )
-{
-  BOOLEAN Present;
-
-  Present = CardPresent ();
-  if (gMMCHSMedia.MediaPresent) {
-    if (!Present && !gMediaChange) {
-      gMediaChange = TRUE;
-    }
-  } else {
-    if (Present && !gMediaChange) {
-      gMediaChange = TRUE;    
-    }
-  }
-}
-
-
-EFI_STATUS
-EFIAPI
-MMCHSInitialize (
-  IN EFI_HANDLE         ImageHandle,
-  IN EFI_SYSTEM_TABLE   *SystemTable
-  )
-{
-  EFI_STATUS  Status;
-
-  Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
-  ASSERT_EFI_ERROR(Status);
-
-  ZeroMem (&gCardInfo, sizeof (CARD_INFO));
-  Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, TimerCallback, NULL, &gTimerEvent);
-  ASSERT_EFI_ERROR (Status);
-  Status = gBS->SetTimer (gTimerEvent, TimerPeriodic, 1000000); // make me a PCD
-  ASSERT_EFI_ERROR (Status);
-
-  //Publish BlockIO.
-  Status = gBS->InstallMultipleProtocolInterfaces (
-                  &ImageHandle, 
-                  &gEfiBlockIoProtocolGuid,    &gBlockIo, 
-                  &gEfiDevicePathProtocolGuid, &gMmcHsDevicePath,
-                  NULL
-                  );
-  return Status;
-}
+\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+TimerCallback (\r
+  IN  EFI_EVENT   Event,\r
+  IN  VOID        *Context\r
+  )\r
+{\r
+  BOOLEAN Present;\r
+\r
+  Present = CardPresent ();\r
+  if (gMMCHSMedia.MediaPresent) {\r
+    if (!Present && !gMediaChange) {\r
+      gMediaChange = TRUE;\r
+    }\r
+  } else {\r
+    if (Present && !gMediaChange) {\r
+      gMediaChange = TRUE;    \r
+    }\r
+  }\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MMCHSInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  ZeroMem (&gCardInfo, sizeof (CARD_INFO));\r
+\r
+  Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, TimerCallback, NULL, &gTimerEvent);\r
+  ASSERT_EFI_ERROR (Status);\r
\r
+  Status = gBS->SetTimer (gTimerEvent, TimerPeriodic, FixedPcdGet32 (PcdMmchsTimerFreq100NanoSeconds)); \r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //Publish BlockIO.\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &ImageHandle, \r
+                  &gEfiBlockIoProtocolGuid,    &gBlockIo, \r
+                  &gEfiDevicePathProtocolGuid, &gMmcHsDevicePath,\r
+                  NULL\r
+                  );\r
+  return Status;\r
+}\r