[edk2] [PATCH 2/3] Platform/NXP :Add Support of MMC Host Driver

Vabhav posted 3 patches 7 years ago
[edk2] [PATCH 2/3] Platform/NXP :Add Support of MMC Host Driver
Posted by Vabhav 7 years ago
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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel