public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 0/3] Platform/NXP-Adding NXP MMC Host Driver
@ 2017-12-01  4:18 Vabhav
  2017-12-01  4:18 ` [PATCH 1/3] Platform/NXP :Add Support for MMC Library Vabhav
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Vabhav @ 2017-12-01  4:18 UTC (permalink / raw)
  To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel

Following patches will add support of NXP MMC Host Driver in
edk2-platforms directory 'edk2-platforms/Platform/NXP'

Updated Directory structure for added folders in 'edk2-platforms/Platform/NXP'
will be:

Platform/NXP/
|-- Drivers
|   |-- MmcHostDxe
|   |   |-- MmcHostDxe.c
|   |   `-- MmcHostDxe.inf
|-- Include
|   `-- Library
|       `-- MmcLib.h
|-- Library
|   `-- MmcLib
|       |-- MmcInterface.c
|       |-- MmcInternal.h
|       |-- MmcLib.c
|       `-- MmcLib.inf

In Platform/NXP/Library:
MmcLib will be added

In Platform/NXP/Drivers:
MmcHostDxe driver will be added

Mmc host driver will produce gEfiMmcHostProtocolGuid which
will be used by consumed by MmcDxe driver of EmbeddedPkg.

Please review and look forward for your support in upstreaming
the patches in edk2-platforms.

Vabhav (3):
  Platform/NXP :Add Support for MMC Library
  Platform/NXP :Add Support of MMC Host Driver
  Compilation:Modify dsc,fdf files

 Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.c   | 418 +++++++++++++++++
 Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf |  42 ++
 Platform/NXP/Include/Library/MmcLib.h          | 138 ++++++
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc   |  11 +
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf   |   7 +
 Platform/NXP/Library/MmcLib/MmcInterface.c     | 544 ++++++++++++++++++++++
 Platform/NXP/Library/MmcLib/MmcInternal.h      | 350 +++++++++++++++
 Platform/NXP/Library/MmcLib/MmcLib.c           | 597 +++++++++++++++++++++++++
 Platform/NXP/Library/MmcLib/MmcLib.inf         |  39 ++
 9 files changed, 2146 insertions(+)
 create mode 100644 Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.c
 create mode 100644 Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf
 create mode 100644 Platform/NXP/Include/Library/MmcLib.h
 create mode 100644 Platform/NXP/Library/MmcLib/MmcInterface.c
 create mode 100644 Platform/NXP/Library/MmcLib/MmcInternal.h
 create mode 100644 Platform/NXP/Library/MmcLib/MmcLib.c
 create mode 100644 Platform/NXP/Library/MmcLib/MmcLib.inf


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] Platform/NXP :Add Support for MMC Library
  2017-12-01  4:18 [PATCH 0/3] Platform/NXP-Adding NXP MMC Host Driver Vabhav
