]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Omap35xxPkg/MmcHostDxe/MmcHostDxe.c
ARM Packages: Fixed line endings
[mirror_edk2.git] / Omap35xxPkg / MmcHostDxe / MmcHostDxe.c
index 17ebf8d7086a9a85813e885cf39ae171af0386f1..0cbd82bd44d8593a8b045d4a772ea6078ea0fe57 100755 (executable)
-/** @file
-*
-*  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
-*  Copyright (c) 2011, 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 "MmcHostDxe.h"
-
-EMBEDDED_EXTERNAL_DEVICE   *gTPS65950;
-UINT8                      mMaxDataTransferRate = 0;
-UINT32                     mRca = 0;
-BOOLEAN                    mBitModeSet = FALSE;
-
-
-typedef struct {
-  VENDOR_DEVICE_PATH  Mmc;
-  EFI_DEVICE_PATH     End;
-} MMCHS_DEVICE_PATH;
-
-MMCHS_DEVICE_PATH gMMCDevicePath = {
-  {
-    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
-  }
-};
-
-BOOLEAN
-IgnoreCommand (
-  UINT32 Command
-  )
-{
-  switch(Command) {
-    case MMC_CMD12:
-      return TRUE;
-    case MMC_CMD13:
-      return TRUE;
-    default:
-      return FALSE;
-  }
-}
-
-UINT32
-TranslateCommand (
-  UINT32 Command
-  )
-{
-  UINT32 Translation;
-
-  switch(Command) {
-    case MMC_CMD2:
-      Translation = CMD2;
-      break;
-    case MMC_CMD3:
-      Translation = CMD3;
-      break;
-    /*case MMC_CMD6:
-      Translation = CMD6;
-      break;*/
-    case MMC_CMD7:
-      Translation = CMD7;
-      break;
-    case MMC_CMD8:
-      Translation = CMD8;
-      break;
-    case MMC_CMD9:
-      Translation = CMD9;
-      break;
-    /*case MMC_CMD12:
-      Translation = CMD12;
-      break;
-    case MMC_CMD13:
-      Translation = CMD13;
-      break;*/
-    case MMC_CMD16:
-      Translation = CMD16;
-      break;
-    case MMC_CMD17:
-      Translation = 0x113A0014;//CMD17;
-      break;
-    case MMC_CMD24:
-      Translation = CMD24 | 4;
-      break;
-    case MMC_CMD55:
-      Translation = CMD55;
-      break;
-    case MMC_ACMD41:
-      Translation = ACMD41;
-      break;
-    default:
-      Translation = Command;
-  }
-
-  return Translation;
-}
-
-VOID
-CalculateCardCLKD (
-  UINTN *ClockFrequencySelect
-  )
-{
-  UINTN    TransferRateValue = 0;
-  UINTN    TimeValue = 0 ;
-  UINTN    Frequency = 0;
-
-  DEBUG ((DEBUG_BLKIO, "CalculateCardCLKD()\n"));
-
-  // For SD Cards  we would need to send CMD6 to set
-  // speeds abouve 25MHz. High Speed mode 50 MHz and up
-
-  // Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED)
-  switch (mMaxDataTransferRate & 0x7) { // 2
-    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 ((DEBUG_BLKIO, "Invalid parameter.\n"));
-      ASSERT(FALSE);
-      return;
-  }
-
-  //Calculate Time value (Bits 6:3 of TRAN_SPEED)
-  switch ((mMaxDataTransferRate >> 3) & 0xF) { // 6
-    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 ((DEBUG_BLKIO, "Invalid parameter.\n"));
-      ASSERT(FALSE);
-      return;
-  }
-
-  Frequency = TransferRateValue * TimeValue/10;
-
-  // Calculate Clock divider value to program in MMCHS_SYSCTL[CLKD] field.
-  *ClockFrequencySelect = ((MMC_REFERENCE_CLK/Frequency) + 1);
-
-  DEBUG ((DEBUG_BLKIO, "mMaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", mMaxDataTransferRate, Frequency/1000, *ClockFrequencySelect));
-}
-
-VOID
-UpdateMMCHSClkFrequency (
-  UINTN NewCLKD
-  )
-{
-  DEBUG ((DEBUG_BLKIO, "UpdateMMCHSClkFrequency()\n"));
-
-  // 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
-InitializeMMCHS (
-  VOID
-  )
-{
-  UINT8      Data;
-  EFI_STATUS Status;
-
-  DEBUG ((DEBUG_BLKIO, "InitializeMMCHS()\n"));
-
-  // 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;
-}
-
-BOOLEAN
-MMCIsCardPresent (
-  IN EFI_MMC_HOST_PROTOCOL     *This
-  )
-{
-  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;
-  }
-
-  return !(Data & CARD_DETECT_BIT);
-}
-
-BOOLEAN
-MMCIsReadOnly (
-  IN EFI_MMC_HOST_PROTOCOL     *This
-  )
-{
-  /* Note:
-   * On our BeagleBoard the SD card WP pin is always read as TRUE. 
-   * Probably something wrong with GPIO configuration.
-   * BeagleBoard-xM uses microSD cards so there is no write protect at all.
-   * Hence commenting out SD card WP pin read status.  
-   */
-  //return (MmioRead32 (GPIO1_BASE + GPIO_DATAIN) & BIT23) == BIT23;
-  return 0;
-
-}
-
-// TODO
-EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;
-
-EFI_STATUS
-MMCBuildDevicePath (
-  IN EFI_MMC_HOST_PROTOCOL     *This,
-  IN EFI_DEVICE_PATH_PROTOCOL  **DevicePath
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL    *NewDevicePathNode;
-
-  NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));
-  CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);
-  *DevicePath = NewDevicePathNode;
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-MMCSendCommand (
-  IN EFI_MMC_HOST_PROTOCOL     *This,
-  IN MMC_CMD                   MmcCmd,
-  IN UINT32                    Argument
-  )
-{
-  UINTN MmcStatus;
-  UINTN RetryCount = 0;
-
-  if (IgnoreCommand(MmcCmd))
-    return EFI_SUCCESS;
-
-  MmcCmd = TranslateCommand(MmcCmd);
-
-  //DEBUG ((EFI_D_ERROR, "MMCSendCommand(%d)\n", MmcCmd));
-
-  // 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, Argument);
-
-  //TODO: fix this
-  //Enable interrupt enable events to occur
-  //MmioWrite32 (MMCHS_IE, CmdInterruptEnableVal);
-
-  // Send a command
-  MmioWrite32 (MMCHS_CMD, MmcCmd);
-
-  // 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: 0x%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) {
-    DEBUG ((DEBUG_BLKIO, "MMCSendCommand: Timeout\n"));
-    return EFI_TIMEOUT;
-  }
-
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-MMCNotifyState (
-  IN EFI_MMC_HOST_PROTOCOL    *This,
-  IN MMC_STATE                State
-  )
-{
-  EFI_STATUS              Status;
-  UINTN                   FreqSel;
-
-  switch(State) {
-    case MmcInvalidState:
-      ASSERT(0);
-      break;
-    case MmcHwInitializationState:
-      mBitModeSet = FALSE;
-
-      DEBUG ((DEBUG_BLKIO, "MMCHwInitializationState()\n"));
-      Status = InitializeMMCHS ();
-      if (EFI_ERROR(Status)) {
-        DEBUG ((DEBUG_BLKIO, "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);
-
-      // 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);
-      break;
-    case MmcIdleState:
-      break;
-    case MmcReadyState:
-      break;
-    case MmcIdentificationState:
-      break;
-    case MmcStandByState:
-      CalculateCardCLKD (&FreqSel);
-      UpdateMMCHSClkFrequency (FreqSel);
-      break;
-    case MmcTransferState:
-      if (!mBitModeSet) {
-        Status = MMCSendCommand (This, CMD55, mRca << 16);
-        if (!EFI_ERROR (Status)) {
-          // Set device into 4-bit data bus mode
-          Status = MMCSendCommand (This, ACMD6, 0x2);
-          if (!EFI_ERROR (Status)) {
-            // Set host controler into 4-bit mode
-            MmioOr32 (MMCHS_HCTL, DTW_4_BIT);
-            DEBUG ((DEBUG_BLKIO, "SD Memory Card set to 4-bit mode\n"));
-            mBitModeSet = TRUE;
-          }
-        }
-      }
-      break;
-    case MmcSendingDataState:
-      break;
-    case MmcReceiveDataState:
-      break;
-    case MmcProgrammingState:
-      break;
-    case MmcDisconnectState:
-    default:
-      ASSERT(0);
-  }
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-MMCReceiveResponse (
-  IN EFI_MMC_HOST_PROTOCOL     *This,
-  IN MMC_RESPONSE_TYPE         Type,
-  IN UINT32*                   Buffer
-  )
-{
-  if (Buffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (Type == MMC_RESPONSE_TYPE_R2) {
-    Buffer[0] = MmioRead32 (MMCHS_RSP10);
-    Buffer[1] = MmioRead32 (MMCHS_RSP32);
-    Buffer[2] = MmioRead32 (MMCHS_RSP54);
-    Buffer[3] = MmioRead32 (MMCHS_RSP76);
-  } else {
-    Buffer[0] = MmioRead32 (MMCHS_RSP10);
-  }
-
-  if (Type == MMC_RESPONSE_TYPE_CSD) {
-    mMaxDataTransferRate = Buffer[3] & 0xFF;
-  } else if (Type == MMC_RESPONSE_TYPE_RCA) {
-    mRca = Buffer[0] >> 16;
-  }
-
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-MMCReadBlockData (
-  IN EFI_MMC_HOST_PROTOCOL      *This,
-  IN EFI_LBA                    Lba,
-  IN UINTN                      Length,
-  IN UINT32*                    Buffer
-  )
-{
-  UINTN MmcStatus;
-  UINTN Count;
-  UINTN RetryCount = 0;
-
-  DEBUG ((DEBUG_BLKIO, "MMCReadBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n", Lba, Length, Buffer));
-
-  // 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);
-
-      for (Count = 0; Count < Length / 4; Count++) {
-        *Buffer++ = MmioRead32(MMCHS_DATA);
-      }
-      break;
-    }
-    RetryCount++;
-  }
-
-  if (RetryCount == MAX_RETRY_COUNT) {
-    return EFI_TIMEOUT;
-  }
-
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-MMCWriteBlockData (
-  IN EFI_MMC_HOST_PROTOCOL    *This,
-  IN EFI_LBA                  Lba,
-  IN UINTN                    Length,
-  IN UINT32*                  Buffer
-  )
-{
-  UINTN MmcStatus;
-  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 < Length / 4; Count++) {
-        MmioWrite32 (MMCHS_DATA, *Buffer++);
-      }
-
-      break;
-    }
-    RetryCount++;
-  }
-
-  if (RetryCount == MAX_RETRY_COUNT) {
-    return EFI_TIMEOUT;
-  }
-
-  return EFI_SUCCESS;
-}
-
-EFI_MMC_HOST_PROTOCOL gMMCHost = {
-  MMC_HOST_PROTOCOL_REVISION,
-  MMCIsCardPresent,
-  MMCIsReadOnly,
-  MMCBuildDevicePath,
-  MMCNotifyState,
-  MMCSendCommand,
-  MMCReceiveResponse,
-  MMCReadBlockData,
-  MMCWriteBlockData
-};
-
-EFI_STATUS
-MMCInitialize (
-  IN EFI_HANDLE         ImageHandle,
-  IN EFI_SYSTEM_TABLE   *SystemTable
-  )
-{
-  EFI_STATUS    Status;
-  EFI_HANDLE    Handle = NULL;
-
-  DEBUG ((DEBUG_BLKIO, "MMCInitialize()\n"));
-
-  Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
-  ASSERT_EFI_ERROR(Status);
-
-  Status = gBS->InstallMultipleProtocolInterfaces (
-                  &Handle, 
-                  &gEfiMmcHostProtocolGuid,         &gMMCHost,
-                  NULL
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  return Status;
-}
+/** @file\r
+*\r
+*  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.\r
+*  Copyright (c) 2011, ARM Limited. All rights reserved.\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 "MmcHostDxe.h"\r
+\r
+EMBEDDED_EXTERNAL_DEVICE   *gTPS65950;\r
+UINT8                      mMaxDataTransferRate = 0;\r
+UINT32                     mRca = 0;\r
+BOOLEAN                    mBitModeSet = FALSE;\r
+\r
+\r
+typedef struct {\r
+  VENDOR_DEVICE_PATH  Mmc;\r
+  EFI_DEVICE_PATH     End;\r
+} MMCHS_DEVICE_PATH;\r
+\r
+MMCHS_DEVICE_PATH gMMCDevicePath = {\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
+BOOLEAN\r
+IgnoreCommand (\r
+  UINT32 Command\r
+  )\r
+{\r
+  switch(Command) {\r
+    case MMC_CMD12:\r
+      return TRUE;\r
+    case MMC_CMD13:\r
+      return TRUE;\r
+    default:\r
+      return FALSE;\r
+  }\r
+}\r
+\r
+UINT32\r
+TranslateCommand (\r
+  UINT32 Command\r
+  )\r
+{\r
+  UINT32 Translation;\r
+\r
+  switch(Command) {\r
+    case MMC_CMD2:\r
+      Translation = CMD2;\r
+      break;\r
+    case MMC_CMD3:\r
+      Translation = CMD3;\r
+      break;\r
+    /*case MMC_CMD6:\r
+      Translation = CMD6;\r
+      break;*/\r
+    case MMC_CMD7:\r
+      Translation = CMD7;\r
+      break;\r
+    case MMC_CMD8:\r
+      Translation = CMD8;\r
+      break;\r
+    case MMC_CMD9:\r
+      Translation = CMD9;\r
+      break;\r
+    /*case MMC_CMD12:\r
+      Translation = CMD12;\r
+      break;\r
+    case MMC_CMD13:\r
+      Translation = CMD13;\r
+      break;*/\r
+    case MMC_CMD16:\r
+      Translation = CMD16;\r
+      break;\r
+    case MMC_CMD17:\r
+      Translation = 0x113A0014;//CMD17;\r
+      break;\r
+    case MMC_CMD24:\r
+      Translation = CMD24 | 4;\r
+      break;\r
+    case MMC_CMD55:\r
+      Translation = CMD55;\r
+      break;\r
+    case MMC_ACMD41:\r
+      Translation = ACMD41;\r
+      break;\r
+    default:\r
+      Translation = Command;\r
+  }\r
+\r
+  return Translation;\r
+}\r
+\r
+VOID\r
+CalculateCardCLKD (\r
+  UINTN *ClockFrequencySelect\r
+  )\r
+{\r
+  UINTN    TransferRateValue = 0;\r
+  UINTN    TimeValue = 0 ;\r
+  UINTN    Frequency = 0;\r
+\r
+  DEBUG ((DEBUG_BLKIO, "CalculateCardCLKD()\n"));\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 (mMaxDataTransferRate & 0x7) { // 2\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 ((DEBUG_BLKIO, "Invalid parameter.\n"));\r
+      ASSERT(FALSE);\r
+      return;\r
+  }\r
+\r
+  //Calculate Time value (Bits 6:3 of TRAN_SPEED)\r
+  switch ((mMaxDataTransferRate >> 3) & 0xF) { // 6\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 ((DEBUG_BLKIO, "Invalid parameter.\n"));\r
+      ASSERT(FALSE);\r
+      return;\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 ((DEBUG_BLKIO, "mMaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", mMaxDataTransferRate, Frequency/1000, *ClockFrequencySelect));\r
+}\r
+\r
+VOID\r
+UpdateMMCHSClkFrequency (\r
+  UINTN NewCLKD\r
+  )\r
+{\r
+  DEBUG ((DEBUG_BLKIO, "UpdateMMCHSClkFrequency()\n"));\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
+EFI_STATUS\r
+InitializeMMCHS (\r
+  VOID\r
+  )\r
+{\r
+  UINT8      Data;\r
+  EFI_STATUS Status;\r
+\r
+  DEBUG ((DEBUG_BLKIO, "InitializeMMCHS()\n"));\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
+  return Status;\r
+}\r
+\r
+BOOLEAN\r
+MMCIsCardPresent (\r
+  IN EFI_MMC_HOST_PROTOCOL     *This\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
+  return !(Data & CARD_DETECT_BIT);\r
+}\r
+\r
+BOOLEAN\r
+MMCIsReadOnly (\r
+  IN EFI_MMC_HOST_PROTOCOL     *This\r
+  )\r
+{\r
+  /* Note:\r
+   * On our BeagleBoard the SD card WP pin is always read as TRUE. \r
+   * Probably something wrong with GPIO configuration.\r
+   * BeagleBoard-xM uses microSD cards so there is no write protect at all.\r
+   * Hence commenting out SD card WP pin read status.  \r
+   */\r
+  //return (MmioRead32 (GPIO1_BASE + GPIO_DATAIN) & BIT23) == BIT23;\r
+  return 0;\r
+\r
+}\r
+\r
+// TODO\r
+EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;\r
+\r
+EFI_STATUS\r
+MMCBuildDevicePath (\r
+  IN EFI_MMC_HOST_PROTOCOL     *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL  **DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL    *NewDevicePathNode;\r
+\r
+  NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));\r
+  CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);\r
+  *DevicePath = NewDevicePathNode;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+MMCSendCommand (\r
+  IN EFI_MMC_HOST_PROTOCOL     *This,\r
+  IN MMC_CMD                   MmcCmd,\r
+  IN UINT32                    Argument\r
+  )\r
+{\r
+  UINTN MmcStatus;\r
+  UINTN RetryCount = 0;\r
+\r
+  if (IgnoreCommand(MmcCmd))\r
+    return EFI_SUCCESS;\r
+\r
+  MmcCmd = TranslateCommand(MmcCmd);\r
+\r
+  //DEBUG ((EFI_D_ERROR, "MMCSendCommand(%d)\n", MmcCmd));\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, Argument);\r
+\r
+  //TODO: fix this\r
+  //Enable interrupt enable events to occur\r
+  //MmioWrite32 (MMCHS_IE, CmdInterruptEnableVal);\r
+\r
+  // Send a command\r
+  MmioWrite32 (MMCHS_CMD, MmcCmd);\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: 0x%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
+    DEBUG ((DEBUG_BLKIO, "MMCSendCommand: Timeout\n"));\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+MMCNotifyState (\r
+  IN EFI_MMC_HOST_PROTOCOL    *This,\r
+  IN MMC_STATE                State\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINTN                   FreqSel;\r
+\r
+  switch(State) {\r
+    case MmcInvalidState:\r
+      ASSERT(0);\r
+      break;\r
+    case MmcHwInitializationState:\r
+      mBitModeSet = FALSE;\r
+\r
+      DEBUG ((DEBUG_BLKIO, "MMCHwInitializationState()\n"));\r
+      Status = InitializeMMCHS ();\r
+      if (EFI_ERROR(Status)) {\r
+        DEBUG ((DEBUG_BLKIO, "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
+      // 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
+      break;\r
+    case MmcIdleState:\r
+      break;\r
+    case MmcReadyState:\r
+      break;\r
+    case MmcIdentificationState:\r
+      break;\r
+    case MmcStandByState:\r
+      CalculateCardCLKD (&FreqSel);\r
+      UpdateMMCHSClkFrequency (FreqSel);\r
+      break;\r
+    case MmcTransferState:\r
+      if (!mBitModeSet) {\r
+        Status = MMCSendCommand (This, CMD55, mRca << 16);\r
+        if (!EFI_ERROR (Status)) {\r
+          // Set device into 4-bit data bus mode\r
+          Status = MMCSendCommand (This, ACMD6, 0x2);\r
+          if (!EFI_ERROR (Status)) {\r
+            // Set host controler into 4-bit mode\r
+            MmioOr32 (MMCHS_HCTL, DTW_4_BIT);\r
+            DEBUG ((DEBUG_BLKIO, "SD Memory Card set to 4-bit mode\n"));\r
+            mBitModeSet = TRUE;\r
+          }\r
+        }\r
+      }\r
+      break;\r
+    case MmcSendingDataState:\r
+      break;\r
+    case MmcReceiveDataState:\r
+      break;\r
+    case MmcProgrammingState:\r
+      break;\r
+    case MmcDisconnectState:\r
+    default:\r
+      ASSERT(0);\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+MMCReceiveResponse (\r
+  IN EFI_MMC_HOST_PROTOCOL     *This,\r
+  IN MMC_RESPONSE_TYPE         Type,\r
+  IN UINT32*                   Buffer\r
+  )\r
+{\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Type == MMC_RESPONSE_TYPE_R2) {\r
+    Buffer[0] = MmioRead32 (MMCHS_RSP10);\r
+    Buffer[1] = MmioRead32 (MMCHS_RSP32);\r
+    Buffer[2] = MmioRead32 (MMCHS_RSP54);\r
+    Buffer[3] = MmioRead32 (MMCHS_RSP76);\r
+  } else {\r
+    Buffer[0] = MmioRead32 (MMCHS_RSP10);\r
+  }\r
+\r
+  if (Type == MMC_RESPONSE_TYPE_CSD) {\r
+    mMaxDataTransferRate = Buffer[3] & 0xFF;\r
+  } else if (Type == MMC_RESPONSE_TYPE_RCA) {\r
+    mRca = Buffer[0] >> 16;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+MMCReadBlockData (\r
+  IN EFI_MMC_HOST_PROTOCOL      *This,\r
+  IN EFI_LBA                    Lba,\r
+  IN UINTN                      Length,\r
+  IN UINT32*                    Buffer\r
+  )\r
+{\r
+  UINTN MmcStatus;\r
+  UINTN Count;\r
+  UINTN RetryCount = 0;\r
+\r
+  DEBUG ((DEBUG_BLKIO, "MMCReadBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n", Lba, Length, Buffer));\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
+      for (Count = 0; Count < Length / 4; Count++) {\r
+        *Buffer++ = 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
+EFI_STATUS\r
+MMCWriteBlockData (\r
+  IN EFI_MMC_HOST_PROTOCOL    *This,\r
+  IN EFI_LBA                  Lba,\r
+  IN UINTN                    Length,\r
+  IN UINT32*                  Buffer\r
+  )\r
+{\r
+  UINTN MmcStatus;\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 < Length / 4; Count++) {\r
+        MmioWrite32 (MMCHS_DATA, *Buffer++);\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_MMC_HOST_PROTOCOL gMMCHost = {\r
+  MMC_HOST_PROTOCOL_REVISION,\r
+  MMCIsCardPresent,\r
+  MMCIsReadOnly,\r
+  MMCBuildDevicePath,\r
+  MMCNotifyState,\r
+  MMCSendCommand,\r
+  MMCReceiveResponse,\r
+  MMCReadBlockData,\r
+  MMCWriteBlockData\r
+};\r
+\r
+EFI_STATUS\r
+MMCInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_HANDLE    Handle = NULL;\r
+\r
+  DEBUG ((DEBUG_BLKIO, "MMCInitialize()\n"));\r
+\r
+  Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &Handle, \r
+                  &gEfiMmcHostProtocolGuid,         &gMMCHost,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r