* [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