@ 2017-12-01  4:18 ` Vabhav
  2017-12-01  4:18 ` [PATCH 2/3] Platform/NXP :Add Support of MMC Host Driver Vabhav
  2017-12-01  4:18 ` [PATCH 3/3] Compilation:Modify dsc,fdf files Vabhav
  2 siblings, 0 replies; 4+ messages in thread
From: Vabhav @ 2017-12-01  4:18 UTC (permalink / raw)
  To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel

This patch adds support for MMC library(MmcLib)to
provide functions which will be used by MMC Host
driver.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
 Platform/NXP/Include/Library/MmcLib.h      | 138 +++++++
 Platform/NXP/Library/MmcLib/MmcInterface.c | 544 ++++++++++++++++++++++++++
 Platform/NXP/Library/MmcLib/MmcInternal.h  | 350 +++++++++++++++++
 Platform/NXP/Library/MmcLib/MmcLib.c       | 597 +++++++++++++++++++++++++++++
 Platform/NXP/Library/MmcLib/MmcLib.inf     |  39 ++
 5 files changed, 1668 insertions(+)
 create mode 100644 Platform/NXP/Include/Library/MmcLib.h
 create mode 100644 Platform/NXP/Library/MmcLib/MmcInterface.c
 create mode 100644 Platform/NXP/Library/MmcLib/MmcInternal.h
 create mode 100644 Platform/NXP/Library/MmcLib/MmcLib.c
 create mode 100644 Platform/NXP/Library/MmcLib/MmcLib.inf

diff --git a/Platform/NXP/Include/Library/MmcLib.h b/Platform/NXP/Include/Library/MmcLib.h
new file mode 100644
index 0000000..36941bc
--- /dev/null
+++ b/Platform/NXP/Include/Library/MmcLib.h
@@ -0,0 +1,138 @@
+/** @file
+  Header Defining The MMC Memory Controller Constants, Function Prototype, Structures Etc
+
+  Copyright 2017 NXP
+
+  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.
+
+**/
+
+#ifndef __MMCLIB_H__
+#define __MMCLIB_H__
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+
+//define MMC_DEBUG to enable debug feature
+//#define MMC_DEBUG  1
+#ifdef MMC_DEBUG
+#define DEBUG_MSG(_Fmt,...)   DEBUG ((DEBUG_ERROR, "MMC: " _Fmt, ##__VA_ARGS__));
+#else
+#define DEBUG_MSG(_Fmt,...)
+#endif
+
+/**
+ MMC RESPONSE TYPE
+**/
+#define MMC_RSP_PRESENT  (1 << 0)
+#define MMC_RSP_136      (1 << 1)  // 136 Bit Response
+#define MMC_RSP_CRC      (1 << 2)  // Expect Valid Crc
+#define MMC_RSP_BUSY     (1 << 3)  // Card May Send Busy
+#define MMC_RSP_OPCODE   (1 << 4)  // Response Contains Opcode
+
+#define MMC_RSP_NONE     (0)
+#define MMC_RSP_R1       (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R1b      (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE| \
+                         MMC_RSP_BUSY)
+#define MMC_RSP_R2       (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
+#define MMC_RSP_R3       (MMC_RSP_PRESENT)
+#define MMC_RSP_R4       (MMC_RSP_PRESENT)
+#define MMC_RSP_R5       (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R6       (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R7       (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+
+/**
+  Find most significant set
+
+  @param   X  word to search
+
+  @retval most significant set bit number
+
+**/
+static inline INT32 GenericFls (INT32 X)
+{
+
+  INT32 I = 31;
+
+  for (I=31; I >= 0; I--) {
+    if(X & (1<<I))
+      return (I+1);
+  }
+
+  return 0;
+}
+
+struct SdCmd {
+  UINT16 CmdIdx;
+  UINT32 RespType;
+  UINT32 CmdArg;
+};
+
+EFI_STATUS
+MmcInitialize (
+  VOID
+  );
+
+EFI_STATUS
+RcvResp (
+  IN  UINT32  RespType,
+  OUT UINT32* Response,
+  IN  UINT8   Data
+  );
+
+BOOLEAN
+DetectCardPresence (
+  IN VOID
+  );
+
+BOOLEAN
+IsCardReadOnly (
+  IN VOID
+  );
+
+struct SdData {
+  UINT32 Flags;
+  UINT32 Blocks;
+  UINT32 Blocksize;
+  VOID   *Addr;
+};
+
+EFI_STATUS
+SendCmd (
+  IN  struct SdCmd  *Cmd,
+  IN  struct SdData *Data
+  );
+
+VOID
+SetIos (
+  IN  UINT32 BusClockFreq,
+  IN  UINT32 BusWidth,
+  IN  UINT32 TimingMode
+  );
+
+EFI_STATUS
+WriteBlock (
+  IN UINTN        Offset,
+  IN UINTN        Length,
+  IN UINT32*      Buffer,
+  IN struct SdCmd Cmd
+  );
+
+EFI_STATUS
+ReadBlock (
+  IN UINTN        Offset,
+  IN UINTN        Length,
+  OUT UINT32*     Buffer,
+  IN struct SdCmd Cmd
+  );
+
+extern UINT64 GetSdxcFrequency();
+
+#endif
diff --git a/Platform/NXP/Library/MmcLib/MmcInterface.c b/Platform/NXP/Library/MmcLib/MmcInterface.c
new file mode 100644
index 0000000..1b8ce25
--- /dev/null
+++ b/Platform/NXP/Library/MmcLib/MmcInterface.c
@@ -0,0 +1,544 @@
+/** @MmcInterface.c
+
+  Functions for providing Library interface APIs.
+
+  Copyright 2017 NXP
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD
+  License which accompanies this distribution. The full text of the license
+  may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseMemoryLib/MemLibInternals.h>
+#include <Library/BeIoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/MmcLib.h>
+#include <Library/TimerLib.h>
+
+#include "MmcInternal.h"
+
+struct Mmc *mMmc;
+
+/**
+  Function to detect card presence by checking host controller
+  present state register
+
+  @retval  Returns the card presence as TRUE/FALSE
+
+**/
+BOOLEAN
+DetectCardPresence (
+  IN VOID
+  )
+{
+  struct SdxcRegs *Regs;
+  INT32 Timeout;
+
+  Regs = (VOID *)PcdGet64 (PcdSdxcBaseAddr);
+  Timeout = 1000;
+
+  while (!(MmcRead ((UINTN)&Regs->Prsstat) & PRSSTATE_CINS) && --Timeout)
+    MicroSecondDelay (10);
+
+  if (Timeout > 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Function to check whether card is read only by verifying host controller
+  present state register
+
+  @retval  Returns the card read only or not as TRUE/FALSE
+
+**/
+BOOLEAN
+IsCardReadOnly (
+  IN VOID
+  )
+{
+  struct SdxcRegs *Regs;
+
+  Regs = (VOID *)PcdGet64 (PcdSdxcBaseAddr);
+
+  if (MmcRead ((UINTN)&Regs->Prsstat) & PRSSTATE_WPSPL) {
+    return FALSE;
+  } else {
+    DEBUG ((DEBUG_ERROR, "SD/MMC : Write Protection PIN is high\n"));
+    return TRUE;
+  }
+}
+
+/**
+  Function to prepare state(Wait for bus,Set up host controller
+  data,Transfer type)  for command to be send
+
+  @param  Cmd  Command to be used
+  @param  Data Data with command
+
+  @retval  Returns the command status
+
+**/
+EFI_STATUS
+SendCmd (
+  IN  struct SdCmd *Cmd,
+  IN  struct SdData *Data
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      Xfertype;
+  UINT32      Irqstat;
+  INT32       Timeout;
+  struct SdxcRegs *Regs;
+
+  Status = 0;
+  Timeout = 100000;
+  Regs = (VOID *)PcdGet64 (PcdSdxcBaseAddr);
+
+  DEBUG_MSG ("0x%x : Cmd.Id %d, Arg 0x%x SdCmd.RespType 0x%x \n",
+              Regs, Cmd->CmdIdx, Cmd->CmdArg, Cmd->RespType);
+
+  MmcWrite ((UINTN)&Regs->Irqstat, 0xFFFFFFFF);
+
+  asm ("Dmb :");
+
+  // Wait for The Bus To Be Idle
+  while ((MmcRead ((UINTN)&Regs->Prsstat) & PRSSTATE_CICHB) ||
+        (MmcRead ((UINTN)&Regs->Prsstat) & PRSSTATE_CIDHB))
+    NanoSecondDelay (10);
+
+  // Wait for data line to be active
+  while (MmcRead ((UINTN)&Regs->Prsstat) & PRSSTATE_DLA)
+    NanoSecondDelay (10);
+
+  // Wait Before The Next Command
+  MicroSecondDelay (1000);
+
+  // Set Up for A Data Transfer if We Have One
+  if (Data) {
+    Status = SdxcSetupData (Data);
+    if (Status) {
+      return Status;
+    }
+  }
+
+  // Figure Out The Transfer Arguments
+  Xfertype = SdxcXfertype (Cmd, Data);
+
+  // Mask All Irqs
+  MmcWrite ((UINTN)&Regs->Irqsigen, 0);
+
+  // Send The Command
+  MmcWrite ((UINTN)&Regs->CmdArg, Cmd->CmdArg);
+  MmcWrite ((UINTN)&Regs->Xfertype, Xfertype);
+
+  // Wait for The Command To Complete
+  Timeout = 100000;
+  while ((!(MmcRead ((UINTN)&Regs->Irqstat) & (IRQSTATE_CC | IRQSTATE_CTOE)))
+        && Timeout--);
+
+  if (Timeout <= 0) {
+    DEBUG ((DEBUG_ERROR, "Command not completed %d\n", Cmd->CmdIdx));
+    return EFI_TIMEOUT;
+  }
+
+  Irqstat = MmcRead ((UINTN)&Regs->Irqstat);
+
+  if (Irqstat & CMD_ERR) {
+    Status = EFI_DEVICE_ERROR;
+    DEBUG ((DEBUG_ERROR, "SdxcSendCmd: Device Error(0x%x) for Cmd(%d)\n",
+                Irqstat, Cmd->CmdIdx));
+    goto Out;
+  }
+
+  if (Irqstat & IRQSTATE_CTOE) {
+    Status = EFI_TIMEOUT;
+    DEBUG ((DEBUG_ERROR, "SdxcSendCmd: Timeout for Cmd(%d)\n", Cmd->CmdIdx));
+    goto Out;
+  }
+
+Out:
+  if (Status) {
+    ResetCmdFailedData (Regs, (Data != NULL));
+  }
+  else {
+    MmcWrite ((UINTN)&Regs->Irqstat, 0xFFFFFFFF);
+  }
+  return Status;
+
+}
+
+/**
+  Function to receive command response
+
+  @param  RespType Type of response
+  @param  Data     Data of response
+
+  @param  Response Pointer to response buffer
+
+  @retval  Returns the command response status
+
+**/
+EFI_STATUS
+RcvResp (
+  IN   UINT32   RespType,
+  OUT  UINT32*  Response,
+  IN   UINT8    Data
+  )
+{
+  if (RespType != 0xFF) {
+    INT32 Timeout;
+    struct SdxcRegs *Regs;
+
+    Timeout = 25000;
+    Regs = (VOID *)PcdGet64(PcdSdxcBaseAddr);
+
+    // Workaround for SDXC Errata ENGcm03648
+    if (!Data && (RespType & MMC_RSP_BUSY)) {
+      Timeout = 25000;
+
+      // Poll On DATA0 Line for Cmd With Busy Signal for 250 Ms
+      while (Timeout > 0 && !(MmcRead ((UINTN)&Regs->Prsstat) &
+            PRSSTATE_DAT0)) {
+        MicroSecondDelay (100);
+        Timeout--;
+      }
+
+      if (Timeout <= 0) {
+        DEBUG ((DEBUG_ERROR, "Timeout Waiting for DAT0 To Go High!\n"));
+        ResetCmdFailedData (Regs, Data);
+        return EFI_TIMEOUT;
+      }
+    }
+
+    // Copy The Response To The Response Buffer
+    if (RespType & MMC_RSP_136) {
+      UINT32 Rspns3, Rspns2, Rspns1, Rspns0;
+
+      Rspns3 = MmcRead ((UINTN)&Regs->Rspns3);
+      Rspns2 = MmcRead ((UINTN)&Regs->Rspns2);
+      Rspns1 = MmcRead ((UINTN)&Regs->Rspns1);
+      Rspns0 = MmcRead ((UINTN)&Regs->Rspns0);
+      Response[3] = (Rspns3 << 8) | (Rspns2 >> 24);
+      Response[2] = (Rspns2 << 8) | (Rspns1 >> 24);
+      Response[1] = (Rspns1 << 8) | (Rspns0 >> 24);
+      Response[0] = (Rspns0 << 8);
+      DEBUG_MSG ("RESP : 0x%x : 0x%x : 0x%x : 0x%x \n",
+                 Response[0], Response[1], Response[2], Response[3]);
+    } else {
+      Response[0] = MmcRead ((UINTN)&Regs->Rspns0);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Function to prepare command transfer
+
+  @param  Flags  Flags for transferType of response
+  @param  Length Length of block
+  @param  Cmd    Pointer to command structure
+
+  @retval  Returns the command status
+
+**/
+EFI_STATUS
+PrepareTransfer (
+  UINT32        Flags,
+  IN UINTN      Length,
+  IN VOID*      Buffer,
+  IN struct SdCmd   *Cmd
+  )
+{
+  EFI_STATUS Status;
+  struct SdData Data;
+
+  Data.Flags = Flags;
+
+  if (Length > MMC_MAX_BLOCK_LEN) {
+    Data.Blocks = (Length / MMC_MAX_BLOCK_LEN) +
+            ((Length % MMC_MAX_BLOCK_LEN) ? 1 : 0);
+    Data.Blocksize = MMC_MAX_BLOCK_LEN;
+  } else {
+    Data.Blocks = 1;
+    Data.Blocksize = Length;
+  }
+
+  Data.Addr = Buffer;
+
+  Status = SendCmd (Cmd, &Data);
+
+  return Status;
+}
+
+/**
+  Function to Read MMC Block
+
+  @param  Offset Offset to read from
+  @param  Length Length of block
+  @param  Cmd    Pointer to command structure
+
+  @param  Buffer Pointer to buffer for data read
+
+  @retval  Returns the read block command status
+
+**/
+EFI_STATUS
+ReadBlock (
+  IN UINTN      Offset,
+  IN UINTN      Length,
+  OUT UINT32*   Buffer,
+  IN struct SdCmd      Cmd
+  )
+{
+  EFI_STATUS Status;
+  struct DmaData DmaData;
+  VOID * Temp;
+
+  Temp = NULL;
+
+  DmaData.Bytes = Length;
+  DmaData.MapOperation = MapOperationBusMasterRead;
+
+  Temp = GetDmaBuffer (&DmaData);
+  if (Temp == NULL) {
+    DEBUG ((DEBUG_ERROR,"Mmc Read : Failed to get DMA buffer \n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = PrepareTransfer (MMC_DATA_READ, Length, Temp, &Cmd);
+  if (Status) {
+    DEBUG((DEBUG_ERROR,"Mmc Read: Fail to setup controller 0x%x \n", Status));
+    FreeDmaBuffer (&DmaData);
+    return Status;
+  }
+
+  Status = Transfer ();
+  if (Status) {
+    DEBUG ((DEBUG_ERROR,"Mmc Read Failed (0x%x) \n", Status));
+    FreeDmaBuffer (&DmaData);
+    return Status;
+  }
+
+  InternalMemCopyMem (Buffer, Temp , DmaData.Bytes);
+
+  Status = FreeDmaBuffer (&DmaData);
+  if (Status) {
+    DEBUG ((DEBUG_ERROR,"Mmc Read : Failed to release DMA buffer \n"));
+    return Status;
+  }
+
+  return Status;
+}
+
+/**
+  Function to Write MMC Block
+
+  @param  Offset Offset to write to
+  @param  Length Length of block
+  @param  Buffer Pointer to buffer for data to be written
+  @param  Cmd    Pointer to command structure
+
+  @retval  Returns the write block command status
+
+**/
+EFI_STATUS
+WriteBlock (
+  IN UINTN      Offset,
+  IN UINTN      Length,
+  IN UINT32*    Buffer,
+  IN struct SdCmd      Cmd
+  )
+{
+  EFI_STATUS  Status;
+  struct DmaData DmaData;
+  VOID * Temp;
+
+  Temp = NULL;
+
+  DmaData.Bytes = Length;
+  DmaData.MapOperation = MapOperationBusMasterWrite;
+
+  Temp = GetDmaBuffer (&DmaData);
+  if (Temp == NULL) {
+    DEBUG ((DEBUG_ERROR,"Mmc Write : Failed to get DMA buffer \n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  InternalMemCopyMem (Temp, Buffer, DmaData.Bytes);
+
+  Status = PrepareTransfer (MMC_DATA_WRITE, Length, Temp, &Cmd);
+  if (Status) {
+    DEBUG ((DEBUG_ERROR,"Mmc Write: Fail to setup controller 0x%x \n", Status));
+    FreeDmaBuffer (&DmaData);
+    return Status;
+  }
+
+  Status = Transfer ();
+  if (Status) {
+    DEBUG((DEBUG_ERROR,"Mmc Write Failed (0x%x) \n", Status));
+    FreeDmaBuffer (&DmaData);
+    return Status;
+  }
+
+  Status = FreeDmaBuffer (&DmaData);
+  if (Status) {
+    DEBUG ((DEBUG_ERROR,"Mmc Write : Failed to release DMA buffer \n"));
+    return Status;
+  }
+
+  return Status;
+}
+
+/**
+  Function to Initialize MMC
+
+  // Set Bus width
+  // Set protocol register
+
+  @retval  Returns the initialization status
+
+**/
+EFI_STATUS
+InitMmc (
+  IN  VOID
+  )
+{
+  EFI_STATUS Status;
+  struct SdxcRegs *Regs;
+
+  Regs = (VOID *)PcdGet64 (PcdSdxcBaseAddr);
+
+  Status = SdxcInit (mMmc);
+  if (Status) {
+    return Status;
+  }
+
+  mMmc->DdrMode = 0;
+  SdxcSetBusWidth (mMmc, 1);
+
+  MmcAnd ((UINTN)&Regs->Proctl, ~PRCTL_BE);
+
+  return Status;
+}
+
+/**
+  Function to set MMC clock speed
+
+  @param  BusClockFreq Bus clock frequency to be set Offset to write to
+  @param  BusWidth     Bus width
+  @param  TimingMode   Timing mode to be set
+
+**/
+VOID
+SetIos (
+  IN  UINT32   BusClockFreq,
+  IN  UINT32   BusWidth,
+  IN  UINT32   TimingMode
+  )
+{
+  struct SdxcRegs *Regs;
+
+  Regs = (VOID *)PcdGet64 (PcdSdxcBaseAddr);
+
+  DEBUG_MSG ("BusClockFreq %d, BusWidth %d\n", BusClockFreq, BusWidth);
+
+  // Set The Clock Speed
+  if (BusClockFreq) {
+    SetSysctl (BusClockFreq);
+  }
+
+  // Set The Bus Width
+  if (BusWidth) {
+    MmcAnd ((UINTN)&Regs->Proctl, ~(PRCTL_DTW_4 | PRCTL_DTW_8));
+  }
+
+  if (BusWidth == 4) {
+    MmcOr ((UINTN)&Regs->Proctl, PRCTL_DTW_4);
+  }
+  else if (BusWidth == 8) {
+    MmcOr ((UINTN)&Regs->Proctl, PRCTL_DTW_8);
+  }
+}
+
+/**
+  Helper Function to initialize MMC
+
+  // Reset MMC controller
+  // Set host voltage capabilities
+  // Set MMC clock
+
+**/
+EFI_STATUS
+MmcInitialize (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  struct SdxcRegs *Regs;
+
+  UINT32 Caps, VoltageCaps;
+  UINTN Voltages;
+
+  Regs = (VOID *)PcdGet64 (PcdSdxcBaseAddr);
+
+  // First Reset The SDXC Controller
+  SdxcReset (Regs);
+
+  VoltageCaps = 0;
+  Caps = MmcRead ((UINTN)&Regs->Hostcapblt);
+
+  Caps = Caps | SDXC_HOSTCAPBLT_VS33;
+
+  if (Caps & SDXC_HOSTCAPBLT_VS30) {
+    VoltageCaps |= MMC_VDD_29_30 | MMC_VDD_30_31;
+  }
+  if (Caps & SDXC_HOSTCAPBLT_VS33) {
+    VoltageCaps |= MMC_VDD_32_33 | MMC_VDD_33_34;
+  }
+  if (Caps & SDXC_HOSTCAPBLT_VS18) {
+    VoltageCaps |= MMC_VDD_165_195;
+  }
+
+  Voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+  if ((Voltages & VoltageCaps) == 0) {
+    DEBUG ((DEBUG_ERROR, "Voltage Not Supported By Controller\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  mMmc = (struct Mmc*)AllocatePool (sizeof (struct Mmc));
+  if (mMmc == NULL) {
+    DEBUG ((DEBUG_ERROR, "Memory Allocation failed for gMMC\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  InternalMemZeroMem (mMmc, sizeof (struct Mmc));
+
+  mMmc->SdhcClk = GetSdxcFrequency ();
+
+  mMmc->HostCaps = MMC_MODE_4_BIT | MMC_MODE_8_BIT | MMC_MODE_HC;
+
+  if (Caps & SDXC_HOSTCAPBLT_HSS) {
+    mMmc->HostCaps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+  }
+
+  mMmc->FMin = MIN_CLK_FREQUENCY;
+  mMmc->FMax = MIN ((UINT32)mMmc->SdhcClk, MAX_CLK_FREQUENCY);
+
+  Status = InitMmc ();
+  if (Status != EFI_SUCCESS) {
+      DEBUG ((DEBUG_ERROR,"Failed to initialize MMC\n"));
+      return Status;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/NXP/Library/MmcLib/MmcInternal.h b/Platform/NXP/Library/MmcLib/MmcInternal.h
new file mode 100644
index 0000000..0e56764
--- /dev/null
+++ b/Platform/NXP/Library/MmcLib/MmcInternal.h
@@ -0,0 +1,350 @@
+/** @file
+  Header Defining The MMC Memory Controller Constants, Function Prototype, Structures Etc
+
+  Copyright 2017 NXP
+
+  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.
+
+**/
+
+#ifndef __MMC_INTERNAL_H__
+#define __MMC_INTERNAL_H__
+
+#include <Library/DmaLib.h>
+
+#define MIN_CLK_FREQUENCY          400000
+#define MAX_CLK_FREQUENCY          52000000
+
+#define ENABLE_CACHE_SNOOPING      0x00000040
+#define CMD_STOP_TRANSMISSION      12
+/**
+  Pre Div factor for DDR mode
+**/
+#define DIV_2  2
+#define DIV_1  1
+
+/**
+  SDXC-Specific Constants
+**/
+#define SYSCTL              0x0002e02c
+#define SYSCTL_INITA        0x08000000
+#define SYSCTL_TIMEOUT_MASK 0x000f0000
+#define SYSCTL_CLOCK_MASK   0x0000fff0
+#define SYSCTL_CKEN         0x00000008
+#define SYSCTL_PEREN        0x00000004
+#define SYSCTL_HCKEN        0x00000002
+#define SYSCTL_IPGEN        0x00000001
+#define SYSCTL_RSTA         0x01000000
+#define SYSCTL_RSTC         0x02000000
+#define SYSCTL_RSTD         0x04000000
+
+/**
+  Host Capabilities
+**/
+#define SDXC_HOSTCAPBLT_VS18      0x04000000
+#define SDXC_HOSTCAPBLT_VS30      0x02000000
+#define SDXC_HOSTCAPBLT_VS33      0x01000000
+#define SDXC_HOSTCAPBLT_SRS       0x00800000
+#define SDXC_HOSTCAPBLT_DMAS      0x00400000
+#define SDXC_HOSTCAPBLT_HSS       0x00200000
+
+/**
+  VDD Voltage Range
+**/
+#define MMC_VDD_165_195            0x00000080    // VDD Voltage 1.65 - 1.95
+#define MMC_VDD_20_21              0x00000100    // VDD Voltage 2.0 ~ 2.1
+#define MMC_VDD_21_22              0x00000200    // VDD Voltage 2.1 ~ 2.2
+#define MMC_VDD_22_23              0x00000400    // VDD Voltage 2.2 ~ 2.3
+#define MMC_VDD_23_24              0x00000800    // VDD Voltage 2.3 ~ 2.4
+#define MMC_VDD_24_25              0x00001000    // VDD Voltage 2.4 ~ 2.5
+#define MMC_VDD_25_26              0x00002000    // VDD Voltage 2.5 ~ 2.6
+#define MMC_VDD_26_27              0x00004000    // VDD Voltage 2.6 ~ 2.7
+#define MMC_VDD_27_28              0x00008000    // VDD Voltage 2.7 ~ 2.8
+#define MMC_VDD_28_29              0x00010000    // VDD Voltage 2.8 ~ 2.9
+#define MMC_VDD_29_30              0x00020000    // VDD Voltage 2.9 ~ 3.0
+#define MMC_VDD_30_31              0x00040000    // VDD Voltage 3.0 ~ 3.1
+#define MMC_VDD_31_32              0x00080000    // VDD Voltage 3.1 ~ 3.2
+#define MMC_VDD_32_33              0x00100000    // VDD Voltage 3.2 ~ 3.3
+#define MMC_VDD_33_34              0x00200000    // VDD Voltage 3.3 ~ 3.4
+#define MMC_VDD_34_35              0x00400000    // VDD Voltage 3.4 ~ 3.5
+#define MMC_VDD_35_36              0x00800000    // VDD Voltage 3.5 ~ 3.6
+
+/**
+  MMC Operating Modes
+**/
+#define MMC_MODE_HS         (1 << 0)
+#define MMC_MODE_HS_52MHz   (1 << 1)
+#define MMC_MODE_4_BIT      (1 << 2)
+#define MMC_MODE_8_BIT      (1 << 3)
+#define MMC_MODE_SPI        (1 << 4)
+#define MMC_MODE_HC         (1 << 5)
+#define MMC_MODE_DDR_52MHz  (1 << 6)
+
+#define MMC_DATA_READ        1
+#define MMC_DATA_WRITE       2
+
+/**
+  Maximum Block Size for MMC
+**/
+#define MMC_MAX_BLOCK_LEN   512
+
+#define WML_RD_MAX      0x10
+#define WML_WR_MAX      0x80
+#define WML_RD_MAX_VAL  0x00
+#define WML_WR_MAX_VAL  0x80
+#define WML_RD_MASK     0xff
+#define WML_WR_MASK     0xff0000
+
+#define XFERTYPE                    0x0002e00c
+#define XFERTYPE_CMD(X)             ((X & 0x3f) << 24)
+#define XFERTYPE_CMDTYP_NORMAL      0x0
+#define XFERTYPE_CMDTYP_SUSPEND     0x00400000
+#define XFERTYPE_CMDTYP_RESUME      0x00800000
+#define XFERTYPE_CMDTYP_ABORT       0x00c00000
+#define XFERTYPE_DPSEL              0x00200000
+#define XFERTYPE_CICEN              0x00100000
+#define XFERTYPE_CCCEN              0x00080000
+#define XFERTYPE_RSPTYP_NONE        0
+#define XFERTYPE_RSPTYP_136         0x00010000
+#define XFERTYPE_RSPTYP_48          0x00020000
+#define XFERTYPE_RSPTYP_48_BUSY     0x00030000
+#define XFERTYPE_MSBSEL             0x00000020
+#define XFERTYPE_DTDSEL             0x00000010
+#define XFERTYPE_AC12EN             0x00000004
+#define XFERTYPE_BCEN               0x00000002
+#define XFERTYPE_DMAEN              0x00000001
+
+/**
+  IRQSTAT bits
+**/
+#define IRQSTAT              (0x0002e030)
+#define IRQSTATE_DMAE        (0x10000000)
+#define IRQSTATE_AC12E       (0x01000000)
+#define IRQSTATE_DEBE        (0x00400000)
+#define IRQSTATE_DCE         (0x00200000)
+#define IRQSTATE_DTOE        (0x00100000)
+#define IRQSTATE_CIE         (0x00080000)
+#define IRQSTATE_CEBE        (0x00040000)
+#define IRQSTATE_CCE         (0x00020000)
+#define IRQSTATE_CTOE        (0x00010000)
+#define IRQSTATE_CINT        (0x00000100)
+#define IRQSTATE_CRM         (0x00000080)
+#define IRQSTATE_CINS        (0x00000040)
+#define IRQSTATE_BRR         (0x00000020)
+#define IRQSTATE_BWR         (0x00000010)
+#define IRQSTATE_DINT        (0x00000008)
+#define IRQSTATE_BGE         (0x00000004)
+#define IRQSTATE_TC          (0x00000002)
+#define IRQSTATE_CC          (0x00000001)
+
+#define CMD_ERR             (IRQSTATE_CIE | IRQSTATE_CEBE | IRQSTATE_CCE)
+#define DATA_ERR            (IRQSTATE_DEBE | IRQSTATE_DCE | IRQSTATE_DTOE | \
+                            IRQSTATE_DMAE)
+#define DATA_COMPLETE       (IRQSTATE_TC | IRQSTATE_DINT)
+
+#define IRQSTATE_EN           (0x0002e034)
+#define IRQSTATE_EN_DMAE      (0x10000000)
+#define IRQSTATE_EN_AC12E     (0x01000000)
+#define IRQSTATE_EN_DEBE      (0x00400000)
+#define IRQSTATE_EN_DCE       (0x00200000)
+#define IRQSTATE_EN_DTOE      (0x00100000)
+#define IRQSTATE_EN_CIE       (0x00080000)
+#define IRQSTATE_EN_CEBE      (0x00040000)
+#define IRQSTATE_EN_CCE       (0x00020000)
+#define IRQSTATE_EN_CTOE      (0x00010000)
+#define IRQSTATE_EN_CINT      (0x00000100)
+#define IRQSTATE_EN_CRM       (0x00000080)
+#define IRQSTATE_EN_CINS      (0x00000040)
+#define IRQSTATE_EN_BRR       (0x00000020)
+#define IRQSTATE_EN_BWR       (0x00000010)
+#define IRQSTATE_EN_DINT      (0x00000008)
+#define IRQSTATE_EN_BGE       (0x00000004)
+#define IRQSTATE_EN_TC        (0x00000002)
+#define IRQSTATE_EN_CC        (0x00000001)
+
+#define PRSSTATE             (0x0002e024)
+#define PRSSTATE_DAT0        (0x01000000)
+#define PRSSTATE_CLSL        (0x00800000)
+#define PRSSTATE_WPSPL       (0x00080000)
+#define PRSSTATE_CDPL        (0x00040000)
+#define PRSSTATE_CINS        (0x00010000)
+#define PRSSTATE_BREN        (0x00000800)
+#define PRSSTATE_BWEN        (0x00000400)
+#define PRSSTATE_DLA         (0x00000004)
+#define PRSSTATE_CICHB       (0x00000002)
+#define PRSSTATE_CIDHB       (0x00000001)
+
+#define PRCTL              0x0002e028
+#define PRCTL_INIT         0x00000020
+#define PRCTL_DTW_4        0x00000002
+#define PRCTL_DTW_8        0x00000004
+#define PRCTL_BE           0x00000030
+
+struct SdxcRegs {
+       UINT32    Dsaddr;      // SDMA System Address Register
+       UINT32    Blkattr;     // Block Attributes Register
+       UINT32    CmdArg;      // Command Argument Register
+       UINT32    Xfertype;     // Transfer Type Register
+       UINT32    Rspns0;     // Command Response 0 Register
+       UINT32    Rspns1;     // Command Response 1 Register
+       UINT32    Rspns2;     // Command Response 2 Register
+       UINT32    Rspns3;     // Command Response 3 Register
+       UINT32    Datport;     // Buffer Data Port Register
+       UINT32    Prsstat;     // Present State Register
+       UINT32    Proctl;      // Protocol Control Register
+       UINT32    Sysctl;      // System Control Register
+       UINT32    Irqstat;     // Interrupt Status Register
+       UINT32    Irqstaten;   // Interrupt Status Enable Register
+       UINT32    Irqsigen;    // Interrupt Signal Enable Register
+       UINT32    Autoc12err;  // Auto CMD Error Status Register
+       UINT32    Hostcapblt;  // Host Controller Capabilities Register
+       UINT32    Wml;         // Watermark Level Register
+       UINT32    Mixctrl;     // for USDHC
+       CHAR8     Reserved1[4]; // Reserved
+       UINT32    Fevt;        // Force Event Register
+       UINT32    Admaes;      // ADMA Error Status Register
+       UINT32    Adsaddr;     // ADMA System Address Register
+       CHAR8     Reserved2[100];// Reserved
+       UINT32    VendorSpec;  //Vendor Specific Register
+       CHAR8     Reserved3[56];// Reserved
+       UINT32    Hostver;     // Host Controller Version Register
+       CHAR8     Reserved4[4];// Reserved
+       UINT32    Dmaerraddr;  // DMA Error Address Register
+       CHAR8     Reserved5[4];// Reserved
+       UINT32    Dmaerrattr;  // DMA Error Attribute Register
+       CHAR8     Reserved6[4];// Reserved
+       UINT32    Hostcapblt2; // Host Controller Capabilities Register 2
+       CHAR8     Reserved7[8];// Reserved
+       UINT32    Tcr;         // Tuning Control Register
+       CHAR8     Reserved8[28];// Reserved
+       UINT32    Sddirctl;    // SD Direction Control Register
+       CHAR8     Reserved9[712];// Reserved
+       UINT32    Scr;         // SDXC Control Register
+};
+
+struct DmaData {
+  VOID *DmaAddr;
+  UINTN Bytes;
+  VOID *Mapping;
+  DMA_MAP_OPERATION MapOperation;
+};
+
+struct Mmc {
+       UINT32 SdhcClk;
+       UINT32 HostCaps;
+       UINT32 HasInit;
+       UINT32 FMin;
+       UINT32 FMax;
+       UINT32 BusWidth;
+       UINT32 Clock;
+       UINT32 CardCaps;
+       INT32  DdrMode;
+};
+
+VOID
+SdxcSetClock (
+  IN  struct Mmc *Mmc,
+  IN  UINT32 Clock
+  );
+
+EFI_STATUS
+SdxcInit (
+  IN  struct Mmc *Mmc
+  );
+
+EFI_STATUS
+SdxcGoIdle (
+  IN  struct Mmc *Mmc
+  );
+
+VOID
+SdxcReset (
+  IN struct SdxcRegs *Regs
+  );
+
+VOID *
+GetDmaBuffer (
+  IN struct DmaData *DmaData
+  );
+
+EFI_STATUS
+FreeDmaBuffer (
+  IN struct DmaData *DmaData
+  );
+
+EFI_STATUS
+SdxcSetupData (
+  IN  struct SdData *Data
+  );
+
+UINT32
+SdxcXfertype (
+  IN  struct SdCmd *Cmd,
+  IN  struct SdData *Data
+  );
+
+VOID
+ResetCmdFailedData (
+  IN  struct SdxcRegs *Regs,
+  IN  UINT8  Data
+  );
+
+VOID
+SdxcSetBusWidth (
+  IN  struct Mmc *Mmc,
+  IN  UINT32 BWidth
+  );
+
+EFI_STATUS
+Transfer (
+  IN  VOID
+  );
+
+VOID
+SetSysctl (
+  UINT32 Clock
+  );
+
+UINT32
+EFIAPI
+MmcRead (
+  IN  UINTN     Address
+  );
+
+UINT32
+EFIAPI
+MmcWrite (
+  IN  UINTN     Address,
+  IN  UINT32    Value
+  );
+
+UINT32
+EFIAPI
+MmcAndThenOr (
+  IN  UINTN     Address,
+  IN  UINT32    AndData,
+  IN  UINT32    OrData
+  );
+
+UINT32
+EFIAPI
+MmcOr (
+  IN  UINTN     Address,
+  IN  UINT32    OrData
+  );
+
+UINT32
+EFIAPI
+MmcAnd (
+  IN  UINTN     Address,
+  IN  UINT32    AndData
+  );
+
+#endif
diff --git a/Platform/NXP/Library/MmcLib/MmcLib.c b/Platform/NXP/Library/MmcLib/MmcLib.c
new file mode 100644
index 0000000..83b12c9
--- /dev/null
+++ b/Platform/NXP/Library/MmcLib/MmcLib.c
@@ -0,0 +1,597 @@
+/**@file
+
+  Copyright 2017 NXP
+
+  This Program And The Accompanying Materials
+  Are Licensed And Made Available Under The Terms And Conditions Of The BSD License
+  Which Accompanies This Distribution.  The Full Text Of The License May Be Found At
+  Http://Opensource.Org/Licenses/Bsd-License.Php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BeIoLib.h>
+#include <Library/IoLib.h>
+#include <Library/MmcLib.h>
+#include <Library/TimerLib.h>
+#include "MmcInternal.h"
+
+extern struct Mmc *mMmc;
+
+/**
+  Function to read from MMC depending upon pcd
+
+  @param   Address  MMC register to read
+
+  @retval  Read Value from register
+
+**/
+UINT32
+EFIAPI
+MmcRead (
+  IN  UINTN     Address
+  )
+{
+  if (FixedPcdGetBool (PcdMmcBigEndian)) {
+    return BeMmioRead32(Address);
+  } else {
+    return MmioRead32 (Address);
+  }
+}
+
+/**
+  Function to write on MMC depeding upon pcd
+
+  @param   Address  MMC register to write
+
+**/
+UINT32
+EFIAPI
+MmcWrite (
+  IN  UINTN     Address,
+  IN  UINT32    Value
+  )
+{
+  if (FixedPcdGetBool (PcdMmcBigEndian)) {
+    return BeMmioWrite32 (Address, Value);
+  } else {
+    return MmioWrite32 (Address, Value);
+  }
+}
+
+/**
+  Function to call MmioAndThenOr32 depending upon pcd
+
+  @param   Address MMC register
+  @param   AndData The value to AND with the read value from the MMC register
+  @param   OrData  The value to OR with the result of the AND operation.
+
+  @retval  Value written back to register
+
+**/
+UINT32
+EFIAPI
+MmcAndThenOr (
+  IN  UINTN     Address,
+  IN  UINT32    AndData,
+  IN  UINT32    OrData
+  )
+{
+  if (FixedPcdGetBool (PcdMmcBigEndian)) {
+    return BeMmioAndThenOr32 (Address, AndData, OrData);
+  } else {
+    return MmioAndThenOr32 (Address, AndData, OrData);
+  }
+}
+
+/**
+  Function to call MmioOr32 depending upon pcd
+
+  @param   Address MMC register
+  @param   OrData  The value to OR with the result of the AND operation.
+
+  @retval  Value written back to register
+
+**/
+UINT32
+EFIAPI
+MmcOr (
+  IN  UINTN     Address,
+  IN  UINT32    OrData
+  )
+{
+  if (FixedPcdGetBool (PcdMmcBigEndian)) {
+    return BeMmioOr32 (Address, OrData);
+  } else {
+    return MmioOr32 (Address, OrData);
+  }
+}
+
+/**
+  Function to call MmioAnd32 depending upon pcd
+
+  @param   Address MMC register
+  @param   AndData The value to AND with the read value from the MMC register
+
+  @retval  Value written back to register
+
+**/
+UINT32
+EFIAPI
+MmcAnd (
+  IN  UINTN     Address,
+  IN  UINT32    AndData
+  )
+{
+  if (FixedPcdGetBool (PcdMmcBigEndian)) {
+    return BeMmioAnd32 (Address, AndData);
+  } else {
+    return MmioAnd32 (Address, AndData);
+  }
+}
+
+/**
+  Function to Dump MMC Controller register
+**/
+VOID
+DumpMmcRegs (
+  IN VOID
+  )
+{
+  struct SdxcRegs *Regs;
+
+  Regs = (VOID *)PcdGet64(PcdSdxcBaseAddr);
+
+  DEBUG ((DEBUG_ERROR, "Dsaddr : 0x%x \n", Regs->Dsaddr));
+  DEBUG ((DEBUG_ERROR, "Blkattr : 0x%x \n", Regs->Blkattr));
+  DEBUG ((DEBUG_ERROR, "CmdArg : 0x%x \n", Regs->CmdArg));
+  DEBUG ((DEBUG_ERROR, "Xfertype : 0x%x \n", Regs->Xfertype));
+  DEBUG ((DEBUG_ERROR, "Rspns0 : 0x%x \n", Regs->Rspns0));
+  DEBUG ((DEBUG_ERROR, "Rspns1 : 0x%x \n", Regs->Rspns1));
+  DEBUG ((DEBUG_ERROR, "Rspns1 : 0x%x \n", Regs->Rspns1));
+  DEBUG ((DEBUG_ERROR, "Rspns3 : 0x%x \n", Regs->Rspns3));
+  DEBUG ((DEBUG_ERROR, "Datport : 0x%x \n", Regs->Datport));
+  DEBUG ((DEBUG_ERROR, "Prsstat : 0x%x \n", Regs->Prsstat));
+  DEBUG ((DEBUG_ERROR, "Proctl : 0x%x \n", Regs->Proctl));
+  DEBUG ((DEBUG_ERROR, "Sysctl : 0x%x \n", Regs->Sysctl));
+  DEBUG ((DEBUG_ERROR, "Irqstat : 0x%x \n", Regs->Irqstat));
+  DEBUG ((DEBUG_ERROR, "Irqstaten : 0x%x \n", Regs->Irqstaten));
+  DEBUG ((DEBUG_ERROR, "Irqsigen : 0x%x \n", Regs->Irqsigen));
+  DEBUG ((DEBUG_ERROR, "Autoc12err : 0x%x \n", Regs->Autoc12err));
+  DEBUG ((DEBUG_ERROR, "Hostcapblt : 0x%x \n", Regs->Hostcapblt));
+  DEBUG ((DEBUG_ERROR, "Wml : 0x%x \n", Regs->Wml));
+  DEBUG ((DEBUG_ERROR, "Mixctrl : 0x%x \n", Regs->Mixctrl));
+  DEBUG ((DEBUG_ERROR, "Fevt : 0x%x \n", Regs->Fevt));
+  DEBUG ((DEBUG_ERROR, "Admaes : 0x%x \n", Regs->Admaes));
+  DEBUG ((DEBUG_ERROR, "Adsaddr : 0x%x \n", Regs->Adsaddr));
+  DEBUG ((DEBUG_ERROR, "Hostver : 0x%x \n", Regs->Hostver));
+  DEBUG ((DEBUG_ERROR, "Dmaerraddr : 0x%x \n", Regs->Dmaerraddr));
+  DEBUG ((DEBUG_ERROR, "Dmaerrattr : 0x%x \n", Regs->Dmaerrattr));
+  DEBUG ((DEBUG_ERROR, "Hostcapblt2 : 0x%x \n", Regs->Hostcapblt2));
+  DEBUG ((DEBUG_ERROR, "Tcr : 0x%x \n", Regs->Tcr));
+  DEBUG ((DEBUG_ERROR, "Sddirctl : 0x%x \n", Regs->Sddirctl));
+  DEBUG ((DEBUG_ERROR, "Scr : 0x%x \n", Regs->Scr));
+}
+
+/**
+  Function to create dma map for read/write operation
+
+  @param   DmaData Pointer to Dma data Structure
+
+  @retval  Address of dma map
+
+**/
+VOID *
+GetDmaBuffer (
+  IN struct DmaData *DmaData
+  )
+{
+  EFI_STATUS Status;
+  EFI_PHYSICAL_ADDRESS PhyAddr;
+
+  Status = DmaAllocateBuffer (EfiBootServicesData,
+                              EFI_SIZE_TO_PAGES (DmaData->Bytes),
+                              &(DmaData->DmaAddr));
+  if (Status) {
+    DEBUG((DEBUG_ERROR,"DmaAllocateBuffer failed\n"));
+    return NULL;
+  }
+
+  Status = DmaMap (DmaData->MapOperation, DmaData->DmaAddr,
+                  &DmaData->Bytes, &PhyAddr, &DmaData->Mapping);
+  if (Status) {
+    DEBUG((DEBUG_ERROR,"DmaMap failed %d \n", Status));
+
+    DmaFreeBuffer(EFI_SIZE_TO_PAGES (DmaData->Bytes), DmaData->DmaAddr);
+
+    return NULL;
+  }
+  return (VOID *)PhyAddr;
+}
+
+/**
+  Function to free dma map
+
+  @param   DmaData Pointer to Dma data Structure
+
+  @retval  Address of dma map
+
+**/
+EFI_STATUS
+FreeDmaBuffer (
+  IN struct DmaData *DmaData
+  )
+{
+  EFI_STATUS Status;
+
+  Status = DmaUnmap (DmaData->Mapping);
+  if (Status) {
+    DEBUG((DEBUG_ERROR,"DmaUnmap failed 0x%x\n", Status));
+  }
+
+  Status = DmaFreeBuffer (EFI_SIZE_TO_PAGES (DmaData->Bytes), DmaData->DmaAddr);
+  if (Status) {
+    DEBUG((DEBUG_ERROR,"DmaFreeBuffer failed 0x%x\n", Status));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Function to select the transfer type flags depending upon given
+  command and data packet
+
+  @param   Cmd  Pointer to MMC command
+  @param   Data Pointer to MMC data
+
+  @retval  Returns the XFERTYPE flags
+
+**/
+UINT32
+SdxcXfertype (
+  IN  struct SdCmd *Cmd,
+  IN  struct SdData *Data
+  )
+{
+  UINT32 Xfertype;
+
+  Xfertype = 0;
+
+  if (Data) {
+    Xfertype |= XFERTYPE_DPSEL;
+    Xfertype |= XFERTYPE_DMAEN; //DMA Support
+
+    if (Data->Blocks > 1) {
+      Xfertype |= XFERTYPE_MSBSEL;
+      Xfertype |= XFERTYPE_BCEN;
+    }
+
+    if (Data->Flags & MMC_DATA_READ) {
+      Xfertype |= XFERTYPE_DTDSEL;
+    }
+  }
+
+  if (Cmd->RespType & MMC_RSP_CRC) {
+    Xfertype |= XFERTYPE_CCCEN;
+  }
+  if (Cmd->RespType & MMC_RSP_OPCODE) {
+    Xfertype |= XFERTYPE_CICEN;
+  }
+  if (Cmd->RespType & MMC_RSP_136) {
+    Xfertype |= XFERTYPE_RSPTYP_136;
+  }
+  else if (Cmd->RespType & MMC_RSP_BUSY) {
+    Xfertype |= XFERTYPE_RSPTYP_48_BUSY;
+  }
+  else if (Cmd->RespType & MMC_RSP_PRESENT) {
+    Xfertype |= XFERTYPE_RSPTYP_48;
+  }
+
+  if (Cmd->CmdIdx == CMD_STOP_TRANSMISSION) {
+    Xfertype |= XFERTYPE_CMDTYP_ABORT;
+  }
+
+  return XFERTYPE_CMD (Cmd->CmdIdx) | Xfertype;
+}
+
+/**
+  Function to set up MMC data(timeout value,watermark level,
+  system address,block attributes etc.)
+
+  @param   Data Pointer to MMC data
+
+**/
+EFI_STATUS
+SdxcSetupData (
+  IN  struct SdData *Data
+  )
+{
+  struct SdxcRegs *Regs;
+  INT32 Timeout;
+  UINT32 WmlVal;
+
+  Regs = (VOID *)PcdGet64 (PcdSdxcBaseAddr);
+  Timeout = 0;
+  WmlVal = 0;
+
+  WmlVal = Data->Blocksize/4;
+
+  if (Data->Flags & MMC_DATA_READ) {
+
+    if (WmlVal > WML_RD_MAX) {
+      WmlVal = WML_RD_MAX_VAL;
+    }
+
+    MmcAndThenOr ((UINTN)&Regs->Wml, ~WML_RD_MASK, WmlVal);
+
+  } else {
+    if (WmlVal > WML_WR_MAX) {
+      WmlVal = WML_WR_MAX_VAL;
+    }
+
+    if ((MmcRead ((UINTN)&Regs->Prsstat) & PRSSTATE_WPSPL) == 0) {
+      DEBUG ((DEBUG_ERROR, "The SD Card Is Locked. Can Not Write To A Locked Card.\n"));
+      return EFI_TIMEOUT;
+    }
+
+    MmcAndThenOr ((UINTN)&Regs->Wml, ~WML_WR_MASK, WmlVal << 16);
+  }
+
+  EFI_PHYSICAL_ADDRESS Addr = (EFI_PHYSICAL_ADDRESS)Data->Addr;
+  MmcWrite ((UINTN)&Regs->Dsaddr, Addr);
+
+  MmcWrite ((UINTN)&Regs->Blkattr, Data->Blocks << 16 | Data->Blocksize);
+
+  // Calculate The Timeout Period for Data Transactions
+  Timeout = GenericFls (mMmc->Clock/4);
+  Timeout -= 13;
+
+  if (Timeout > 14) {
+    Timeout = 14;
+  }
+
+  if (Timeout < 0) {
+    Timeout = 0;
+  }
+
+  MmcAndThenOr ((UINTN)&Regs->Sysctl, ~SYSCTL_TIMEOUT_MASK, Timeout << 16);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Function to peform reset of MMC command and data
+
+**/
+VOID
+ResetCmdFailedData (
+  IN  struct SdxcRegs *Regs,
+  IN  UINT8  Data
+  )
+{
+  INT32 Timeout;
+
+  Timeout = 10000;
+
+  // Reset CMD And DATA Portions On Error
+  MmcWrite ((UINTN)&Regs->Sysctl, MmcRead ((UINTN)&Regs->Sysctl) |
+           SYSCTL_RSTC);
+
+  while ((MmcRead((UINTN)&Regs->Sysctl) & SYSCTL_RSTC) && Timeout--);
+  if (Timeout <= 0) {
+    DEBUG((DEBUG_ERROR, "Failed to reset CMD Portion On Error\n"));
+    return;
+  }
+
+  Timeout = 10000;
+  if (Data) {
+    MmcWrite ((UINTN)&Regs->Sysctl,
+           MmcRead ((UINTN)&Regs->Sysctl) | SYSCTL_RSTD);
+    while ((MmcRead ((UINTN)&Regs->Sysctl) & SYSCTL_RSTD) && Timeout--);
+    if (Timeout <= 0) {
+      DEBUG ((DEBUG_ERROR, "Failed to reset DATA Portion On Error\n"));
+    }
+  }
+
+  MmcWrite ((UINTN)&Regs->Irqstat, 0xFFFFFFFF);
+}
+
+/**
+  Function to do MMC read/write transfer using DMA and checks
+  whether transfer is completed or not
+
+**/
+EFI_STATUS
+Transfer (
+  IN  VOID
+  )
+{
+  UINT32        Irqstat;
+  UINT32        Timeout;
+  struct SdxcRegs *Regs;
+
+  Regs = (VOID *)PcdGet64 (PcdSdxcBaseAddr);
+  Timeout = 10000000;
+  do {
+    Irqstat = MmcRead ((UINTN)&Regs->Irqstat);
+
+    if (Irqstat & IRQSTATE_DTOE) {
+      DumpMmcRegs ();
+      ResetCmdFailedData (Regs, 1);
+      return EFI_TIMEOUT;
+    }
+
+    if (Irqstat & DATA_ERR) {
+      ResetCmdFailedData (Regs, 1);
+      return EFI_DEVICE_ERROR;
+    }
+
+   MicroSecondDelay (10);
+
+  } while ((!(Irqstat & DATA_COMPLETE)) && Timeout--);
+
+  if (Timeout <= 0) {
+    DEBUG ((DEBUG_ERROR, "Timeout Waiting for DATA_COMPLETE to set\n"));
+    ResetCmdFailedData (Regs, 1);
+    return EFI_TIMEOUT;
+  }
+
+  MmcWrite ((UINTN)&Regs->Irqstat, 0xFFFFFFFF);
+  return EFI_SUCCESS;
+}
+
+/**
+  Function to set MMC host controller system control register
+
+  @param  Clock Clock value for setting the register
+
+**/
+VOID
+SetSysctl (
+  UINT32 Clock
+  )
+{
+  INT32 Div, PreDiv;
+  struct SdxcRegs *Regs;
+  INT32 SdhcClk;
+  UINT32 Clk;
+
+  Regs = (VOID *)PcdGet64(PcdSdxcBaseAddr);
+  SdhcClk = mMmc->SdhcClk;
+
+  if (Clock < mMmc->FMin) {
+    Clock = mMmc->FMin;
+  } else if (Clock > mMmc->FMax) {
+    Clock = mMmc->FMax;
+  }
+
+  mMmc->Clock = Clock;
+
+  if (SdhcClk / 16 > Clock) {
+    for (PreDiv = 2; PreDiv < 256; PreDiv *= 2)
+      if ((SdhcClk / PreDiv) <= (Clock * 16)) {
+        break;
+      }
+  } else {
+    PreDiv = 2;
+  }
+
+  for (Div = 1; Div <= 16; Div++)
+    if ((SdhcClk / (Div * PreDiv)) <= Clock) {
+      break;
+    }
+
+  PreDiv >>= mMmc->DdrMode ? DIV_2 : DIV_1;
+  Div -= 1;
+
+  Clk = (PreDiv << 8) | (Div << 4);
+
+  MmcAnd ((UINTN)&Regs->Sysctl, ~SYSCTL_CKEN);
+
+  MmcAndThenOr ((UINTN)&Regs->Sysctl, ~SYSCTL_CLOCK_MASK, Clk);
+
+  MicroSecondDelay (100);
+
+  Clk = SYSCTL_PEREN | SYSCTL_CKEN;
+
+  MmcOr ((UINTN)&Regs->Sysctl, Clk);
+}
+
+/**
+  Function to set MMC host controller bus width
+
+  @param  Mmc    Pointer to MMC data structure
+  @param  BWidth Bus width to be set
+
+**/
+VOID
+SdxcSetBusWidth (
+  IN  struct Mmc *Mmc,
+  IN  UINT32 BWidth
+  )
+{
+  Mmc->BusWidth = BWidth;
+
+  SetIos (Mmc->Clock, Mmc->BusWidth, 0);
+}
+
+/**
+  Function to Initialize MMC host controller
+
+  @param  Mmc Pointer to MMC data structure
+
+**/
+EFI_STATUS
+SdxcInit (
+  IN  struct Mmc *Mmc
+  )
+{
+  struct SdxcRegs *Regs;
+  INT32 Timeout;
+
+  Regs = (VOID *)PcdGet64(PcdSdxcBaseAddr);
+  Timeout = 1000;
+
+  // Reset The Entire Host Controller
+  MmcOr ((UINTN)&Regs->Sysctl, SYSCTL_RSTA);
+
+  // Wait Until The Controller Is Available
+  while ((MmcRead ((UINTN)&Regs->Sysctl) & SYSCTL_RSTA) && --Timeout)
+    MicroSecondDelay (1000);
+
+  if (Timeout <= 0) {
+    DEBUG ((DEBUG_ERROR, "Host controller failed to reset \n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Enable Cache Snooping
+  MmcWrite ((UINTN)&Regs->Scr, ENABLE_CACHE_SNOOPING);
+
+  MmcOr ((UINTN)&Regs->Sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
+
+  // Set The Initial Clock Speed
+  SetIos (MIN_CLK_FREQUENCY, Mmc->BusWidth, 0);
+
+  // Disable The BRR And BWR Bits In IRQSTAT
+  MmcAnd ((UINTN)&Regs->Irqstaten,
+          ~(IRQSTATE_EN_BRR | IRQSTATE_EN_BWR));
+
+  // Set Little Endian mode for data Buffer
+  MmcWrite ((UINTN)&Regs->Proctl, PRCTL_INIT);
+
+  // Set Timeout To The Maximum Value
+  MmcAndThenOr ((UINTN)&Regs->Sysctl,
+          ~SYSCTL_TIMEOUT_MASK, 14 << 16);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Function to reset MMC host controller
+
+  @param   Regs Pointer to MMC host Controller
+
+**/
+VOID
+SdxcReset (
+  IN struct SdxcRegs *Regs
+  )
+{
+  UINT64 Timeout;
+
+  Timeout = 100;
+
+  // Reset The Controller
+  MmcWrite ((UINTN)&Regs->Sysctl, SYSCTL_RSTA);
+
+  // Hardware Clears The Bit When It Is Done
+  while ((MmcRead ((UINTN)&Regs->Sysctl) & SYSCTL_RSTA) && --Timeout)
+    MicroSecondDelay (10);
+
+  if (!Timeout) {
+    DEBUG((DEBUG_ERROR, "MMC/SD: Reset Never Completed.\n"));
+  }
+}
diff --git a/Platform/NXP/Library/MmcLib/MmcLib.inf b/Platform/NXP/Library/MmcLib/MmcLib.inf
new file mode 100644
index 0000000..017c6ad
--- /dev/null
+++ b/Platform/NXP/Library/MmcLib/MmcLib.inf
@@ -0,0 +1,39 @@
+##@file
+#
+#  Copyright 2017 NXP
+#
+#  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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = MmcLib
+  FILE_GUID                      = c0f5dfa0-7599-11e0-9866-0002a5d5c61b
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = MmcLib
+
+[Sources.common]
+  MmcLib.c
+  MmcInterface.c
+
+[LibraryClasses]
+  BaseMemoryLib
+  BeIoLib
+  DmaLib
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/NXP/NxpQoriqLs.dec
+
+[FixedPcd]
+  gNxpQoriqLsTokenSpaceGuid.PcdSdxcBaseAddr
+  gNxpQoriqLsTokenSpaceGuid.PcdMmcBigEndian
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] Platform/NXP :Add Support of MMC Host Driver
  2017-12-01  4:18 [PATCH 0/3] Platform/NXP-Adding NXP MMC Host Driver Vabhav
  2017-12-01  4:18 ` [PATCH 1/3] Platform/NXP :Add Support for MMC Library Vabhav
@ 2017-12-01  4:18 ` Vabhav
  2017-12-01  4:18 ` [PATCH 3/3] Compilation:Modify dsc,fdf files Vabhav
  2 siblings, 0 replies; 4+ messages in thread
From: Vabhav @ 2017-12-01  4:18 UTC (permalink / raw)
  To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel

This patch adds support for MMC host driver
Mmc host driver will produce gEfiMmcHostProtocolGuid which
will be consumed by MmcDxe driver of EmbeddedPkg

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
 Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.c   | 418 +++++++++++++++++++++++++
 Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf |  42 +++
 2 files changed, 460 insertions(+)
 create mode 100644 Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.c
 create mode 100644 Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf

diff --git a/Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.c b/Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.c
new file mode 100644
index 0000000..81269bf
--- /dev/null
+++ b/Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.c
@@ -0,0 +1,418 @@
+/** @file
+
+  This file implement the MMC Host Protocol for the NXP SDHC controller.
+
+  Copyright 2017 NXP
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MmcLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/MmcHost.h>
+
+UINT8  LastCmd;
+struct SdCmd Cmd;
+
+EFI_GUID mMmcDevicePathGuid = EFI_CALLER_ID_GUID;
+
+/**
+  Function to call library function to detect card presence
+
+  @param  This Pointer to MMC host protocol structure
+
+**/
+BOOLEAN
+MmcIsCardPresent (
+  IN EFI_MMC_HOST_PROTOCOL     *This
+  )
+{
+  return DetectCardPresence ();
+}
+
+/**
+  Function to call library function to verify card is read only
+
+  @param  This Pointer to MMC host protocol structure
+
+**/
+BOOLEAN
+MmcIsReadOnly (
+  IN EFI_MMC_HOST_PROTOCOL     *This
+  )
+{
+  return IsCardReadOnly ();
+}
+
+/**
+  Function to create command reseponse depeping upon
+  input command parameter
+
+  @param  MmcCmd MMC Command
+
+**/
+STATIC UINT32
+CreateResponseType (
+   IN  UINT32 MmcCmd
+  )
+{
+
+  UINT32 RespType;
+
+  RespType = 0;
+
+  if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {
+    RespType = MMC_RSP_PRESENT;
+
+    if (MmcCmd & MMC_CMD_LONG_RESPONSE) {
+      RespType |= (MMC_RSP_136|MMC_RSP_CRC);
+    }
+    else if (!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) {
+      RespType |= (MMC_RSP_CRC|MMC_RSP_OPCODE);
+    }
+  }
+
+  if (MMC_GET_INDX(MmcCmd) == MMC_INDX(12)) {
+    RespType |= MMC_RSP_BUSY;
+  }
+
+  return RespType;
+}
+
+/**
+  Function to send MMC command
+
+  @param  This     Pointer to MMC host protocol structure
+  @param  MmcCmd   MMC Command
+  @param  Argument Argument if any
+
+**/
+EFI_STATUS
+MmcSendCommand (
+  IN EFI_MMC_HOST_PROTOCOL     *This,
+  IN MMC_CMD                    MmcCmd,
+  IN UINT32                     Argument
+  )
+{
+  EFI_STATUS  Status;
+
+  Cmd.CmdIdx = MMC_GET_INDX (MmcCmd);
+  Cmd.CmdArg = Argument;
+  Cmd.RespType = CreateResponseType (MmcCmd);
+
+  //Saved data in Cmd struct for commands that need a read/write.
+  //This is done because which setting Xfertype register we need
+  //information of block number and blocksize.
+  if ((Cmd.CmdIdx == MMC_INDX(6)) || (Cmd.CmdIdx == MMC_INDX(51)) ||
+       (Cmd.CmdIdx == MMC_INDX(17)) || (Cmd.CmdIdx == MMC_INDX(18)) ||
+       (Cmd.CmdIdx == MMC_INDX(24)) || (Cmd.CmdIdx == MMC_INDX(25))) {
+
+      if ((Cmd.CmdIdx == MMC_INDX(6)) && (LastCmd == MMC_INDX(55))) {
+        Status = SendCmd (&Cmd, NULL);
+      }
+      else {
+        Status = EFI_SUCCESS;
+      }
+   } else {
+      Status = SendCmd (&Cmd, NULL);
+   }
+
+  LastCmd = Cmd.CmdIdx;
+
+  return Status;
+}
+
+/**
+  Function to receive MMC command response
+
+  @param  This   Pointer to MMC host protocol structure
+  @param  Type   MMC Command response type
+  @param  Buffer Pointer to response Buffer
+
+**/
+EFI_STATUS
+MmcReceiveResponse (
+  IN EFI_MMC_HOST_PROTOCOL     *This,
+  IN MMC_RESPONSE_TYPE          Type,
+  IN UINT32*                    Buffer
+  )
+{
+  EFI_STATUS Status;
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Type == MMC_RESPONSE_TYPE_R2) {
+    Type |= MMC_RSP_136;
+  } else if (Type == MMC_RESPONSE_TYPE_R1b) {
+    Type |= MMC_RSP_BUSY;
+  }
+
+  DEBUG_MSG ("MMC_RESPONSE_TYPE 0x%x for cmd %d \n", Type, LastCmd);
+
+  // if Last sent command is one among 6, 51, 17, 18, 24 and 25, then
+  // set data to 1 else 0
+  if ((LastCmd == MMC_INDX(6)) || (LastCmd == MMC_INDX(51)) ||
+      (LastCmd == MMC_INDX(17)) || (LastCmd == MMC_INDX(18)) ||
+      (LastCmd == MMC_INDX(24)) || (LastCmd == MMC_INDX(25))) {
+    Status = RcvResp (Type, Buffer, 1);
+  } else {
+    Status = RcvResp (Type, Buffer, 0);
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to receive response for %d \n", LastCmd));
+    return Status;
+  }
+
+  return Status;
+}
+
+/**
+  Function to dump MMC data
+
+  @param  Buffer  Pointer to MMC data
+  @param  Length  Length of MMC data
+
+**/
+VOID
+DumpData (
+  IN UINT32*                   Buffer,
+  IN UINTN                     Length
+  )
+{
+#ifdef MMC_DEBUG_READ
+  UINT32 Temp;
+
+  DEBUG ((DEBUG_ERROR, "DATA IS (%d) :", Length));
+  for (Temp = 1; Temp <= Length; Temp++) {
+      DEBUG ((DEBUG_ERROR, "0x%x ", Buffer[Temp-1]));
+      if ((Temp != 0) && !(Temp % 8))
+          DEBUG ((DEBUG_ERROR, "--- %d\n", Temp-1));
+  }
+  DEBUG ((DEBUG_ERROR, "\n"));
+#endif
+}
+
+/**
+  Function to read MMC Data Block
+
+  @param  This    Pointer to MMC host protocol structure
+  @param  Lba
+  @param  Length  Length of MMC data
+  @param  Buffer  Pointer to MMC data
+
+**/
+EFI_STATUS
+MmcReadBlockData (
+  IN EFI_MMC_HOST_PROTOCOL     *This,
+  IN EFI_LBA                    Lba,
+  IN UINTN                      Length,
+  IN UINT32*                    Buffer
+  )
+{
+  EFI_STATUS RetVal;
+  EFI_TPL Tpl;
+  UINT8   Temp;
+
+  // Raise the TPL at the highest level to disable Interrupts.
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  //send Cmd structure here, library will send this command.
+  RetVal = ReadBlock (Lba, Length, Buffer, Cmd);
+
+  if (Cmd.CmdIdx == MMC_INDX(6)) {
+    for (Temp = 0; Temp < Length/8; Temp++) {
+    Buffer[Temp] = SwapBytes32(Buffer[Temp]);
+    }
+  }
+
+  if (RetVal == EFI_SUCCESS) {
+    DumpData(Buffer, Length);
+  }
+
+  // Restore Tpl
+  gBS->RestoreTPL (Tpl);
+
+  return RetVal;
+}
+
+/**
+  Function to write MMC Data Block
+
+  @param  This    Pointer to MMC host protocol structure
+  @param  Lba
+  @param  Length  Length of MMC data block to be written
+  @param  Buffer  Pointer to MMC data
+
+**/
+EFI_STATUS
+MmcWriteBlockData (
+  IN EFI_MMC_HOST_PROTOCOL     *This,
+  IN EFI_LBA                   Lba,
+  IN UINTN                     Length,
+  IN UINT32*                   Buffer
+  )
+{
+  EFI_STATUS RetVal;
+  EFI_TPL Tpl;
+
+  // Raise the TPL at the highest level to disable Interrupts.
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  //send Cmd structure here, library will send this command.
+  RetVal = WriteBlock (Lba, Length, Buffer, Cmd);
+
+  // Restore Tpl
+  gBS->RestoreTPL (Tpl);
+
+  return RetVal;
+}
+
+/**
+  Function to notify for different MMC states
+
+  @param  This  Pointer to MMC host protocol structure
+  @param  State MMC State
+
+**/
+EFI_STATUS
+MmcNotifyState (
+  IN  EFI_MMC_HOST_PROTOCOL     *This,
+  IN MMC_STATE                  State
+  )
+{
+  EFI_STATUS  Status;
+
+  switch (State) {
+  case MmcInvalidState:
+    ASSERT (0);
+    break;
+  case MmcHwInitializationState:
+    DEBUG ((DEBUG_ERROR, "MmcNotifyState(MmcHwInitializationState)\n"));
+
+    Status = MmcInitialize();
+    if (Status != EFI_SUCCESS) {
+      DEBUG ((DEBUG_ERROR,"Failed to init MMC\n"));
+      return Status;
+    }
+    break;
+  case MmcIdleState:
+  case MmcReadyState:
+  case MmcIdentificationState:
+  case MmcStandByState:
+  case MmcTransferState:
+  case MmcSendingDataState:
+  case MmcReceiveDataState:
+  case MmcProgrammingState:
+  case MmcDisconnectState:
+    break;
+  default:
+    ASSERT (0);
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Function to create device PATH for MMC node
+
+  @param  This       Pointer to MMC host protocol structure
+  @param  DevicePath Pointer to device path protocol structure
+
+**/
+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, &mMmcDevicePathGuid);
+
+  *DevicePath = NewDevicePathNode;
+  return EFI_SUCCESS;
+}
+
+/**
+  Function to set MMC speed
+
+  @param  This         Pointer to MMC host protocol structure
+  @param  BusClockFreq Bus clock frequency
+  @param  BusWidth     Bus width
+  @param  TimingMode   Timing mode
+
+**/
+EFI_STATUS
+MmcSetIos (
+  IN  EFI_MMC_HOST_PROTOCOL     *This,
+  IN  UINT32                    BusClockFreq,
+  IN  UINT32                    BusWidth,
+  IN  UINT32                    TimingMode
+  )
+{
+  SetIos (BusClockFreq, BusWidth, TimingMode);
+  return EFI_SUCCESS;
+}
+
+BOOLEAN
+MmcIsMultBlk (
+  IN  EFI_MMC_HOST_PROTOCOL     *This
+  )
+{
+  return TRUE;
+}
+
+EFI_MMC_HOST_PROTOCOL gMmcHost = {
+  MMC_HOST_PROTOCOL_REVISION,
+  MmcIsCardPresent,
+  MmcIsReadOnly,
+  MmcBuildDevicePath,
+  MmcNotifyState,
+  MmcSendCommand,
+  MmcReceiveResponse,
+  MmcReadBlockData,
+  MmcWriteBlockData,
+  MmcSetIos,
+  MmcIsMultBlk
+};
+
+/**
+  Function to install MMC Host Protocol gEfiMmcHostProtocolGuid
+**/
+EFI_STATUS
+MmcHostDxeEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+  EFI_HANDLE    Handle;
+
+  Handle = NULL;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Handle,
+                  &gEfiMmcHostProtocolGuid, &gMmcHost,
+                  NULL
+                  );
+
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "Failed to install gEfiMmcHostProtocolGuid\n"));
+  }
+
+  return Status;
+}
diff --git a/Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf b/Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf
new file mode 100644
index 0000000..6761f3e
--- /dev/null
+++ b/Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf
@@ -0,0 +1,42 @@
+#/**@file
+#
+#  Copyright 2017 NXP
+#
+#  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.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = MmcHostDxe
+  FILE_GUID                      = 7948a4ca-2f2e-41ca-90a2-d4420cecbbcf
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = MmcHostDxeEntryPoint
+
+[Sources.common]
+  MmcHostDxe.c
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/NXP/NxpQoriqLs.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  MmcLib
+  TimerLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiMmcHostProtocolGuid
+
+[Depex]
+  TRUE
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] Compilation:Modify dsc,fdf files
  2017-12-01  4:18 [PATCH 0/3] Platform/NXP-Adding NXP MMC Host Driver Vabhav
  2017-12-01  4:18 ` [PATCH 1/3] Platform/NXP :Add Support for MMC Library Vabhav
  2017-12-01  4:18 ` [PATCH 2/3] Platform/NXP :Add Support of MMC Host Driver Vabhav
@ 2017-12-01  4:18 ` Vabhav
  2 siblings, 0 replies; 4+ messages in thread
From: Vabhav @ 2017-12-01  4:18 UTC (permalink / raw)
  To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel

This patch adds support for compilation of NXP MMC
library and MMC Host Driver.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 11 +++++++++++
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf |  7 +++++++
 2 files changed, 18 insertions(+)

diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
index 19d4d30..134267f 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
@@ -39,6 +39,11 @@
   SocLib|edk2-platforms/Silicon/NXP/Chassis/LS1043aSocLib.inf
   RealTimeClockLib|edk2-platforms/Silicon/Maxim/Library/Ds1307RtcLib/Ds1307RtcLib.inf
 
+  #
+  # Mmc Lib
+  #
+  MmcLib|edk2-platforms/Platform/NXP/Library/MmcLib/MmcLib.inf
+
 [PcdsFixedAtBuild.common]
   gArmPlatformTokenSpaceGuid.PcdFirmwareVendor|"LS1043a RDB board"
 
@@ -74,4 +79,10 @@
   edk2-platforms/Platform/NXP/Drivers/WatchDog/WatchDogDxe.inf
   edk2-platforms/Platform/NXP/Drivers/I2cDxe/I2cDxe.inf
 
+  #
+  # MMC
+  #
+  EmbeddedPkg/Universal/MmcDxe/MmcDxe.inf
+  edk2-platforms/Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf
+
  ##
diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
index 9a8f242..729f7a5 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
@@ -145,6 +145,13 @@ READ_LOCK_STATUS   = TRUE
 !endif
 
   #
+  # MMC
+  #
+  INF edk2-platforms/Platform/NXP/Drivers/MmcHostDxe/MmcHostDxe.inf
+  INF EmbeddedPkg/Universal/MmcDxe/MmcDxe.inf
+
+  #
+  #
   # FAT filesystem + GPT/MBR partitioning
   #
   INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-12-01 16:16 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-01  4:18 [PATCH 0/3] Platform/NXP-Adding NXP MMC Host Driver Vabhav
2017-12-01  4:18 ` [PATCH 1/3] Platform/NXP :Add Support for MMC Library Vabhav
2017-12-01  4:18 ` [PATCH 2/3] Platform/NXP :Add Support of MMC Host Driver Vabhav
2017-12-01  4:18 ` [PATCH 3/3] Compilation:Modify dsc,fdf files Vabhav

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox