From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from ma1-aaemail-dr-lapp02.apple.com (ma1-aaemail-dr-lapp02.apple.com [17.171.2.68]) by mx.groups.io with SMTP id smtpd.web10.11798.1619544675431801423 for ; Tue, 27 Apr 2021 10:31:16 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@apple.com header.s=20180706 header.b=W0KJZ5y8; spf=pass (domain: apple.com, ip: 17.171.2.68, mailfrom: afish@apple.com) Received: from pps.filterd (ma1-aaemail-dr-lapp02.apple.com [127.0.0.1]) by ma1-aaemail-dr-lapp02.apple.com (8.16.0.42/8.16.0.42) with SMTP id 13RHOAQs048095; Tue, 27 Apr 2021 10:31:14 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=apple.com; h=from : message-id : content-type : mime-version : subject : date : in-reply-to : cc : to : references; s=20180706; bh=cYaA+g0ZqX+UqPL1SoKmtbodaFtZiHoCKUtxJhcDAOU=; b=W0KJZ5y8tOPsg4z2wJxB2gFx4Am38biF15lsJ1quWWLA9FCXAewXLIARcxPshAA6BdQx 8MQp13V0s66Sv4ToV76sDiRcjbYAphOw1D6JlNYJNj7zIy5jN5ISOkOptzNRa3yc4g8l gKz1KbsJVl44FcM8STYxo7pxFBEGldNw4m17MXcIJk+id9sbCBRPbAN56Mr1k4TXZ7s3 x0G+bRKEqdPLTmuawtGYdCEatOXfVJjyBadPlgdMiWM6ibV+9H6Id5nbbcPdrq/brLL2 HsUDQdffYe4/Zsvsf93NCRr9MxKdXKwg/r+1vKH6EN9QkhC/2UZg9G91Q/vVRMJTslq+ pg== Received: from rn-mailsvcp-mta-lapp04.rno.apple.com (rn-mailsvcp-mta-lapp04.rno.apple.com [10.225.203.152]) by ma1-aaemail-dr-lapp02.apple.com with ESMTP id 384g0t5vub-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Tue, 27 Apr 2021 10:31:13 -0700 Received: from rn-mailsvcp-mmp-lapp03.rno.apple.com (rn-mailsvcp-mmp-lapp03.rno.apple.com [17.179.253.16]) by rn-mailsvcp-mta-lapp04.rno.apple.com (Oracle Communications Messaging Server 8.1.0.7.20201203 64bit (built Dec 3 2020)) with ESMTPS id <0QS8009RVGO0KYE0@rn-mailsvcp-mta-lapp04.rno.apple.com>; Tue, 27 Apr 2021 10:31:12 -0700 (PDT) Received: from process_milters-daemon.rn-mailsvcp-mmp-lapp03.rno.apple.com by rn-mailsvcp-mmp-lapp03.rno.apple.com (Oracle Communications Messaging Server 8.1.0.7.20201203 64bit (built Dec 3 2020)) id <0QS800U00GC98F00@rn-mailsvcp-mmp-lapp03.rno.apple.com>; Tue, 27 Apr 2021 10:31:12 -0700 (PDT) X-Va-A: X-Va-T-CD: e24a32ca7736d4df6ede859e10b3ed0b X-Va-E-CD: f4dd3ccc251b56941c826d2c70ead673 X-Va-R-CD: 6353a72eb7abb219a4e9576c7769c664 X-Va-CD: 0 X-Va-ID: 53cb8427-67af-4aa5-882d-9286a6afd55b X-V-A: X-V-T-CD: e24a32ca7736d4df6ede859e10b3ed0b X-V-E-CD: f4dd3ccc251b56941c826d2c70ead673 X-V-R-CD: 6353a72eb7abb219a4e9576c7769c664 X-V-CD: 0 X-V-ID: 38302ec1-d0e4-4232-8ca3-aef35b8cc0a6 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391,18.0.761 definitions=2021-04-27_10:2021-04-27,2021-04-27 signatures=0 Received: from [17.235.56.131] (unknown [17.235.56.131]) by rn-mailsvcp-mmp-lapp03.rno.apple.com (Oracle Communications Messaging Server 8.1.0.7.20201203 64bit (built Dec 3 2020)) with ESMTPSA id <0QS800UDJGNY7Q00@rn-mailsvcp-mmp-lapp03.rno.apple.com>; Tue, 27 Apr 2021 10:31:11 -0700 (PDT) From: "Andrew Fish" Message-id: <09F9E77A-9B6B-4D5F-A7FF-F49EAFA03FEB@apple.com> MIME-version: 1.0 (Mac OS X Mail 14.0 \(3654.20.0.2.1\)) Subject: Re: [edk2-devel] [PATCH V5 1/1] EmbeddedPkg: DwMmcHcDxe: Add support for Designware SDMMC driver Date: Tue, 27 Apr 2021 10:31:09 -0700 In-reply-to: Cc: Mike Kinney , "thloh85@gmail.com" , Leif Lindholm , Ard Biesheuvel To: edk2-devel-groups-io , tien.hock.loh@intel.com References: <20210322032439.9312-1-tien.hock.loh@intel.com> <20210322032439.9312-2-tien.hock.loh@intel.com> X-Mailer: Apple Mail (2.3654.20.0.2.1) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391,18.0.761 definitions=2021-04-27_10:2021-04-27,2021-04-27 signatures=0 Content-type: multipart/alternative; boundary="Apple-Mail=_F3B2F092-F088-4876-A0B5-24429692734D" --Apple-Mail=_F3B2F092-F088-4876-A0B5-24429692734D Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 One trick people have pulled in the past is to write a driver that produces= a =E2=80=9Cfake=E2=80=9D PCI IO Protocol. The =E2=80=9Cfake=E2=80=9D PCI I= O driver abstracts how the MMIO device shows up on the platform. This works= well if the MMIO device is really the same IP block as a PCI device. This = usually maps to the PCI BAR being the same thing as the magic MMIO range. T= he =E2=80=9Cfake=E2=80=9D PCI IO Protocol also abstracts platform specific = DMA rules from the generic driver.=20 Thanks, Andrew Fish > On Apr 27, 2021, at 2:08 AM, Loh, Tien Hock wr= ote: >=20 > Hi Mike >=20 > Yes, the existing Sd driver is very tightly coupled with PCI IO struct, = thus the reason for a new driver.=20 > I can attempt to refactor the Pci/SdMmcPciHcDxe and make PCI and Mmio a = library if that's the best route. I remember I tried briefly to refactor th= e code but it was quite a bit of work. >=20 > Let me give it another go, and get back to you.=20 >=20 > Thanks. >=20 >=20 >> -----Original Message----- >> From: Kinney, Michael D > >> Sent: Tuesday, April 27, 2021 1:54 AM >> To: Loh, Tien Hock >; devel@edk2.groups.io ; >> Kinney, Michael D > >> Cc: thloh85@gmail.com ; Leif Lindholm >; Ard Biesheuvel >> > >> Subject: RE: [PATCH V5 1/1] EmbeddedPkg: DwMmcHcDxe: Add support for >> Designware SDMMC driver >>=20 >> I see the MdeModulePkg has the SdMmcPciHcDxe module and it uses the >> EDK II SD MMC Override >> Protocol for host controller specific behaviors. Why was this driver a= nd an >> implementation >> of the EDK II SD MMC Override Protocol for the DesignWare MMC HC not >> used? >>=20 >> If there is a good reason that this exiting module and override extensi= ons can >> not be used, >> then please add that background and analysis to the BZ. >>=20 >> I see the existing module is PCI and I think this new one is for a MMIO= based >> device >> that requires different DMA services. Is this correct? I am wondering= if there >> is >> a way to implement t a single UEFI Driver sources that can support a de= vice >> that is >> with PCI or MMIO? >>=20 >> If a new driver is required, then here is some more specific code revie= w >> feedback: >>=20 >> 1) EmbeddedPkg/Include/Protocol/PlatformSwMmc.h >>=20 >> The enum EFI_SD_MMC_SLOT_TYPE can not being with EFI_ unless is part >> of the UEFI Spec. >> This file appears to be specific to DW, so perhaps it should be prefi= xed with >> DW_ instead >> to match the usage of DW_MMC_HC_SLOT_CAP. >>=20 >> The same comment applies to SD_MMC_CARD_TYPE. Should that be >> DW_SD_MMC_CARD_TYPE? >>=20 >>=20 >> 2) EmbeddedPkg/Drivers/DwMmcHcDxe >> a) There is a package .dec file in this directory. Packages can neve= r be >> nested. Any >> interfaces that need to be exported from the EmbeddedPkg should be >> declared in >> EmbeddedPkg.dec and DwMmcDcDxe.dec should be removed. >> b) DwMmcDcDxe.dec declared a token space GUID, but there are not PCDs= . >> I think this GUID >> can be removed. >> c) DwMmcDcDxe.inf. Remove reference to DwMmcDcDxe.dec. Also, is thi= s >> UEFI Driver really >> ARM specific? Why is there a dependency on ArmPkg/ArmPkg.dec? Ca= n >> that be removed? >> Can the dependency on ArmLib be removed? >>=20 >> 3) I see use of #ifdef in the DwMmcHci.h file. This is highly discoura= ged. Why >> are >> those there and why not use featured flags PCD instead? If it is rel= ated to >> the >> PCI vs MMIO register mapping, then perhaps the PCI related content ca= n >> be removed >> from this MMIO specific driver? >>=20 >> Best regards, >>=20 >> Mike >>=20 >>> -----Original Message----- >>> From: Loh, Tien Hock >>> Sent: Sunday, March 21, 2021 8:25 PM >>> To: devel@edk2.groups.io >>> Cc: thloh85@gmail.com; Loh, Tien Hock ; Kinne= y, >> Michael D ; Leif >>> Lindholm ; Ard Biesheuvel >> >>> Subject: [PATCH V5 1/1] EmbeddedPkg: DwMmcHcDxe: Add support for >> Designware SDMMC driver >>>=20 >>> From: "Tien Hock, Loh" >>>=20 >>> This adds support for Designware SDMMC driver. The SDMMC driver >> depends on >>> MdeModulePkg/Bus/Sd/, and produces >> EFI_SD_MMC_PASS_THRU_PROTOCOL. The >>> driver uses MMIO to read/write, and uses >>> gEdkiiNonDiscoverableDeviceProtocolGuid. Platform needs to register >> device >>> with gEdkiiNonDiscoverableDeviceProtocolGuid. >>>=20 >>> Signed-off-by: Loh Tien Hock >>> Cc: Leif Lindholm >>> Cc: Ard Biesheuvel >>> --- >>> EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec | 40 + >>> EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf | 70 + >>> EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h | 817 >> ++++++++++ >>> EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h | 985 >> ++++++++++++ >>> EmbeddedPkg/Include/Protocol/PlatformDwMmc.h | 79 + >>> EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c | 214 +++ >>> EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c | 1296 >> ++++++++++++++++ >>> EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.c | 1602 >> ++++++++++++++++++++ >>> EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c | 1042 >> +++++++++++++ >>> EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c | 1105 >> ++++++++++++++ >>> 10 files changed, 7250 insertions(+) >>>=20 >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec >>> new file mode 100644 >>> index 000000000000..cf85ccb1a030 >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec >>> @@ -0,0 +1,40 @@ >>> +#/** @file >>> +# Framework Module Development Environment Industry Standards >>> +# >>> +# This Package provides headers and libraries that conform to EFI/PI >> Industry standards. >>> +# Copyright (c) 2007, Intel Corporation. All rights reserved.
>>> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.
>>> +# Copyright (c) 2018, Linaro. All rights reserved.
>>> +# >>> +# This program and the accompanying materials are licensed and mad= e >> available under >>> +# the terms and conditions of the BSD License which accompanies th= is >> 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] >>> + DEC_SPECIFICATION =3D 0x00010019 >>> + PACKAGE_NAME =3D DwMmcHcDxePkg >>> + PACKAGE_GUID =3D e73097ce-1fe2-41a6-a930-3136bc6d= 23ef >>> + PACKAGE_VERSION =3D 0.1 >>> + >>> + >>>=20 >> +######################################################### >> ####################### >>> +# >>> +# Include Section - list of Include Paths that are provided by this p= ackage. >>> +# Comments are used for Keywords and Module Types. >>> +# >>> +# Supported Module Types: >>> +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER >> DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER >>> UEFI_APPLICATION >>> +# >>>=20 >> +######################################################### >> ####################### >>> + >>> +[Guids.common] >>> + gDwMmcHcDxeTokenSpaceGuid =3D { 0x576c132e, 0x7d51, 0x4abb, { >> 0xbc, 0x60, 0x13, 0x08, 0x04, 0x0e, 0x90, 0x92 }} >>> + >>> +[Protocols.common] >>> + gPlatformDwMmcProtocolGuid =3D { 0x1d6dfde5, 0x76a7, 0x4404, { 0= x85, >> 0x74, 0x7a, 0xdf, 0x1a, 0x8a, 0xa2, 0x0d }} >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf >>> new file mode 100644 >>> index 000000000000..4cd0960ef9c3 >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf >>> @@ -0,0 +1,70 @@ >>> +## @file >>> +# DwSdMmcHcDxe driver is used to manage those host controllers which >> comply with >>> +# Designware SD Host Controller. >>> +# >>> +# It will produce EFI_SD_MMC_PASS_THRU_PROTOCOL to allow sending >> SD/MMC/eMMC cmds >>> +# to specified devices from upper layer. >>> +# >>> +# Copyright (c) 2015, Intel Corporation. All rights reserved.
>>> +# Copyright (C) 2016, Marvell International Ltd. All rights reserved= .
>>> +# Copyright (c) 2018, Linaro Ltd. All rights reserved.
>>> +# >>> +# This program and the accompanying materials >>> +# are licensed and made available under the terms and conditions of = the >> BSD License >>> +# which accompanies this distribution. The full text of the license = may be >> found at >>> +# http://opensource.org/licenses/bsd-license.php >>> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" >> BASIS, >>> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER >> EXPRESS OR IMPLIED. >>> +# >>> +# >>> +## >>> + >>> +[Defines] >>> + INF_VERSION =3D 0x00010019 >>> + BASE_NAME =3D DwMmcHcDxe >>> + MODULE_UNI_FILE =3D DwMmcHcDxe.uni >>> + FILE_GUID =3D 9be4d260-208c-4efe-a524-0b5d3bf7= 7f9d >>> + MODULE_TYPE =3D UEFI_DRIVER >>> + VERSION_STRING =3D 1.0 >>> + ENTRY_POINT =3D InitializeDwMmcHcDxe >>> + >>> +[Sources] >>> + ComponentName.c >>> + DwMmcHcDxe.c >>> + DwMmcHcDxe.h >>> + DwMmcHci.c >>> + DwMmcHci.h >>> + EmmcDevice.c >>> + SdDevice.c >>> + >>> +[Packages] >>> + ArmPkg/ArmPkg.dec >>> + EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec >>> + EmbeddedPkg/EmbeddedPkg.dec >>> + MdeModulePkg/MdeModulePkg.dec >>> + MdePkg/MdePkg.dec >>> + >>> +[LibraryClasses] >>> + ArmLib >>> + BaseLib >>> + BaseMemoryLib >>> + CacheMaintenanceLib >>> + DebugLib >>> + DevicePathLib >>> + DmaLib >>> + MemoryAllocationLib >>> + TimerLib >>> + UefiBootServicesTableLib >>> + UefiDriverEntryPoint >>> + UefiLib >>> + UefiRuntimeServicesTableLib >>> + >>> +[Protocols] >>> + gEdkiiNonDiscoverableDeviceProtocolGuid >>> + gEfiDevicePathProtocolGuid ## TO_START >>> + gEfiPciIoProtocolGuid ## TO_START >>> + gEfiSdMmcPassThruProtocolGuid ## BY_START >>> + gPlatformDwMmcProtocolGuid >>> + >>> +[UserExtensions.TianoCore."ExtraFiles"] >>> + DwMmcHcDxeExtra.uni >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h >>> new file mode 100644 >>> index 000000000000..b783d9830325 >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h >>> @@ -0,0 +1,817 @@ >>> +/** @file >>> + >>> + Provides some data structure definitions used by the Designware >> SD/MMC >>> + host controller driver. >>> + >>> + Copyright (c) 2015, Intel Corporation. All rights reserved.
>>> + Copyright (C) 2018, Linaro Ltd. All rigths reserved.
>>> + >>> + This program and the accompanying materials are licensed and made >> available >>> + under the terms and conditions of the BSD License which accompanies >> this >>> + distribution. The full text of the license may be found at >>> + http://opensource.org/licenses/bsd-license.php >>> + >>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" >> BASIS, >>> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER >> EXPRESS OR IMPLIED. >>> + >>> +**/ >>> + >>> +#ifndef _DW_MMC_HC_DXE_H_ >>> +#define _DW_MMC_HC_DXE_H_ >>> + >>> +#include >>> + >>> +#include >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include "DwMmcHci.h" >>> + >>> +extern EFI_COMPONENT_NAME_PROTOCOL >> gDwMmcHcComponentName; >>> +extern EFI_COMPONENT_NAME2_PROTOCOL >> gDwMmcHcComponentName2; >>> +extern EFI_DRIVER_BINDING_PROTOCOL gDwMmcHcDriverBinding; >>> + >>> +#define DW_MMC_HC_PRIVATE_SIGNATURE SIGNATURE_32 ('d', 'w', 's', >> 'd') >>> + >>> +#define DW_MMC_HC_PRIVATE_FROM_THIS(a) \ >>> + CR(a, DW_MMC_HC_PRIVATE_DATA, PassThru, >> DW_MMC_HC_PRIVATE_SIGNATURE) >>> + >>> +// >>> +// Generic time out value, 1 microsecond as unit. >>> +// >>> +#define DW_MMC_HC_GENERIC_TIMEOUT (1 * 1000 * 1000) >>> + >>> +// >>> +// SD/MMC async transfer timer interval, set by experience. >>> +// The unit is 100us, takes 1ms as interval. >>> +// >>> +#define DW_MMC_HC_ASYNC_TIMER >> EFI_TIMER_PERIOD_MILLISECONDS(1) >>> +// >>> +// SD/MMC removable device enumeration timer interval, set by >> experience. >>> +// The unit is 100us, takes 100ms as interval. >>> +// >>> +#define DW_MMC_HC_ENUM_TIMER >> EFI_TIMER_PERIOD_MILLISECONDS(100) >>> + >>> +typedef struct { >>> + BOOLEAN Enable; >>> + EFI_SD_MMC_SLOT_TYPE SlotType; >>> + BOOLEAN MediaPresent; >>> + BOOLEAN Initialized; >>> + SD_MMC_CARD_TYPE CardType; >>> +} DW_MMC_HC_SLOT; >>> + >>> +typedef struct { >>> + UINTN Signature; >>> + >>> + EFI_HANDLE ControllerHandle; >>> + >>> + // Mmio base address >>> + UINTN DevBase; >>> + >>> + EFI_SD_MMC_PASS_THRU_PROTOCOL PassThru; >>> + >>> + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; >>> + // >>> + // The field is used to record the previous slot in GetNextSlot(). >>> + // >>> + UINT8 PreviousSlot; >>> + // >>> + // For Non-blocking operation. >>> + // >>> + EFI_EVENT TimerEvent; >>> + // >>> + // For Sd removable device enumeration. >>> + // >>> + EFI_EVENT ConnectEvent; >>> + LIST_ENTRY Queue; >>> + >>> + DW_MMC_HC_SLOT Slot[DW_MMC_HC_MAX_SLOT]; >>> + DW_MMC_HC_SLOT_CAP >> Capability[DW_MMC_HC_MAX_SLOT]; >>> + UINT64 MaxCurrent[DW_MMC_HC_MAX_SLOT]; >>> + >>> + UINT32 ControllerVersion; >>> +} DW_MMC_HC_PRIVATE_DATA; >>> + >>> +#define DW_MMC_HC_TRB_SIG SIGNATURE_32 ('D', 'T', 'R', 'B= ') >>> + >>> +// >>> +// TRB (Transfer Request Block) contains information for the cmd requ= est. >>> +// >>> +typedef struct { >>> + UINT32 Signature; >>> + LIST_ENTRY TrbList; >>> + >>> + UINT8 Slot; >>> + UINT16 BlockSize; >>> + >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; >>> + VOID *Data; >>> + UINT32 DataLen; >>> + BOOLEAN Read; >>> + EFI_PHYSICAL_ADDRESS DataPhy; >>> + VOID *DataMap; >>> + DW_MMC_HC_TRANSFER_MODE Mode; >>> + >>> + EFI_EVENT Event; >>> + BOOLEAN Started; >>> + UINT64 Timeout; >>> + >>> + DW_MMC_HC_DMA_DESC_LINE *DmaDesc; >>> + EFI_PHYSICAL_ADDRESS DmaDescPhy; >>> + UINT32 DmaDescPages; >>> + VOID *DmaMap; >>> + >>> + BOOLEAN UseFifo; >>> + BOOLEAN UseBE; // Big-= endian >>> + >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> +} DW_MMC_HC_TRB; >>> + >>> +#define DW_MMC_HC_TRB_FROM_THIS(a) \ >>> + CR(a, DW_MMC_HC_TRB, TrbList, DW_MMC_HC_TRB_SIG) >>> + >>> +// >>> +// Task for Non-blocking mode. >>> +// >>> +typedef struct { >>> + UINT32 Signature; >>> + LIST_ENTRY Link; >>> + >>> + UINT8 Slot; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; >>> + BOOLEAN IsStart; >>> + EFI_EVENT Event; >>> + UINT64 RetryTimes; >>> + BOOLEAN InfiniteWait; >>> + VOID *Map; >>> + VOID *MapAddress; >>> +} DW_MMC_HC_QUEUE; >>> + >>> +// >>> +// Prototypes >>> +// >>> +/** >>> + Execute card identification procedure. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + >>> + @retval EFI_SUCCESS The card is identified correctly. >>> + @retval Others The card can't be identified. >>> + >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(*DWMMC_CARD_TYPE_DETECT_ROUTINE) ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private >>> + ); >>> + >>> +/** >>> + Sends SD command to an SD card that is attached to the SD controlle= r. >>> + >>> + The PassThru() function sends the SD command specified by Packet to >> the SD >>> + card specified by Slot. >>> + >>> + If Packet is successfully sent to the SD card, then EFI_SUCCESS is >> returned. >>> + >>> + If a device error occurs while sending the Packet, then >> EFI_DEVICE_ERROR is >>> + returned. >>> + >>> + If Slot is not in a valid range for the SD controller, then >>> + EFI_INVALID_PARAMETER is returned. >>> + >>> + If Packet defines a data command but both InDataBuffer and >> OutDataBuffer are >>> + NULL, EFI_INVALID_PARAMETER is returned. >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Slot The slot number of the SD card to sen= d the >>> + command to. >>> + @param[in,out] Packet A pointer to the SD command data stru= cture. >>> + @param[in] Event If Event is NULL, blocking I/O is per= formed. If >>> + Event is not NULL, then nonblocking I= /O is >>> + performed, and Event will be signaled= when the >>> + Packet completes. >>> + >>> + @retval EFI_SUCCESS The SD Command Packet was sent by the >> host. >>> + @retval EFI_DEVICE_ERROR A device error occurred while attempt= ing >> to send >>> + the SD command Packet. >>> + @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the >> Packet is >>> + invalid. >>> + @retval EFI_INVALID_PARAMETER Packet defines a data command but >> both >>> + InDataBuffer and OutDataBuffer are NU= LL. >>> + @retval EFI_NO_MEDIA SD Device not present in the Slot. >>> + @retval EFI_UNSUPPORTED The command described by the SD >> Command Packet >>> + is not supported by the host controll= er. >>> + @retval EFI_BAD_BUFFER_SIZE The InTransferLength or >> OutTransferLength >>> + exceeds the limit supported by SD car= d ( i.e. if >>> + the number of bytes exceed the Last L= BA). >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruPassThru ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN UINT8 Slot, >>> + IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, >>> + IN EFI_EVENT Event OPTIONAL >>> + ); >>> + >>> +/** >>> + Used to retrieve next slot numbers supported by the SD controller. = The >>> + function returns information about all available slots (populated o= r >>> + not-populated). >>> + >>> + The GetNextSlot() function retrieves the next slot number on an SD >> controller. >>> + If on input Slot is 0xFF, then the slot number of the first slot on= the SD >>> + controller is returned. >>> + >>> + If Slot is a slot number that was returned on a previous call to >>> + GetNextSlot(), then the slot number of the next slot on the SD cont= roller >> is >>> + returned. >>> + >>> + If Slot is not 0xFF and Slot was not returned on a previous call to >>> + GetNextSlot(), EFI_INVALID_PARAMETER is returned. >>> + >>> + If Slot is the slot number of the last slot on the SD controller, t= hen >>> + EFI_NOT_FOUND is returned. >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in,out] Slot On input, a pointer to a slot number = on the SD >>> + controller. >>> + On output, a pointer to the next slot= number on >>> + the SD controller. >>> + An input value of 0xFF retrieves the = first slot >>> + number on the SD controller. >>> + >>> + @retval EFI_SUCCESS The next slot number on the SD contro= ller >> was >>> + returned in Slot. >>> + @retval EFI_NOT_FOUND There are no more slots on this SD >> controller. >>> + @retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not >> returned on a >>> + previous call to GetNextSlot(). >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruGetNextSlot ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN OUT UINT8 *Slot >>> + ); >>> + >>> +/** >>> + Used to allocate and build a device path node for an SD card on the= SD >>> + controller. >>> + >>> + The BuildDevicePath() function allocates and builds a single device= node >>> + for the SD >>> + card specified by Slot. >>> + >>> + If the SD card specified by Slot is not present on the SD controlle= r, then >>> + EFI_NOT_FOUND is returned. >>> + >>> + If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. >>> + >>> + If there are not enough resources to allocate the device path node,= then >>> + EFI_OUT_OF_RESOURCES is returned. >>> + >>> + Otherwise, DevicePath is allocated with the boot service AllocatePo= ol(), >> the >>> + contents of DevicePath are initialized to describe the SD card spec= ified by >>> + Slot, and EFI_SUCCESS is returned. >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Slot Specifies the slot number of the SD c= ard for >>> + which a device path node is to be all= ocated and >>> + built. >>> + @param[in,out] DevicePath A pointer to a single device path nod= e that >>> + describes the SD card specified by Sl= ot. This >>> + function is responsible for allocatin= g the >>> + buffer DevicePath with the boot servi= ce >>> + AllocatePool(). It is the caller's re= sponsibi- >>> + lity to free DevicePath when the call= er is >>> + finished with DevicePath. >>> + >>> + @retval EFI_SUCCESS The device path node that describes t= he SD >> card >>> + specified by Slot was allocated and r= eturned in >>> + DevicePath. >>> + @retval EFI_NOT_FOUND The SD card specified by Slot does no= t >> exist on >>> + the SD controller. >>> + @retval EFI_INVALID_PARAMETER DevicePath is NULL. >>> + @retval EFI_OUT_OF_RESOURCES There are not enough resources to >> allocate >>> + DevicePath. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruBuildDevicePath ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN UINT8 Slot, >>> + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath >>> + ); >>> + >>> +/** >>> + This function retrieves an SD card slot number based on the input d= evice >> path. >>> + >>> + The GetSlotNumber() function retrieves slot number for the SD card >> specified >>> + by the DevicePath node. If DevicePath is NULL, >> EFI_INVALID_PARAMETER is >>> + returned. >>> + >>> + If DevicePath is not a device path node type that the SD Pass Thru = driver >>> + supports, EFI_UNSUPPORTED is returned. >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] DevicePath A pointer to the device path node tha= t >> describes >>> + a SD card on the SD controller. >>> + @param[out] Slot On return, points to the slot number = of an SD >>> + card on the SD controller. >>> + >>> + @retval EFI_SUCCESS SD card slot number is returned in Sl= ot. >>> + @retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL. >>> + @retval EFI_UNSUPPORTED DevicePath is not a device path node >> type that >>> + the SD Pass Thru driver supports. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruGetSlotNumber ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, >>> + OUT UINT8 *Slot >>> + ); >>> + >>> +/** >>> + Resets an SD card that is connected to the SD controller. >>> + >>> + The ResetDevice() function resets the SD card specified by Slot. >>> + >>> + If this SD controller does not support a device reset operation, >>> + EFI_UNSUPPORTED is returned. >>> + >>> + If Slot is not in a valid slot number for this SD controller, >>> + EFI_INVALID_PARAMETER is returned. >>> + >>> + If the device reset operation is completed, EFI_SUCCESS is returned= . >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Slot Specifies the slot number of the SD c= ard to be >>> + reset. >>> + >>> + @retval EFI_SUCCESS The SD card specified by Slot was res= et. >>> + @retval EFI_UNSUPPORTED The SD controller does not support a >> device >>> + reset operation. >>> + @retval EFI_INVALID_PARAMETER Slot number is invalid. >>> + @retval EFI_NO_MEDIA SD Device not present in the Slot. >>> + @retval EFI_DEVICE_ERROR The reset command failed due to a dev= ice >> error >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruResetDevice ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN UINT8 Slot >>> + ); >>> + >>> +// >>> +// Driver model protocol interfaces >>> +// >>> +/** >>> + Tests to see if this driver supports a given controller. If a child= device is >>> + provided, it further tests to see if this driver supports creating = a handle >>> + for the specified child device. >>> + >>> + This function checks to see if the driver specified by This support= s the >>> + device specified by ControllerHandle. Drivers will typically use th= e device >>> + path attached to ControllerHandle and/or the services from the bus = I/O >>> + abstraction attached to ControllerHandle to determine if the driver >> supports >>> + ControllerHandle. This function may be called many times during >> platform >>> + initialization. In order to reduce boot times, the tests performed = by this >>> + function must be very small, and take as little time as possible to >> execute. >>> + This function must not change the state of any hardware devices, an= d >> this >>> + function must be aware that the device specified by ControllerHandl= e >> may >>> + already be managed by the same driver or a different driver. This >> function >>> + must match its calls to AllocatePages() with FreePages(), AllocateP= ool() >> with >>> + FreePool(), and OpenProtocol() with CloseProtocol(). >>> + Since ControllerHandle may have been previously started by the same >> driver, if >>> + a protocol is already in the opened state, then it must not be clos= ed with >>> + CloseProtocol(). This is required to guarantee the state of >> ControllerHandle >>> + is not modified by this function. >>> + >>> + @param[in] This A pointer to the >> EFI_DRIVER_BINDING_PROTOCOL >>> + instance. >>> + @param[in] ControllerHandle The handle of the controller to te= st. This >>> + handle must support a protocol int= erface that >>> + supplies an I/O abstraction to the= driver. >>> + @param[in] RemainingDevicePath A pointer to the remaining portion= of >> a >>> + device path. This parameter is ig= nored by >>> + device drivers, and is optional fo= r bus >>> + drivers. For bus drivers, if this = parameter >>> + is not NULL, then the bus driver m= ust deter- >>> + mine if the bus controller specifi= ed by >>> + ControllerHandle and the child con= troller >>> + specified by RemainingDevicePath a= re both >>> + supported by this bus driver. >>> + >>> + @retval EFI_SUCCESS The device specified by Controller= Handle >> and >>> + RemainingDevicePath is supported b= y the >>> + driver specified by This. >>> + @retval EFI_ALREADY_STARTED The device specified by >> ControllerHandle and >>> + RemainingDevicePath is already bei= ng managed >>> + by the driver specified by This. >>> + @retval EFI_ACCESS_DENIED The device specified by >> ControllerHandle and >>> + RemainingDevicePath is already bei= ng managed >>> + by a different driver or an applic= ation that >>> + requires exclusive access. >>> + Currently not implemented. >>> + @retval EFI_UNSUPPORTED The device specified by >> ControllerHandle and >>> + RemainingDevicePath is not support= ed by the >>> + driver specified by This. >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcDriverBindingSupported ( >>> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >>> + IN EFI_HANDLE Controller, >>> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >>> + ); >>> + >>> +/** >>> + Starts a device controller or a bus controller. >>> + >>> + The Start() function is designed to be invoked from the EFI boot se= rvice >>> + ConnectController(). >>> + As a result, much of the error checking on the parameters to Start(= ) has >> been >>> + moved into this common boot service. It is legal to call Start() fr= om other >>> + locations, >>> + but the following calling restrictions must be followed or the syst= em >> behavior >>> + will not be deterministic. >>> + 1. ControllerHandle must be a valid EFI_HANDLE. >>> + 2. If RemainingDevicePath is not NULL, then it must be a pointer to= a >> natural- >>> + ly aligned EFI_DEVICE_PATH_PROTOCOL. >>> + 3. Prior to calling Start(), the Supported() function for the drive= r specified >>> + by This must have been called with the same calling parameters, = and >>> + Supported() must have returned EFI_SUCCESS. >>> + >>> + @param[in] This A pointer to the >> EFI_DRIVER_BINDING_PROTOCOL >>> + instance. >>> + @param[in] ControllerHandle The handle of the controller to st= art. >> This >>> + handle must support a protocol int= erface that >>> + supplies an I/O abstraction to the= driver. >>> + @param[in] RemainingDevicePath A pointer to the remaining portion= of >> a >>> + device path. This parameter is ig= nored by >>> + device drivers, and is optional fo= r bus dri- >>> + vers. For a bus driver, if this pa= rameter is >>> + NULL, then handles for all the chi= ldren of >>> + Controller are created by this dri= ver. >>> + If this parameter is not NULL and = the first >>> + Device Path Node is not the End of= Device >>> + Path Node, then only the handle fo= r the >>> + child device specified by the firs= t Device >>> + Path Node of RemainingDevicePath i= s created >>> + by this driver. >>> + If the first Device Path Node of >>> + RemainingDevicePath is the End of = Device Path >>> + Node, no child handle is created b= y this >>> + driver. >>> + >>> + @retval EFI_SUCCESS The device was started. >>> + @retval EFI_DEVICE_ERROR The device could not be started du= e to a >>> + device error. Currently not implem= ented. >>> + @retval EFI_OUT_OF_RESOURCES The request could not be >> completed due to a >>> + lack of resources. >>> + @retval Others The driver failded to start the de= vice. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcDriverBindingStart ( >>> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >>> + IN EFI_HANDLE Controller, >>> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >>> + ); >>> + >>> +/** >>> + Stops a device controller or a bus controller. >>> + >>> + The Stop() function is designed to be invoked from the EFI boot ser= vice >>> + DisconnectController(). >>> + As a result, much of the error checking on the parameters to Stop()= has >> been >>> + moved into this common boot service. It is legal to call Stop() fro= m other >>> + locations, but the following calling restrictions must be followed = or the >>> + system behavior will not be deterministic. >>> + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a >> previous >>> + call to this same driver's Start() function. >>> + 2. The first NumberOfChildren handles of ChildHandleBuffer must all= be a >> valid >>> + EFI_HANDLE. In addition, all of these handles must have been cre= ated >> in >>> + this driver's Start() function, and the Start() function must ha= ve called >>> + OpenProtocol() on ControllerHandle with an Attribute of >>> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. >>> + >>> + @param[in] This A pointer to the >> EFI_DRIVER_BINDING_PROTOCOL >>> + instance. >>> + @param[in] ControllerHandle A handle to the device being stopped. >> The handle >>> + must support a bus specific I/O proto= col for the >>> + driver to use to stop the device. >>> + @param[in] NumberOfChildren The number of child device handles in >>> + ChildHandleBuffer. >>> + @param[in] ChildHandleBuffer An array of child handles to be freed= . >> May be >>> + NULL if NumberOfChildren is 0. >>> + >>> + @retval EFI_SUCCESS The device was stopped. >>> + @retval EFI_DEVICE_ERROR The device could not be stopped due t= o a >> device >>> + error. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcDriverBindingStop ( >>> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >>> + IN EFI_HANDLE Controller, >>> + IN UINTN NumberOfChildren, >>> + IN EFI_HANDLE *ChildHandleBuffer >>> + ); >>> + >>> +// >>> +// EFI Component Name Functions >>> +// >>> +/** >>> + Retrieves a Unicode string that is the user readable name of the dr= iver. >>> + >>> + This function retrieves the user readable name of a driver in the f= orm of >> a >>> + Unicode string. If the driver specified by This has a user readable= name in >>> + the language specified by Language, then a pointer to the driver na= me is >>> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >>> + by This does not support the language specified by Language, >>> + then EFI_UNSUPPORTED is returned. >>> + >>> + @param This[in] A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >>> + EFI_COMPONENT_NAME_PROTOCOL instance. >>> + >>> + @param Language[in] A pointer to a Null-terminated ASCII = string >>> + array indicating the language. This i= s the >>> + language of the driver name that the = caller is >>> + requesting, and it must match one of = the >>> + languages specified in SupportedLangu= ages. The >>> + number of languages supported by a dr= iver is up >>> + to the driver writer. Language is spe= cified >>> + in RFC 4646 or ISO 639-2 language cod= e format. >>> + >>> + @param DriverName[out] A pointer to the Unicode string to re= turn. >>> + This Unicode string is the name of th= e >>> + driver specified by This in the langu= age >>> + specified by Language. >>> + >>> + @retval EFI_SUCCESS The Unicode string for the Driver spe= cified by >>> + This and the language specified by La= nguage was >>> + returned in DriverName. >>> + >>> + @retval EFI_INVALID_PARAMETER Language is NULL. >>> + >>> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >>> + >>> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >>> + the language specified by Language. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcComponentNameGetDriverName ( >>> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >>> + IN CHAR8 *Language, >>> + OUT CHAR16 **DriverName >>> + ); >>> + >>> +/** >>> + Retrieves a Unicode string that is the user readable name of the >> controller >>> + that is being managed by a driver. >>> + >>> + This function retrieves the user readable name of the controller sp= ecified >> by >>> + ControllerHandle and ChildHandle in the form of a Unicode string. I= f the >>> + driver specified by This has a user readable name in the language >> specified by >>> + Language, then a pointer to the controller name is returned in >> ControllerName, >>> + and EFI_SUCCESS is returned. If the driver specified by This is no= t >> currently >>> + managing the controller specified by ControllerHandle and ChildHand= le, >>> + then EFI_UNSUPPORTED is returned. If the driver specified by This = does >> not >>> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >>> + >>> + @param This[in] A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >>> + EFI_COMPONENT_NAME_PROTOCOL instance. >>> + >>> + @param ControllerHandle[in] The handle of a controller that the d= river >>> + specified by This is managing. This = handle >>> + specifies the controller whose name i= s to be >>> + returned. >>> + >>> + @param ChildHandle[in] The handle of the child controller to= retrieve >>> + the name of. This is an optional par= ameter that >>> + may be NULL. It will be NULL for dev= ice >>> + drivers. It will also be NULL for a = bus drivers >>> + that wish to retrieve the name of the= bus >>> + controller. It will not be NULL for = a bus >>> + driver that wishes to retrieve the na= me of a >>> + child controller. >>> + >>> + @param Language[in] A pointer to a Null-terminated ASCII = string >>> + array indicating the language. This = is the >>> + language of the driver name that the = caller is >>> + requesting, and it must match one of = the >>> + languages specified in SupportedLangu= ages. The >>> + number of languages supported by a dr= iver is up >>> + to the driver writer. Language is spe= cified in >>> + RFC 4646 or ISO 639-2 language code f= ormat. >>> + >>> + @param ControllerName[out] A pointer to the Unicode string to >> return. >>> + This Unicode string is the name of th= e >>> + controller specified by ControllerHan= dle and >>> + ChildHandle in the language specified= by >>> + Language from the point of view of th= e driver >>> + specified by This. >>> + >>> + @retval EFI_SUCCESS The Unicode string for the user reada= ble >> name in >>> + the language specified by Language fo= r the >>> + driver specified by This was returned= in >>> + DriverName. >>> + >>> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >>> + >>> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not= a >> valid >>> + EFI_HANDLE. >>> + >>> + @retval EFI_INVALID_PARAMETER Language is NULL. >>> + >>> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >>> + >>> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >>> + managing the controller specified by >>> + ControllerHandle and ChildHandle. >>> + >>> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >>> + the language specified by Language. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcComponentNameGetControllerName ( >>> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >>> + IN EFI_HANDLE ControllerHandle, >>> + IN EFI_HANDLE ChildHandle, OPTIONAL >>> + IN CHAR8 *Language, >>> + OUT CHAR16 **ControllerName >>> + ); >>> + >>> +/** >>> + Create a new TRB for the SD/MMC cmd request. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command >>> + to. >>> + @param[in] Packet A pointer to the SD command data structur= e. >>> + @param[in] Event If Event is NULL, blocking I/O is perform= ed. >>> + If Event is not NULL, then nonblocking I/= O is >>> + performed, and Event will be signaled whe= n the >>> + Packet completes. >>> + >>> + @return Created Trb or NULL. >>> + >>> +**/ >>> +DW_MMC_HC_TRB * >>> +DwMmcCreateTrb ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN UINT8 Slot, >>> + IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, >>> + IN EFI_EVENT Event >>> + ); >>> + >>> +/** >>> + Free the resource used by the TRB. >>> + >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> +**/ >>> +VOID >>> +DwMmcFreeTrb ( >>> + IN DW_MMC_HC_TRB *Trb >>> + ); >>> + >>> +/** >>> + Check if the env is ready for execute specified TRB. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The env is ready for TRB execution. >>> + @retval EFI_NOT_READY The env is not ready for TRB execution. >>> + @retval Others Some erros happen. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcCheckTrbEnv ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ); >>> + >>> +/** >>> + Wait for the env to be ready for execute specified TRB. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The env is ready for TRB execution. >>> + @retval EFI_TIMEOUT The env is not ready for TRB execution in= time. >>> + @retval Others Some erros happen. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcWaitTrbEnv ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ); >>> + >>> +/** >>> + Execute the specified TRB. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The TRB is sent to host controller succes= sfully. >>> + @retval Others Some erros happen when sending this reque= st to >> the >>> + host controller. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcExecTrb ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ); >>> + >>> +/** >>> + Check the TRB execution result. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The TRB is executed successfully. >>> + @retval EFI_NOT_READY The TRB is not completed for execution. >>> + @retval Others Some erros happen when executing this req= uest. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcCheckTrbResult ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ); >>> + >>> +/** >>> + Wait for the TRB execution result. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The TRB is executed successfully. >>> + @retval Others Some erros happen when executing this req= uest. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcWaitTrbResult ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ); >>> + >>> +/** >>> + Execute EMMC device identification procedure. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + >>> + @retval EFI_SUCCESS There is a EMMC card. >>> + @retval Others There is not a EMMC card. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcIdentification ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private >>> + ); >>> + >>> +/** >>> + Execute EMMC device identification procedure. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + >>> + @retval EFI_SUCCESS There is a EMMC card. >>> + @retval Others There is not a EMMC card. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardIdentification ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private >>> + ); >>> + >>> +#endif /* _DW_MMC_HC_DXE_H_ */ >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h >>> new file mode 100644 >>> index 000000000000..12ef58a37368 >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h >>> @@ -0,0 +1,985 @@ >>> +/** @file >>> + >>> + Provides some data structure definitions used by the SD/MMC host >> controller >>> + driver. >>> + >>> + Copyright (c) 2015, Intel Corporation. All rights reserved.
>>> + Copyright (c) 2018, Linaro Ltd. All rights reserved.
>>> + >>> + This program and the accompanying materials are licensed and made >> available >>> + under the terms and conditions of the BSD License which accompanies >> this >>> + distribution. The full text of the license may be found at >>> + http://opensource.org/licenses/bsd-license.php >>> + >>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" >> BASIS, >>> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER >> EXPRESS OR IMPLIED. >>> + >>> +**/ >>> + >>> +#ifndef _DW_MMC_HCI_H_ >>> +#define _DW_MMC_HCI_H_ >>> + >>> +#include >>> +#include >>> + >>> +#include >>> + >>> +// >>> +// SD Host Controller SlotInfo Register Offset >>> +// >>> +#define DW_MMC_HC_SLOT_OFFSET 0x40 >>> + >>> +#define DW_MMC_HC_MAX_SLOT 1 >>> + >>> +// >>> +// SD Host Controller MMIO Register Offset >>> +// >>> +#define DW_MMC_CTRL 0x000 >>> +#define DW_MMC_PWREN 0x004 >>> +#define DW_MMC_CLKDIV 0x008 >>> +#define DW_MMC_CLKSRC 0x00c >>> +#define DW_MMC_CLKENA 0x010 >>> +#define DW_MMC_TMOUT 0x014 >>> +#define DW_MMC_CTYPE 0x018 >>> +#define DW_MMC_BLKSIZ 0x01c >>> +#define DW_MMC_BYTCNT 0x020 >>> +#define DW_MMC_INTMASK 0x024 >>> +#define DW_MMC_CMDARG 0x028 >>> +#define DW_MMC_CMD 0x02c >>> +#define DW_MMC_RESP0 0x030 >>> +#define DW_MMC_RESP1 0x034 >>> +#define DW_MMC_RESP2 0x038 >>> +#define DW_MMC_RESP3 0x03c >>> +#define DW_MMC_RINTSTS 0x044 >>> +#define DW_MMC_STATUS 0x048 >>> +#define DW_MMC_FIFOTH 0x04c >>> +#define DW_MMC_GPIO 0x058 >>> +#define DW_MMC_DEBNCE 0x064 >>> +#define DW_MMC_USRID 0x068 >>> +#define DW_MMC_VERID 0x06c >>> +#define DW_MMC_HCON 0x070 >>> +#define DW_MMC_UHSREG 0x074 >>> +#define DW_MMC_BMOD 0x080 >>> +#define DW_MMC_DBADDR 0x088 >>> +#define DW_MMC_IDSTS 0x08c >>> +#define DW_MMC_IDINTEN 0x090 >>> +#define DW_MMC_DSCADDR 0x094 >>> +#define DW_MMC_BUFADDR 0x098 >>> +#define DW_MMC_CARDTHRCTL 0x100 >>> +#define DW_MMC_UHSREG_EXT 0x108 >>> +#define DW_MMC_ENABLE_SHIFT 0x110 >>> +#define DW_MMC_FIFO_START 0x200 >>> + >>> +#define GET_IDSTS_DMAC_FSM(x) (((x) >> 13) & 0xf) >>> +#define IDSTS_FSM_DMA_IDLE 0 >>> +#define IDSTS_FSM_DMA_SUSPEND 1 >>> +#define IDSTS_FSM_DESC_RD 2 >>> +#define IDSTS_FSM_DESC_CHK 3 >>> +#define IDSTS_FSM_DMA_RD_REQ_WAIT 4 >>> +#define IDSTS_FSM_DMA_WR_REQ_WAIT 5 >>> +#define IDSTS_FSM_DMA_RD 6 >>> +#define IDSTS_FSM_DMA_WR 7 >>> +#define IDSTS_FSM_DESC_CLOSE 8 >>> +#define IDSTS_FSM_MASK 0xf >>> + >>> +#define CMD_UPDATE_CLK 0x80202000 >>> +#define CMD_START_BIT (1 << 31) >>> + >>> +#define MMC_8BIT_MODE (1 << 16) >>> +#define MMC_4BIT_MODE (1 << 0) >>> +#define MMC_1BIT_MODE 0 >>> + >>> +#define DW_MMC_BLOCK_SIZE 512 >>> + >>> +#define CMD_INDEX_MASK 0x3F >>> +#define BIT_CMD_RESPONSE_EXPECT (1 << 6) >>> +#define BIT_CMD_LONG_RESPONSE (1 << 7) >>> +#define BIT_CMD_CHECK_RESPONSE_CRC (1 << 8) >>> +#define BIT_CMD_DATA_EXPECTED (1 << 9) >>> +#define BIT_CMD_READ (0 << 10) >>> +#define BIT_CMD_WRITE (1 << 10) >>> +#define BIT_CMD_BLOCK_TRANSFER (0 << 11) >>> +#define BIT_CMD_STREAM_TRANSFER (1 << 11) >>> +#define BIT_CMD_SEND_AUTO_STOP (1 << 12) >>> +#define BIT_CMD_WAIT_PRVDATA_COMPLETE (1 << 13) >>> +#define BIT_CMD_STOP_ABORT_CMD (1 << 14) >>> +#define BIT_CMD_SEND_INIT (1 << 15) >>> +#define BIT_CMD_UPDATE_CLOCK_ONLY (1 << 21) >>> +#define BIT_CMD_READ_CEATA_DEVICE (1 << 22) >>> +#define BIT_CMD_CCS_EXPECTED (1 << 23) >>> +#define BIT_CMD_ENABLE_BOOT (1 << 24) >>> +#define BIT_CMD_EXPECT_BOOT_ACK (1 << 25) >>> +#define BIT_CMD_DISABLE_BOOT (1 << 26) >>> +#define BIT_CMD_MANDATORY_BOOT (0 << 27) >>> +#define BIT_CMD_ALTERNATE_BOOT (1 << 27) >>> +#define BIT_CMD_VOLT_SWITCH (1 << 28) >>> +#define BIT_CMD_USE_HOLD_REG (1 << 29) >>> +#define BIT_CMD_START (1 << 31) >>> + >>> +#define CMD_INDEX(x) ((x) & CMD_INDEX_MASK= ) >>> + >>> +#define DW_MMC_INT_EBE (1 << 15) /* En= d-bit Err */ >>> +#define DW_MMC_INT_SBE (1 << 13) /* St= art-bit Err */ >>> +#define DW_MMC_INT_HLE (1 << 12) /* Ha= rdware-lock >> Err */ >>> +#define DW_MMC_INT_FRUN (1 << 11) /* FI= FO UN/OV >> RUN */ >>> +#define DW_MMC_INT_DRT (1 << 9) /* Da= ta timeout */ >>> +#define DW_MMC_INT_RTO (1 << 8) /* Re= sponse >> timeout */ >>> +#define DW_MMC_INT_DCRC (1 << 7) /* Da= ta CRC err */ >>> +#define DW_MMC_INT_RCRC (1 << 6) /* Re= sponse CRC >> err */ >>> +#define DW_MMC_INT_RXDR (1 << 5) /* Re= ceive FIFO >> data request */ >>> +#define DW_MMC_INT_TXDR (1 << 4) /* Tr= ansmit FIFO >> data request */ >>> +#define DW_MMC_INT_DTO (1 << 3) /* Da= ta trans over >> */ >>> +#define DW_MMC_INT_CMD_DONE (1 << 2) /* Co= mmand >> done */ >>> +#define DW_MMC_INT_RE (1 << 1) /* Re= sponse error */ >>> + >>> +#define DW_MMC_IDMAC_DES0_DIC (1 << 1) >>> +#define DW_MMC_IDMAC_DES0_LD (1 << 2) >>> +#define DW_MMC_IDMAC_DES0_FS (1 << 3) >>> +#define DW_MMC_IDMAC_DES0_CH (1 << 4) >>> +#define DW_MMC_IDMAC_DES0_ER (1 << 5) >>> +#define DW_MMC_IDMAC_DES0_CES (1 << 30) >>> +#define DW_MMC_IDMAC_DES0_OWN (1 << 31) >>> +#define DW_MMC_IDMAC_DES1_BS1(x) ((x) & 0x1fff) >>> +#define DW_MMC_IDMAC_DES2_BS2(x) (((x) & 0x1fff) << 13= ) >>> +#define DW_MMC_IDMAC_SWRESET (1 << 0) >>> +#define DW_MMC_IDMAC_FB (1 << 1) >>> +#define DW_MMC_IDMAC_ENABLE (1 << 7) >>> + >>> +#define DW_MMC_CTRL_RESET (1 << 0) >>> +#define DW_MMC_CTRL_FIFO_RESET (1 << 1) >>> +#define DW_MMC_CTRL_DMA_RESET (1 << 2) >>> +#define DW_MMC_CTRL_INT_EN (1 << 4) >>> +#define DW_MMC_CTRL_DMA_EN (1 << 5) >>> +#define DW_MMC_CTRL_IDMAC_EN (1 << 25) >>> +#define DW_MMC_CTRL_RESET_ALL (DW_MMC_CTRL_RESET | >> DW_MMC_CTRL_FIFO_RESET | DW_MMC_CTRL_DMA_RESET) >>> + >>> +#define DW_MMC_STS_DATA_BUSY (1 << 9) >>> +#define DW_MMC_STS_FIFO_COUNT(x) (((x) & 0x1fff) << 17= ) /* >> Number of filled locations in FIFO */ >>> +#define GET_STS_FIFO_COUNT(x) (((x) >> 17) & 0x1fff= ) >>> +#define DW_MMC_STS_FIFO_FULL(x) (((x) >> 3) & 1) >>> + >>> +#define DW_MMC_BMOD_SWR (1 << 0) /* S= oftware >> Reset */ >>> +#define DW_MMC_BMOD_FB (1 << 1) /* F= ix Burst */ >>> +#define DW_MMC_BMOD_DE (1 << 7) /* I= DMAC Enable >> */ >>> + >>> +#define DW_MMC_IDSTS_TI (1 << 0) /* T= ransmit >> Interrupt */ >>> +#define DW_MMC_IDSTS_RI (1 << 1) /* R= eceive Interrupt >> */ >>> + >>> +#define DW_MMC_FIFO_TWMARK(x) ((x) & 0xfff) >>> +#define DW_MMC_FIFO_RWMARK(x) (((x) & 0x1ff) << 16) >>> +#define DW_MMC_DMA_BURST_SIZE(x) (((x) & 0x7) << 28) >>> + >>> +#define DW_MMC_CARD_RD_THR(x) (((x) & 0xfff) << 16) >>> +#define DW_MMC_CARD_RD_THR_EN (1 << 0) >>> + >>> +#define UHS_DDR_MODE (1 << 16) >>> + >>> +#define GENCLK_DIV 7 >>> + >>> +#define DW_MMC_GPIO_CLK_DIV(x) (((x) & 0xf) << 8) >>> +#define DW_MMC_GPIO_USE_SAMPLE_DLY(x) (((x) & 1) << 13) >>> +#define DW_MMC_GPIO_CLK_ENABLE BIT16 >>> + >>> +#define UHSEXT_SAMPLE_PHASE(x) (((x) & 0x1f) << 16) >>> +#define UHSEXT_SAMPLE_DRVPHASE(x) (((x) & 0x1f) << 21) >>> +#define UHSEXT_SAMPLE_DLY(x) (((x) & 0x1f) << 26) >>> + >>> +#define DWMMC_DMA_BUF_SIZE (512 * 8) >>> +#define DWMMC_FIFO_THRESHOLD 16 >>> + >>> +#define DWMMC_INIT_CLOCK_FREQ 400 /* K= Hz */ >>> + >>> +// >>> +// The transfer modes supported by SD Host Controller >>> +// Simplified Spec 3.0 Table 1-2 >>> +// >>> +typedef enum { >>> + SdMmcNoData, >>> + SdMmcPioMode, >>> + SdMmcSdmaMode, >>> + SdMmcAdmaMode >>> +} DW_MMC_HC_TRANSFER_MODE; >>> + >>> +// >>> +// The maximum data length of each descriptor line >>> +// >>> +#define ADMA_MAX_DATA_PER_LINE 0x10000 >>> + >>> +typedef struct { >>> + UINT32 Des0; >>> + UINT32 Des1; >>> + UINT32 Des2; >>> + UINT32 Des3; >>> +} DW_MMC_HC_DMA_DESC_LINE; >>> + >>> +#define SD_MMC_SDMA_BOUNDARY 512 * 1024 >>> +#define SD_MMC_SDMA_ROUND_UP(x, n) (((x) + n) & ~(n - 1)) >>> + >>> +typedef struct { >>> + UINT8 FirstBar:3; // bit 0:2 >>> + UINT8 Reserved:1; // bit 3 >>> + UINT8 SlotNum:3; // bit 4:6 >>> + UINT8 Reserved1:1; // bit 7 >>> +} DW_MMC_HC_SLOT_INFO; >>> + >>> +/** >>> + Dump the content of SD/MMC host controller's Capability Register. >>> + >>> + @param[in] Slot The slot number of the SD card to send = the >> command to. >>> + @param[in] Capability The buffer to store the capability data= . >>> + >>> +**/ >>> +VOID >>> +DumpCapabilityReg ( >>> + IN UINT8 Slot, >>> + IN DW_MMC_HC_SLOT_CAP *Capability >>> + ); >>> + >>> +#if 0 >>> +/** >>> + Read SlotInfo register from SD/MMC host controller pci config space= . >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[out] FirstBar The buffer to store the first BAR value. >>> + @param[out] SlotNum The buffer to store the supported slot num= ber. >>> + >>> + @retval EFI_SUCCESS The operation succeeds. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcGetSlotInfo ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + OUT UINT8 *FirstBar, >>> + OUT UINT8 *SlotNum >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Read/Write specified SD/MMC host controller mmio register. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] BarIndex The BAR index of the standard PCI >> Configuration >>> + header to use as the base address for = the memory >>> + operation to perform. >>> + @param[in] Offset The offset within the selected BAR to = start the >>> + memory operation. >>> + @param[in] Read A boolean to indicate it's read or wri= te >> operation. >>> + @param[in] Count The width of the mmio register in byte= s. >>> + Must be 1, 2 , 4 or 8 bytes. >>> + @param[in, out] Data For read operations, the destination b= uffer to >> store >>> + the results. For write operations, the= source buffer >>> + to write data from. The caller is resp= onsible for >>> + having ownership of the data buffer an= d ensuring its >>> + size not less than Count bytes. >>> + >>> + @retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the Coun= t >> is not valid. >>> + @retval EFI_SUCCESS The read/write operation succeeds. >>> + @retval Others The read/write operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcRwMmio ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 BarIndex, >>> + IN UINT32 Offset, >>> + IN BOOLEAN Read, >>> + IN UINT8 Count, >>> + IN OUT VOID *Data >>> + ); >>> +#else >>> +/** >>> + Read/Write specified SD/MMC host controller mmio register. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Offset The offset within the selected BAR to = start the >>> + memory operation. >>> + @param[in] Read A boolean to indicate it's read or wri= te >> operation. >>> + @param[in] Count The width of the mmio register in byte= s. >>> + Must be 1, 2 , 4 or 8 bytes. >>> + @param[in, out] Data For read operations, the destination b= uffer to >> store >>> + the results. For write operations, the= source buffer >>> + to write data from. The caller is resp= onsible for >>> + having ownership of the data buffer an= d ensuring its >>> + size not less than Count bytes. >>> + >>> + @retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the Coun= t >> is not valid. >>> + @retval EFI_SUCCESS The read/write operation succeeds. >>> + @retval Others The read/write operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcRwMmio ( >>> + IN UINTN DevBase, >>> + IN UINT32 Offset, >>> + IN BOOLEAN Read, >>> + IN UINT8 Count, >>> + IN OUT VOID *Data >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Do OR operation with the value of the specified SD/MMC host control= ler >> mmio register. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] BarIndex The BAR index of the standard PCI >> Configuration >>> + header to use as the base address for = the memory >>> + operation to perform. >>> + @param[in] Offset The offset within the selected BAR to = start the >>> + memory operation. >>> + @param[in] Count The width of the mmio register in byte= s. >>> + Must be 1, 2 , 4 or 8 bytes. >>> + @param[in] OrData The pointer to the data used to do OR >> operation. >>> + The caller is responsible for having o= wnership of >>> + the data buffer and ensuring its size = not less than >>> + Count bytes. >>> + >>> + @retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the >> Count is not valid. >>> + @retval EFI_SUCCESS The OR operation succeeds. >>> + @retval Others The OR operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcOrMmio ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 BarIndex, >>> + IN UINT32 Offset, >>> + IN UINT8 Count, >>> + IN VOID *OrData >>> + ); >>> +#else >>> +/** >>> + Do OR operation with the value of the specified SD/MMC host control= ler >> mmio register. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] BarIndex The BAR index of the standard PCI >> Configuration >>> + header to use as the base address for = the memory >>> + operation to perform. >>> + @param[in] Offset The offset within the selected BAR to = start the >>> + memory operation. >>> + @param[in] Count The width of the mmio register in byte= s. >>> + Must be 1, 2 , 4 or 8 bytes. >>> + @param[in] OrData The pointer to the data used to do OR >> operation. >>> + The caller is responsible for having o= wnership of >>> + the data buffer and ensuring its size = not less than >>> + Count bytes. >>> + >>> + @retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the >> Count is not valid. >>> + @retval EFI_SUCCESS The OR operation succeeds. >>> + @retval Others The OR operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcOrMmio ( >>> + IN UINTN DevBase, >>> + IN UINT32 Offset, >>> + IN UINT8 Count, >>> + IN VOID *OrData >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Do AND operation with the value of the specified SD/MMC host >> controller mmio register. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] BarIndex The BAR index of the standard PCI >> Configuration >>> + header to use as the base address for = the memory >>> + operation to perform. >>> + @param[in] Offset The offset within the selected BAR to = start the >>> + memory operation. >>> + @param[in] Count The width of the mmio register in byte= s. >>> + Must be 1, 2 , 4 or 8 bytes. >>> + @param[in] AndData The pointer to the data used to do AND >> operation. >>> + The caller is responsible for having o= wnership of >>> + the data buffer and ensuring its size = not less than >>> + Count bytes. >>> + >>> + @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the >> Count is not valid. >>> + @retval EFI_SUCCESS The AND operation succeeds. >>> + @retval Others The AND operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcAndMmio ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 BarIndex, >>> + IN UINT32 Offset, >>> + IN UINT8 Count, >>> + IN VOID *AndData >>> + ); >>> +#else >>> +/** >>> + Do AND operation with the value of the specified SD/MMC host >> controller mmio register. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Offset The offset within the selected BAR to = start the >>> + memory operation. >>> + @param[in] Count The width of the mmio register in byte= s. >>> + Must be 1, 2 , 4 or 8 bytes. >>> + @param[in] AndData The pointer to the data used to do AND >> operation. >>> + The caller is responsible for having o= wnership of >>> + the data buffer and ensuring its size = not less than >>> + Count bytes. >>> + >>> + @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the >> Count is not valid. >>> + @retval EFI_SUCCESS The AND operation succeeds. >>> + @retval Others The AND operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcAndMmio ( >>> + IN UINTN DevBase, >>> + IN UINT32 Offset, >>> + IN UINT8 Count, >>> + IN VOID *AndData >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Wait for the value of the specified MMIO register set to the test v= alue. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] BarIndex The BAR index of the standard PCI >> Configuration >>> + header to use as the base address for the= memory >>> + operation to perform. >>> + @param[in] Offset The offset within the selected BAR to sta= rt the >>> + memory operation. >>> + @param[in] Count The width of the mmio register in bytes. >>> + Must be 1, 2, 4 or 8 bytes. >>> + @param[in] MaskValue The mask value of memory. >>> + @param[in] TestValue The test value of memory. >>> + @param[in] Timeout The time out value for wait memory set, u= ses 1 >>> + microsecond as a unit. >>> + >>> + @retval EFI_TIMEOUT The MMIO register hasn't expected value i= n >> timeout >>> + range. >>> + @retval EFI_SUCCESS The MMIO register has expected value. >>> + @retval Others The MMIO operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcWaitMmioSet ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 BarIndex, >>> + IN UINT32 Offset, >>> + IN UINT8 Count, >>> + IN UINT64 MaskValue, >>> + IN UINT64 TestValue, >>> + IN UINT64 Timeout >>> + ); >>> +#else >>> +/** >>> + Wait for the value of the specified MMIO register set to the test v= alue. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Offset The offset within the selected BAR to sta= rt the >>> + memory operation. >>> + @param[in] Count The width of the mmio register in bytes. >>> + Must be 1, 2, 4 or 8 bytes. >>> + @param[in] MaskValue The mask value of memory. >>> + @param[in] TestValue The test value of memory. >>> + @param[in] Timeout The time out value for wait memory set, u= ses 1 >>> + microsecond as a unit. >>> + >>> + @retval EFI_TIMEOUT The MMIO register hasn't expected value i= n >> timeout >>> + range. >>> + @retval EFI_SUCCESS The MMIO register has expected value. >>> + @retval Others The MMIO operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcWaitMmioSet ( >>> + IN UINTN DevBase, >>> + IN UINT32 Offset, >>> + IN UINT8 Count, >>> + IN UINT64 MaskValue, >>> + IN UINT64 TestValue, >>> + IN UINT64 Timeout >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Software reset the specified SD/MMC host controller. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + >>> + @retval EFI_SUCCESS The software reset executes successfully. >>> + @retval Others The software reset fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcReset ( >>> +fark >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#else >>> +/** >>> + Software reset the specified SD/MMC host controller. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + >>> + @retval EFI_SUCCESS The software reset executes successfully. >>> + @retval Others The software reset fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcReset ( >>> + IN UINTN DevBase, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Set all interrupt status bits in Normal and Error Interrupt Status = Enable >>> + register. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + >>> + @retval EFI_SUCCESS The operation executes successfully. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcEnableInterrupt ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot >>> + ); >>> +#else >>> +/** >>> + Set all interrupt status bits in Normal and Error Interrupt Status = Enable >>> + register. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + >>> + @retval EFI_SUCCESS The operation executes successfully. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcEnableInterrupt ( >>> + IN UINTN DevBase >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Get the capability data from the specified slot. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send = the >> command to. >>> + @param[out] Capability The buffer to store the capability data= . >>> + >>> + @retval EFI_SUCCESS The operation executes successfully. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcGetCapability ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN EFI_HANDLE Controller, >>> + IN UINT8 Slot, >>> + OUT DW_MMC_HC_SLOT_CAP *Capability >>> + ); >>> +#else >>> +/** >>> + Get the capability data from the specified slot. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send = the >> command to. >>> + @param[out] Capability The buffer to store the capability data= . >>> + >>> + @retval EFI_SUCCESS The operation executes successfully. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcGetCapability ( >>> + IN UINTN DevBase, >>> + IN EFI_HANDLE Controller, >>> + IN UINT8 Slot, >>> + OUT DW_MMC_HC_SLOT_CAP *Capability >>> + ); >>> +#endif >>> + >>> +#if 0 >>> +/** >>> + Get the maximum current capability data from the specified slot. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send = the >> command to. >>> + @param[out] MaxCurrent The buffer to store the maximum current >> capability data. >>> + >>> + @retval EFI_SUCCESS The operation executes successfully. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcGetMaxCurrent ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot, >>> + OUT UINT64 *MaxCurrent >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Detect whether there is a SD/MMC card attached at the specified >> SD/MMC host controller >>> + slot. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for det= ails. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + @param[out] MediaPresent The pointer to the media present boolean >> value. >>> + >>> + @retval EFI_SUCCESS There is no media change happened. >>> + @retval EFI_MEDIA_CHANGED There is media change happened. >>> + @retval Others The detection fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcCardDetect ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN EFI_HANDLE Controller, >>> + IN UINT8 Slot, >>> + OUT BOOLEAN *MediaPresent >>> + ); >>> +#else >>> +/** >>> + Detect whether there is a SD/MMC card attached at the specified >> SD/MMC host controller >>> + slot. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for det= ails. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + @param[out] MediaPresent The pointer to the media present boolean >> value. >>> + >>> + @retval EFI_SUCCESS There is no media change happened. >>> + @retval EFI_MEDIA_CHANGED There is media change happened. >>> + @retval Others The detection fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcCardDetect ( >>> + IN UINTN DevBase, >>> + IN EFI_HANDLE Controller, >>> + IN UINT8 Slot, >>> + OUT BOOLEAN *MediaPresent >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Stop SD/MMC card clock. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.2.2 for d= etails. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + >>> + @retval EFI_SUCCESS Succeed to stop SD/MMC clock. >>> + @retval Others Fail to stop SD/MMC clock. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcStopClock ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot >>> + ); >>> + >>> +/** >>> + SD/MMC card clock supply. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for d= etails. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + @param[in] ClockFreq The max clock frequency to be set. The un= it is >> KHz. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The clock is supplied successfully. >>> + @retval Others The clock isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcClockSupply ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot, >>> + IN UINT64 ClockFreq, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#else >>> +/** >>> + Stop SD/MMC card clock. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.2.2 for d= etails. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + >>> + @retval EFI_SUCCESS Succeed to stop SD/MMC clock. >>> + @retval Others Fail to stop SD/MMC clock. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcStopClock ( >>> + IN UINTN DevBase >>> + ); >>> + >>> +/** >>> + SD/MMC card clock supply. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for d= etails. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] ClockFreq The max clock frequency to be set. The un= it is >> KHz. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The clock is supplied successfully. >>> + @retval Others The clock isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcClockSupply ( >>> + IN UINTN DevBase, >>> + IN UINT64 ClockFreq, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#endif >>> + >>> +#if 0 >>> +/** >>> + SD/MMC bus power control. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for det= ails. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + @param[in] PowerCtrl The value setting to the power control re= gister. >>> + >>> + @retval TRUE There is a SD/MMC card attached. >>> + @retval FALSE There is no a SD/MMC card attached. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcPowerControl ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot, >>> + IN UINT8 PowerCtrl >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Set the SD/MMC bus width. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for det= ails. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + @param[in] BusWidth The bus width used by the SD/MMC device, = it >> must be 1, 4 or 8. >>> + >>> + @retval EFI_SUCCESS The bus width is set successfully. >>> + @retval Others The bus width isn't set successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcSetBusWidth ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot, >>> + IN BOOLEAN IsDdr, >>> + IN UINT16 BusWidth >>> + ); >>> +#else >>> +/** >>> + Set the SD/MMC bus width. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for det= ails. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] BusWidth The bus width used by the SD/MMC device, = it >> must be 1, 4 or 8. >>> + >>> + @retval EFI_SUCCESS The bus width is set successfully. >>> + @retval Others The bus width isn't set successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcSetBusWidth ( >>> + IN UINTN DevBase, >>> + IN BOOLEAN IsDdr, >>> + IN UINT16 BusWidth >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Supply SD/MMC card with lowest clock frequency at initialization. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The clock is supplied successfully. >>> + @retval Others The clock isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitClockFreq ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#else >>> +/** >>> + Supply SD/MMC card with lowest clock frequency at initialization. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The clock is supplied successfully. >>> + @retval Others The clock isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitClockFreq ( >>> + IN UINTN DevBase, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Supply SD/MMC card with maximum voltage at initialization. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for det= ails. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The voltage is supplied successfully. >>> + @retval Others The voltage isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitPowerVoltage ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#else >>> +/** >>> + Supply SD/MMC card with maximum voltage at initialization. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for det= ails. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The voltage is supplied successfully. >>> + @retval Others The voltage isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitPowerVoltage ( >>> + IN UINTN DevBase, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Initialize the Timeout Control register with most conservative valu= e at >> initialization. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 2.2.15 for = details. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + >>> + @retval EFI_SUCCESS The timeout control register is configure= d >> successfully. >>> + @retval Others The timeout control register isn't config= ured >> successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitTimeoutCtrl ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot >>> + ); >>> +#else >>> +/** >>> + Initialize the Timeout Control register with most conservative valu= e at >> initialization. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 2.2.15 for = details. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + >>> + @retval EFI_SUCCESS The timeout control register is configure= d >> successfully. >>> + @retval Others The timeout control register isn't config= ured >> successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitTimeoutCtrl ( >>> + IN UINTN DevBase >>> + ); >>> +#endif >>> + >>> +#ifdef DWMMC_PCI >>> +/** >>> + Initial SD/MMC host controller with lowest clock frequency, max pow= er >> and max timeout value >>> + at initialization. >>> + >>> + @param[in] PciIo The PCI IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command to. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The host controller is initialized succes= sfully. >>> + @retval Others The host controller isn't initialized suc= cessfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitHost ( >>> + IN EFI_PCI_IO_PROTOCOL *PciIo, >>> + IN UINT8 Slot, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#else >>> +/** >>> + Initial SD/MMC host controller with lowest clock frequency, max pow= er >> and >>> + max timeout value at initialization. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The host controller is initialized succes= sfully. >>> + @retval Others The host controller isn't initialized suc= cessfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitHost ( >>> + IN UINTN DevBase, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ); >>> +#endif >>> + >>> +#endif /* _DW_MMC_HCI_H_ */ >>> diff --git a/EmbeddedPkg/Include/Protocol/PlatformDwMmc.h >> b/EmbeddedPkg/Include/Protocol/PlatformDwMmc.h >>> new file mode 100644 >>> index 000000000000..acbc3e153dac >>> --- /dev/null >>> +++ b/EmbeddedPkg/Include/Protocol/PlatformDwMmc.h >>> @@ -0,0 +1,79 @@ >>> +/** @file >>> + >>> + Copyright (c) 2018, Linaro. All rights reserved. >>> + >>> + This program and the accompanying materials are licensed and made >> available >>> + under the terms and conditions of the BSD License which accompanies >> this >>> + distribution. The full text of the license may be found at >>> + http://opensource.org/licenses/bsd-license.php >>> + >>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" >> BASIS, >>> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER >> EXPRESS OR IMPLIED. >>> + >>> +**/ >>> + >>> +#ifndef __PLATFORM_DW_MMC_H__ >>> +#define __PLATFORM_DW_MMC_H__ >>> + >>> +typedef enum { >>> + RemovableSlot, >>> + EmbeddedSlot, >>> + SharedBusSlot, >>> + UnknownSlot >>> +} EFI_SD_MMC_SLOT_TYPE; >>> + >>> +typedef enum { >>> + UnknownCardType, >>> + SdCardType, >>> + SdioCardType, >>> + MmcCardType, >>> + EmmcCardType >>> +} SD_MMC_CARD_TYPE; >>> + >>> +typedef struct { >>> + UINT32 DefaultSpeed:1; // bit 0 >>> + UINT32 HighSpeed:1; // bit 1 >>> + UINT32 Sdr12:1; // bit 2 >>> + UINT32 Sdr25:1; // bit 3 >>> + UINT32 Sdr50:1; // bit 4 >>> + UINT32 Sdr104:1; // bit 5 >>> + UINT32 Ddr50:1; // bit 6 >>> + UINT32 SysBus64:1; // bit 7 >>> + UINT32 BusWidth:4; // bit 11:8 >>> + UINT32 SlotType:2; // bit 13:12 >>> + UINT32 CardType:3; // bit 16:14 >>> + UINT32 Voltage18:1; // bit 17 >>> + UINT32 Voltage30:1; // bit 18 >>> + UINT32 Voltage33:1; // bit 19 >>> + UINT32 BaseClkFreq; >>> + EFI_HANDLE Controller; >>> +} DW_MMC_HC_SLOT_CAP; >>> + >>> +// >>> +// Protocol interface structure >>> +// >>> +typedef struct _PLATFORM_DW_MMC_PROTOCOL >> PLATFORM_DW_MMC_PROTOCOL; >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *PLATFORM_DW_MMC_GET_CAPABILITY) ( >>> + IN EFI_HANDLE Controller, >>> + IN UINT8 Slot, >>> + OUT DW_MMC_HC_SLOT_CAP *Capability >>> + ); >>> + >>> +typedef >>> +BOOLEAN >>> +(EFIAPI *PLATFORM_DW_MMC_CARD_DETECT) ( >>> + IN EFI_HANDLE Controller, >>> + IN UINT8 Slot >>> + ); >>> + >>> +struct _PLATFORM_DW_MMC_PROTOCOL { >>> + PLATFORM_DW_MMC_GET_CAPABILITY GetCapability; >>> + PLATFORM_DW_MMC_CARD_DETECT CardDetect; >>> +}; >>> + >>> +extern EFI_GUID gPlatformDwMmcProtocolGuid; >>> + >>> +#endif /* __PLATFORM_DW_MMC_H__ */ >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c >>> new file mode 100644 >>> index 000000000000..1edade69d091 >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c >>> @@ -0,0 +1,214 @@ >>> +/** @file >>> + UEFI Component Name(2) protocol implementation for Designware >> SD/MMC host >>> + controller driver. >>> + >>> + Copyright (c) 2015, Intel Corporation. All rights reserved.
>>> + Copyright (c) 2018, Linaro Ltd. All rights reserved.
>>> + >>> + This program and the accompanying materials are licensed and made >> available >>> + under the terms and conditions of the BSD License which accompanies >> this >>> + distribution. The full text of the license may be found at >>> + http://opensource.org/licenses/bsd-license.php >>> + >>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" >> BASIS, >>> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER >> EXPRESS OR IMPLIED. >>> + >>> +**/ >>> + >>> +#include "DwMmcHcDxe.h" >>> + >>> +// >>> +// EFI Component Name Protocol >>> +// >>> +GLOBAL_REMOVE_IF_UNREFERENCED >> EFI_COMPONENT_NAME_PROTOCOL gDwMmcHcComponentName =3D { >>> + DwMmcHcComponentNameGetDriverName, >>> + DwMmcHcComponentNameGetControllerName, >>> + "eng" >>> +}; >>> + >>> +// >>> +// EFI Component Name 2 Protocol >>> +// >>> +GLOBAL_REMOVE_IF_UNREFERENCED >> EFI_COMPONENT_NAME2_PROTOCOL gDwMmcHcComponentName2 =3D { >>> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) >> DwMmcHcComponentNameGetDriverName, >>> + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) >> DwMmcHcComponentNameGetControllerName, >>> + "en" >>> +}; >>> + >>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> mDwMmcHcDriverNameTable[] =3D { >>> + { "eng;en", L"Designware Sd/Mmc Host Controller Driver" }, >>> + { NULL , NULL } >>> +}; >>> + >>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> mDwMmcHcControllerNameTable[] =3D { >>> + { "eng;en", L"Designware Sd/Mmc Host Controller" }, >>> + { NULL , NULL } >>> +}; >>> + >>> +/** >>> + Retrieves a Unicode string that is the user readable name of the dr= iver. >>> + >>> + This function retrieves the user readable name of a driver in the f= orm of >> a >>> + Unicode string. If the driver specified by This has a user readable= name in >>> + the language specified by Language, then a pointer to the driver na= me is >>> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >>> + by This does not support the language specified by Language, >>> + then EFI_UNSUPPORTED is returned. >>> + >>> + @param This[in] A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >>> + EFI_COMPONENT_NAME_PROTOCOL instance. >>> + >>> + @param Language[in] A pointer to a Null-terminated ASCII = string >>> + array indicating the language. This i= s the >>> + language of the driver name that the = caller is >>> + requesting, and it must match one of = the >>> + languages specified in SupportedLangu= ages. The >>> + number of languages supported by a dr= iver is up >>> + to the driver writer. Language is spe= cified >>> + in RFC 4646 or ISO 639-2 language cod= e format. >>> + >>> + @param DriverName[out] A pointer to the Unicode string to re= turn. >>> + This Unicode string is the name of th= e >>> + driver specified by This in the langu= age >>> + specified by Language. >>> + >>> + @retval EFI_SUCCESS The Unicode string for the Driver spe= cified by >>> + This and the language specified by La= nguage was >>> + returned in DriverName. >>> + >>> + @retval EFI_INVALID_PARAMETER Language is NULL. >>> + >>> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >>> + >>> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >>> + the language specified by Language. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcComponentNameGetDriverName ( >>> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >>> + IN CHAR8 *Language, >>> + OUT CHAR16 **DriverName >>> + ) >>> +{ >>> + return LookupUnicodeString2 ( >>> + Language, >>> + This->SupportedLanguages, >>> + mDwMmcHcDriverNameTable, >>> + DriverName, >>> + (BOOLEAN)(This =3D=3D &gDwMmcHcComponentName) >>> + ); >>> +} >>> + >>> +/** >>> + Retrieves a Unicode string that is the user readable name of the >> controller >>> + that is being managed by a driver. >>> + >>> + This function retrieves the user readable name of the controller sp= ecified >> by >>> + ControllerHandle and ChildHandle in the form of a Unicode string. I= f the >>> + driver specified by This has a user readable name in the language >> specified by >>> + Language, then a pointer to the controller name is returned in >> ControllerName, >>> + and EFI_SUCCESS is returned. If the driver specified by This is no= t >> currently >>> + managing the controller specified by ControllerHandle and ChildHand= le, >>> + then EFI_UNSUPPORTED is returned. If the driver specified by This = does >> not >>> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >>> + >>> + @param This[in] A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >>> + EFI_COMPONENT_NAME_PROTOCOL instance. >>> + >>> + @param ControllerHandle[in] The handle of a controller that the d= river >>> + specified by This is managing. This = handle >>> + specifies the controller whose name i= s to be >>> + returned. >>> + >>> + @param ChildHandle[in] The handle of the child controller to= retrieve >>> + the name of. This is an optional par= ameter that >>> + may be NULL. It will be NULL for dev= ice >>> + drivers. It will also be NULL for a = bus drivers >>> + that wish to retrieve the name of the= bus >>> + controller. It will not be NULL for = a bus >>> + driver that wishes to retrieve the na= me of a >>> + child controller. >>> + >>> + @param Language[in] A pointer to a Null-terminated ASCII = string >>> + array indicating the language. This = is the >>> + language of the driver name that the = caller is >>> + requesting, and it must match one of = the >>> + languages specified in SupportedLangu= ages. The >>> + number of languages supported by a dr= iver is up >>> + to the driver writer. Language is spe= cified in >>> + RFC 4646 or ISO 639-2 language code f= ormat. >>> + >>> + @param ControllerName[out] A pointer to the Unicode string to >> return. >>> + This Unicode string is the name of th= e >>> + controller specified by ControllerHan= dle and >>> + ChildHandle in the language specified= by >>> + Language from the point of view of th= e driver >>> + specified by This. >>> + >>> + @retval EFI_SUCCESS The Unicode string for the user reada= ble >> name in >>> + the language specified by Language fo= r the >>> + driver specified by This was returned= in >>> + DriverName. >>> + >>> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >>> + >>> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not= a >> valid >>> + EFI_HANDLE. >>> + >>> + @retval EFI_INVALID_PARAMETER Language is NULL. >>> + >>> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >>> + >>> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >>> + managing the controller specified by >>> + ControllerHandle and ChildHandle. >>> + >>> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >>> + the language specified by Language. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcComponentNameGetControllerName ( >>> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >>> + IN EFI_HANDLE ControllerHandle, >>> + IN EFI_HANDLE ChildHandle, OPTIONAL >>> + IN CHAR8 *Language, >>> + OUT CHAR16 **ControllerName >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + >>> + if (Language =3D=3D NULL || ControllerName =3D=3D NULL) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + // >>> + // This is a device driver, so ChildHandle must be NULL. >>> + // >>> + if (ChildHandle !=3D NULL) { >>> + return EFI_UNSUPPORTED; >>> + } >>> + >>> + // >>> + // Make sure this driver is currently managing ControllerHandle >>> + // >>> + Status =3D EfiTestManagedDevice ( >>> + ControllerHandle, >>> + gDwMmcHcDriverBinding.DriverBindingHandle, >>> + &gEfiPciIoProtocolGuid >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + return LookupUnicodeString2 ( >>> + Language, >>> + This->SupportedLanguages, >>> + mDwMmcHcControllerNameTable, >>> + ControllerName, >>> + (BOOLEAN)(This =3D=3D &gDwMmcHcComponentName) >>> + ); >>> +} >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c >>> new file mode 100644 >>> index 000000000000..aea12170d2cc >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c >>> @@ -0,0 +1,1296 @@ >>> +/** @file >>> + This driver is used to manage Designware SD/MMC host controller. >>> + >>> + It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer >> use. >>> + >>> + Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<= BR> >>> + Copyright (C) 2016 Marvell International Ltd. All rigths reserved.<= BR> >>> + Copyright (C) 2018, Linaro Ltd. All rigths reserved.
>>> + >>> + This program and the accompanying materials >>> + are licensed and made available under the terms and conditions of t= he >> 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 >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include >>> +#include >>> + >>> +#include "DwMmcHcDxe.h" >>> + >>> +// >>> +// Driver Global Variables >>> +// >>> +EFI_DRIVER_BINDING_PROTOCOL gDwMmcHcDriverBinding =3D { >>> + DwMmcHcDriverBindingSupported, >>> + DwMmcHcDriverBindingStart, >>> + DwMmcHcDriverBindingStop, >>> + 0x10, >>> + NULL, >>> + NULL >>> +}; >>> + >>> +// >>> +// Template for Designware SD/MMC host controller private data. >>> +// >>> +DW_MMC_HC_PRIVATE_DATA gDwMmcHcTemplate =3D { >>> + DW_MMC_HC_PRIVATE_SIGNATURE, // Signature >>> + NULL, // ControllerHandle >>> + 0x0, // Mmio base address >>> + { // PassThru >>> + sizeof (UINT32), >>> + DwMmcPassThruPassThru, >>> + DwMmcPassThruGetNextSlot, >>> + DwMmcPassThruBuildDevicePath, >>> + DwMmcPassThruGetSlotNumber, >>> + DwMmcPassThruResetDevice >>> + }, >>> + NULL, // PlatformDwMmc >>> + 0, // PreviousSlot >>> + NULL, // TimerEvent >>> + NULL, // ConnectEvent >>> + // Queue >>> + INITIALIZE_LIST_HEAD_VARIABLE (gDwMmcHcTemplate.Queue), >>> + { // Slot >>> + {0, UnknownSlot, 0, 0, 0} >>> + }, >>> + { // Capability >>> + {0} >>> + }, >>> + { // MaxCurrent >>> + 0 >>> + }, >>> + 0 // ControllerVersion >>> +}; >>> + >>> +SD_DEVICE_PATH mSdDpTemplate =3D { >>> + { >>> + MESSAGING_DEVICE_PATH, >>> + MSG_SD_DP, >>> + { >>> + (UINT8) (sizeof (SD_DEVICE_PATH)), >>> + (UINT8) ((sizeof (SD_DEVICE_PATH)) >> 8) >>> + } >>> + }, >>> + 0 >>> +}; >>> + >>> +EMMC_DEVICE_PATH mEmmcDpTemplate =3D { >>> + { >>> + MESSAGING_DEVICE_PATH, >>> + MSG_EMMC_DP, >>> + { >>> + (UINT8) (sizeof (EMMC_DEVICE_PATH)), >>> + (UINT8) ((sizeof (EMMC_DEVICE_PATH)) >> 8) >>> + } >>> + }, >>> + 0 >>> +}; >>> + >>> +// >>> +// Prioritized function list to detect card type. >>> +// User could add other card detection logic here. >>> +// >>> +DWMMC_CARD_TYPE_DETECT_ROUTINE >> mCardTypeDetectRoutineTable[] =3D { >>> + EmmcIdentification, >>> + SdCardIdentification, >>> + NULL >>> +}; >>> + >>> +/** >>> + The entry point for SD host controller driver, used to install this= driver on >> the ImageHandle. >>> + >>> + @param[in] ImageHandle The firmware allocated handle for this dr= iver >> image. >>> + @param[in] SystemTable Pointer to the EFI system table. >>> + >>> + @retval EFI_SUCCESS Driver loaded. >>> + @retval other Driver not loaded. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +InitializeDwMmcHcDxe ( >>> + IN EFI_HANDLE ImageHandle, >>> + IN EFI_SYSTEM_TABLE *SystemTable >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + >>> + Status =3D EfiLibInstallDriverBindingComponentName2 ( >>> + ImageHandle, >>> + SystemTable, >>> + &gDwMmcHcDriverBinding, >>> + ImageHandle, >>> + &gDwMmcHcComponentName, >>> + &gDwMmcHcComponentName2 >>> + ); >>> + ASSERT_EFI_ERROR (Status); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Call back function when the timer event is signaled. >>> + >>> + @param[in] Event The Event this notify function registered to. >>> + @param[in] Context Pointer to the context data registered to the >>> + Event. >>> + >>> +**/ >>> +VOID >>> +EFIAPI >>> +ProcessAsyncTaskList ( >>> + IN EFI_EVENT Event, >>> + IN VOID* Context >>> + ) >>> +{ >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + LIST_ENTRY *Link; >>> + DW_MMC_HC_TRB *Trb; >>> + EFI_STATUS Status; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; >>> + BOOLEAN InfiniteWait; >>> + EFI_EVENT TrbEvent; >>> + >>> + Private =3D (DW_MMC_HC_PRIVATE_DATA *)Context; >>> + >>> + // >>> + // Check if the first entry in the async I/O queue is done or not. >>> + // >>> + Status =3D EFI_SUCCESS; >>> + Trb =3D NULL; >>> + Link =3D GetFirstNode (&Private->Queue); >>> + if (!IsNull (&Private->Queue, Link)) { >>> + Trb =3D DW_MMC_HC_TRB_FROM_THIS (Link); >>> + if (!Private->Slot[Trb->Slot].MediaPresent) { >>> + Status =3D EFI_NO_MEDIA; >>> + goto Done; >>> + } >>> + if (!Trb->Started) { >>> + // >>> + // Check whether the cmd/data line is ready for transfer. >>> + // >>> + Status =3D DwMmcCheckTrbEnv (Private, Trb); >>> + if (!EFI_ERROR (Status)) { >>> + Trb->Started =3D TRUE; >>> + Status =3D DwMmcExecTrb (Private, Trb); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + } else { >>> + goto Done; >>> + } >>> + } >>> + Status =3D DwMmcCheckTrbResult (Private, Trb); >>> + } >>> + >>> +Done: >>> + if ((Trb !=3D NULL) && (Status =3D=3D EFI_NOT_READY)) { >>> + Packet =3D Trb->Packet; >>> + if (Packet->Timeout =3D=3D 0) { >>> + InfiniteWait =3D TRUE; >>> + } else { >>> + InfiniteWait =3D FALSE; >>> + } >>> + if ((!InfiniteWait) && (Trb->Timeout-- =3D=3D 0)) { >>> + RemoveEntryList (Link); >>> + Trb->Packet->TransactionStatus =3D EFI_TIMEOUT; >>> + TrbEvent =3D Trb->Event; >>> + DwMmcFreeTrb (Trb); >>> + DEBUG (( >>> + DEBUG_VERBOSE, >>> + "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", >>> + TrbEvent >>> + )); >>> + gBS->SignalEvent (TrbEvent); >>> + return; >>> + } >>> + } >>> + if ((Trb !=3D NULL) && (Status !=3D EFI_NOT_READY)) { >>> + RemoveEntryList (Link); >>> + Trb->Packet->TransactionStatus =3D Status; >>> + TrbEvent =3D Trb->Event; >>> + DwMmcFreeTrb (Trb); >>> + DEBUG (( >>> + DEBUG_VERBOSE, >>> + "ProcessAsyncTaskList(): Signal Event %p with %r\n", >>> + TrbEvent, >>> + Status >>> + )); >>> + gBS->SignalEvent (TrbEvent); >>> + } >>> + return; >>> +} >>> + >>> +/** >>> + Sd removable device enumeration callback function when the timer >> event is signaled. >>> + >>> + @param[in] Event The Event this notify function registered to. >>> + @param[in] Context Pointer to the context data registered to the >>> + Event. >>> + >>> +**/ >>> +VOID >>> +EFIAPI >>> +DwMmcHcEnumerateDevice ( >>> + IN EFI_EVENT Event, >>> + IN VOID* Context >>> + ) >>> +{ >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + EFI_STATUS Status; >>> + BOOLEAN MediaPresent; >>> + UINT32 RoutineNum; >>> + DWMMC_CARD_TYPE_DETECT_ROUTINE *Routine; >>> + UINTN Index; >>> + LIST_ENTRY *Link; >>> + LIST_ENTRY *NextLink; >>> + DW_MMC_HC_TRB *Trb; >>> + EFI_TPL OldTpl; >>> + >>> + Private =3D (DW_MMC_HC_PRIVATE_DATA *)Context; >>> + >>> + if ((Private->Slot[0].Enable) && >>> + (Private->Slot[0].SlotType =3D=3D RemovableSlot)) { >>> + Status =3D DwMmcHcCardDetect ( >>> + Private->DevBase, >>> + Private->ControllerHandle, >>> + 0, >>> + &MediaPresent >>> + ); >>> + if ((Status =3D=3D EFI_MEDIA_CHANGED) && !MediaPresent) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "DwMmcHcEnumerateDevice: device disconnected at %p\n", >>> + Private->DevBase >>> + )); >>> + Private->Slot[0].MediaPresent =3D FALSE; >>> + // >>> + // Signal all async task events at the slot with EFI_NO_MEDIA s= tatus. >>> + // >>> + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); >>> + for (Link =3D GetFirstNode (&Private->Queue); >>> + !IsNull (&Private->Queue, Link); >>> + Link =3D NextLink) { >>> + NextLink =3D GetNextNode (&Private->Queue, Link); >>> + Trb =3D DW_MMC_HC_TRB_FROM_THIS (Link); >>> + if (Trb->Slot =3D=3D 0) { >>> + RemoveEntryList (Link); >>> + Trb->Packet->TransactionStatus =3D EFI_NO_MEDIA; >>> + gBS->SignalEvent (Trb->Event); >>> + DwMmcFreeTrb (Trb); >>> + } >>> + } >>> + gBS->RestoreTPL (OldTpl); >>> + // >>> + // Notify the upper layer the connect state change through >>> + // ReinstallProtocolInterface. >>> + // >>> + gBS->ReinstallProtocolInterface ( >>> + Private->ControllerHandle, >>> + &gEfiSdMmcPassThruProtocolGuid, >>> + &Private->PassThru, >>> + &Private->PassThru >>> + ); >>> + } >>> + if ((Status =3D=3D EFI_MEDIA_CHANGED) && MediaPresent) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "DwMmcHcEnumerateDevice: device connected at %p\n", >>> + Private->DevBase >>> + )); >>> + // >>> + // Initialize slot and start identification process for the new >>> + // attached device >>> + // >>> + Status =3D DwMmcHcInitHost (Private->DevBase, Private->Capabili= ty[0]); >>> + if (EFI_ERROR (Status)) { >>> + return; >>> + } >>> + // >>> + // Reset the specified slot of the SD/MMC Pci Host Controller >>> + // >>> + Status =3D DwMmcHcReset (Private->DevBase, Private->Capability[= 0]); >>> + if (EFI_ERROR (Status)) { >>> + return; >>> + } >>> + >>> + Private->Slot[0].MediaPresent =3D TRUE; >>> + RoutineNum =3D sizeof (mCardTypeDetectRoutineTable) / >>> + sizeof (DWMMC_CARD_TYPE_DETECT_ROUTINE); >>> + for (Index =3D 0; Index < RoutineNum; Index++) { >>> + Routine =3D &mCardTypeDetectRoutineTable[Index]; >>> + if (*Routine !=3D NULL) { >>> + Status =3D (*Routine) (Private); >>> + if (!EFI_ERROR (Status)) { >>> + break; >>> + } >>> + } >>> + } >>> + // >>> + // This card doesn't get initialized correctly. >>> + // >>> + if (Index =3D=3D RoutineNum) { >>> + return; >>> + } >>> + >>> + // >>> + // Notify the upper layer the connect state change through >>> + // ReinstallProtocolInterface. >>> + // >>> + gBS->ReinstallProtocolInterface ( >>> + Private->ControllerHandle, >>> + &gEfiSdMmcPassThruProtocolGuid, >>> + &Private->PassThru, >>> + &Private->PassThru >>> + ); >>> + } >>> + } >>> + >>> + return; >>> +} >>> + >>> +/** >>> + Reset the specified SD/MMC host controller and enable all interrupt= s. >>> + >>> + @param[in] DevBase The Mmio Device Base Address. >>> + >>> + @retval EFI_SUCCESS The software reset executes successfully. >>> + @retval Others The software reset fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcReset ( >>> + IN UINTN DevBase, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT32 BlkSize; >>> + >>> + // >>> + // Enable all interrupt after reset all. >>> + // >>> + Status =3D DwMmcHcEnableInterrupt (DevBase); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "DwMmcHcReset: enable interrupts fail: >> %r\n", Status)); >>> + return Status; >>> + } >>> + Status =3D DwMmcHcInitTimeoutCtrl (DevBase); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + BlkSize =3D DW_MMC_BLOCK_SIZE; >>> + MmioWrite32 (DevBase + DW_MMC_BLKSIZ, BlkSize); >>> + >>> + Status =3D DwMmcHcInitClockFreq (DevBase, Capability); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + Status =3D DwMmcHcSetBusWidth (DevBase, FALSE, 1); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Tests to see if this driver supports a given controller. If a child= device >>> + is provided, it further tests to see if this driver supports creati= ng a >>> + handle for the specified child device. >>> + >>> + This function checks to see if the driver specified by This support= s the >>> + device specified by ControllerHandle. Drivers will typically use th= e device >>> + path attached to ControllerHandle and/or the services from the bus = I/O >>> + abstraction attached to ControllerHandle to determine if the driver >> supports >>> + ControllerHandle. This function may be called many times during >> platform >>> + initialization. In order to reduce boot times, the tests performed = by this >>> + function must be very small, and take as little time as possible to >> execute. >>> + This function must not change the state of any hardware devices, an= d >> this >>> + function must be aware that the device specified by ControllerHandl= e >> may >>> + already be managed by the same driver or a different driver. This >> function >>> + must match its calls to AllocatePages() with FreePages(), AllocateP= ool() >> with >>> + FreePool(), and OpenProtocol() with CloseProtocol(). Since >> ControllerHandle >>> + may have been previously started by the same driver, if a protocol = is >> already >>> + in the opened state, then it must not be closed with CloseProtocol(= ). This >> is >>> + required to guarantee the state of ControllerHandle is not modified= by >> this >>> + function. >>> + >>> + @param[in] This A pointer to the >> EFI_DRIVER_BINDING_PROTOCOL >>> + instance. >>> + @param[in] ControllerHandle The handle of the controller to te= st. This >>> + handle must support a protocol int= erface that >>> + supplies an I/O abstraction to the= driver. >>> + @param[in] RemainingDevicePath A pointer to the remaining portion= of >> a >>> + device path. This parameter is ig= nored by >>> + device drivers, and is optional fo= r bus >>> + drivers. For bus drivers, if this = parameter >>> + is not NULL, then the bus driver m= ust deter- >>> + mine if the bus controller specifi= ed by >>> + ControllerHandle and the child con= troller >>> + specified by RemainingDevicePath a= re both >>> + supported by this bus driver. >>> + >>> + @retval EFI_SUCCESS The device specified by Controller= Handle >> and >>> + RemainingDevicePath is supported b= y the >>> + driver specified by This. >>> + @retval EFI_ALREADY_STARTED The device specified by >> ControllerHandle and >>> + RemainingDevicePath is already bei= ng managed >>> + by the driver specified by This. >>> + @retval EFI_ACCESS_DENIED The device specified by >> ControllerHandle and >>> + RemainingDevicePath is already bei= ng managed >>> + by a different driver or an applic= ation that >>> + requires exclusive access. >>> + Currently not implemented. >>> + @retval EFI_UNSUPPORTED The device specified by >> ControllerHandle and >>> + RemainingDevicePath is not support= ed by the >>> + driver specified by This. >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcDriverBindingSupported ( >>> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >>> + IN EFI_HANDLE Controller, >>> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; >>> + NON_DISCOVERABLE_DEVICE *Dev; >>> + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; >>> + >>> + ParentDevicePath =3D NULL; >>> + >>> + Status =3D gBS->LocateProtocol ( >>> + &gPlatformDwMmcProtocolGuid, >>> + NULL, >>> + (VOID **) &PlatformDwMmc >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + Status =3D gBS->OpenProtocol ( >>> + Controller, >>> + &gEfiDevicePathProtocolGuid, >>> + (VOID *) &ParentDevicePath, >>> + This->DriverBindingHandle, >>> + Controller, >>> + EFI_OPEN_PROTOCOL_BY_DRIVER >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + // >>> + // EFI_ALREADY_STARTED is also an error. >>> + // >>> + return Status; >>> + } >>> + // >>> + // Close the protocol because we don't use it here. >>> + // >>> + gBS->CloseProtocol ( >>> + Controller, >>> + &gEfiDevicePathProtocolGuid, >>> + This->DriverBindingHandle, >>> + Controller >>> + ); >>> + >>> + // >>> + // Now test the EmbeddedNonDiscoverableIoProtocol. >>> + // >>> + Status =3D gBS->OpenProtocol ( >>> + Controller, >>> + &gEdkiiNonDiscoverableDeviceProtocolGuid, >>> + (VOID **) &Dev, >>> + This->DriverBindingHandle, >>> + Controller, >>> + EFI_OPEN_PROTOCOL_BY_DRIVER >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + gBS->CloseProtocol ( >>> + Controller, >>> + &gEdkiiNonDiscoverableDeviceProtocolGuid, >>> + This->DriverBindingHandle, >>> + Controller >>> + ); >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Starts a device controller or a bus controller. >>> + >>> + The Start() function is designed to be invoked from the EFI boot se= rvice >>> + ConnectController(). >>> + As a result, much of the error checking on the parameters to Start(= ) has >>> + been moved into this >>> + common boot service. It is legal to call Start() from other locatio= ns, >>> + but the following calling restrictions must be followed or the syst= em >>> + behavior will not be deterministic. >>> + 1. ControllerHandle must be a valid EFI_HANDLE. >>> + 2. If RemainingDevicePath is not NULL, then it must be a pointer to= a >>> + naturally aligned EFI_DEVICE_PATH_PROTOCOL. >>> + 3. Prior to calling Start(), the Supported() function for the drive= r >>> + specified by This must have been called with the same calling >> parameters, >>> + and Supported() must have returned EFI_SUCCESS. >>> + >>> + @param[in] This A pointer to the >> EFI_DRIVER_BINDING_PROTOCOL >>> + instance. >>> + @param[in] ControllerHandle The handle of the controller to st= art. >> This >>> + handle must support a protocol int= erface >>> + that supplies an I/O abstraction t= o the >>> + driver. >>> + @param[in] RemainingDevicePath A pointer to the remaining portion= of >> a >>> + device path. This parameter is ig= nored by >>> + device drivers, and is optional fo= r bus >>> + drivers. >>> + For a bus driver, if this paramete= r is NULL, >>> + then handles for all the children = of >>> + Controller are created by this dri= ver. >>> + If this parameter is not NULL and = the first >>> + Device Path Node is not the End of= Device >>> + Path Node, then only the handle fo= r the >>> + child device specified by the firs= t Device >>> + Path Node of RemainingDevicePath i= s created >>> + by this driver. >>> + If the first Device Path Node of >>> + RemainingDevicePath is the End of = Device Path >>> + Node, no child handle is created b= y this >>> + driver. >>> + >>> + @retval EFI_SUCCESS The device was started. >>> + @retval EFI_DEVICE_ERROR The device could not be started du= e to a >>> + device error. Currently not implem= ented. >>> + @retval EFI_OUT_OF_RESOURCES The request could not be >> completed due to a >>> + lack of resources. >>> + @retval Others The driver failded to start the de= vice. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcDriverBindingStart ( >>> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >>> + IN EFI_HANDLE Controller, >>> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + >>> + NON_DISCOVERABLE_DEVICE *Dev; >>> + >>> + BOOLEAN MediaPresent; >>> + DWMMC_CARD_TYPE_DETECT_ROUTINE *Routine; >>> + UINT8 Index; >>> + UINT32 RoutineNum; >>> + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; >>> + >>> + Status =3D gBS->LocateProtocol ( >>> + &gPlatformDwMmcProtocolGuid, >>> + NULL, >>> + (VOID **) &PlatformDwMmc >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "err %d", __LINE__)); >>> + return Status; >>> + } >>> + >>> + Status =3D gBS->OpenProtocol ( >>> + Controller, >>> + &gEdkiiNonDiscoverableDeviceProtocolGuid, >>> + (VOID **) &Dev, >>> + This->DriverBindingHandle, >>> + Controller, >>> + EFI_OPEN_PROTOCOL_BY_DRIVER >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "err %d", __LINE__)); >>> + return Status; >>> + } >>> + >>> + Private =3D AllocateCopyPool (sizeof (DW_MMC_HC_PRIVATE_DATA), >> &gDwMmcHcTemplate); >>> + if (Private =3D=3D NULL) { >>> + DEBUG ((DEBUG_ERROR, "err %d", __LINE__)); >>> + Status =3D EFI_OUT_OF_RESOURCES; >>> + goto Done; >>> + } >>> + >>> + Private->ControllerHandle =3D Controller; >>> + Private->DevBase =3D Dev->Resources[0].AddrRangeMin; >>> + Private->PlatformDwMmc =3D PlatformDwMmc; >>> + InitializeListHead (&Private->Queue); >>> + >>> + Status =3D Private->PlatformDwMmc->GetCapability (Controller, 0, >> &Private->Capability[0]); >>> + >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + if (Private->Capability[0].BaseClkFreq =3D=3D 0) { >>> + goto Done; >>> + } >>> + >>> + DumpCapabilityReg (0, &Private->Capability[0]); >>> + >>> + MediaPresent =3D FALSE; >>> + >>> + Status =3D Private->PlatformDwMmc->CardDetect (Controller, 0); >>> + Status =3D DwMmcHcCardDetect (Private->DevBase, Controller, 0, >> &MediaPresent); >>> + if (MediaPresent =3D=3D FALSE) { >>> + goto Done; >>> + } >>> + >>> + // >>> + // Initialize slot and start identification process for the new att= ached >> device >>> + // >>> + Status =3D DwMmcHcInitHost (Private->DevBase, Private->Capability[0= ]); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + // >>> + // Reset HC >>> + // >>> + Status =3D DwMmcHcReset (Private->DevBase, Private->Capability[0]); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + Private->Slot[0].CardType =3D Private->Capability[0].CardType; >>> + Private->Slot[0].Enable =3D TRUE; >>> + Private->Slot[0].MediaPresent =3D TRUE; >>> + >>> + RoutineNum =3D sizeof (mCardTypeDetectRoutineTable) / sizeof >> (DWMMC_CARD_TYPE_DETECT_ROUTINE); >>> + for (Index =3D 0; Index < RoutineNum; Index++) { >>> + Routine =3D &mCardTypeDetectRoutineTable[Index]; >>> + if (*Routine !=3D NULL) { >>> + Status =3D (*Routine) (Private); >>> + if (!EFI_ERROR (Status)) { >>> + break; >>> + } >>> + } >>> + } >>> + >>> + // >>> + // Start the asynchronous I/O monitor >>> + // >>> + Status =3D gBS->CreateEvent ( >>> + EVT_TIMER | EVT_NOTIFY_SIGNAL, >>> + TPL_NOTIFY, >>> + ProcessAsyncTaskList, >>> + Private, >>> + &Private->TimerEvent >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + Status =3D gBS->SetTimer (Private->TimerEvent, TimerPeriodic, >> DW_MMC_HC_ASYNC_TIMER); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + // >>> + // Start the Sd removable device connection enumeration >>> + // >>> + Status =3D gBS->CreateEvent ( >>> + EVT_TIMER | EVT_NOTIFY_SIGNAL, >>> + TPL_CALLBACK, >>> + DwMmcHcEnumerateDevice, >>> + Private, >>> + &Private->ConnectEvent >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + Status =3D gBS->SetTimer (Private->ConnectEvent, TimerPeriodic, >> DW_MMC_HC_ENUM_TIMER); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + Status =3D gBS->InstallMultipleProtocolInterfaces ( >>> + &Controller, >>> + &gEfiSdMmcPassThruProtocolGuid, >>> + &(Private->PassThru), >>> + NULL >>> + ); >>> + >>> + DEBUG ((DEBUG_INFO, "DwMmcHcDriverBindingStart: %r End on %x\n", >> Status, Controller)); >>> + >>> +Done: >>> + if (EFI_ERROR (Status)) { >>> + if ((Private !=3D NULL) && (Private->TimerEvent !=3D NULL)) { >>> + gBS->CloseEvent (Private->TimerEvent); >>> + } >>> + >>> + if ((Private !=3D NULL) && (Private->ConnectEvent !=3D NULL)) { >>> + gBS->CloseEvent (Private->ConnectEvent); >>> + } >>> + >>> + if (Private !=3D NULL) { >>> + FreePool (Private); >>> + } >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Stops a device controller or a bus controller. >>> + >>> + The Stop() function is designed to be invoked from the EFI boot ser= vice >>> + DisconnectController(). >>> + As a result, much of the error checking on the parameters to Stop()= has >> been >>> + moved into this common boot service. It is legal to call Stop() fro= m other >>> + locations, but the following calling restrictions must be followed = or the >>> + system behavior will not be deterministic. >>> + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a >> previous >>> + call to this same driver's Start() function. >>> + 2. The first NumberOfChildren handles of ChildHandleBuffer must all= be a >> valid >>> + EFI_HANDLE. In addition, all of these handles must have been cre= ated >> in >>> + this driver's Start() function, and the Start() function must ha= ve called >>> + OpenProtocol() on ControllerHandle with an Attribute of >>> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. >>> + >>> + @param[in] This A pointer to the >> EFI_DRIVER_BINDING_PROTOCOL >>> + instance. >>> + @param[in] ControllerHandle A handle to the device being stopped. >> The handle >>> + must support a bus specific I/O proto= col for the >>> + driver to use to stop the device. >>> + @param[in] NumberOfChildren The number of child device handles in >>> + ChildHandleBuffer. >>> + @param[in] ChildHandleBuffer An array of child handles to be freed= . >> May be >>> + NULL if NumberOfChildren is 0. >>> + >>> + @retval EFI_SUCCESS The device was stopped. >>> + @retval EFI_DEVICE_ERROR The device could not be stopped due t= o a >> device >>> + error. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcHcDriverBindingStop ( >>> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >>> + IN EFI_HANDLE Controller, >>> + IN UINTN NumberOfChildren, >>> + IN EFI_HANDLE *ChildHandleBuffer >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + LIST_ENTRY *Link; >>> + LIST_ENTRY *NextLink; >>> + DW_MMC_HC_TRB *Trb; >>> + >>> + DEBUG ((DEBUG_INFO, "DwMmcHcDriverBindingStop: Start\n")); >>> + >>> + Status =3D gBS->OpenProtocol ( >>> + Controller, >>> + &gEfiSdMmcPassThruProtocolGuid, >>> + (VOID**) &PassThru, >>> + This->DriverBindingHandle, >>> + Controller, >>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); >>> + // >>> + // Close Non-Blocking timer and free Task list. >>> + // >>> + if (Private->TimerEvent !=3D NULL) { >>> + gBS->CloseEvent (Private->TimerEvent); >>> + Private->TimerEvent =3D NULL; >>> + } >>> + if (Private->ConnectEvent !=3D NULL) { >>> + gBS->CloseEvent (Private->ConnectEvent); >>> + Private->ConnectEvent =3D NULL; >>> + } >>> + // >>> + // As the timer is closed, there is no needs to use TPL lock to >>> + // protect the critical region "queue". >>> + // >>> + for (Link =3D GetFirstNode (&Private->Queue); >>> + !IsNull (&Private->Queue, Link); >>> + Link =3D NextLink) { >>> + NextLink =3D GetNextNode (&Private->Queue, Link); >>> + RemoveEntryList (Link); >>> + Trb =3D DW_MMC_HC_TRB_FROM_THIS (Link); >>> + Trb->Packet->TransactionStatus =3D EFI_ABORTED; >>> + gBS->SignalEvent (Trb->Event); >>> + DwMmcFreeTrb (Trb); >>> + } >>> + >>> + // >>> + // Uninstall Block I/O protocol from the device handle >>> + // >>> + Status =3D gBS->UninstallProtocolInterface ( >>> + Controller, >>> + &gEfiSdMmcPassThruProtocolGuid, >>> + &(Private->PassThru) >>> + ); >>> + >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + gBS->CloseProtocol ( >>> + Controller, >>> + &gEfiPciIoProtocolGuid, >>> + This->DriverBindingHandle, >>> + Controller >>> + ); >>> + >>> + FreePool (Private); >>> + >>> + DEBUG ((DEBUG_INFO, "DwMmcHcDriverBindingStop: End with %r\n", >> Status)); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Sends SD command to an SD card that is attached to the SD controlle= r. >>> + >>> + The PassThru() function sends the SD command specified by Packet to >> the SD >>> + card specified by Slot. >>> + >>> + If Packet is successfully sent to the SD card, then EFI_SUCCESS is >> returned. >>> + >>> + If a device error occurs while sending the Packet, then >> EFI_DEVICE_ERROR is >>> + returned. >>> + >>> + If Slot is not in a valid range for the SD controller, then >>> + EFI_INVALID_PARAMETER is returned. >>> + >>> + If Packet defines a data command but both InDataBuffer and >> OutDataBuffer are >>> + NULL, EFI_INVALID_PARAMETER is returned. >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Slot The slot number of the SD card to sen= d the >>> + command to. >>> + @param[in,out] Packet A pointer to the SD command data stru= cture. >>> + @param[in] Event If Event is NULL, blocking I/O is per= formed. If >>> + Event is not NULL, then nonblocking I= /O is >>> + performed, and Event will be signaled= when the >>> + Packet completes. >>> + >>> + @retval EFI_SUCCESS The SD Command Packet was sent by the >> host. >>> + @retval EFI_DEVICE_ERROR A device error occurred while attempt= ing >> to send >>> + the SD command Packet. >>> + @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the >> Packet is >>> + invalid. >>> + @retval EFI_INVALID_PARAMETER Packet defines a data command but >> both >>> + InDataBuffer and OutDataBuffer are NU= LL. >>> + @retval EFI_NO_MEDIA SD Device not present in the Slot. >>> + @retval EFI_UNSUPPORTED The command described by the SD >> Command Packet >>> + is not supported by the host controll= er. >>> + @retval EFI_BAD_BUFFER_SIZE The InTransferLength or >> OutTransferLength >>> + exceeds the limit supported by SD car= d >>> + ( i.e. if the number of bytes exceed = the Last >>> + LBA). >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruPassThru ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN UINT8 Slot, >>> + IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, >>> + IN EFI_EVENT Event OPTIONAL >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + DW_MMC_HC_TRB *Trb; >>> + EFI_TPL OldTpl; >>> + >>> + if ((This =3D=3D NULL) || (Packet =3D=3D NULL)) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if ((Packet->SdMmcCmdBlk =3D=3D NULL) || (Packet->SdMmcStatusBlk = =3D=3D >> NULL)) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if ((Packet->OutDataBuffer =3D=3D NULL) && (Packet->OutTransferLeng= th !=3D >> 0)) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if ((Packet->InDataBuffer =3D=3D NULL) && (Packet->InTransferLength= !=3D 0)) >> { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); >>> + >>> + if (!Private->Slot[Slot].Enable) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if (!Private->Slot[Slot].MediaPresent) { >>> + return EFI_NO_MEDIA; >>> + } >>> + >>> + Trb =3D DwMmcCreateTrb (Private, Slot, Packet, Event); >>> + if (Trb =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + // >>> + // Immediately return for async I/O. >>> + // >>> + if (Event !=3D NULL) { >>> + return EFI_SUCCESS; >>> + } >>> + >>> + // >>> + // Wait async I/O list is empty before execute sync I/O operation. >>> + // >>> + while (TRUE) { >>> + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); >>> + if (IsListEmpty (&Private->Queue)) { >>> + gBS->RestoreTPL (OldTpl); >>> + break; >>> + } >>> + gBS->RestoreTPL (OldTpl); >>> + } >>> + >>> + Status =3D DwMmcWaitTrbEnv (Private, Trb); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + Status =3D DwMmcExecTrb (Private, Trb); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> + Status =3D DwMmcWaitTrbResult (Private, Trb); >>> + if (EFI_ERROR (Status)) { >>> + goto Done; >>> + } >>> + >>> +Done: >>> + if (Trb !=3D NULL) { >>> + DwMmcFreeTrb (Trb); >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Used to retrieve next slot numbers supported by the SD controller. = The >>> + function returns information about all available slots (populated o= r >>> + not-populated). >>> + >>> + The GetNextSlot() function retrieves the next slot number on an SD >> controller. >>> + If on input Slot is 0xFF, then the slot number of the first slot on= the SD >>> + controller is returned. >>> + >>> + If Slot is a slot number that was returned on a previous call to >>> + GetNextSlot(), then the slot number of the next slot on the SD cont= roller >> is >>> + returned. >>> + >>> + If Slot is not 0xFF and Slot was not returned on a previous call to >>> + GetNextSlot(), EFI_INVALID_PARAMETER is returned. >>> + >>> + If Slot is the slot number of the last slot on the SD controller, t= hen >>> + EFI_NOT_FOUND is returned. >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in,out] Slot On input, a pointer to a slot number = on the SD >>> + controller. >>> + On output, a pointer to the next slot= number on >>> + the SD controller. >>> + An input value of 0xFF retrieves the = first slot >>> + number on the SD controller. >>> + >>> + @retval EFI_SUCCESS The next slot number on the SD contro= ller >> was >>> + returned in Slot. >>> + @retval EFI_NOT_FOUND There are no more slots on this SD >> controller. >>> + @retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not >> returned on a >>> + previous call to GetNextSlot(). >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruGetNextSlot ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN OUT UINT8 *Slot >>> + ) >>> +{ >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + >>> + if ((This =3D=3D NULL) || (Slot =3D=3D NULL)) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); >>> + >>> + if (*Slot =3D=3D 0xFF) { >>> + if (Private->Slot[0].Enable) { >>> + *Slot =3D 0; >>> + Private->PreviousSlot =3D 0; >>> + return EFI_SUCCESS; >>> + } >>> + return EFI_NOT_FOUND; >>> + } else if (*Slot =3D=3D Private->PreviousSlot) { >>> + return EFI_NOT_FOUND; >>> + } else { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> +} >>> + >>> +/** >>> + Used to allocate and build a device path node for an SD card on the= SD >>> + controller. >>> + >>> + The BuildDevicePath() function allocates and builds a single device= node >>> + for the SD card specified by Slot. >>> + >>> + If the SD card specified by Slot is not present on the SD controlle= r, then >>> + EFI_NOT_FOUND is returned. >>> + >>> + If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. >>> + >>> + If there are not enough resources to allocate the device path node,= then >>> + EFI_OUT_OF_RESOURCES is returned. >>> + >>> + Otherwise, DevicePath is allocated with the boot service AllocatePo= ol(), >>> + the contents of DevicePath are initialized to describe the SD card >> specified >>> + by Slot, and EFI_SUCCESS is returned. >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Slot Specifies the slot number of the SD c= ard for >>> + which a device path node is to be all= ocated and >>> + built. >>> + @param[in,out] DevicePath A pointer to a single device path nod= e that >>> + describes the SD card specified by Sl= ot. This >>> + function is responsible for allocatin= g the >>> + buffer DevicePath with the boot servi= ce >>> + AllocatePool(). It is the caller's re= sponsi- >>> + bility to free DevicePath when the ca= ller is >>> + finished with DevicePath. >>> + >>> + @retval EFI_SUCCESS The device path node that describes t= he SD >> card >>> + specified by Slot was allocated and r= eturned in >>> + DevicePath. >>> + @retval EFI_NOT_FOUND The SD card specified by Slot does no= t >> exist on >>> + the SD controller. >>> + @retval EFI_INVALID_PARAMETER DevicePath is NULL. >>> + @retval EFI_OUT_OF_RESOURCES There are not enough resources to >> allocate >>> + DevicePath. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruBuildDevicePath ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN UINT8 Slot, >>> + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath >>> + ) >>> +{ >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + SD_DEVICE_PATH *SdNode; >>> + EMMC_DEVICE_PATH *EmmcNode; >>> + >>> + if ((This =3D=3D NULL) || (DevicePath =3D=3D NULL) || (Slot >=3D >> DW_MMC_HC_MAX_SLOT)) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); >>> + >>> + if ((!Private->Slot[Slot].Enable) || (!Private->Slot[Slot].MediaPre= sent)) { >>> + return EFI_NOT_FOUND; >>> + } >>> + >>> + if (Private->Slot[Slot].CardType =3D=3D SdCardType) { >>> + SdNode =3D AllocateCopyPool (sizeof (SD_DEVICE_PATH), >> &mSdDpTemplate); >>> + if (SdNode =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + SdNode->SlotNumber =3D Slot; >>> + >>> + *DevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) SdNode; >>> + } else if (Private->Slot[Slot].CardType =3D=3D EmmcCardType) { >>> + EmmcNode =3D AllocateCopyPool (sizeof (EMMC_DEVICE_PATH), >> &mEmmcDpTemplate); >>> + if (EmmcNode =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + EmmcNode->SlotNumber =3D Slot; >>> + >>> + *DevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) EmmcNode; >>> + } else { >>> + // >>> + // Currently we only support SD and EMMC two device nodes. >>> + // >>> + return EFI_NOT_FOUND; >>> + } >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + This function retrieves an SD card slot number based on the input d= evice >> path. >>> + >>> + The GetSlotNumber() function retrieves slot number for the SD card >> specified >>> + by the DevicePath node. If DevicePath is NULL, >> EFI_INVALID_PARAMETER is >>> + returned. >>> + >>> + If DevicePath is not a device path node type that the SD Pass Thru = driver >>> + supports, EFI_UNSUPPORTED is returned. >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] DevicePath A pointer to the device path node tha= t >> describes >>> + a SD card on the SD controller. >>> + @param[out] Slot On return, points to the slot number = of an SD >>> + card on the SD controller. >>> + >>> + @retval EFI_SUCCESS SD card slot number is returned in Sl= ot. >>> + @retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL. >>> + @retval EFI_UNSUPPORTED DevicePath is not a device path node >> type that >>> + the SD Pass Thru driver supports. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruGetSlotNumber ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, >>> + OUT UINT8 *Slot >>> + ) >>> +{ >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + SD_DEVICE_PATH *SdNode; >>> + EMMC_DEVICE_PATH *EmmcNode; >>> + UINT8 SlotNumber; >>> + >>> + if ((This =3D=3D NULL) || (DevicePath =3D=3D NULL) || (Slot =3D=3D = NULL)) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); >>> + >>> + // >>> + // Check whether the DevicePath belongs to SD_DEVICE_PATH or >> EMMC_DEVICE_PATH >>> + // >>> + if ((DevicePath->Type !=3D MESSAGING_DEVICE_PATH) || >>> + ((DevicePath->SubType !=3D MSG_SD_DP) && >>> + (DevicePath->SubType !=3D MSG_EMMC_DP)) || >>> + (DevicePathNodeLength(DevicePath) !=3D sizeof(SD_DEVICE_PATH)) = || >>> + (DevicePathNodeLength(DevicePath) !=3D >> sizeof(EMMC_DEVICE_PATH))) { >>> + return EFI_UNSUPPORTED; >>> + } >>> + >>> + if (DevicePath->SubType =3D=3D MSG_SD_DP) { >>> + SdNode =3D (SD_DEVICE_PATH *) DevicePath; >>> + SlotNumber =3D SdNode->SlotNumber; >>> + } else { >>> + EmmcNode =3D (EMMC_DEVICE_PATH *) DevicePath; >>> + SlotNumber =3D EmmcNode->SlotNumber; >>> + } >>> + >>> + if (SlotNumber >=3D DW_MMC_HC_MAX_SLOT) { >>> + return EFI_NOT_FOUND; >>> + } >>> + >>> + if (Private->Slot[SlotNumber].Enable) { >>> + *Slot =3D SlotNumber; >>> + return EFI_SUCCESS; >>> + } else { >>> + return EFI_NOT_FOUND; >>> + } >>> +} >>> + >>> +/** >>> + Resets an SD card that is connected to the SD controller. >>> + >>> + The ResetDevice() function resets the SD card specified by Slot. >>> + >>> + If this SD controller does not support a device reset operation, >>> + EFI_UNSUPPORTED is returned. >>> + >>> + If Slot is not in a valid slot number for this SD controller, >>> + EFI_INVALID_PARAMETER is returned. >>> + >>> + If the device reset operation is completed, EFI_SUCCESS is returned= . >>> + >>> + @param[in] This A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Slot Specifies the slot number of the SD c= ard to be >>> + reset. >>> + >>> + @retval EFI_SUCCESS The SD card specified by Slot was res= et. >>> + @retval EFI_UNSUPPORTED The SD controller does not support a >> device >>> + reset operation. >>> + @retval EFI_INVALID_PARAMETER Slot number is invalid. >>> + @retval EFI_NO_MEDIA SD Device not present in the Slot. >>> + @retval EFI_DEVICE_ERROR The reset command failed due to a dev= ice >> error >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +DwMmcPassThruResetDevice ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, >>> + IN UINT8 Slot >>> + ) >>> +{ >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + LIST_ENTRY *Link; >>> + LIST_ENTRY *NextLink; >>> + DW_MMC_HC_TRB *Trb; >>> + EFI_TPL OldTpl; >>> + >>> + if (This =3D=3D NULL) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); >>> + >>> + if (!Private->Slot[Slot].Enable) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if (!Private->Slot[Slot].MediaPresent) { >>> + return EFI_NO_MEDIA; >>> + } >>> + >>> + // >>> + // Free all async I/O requests in the queue >>> + // >>> + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); >>> + >>> + for (Link =3D GetFirstNode (&Private->Queue); >>> + !IsNull (&Private->Queue, Link); >>> + Link =3D NextLink) { >>> + NextLink =3D GetNextNode (&Private->Queue, Link); >>> + RemoveEntryList (Link); >>> + Trb =3D DW_MMC_HC_TRB_FROM_THIS (Link); >>> + Trb->Packet->TransactionStatus =3D EFI_ABORTED; >>> + gBS->SignalEvent (Trb->Event); >>> + DwMmcFreeTrb (Trb); >>> + } >>> + >>> + gBS->RestoreTPL (OldTpl); >>> + >>> + return EFI_SUCCESS; >>> +} >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.c >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.c >>> new file mode 100644 >>> index 000000000000..b091f9803b2e >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.c >>> @@ -0,0 +1,1602 @@ >>> +/** @file >>> + This driver is used to manage Designware SD/MMC PCI host controller= s. >>> + >>> + It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer >> use. >>> + >>> + Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<= BR> >>> + Copyright (c) 2018, Linaro Ltd. All rights reserved.
>>> + >>> + This program and the accompanying materials are licensed and made >> available >>> + under the terms and conditions of the BSD License which accompanies >> this >>> + distribution. The full text of the license may be found at >>> + http://opensource.org/licenses/bsd-license.php >>> + >>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" >> BASIS, >>> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER >> EXPRESS OR IMPLIED. >>> + >>> +**/ >>> + >>> +#include >>> +#include >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include "DwMmcHcDxe.h" >>> + >>> +/** >>> + Dump the content of SD/MMC host controller's Capability Register. >>> + >>> + @param[in] Slot The slot number of the SD card to send = the >>> + command to. >>> + @param[in] Capability The buffer to store the capability data= . >>> + >>> +**/ >>> +VOID >>> +DumpCapabilityReg ( >>> + IN UINT8 Slot, >>> + IN DW_MMC_HC_SLOT_CAP *Capability >>> + ) >>> +{ >>> + // >>> + // Dump Capability Data >>> + // >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " =3D=3D Slot [%d] Capability is 0x%x =3D=3D\n", >>> + Slot, >>> + Capability >>> + )); >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " Base Clk Freq %dKHz\n", >>> + Capability->BaseClkFreq >>> + )); >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " BusWidth %d\n", >>> + Capability->BusWidth >>> + )); >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " HighSpeed Support %a\n", >>> + Capability->HighSpeed ? "TRUE" : "FALSE" >>> + )); >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " Voltage 1.8 %a\n", >>> + Capability->Voltage18 ? "TRUE" : "FALSE" >>> + )); >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " 64-bit Sys Bus %a\n", >>> + Capability->SysBus64 ? "TRUE" : "FALSE" >>> + )); >>> + DEBUG ((DEBUG_INFO, " SlotType ")); >>> + if (Capability->SlotType =3D=3D 0x00) { >>> + DEBUG ((DEBUG_INFO, "%a\n", "Removable Slot")); >>> + } else if (Capability->SlotType =3D=3D 0x01) { >>> + DEBUG ((DEBUG_INFO, "%a\n", "Embedded Slot")); >>> + } else if (Capability->SlotType =3D=3D 0x02) { >>> + DEBUG ((DEBUG_INFO, "%a\n", "Shared Bus Slot")); >>> + } else { >>> + DEBUG ((DEBUG_INFO, "%a\n", "Reserved")); >>> + } >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " SDR50 Support %a\n", >>> + Capability->Sdr50 ? "TRUE" : "FALSE" >>> + )); >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " SDR104 Support %a\n", >>> + Capability->Sdr104 ? "TRUE" : "FALSE" >>> + )); >>> + DEBUG (( >>> + DEBUG_INFO, >>> + " DDR50 Support %a\n", >>> + Capability->Ddr50 ? "TRUE" : "FALSE" >>> + )); >>> + return; >>> +} >>> + >>> +/** >>> + Set all interrupt status bits in Normal and Error Interrupt Status = Enable >>> + register. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + >>> + @retval EFI_SUCCESS The operation executes successfully. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcEnableInterrupt ( >>> + UINTN DevBase >>> + ) >>> +{ >>> + UINT32 IntStatus; >>> + UINT32 IdIntEn; >>> + UINT32 IdSts; >>> + >>> + // >>> + // Enable all bits in Interrupt Mask Register >>> + // >>> + IntStatus =3D 0; >>> + MmioWrite32 (DevBase + DW_MMC_INTMASK, IntStatus); >>> + >>> + // >>> + // Clear status in Interrupt Status Register >>> + // >>> + IntStatus =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_RINTSTS, IntStatus); >>> + >>> + IdIntEn =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_IDINTEN, IdIntEn); >>> + >>> + IdSts =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_IDSTS, IdSts); >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +EFI_STATUS >>> +DwMmcHcGetCapability ( >>> + IN UINTN DevBase, >>> + IN EFI_HANDLE Controller, >>> + IN UINT8 Slot, >>> + OUT DW_MMC_HC_SLOT_CAP *Capacity >>> + ) >>> +{ >>> + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; >>> + EFI_STATUS Status; >>> + >>> + if (Capacity =3D=3D NULL) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + Status =3D gBS->LocateProtocol ( >>> + &gPlatformDwMmcProtocolGuid, >>> + NULL, >>> + (VOID **) &PlatformDwMmc >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + Status =3D PlatformDwMmc->GetCapability (Controller, Slot, Capacity= ); >>> + return Status; >>> +} >>> + >>> +/** >>> + Detect whether there is a SD/MMC card attached at the specified >> SD/MMC host >>> + controller slot. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for det= ails. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command >>> + to. >>> + @param[out] MediaPresent The pointer to the media present boolean >> value. >>> + >>> + @retval EFI_SUCCESS There is no media change happened. >>> + @retval EFI_MEDIA_CHANGED There is media change happened. >>> + @retval Others The detection fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcCardDetect ( >>> + IN UINTN DevBase, >>> + IN EFI_HANDLE Controller, >>> + IN UINT8 Slot, >>> + OUT BOOLEAN *MediaPresent >>> + ) >>> +{ >>> + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; >>> + EFI_STATUS Status; >>> + >>> + if (MediaPresent =3D=3D NULL) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + Status =3D gBS->LocateProtocol ( >>> + &gPlatformDwMmcProtocolGuid, >>> + NULL, >>> + (VOID **) &PlatformDwMmc >>> + ); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + *MediaPresent =3D PlatformDwMmc->CardDetect (Controller, Slot); >>> + return EFI_SUCCESS; >>> +} >>> + >>> +STATIC >>> +EFI_STATUS >>> +DwMmcHcUpdateClock ( >>> + IN UINTN DevBase >>> + ) >>> +{ >>> + UINT32 Cmd; >>> + UINT32 IntStatus; >>> + >>> + Cmd =3D BIT_CMD_WAIT_PRVDATA_COMPLETE | >> BIT_CMD_UPDATE_CLOCK_ONLY | >>> + BIT_CMD_START; >>> + MmioWrite32 (DevBase + DW_MMC_CMD, Cmd); >>> + >>> + while (1) { >>> + Cmd =3D MmioRead32 (DevBase + DW_MMC_CMD); >>> + >>> + if (!(Cmd & CMD_START_BIT)) { >>> + break; >>> + } >>> + >>> + IntStatus =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); >>> + >>> + if (IntStatus & DW_MMC_INT_HLE) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "DwMmcHcUpdateClock: failed to update mmc clock frequency\n" >>> + )); >>> + return EFI_DEVICE_ERROR; >>> + } >>> + } >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Stop SD/MMC card clock. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + >>> + @retval EFI_SUCCESS Succeed to stop SD/MMC clock. >>> + @retval Others Fail to stop SD/MMC clock. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcStopClock ( >>> + IN UINTN DevBase >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT32 ClkEna; >>> + >>> + // >>> + // Disable MMC clock first >>> + // >>> + ClkEna =3D 0; >>> + MmioWrite32 (DevBase + DW_MMC_CLKENA, ClkEna); >>> + >>> + Status =3D DwMmcHcUpdateClock (DevBase); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + return Status; >>> +} >>> + >>> +/** >>> + SD/MMC card clock supply. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] ClockFreq The max clock frequency to be set. The un= it is >> KHz. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The clock is supplied successfully. >>> + @retval Others The clock isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcClockSupply ( >>> + IN UINTN DevBase, >>> + IN UINT64 ClockFreq, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT32 BaseClkFreq; >>> + UINT32 SettingFreq; >>> + UINT32 Divisor; >>> + UINT32 Remainder; >>> + UINT32 MmcStatus; >>> + UINT32 ClkEna; >>> + UINT32 ClkSrc; >>> + >>> + // >>> + // Calculate a divisor for SD clock frequency >>> + // >>> + ASSERT (Capability.BaseClkFreq !=3D 0); >>> + >>> + BaseClkFreq =3D Capability.BaseClkFreq; >>> + if (ClockFreq =3D=3D 0) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if (ClockFreq > BaseClkFreq) { >>> + ClockFreq =3D BaseClkFreq; >>> + } >>> + >>> + // >>> + // Calculate the divisor of base frequency. >>> + // >>> + Divisor =3D 0; >>> + SettingFreq =3D BaseClkFreq; >>> + while (ClockFreq < SettingFreq) { >>> + Divisor++; >>> + >>> + SettingFreq =3D BaseClkFreq / (2 * Divisor); >>> + Remainder =3D BaseClkFreq % (2 * Divisor); >>> + if ((ClockFreq =3D=3D SettingFreq) && (Remainder =3D=3D 0)) { >>> + break; >>> + } >>> + if ((ClockFreq =3D=3D SettingFreq) && (Remainder !=3D 0)) { >>> + SettingFreq ++; >>> + } >>> + } >>> + >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "BaseClkFreq %dKHz Divisor %d ClockFreq %dKhz\n", >>> + BaseClkFreq, >>> + Divisor, >>> + ClockFreq >>> + )); >>> + >>> + // >>> + // Wait until MMC is idle >>> + // >>> + do { >>> + MmcStatus =3D MmioRead32 (DevBase + DW_MMC_STATUS); >>> + } while (MmcStatus & DW_MMC_STS_DATA_BUSY); >>> + >>> + do { >>> + Status =3D DwMmcHcStopClock (DevBase); >>> + } while (EFI_ERROR (Status)); >>> + >>> + do { >>> + ClkSrc =3D 0; >>> + MmioWrite32 (DevBase + DW_MMC_CLKSRC, ClkSrc); >>> + // >>> + // Set clock divisor >>> + // >>> + MmioWrite32 (DevBase + DW_MMC_CLKDIV, Divisor); >>> + // >>> + // Enable MMC clock >>> + // >>> + ClkEna =3D 1; >>> + MmioWrite32 (DevBase + DW_MMC_CLKENA, ClkEna); >>> + >>> + Status =3D DwMmcHcUpdateClock (DevBase); >>> + } while (EFI_ERROR (Status)); >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Set the SD/MMC bus width. >>> + >>> + Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for det= ails. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] IsDdr A boolean to indicate it's dual data rate= or not. >>> + @param[in] BusWidth The bus width used by the SD/MMC device, = it >> must be >>> + 1, 4 or 8. >>> + >>> + @retval EFI_SUCCESS The bus width is set successfully. >>> + @retval Others The bus width isn't set successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcSetBusWidth ( >>> + IN UINTN DevBase, >>> + IN BOOLEAN IsDdr, >>> + IN UINT16 BusWidth >>> + ) >>> +{ >>> + UINT32 Ctype; >>> + UINT32 Uhs; >>> + >>> + switch (BusWidth) { >>> + case 1: >>> + Ctype =3D MMC_1BIT_MODE; >>> + break; >>> + case 4: >>> + Ctype =3D MMC_4BIT_MODE; >>> + break; >>> + case 8: >>> + Ctype =3D MMC_8BIT_MODE; >>> + break; >>> + default: >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + MmioWrite32 (DevBase + DW_MMC_CTYPE, Ctype); >>> + >>> + Uhs =3D MmioRead32 (DevBase + DW_MMC_UHSREG); >>> + >>> + if (IsDdr) { >>> + Uhs |=3D UHS_DDR_MODE; >>> + } else { >>> + Uhs &=3D ~(UHS_DDR_MODE); >>> + } >>> + >>> + MmioWrite32 (DevBase + DW_MMC_UHSREG, Uhs); >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Supply SD/MMC card with lowest clock frequency at initialization. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The clock is supplied successfully. >>> + @retval Others The clock isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitClockFreq ( >>> + IN UINTN DevBase, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT32 InitFreq; >>> + >>> + // >>> + // Calculate a divisor for SD clock frequency >>> + // >>> + if (Capability.BaseClkFreq =3D=3D 0) { >>> + // >>> + // Don't support get Base Clock Frequency information via another >> method >>> + // >>> + return EFI_UNSUPPORTED; >>> + } >>> + // >>> + // Supply 400KHz clock frequency at initialization phase. >>> + // >>> + InitFreq =3D DWMMC_INIT_CLOCK_FREQ; >>> + Status =3D DwMmcHcClockSupply (DevBase, InitFreq, Capability); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + MicroSecondDelay (100); >>> + return Status; >>> +} >>> + >>> +/** >>> + Supply SD/MMC card with maximum voltage at initialization. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The voltage is supplied successfully. >>> + @retval Others The voltage isn't supplied successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitPowerVoltage ( >>> + IN UINTN DevBase, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ) >>> +{ >>> + UINT32 Data; >>> + UINT32 Timeout; >>> + >>> + Data =3D 0x1; >>> + MmioWrite32 (DevBase + DW_MMC_PWREN, Data); >>> + >>> + Data =3D DW_MMC_CTRL_RESET_ALL; >>> + MmioWrite32 (DevBase + DW_MMC_CTRL, Data); >>> + >>> + Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + while (Timeout > 0) { >>> + Data =3D MmioRead32 (DevBase + DW_MMC_CTRL); >>> + >>> + if ((Data & DW_MMC_CTRL_RESET_ALL) =3D=3D 0) { >>> + break; >>> + } >>> + gBS->Stall (1); >>> + >>> + Timeout--; >>> + } >>> + >>> + if (Timeout <=3D 0) { >>> + DEBUG ((DEBUG_INFO, >>> + "DwMmcHcInitPowerVoltage: reset failed due to timeout")); >>> + >>> + return EFI_TIMEOUT; >>> + } >>> + >>> + Data =3D DW_MMC_CTRL_INT_EN; >>> + MmioWrite32 (DevBase + DW_MMC_CTRL, Data); >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Initialize the Timeout Control register with most conservative valu= e at >>> + initialization. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + >>> + @retval EFI_SUCCESS The timeout control register is configure= d >>> + successfully. >>> + @retval Others The timeout control register isn't config= ured >>> + successfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitTimeoutCtrl ( >>> + IN UINTN DevBase >>> + ) >>> +{ >>> + UINT32 Data; >>> + >>> + Data =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_TMOUT, Data); >>> + >>> + Data =3D 0x00FFFFFF; >>> + MmioWrite32 (DevBase + DW_MMC_DEBNCE, Data); >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Initial SD/MMC host controller with lowest clock frequency, max pow= er >> and >>> + max timeout value at initialization. >>> + >>> + @param[in] DevIo The DEVICE IO protocol instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command >>> + to. >>> + @param[in] Capability The capability of the slot. >>> + >>> + @retval EFI_SUCCESS The host controller is initialized succes= sfully. >>> + @retval Others The host controller isn't initialized suc= cessfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcHcInitHost ( >>> + IN UINTN DevBase, >>> + IN DW_MMC_HC_SLOT_CAP Capability >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + >>> + Status =3D DwMmcHcInitPowerVoltage (DevBase, Capability); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + return Status; >>> +} >>> + >>> +EFI_STATUS >>> +DwMmcHcStartDma ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + UINTN DevBase; >>> + UINT32 Ctrl; >>> + UINT32 Bmod; >>> + UINT32 Timeout; >>> + UINT32 Data; >>> + >>> +// DevIo =3D Trb->Private->DevIo; >>> + DevBase =3D Trb->Private->DevBase; >>> + >>> + // >>> + // Reset DMA >>> + // >>> + Ctrl =3D DW_MMC_CTRL_DMA_RESET; >>> + MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl); >>> + >>> + Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + while (Timeout > 0) { >>> + Data =3D MmioRead32 (DevBase + DW_MMC_CTRL); >>> + >>> + if ((Data & DW_MMC_CTRL_DMA_RESET) =3D=3D 0) { >>> + break; >>> + } >>> + gBS->Stall (1); >>> + >>> + Timeout--; >>> + } >>> + >>> + if (Timeout <=3D 0) { >>> + DEBUG ((DEBUG_ERROR, "Timed out waiting for CTRL_DMA_RESET")); >>> + >>> + return EFI_TIMEOUT; >>> + } >>> + >>> + Bmod =3D DW_MMC_IDMAC_SWRESET | MmioRead32 (DevBase + >> DW_MMC_BMOD); >>> + >>> + MmioWrite32 (DevBase + DW_MMC_BMOD, Bmod); >>> + >>> + // >>> + // Select IDMAC >>> + // >>> + Ctrl =3D DW_MMC_CTRL_IDMAC_EN; >>> + Ctrl |=3D MmioRead32 (DevBase + DW_MMC_CTRL); >>> + MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl); >>> + >>> + // >>> + // Enable IDMAC >>> + // >>> + Bmod =3D DW_MMC_IDMAC_ENABLE | DW_MMC_IDMAC_FB; >>> + Bmod |=3D MmioRead32 (DevBase + DW_MMC_BMOD); >>> + >>> + MmioWrite32 (DevBase + DW_MMC_BMOD, Bmod); >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +EFI_STATUS >>> +DwMmcHcStopDma ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + UINTN DevBase; >>> + UINT32 Ctrl; >>> + UINT32 Bmod; >>> + >>> + DevBase =3D Trb->Private->DevBase; >>> + >>> + // >>> + // Disable and reset IDMAC >>> + // >>> + Ctrl =3D MmioRead32 (DevBase + DW_MMC_CTRL); >>> + Ctrl &=3D ~DW_MMC_CTRL_IDMAC_EN; >>> + Ctrl |=3D DW_MMC_CTRL_DMA_RESET; >>> + MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl); >>> + >>> + // >>> + // Stop IDMAC >>> + // >>> + Bmod =3D MmioRead32 (DevBase + DW_MMC_BMOD); >>> + Bmod &=3D ~(DW_MMC_BMOD_FB | DW_MMC_BMOD_DE); >>> + Bmod |=3D DW_MMC_BMOD_SWR; >>> + MmioWrite32 (DevBase + DW_MMC_BMOD, Bmod); >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Build DMA descriptor table for transfer. >>> + >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The DMA descriptor table is created >> successfully. >>> + @retval Others The DMA descriptor table isn't created su= ccessfully. >>> + >>> +**/ >>> +EFI_STATUS >>> +BuildDmaDescTable ( >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + EFI_PHYSICAL_ADDRESS Data; >>> + UINT64 DataLen; >>> + UINT64 Entries; >>> + UINT32 Index; >>> + UINT64 Remaining; >>> + UINTN TableSize; >>> + UINTN DevBase; >>> + EFI_STATUS Status; >>> + UINTN Bytes; >>> + UINTN Blocks; >>> + DW_MMC_HC_DMA_DESC_LINE *DmaDesc; >>> + UINT32 DmaDescPhy; >>> + UINT32 Idsts; >>> + UINT32 BytCnt; >>> + UINT32 BlkSize; >>> + >>> + Data =3D Trb->DataPhy; >>> + DataLen =3D Trb->DataLen; >>> + DevBase =3D Trb->Private->DevBase; >>> + // >>> + // Only support 32bit DMA Descriptor Table >>> + // >>> + if ((Data >=3D 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)= ) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + // >>> + // Address field shall be set on 32-bit boundary (Lower 2-bit is al= ways set >>> + // to 0) for 32-bit address descriptor table. >>> + // >>> + if ((Data & (BIT0 | BIT1)) !=3D 0) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "The buffer [0x%x] to construct DMA desc is not aligned to 4 by= tes!\n", >>> + Data >>> + )); >>> + } >>> + >>> + Entries =3D (DataLen + DWMMC_DMA_BUF_SIZE - 1) / >> DWMMC_DMA_BUF_SIZE; >>> + TableSize =3D Entries * sizeof (DW_MMC_HC_DMA_DESC_LINE); >>> + Blocks =3D (DataLen + DW_MMC_BLOCK_SIZE - 1) / >> DW_MMC_BLOCK_SIZE; >>> + >>> + Trb->DmaDescPages =3D (UINT32)EFI_SIZE_TO_PAGES (Entries * >> DWMMC_DMA_BUF_SIZE); >>> +/* Status =3D DevIo->AllocateBuffer ( >>> + DevIo, >>> + AllocateAnyPages, >>> + EfiBootServicesData, >>> + EFI_SIZE_TO_PAGES (TableSize), >>> + (EFI_PHYSICAL_ADDRESS *)&Trb->DmaDesc >>> + );*/ >>> + Status =3D DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGE= S >> (TableSize), >>> + (VOID *)&Trb->DmaDesc); >>> + if (EFI_ERROR (Status)) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ZeroMem (Trb->DmaDesc, TableSize); >>> + Bytes =3D TableSize; >>> + >>> + Status =3D DmaMap (MapOperationBusMasterCommonBuffer, >>> + (EFI_PHYSICAL_ADDRESS *)Trb->DmaDesc, >>> + &Bytes, &Trb->DmaDescPhy, &Trb->DmaMap); >>> +/* Status =3D DevIo->Map ( >>> + DevIo, >>> + EfiBusMasterCommonBuffer, >>> + (EFI_PHYSICAL_ADDRESS *)Trb->DmaDesc, >>> + &Bytes, >>> + &Trb->DmaDescPhy, >>> + &Trb->DmaMap >>> + );*/ >>> + >>> + if (EFI_ERROR (Status) || (Bytes !=3D TableSize)) { >>> + // >>> + // Map error or unable to map the whole RFis buffer into a contig= uous >>> + // region. >>> + // >>> +/* DevIo->FreeBuffer ( >>> + DevIo, >>> + EFI_SIZE_TO_PAGES (TableSize), >>> + (EFI_PHYSICAL_ADDRESS)Trb->DmaDesc >>> + );*/ >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + if ((UINT64)(UINTN)Trb->DmaDescPhy > 0x100000000ul) { >>> + // >>> + // The DMA doesn't support 64bit addressing. >>> + // >>> + DmaUnmap (Trb->DmaMap); >>> +/* DevIo->Unmap ( >>> + DevIo, >>> + Trb->DmaMap >>> + );*/ >>> + return EFI_DEVICE_ERROR; >>> + } >>> + >>> + if (DataLen < DW_MMC_BLOCK_SIZE) { >>> + BlkSize =3D DataLen; >>> + BytCnt =3D DataLen; >>> + Remaining =3D DataLen; >>> + } else { >>> + BlkSize =3D DW_MMC_BLOCK_SIZE; >>> + BytCnt =3D DW_MMC_BLOCK_SIZE * Blocks; >>> + Remaining =3D DW_MMC_BLOCK_SIZE * Blocks; >>> + } >>> + >>> + MmioWrite32 (DevBase + DW_MMC_BLKSIZ, BlkSize); >>> + MmioWrite32 (DevBase + DW_MMC_BYTCNT, BytCnt); >>> + DmaDesc =3D Trb->DmaDesc; >>> + for (Index =3D 0; Index < Entries; Index++, DmaDesc++) { >>> + DmaDesc->Des0 =3D DW_MMC_IDMAC_DES0_OWN | >> DW_MMC_IDMAC_DES0_CH | >>> + DW_MMC_IDMAC_DES0_DIC; >>> + DmaDesc->Des1 =3D DW_MMC_IDMAC_DES1_BS1 >> (DWMMC_DMA_BUF_SIZE); >>> + // >>> + // Buffer Address >>> + // >>> + DmaDesc->Des2 =3D (UINT32)((UINTN)Trb->DataPhy + >>> + (DWMMC_DMA_BUF_SIZE * Index)); >>> + // >>> + // Next Descriptor Address >>> + // >>> + DmaDesc->Des3 =3D (UINT32)((UINTN)Trb->DmaDescPhy + >>> + sizeof (DW_MMC_HC_DMA_DESC_LINE) * (Index + 1)); >>> + Remaining =3D Remaining - DWMMC_DMA_BUF_SIZE; >>> + } >>> + // >>> + // First Descriptor >>> + // >>> + Trb->DmaDesc[0].Des0 |=3D DW_MMC_IDMAC_DES0_FS; >>> + // >>> + // Last Descriptor >>> + // >>> + Trb->DmaDesc[Entries - 1].Des0 &=3D ~(DW_MMC_IDMAC_DES0_CH | >>> + DW_MMC_IDMAC_DES0_DIC); >>> + Trb->DmaDesc[Entries - 1].Des0 |=3D DW_MMC_IDMAC_DES0_OWN | >>> + DW_MMC_IDMAC_DES0_LD; >>> + Trb->DmaDesc[Entries - 1].Des1 =3D DW_MMC_IDMAC_DES1_BS1 >> (Remaining + >>> + DWMMC_DMA_BUF_SIZE); >>> + // >>> + // Set the next field of the Last Descriptor >>> + // >>> + Trb->DmaDesc[Entries - 1].Des3 =3D 0; >>> + DmaDescPhy =3D (UINT32)Trb->DmaDescPhy; >>> + >>> + MmioWrite32 (DevBase + DW_MMC_DBADDR, DmaDescPhy); >>> + >>> + ArmDataSynchronizationBarrier (); >>> + ArmInstructionSynchronizationBarrier (); >>> + // >>> + // Clear interrupts >>> + // >>> + Idsts =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_IDSTS, Idsts); >>> + >>> + return Status; >>> +} >>> + >>> +EFI_STATUS >>> +TransferFifo ( >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + UINTN DevBase; >>> + UINT32 Data; >>> + UINT32 Received; >>> + UINT32 Count; >>> + UINT32 Intsts; >>> + UINT32 Sts; >>> + UINT32 FifoCount; >>> + UINT32 Index; /* count with bytes */ >>> + UINT32 Ascending; >>> + UINT32 Descending; >>> + >>> + DevBase =3D Trb->Private->DevBase; >>> + Received =3D 0; >>> + Count =3D 0; >>> + Index =3D 0; >>> + Ascending =3D 0; >>> + Descending =3D ((Trb->DataLen + 3) & ~3) - 4; >>> + do { >>> + Intsts =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); >>> + >>> + if (Trb->DataLen && (Intsts & DW_MMC_INT_TXDR) && !Trb->Read) { >>> + Sts =3D MmioRead32 (DevBase + DW_MMC_STATUS); >>> + >>> + while (!(DW_MMC_STS_FIFO_FULL(Sts)) >>> + && (Received < Trb->DataLen) >>> + && (Intsts & DW_MMC_INT_TXDR)) { >>> + if (Trb->UseBE) { >>> + Data =3D SwapBytes32 (*(UINT32 *)((UINTN)Trb->Data + Descen= ding)); >>> + Descending =3D Descending - 4; >>> + } else { >>> + Data =3D *(UINT32 *)((UINTN)Trb->Data + Ascending); >>> + Ascending +=3D 4; >>> + } >>> + Index +=3D 4; >>> + Received +=3D 4; >>> + >>> + MmioWrite32 (DevBase + DW_MMC_FIFO_START, Data); >>> + >>> + Intsts =3D DW_MMC_INT_TXDR; >>> + MmioWrite32 (DevBase + DW_MMC_RINTSTS, Intsts); >>> + >>> + Intsts =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); >>> + Sts =3D MmioRead32 (DevBase + DW_MMC_STATUS); >>> + } >>> + continue; >>> + } >>> + >>> + if (Trb->DataLen && ((Intsts & DW_MMC_INT_RXDR) || >>> + (Intsts & DW_MMC_INT_DTO)) && Trb->Read) { >>> + Sts =3D MmioRead32 (DevBase + DW_MMC_STATUS); >>> + // >>> + // Convert to bytes >>> + // >>> + FifoCount =3D GET_STS_FIFO_COUNT (Sts) << 2; >>> + if ((FifoCount =3D=3D 0) && (Received < Trb->DataLen)) { >>> + continue; >>> + } >>> + Index =3D 0; >>> + Count =3D (MIN (FifoCount, Trb->DataLen) + 3) & ~3; >>> + while (Index < Count) { >>> + Data =3D MmioRead32 (DevBase + DW_MMC_FIFO_START); >>> + >>> + if (Trb->UseBE) { >>> + *(UINT32 *)((UINTN)Trb->Data + Descending) =3D SwapBytes32 = (Data); >>> + Descending =3D Descending - 4; >>> + } else { >>> + *(UINT32 *)((UINTN)Trb->Data + Ascending) =3D Data; >>> + Ascending +=3D 4; >>> + } >>> + Index +=3D 4; >>> + Received +=3D 4; >>> + } /* while */ >>> + } /* if */ >>> + } while (((Intsts & DW_MMC_INT_CMD_DONE) =3D=3D 0) || (Received < T= rb- >>> DataLen)); >>> + // >>> + // Clear RINTSTS >>> + // >>> + Intsts =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_RINTSTS, Intsts); >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Create a new TRB for the SD/MMC cmd request. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command >>> + to. >>> + @param[in] Packet A pointer to the SD command data structur= e. >>> + @param[in] Event If Event is NULL, blocking I/O is perform= ed. If >>> + Event is not NULL, then nonblocking I/O i= s >>> + performed, and Event will be signaled whe= n the >>> + Packet completes. >>> + >>> + @return Created Trb or NULL. >>> + >>> +**/ >>> +DW_MMC_HC_TRB * >>> +DwMmcCreateTrb ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN UINT8 Slot, >>> + IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, >>> + IN EFI_EVENT Event >>> + ) >>> +{ >>> + DW_MMC_HC_TRB *Trb; >>> + EFI_STATUS Status; >>> + EFI_TPL OldTpl; >>> + EFI_IO_OPERATION_TYPE Flag; >>> + UINTN MapLength; >>> + >>> + Trb =3D AllocateZeroPool (sizeof (DW_MMC_HC_TRB)); >>> + if (Trb =3D=3D NULL) { >>> + return NULL; >>> + } >>> + >>> + Trb->Signature =3D DW_MMC_HC_TRB_SIG; >>> + Trb->Slot =3D Slot; >>> + Trb->BlockSize =3D 0x200; >>> + Trb->Packet =3D Packet; >>> + Trb->Event =3D Event; >>> + Trb->Started =3D FALSE; >>> + Trb->Timeout =3D Packet->Timeout; >>> + Trb->Private =3D Private; >>> + >>> + if ((Packet->InTransferLength !=3D 0) && (Packet->InDataBuffer !=3D= NULL)) { >>> + Trb->Data =3D Packet->InDataBuffer; >>> + Trb->DataLen =3D Packet->InTransferLength; >>> + Trb->Read =3D TRUE; >>> + ZeroMem (Trb->Data, Trb->DataLen); >>> + } else if (Packet->OutTransferLength && (Packet->OutDataBuffer !=3D >> NULL)) { >>> + Trb->Data =3D Packet->OutDataBuffer; >>> + Trb->DataLen =3D Packet->OutTransferLength; >>> + Trb->Read =3D FALSE; >>> + } else if (!Packet->InTransferLength && !Packet->OutTransferLength)= { >>> + Trb->Data =3D NULL; >>> + Trb->DataLen =3D 0; >>> + } else { >>> + goto Error; >>> + } >>> + >>> + if (((Private->Slot[Trb->Slot].CardType =3D=3D EmmcCardType) && >>> + (Packet->SdMmcCmdBlk->CommandIndex =3D=3D >> EMMC_SEND_TUNING_BLOCK)) || >>> + ((Private->Slot[Trb->Slot].CardType =3D=3D SdCardType) && >>> + (Packet->SdMmcCmdBlk->CommandIndex =3D=3D >> SD_SEND_TUNING_BLOCK))) { >>> + Trb->Mode =3D SdMmcPioMode; >>> + } else { >>> + if (Trb->Read) { >>> + Flag =3D EfiBusMasterWrite; >>> + } else { >>> + Flag =3D EfiBusMasterRead; >>> + } >>> + >>> + if (Private->Slot[Trb->Slot].CardType =3D=3D SdCardType) { >>> + Trb->UseFifo =3D TRUE; >>> + } else { >>> + Trb->UseFifo =3D FALSE; >>> + if (Trb->DataLen) { >>> + MapLength =3D Trb->DataLen; >>> + Status =3D DmaMap (Flag, Trb->Data, &MapLength, &Trb->DataPhy= , >> &Trb->DataMap); >>> +/* Status =3D DevIo->Map ( >>> + DevIo, >>> + Flag, >>> + Trb->Data, >>> + &MapLength, >>> + &Trb->DataPhy, >>> + &Trb->DataMap >>> + );*/ >>> + if (EFI_ERROR (Status) || (Trb->DataLen !=3D MapLength)) { >>> + Status =3D EFI_BAD_BUFFER_SIZE; >>> + goto Error; >>> + } >>> + >>> + Status =3D BuildDmaDescTable (Trb); >>> + if (EFI_ERROR (Status)) { >>> + DmaUnmap(Trb->DataMap); >>> + goto Error; >>> + } >>> + Status =3D DwMmcHcStartDma (Private, Trb); >>> + if (EFI_ERROR (Status)) { >>> + DmaUnmap(Trb->DataMap); >>> + goto Error; >>> + } >>> + } >>> + } >>> + } /* TuningBlock */ >>> + >>> + if (Event !=3D NULL) { >>> + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); >>> + InsertTailList (&Private->Queue, &Trb->TrbList); >>> + gBS->RestoreTPL (OldTpl); >>> + } >>> + >>> + return Trb; >>> + >>> +Error: >>> + return NULL; >>> +} >>> + >>> +/** >>> + Free the resource used by the TRB. >>> + >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> +**/ >>> +VOID >>> +DwMmcFreeTrb ( >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + if (Trb->DmaMap !=3D NULL) { >>> + DmaUnmap (Trb->DmaMap); >>> + } >>> + if (Trb->DataMap !=3D NULL) { >>> + DmaUnmap (Trb->DataMap); >>> + } >>> + FreePool (Trb); >>> +} >>> + >>> +/** >>> + Check if the env is ready for execute specified TRB. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The env is ready for TRB execution. >>> + @retval EFI_NOT_READY The env is not ready for TRB execution. >>> + @retval Others Some erros happen. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcCheckTrbEnv ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Wait for the env to be ready for execute specified TRB. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The env is ready for TRB execution. >>> + @retval EFI_TIMEOUT The env is not ready for TRB execution in= time. >>> + @retval Others Some erros happen. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcWaitTrbEnv ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; >>> + UINT64 Timeout; >>> + BOOLEAN InfiniteWait; >>> + >>> + // >>> + // Wait Command Complete Interrupt Status bit in Normal Interrupt >> Status >>> + // Register >>> + // >>> + Packet =3D Trb->Packet; >>> + Timeout =3D Packet->Timeout; >>> + if (Timeout =3D=3D 0) { >>> + InfiniteWait =3D TRUE; >>> + } else { >>> + InfiniteWait =3D FALSE; >>> + } >>> + >>> + while (InfiniteWait || (Timeout > 0)) { >>> + // >>> + // Check Trb execution result by reading Normal Interrupt Status >> register. >>> + // >>> + Status =3D DwMmcCheckTrbEnv (Private, Trb); >>> + if (Status !=3D EFI_NOT_READY) { >>> + return Status; >>> + } >>> + // >>> + // Stall for 1 microsecond. >>> + // >>> + gBS->Stall (1); >>> + >>> + Timeout--; >>> + } >>> + >>> + return EFI_TIMEOUT; >>> +} >>> + >>> +EFI_STATUS >>> +DwEmmcExecTrb ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; >>> + UINTN DevBase; >>> + UINT32 Cmd; >>> + UINT32 MmcStatus; >>> + UINT32 IntStatus; >>> + UINT32 Argument; >>> + UINT32 ErrMask; >>> + UINT32 Timeout; >>> + >>> + Packet =3D Trb->Packet; >>> + DevBase =3D Trb->Private->DevBase; >>> + >>> + ArmDataSynchronizationBarrier (); >>> + ArmInstructionSynchronizationBarrier (); >>> + // >>> + // Wait until MMC is idle >>> + // >>> + do { >>> + MmcStatus =3D MmioRead32 (DevBase + DW_MMC_STATUS); >>> + } while (MmcStatus & DW_MMC_STS_DATA_BUSY); >>> + >>> + IntStatus =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_RINTSTS, IntStatus); >>> + Cmd =3D CMD_INDEX (Packet->SdMmcCmdBlk->CommandIndex); >>> + if ((Packet->SdMmcCmdBlk->CommandType =3D=3D >> SdMmcCommandTypeAc) || >>> + (Packet->SdMmcCmdBlk->CommandType =3D=3D >> SdMmcCommandTypeAdtc)) { >>> + switch (Packet->SdMmcCmdBlk->CommandIndex) { >>> + case EMMC_SET_RELATIVE_ADDR: >>> + Cmd |=3D BIT_CMD_SEND_INIT; >>> + break; >>> + case EMMC_SEND_STATUS: >>> + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE; >>> + break; >>> + case EMMC_STOP_TRANSMISSION: >>> + Cmd |=3D BIT_CMD_STOP_ABORT_CMD; >>> + break; >>> + } >>> + if (Packet->InTransferLength) { >>> + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE | >> BIT_CMD_DATA_EXPECTED | >>> + BIT_CMD_READ; >>> + } else if (Packet->OutTransferLength) { >>> + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE | >> BIT_CMD_DATA_EXPECTED | >>> + BIT_CMD_WRITE; >>> + } >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | >> BIT_CMD_CHECK_RESPONSE_CRC; >>> + } else { >>> + switch (Packet->SdMmcCmdBlk->CommandIndex) { >>> + case EMMC_GO_IDLE_STATE: >>> + Cmd |=3D BIT_CMD_SEND_INIT; >>> + break; >>> + case EMMC_SEND_OP_COND: >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT; >>> + break; >>> + case EMMC_ALL_SEND_CID: >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE | >>> + BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT; >>> + break; >>> + } >>> + } >>> + switch (Packet->SdMmcCmdBlk->ResponseType) { >>> + case SdMmcResponseTypeR2: >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | >> BIT_CMD_CHECK_RESPONSE_CRC | >>> + BIT_CMD_LONG_RESPONSE; >>> + break; >>> + case SdMmcResponseTypeR3: >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT; >>> + break; >>> + } >>> + Cmd |=3D BIT_CMD_USE_HOLD_REG | BIT_CMD_START; >>> + >>> + Argument =3D Packet->SdMmcCmdBlk->CommandArgument; >>> + MmioWrite32 (DevBase + DW_MMC_CMDARG, Argument); >>> + >>> + ArmDataSynchronizationBarrier (); >>> + ArmInstructionSynchronizationBarrier (); >>> + >>> + MmioWrite32 (DevBase + DW_MMC_CMD, Cmd); >>> + ArmDataSynchronizationBarrier (); >>> + ArmInstructionSynchronizationBarrier (); >>> + >>> + ErrMask =3D DW_MMC_INT_EBE | DW_MMC_INT_HLE | >> DW_MMC_INT_RTO | >>> + DW_MMC_INT_RCRC | DW_MMC_INT_RE; >>> + ErrMask |=3D DW_MMC_INT_DCRC | DW_MMC_INT_DRT | >> DW_MMC_INT_SBE; >>> + do { >>> + Timeout =3D 10000; >>> + if (--Timeout =3D=3D 0) { >>> + break; >>> + } >>> + IntStatus =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); >>> + if (IntStatus & ErrMask) { >>> + return EFI_DEVICE_ERROR; >>> + } >>> + if (Trb->DataLen && ((IntStatus & DW_MMC_INT_DTO) =3D=3D 0)) { >>> + // >>> + // Transfer Not Done >>> + // >>> + MicroSecondDelay (10); >>> + continue; >>> + } >>> + MicroSecondDelay (10); >>> + } while (!(IntStatus & DW_MMC_INT_CMD_DONE)); >>> + switch (Packet->SdMmcCmdBlk->ResponseType) { >>> + case SdMmcResponseTypeR1: >>> + case SdMmcResponseTypeR1b: >>> + case SdMmcResponseTypeR3: >>> + case SdMmcResponseTypeR4: >>> + case SdMmcResponseTypeR5: >>> + Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase + >> DW_MMC_RESP0); >>> + break; >>> + case SdMmcResponseTypeR2: >>> + Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase + >> DW_MMC_RESP0); >>> + Packet->SdMmcStatusBlk->Resp1 =3D MmioRead32 (DevBase + >> DW_MMC_RESP1); >>> + Packet->SdMmcStatusBlk->Resp2 =3D MmioRead32 (DevBase + >> DW_MMC_RESP2); >>> + Packet->SdMmcStatusBlk->Resp3 =3D MmioRead32 (DevBase + >> DW_MMC_RESP3); >>> + break; >>> + } >>> + >>> + // >>> + // The workaround on EMMC_SEND_CSD is used to be compatible with >> SDHC. >>> + // >>> + if (Packet->SdMmcCmdBlk->CommandIndex =3D=3D EMMC_SEND_CSD) { >>> + { >>> + UINT32 Buf[4]; >>> + ZeroMem (Buf, sizeof (Buf)); >>> + CopyMem ( >>> + (UINT8 *)Buf, >>> + (UINT8 *)&Packet->SdMmcStatusBlk->Resp0 + 1, >>> + sizeof (Buf) - 1 >>> + ); >>> + CopyMem ( >>> + (UINT8 *)&Packet->SdMmcStatusBlk->Resp0, >>> + (UINT8 *)Buf, >>> + sizeof (Buf) - 1 >>> + ); >>> + } >>> + } >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +EFI_STATUS >>> +DwSdExecTrb ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; >>> + UINTN DevBase; >>> + UINT32 Cmd; >>> + UINT32 MmcStatus; >>> + UINT32 IntStatus; >>> + UINT32 Argument; >>> + UINT32 ErrMask; >>> + UINT32 Timeout; >>> + UINT32 Idsts; >>> + UINT32 BytCnt; >>> + UINT32 BlkSize; >>> + EFI_STATUS Status; >>> + >>> + Packet =3D Trb->Packet; >>> + DevBase =3D Trb->Private->DevBase; >>> + >>> + ArmDataSynchronizationBarrier (); >>> + ArmInstructionSynchronizationBarrier (); >>> + // >>> + // Wait until MMC is idle >>> + // >>> + do { >>> + MmcStatus =3D MmioRead32 (DevBase + DW_MMC_STATUS); >>> + } while (MmcStatus & DW_MMC_STS_DATA_BUSY); >>> + >>> + IntStatus =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_RINTSTS, IntStatus); >>> + Cmd =3D CMD_INDEX (Packet->SdMmcCmdBlk->CommandIndex); >>> + if ((Packet->SdMmcCmdBlk->CommandType =3D=3D >> SdMmcCommandTypeAc) || >>> + (Packet->SdMmcCmdBlk->CommandType =3D=3D >> SdMmcCommandTypeAdtc)) { >>> + switch (Packet->SdMmcCmdBlk->CommandIndex) { >>> + case SD_SET_RELATIVE_ADDR: >>> + Cmd |=3D BIT_CMD_SEND_INIT; >>> + break; >>> + case SD_STOP_TRANSMISSION: >>> + Cmd |=3D BIT_CMD_STOP_ABORT_CMD; >>> + break; >>> + case SD_SEND_SCR: >>> + Trb->UseBE =3D TRUE; >>> + break; >>> + } >>> + if (Packet->InTransferLength) { >>> + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE | >> BIT_CMD_DATA_EXPECTED | >>> + BIT_CMD_READ; >>> + } else if (Packet->OutTransferLength) { >>> + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE | >> BIT_CMD_DATA_EXPECTED | >>> + BIT_CMD_WRITE; >>> + } >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | >> BIT_CMD_CHECK_RESPONSE_CRC | >>> + BIT_CMD_SEND_AUTO_STOP; >>> + } else { >>> + switch (Packet->SdMmcCmdBlk->CommandIndex) { >>> + case SD_GO_IDLE_STATE: >>> + Cmd |=3D BIT_CMD_SEND_INIT; >>> + break; >>> + } >>> + } >>> + switch (Packet->SdMmcCmdBlk->ResponseType) { >>> + case SdMmcResponseTypeR2: >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | >> BIT_CMD_CHECK_RESPONSE_CRC | >>> + BIT_CMD_LONG_RESPONSE; >>> + break; >>> + case SdMmcResponseTypeR3: >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT; >>> + break; >>> + case SdMmcResponseTypeR1b: >>> + case SdMmcResponseTypeR4: >>> + case SdMmcResponseTypeR6: >>> + case SdMmcResponseTypeR7: >>> + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | >> BIT_CMD_CHECK_RESPONSE_CRC; >>> + break; >>> + } >>> + Cmd |=3D BIT_CMD_USE_HOLD_REG | BIT_CMD_START; >>> + >>> + if (Trb->UseFifo =3D=3D TRUE) { >>> + BytCnt =3D Trb->Read ? Packet->InTransferLength : Packet- >>> OutTransferLength; >>> + MmioWrite32 (DevBase + DW_MMC_BYTCNT, BytCnt); >>> + if (Trb->Read) { >>> + if (Packet->InTransferLength > DW_MMC_BLOCK_SIZE) { >>> + BlkSize =3D DW_MMC_BLOCK_SIZE; >>> + } else { >>> + BlkSize =3D Packet->InTransferLength; >>> + } >>> + } >>> + else { >>> + if (Packet->OutTransferLength > DW_MMC_BLOCK_SIZE) { >>> + BlkSize =3D DW_MMC_BLOCK_SIZE; >>> + } else { >>> + BlkSize =3D Packet->OutTransferLength; >>> + } >>> + } >>> + >>> + MmioWrite32 (DevBase + DW_MMC_BLKSIZ, BlkSize); >>> + } >>> + >>> + Argument =3D Packet->SdMmcCmdBlk->CommandArgument; >>> + MmioWrite32 (DevBase + DW_MMC_CMDARG, Argument); >>> + ArmDataSynchronizationBarrier (); >>> + ArmInstructionSynchronizationBarrier (); >>> + MmioWrite32 (DevBase + DW_MMC_CMD, Cmd); >>> + ArmDataSynchronizationBarrier (); >>> + ArmInstructionSynchronizationBarrier (); >>> + >>> + ErrMask =3D DW_MMC_INT_EBE | DW_MMC_INT_HLE | >> DW_MMC_INT_RTO | >>> + DW_MMC_INT_RCRC | DW_MMC_INT_RE; >>> + ErrMask |=3D DW_MMC_INT_DRT | DW_MMC_INT_SBE; >>> + if (Packet->InTransferLength || Packet->OutTransferLength) { >>> + ErrMask |=3D DW_MMC_INT_DCRC; >>> + } >>> + if (Trb->UseFifo =3D=3D TRUE) { >>> + Status =3D TransferFifo (Trb); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + } else { >>> + Timeout =3D 10000; >>> + do { >>> + if (--Timeout =3D=3D 0) { >>> + break; >>> + } >>> + IntStatus =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); >>> + if (IntStatus & ErrMask) { >>> + return EFI_DEVICE_ERROR; >>> + } >>> + if (Trb->DataLen && ((IntStatus & DW_MMC_INT_DTO) =3D=3D 0)) { >>> + // >>> + // Transfer not Done >>> + // >>> + MicroSecondDelay (10); >>> + continue; >>> + } >>> + MicroSecondDelay (10); >>> + } while (!(IntStatus & DW_MMC_INT_CMD_DONE)); >>> + if (Packet->InTransferLength) { >>> + do { >>> + Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS); >>> + } while ((Idsts & DW_MMC_IDSTS_RI) =3D=3D 0); >>> + Status =3D DwMmcHcStopDma (Private, Trb); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + } else if (Packet->OutTransferLength) { >>> + do { >>> + Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS); >>> + } while ((Idsts & DW_MMC_IDSTS_TI) =3D=3D 0); >>> + Status =3D DwMmcHcStopDma (Private, Trb); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + } /* Packet->InTransferLength */ >>> + } /* UseFifo */ >>> + switch (Packet->SdMmcCmdBlk->ResponseType) { >>> + case SdMmcResponseTypeR1: >>> + case SdMmcResponseTypeR1b: >>> + case SdMmcResponseTypeR3: >>> + case SdMmcResponseTypeR4: >>> + case SdMmcResponseTypeR5: >>> + case SdMmcResponseTypeR6: >>> + case SdMmcResponseTypeR7: >>> + Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase + >> DW_MMC_RESP0); >>> + break; >>> + case SdMmcResponseTypeR2: >>> + Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase + >> DW_MMC_RESP0); >>> + Packet->SdMmcStatusBlk->Resp1 =3D MmioRead32 (DevBase + >> DW_MMC_RESP1); >>> + Packet->SdMmcStatusBlk->Resp2 =3D MmioRead32 (DevBase + >> DW_MMC_RESP2); >>> + Packet->SdMmcStatusBlk->Resp3 =3D MmioRead32 (DevBase + >> DW_MMC_RESP3); >>> + break; >>> + } >>> + >>> + // >>> + // The workaround on SD_SEND_CSD is used to be compatible with >> SDHC. >>> + // >>> + if (Packet->SdMmcCmdBlk->CommandIndex =3D=3D SD_SEND_CSD) { >>> + { >>> + UINT32 Buf[4]; >>> + ZeroMem (Buf, sizeof (Buf)); >>> + CopyMem ( >>> + (UINT8 *)Buf, >>> + (UINT8 *)&Packet->SdMmcStatusBlk->Resp0 + 1, >>> + sizeof (Buf) - 1 >>> + ); >>> + CopyMem ( >>> + (UINT8 *)&Packet->SdMmcStatusBlk->Resp0, >>> + (UINT8 *)Buf, >>> + sizeof (Buf) - 1 >>> + ); >>> + } >>> + } >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Execute the specified TRB. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The TRB is sent to host controller succes= sfully. >>> + @retval Others Some erros happen when sending this reque= st to >> the >>> + host controller. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcExecTrb ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + EFI_STATUS Status =3D EFI_SUCCESS; >>> + UINT32 Slot; >>> + >>> + Slot =3D Trb->Slot; >>> + if (Private->Slot[Slot].CardType =3D=3D EmmcCardType) { >>> + Status =3D DwEmmcExecTrb (Private, Trb); >>> + } else if (Private->Slot[Slot].CardType =3D=3D SdCardType) { >>> + Status =3D DwSdExecTrb (Private, Trb); >>> + } else { >>> + ASSERT (0); >>> + } >>> + return Status; >>> +} >>> + >>> +/** >>> + Check the TRB execution result. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The TRB is executed successfully. >>> + @retval EFI_NOT_READY The TRB is not completed for execution. >>> + @retval Others Some erros happen when executing this req= uest. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcCheckTrbResult ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; >>> + UINT32 Idsts; >>> + UINTN DevBase; >>> + >>> + DevBase =3D Private->DevBase; >>> + Packet =3D Trb->Packet; >>> + if (Trb->UseFifo =3D=3D TRUE) { >>> + return EFI_SUCCESS; >>> + } >>> + if (Packet->InTransferLength) { >>> + do { >>> + Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS); >>> + } while ((Idsts & BIT1) =3D=3D 0); >>> + } else if (Packet->OutTransferLength) { >>> + do { >>> + Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS); >>> + } while ((Idsts & BIT0) =3D=3D 0); >>> + } else { >>> + return EFI_SUCCESS; >>> + } >>> + Idsts =3D ~0; >>> + MmioWrite32 (DevBase + DW_MMC_IDSTS, Idsts); >>> + >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Wait for the TRB execution result. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance= . >>> + >>> + @retval EFI_SUCCESS The TRB is executed successfully. >>> + @retval Others Some erros happen when executing this req= uest. >>> + >>> +**/ >>> +EFI_STATUS >>> +DwMmcWaitTrbResult ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private, >>> + IN DW_MMC_HC_TRB *Trb >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; >>> + UINT64 Timeout; >>> + BOOLEAN InfiniteWait; >>> + >>> + Packet =3D Trb->Packet; >>> + // >>> + // Wait Command Complete Interrupt Status bit in Normal Interrupt >> Status >>> + // Register >>> + // >>> + Timeout =3D Packet->Timeout; >>> + if (Timeout =3D=3D 0) { >>> + InfiniteWait =3D TRUE; >>> + } else { >>> + InfiniteWait =3D FALSE; >>> + } >>> + >>> + while (InfiniteWait || (Timeout > 0)) { >>> + // >>> + // Check Trb execution result by reading Normal Interrupt Status >> register. >>> + // >>> + Status =3D DwMmcCheckTrbResult (Private, Trb); >>> + if (Status !=3D EFI_NOT_READY) { >>> + return Status; >>> + } >>> + // >>> + // Stall for 1 microsecond. >>> + // >>> + gBS->Stall (1); >>> + >>> + Timeout--; >>> + } >>> + >>> + return EFI_TIMEOUT; >>> +} >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c >>> new file mode 100644 >>> index 000000000000..b7a8688c4d2e >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c >>> @@ -0,0 +1,1042 @@ >>> +/** @file >>> + This file provides some helper functions which are specific for EMM= C >> device. >>> + >>> + Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<= BR> >>> + Copyright (c) 2018, Linaro. All rights reserved.
>>> + >>> + This program and the accompanying materials are licensed and made >> available >>> + under the terms and conditions of the BSD License which accompanies >> this >>> + distribution. The full text of the license may be found at >>> + http://opensource.org/licenses/bsd-license.php >>> + >>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" >> BASIS, >>> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER >> EXPRESS OR IMPLIED. >>> + >>> +**/ >>> + >>> +#include >>> + >>> +#include >>> +#include >>> +#include >>> + >>> +#include "DwMmcHcDxe.h" >>> + >>> +#define EMMC_GET_STATE(x) (((x) >> 9) & 0xf) >>> +#define EMMC_STATE_IDLE 0 >>> +#define EMMC_STATE_READY 1 >>> +#define EMMC_STATE_IDENT 2 >>> +#define EMMC_STATE_STBY 3 >>> +#define EMMC_STATE_TRAN 4 >>> +#define EMMC_STATE_DATA 5 >>> +#define EMMC_STATE_RCV 6 >>> +#define EMMC_STATE_PRG 7 >>> +#define EMMC_STATE_DIS 8 >>> +#define EMMC_STATE_BTST 9 >>> +#define EMMC_STATE_SLP 10 >>> + >>> +#define EMMC_CMD1_CAPACITY_LESS_THAN_2GB 0x00FF8080 // >> Capacity <=3D 2GB, byte addressing used >>> +#define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // >> Capacity > 2GB, 512-byte sector addressing used >>> + >>> +/** >>> + Send command GO_IDLE_STATE (CMD0 with argument of 0x00000000) to >> the device to >>> + make it go to Idle State. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Slot The slot number of the SD card to send th= e >> command >>> + to. >>> + >>> + @retval EFI_SUCCESS The EMMC device is reset correctly. >>> + @retval Others The device reset fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcReset ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_GO_IDLE_STATE; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBc; >>> + SdMmcCmdBlk.ResponseType =3D 0; >>> + SdMmcCmdBlk.CommandArgument =3D 0; >>> + >>> + gBS->Stall (1000); >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_OP_COND to the EMMC device to get the data of >> the OCR >>> + register. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in, out] Argument On input, the argument of SEND_OP_COND >> is to send >>> + to the device. >>> + On output, the argument is the value of O= CR >>> + register. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcGetOcr ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN OUT UINT32 *Argument >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_OP_COND; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR3; >>> + SdMmcCmdBlk.CommandArgument =3D *Argument; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (!EFI_ERROR (Status)) { >>> + // >>> + // For details, refer to SD Host Controller Simplified Spec 3.0 T= able 2-12. >>> + // >>> + *Argument =3D SdMmcStatusBlk.Resp0; >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Broadcast command ALL_SEND_CID to the bus to ask all the EMMC >> devices to send >>> + the data of their CID registers. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcGetAllCid ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_ALL_SEND_CID; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2; >>> + SdMmcCmdBlk.CommandArgument =3D 0; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SET_RELATIVE_ADDR to the EMMC device to assign a >> Relative device >>> + Address (RCA). >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address to be assigne= d. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSetRca ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_SET_RELATIVE_ADDR; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_CSD to the EMMC device to get the data of the >> CSD register. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detai= ls. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of selected d= evice. >>> + @param[out] Csd The buffer to store the content of the CS= D >> register. >>> + Note the caller should ignore the lowest = byte of >>> + this buffer as the content of this byte i= s >>> + meaningless even if the operation succeed= s. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcGetCsd ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + OUT EMMC_CSD *Csd >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_CSD; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (!EFI_ERROR (Status)) { >>> + // >>> + // Copy 128bit data for CSD structure. >>> + // >>> + CopyMem ((VOID *)Csd + 1, &SdMmcStatusBlk.Resp0, sizeof >> (EMMC_CSD) - 1); >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SELECT_DESELECT_CARD to the EMMC device to >> select/deselect it. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detai= ls. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of selected d= evice. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSelect ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_SELECT_DESELECT_CARD; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_EXT_CSD to the EMMC device to get the data of >> the EXT_CSD >>> + register. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detai= ls. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[out] ExtCsd The buffer to store the content of the EX= T_CSD >>> + register. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcGetExtCsd ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + OUT EMMC_EXT_CSD *ExtCsd >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_EXT_CSD; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D 0x00000000; >>> + >>> + Packet.InDataBuffer =3D ExtCsd; >>> + Packet.InTransferLength =3D sizeof (EMMC_EXT_CSD); >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SWITCH to the EMMC device to switch the mode of >> operation of the >>> + selected Device or modifies the EXT_CSD registers. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detai= ls. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Access The access mode of SWTICH command. >>> + @param[in] Index The offset of the field to be access. >>> + @param[in] Value The value to be set to the specified fiel= d of >>> + EXT_CSD register. >>> + @param[in] CmdSet The value of CmdSet field of EXT_CSD regi= ster. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSwitch ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT8 Access, >>> + IN UINT8 Index, >>> + IN UINT8 Value, >>> + IN UINT8 CmdSet >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_SWITCH; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1b; >>> + SdMmcCmdBlk.CommandArgument =3D (Access << 24) | (Index << 16) | \ >>> + (Value << 8) | CmdSet; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_STATUS to the addressed EMMC device to get its >> status >>> + register. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detai= ls. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of addressed = device. >>> + @param[out] DevStatus The returned device status. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSendStatus ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + OUT UINT32 *DevStatus >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_STATUS; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (!EFI_ERROR (Status)) { >>> + *DevStatus =3D SdMmcStatusBlk.Resp0; >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_TUNING_BLOCK to the EMMC device for HS200 >> optimal sampling >>> + point detection. >>> + >>> + It may be sent up to 40 times until the host finishes the tuning >> procedure. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 for detail= s. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] BusWidth The bus width to work. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSendTuningBlk ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT8 BusWidth >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + UINT8 TuningBlock[128]; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_TUNING_BLOCK; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D 0; >>> + >>> + Packet.InDataBuffer =3D TuningBlock; >>> + if (BusWidth =3D=3D 8) { >>> + Packet.InTransferLength =3D sizeof (TuningBlock); >>> + } else { >>> + Packet.InTransferLength =3D 64; >>> + } >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Tunning the clock to get HS200 optimal sampling point. >>> + >>> + Command SEND_TUNING_BLOCK may be sent up to 40 times until the >> host finishes >>> + the tuning procedure. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8. >>> + >>> + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL >> instance. >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] BusWidth The bus width to work. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcTuningClkForHs200 ( >>> + IN UINTN DevBase, >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT8 BusWidth >>> + ) >>> +{ >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Switch the bus width to specified width. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.9. >>> + >>> + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL >> instance. >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address to be assigne= d. >>> + @param[in] IsDdr If TRUE, use dual data rate data simpling= method. >>> + Otherwise use single data rate data simpl= ing method. >>> + @param[in] BusWidth The bus width to be set, it could be 4 or= 8. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSwitchBusWidth ( >>> + IN UINTN DevBase, >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + IN BOOLEAN IsDdr, >>> + IN UINT8 BusWidth >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 Access; >>> + UINT8 Index; >>> + UINT8 Value; >>> + UINT8 CmdSet; >>> + UINT32 DevStatus; >>> + >>> + // >>> + // Write Byte, the Value field is written into the byte pointed by = Index. >>> + // >>> + Access =3D 0x03; >>> + Index =3D OFFSET_OF (EMMC_EXT_CSD, BusWidth); >>> + if (BusWidth =3D=3D 1) { >>> + Value =3D 0; >>> + } else { >>> + if (BusWidth =3D=3D 4) { >>> + Value =3D 1; >>> + } else if (BusWidth =3D=3D 8) { >>> + Value =3D 2; >>> + } else { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if (IsDdr) { >>> + Value +=3D 4; >>> + } >>> + } >>> + >>> + CmdSet =3D 0; >>> + Status =3D EmmcSwitch (PassThru, Access, Index, Value, CmdSet); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "EmmcSwitchBusWidth: Switch to bus width %d fails with %r\n", >>> + BusWidth, >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + do { >>> + Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "EmmcSwitchBusWidth: Send status fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + // >>> + // Check the switch operation is really successful or not. >>> + // >>> + } while ((DevStatus & 0xf) =3D=3D EMMC_STATE_PRG); >>> + >>> + Status =3D DwMmcHcSetBusWidth (DevBase, IsDdr, BusWidth); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Switch the clock frequency to the specified value. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6. >>> + >>> + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL >> instance. >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address to be assigne= d. >>> + @param[in] HsTiming The value to be written to HS_TIMING fiel= d of >>> + EXT_CSD register. >>> + @param[in] ClockFreq The max clock frequency to be set, the un= it is >> MHz. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSwitchClockFreq ( >>> + IN UINTN DevBase, >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + IN UINT8 HsTiming, >>> + IN UINT32 ClockFreq >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 Access; >>> + UINT8 Index; >>> + UINT8 Value; >>> + UINT8 CmdSet; >>> + UINT32 DevStatus; >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); >>> + // >>> + // Write Byte, the Value field is written into the byte pointed by = Index. >>> + // >>> + Access =3D 0x03; >>> + Index =3D OFFSET_OF (EMMC_EXT_CSD, HsTiming); >>> + Value =3D HsTiming; >>> + CmdSet =3D 0; >>> + >>> + Status =3D EmmcSwitch (PassThru, Access, Index, Value, CmdSet); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "EmmcSwitchClockFreq: Switch to hstiming %d fails with %r\n", >>> + HsTiming, >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "EmmcSwitchClockFreq: Send status fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + // >>> + // Check the switch operation is really successful or not. >>> + // >>> + if ((DevStatus & BIT7) !=3D 0) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "EmmcSwitchClockFreq: The switch operation fails as DevStatus >> 0x%08x\n", >>> + DevStatus >>> + )); >>> + return EFI_DEVICE_ERROR; >>> + } >>> + // >>> + // Convert the clock freq unit from MHz to KHz. >>> + // >>> + Status =3D DwMmcHcClockSupply (DevBase, ClockFreq * 1000, Private- >>> Capability[0]); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Switch to the High Speed timing according to request. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8. >>> + >>> + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL >> instance. >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address to be assigne= d. >>> + @param[in] ClockFreq The max clock frequency to be set. >>> + @param[in] IsDdr If TRUE, use dual data rate data simpling= method. >>> + Otherwise use single data rate data simpl= ing method. >>> + @param[in] BusWidth The bus width to be set, it could be 4 or= 8. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSwitchToHighSpeed ( >>> + IN UINTN DevBase, >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + IN UINT32 ClockFreq, >>> + IN BOOLEAN IsDdr, >>> + IN UINT8 BusWidth >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 HsTiming; >>> + >>> + HsTiming =3D 1; >>> + Status =3D EmmcSwitchClockFreq (DevBase, PassThru, Rca, HsTiming, >> ClockFreq); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + Status =3D EmmcSwitchBusWidth (DevBase, PassThru, Rca, IsDdr, >> BusWidth); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Switch to the HS200 timing according to request. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8. >>> + >>> + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL >> instance. >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address to be assigne= d. >>> + @param[in] ClockFreq The max clock frequency to be set. >>> + @param[in] BusWidth The bus width to be set, it could be 4 or= 8. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSwitchToHS200 ( >>> + IN UINTN DevBase, >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + IN UINT32 ClockFreq, >>> + IN UINT8 BusWidth >>> + ) >>> +{ >>> + return EFI_SUCCESS; >>> +} >>> + >>> +/** >>> + Switch the high speed timing according to request. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8. >>> + >>> + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL >> instance. >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address to be assigne= d. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcSetBusMode ( >>> + IN UINTN DevBase, >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + EMMC_CSD Csd; >>> + EMMC_EXT_CSD ExtCsd; >>> + UINT8 HsTiming; >>> + BOOLEAN IsDdr; >>> + UINT32 DevStatus; >>> + UINT32 ClockFreq; >>> + UINT8 BusWidth; >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); >>> + ASSERT (Private->Capability[0].BaseClkFreq !=3D 0); >>> + >>> + Status =3D EmmcGetCsd (PassThru, Rca, &Csd); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetCsd fails with %r\n", >> Status)); >>> + return Status; >>> + } >>> + >>> + Status =3D EmmcSelect (PassThru, Rca); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Select fails with %r\n", >> Status)); >>> + return Status; >>> + } >>> + >>> + do { >>> + Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "EmmcSetBusMode: Get Status fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + } while (EMMC_GET_STATE (DevStatus) !=3D EMMC_STATE_TRAN); >>> + >>> + BusWidth =3D 1; >>> + Status =3D EmmcSwitchBusWidth (DevBase, PassThru, Rca, FALSE, >> BusWidth); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + BusWidth =3D Private->Capability[0].BusWidth; >>> + // >>> + // Get Deivce_Type from EXT_CSD register. >>> + // >>> + Status =3D EmmcGetExtCsd (PassThru, &ExtCsd); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails with >> %r\n", Status)); >>> + return Status; >>> + } >>> + >>> + // >>> + // Calculate supported bus speed/bus width/clock frequency. >>> + // >>> + HsTiming =3D 0; >>> + IsDdr =3D FALSE; >>> + ClockFreq =3D 0; >>> + if (((ExtCsd.DeviceType & (BIT4 | BIT5)) !=3D 0) && >>> + (Private->Capability[0].Sdr104 !=3D 0)) { >>> + HsTiming =3D 2; >>> + IsDdr =3D FALSE; >>> + ClockFreq =3D 200; >>> + } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) !=3D 0) && >>> + (Private->Capability[0].Ddr50 !=3D 0)) { >>> + HsTiming =3D 1; >>> + IsDdr =3D TRUE; >>> + ClockFreq =3D 52; >>> + } else if (((ExtCsd.DeviceType & BIT1) !=3D 0) && >>> + (Private->Capability[0].HighSpeed !=3D 0)) { >>> + HsTiming =3D 1; >>> + IsDdr =3D FALSE; >>> + ClockFreq =3D 52; >>> + } else if (((ExtCsd.DeviceType & BIT0) !=3D 0) && >>> + (Private->Capability[0].HighSpeed !=3D 0)) { >>> + HsTiming =3D 1; >>> + IsDdr =3D FALSE; >>> + ClockFreq =3D 26; >>> + } >>> + >>> + if ((ClockFreq =3D=3D 0) || (HsTiming =3D=3D 0)) { >>> + // >>> + // Continue using default setting. >>> + // >>> + return EFI_SUCCESS; >>> + } >>> + >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr >> %a\n", >>> + HsTiming, >>> + ClockFreq, >>> + BusWidth, >>> + IsDdr ? "TRUE" : "FALSE" >>> + )); >>> + >>> + if (HsTiming =3D=3D 2) { >>> + // >>> + // Execute HS200 timing switch procedure >>> + // >>> + Status =3D EmmcSwitchToHS200 (DevBase, PassThru, Rca, ClockFreq, >> BusWidth); >>> + } else { >>> + // >>> + // Execute High Speed timing switch procedure >>> + // >>> + Status =3D EmmcSwitchToHighSpeed ( >>> + DevBase, >>> + PassThru, >>> + Rca, >>> + ClockFreq, >>> + IsDdr, >>> + BusWidth >>> + ); >>> + } >>> + >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "EmmcSetBusMode: Switch to %a %r\n", >>> + (HsTiming =3D=3D 3) ? "HS400" : ((HsTiming =3D=3D 2) ? "HS200" : = "HighSpeed"), >>> + Status >>> + )); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Execute EMMC device identification procedure. >>> + >>> + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. >>> + >>> + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA >> instance. >>> + >>> + @retval EFI_SUCCESS There is a EMMC card. >>> + @retval Others There is not a EMMC card. >>> + >>> +**/ >>> +EFI_STATUS >>> +EmmcIdentification ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINTN DevBase; >>> + EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; >>> + UINT32 Ocr; >>> + UINT16 Rca; >>> + UINT32 DevStatus; >>> + UINT32 Timeout; >>> + >>> + DevBase =3D Private->DevBase; >>> + PassThru =3D &Private->PassThru; >>> + >>> + Status =3D EmmcReset (PassThru); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "EmmcIdentification: Executing Cmd0 fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + Timeout =3D 100; >>> + do { >>> + Ocr =3D EMMC_CMD1_CAPACITY_GREATER_THAN_2GB; >>> + Status =3D EmmcGetOcr (PassThru, &Ocr); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "EmmcIdentification: Executing Cmd1 fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + if (--Timeout <=3D 0) { >>> + return EFI_DEVICE_ERROR; >>> + } >>> + MicroSecondDelay (100); >>> + } while ((Ocr & BIT31) =3D=3D 0); >>> + >>> + Status =3D EmmcGetAllCid (PassThru); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "EmmcIdentification: Executing Cmd2 fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + // >>> + // valid RCA starts from 1. >>> + // Here we takes a simple formula to calculate the RCA. >>> + // Don't support multiple devices on the slot, that is >>> + // shared bus slot feature. >>> + // >>> + Rca =3D 1; >>> + Status =3D EmmcSetRca (PassThru, Rca); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "EmmcIdentification: Executing Cmd3 fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + // >>> + // Enter Data Tranfer Mode. >>> + // >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "EmmcIdentification: Found a EMMC device at RCA [%d]\n", >>> + Rca >>> + )); >>> + Private->Slot[0].CardType =3D EmmcCardType; >>> + >>> + Status =3D EmmcSetBusMode (DevBase, PassThru, Rca); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + // >>> + // Exit DATA Mode. >>> + // >>> + do { >>> + Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "EmmcSwitchBusWidth: Send status fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + } while ((DevStatus & 0xf) =3D=3D EMMC_STATE_DATA); >>> + >>> + return Status; >>> +} >>> diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c >> b/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c >>> new file mode 100644 >>> index 000000000000..63246637b6dd >>> --- /dev/null >>> +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c >>> @@ -0,0 +1,1105 @@ >>> +/** @file >>> + This file provides some helper functions which are specific for SD = card >>> + device. >>> + >>> + Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<= BR> >>> + Copyright (c) 2018, Linaro. All rights reserved.
>>> + >>> + This program and the accompanying materials are licensed and made >> available >>> + under the terms and conditions of the BSD License which accompanies >> this >>> + distribution. The full text of the license may be found at >>> + http://opensource.org/licenses/bsd-license.php >>> + >>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" >> BASIS, >>> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER >> EXPRESS OR IMPLIED. >>> + >>> +**/ >>> + >>> +#include >>> + >>> +#include >>> +#include >>> + >>> +#include "DwMmcHcDxe.h" >>> + >>> +/** >>> + Send command GO_IDLE_STATE to the device to make it go to Idle Stat= e. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + >>> + @retval EFI_SUCCESS The SD device is reset correctly. >>> + @retval Others The device reset fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardReset ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_GO_IDLE_STATE; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBc; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + //Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_IF_COND to the device to inquiry the SD Memory >> Card >>> + interface condition. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] SupplyVoltage The supplied voltage by the host. >>> + @param[in] CheckPattern The check pattern to be sent to the devic= e. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardVoltageCheck ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT8 SupplyVoltage, >>> + IN UINT8 CheckPattern >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SEND_IF_COND; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR7; >>> + SdMmcCmdBlk.CommandArgument =3D (SupplyVoltage << 8) | >> CheckPattern; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + if (!EFI_ERROR (Status)) { >>> + if (SdMmcStatusBlk.Resp0 !=3D SdMmcCmdBlk.CommandArgument) { >>> + return EFI_DEVICE_ERROR; >>> + } >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SDIO_SEND_OP_COND to the device to see whether it is >> SDIO device. >>> + >>> + Refer to SDIO Simplified Spec 3 Section 3.2 for details. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] VoltageWindow The supply voltage window. >>> + @param[in] S18R The boolean to show if it should switch t= o 1.8v. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdioSendOpCond ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT32 VoltageWindow, >>> + IN BOOLEAN S18R >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + UINT32 Switch; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SDIO_SEND_OP_COND; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR4; >>> + >>> + Switch =3D S18R ? BIT24 : 0; >>> + >>> + SdMmcCmdBlk.CommandArgument =3D (VoltageWindow & 0xFFFFFF) | >> Switch; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SD_SEND_OP_COND to the device to see whether it is >> SDIO device. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of addressed= device. >>> + @param[in] VoltageWindow The supply voltage window. >>> + @param[in] S18R The boolean to show if it should switch = to 1.8v. >>> + @param[in] Xpc The boolean to show if it should provide= 0.36w >>> + power control. >>> + @param[in] Hcs The boolean to show if it support host c= apacity >>> + info. >>> + @param[out] Ocr The buffer to store returned OCR registe= r value. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSendOpCond ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + IN UINT32 VoltageWindow, >>> + IN BOOLEAN S18R, >>> + IN BOOLEAN Xpc, >>> + IN BOOLEAN Hcs, >>> + OUT UINT32 *Ocr >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + UINT32 Switch; >>> + UINT32 MaxPower; >>> + UINT32 HostCapacity; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_APP_CMD; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SEND_OP_COND; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR3; >>> + >>> + Switch =3D S18R ? BIT24 : 0; >>> + MaxPower =3D Xpc ? BIT28 : 0; >>> + HostCapacity =3D Hcs ? BIT30 : 0; >>> + >>> + SdMmcCmdBlk.CommandArgument =3D (VoltageWindow & 0xFFFFFF) | >> Switch | \ >>> + MaxPower | HostCapacity; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (!EFI_ERROR (Status)) { >>> + *Ocr =3D SdMmcStatusBlk.Resp0; >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Broadcast command ALL_SEND_CID to the bus to ask all the SD devices >> to send >>> + the data of their CID registers. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardAllSendCid ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_ALL_SEND_CID; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SET_RELATIVE_ADDR to the SD device to assign a >> Relative device >>> + Address (RCA). >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[out] Rca The relative device address to assign. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSetRca ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + OUT UINT16 *Rca >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SET_RELATIVE_ADDR; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR6; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (!EFI_ERROR (Status)) { >>> + *Rca =3D (UINT16)(SdMmcStatusBlk.Resp0 >> 16); >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_CSD to the SD device to get the data of the CSD >> register. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of selected d= evice. >>> + @param[out] Csd The buffer to store the content of the CS= D >> register. >>> + Note the caller should ignore the lowest = byte of >>> + this buffer as the content of this byte i= s meaning- >>> + less even if the operation succeeds. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardGetCsd ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + OUT SD_CSD *Csd >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SEND_CSD; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (!EFI_ERROR (Status)) { >>> + CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof >> (SD_CSD) - 1); >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_CSD to the SD device to get the data of the CSD >> register. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of selected d= evice. >>> + @param[out] Scr The buffer to store the content of the SC= R >> register. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardGetScr ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + OUT SD_SCR *Scr >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_APP_CMD; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SEND_SCR; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + >>> + Packet.InDataBuffer =3D Scr; >>> + Packet.InTransferLength =3D sizeof (SD_SCR); >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SELECT_DESELECT_CARD to the SD device to >> select/deselect it. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of selected d= evice. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSelect ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SELECT_DESELECT_CARD; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + if (Rca !=3D 0) { >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1b; >>> + } >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command VOLTAGE_SWITCH to the SD device to switch the voltage >> of the >>> + device. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardVoltageSwitch ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_VOLTAGE_SWITCH; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D 0; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SET_BUS_WIDTH to the SD device to set the bus width. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of addressed = device. >>> + @param[in] BusWidth The bus width to be set, it could be 1 or= 4. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSetBusWidth ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + IN UINT8 BusWidth >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + UINT8 Value; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_APP_CMD; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SET_BUS_WIDTH; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + >>> + if (BusWidth =3D=3D 1) { >>> + Value =3D 0; >>> + } else if (BusWidth =3D=3D 4) { >>> + Value =3D 2; >>> + } else { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + SdMmcCmdBlk.CommandArgument =3D Value & 0x3; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SWITCH_FUNC to the SD device to check switchable >> function or >>> + switch card function. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] AccessMode The value for access mode group. >>> + @param[in] CommandSystem The value for command set group. >>> + @param[in] DriveStrength The value for drive length group. >>> + @param[in] PowerLimit The value for power limit group. >>> + @param[in] Mode Switch or check function. >>> + @param[out] SwitchResp The return switch function status. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSwitch ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT8 AccessMode, >>> + IN UINT8 CommandSystem, >>> + IN UINT8 DriveStrength, >>> + IN UINT8 PowerLimit, >>> + IN BOOLEAN Mode, >>> + OUT UINT8 *SwitchResp >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + UINT32 ModeValue; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SWITCH_FUNC; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + >>> + ModeValue =3D Mode ? BIT31 : 0; >>> + SdMmcCmdBlk.CommandArgument =3D (AccessMode & 0xF) | \ >>> + ((PowerLimit & 0xF) << 4) | \ >>> + ((DriveStrength & 0xF) << 8) | \ >>> + ((DriveStrength & 0xF) << 12) | \ >>> + ModeValue; >>> + >>> + Packet.InDataBuffer =3D SwitchResp; >>> + Packet.InTransferLength =3D 64; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_STATUS to the addressed SD device to get its >> status >>> + register. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address of addressed = device. >>> + @param[out] DevStatus The returned device status. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSendStatus ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + OUT UINT32 *DevStatus >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SEND_STATUS; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + if (!EFI_ERROR (Status)) { >>> + *DevStatus =3D SdMmcStatusBlk.Resp0; >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Send command SEND_TUNING_BLOCK to the SD device for HS200 >> optimal sampling >>> + point detection. >>> + >>> + It may be sent up to 40 times until the host finishes the tuning >> procedure. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSendTuningBlk ( >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru >>> + ) >>> +{ >>> + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; >>> + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; >>> + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; >>> + EFI_STATUS Status; >>> + UINT8 TuningBlock[64]; >>> + >>> + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); >>> + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); >>> + ZeroMem (&Packet, sizeof (Packet)); >>> + >>> + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; >>> + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; >>> + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; >>> + >>> + SdMmcCmdBlk.CommandIndex =3D SD_SEND_TUNING_BLOCK; >>> + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; >>> + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; >>> + SdMmcCmdBlk.CommandArgument =3D 0; >>> + >>> + Packet.InDataBuffer =3D TuningBlock; >>> + Packet.InTransferLength =3D sizeof (TuningBlock); >>> + >>> + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Switch the bus width to specified width. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and >>> + SD Host Controller Simplified Spec 3.0 section Figure 3-7 for detai= ls. >>> + >>> + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL inst= ance. >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address to be assigne= d. >>> + @param[in] BusWidth The bus width to be set, it could be 4 or= 8. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSwitchBusWidth ( >>> + IN UINTN DevBase, >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + IN BOOLEAN IsDdr, >>> + IN UINT8 BusWidth >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT32 DevStatus; >>> + >>> + Status =3D SdCardSetBusWidth (PassThru, Rca, BusWidth); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardSwitchBusWidth: Switch to bus width %d fails with %r\n", >>> + BusWidth, >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + Status =3D SdCardSendStatus (PassThru, Rca, &DevStatus); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardSwitchBusWidth: Send status fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + // >>> + // Check the switch operation is really successful or not. >>> + // >>> + if ((DevStatus >> 16) !=3D 0) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardSwitchBusWidth: The switch operation fails as DevStatus >> 0x%08x\n", >>> + DevStatus >>> + )); >>> + return EFI_DEVICE_ERROR; >>> + } >>> + >>> + Status =3D DwMmcHcSetBusWidth (DevBase, IsDdr, BusWidth); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Switch the high speed timing according to request. >>> + >>> + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for deta= ils. >>> + >>> + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL inst= ance. >>> + @param[in] PassThru A pointer to the >> EFI_SD_MMC_PASS_THRU_PROTOCOL >>> + instance. >>> + @param[in] Rca The relative device address to be assigne= d. >>> + @param[in] S18A The boolean to show if it's a UHS-I SD ca= rd. >>> + @param[in] BusWidths The bus width of the SD card. >>> + >>> + @retval EFI_SUCCESS The operation is done correctly. >>> + @retval Others The operation fails. >>> + >>> +**/ >>> +EFI_STATUS >>> +SdCardSetBusMode ( >>> + IN UINTN DevBase, >>> + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, >>> + IN UINT16 Rca, >>> + IN BOOLEAN S18A, >>> + IN UINT32 BusWidths >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + DW_MMC_HC_SLOT_CAP *Capability; >>> + UINT32 ClockFreq; >>> + UINT8 AccessMode; >>> + UINT8 SwitchResp[64]; >>> + DW_MMC_HC_PRIVATE_DATA *Private; >>> + BOOLEAN IsDdr; >>> + >>> + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); >>> + >>> + Capability =3D &Private->Capability[0]; >>> + >>> + if ((Capability->BusWidth =3D=3D 1) || (Capability->BusWidth =3D=3D= 4)) { >>> + BusWidths &=3D Capability[0].BusWidth; >>> + } else { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardSetBusMode: BusWidths (%d) in capability are wrong\n", >>> + Capability->BusWidth >>> + )); >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if (BusWidths =3D=3D 0) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardSetBusMode: Get wrong BusWidths:%d\n", >>> + BusWidths >>> + )); >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + if (Private->Capability[0].Ddr50) { >>> + IsDdr =3D TRUE; >>> + } else { >>> + IsDdr =3D FALSE; >>> + } >>> + >>> + Status =3D SdCardSwitchBusWidth (DevBase, PassThru, Rca, IsDdr, >> BusWidths); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardSetBusMode: Executing SdCardSwitchBusWidth fails with >> %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + // >>> + // Get the supported bus speed from SWITCH cmd return data group #1= . >>> + // >>> + Status =3D SdCardSwitch (PassThru, 0xF, 0xF, 0xF, 0xF, FALSE, Switc= hResp); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + // >>> + // Calculate supported bus speed/bus width/clock frequency by host = and >> device >>> + // capability. >>> + // >>> + ClockFreq =3D 0; >>> + if (S18A && (Capability->Sdr104 !=3D 0) && ((SwitchResp[13] & BIT3)= !=3D 0)) { >>> + ClockFreq =3D 208; >>> + AccessMode =3D 3; >>> + } else if (S18A && (Capability->Sdr50 !=3D 0) && >>> + ((SwitchResp[13] & BIT2) !=3D 0)) { >>> + ClockFreq =3D 100; >>> + AccessMode =3D 2; >>> + } else if (S18A && (Capability->Ddr50 !=3D 0) && >>> + ((SwitchResp[13] & BIT4) !=3D 0)) { >>> + ClockFreq =3D 50; >>> + AccessMode =3D 4; >>> + } else if ((SwitchResp[13] & BIT1) !=3D 0) { >>> + ClockFreq =3D 50; >>> + AccessMode =3D 1; >>> + } else { >>> + ClockFreq =3D 25; >>> + AccessMode =3D 0; >>> + } >>> + >>> + Status =3D SdCardSwitch (PassThru, AccessMode, 0xF, 0xF, 0xF, TRUE, >> SwitchResp); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + if ((SwitchResp[16] & 0xF) !=3D AccessMode) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d fails! >> The Switch response is 0x%1x\n", >>> + AccessMode, >>> + ClockFreq, >>> + SwitchResp[16] & 0xF >>> + )); >>> + return EFI_DEVICE_ERROR; >>> + } >>> + >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d \n", >>> + AccessMode, >>> + ClockFreq >>> + )); >>> + >>> + Status =3D DwMmcHcClockSupply (DevBase, ClockFreq * 1000, *Capabili= ty); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + return Status; >>> +} >>> + >>> +EFI_STATUS >>> +SdCardIdentification ( >>> + IN DW_MMC_HC_PRIVATE_DATA *Private >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINTN DevBase; >>> + EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; >>> + UINT32 Ocr; >>> + UINT16 Rca; >>> + BOOLEAN Xpc; >>> + BOOLEAN S18r; >>> + UINT64 MaxCurrent; >>> + SD_SCR Scr; >>> + SD_CSD Csd; >>> + >>> + DevBase =3D Private->DevBase; >>> + PassThru =3D &Private->PassThru; >>> + // >>> + // 1. Send Cmd0 to the device >>> + // >>> + Status =3D SdCardReset (PassThru); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "SdCardIdentification: Executing Cmd0 fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + MicroSecondDelay (10000); >>> + // >>> + // 2. Send Cmd8 to the device >>> + // >>> + Status =3D SdCardVoltageCheck (PassThru, 0x1, 0xFF); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "SdCardIdentification: Executing Cmd8 fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + // >>> + // 3. Send Acmd41 with voltage window 0 to the device >>> + // >>> + Status =3D SdCardSendOpCond (PassThru, 0, 0, FALSE, FALSE, FALSE, &= Ocr); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_INFO, >>> + "SdCardIdentification: Executing SdCardSendOpCond fails with %r= \n", >>> + Status >>> + )); >>> + return EFI_DEVICE_ERROR; >>> + } >>> + >>> + if (Private->Capability[0].Voltage33 !=3D 0) { >>> + // >>> + // Support 3.3V >>> + // >>> + MaxCurrent =3D ((UINT32)Private->MaxCurrent[0] & 0xFF) * 4; >>> + S18r =3D FALSE; >>> + } else if (Private->Capability[0].Voltage30 !=3D 0) { >>> + // >>> + // Support 3.0V >>> + // >>> + MaxCurrent =3D (((UINT32)Private->MaxCurrent[0] >> 8) & 0xFF) * 4= ; >>> + S18r =3D FALSE; >>> + } else if (Private->Capability[0].Voltage18 !=3D 0) { >>> + // >>> + // Support 1.8V >>> + // >>> + MaxCurrent =3D (((UINT32)Private->MaxCurrent[0] >> 16) & 0xFF) * = 4; >>> + S18r =3D TRUE; >>> + } else { >>> + ASSERT (FALSE); >>> + return EFI_DEVICE_ERROR; >>> + } >>> + >>> + if (MaxCurrent >=3D 150) { >>> + Xpc =3D TRUE; >>> + } else { >>> + Xpc =3D FALSE; >>> + } >>> + >>> + // >>> + // 4. Repeatly send Acmd41 with supply voltage window to the device= . >>> + // Note here we only support the cards complied with SD physical >>> + // layer simplified spec version 2.0 and version 3.0 and above. >>> + // >>> + do { >>> + Status =3D SdCardSendOpCond (PassThru, 0, Ocr, S18r, Xpc, TRUE, &= Ocr); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x,= S18r >> %x, Xpc %x\n", >>> + Status, >>> + Ocr, >>> + S18r, >>> + Xpc >>> + )); >>> + return EFI_DEVICE_ERROR; >>> + } >>> + } while ((Ocr & BIT31) =3D=3D 0); >>> + >>> + Status =3D SdCardAllSendCid (PassThru); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardIdentification: Executing SdCardAllSendCid fails with %r= \n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + Status =3D SdCardSetRca (PassThru, &Rca); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardIdentification: Executing SdCardSetRca fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + Status =3D SdCardGetCsd (PassThru, Rca, &Csd); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardIdentification: Executing SdCardGetCsd fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + Status =3D SdCardSelect (PassThru, Rca); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardIdentification: Selecting card fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + Status =3D SdCardGetScr (PassThru, Rca, &Scr); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG (( >>> + DEBUG_ERROR, >>> + "SdCardIdentification: Executing SdCardGetScr fails with %r\n", >>> + Status >>> + )); >>> + return Status; >>> + } >>> + >>> + // >>> + // Enter Data Tranfer Mode. >>> + // >>> + DEBUG ((DEBUG_INFO, "SdCardIdentification: Found a SD device\n")); >>> + Private->Slot[0].CardType =3D SdCardType; >>> + >>> + Status =3D SdCardSetBusMode (DevBase, PassThru, Rca, S18r, >> Scr.SdBusWidths); >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + Private->Slot[0].Initialized =3D TRUE; >>> + >>> + return Status; >>> +} >>> -- >>> 2.12.3 >=20 >=20 >=20 >=20 --Apple-Mail=_F3B2F092-F088-4876-A0B5-24429692734D Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 One trick people have pul= led in the past is to write a driver that produces a =E2=80=9Cfake=E2=80=9D= PCI IO Protocol. The =E2=80=9Cfake=E2=80=9D PCI IO driver abstracts how th= e MMIO device shows up on the platform. This works well if the MMIO device = is really the same IP block as a PCI device. This usually maps to the PCI B= AR being the same thing as the magic MMIO range. The =E2=80=9Cfake=E2=80=9D= PCI IO Protocol also abstracts platform specific DMA rules from the generi= c driver. 

Thanks,=

Andrew Fish

On Apr 27, 2021, at 2:08 AM, Loh, Tien Hock <tien.hock.loh@intel.com> wrote:
Hi Mike

Yes, the existing Sd = driver is very tightly coupled with PCI IO struct, thus the reason for a ne= w driver. 
I can attempt to refactor the Pci/SdM= mcPciHcDxe and make PCI and Mmio a library if that's the best route. I reme= mber I tried briefly to refactor the code but it was quite a bit of work.

Let me give it another go, and get back to you. 

Thanks.
=
-----Original Me= ssage-----
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Tuesday, April 27, 2021 1:54 AM
To: Loh, Tien = Hock <tien.hock.lo= h@intel.com>; devel@edk2.groups.io;Kinney, Michael D <michael.d.kinney@intel.com>
Cc: thloh85@gmail.com; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel<ard= b+tianocore@kernel.org>
Subject: RE: [PATCH V5 1/1] Em= beddedPkg: DwMmcHcDxe: Add support for
Designware SDMMC drive= r

I see the MdeModulePkg has the SdMmcPciHcDxe= module and it uses the
EDK II SD MMC Override
= Protocol for host controller specific behaviors.  Why was this driver = and an
implementation
of the EDK II SD MMC Over= ride Protocol for the DesignWare MMC HC not
used?

If there is a good reason that this exiting module and ov= erride extensions can
not be used,
then please = add that background and analysis to the BZ.

I = see the existing module is PCI and I think this new one is for a MMIO based=
device
that requires different DMA services. &= nbsp;Is this correct?  I am wondering if there
is
a way to implement t a single UEFI Driver sources that can support = a device
that is
with PCI or MMIO?

If a new driver is required, then here is some more specif= ic code review
feedback:

1) Embe= ddedPkg/Include/Protocol/PlatformSwMmc.h

 = ; The enum EFI_SD_MMC_SLOT_TYPE can not being with EFI_ unless is part=
of the UEFI Spec.
  This file appear= s to be specific to DW, so perhaps it should be prefixed with
DW_ instead
  to match the usage of DW_MMC_HC_SLOT= _CAP.

  The same comment applies to = SD_MMC_CARD_TYPE.  Should that be
DW_SD_MMC_CARD_TYPE?

2) EmbeddedPkg/Drivers/DwMmcHcDx= e
  a) There is a package .dec file in this directo= ry.  Packages can never be
nested. Any
&nb= sp;    interfaces that need to be exported from the Emb= eddedPkg should be
declared in
  &nbs= p;  EmbeddedPkg.dec and DwMmcDcDxe.dec should be removed.
  b) DwMmcDcDxe.dec declared a token space GUID, but there= are not PCDs.
I think this GUID
  &n= bsp;  can be removed.
  c) DwMmcDcDxe.inf= .  Remove reference to DwMmcDcDxe.dec.  Also, is this
UEFI Driver really
     ARM speci= fic?  Why is there a dependency on ArmPkg/ArmPkg.dec?  Can
that be removed?
     Can th= e dependency on ArmLib be removed?

3) I see us= e of #ifdef in the DwMmcHci.h file.  This is highly discouraged.  = ;Why
are
  those there and why not us= e featured flags PCD instead?  If it is related to
the  PCI vs MMIO register mapping, then perhaps the PCI= related content can
be removed
  fro= m this MMIO specific driver?

Best regards,

Mike

-----Original Message-----
From: Loh, T= ien Hock <tien.hoc= k.loh@intel.com>
Sent: Sunday, March 21, 2021 8:25 PM<= br class=3D"">To: devel@= edk2.groups.io
Cc: thloh85@gmail.com; Loh, Tien Hock <tien.hock.loh@intel.com>; Kinney,
Michael D <michael.d.kinney@intel.com>; Leif
=
Lindholm <leif@nuviainc.com>; Ard Biesheuvel
<ardb+tianocore@kernel.org>
Subject: [PATCH V5 1/1] EmbeddedPkg: DwMmcHcDxe: Add suppo= rt for
Designware SDMMC driver

From: "Tien Hock, Loh" <= ;tien.hock.loh@intel.= com>

This adds support for Designware S= DMMC driver. The SDMMC driver
depends on
MdeModulePkg/Bus/Sd/, and produ= ces
EFI_SD_MMC_PASS_THRU_PROTOCOL. The
driver uses MMIO to read/write,= and uses
gEdkiiNonDiscoverableDeviceProtocolGuid. Platform n= eeds to register
device
with gEdkiiNonDiscoverableDeviceProtocolGuid.
Signed-off-by: Loh Tien Hock <tien.hock.loh@intel.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.or= g>
---
EmbeddedPkg/Drivers/DwMmcHcDxe/Dw= MmcHcDxe.dec  |   40 +
EmbeddedPkg/Drivers/DwM= mcHcDxe/DwMmcHcDxe.inf  |   70 +
EmbeddedPkg/D= rivers/DwMmcHcDxe/DwMmcHcDxe.h    |  817
=
++++++++++
= EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h      | &= nbsp;985
++++++++++++
EmbeddedPkg/Include/Protocol/PlatformDwMmc.h  = ; |   79 +
EmbeddedPkg/Drivers/DwMmcHcDxe/Comp= onentName.c |  214 +++
EmbeddedPkg/Drivers/DwMmcHcDxe/Dw= MmcHcDxe.c    | 1296
++++++++++++= ++++
EmbeddedPkg/Drivers= /DwMmcHcDxe/DwMmcHci.c      | 1602
<= /blockquote>++++++++++++++++++++
EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c    | 10= 42
+++++++++++++
EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c   = ;   | 1105
++++++++++++++
10 files changed, 7250 insertio= ns(+)

diff --git a/EmbeddedPkg/Drivers/DwMmcHc= Dxe/DwMmcHcDxe.dec
b/EmbeddedPkg/Drivers/DwMmcHc= Dxe/DwMmcHcDxe.dec
new f= ile mode 100644
index 000000000000..cf85ccb1a030
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcD= xe.dec
@@ -0,0 +1,40 @@
+#/** @file
+# Framework Module Development Environment Industry Standards
+#
+# This Package provides headers and libraries that= conform to EFI/PI
Industry standards.
+# Copyright (c) 2007, Intel Co= rporation. All rights reserved.<BR>
+# Copyright (c) 20= 12-2014, ARM Ltd. All rights reserved.<BR>
+# Copyright= (c) 2018, Linaro. All rights reserved.<BR>
+#
+#    This program and the accompanying materials are= licensed and made
available under
+#    the terms and co= nditions of the BSD License which accompanies this
distribution.
+# &nbs= p;  The full text of the license may be found at
+#=    http://opensource.org/licenses/bsd-license.php
+#
+#    THE PROGRAM IS DISTRIBUTED UND= ER THE BSD LICENSE ON AN "AS IS"
BASIS,
+#    WITHOUT WA= RRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
= EXPRESS OR IMPLIED.
+#+#**/
+
+[Defines]
+=  DEC_SPECIFICATION         &n= bsp;    =3D 0x00010019
+  PACKAGE_NA= ME             =       =3D DwMmcHcDxePkg
+  = ;PACKAGE_GUID           &= nbsp;       =3D e73097ce-1fe2-41a6-a930-= 3136bc6d23ef
+  PACKAGE_VERSION     =            =3D 0.1+
+

+#= ########################################################
####= ###################
+#+# Include Section - list of Include Paths that are provided b= y this package.
+#        =            Comments = are used for Keywords and Module Types.
+#
+# S= upported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CO= RE DXE_DRIVER
DXE_RUNTIME_DRIVER DXE_SMM_DRIVER = DXE_SAL_DRIVER UEFI_DRIVER
UEFI_APPLICATION
+#

+#########################################################
#######################
+
+[Guids.common]
+  gDwMmcHcDxeTokenSpa= ceGuid     =3D { 0x576c132e, 0x7d51, 0x4abb, {
0xbc, 0x60, 0x13, 0x08, 0x04, 0x0e, 0x90, 0x92 }}
+
+[Protocols.c= ommon]
+  gPlatformDwMmcProtocolGuid    = =3D { 0x1d6dfde5, 0x76a7, 0x4404, { 0x85,
0x74,= 0x7a, 0xdf, 0x1a, 0x8a, 0xa2, 0x0d }}
diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf
b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf
new file mode 100644
index 000000000000..4cd0960ef9c3
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf
@@ -0,0 +1,70 @@
+## @file
+#  DwSdMmcHcD= xe driver is used to manage those host controllers which
comply with
+# =  Designware SD Host Controller.
+#
+# &nbs= p;It will produce EFI_SD_MMC_PASS_THRU_PROTOCOL to allow sending
SD/MMC/eMMC cmds
+#  to specified devices from upper layer.
= +#
+#  Copyright (c) 2015, Intel Corporation. All rights= reserved.<BR>
+#  Copyright (C) 2016, Marvell Int= ernational Ltd. All rights reserved.<BR>
+#  Copyr= ight (c) 2018, Linaro Ltd. All rights reserved.<BR>
+#<= br class=3D"">+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditi= ons of the
BSD License
+#  which accompanies this distribution. The= full text of the license may be
found at
+#  http://opensource.org/lice= nses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED = UNDER THE BSD LICENSE ON AN "AS IS"
BASIS,
+#  WITHOUT WARRANTIES O= R REPRESENTATIONS OF ANY KIND, EITHER
EXPRESS OR= IMPLIED.
+#
+#
+##
+
+[Defines]
+  INF_VERSION         =            =3D 0x000= 10019
+  BASE_NAME       &= nbsp;           &nbs= p;  =3D DwMmcHcDxe
+  MODULE_UNI_FILE  &n= bsp;            = ; =3D DwMmcHcDxe.uni
+  FILE_GUID    = ;            &n= bsp;     =3D 9be4d260-208c-4efe-a524-0b5d3bf77f9d<= br class=3D"">+  MODULE_TYPE        = ;            = =3D UEFI_DRIVER
+  VERSION_STRING    &nb= sp;            = = =3D 1.0
+  ENTRY_POINT      &n= bsp;            = ; =3D InitializeDwMmcHcDxe
+
+[Sources]+  ComponentName.c
+  DwMmcHcDxe.c
+  DwMmcHcDxe.h
+  DwMmcHci.c
+  DwMmcHci.h
+  EmmcDevice.c
+ &n= bsp;SdDevice.c
+
+[Packages]
+ &n= bsp;ArmPkg/ArmPkg.dec
+  EmbeddedPkg/Drivers/DwMmcHcDxe/= DwMmcHcDxe.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/M= dePkg.dec
+
+[LibraryClasses]
+ &= nbsp;ArmLib
+  BaseLib
+  BaseMemoryL= ib
+  CacheMaintenanceLib
+  DebugLib=
+  DevicePathLib
+  DmaLib
+  MemoryAllocationLib
+  TimerLib
+  UefiBootServicesTableLib
+  UefiDriverEnt= ryPoint
+  UefiLib
+  UefiRuntimeServ= icesTableLib
+
+[Protocols]
+ &nb= sp;gEdkiiNonDiscoverableDeviceProtocolGuid
+  gEfiDevice= PathProtocolGuid          &nbs= p;         ## TO_START
+  gEfiPciIoProtocolGuid       &n= bsp;            = ;     ## TO_START
+  gEfiSdMmcP= assThruProtocolGuid          &= nbsp;      ## BY_START
+  = gPlatformDwMmcProtocolGuid
+
+[UserExtensions.T= ianoCore."ExtraFiles"]
+  DwMmcHcDxeExtra.uni
diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h
b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h
new file mode 100644
in= dex 000000000000..b783d9830325
--- /dev/null
++= + b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h
@@ -0,0 +1,81= 7 @@
+/** @file
+
+  Provide= s some data structure definitions used by the Designware
SD/MMC
+  = host controller driver.
+
+  Copyright (c)= 2015, Intel Corporation. All rights reserved.<BR>
+ &n= bsp;Copyright (C) 2018, Linaro Ltd. All rigths reserved.<BR>
+
+  This program and the accompanying materials = are licensed and made
available
+  under the terms and conditions o= f the BSD License which accompanies
this
+  distribution.  The= full text of the license may be found at
+  http://opensourc= e.org/licenses/bsd-license.php
+
+  TH= E PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
=
BASIS,
+ &n= bsp;WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _DW_M= MC_HC_DXE_H_
+#define _DW_MMC_HC_DXE_H_
+
+#include <Uefi.h>
+
+#include &= lt;Library/UefiLib.h>
+
+#include <Protoc= ol/ComponentName.h>
+#include <Protocol/ComponentName2.= h>
+#include <Protocol/DeviceIo.h>
+#i= nclude <Protocol/DriverBinding.h>
+#include <Protoco= l/SdMmcPassThru.h>
+
+#include "DwMmcHci.h"<= br class=3D"">+
+extern EFI_COMPONENT_NAME_PROTOCOL
gDwMmcHcComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL
gDwMmcHcComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL  gDwMmcHcDriverBinding;=
+
+#define DW_MMC_HC_PRIVATE_SIGNATURE  S= IGNATURE_32 ('d', 'w', 's',
'd')
<= blockquote type=3D"cite" class=3D"">+
+#define DW_MMC_HC_PRIV= ATE_FROM_THIS(a) \
+    CR(a, DW_MMC_HC_PRIVAT= E_DATA, PassThru,
DW_MMC_HC_PRIVATE_SIGNATURE)
+
+//
+// Generic time out value, 1 microsecond as unit.
+= //
+#define DW_MMC_HC_GENERIC_TIMEOUT     = ;(1 * 1000 * 1000)
+
+//
+// SD/M= MC async transfer timer interval, set by experience.
+// The = unit is 100us, takes 1ms as interval.
+//
+#def= ine DW_MMC_HC_ASYNC_TIMER
EFI_TIMER_PERIOD_MILLI= SECONDS(1)
+//
+// SD/MMC removable device enumeration timer interval, set by
experience.
+// The unit is 100us, takes 100ms as interval.
+//=
+#define DW_MMC_HC_ENUM_TIMER
EFI= _TIMER_PERIOD_MILLISECONDS(100)
+
+typedef struct {
+  BOOLEAN &nb= sp;            =             &nb= sp;  Enable;
+  EFI_SD_MMC_SLOT_TYPE  &nb= sp;            =  SlotType;
+  BOOLEAN      = ;            &n= bsp;          MediaPresen= t;
+  BOOLEAN        =             &nb= sp;        Initialized;
+  SD_MMC_CARD_TYPE         = ;           CardType= ;
+} DW_MMC_HC_SLOT;
+
+typedef s= truct {
+  UINTN       &nb= sp;            =            Signature= ;
+
+  EFI_HANDLE     =             &nb= sp;        ControllerHandle;
+
+  // Mmio base address
+  = UINTN            &nb= sp;            =       DevBase;
+
= +  EFI_SD_MMC_PASS_THRU_PROTOCOL       P= assThru;
+
+  PLATFORM_DW_MMC_PROTOCOL &nb= sp;          *PlatformDwM= mc;
+  //
+  // The field is used to = record the previous slot in GetNextSlot().
+  //
+  UINT8          =             &nb= sp;        PreviousSlot;
+  //
+  // For Non-blocking operation.
+  //
+  EFI_EVENT    &nbs= p;            &= nbsp;         TimerEvent;
+  //
+  // For Sd removable device enume= ration.
+  //
+  EFI_EVENT  &nbs= p;            &= nbsp;           Conn= ectEvent;
+  LIST_ENTRY      &n= bsp;            = ;       Queue;
+
+  DW_MMC_HC_SLOT        &nb= sp;            =  Slot[DW_MMC_HC_MAX_SLOT];
+  DW_MMC_HC_SLOT_CAP
Capability[DW_MMC_HC_MAX_SLOT];
+  UINT64     &nb= sp;            =             Max= Current[DW_MMC_HC_MAX_SLOT];
+
+  UINT32 &= nbsp;           &nbs= p;            &= nbsp;   ControllerVersion;
+} DW_MMC_HC_PRIVAT= E_DATA;
+
+#define DW_MMC_HC_TRB_SIG  &nbs= p;          SIGNATURE_32 = ('D', 'T', 'R', 'B')
+
+//
+// TR= B (Transfer Request Block) contains information for the cmd request.
+//
+typedef struct {
+  UINT32 &n= bsp;            = ;            &n= bsp;   Signature;
+  LIST_ENTRY  &nb= sp;            =            TrbList;<= br class=3D"">+
+  UINT8      &= nbsp;           &nbs= p;            S= lot;
+  UINT16        = ;            &n= bsp;         BlockSize;
+
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet= ;
+  VOID        &nbs= p;            &= nbsp;          *Data;
+  UINT32         &= nbsp;           &nbs= p;        DataLen;
+ =  BOOLEAN           &= nbsp;           &nbs= p;     Read;
+  EFI_PHYSICAL_AD= DRESS            &nb= sp;   DataPhy;
+  VOID    =             &nb= sp;            =    *DataMap;
+  DW_MMC_HC_TRANSFER_MODE &= nbsp;           Mode= ;
+
+  EFI_EVENT     &= nbsp;           &nbs= p;         Event;
+  BOOLEAN          &nb= sp;            =       Started;
+  UINT64 &= nbsp;           &nbs= p;            &= nbsp;   Timeout;
+
+  DW_MM= C_HC_DMA_DESC_LINE          &n= bsp;  *DmaDesc;
+  EFI_PHYSICAL_ADDRESS  =             &nb= sp; DmaDescPhy;
+  UINT32     &= nbsp;           &nbs= p;            D= maDescPages;
+  VOID       = ;            &n= bsp;            = ;*DmaMap;
+
+  BOOLEAN    &= nbsp;           &nbs= p;            U= seFifo;
+  BOOLEAN       &= nbsp;           &nbs= p;         UseBE;   =             &nb= sp;  // Big-endian
+
+  DW_MMC_H= C_PRIVATE_DATA           =    *Private;
+} DW_MMC_HC_TRB;
+=
+#define DW_MMC_HC_TRB_FROM_THIS(a) \
+  =   CR(a, DW_MMC_HC_TRB, TrbList, DW_MMC_HC_TRB_SIG)
= +
+//
+// Task for Non-blocking mode.
+//
+typedef struct {
+  UINT32 &nb= sp;            =             &nb= sp;   Signature;
+  LIST_ENTRY  &nbs= p;            &= nbsp;          Link;
+
+  UINT8       = ;            &n= bsp;           Slot;=
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
+  BOOLEAN         &nbs= p;            &= nbsp;      IsStart;
+  EFI= _EVENT            &n= bsp;            = ;  Event;
+  UINT64     &n= bsp;            = ;            Re= tryTimes;
+  BOOLEAN       = ;            &n= bsp;         InfiniteWait;
+  VOID         &nb= sp;            =           *Map;
+  VOID          &= nbsp;           &nbs= p;         *MapAddress;
+} DW_MMC_HC_QUEUE;
+
+//
+// Prototypes
+//
+/**
+  = Execute card identification procedure.
+
+ &nbs= p;@param[in] Private        A pointer to= the DW_MMC_HC_PRIVATE_DATA
instance.
+
+  @retval= EFI_SUCCESS       The card is identified cor= rectly.
+  @retval Others      =       The card can't be identified.
+
+**/
+typedef
+EFI_STATU= S
+(*DWMMC_CARD_TYPE_DETECT_ROUTINE) (
+  = IN DW_MMC_HC_PRIVATE_DATA         &= nbsp;   *Private
+  );
++/**
+  Sends SD command to an SD card that = is attached to the SD controller.
+
+  The= PassThru() function sends the SD command specified by Packet to
the SD
+  card specified by Slot.
+
+  If= Packet is successfully sent to the SD card, then EFI_SUCCESS is
returned.
+
+  If a device error occurs while sending the P= acket, then
EFI_DEVICE_ERROR is
+  returned.
+
+  If Slot is not in a valid range for the SD controller, then=
+  EFI_INVALID_PARAMETER is returned.
++  If Packet defines a data command but both InDataBuffer= and
OutDataBuffer are
+  NULL, EFI_INVALID_PARAMETER is returned.<= br class=3D"">+
+  @param[in]     Th= is           A pointer to= the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+       = ;            &n= bsp;            = ;instance.
+  @param[in]     Slot &n= bsp;         The slot number o= f the SD card to send the
+      &nb= sp;            =             &nb= sp;command to.
+  @param[in,out] Packet   &nbs= p;     A pointer to the SD command data structure.=
+  @param[in]     Event   = ;       If Event is NULL, blocking I/O i= s performed. If
+        &= nbsp;           &nbs= p;           Event i= s not NULL, then nonblocking I/O is
+     = ;            &n= bsp;            = ;  performed, and Event will be signaled when the
+=             &n= bsp;            = ;      Packet completes.
+
+  @retval EFI_SUCCESS       &= nbsp;   The SD Command Packet was sent by the
=
host.
+ &nb= sp;@retval EFI_DEVICE_ERROR      A device error oc= curred while attempting
to send
+       &n= bsp;            = ;            th= e SD command Packet.
+  @retval EFI_INVALID_PARAMETER Pa= cket, Slot, or the contents of the
Packet is
+     &= nbsp;           &nbs= p;            &= nbsp; invalid.
+  @retval EFI_INVALID_PARAMETER Pac= ket defines a data command but
both
+      &nbs= p;            &= nbsp;           &nbs= p;InDataBuffer and OutDataBuffer are NULL.
+  @retval EF= I_NO_MEDIA          SD Device = not present in the Slot.
+  @retval EFI_UNSUPPORTED &nbs= p;     The command described by the SD
Command Packet
+            =             &nb= sp;       is not supported by the host c= ontroller.
+  @retval EFI_BAD_BUFFER_SIZE   Th= e InTransferLength or
OutTransferLength
+      = ;            &n= bsp;            = ; exceeds the limit supported by SD card ( i.e. if
+ &nb= sp;            =             &nb= sp;     the number of bytes exceed the Last LBA).<= br class=3D"">+
+**/
+EFI_STATUS
= +EFIAPI
+DwMmcPassThruPassThru (
+  IN &nb= sp;   EFI_SD_MMC_PASS_THRU_PROTOCOL     =     *This,
+  IN    &= nbsp;UINT8           &nbs= p;            &= nbsp;        Slot,
+ =  IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   *Packet,
+  IN     EFI_EVENT    &nb= sp;            =             Eve= nt    OPTIONAL
+  );
+
+/**
+  Used to retrieve next slot numbers sup= ported by the SD controller. The
+  function returns inf= ormation about all available slots (populated or
+  not-= populated).
+
+  The GetNextSlot() functio= n retrieves the next slot number on an SD
contro= ller.
+  If on inpu= t Slot is 0xFF, then the slot number of the first slot on the SD
+  controller is returned.
+
+ &nbs= p;If Slot is a slot number that was returned on a previous call to
+  GetNextSlot(), then the slot number of the next slot on the = SD controller
is
+  returned.
+
+ &nb= sp;If Slot is not 0xFF and Slot was not returned on a previous call to
+  GetNextSlot(), EFI_INVALID_PARAMETER is returned.
+
+  If Slot is the slot number of the last slot = on the SD controller, then
+  EFI_NOT_FOUND is returned.=
+
+  @param[in]     T= his           A pointer t= o the
EFI_SD_MMMC_PASS_THRU_PROTOCOL
+      &nb= sp;            =             &nb= sp;instance.
+  @param[in,out] Slot    &n= bsp;      On input, a pointer to a slot numbe= r on the SD
+         = ;            &n= bsp;          controller.=
+          &nbs= p;            &= nbsp;        On output, a pointer t= o the next slot number on
+      &nb= sp;            =             &nb= sp;the SD controller.
+       &= nbsp;           &nbs= p;            A= n input value of 0xFF retrieves the first slot
+   =             &nb= sp;            =     number on the SD controller.
+
+  @retval EFI_SUCCESS       &nb= sp;   The next slot number on the SD controller
was
+ &nb= sp;            =             &nb= sp;     returned in Slot.
+  @r= etval EFI_NOT_FOUND         There a= re no more slots on this SD
controller.
+  @retval EFI_INVALID_PAR= AMETER Slot is not 0xFF and Slot was not
returne= d on a
+   &nb= sp;            =             &nb= sp;   previous call to GetNextSlot().
+
+**/
+EFI_STATUS
+EFIAPI
= +DwMmcPassThruGetNextSlot (
+  IN    &nbs= p;EFI_SD_MMC_PASS_THRU_PROTOCOL        *= This,
+  IN OUT UINT8      &nbs= p;            &= nbsp;           &nbs= p;*Slot
+  );
+
+/**
+  Used to allocate and build a device path node for an SD card= on the SD
+  controller.
+
= +  The BuildDevicePath() function allocates and builds a single device= node
+  for the SD
+  card specified= by Slot.
+
+  If the SD card specified by= Slot is not present on the SD controller, then
+  EFI_N= OT_FOUND is returned.
+
+  If DevicePath i= s NULL, then EFI_INVALID_PARAMETER is returned.
+
+  If there are not enough resources to allocate the device path no= de, then
+  EFI_OUT_OF_RESOURCES is returned.
+
+  Otherwise, DevicePath is allocated with the = boot service AllocatePool(),
the
<= blockquote type=3D"cite" class=3D"">+  contents of DevicePath are init= ialized to describe the SD card specified by
+  Slot, an= d EFI_SUCCESS is returned.
+
+  @param[in]=     This        &nb= sp;  A pointer to the
EFI_SD_MMMC_PASS= _THRU_PROTOCOL
+  &= nbsp;           &nbs= p;            &= nbsp;    instance.
+  @param[in] &nb= sp;   Slot         &= nbsp; Specifies the slot number of the SD card for
+ &nb= sp;            =             &nb= sp;     which a device path node is to be allocate= d and
+          = ;            &n= bsp;         built.
+  @param[in,out] DevicePath     A pointer = to a single device path node that
+     &= nbsp;           &nbs= p;            &= nbsp; describes the SD card specified by Slot. This
+ &n= bsp;            = ;            &n= bsp;     function is responsible for allocating th= e
+          &nb= sp;            =          buffer DevicePath wit= h the boot service
+       &nbs= p;            &= nbsp;           Allo= catePool(). It is the caller's responsibi-
+   &nbs= p;            &= nbsp;           &nbs= p;   lity to free DevicePath when the caller is
+             = ;            &n= bsp;      finished with DevicePath.
+
+  @retval EFI_SUCCESS     =       The device path node that describes the= SD
card
+           &= nbsp;           &nbs= p;        specified by Slot was all= ocated and returned in
+       =             &nb= sp;            = DevicePath.
+  @retval EFI_NOT_FOUND    &= nbsp;    The SD card specified by Slot does not
exist on
+            =             &nb= sp;       the SD controller.
+  @retval EFI_INVALID_PARAMETER DevicePath is NULL.
= +  @retval EFI_OUT_OF_RESOURCES  There are not enough resources t= o
allocate
+           = ;            &n= bsp;        DevicePath.
+
+**/
+EFI_STATUS
+EFIAPI
+DwMmcPassThruBuildDevicePath (
+  IN  &= nbsp;  EFI_SD_MMC_PASS_THRU_PROTOCOL     &nbs= p; *This,
+  IN     UINT8  = ;            &n= bsp;            = ;    Slot,
+  IN OUT EFI_DEVICE_PATH= _PROTOCOL            = ;**DevicePath
+  );
+
+/**+  This function retrieves an SD card slot number based o= n the input device
path.
+
+  The GetSlotNumber() fun= ction retrieves slot number for the SD card
spec= ified
+  by the Dev= icePath node. If DevicePath is NULL,
EFI_INVALID= _PARAMETER is
+  re= turned.
+
+  If DevicePath is not a device= path node type that the SD Pass Thru driver
+  supports= , EFI_UNSUPPORTED is returned.
+
+  @param= [in]  This           = ;   A pointer to the
EFI_SD_MMC_P= ASS_THRU_PROTOCOL
+ &nbs= p;            &= nbsp;           &nbs= p;     instance.
+  @param[in] =  DevicePath        A pointer to the= device path node that
describes
<= blockquote type=3D"cite" class=3D"">+       &= nbsp;           &nbs= p;            a= SD card on the SD controller.
+  @param[out] Slot  = ;            On= return, points to the slot number of an SD
+   &nb= sp;            =             &nb= sp;   card on the SD controller.
+
+  @retval EFI_SUCCESS        &n= bsp;  SD card slot number is returned in Slot.
+ &n= bsp;@retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL.
+  @retval EFI_UNSUPPORTED       Device= Path is not a device path node
type that
+      = ;            &n= bsp;            = ; the SD Pass Thru driver supports.
+
+**/=
+EFI_STATUS
+EFIAPI
+DwMmcPassTh= ruGetSlotNumber (
+  IN  EFI_SD_MMC_PASS_THRU_PROTO= COL          *This,
+  IN  EFI_DEVICE_PATH_PROTOCOL     &n= bsp;         *DevicePath,
+  OUT UINT8         = ;            &n= bsp;            = ;*Slot
+  );
+
+/**
+  Resets an SD card that is connected to the SD controller.+
+  The ResetDevice() function resets the S= D card specified by Slot.
+
+  If this SD = controller does not support a device reset operation,
+  = ;EFI_UNSUPPORTED is returned.
+
+  If Slot= is not in a valid slot number for this SD controller,
+ &nbs= p;EFI_INVALID_PARAMETER is returned.
+
+  = If the device reset operation is completed, EFI_SUCCESS is returned.
+
+  @param[in]  This    &nb= sp;         A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+        = ;            &n= bsp;           insta= nce.
+  @param[in]  Slot     &n= bsp;        Specifies the slot numb= er of the SD card to be
+       = ;            &n= bsp;            = ;reset.
+
+  @retval EFI_SUCCESS  &nb= sp;        The SD card specified by= Slot was reset.
+  @retval EFI_UNSUPPORTED   =     The SD controller does not support a
= device
+ &n= bsp;            = ;            &n= bsp;     reset operation.
+  @r= etval EFI_INVALID_PARAMETER Slot number is invalid.
+  @= retval EFI_NO_MEDIA          S= D Device not present in the Slot.
+  @retval EFI_DEVICE_= ERROR      The reset command failed due to a devic= e
error
+
+**/
+EFI_STATUS
+EF= IAPI
+DwMmcPassThruResetDevice (
+  IN EFI= _SD_MMC_PASS_THRU_PROTOCOL         =   *This,
+  IN UINT8     &= nbsp;           &nbs= p;            &= nbsp;    Slot
+  );
+<= br class=3D"">+//
+// Driver model protocol interfaces
+//
+/**
+  Tests to see if this d= river supports a given controller. If a child device is
+ &nb= sp;provided, it further tests to see if this driver supports creating a han= dle
+  for the specified child device.
++  This function checks to see if the driver specified by= This supports the
+  device specified by ControllerHand= le. Drivers will typically use the device
+  path attach= ed to ControllerHandle and/or the services from the bus I/O
+=  abstraction attached to ControllerHandle to determine if the driver<= br class=3D"">
supports
+  ControllerHandle. This function may be called many time= s during
platform
+  initialization. In order to reduce boot times= , the tests performed by this
+  function must be very s= mall, and take as little time as possible to
exe= cute.
+  This funct= ion must not change the state of any hardware devices, and
this
+  = function must be aware that the device specified by ControllerHandle
may
+  already be managed by the same driver or a different driver. This<= br class=3D"">
function
+  must match its calls to AllocatePages() with FreePages(= ), AllocatePool()
with
+  FreePool(), and OpenProtocol() with Close= Protocol().
+  Since ControllerHandle may have been prev= iously started by the same
driver, if
+  a protocol is already i= n the opened state, then it must not be closed with
+  C= loseProtocol(). This is required to guarantee the state of
ControllerHandle
+  is not modified by this function.
+
+  @param[in]  This       &n= bsp;         A pointer to the<= br class=3D"">
EFI_DRIVER_BINDING_PROTOCOL
+        =             &nb= sp;            =   instance.
+  @param[in]  ControllerHand= le     The handle of the controller to test. This
+           &nbs= p;            &= nbsp;          handle mus= t support a protocol interface that
+     = ;            &n= bsp;            = ;     supplies an I/O abstraction to the driver.+  @param[in]  RemainingDevicePath  A pointer t= o the remaining portion of
a
+        = ;            &n= bsp;            = ;  device path.  This parameter is ignored by
= +             &= nbsp;           &nbs= p;         device drivers, and= is optional for bus
+       &n= bsp;            = ;            &n= bsp;  drivers. For bus drivers, if this parameter
+=             &n= bsp;            = ;         is not NULL, then th= e bus driver must deter-
+      &nbs= p;            &= nbsp;           &nbs= p;   mine if the bus controller specified by
+=             &n= bsp;            = ;         ControllerHandle and= the child controller
+       &= nbsp;           &nbs= p;            &= nbsp;  specified by RemainingDevicePath are both
+ =             &nb= sp;            =          supported by this bus= driver.
+
+  @retval EFI_SUCCESS  &n= bsp;           The d= evice specified by ControllerHandle
and
+      = ;            &n= bsp;            = ;    RemainingDevicePath is supported by the
+            =             &nb= sp;          driver speci= fied by This.
+  @retval EFI_ALREADY_STARTED   = ;   The device specified by
Contr= ollerHandle and
+  =             &nb= sp;            =         RemainingDevicePath is alre= ady being managed
+        = ;            &n= bsp;            = ;  by the driver specified by This.
+  @retval= EFI_ACCESS_DENIED        The device spe= cified by
ControllerHandle and
+       &nb= sp;            =             &nb= sp;  RemainingDevicePath is already being managed
+=             &n= bsp;            = ;         by a different drive= r or an application that
+      &nbs= p;            &= nbsp;           &nbs= p;   requires exclusive access.
+   =             &nb= sp;            =        Currently not implemented.
+  @retval EFI_UNSUPPORTED       = ;   The device specified by
Contr= ollerHandle and
+  =             &nb= sp;            =         RemainingDevicePath is not = supported by the
+        =             &nb= sp;            =   driver specified by This.
+**/
+EFI= _STATUS
+EFIAPI
+DwMmcHcDriverBindingSupported = (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE         &nbs= p;        Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath=
+  );
+
+/**
= +  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the = EFI boot service
+  ConnectController().
+=  As a result, much of the error checking on the parameters to Start()= has
been
+  moved into this common boot service. It is legal to ca= ll Start() from other
+  locations,
+ &nbs= p;but the following calling restrictions must be followed or the system
behavior
+  will not be deterministic.
+  1. Contro= llerHandle must be a valid EFI_HANDLE.
+  2. If Remainin= gDevicePath is not NULL, then it must be a pointer to a
natural-
+  = ;   ly aligned EFI_DEVICE_PATH_PROTOCOL.
+ &nb= sp;3. Prior to calling Start(), the Supported() function for the driver spe= cified
+     by This must have been calle= d with the same calling parameters, and
+    &= nbsp;Supported() must have returned EFI_SUCCESS.
+
+  @param[in]  This       &n= bsp;         A pointer to the<= br class=3D"">
EFI_DRIVER_BINDING_PROTOCOL
+        =             &nb= sp;            =   instance.
+  @param[in]  ControllerHand= le     The handle of the controller to start.
This
+             =             &nb= sp;         handle must suppor= t a protocol interface that
+      &= nbsp;           &nbs= p;            &= nbsp;   supplies an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the = remaining portion of
a
+         = ;            &n= bsp;            = ; device path.  This parameter is ignored by
+ &nbs= p;            &= nbsp;           &nbs= p;        device drivers, and is op= tional for bus dri-
+       &nb= sp;            =             &nb= sp;  vers. For a bus driver, if this parameter is
+=             &n= bsp;            = ;         NULL, then handles f= or all the children of
+       =             &nb= sp;            =    Controller are created by this driver.
+ &n= bsp;            = ;            &n= bsp;        If this parameter is no= t NULL and the first
+       &n= bsp;            = ;            &n= bsp;  Device Path Node is not the End of Device
+ &= nbsp;           &nbs= p;            &= nbsp;        Path Node, then only t= he handle for the
+        = ;            &n= bsp;            = ;  child device specified by the first Device
+ &nb= sp;            =             &nb= sp;        Path Node of RemainingDe= vicePath is created
+       &nb= sp;            =             &nb= sp;  by this driver.
+     &nbs= p;            &= nbsp;           &nbs= p;    If the first Device Path Node of
+ =             &nb= sp;            =          RemainingDevicePath i= s the End of Device Path
+      &nbs= p;            &= nbsp;           &nbs= p;   Node, no child handle is created by this
= +             &= nbsp;           &nbs= p;         driver.
+
+  @retval EFI_SUCCESS     &nbs= p;        The device was started.+  @retval EFI_DEVICE_ERROR      = ;   The device could not be started due to a
+=             &n= bsp;            = ;         device error. Curren= tly not implemented.
+  @retval EFI_OUT_OF_RESOURCES &nb= sp;   The request could not be
co= mpleted due to a
+  = ;            &n= bsp;            = ;        lack of resources.
+  @retval Others        &nb= sp;          The driver f= ailded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+DwMmcHcDriverBindingStar= t (
+  IN EFI_DRIVER_BINDING_PROTOCOL    =  *This,
+  IN EFI_HANDLE     &n= bsp;            = ;    Controller,
+  IN EFI_DEVICE_PA= TH_PROTOCOL        *RemainingDevicePath<= br class=3D"">+  );
+
+/**
+=  Stops a device controller or a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI= boot service
+  DisconnectController().
+=  As a result, much of the error checking on the parameters to Stop() = has
been
+  moved into this common boot service. It is legal to cal= l Stop() from other
+  locations, but the following call= ing restrictions must be followed or the
+  system behav= ior will not be deterministic.
+  1. ControllerHandle mu= st be a valid EFI_HANDLE that was used on a
prev= ious
+    = ; call to this same driver's Start() function.
+  2= . The first NumberOfChildren handles of ChildHandleBuffer must all be a
valid
+     EFI_HANDLE. In addition, all of these hand= les must have been created
in
+     this driver's St= art() function, and the Start() function must have called
+ &= nbsp;   OpenProtocol() on ControllerHandle with an Attribute= of
+     EFI_OPEN_PROTOCOL_BY_CHILD_CONT= ROLLER.
+
+  @param[in]  This  &= nbsp;           A po= inter to the
EFI_DRIVER_BINDING_PROTOCOL
+      = ;            &n= bsp;            = ; instance.
+  @param[in]  ControllerHandle &n= bsp;A handle to the device being stopped.
The ha= ndle
+    = ;            &n= bsp;            = ;   must support a bus specific I/O protocol for the
+            =             &nb= sp;       driver to use to stop the devi= ce.
+  @param[in]  NumberOfChildren  The numbe= r of child device handles in
+      =             &nb= sp;            =  ChildHandleBuffer.
+  @param[in]  ChildHandle= Buffer An array of child handles to be freed.
Ma= y be
+    = ;            &n= bsp;            = ;   NULL if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS       &nbs= p;   The device was stopped.
+  @retval E= FI_DEVICE_ERROR      The device could not be stopp= ed due to a
device
+         &nb= sp;            =           error.
+
+**/
+EFI_STATUS
+EFIAPI=
+DwMmcHcDriverBindingStop (
+  IN  E= FI_DRIVER_BINDING_PROTOCOL     *This,
+ &= nbsp;IN  EFI_HANDLE         &n= bsp;            = ;Controller,
+  IN  UINTN     &= nbsp;           &nbs= p;         NumberOfChildren,+  IN  EFI_HANDLE      &nbs= p;            &= nbsp;  *ChildHandleBuffer
+  );
= +
+//
+// EFI Component Name Functions
+//
+/**
+  Retrieves a Unicode str= ing that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver i= n the form of
a
+  Unicode string. If the driver specified by Th= is has a user readable name in
+  the language specified= by Language, then a pointer to the driver name is
+  re= turned in DriverName, and EFI_SUCCESS is returned. If the driver
specified
+  by This does not support the language specified by Language,=
+  then EFI_UNSUPPORTED is returned.
++  @param  This[in]      &nb= sp;       A pointer to the
EFI_COMPONENT_NAME2_PROTOCOL or
+         &nb= sp;            =           EFI_COMPONENT_N= AME_PROTOCOL instance.
+
+  @param  L= anguage[in]          A pointer= to a Null-terminated ASCII string
+     =             &nb= sp;            =   array indicating the language. This is the
+ &nbs= p;            &= nbsp;           &nbs= p;     language of the driver name that the caller= is
+          &= nbsp;           &nbs= p;         requesting, and it = must match one of the
+       &= nbsp;           &nbs= p;            l= anguages specified in SupportedLanguages. The
+   &= nbsp;           &nbs= p;            &= nbsp;   number of languages supported by a driver is up
+           &nb= sp;            =         to the driver writer. Langu= age is specified
+        =             &nb= sp;           in RFC= 4646 or ISO 639-2 language code format.
+
+ &n= bsp;@param  DriverName[out]       A poin= ter to the Unicode string to return.
+    &nbs= p;            &= nbsp;           &nbs= p;  This Unicode string is the name of the
+  =             &nb= sp;            =      driver specified by This in the language
+           &nb= sp;            =         specified by Language.
+
+  @retval EFI_SUCCESS    &nb= sp;      The Unicode string for the Driver sp= ecified by
+         =             &nb= sp;          This and the= language specified by Language was
+     = ;            &n= bsp;            = ;  returned in DriverName.
+
+  = @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
= +
+  @retval EFI_UNSUPPORTED     &nb= sp; The driver specified by This does not
s= upport
+   &nb= sp;            =             &nb= sp;   the language specified by Language.
++**/
+EFI_STATUS
+EFIAPI
+DwMmcHcComponentNameGetDriverName (
+  IN  = EFI_COMPONENT_NAME_PROTOCOL     *This,
+ =  IN  CHAR8          =             &nb= sp;    *Language,
+  OUT CHAR16 &nbs= p;            &= nbsp;           **Dr= iverName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name o= f the
controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable na= me of the controller specified
by
=
+  ControllerHandle and ChildHand= le in the form of a Unicode string. If the
+  driver spe= cified by This has a user readable name in the language
specified by
+ &= nbsp;Language, then a pointer to the controller name is returned in
ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specif= ied by This is not
currently
+  managing the controller specified b= y ControllerHandle and ChildHandle,
+  then EFI_UNSUPPOR= TED is returned.  If the driver specified by This does
<= /blockquote>not
+  = support the language specified by Language, then EFI_UNSUPPORTED is
returned.
+
+  @param  This[in]    &nbs= p;         A pointer to the
EFI_COMPONENT_NAME2_PROTOCOL or
+       &nbs= p;            &= nbsp;           EFI_= COMPONENT_NAME_PROTOCOL instance.
+
+  @pa= ram  ControllerHandle[in]  The handle of a controller that the dr= iver
+          =             &nb= sp;         specified by This = is managing.  This handle
+     &nbs= p;            &= nbsp;           &nbs= p; specifies the controller whose name is to be
+  =             &nb= sp;            =      returned.
+
+ &nb= sp;@param  ChildHandle[in]       The han= dle of the child controller to retrieve
+    &= nbsp;           &nbs= p;            &= nbsp;  the name of.  This is an optional parameter that
+           &nb= sp;            =         may be NULL.  It will = be NULL for device
+       &nbs= p;            &= nbsp;           driv= ers.  It will also be NULL for a bus drivers
+  &nb= sp;            =             &nb= sp;    that wish to retrieve the name of the bus
+            = ;            &n= bsp;       controller.  It will not= be NULL for a bus
+       &nbs= p;            &= nbsp;           driv= er that wishes to retrieve the name of a
+    =             &nb= sp;            =    child controller.
+
+  @= param  Language[in]         &n= bsp;A pointer to a Null-terminated ASCII string
+   = ;            &n= bsp;            = ;    array indicating the language.  This is the+           =             &nb= sp;        language of the driver n= ame that the caller is
+       =             &nb= sp;            = requesting, and it must match one of the
+    =             &nb= sp;            =    languages specified in SupportedLanguages. The
+            =             &nb= sp;       number of languages supported = by a driver is up
+        = ;            &n= bsp;           to th= e driver writer. Language is specified in
+    = ;            &n= bsp;            = ;   RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A po= inter to the Unicode string to
return.
+      = ;            &n= bsp;            = ; This Unicode string is the name of the
+   &= nbsp;           &nbs= p;            &= nbsp;   controller specified by ControllerHandle and
+            =             &nb= sp;       ChildHandle in the language sp= ecified by
+         =             &nb= sp;          Language fro= m the point of view of the driver
+     &= nbsp;           &nbs= p;            &= nbsp; specified by This.
+
+  @retval= EFI_SUCCESS           Th= e Unicode string for the user readable
name in
+     = ;            &n= bsp;            = ;  the language specified by Language for the
+ &nb= sp;            =             &nb= sp;     driver specified by This was returned in+           =             &nb= sp;        DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is= not a valid
EFI_HANDLE.
+
+  @retval EFI_INVALID_PAR= AMETER ChildHandle is not NULL and it is not a
v= alid
+    = ;            &n= bsp;            = ;   EFI_HANDLE.
+
+  @retva= l EFI_INVALID_PARAMETER Language is NULL.
+
+ &= nbsp;@retval EFI_INVALID_PARAMETER ControllerName is NULL.
+<= br class=3D"">+  @retval EFI_UNSUPPORTED      = ; The driver specified by This is not
curre= ntly
+    = ;            &n= bsp;            = ;   managing the controller specified by
+ &nb= sp;            =             &nb= sp;     ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED    &n= bsp;  The driver specified by This does not
support
+  &n= bsp;            = ;            &n= bsp;    the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+DwMmcHcComponentNameGetControllerName (
+  I= N  EFI_COMPONENT_NAME_PROTOCOL     *This,
+  IN  EFI_HANDLE       &nbs= p;            &= nbsp; ControllerHandle,
+  IN  EFI_HANDLE &nbs= p;            &= nbsp;       ChildHandle, OPTIONAL
+  IN  CHAR8        &n= bsp;            = ;      *Language,
+  OUT C= HAR16            &nb= sp;            =  **ControllerName
+  );
+
+/**
+  Create a new TRB for the SD/MMC cmd request.<= br class=3D"">+
+  @param[in] Private    =     A pointer to the DW_MMC_HC_PRIVATE_DATA
instance.
+  @param[in] Slot         &= nbsp; The slot number of the SD card to send the
command
+  &n= bsp;            = ;            &n= bsp;to.
+  @param[in] Packet     &nb= sp;   A pointer to the SD command data structure.
+  @param[in] Event        &= nbsp; If Event is NULL, blocking I/O is performed.
+ &nb= sp;            =             &nb= sp; If Event is not NULL, then nonblocking I/O is
+ &nbs= p;            &= nbsp;           &nbs= p; performed, and Event will be signaled when the
+ &nbs= p;            &= nbsp;           &nbs= p; Packet completes.
+
+  @return Cre= ated Trb or NULL.
+
+**/
+DW_MMC_= HC_TRB *
+DwMmcCreateTrb (
+  IN DW_MMC_HC= _PRIVATE_DATA           &= nbsp;  *Private,
+  IN UINT8    = ;            &n= bsp;            = ;  Slot,
+  IN EFI_SD_MMC_PASS_THRU_COMMAND_PA= CKET *Packet,
+  IN EFI_EVENT     &n= bsp;            = ;         Event
= +  );
+
+/**
+  Free th= e resource used by the TRB.
+
+  @param[in= ] Trb            The= pointer to the DW_MMC_HC_TRB instance.
+
+**/<= br class=3D"">+VOID
+DwMmcFreeTrb (
+  IN = DW_MMC_HC_TRB           *= Trb
+  );
+
+/**
+  Check if the env is ready for execute specified TRB.
+
+  @param[in] Private      = ;  A pointer to the DW_MMC_HC_PRIVATE_DATA
instance.
+  @= param[in] Trb           &= nbsp;The pointer to the DW_MMC_HC_TRB instance.
+
+  @retval EFI_SUCCESS       The env = is ready for TRB execution.
+  @retval EFI_NOT_READY &nb= sp;   The env is not ready for TRB execution.
= +  @retval Others         &nbs= p;  Some erros happen.
+
+**/
+EFI_STATUS
+DwMmcCheckTrbEnv (
+  = IN DW_MMC_HC_PRIVATE_DATA         &= nbsp; *Private,
+  IN DW_MMC_HC_TRB   &nb= sp;            =     *Trb
+  );
+
+/**
+  Wait for the env to be ready for execut= e specified TRB.
+
+  @param[in] Private &= nbsp;      A pointer to the DW_MMC_HC_PRIVATE= _DATA
instance.
+  @param[in] Trb      =       The pointer to the DW_MMC_HC_TRB instan= ce.
+
+  @retval EFI_SUCCESS   &= nbsp;   The env is ready for TRB execution.
+ =  @retval EFI_TIMEOUT       The env is no= t ready for TRB execution in time.
+  @retval Others &nb= sp;          Some erros h= appen.
+
+**/
+EFI_STATUS
+DwMmcWaitTrbEnv (
+  IN DW_MMC_HC_PRIVATE_DATA &= nbsp;         *Private,
+  IN DW_MMC_HC_TRB        =             *Tr= b
+  );
+
+/**
+  Execute the specified TRB.
+
+  @= param[in] Private        A pointer to th= e DW_MMC_HC_PRIVATE_DATA
instance.
+  @param[in] Trb   &n= bsp;        The pointer to the DW_M= MC_HC_TRB instance.
+
+  @retval EFI_SUCCE= SS       The TRB is sent to host controller s= uccessfully.
+  @retval Others     &= nbsp;      Some erros happen when sending thi= s request to
the
+         &nb= sp;            =       host controller.
+
+**/
+EFI_STATUS
+DwMmcExecTrb (
+  IN DW_MMC_HC_PRIVATE_DATA      &nb= sp;    *Private,
+  IN DW_MMC_HC_TRB=             &n= bsp;      *Trb
+  );
+
+/**
+  Check the TRB execution= result.
+
+  @param[in] Private  &nb= sp;     A pointer to the DW_MMC_HC_PRIVATE_DATA
instance.
+  @param[in] Trb        = ;    The pointer to the DW_MMC_HC_TRB instance.
+
+  @retval EFI_SUCCESS     =   The TRB is executed successfully.
+  @retval= EFI_NOT_READY     The TRB is not completed for executi= on.
+  @retval Others      &nbs= p;     Some erros happen when executing this reque= st.
+
+**/
+EFI_STATUS
+DwMmcCheckTrbResult (
+  IN DW_MMC_HC_PRIVATE_DA= TA           *Private,+  IN DW_MMC_HC_TRB       &n= bsp;            = ;*Trb
+  );
+
+/**
+  Wait for the TRB execution result.
+
+  @param[in] Private        = ;A pointer to the DW_MMC_HC_PRIVATE_DATA
instanc= e.
+  @param[in] Tr= b            The poi= nter to the DW_MMC_HC_TRB instance.
+
+  @= retval EFI_SUCCESS       The TRB is executed = successfully.
+  @retval Others     =        Some erros happen when executing = this request.
+
+**/
+EFI_STATUS<= br class=3D"">+DwMmcWaitTrbResult (
+  IN DW_MMC_HC_PRIV= ATE_DATA           *Priva= te,
+  IN DW_MMC_HC_TRB      &n= bsp;            = ; *Trb
+  );
+
+/**
+  Execute EMMC device identification procedure.
+
+  Refer to EMMC Electrical Standard Spec 5.1 S= ection 6.4 for details.
+
+  @param[in] Pr= ivate        A pointer to the DW_MMC_HC_= PRIVATE_DATA
instance.
+
+  @retval EFI_SUCCESS  = ;     There is a EMMC card.
+  = @retval Others           =  There is not a EMMC card.
+
+**/
+EFI_STATUS
+EmmcIdentification (
+ &nbs= p;IN DW_MMC_HC_PRIVATE_DATA         = ;    *Private
+  );
+<= br class=3D"">+/**
+  Execute EMMC device identification= procedure.
+
+  Refer to EMMC Electrical = Standard Spec 5.1 Section 6.4 for details.
+
+ =  @param[in] Private        A pointe= r to the DW_MMC_HC_PRIVATE_DATA
instance.
+
+  @retva= l EFI_SUCCESS       There is a EMMC card.
+  @retval Others        = ;    There is not a EMMC card.
+
+**/
+EFI_STATUS
+SdCardIdentification (=
+  IN DW_MMC_HC_PRIVATE_DATA     &n= bsp;       *Private
+ &nbs= p;);
+
+#endif /* _DW_MMC_HC_DXE_H_ */
diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h
b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h
new file mode 100644
index = 000000000000..12ef58a37368
--- /dev/null
+++ b/= EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h
@@ -0,0 +1,985 @@+/** @file
+
+  Provides some= data structure definitions used by the SD/MMC host
controller
+  d= river.
+
+  Copyright (c) 2015, Intel Corp= oration. All rights reserved.<BR>
+  Copyright (c)= 2018, Linaro Ltd. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and= made
available
+  under the terms and conditions of the BSD Lic= ense which accompanies
this
+  distribution.  The full text of= the license may be found at
+  http://opensource.org/license= s/bsd-license.php
+
+  THE PROGRAM IS = DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
= BASIS,
+  WITHOUT W= ARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED.
++**/
+
+#ifndef _DW_MMC_HCI_H_
+#define _DW_MMC_HCI_H_
+
+#include = <Library/CacheMaintenanceLib.h>
+#include <Library/T= imerLib.h>
+
+#include <Protocol/Platform= DwMmc.h>
+
+//
+// SD Host Con= troller SlotInfo Register Offset
+//
+#define D= W_MMC_HC_SLOT_OFFSET         0x40+
+#define DW_MMC_HC_MAX_SLOT    =         1
+
+//
+// SD Host Controller MMIO Register Offset
+//
+#define DW_MMC_CTRL     &nbs= p;            &= nbsp;0x000
+#define DW_MMC_PWREN     &nbs= p;            0= x004
+#define DW_MMC_CLKDIV      &nb= sp;          0x008
+#define DW_MMC_CLKSRC        &n= bsp;        0x00c
+#d= efine DW_MMC_CLKENA          &= nbsp;      0x010
+#define DW_MM= C_TMOUT            &= nbsp;     0x014
+#define DW_MMC_CTYP= E             &= nbsp;    0x018
+#define DW_MMC_BLKSIZ &nb= sp;            =    0x01c
+#define DW_MMC_BYTCNT   &n= bsp;            = ; 0x020
+#define DW_MMC_INTMASK     =            0x024
+#define DW_MMC_CMDARG        = ;         0x028
= +#define DW_MMC_CMD          &= nbsp;         0x02c
+#define DW_MMC_RESP0        &nbs= p;         0x030
+#define DW_MMC_RESP1         &nbs= p;        0x034
+#def= ine DW_MMC_RESP2          &nbs= p;       0x038
+#define DW= _MMC_RESP3           &nbs= p;      0x03c
+#define DW_MMC_R= INTSTS            &n= bsp;   0x044
+#define DW_MMC_STATUS  &nbs= p;            &= nbsp; 0x048
+#define DW_MMC_FIFOTH    &nb= sp;            = 0x04c
+#define DW_MMC_GPIO      &nbs= p;            0= x058
+#define DW_MMC_DEBNCE      &nb= sp;          0x064
+#define DW_MMC_USRID        &nb= sp;         0x068
+#define DW_MMC_VERID         &nb= sp;        0x06c
+#de= fine DW_MMC_HCON          &nbs= p;        0x070
+#def= ine DW_MMC_UHSREG          &nb= sp;      0x074
+#define DW_MMC_= BMOD            &nbs= p;      0x080
+#define DW_MMC_D= BADDR            &nb= sp;    0x088
+#define DW_MMC_IDSTS  =             &nb= sp;   0x08c
+#define DW_MMC_IDINTEN  &nbs= p;            &= nbsp;0x090
+#define DW_MMC_DSCADDR     &n= bsp;          0x094
+#define DW_MMC_BUFADDR        =         0x098
+#defin= e DW_MMC_CARDTHRCTL          &= nbsp;  0x100
+#define DW_MMC_UHSREG_EXT   = ;          0x108
+#define DW_MMC_ENABLE_SHIFT       &nb= sp;   0x110
+#define DW_MMC_FIFO_START  &= nbsp;          0x200
+
+#define GET_IDSTS_DMAC_FSM(x)    =             &nb= sp;  (((x) >> 13) & 0xf)
+#define IDSTS_F= SM_DMA_IDLE           &nb= sp;          0
+#define IDSTS_FSM_DMA_SUSPEND       &= nbsp;           1+#define IDSTS_FSM_DESC_RD       =             &nb= sp;   2
+#define IDSTS_FSM_DESC_CHK  &nbs= p;            &= nbsp;      3
+#define IDSTS_FSM= _DMA_RD_REQ_WAIT          &nbs= p;    4
+#define IDSTS_FSM_DMA_WR_REQ_WAI= T             &= nbsp; 5
+#define IDSTS_FSM_DMA_RD    &nbs= p;            &= nbsp;      6
+#define IDSTS_FSM= _DMA_WR            &= nbsp;           7+#define IDSTS_FSM_DESC_CLOSE      &nb= sp;            =  8
+#define IDSTS_FSM_MASK      = ;            &n= bsp;       0xf
+
+#define CMD_UPDATE_CLK        &n= bsp;            = ;     0x80202000
+#define CMD_START_= BIT             = ;            &n= bsp; (1 << 31)
+
+#define MMC_8BIT_M= ODE             = ;            &n= bsp; (1 << 16)
+#define MMC_4BIT_MODE   =             &nb= sp;           (1 <= ;< 0)
+#define MMC_1BIT_MODE      = ;            &n= bsp;        0
+
+#define DW_MMC_BLOCK_SIZE       &nb= sp;            =    512
+
+#define CMD_INDEX_MASK=             &n= bsp;            = ;0x3F
+#define BIT_CMD_RESPONSE_EXPECT    &nbs= p;            (= 1 << 6)
+#define BIT_CMD_LONG_RESPONSE   &nbs= p;            &= nbsp;  (1 << 7)
+#define BIT_CMD_CHECK_RESPON= SE_CRC            &n= bsp; (1 << 8)
+#define BIT_CMD_DATA_EXPECTED  = ;            &n= bsp;    (1 << 9)
+#define BIT_CMD_R= EAD             = ;            &n= bsp;  (0 << 10)
+#define BIT_CMD_WRITE  =             &nb= sp;            = (1 << 10)
+#define BIT_CMD_BLOCK_TRANSFER   &= nbsp;           &nbs= p;  (0 << 11)
+#define BIT_CMD_STREAM_TRANSFE= R             &= nbsp;   (1 << 11)
+#define BIT_CMD_SEND_= AUTO_STOP            = ;      (1 << 12)
+#define= BIT_CMD_WAIT_PRVDATA_COMPLETE        &n= bsp;  (1 << 13)
+#define BIT_CMD_STOP_ABORT_C= MD             =      (1 << 14)
+#define BIT_CM= D_SEND_INIT           &nb= sp;           (1 <= ;< 15)
+#define BIT_CMD_UPDATE_CLOCK_ONLY   &nbs= p;           (1 <= < 21)
+#define BIT_CMD_READ_CEATA_DEVICE    = ;           (1 <&= lt; 22)
+#define BIT_CMD_CCS_EXPECTED     = ;            &n= bsp;  (1 << 23)
+#define BIT_CMD_ENABLE_BOOT =             &nb= sp;       (1 << 24)
= +#define BIT_CMD_EXPECT_BOOT_ACK        =          (1 << 25)
+#define BIT_CMD_DISABLE_BOOT       =             &nb= sp;(1 << 26)
+#define BIT_CMD_MANDATORY_BOOT  &nbs= p;            &= nbsp;  (0 << 27)
+#define BIT_CMD_ALTERNATE_B= OOT             = ;     (1 << 27)
+#define BIT_C= MD_VOLT_SWITCH           =           (1 << 28)=
+#define BIT_CMD_USE_HOLD_REG      =             &nb= sp; (1 << 29)
+#define BIT_CMD_START   &= nbsp;           &nbs= p;           (1 <= < 31)
+
+#define CMD_INDEX(x)   &n= bsp;            = ;            ((= x) & CMD_INDEX_MASK)
+
+#define DW_MMC_INT_= EBE             = ;            &n= bsp;(1 << 15)       /* End-bit Err */+#define DW_MMC_INT_SBE       &n= bsp;            = ;      (1 << 13)    &nbs= p;  /* Start-bit  Err */
+#define DW_MMC_INT_H= LE             =             &nb= sp;(1 << 12)       /* Hardware-lock
Err */
+#define DW_MMC_INT_FRUN        &= nbsp;           &nbs= p;    (1 << 11)      &nb= sp;/* FIFO UN/OV
RUN */
+#define DW_MMC_INT_DRT     =             &nb= sp;        (1 << 9)  &nb= sp;     /* Data timeout */
+#define = DW_MMC_INT_RTO           =             &nb= sp;  (1 << 8)        /* = Response
timeout */
+#define DW_MMC_INT_DCRC     &nb= sp;            =        (1 << 7)    =     /* Data CRC err */
+#define DW_MMC_IN= T_RCRC            &n= bsp;            = ;(1 << 6)        /* Response CRC
err */
+#define DW_MMC_INT_RXDR        = ;            &n= bsp;    (1 << 5)      &n= bsp; /* Receive FIFO
data request */
+#define DW_MMC_INT_TXDR  = ;            &n= bsp;          (1 <<= 4)        /* Transmit FIFO
data request */
+#define DW_MMC_INT_DTO        &n= bsp;            = ;     (1 << 3)      = ;  /* Data trans over
*/
+#define DW_MMC_INT_CMD_DONE  &n= bsp;            = ;      (1 << 2)     = ;   /* Command
done */
+#define DW_MMC_INT_RE  &n= bsp;            = ;            (1= << 1)        /* Response error */=
+
+#define DW_MMC_IDMAC_DES0_DIC   &= nbsp;           &nbs= p;   (1 << 1)
+#define DW_MMC_IDMAC_DES0= _LD             = ;       (1 << 2)
+#d= efine DW_MMC_IDMAC_DES0_FS         =            (1 <&l= t; 3)
+#define DW_MMC_IDMAC_DES0_CH     &= nbsp;           &nbs= p;  (1 << 4)
+#define DW_MMC_IDMAC_DES0_ER &n= bsp;            = ;      (1 << 5)
+#define = DW_MMC_IDMAC_DES0_CES          = ;         (1 << 30)
+#define DW_MMC_IDMAC_DES0_OWN      &nbs= p;            (= 1 << 31)
+#define DW_MMC_IDMAC_DES1_BS1(x)   =             &nb= sp;((x) & 0x1fff)
+#define DW_MMC_IDMAC_DES2_BS2(x)  = ;            &n= bsp; (((x) & 0x1fff) << 13)
+#define DW_MMC_ID= MAC_SWRESET           &nb= sp;        (1 << 0)
+#define DW_MMC_IDMAC_FB        &= nbsp;           &nbs= p;    (1 << 1)
+#define DW_MMC_IDMA= C_ENABLE            =          (1 << 7)
+
+#define DW_MMC_CTRL_RESET     =             &nb= sp;     (1 << 0)
+#define DW_M= MC_CTRL_FIFO_RESET          &n= bsp;       (1 << 1)
= +#define DW_MMC_CTRL_DMA_RESET        &n= bsp;          (1 <<= 2)
+#define DW_MMC_CTRL_INT_EN      = ;            &n= bsp;   (1 << 4)
+#define DW_MMC_CTRL_DMA= _EN             = ;         (1 << 5)
+#define DW_MMC_CTRL_IDMAC_EN       =             &nb= sp;(1 << 25)
+#define DW_MMC_CTRL_RESET_ALL   = ;            &n= bsp;   (DW_MMC_CTRL_RESET |
DW_MM= C_CTRL_FIFO_RESET | DW_MMC_CTRL_DMA_RESET)
+
+#define DW_MMC_STS_DATA_BUSY  &= nbsp;           &nbs= p;     (1 << 9)
+#define DW_MM= C_STS_FIFO_COUNT(x)          &= nbsp;     (((x) & 0x1fff) << 17)  &= nbsp;/*
Number of filled locations in FIFO */
+#define GET_STS_FIFO_COUN= T(x)            &nbs= p;      (((x) >> 17) & 0x1fff)
+#define DW_MMC_STS_FIFO_FULL(x)      &n= bsp;          (((x) >&= gt; 3) & 1)
+
+#define DW_MMC_BMOD_SWR &nbs= p;            &= nbsp;          (1 <<= ; 0)         /* Software
Reset */
+#define DW_MMC_BMOD_FB        &n= bsp;            = ;     (1 << 1)      = ;   /* Fix Burst */
+#define DW_MMC_BMOD_DE &n= bsp;            = ;            (1= << 7)         /* IDMAC Enabl= e
*/
+
+#define DW_MMC_IDSTS_TI     &n= bsp;            = ;       (1 << 0)    = ;     /* Transmit
Inter= rupt */
+#define DW_MMC_= IDSTS_RI            =             &nb= sp;(1 << 1)         /* Receiv= e Interrupt
*/
+
+#define DW_MMC_FIFO_TWMARK(x)  &nbs= p;            &= nbsp;   ((x) & 0xfff)
+#define DW_MMC_FIFO= _RWMARK(x)           &nbs= p;       (((x) & 0x1ff) << 16)=
+#define DW_MMC_DMA_BURST_SIZE(x)     &n= bsp;          (((x) &= 0x7) << 28)
+
+#define DW_MMC_CARD_RD_TH= R(x)            &nbs= p;      (((x) & 0xfff) << 16)
+#define DW_MMC_CARD_RD_THR_EN       = ;            (1= << 0)
+
+#define UHS_DDR_MODE  &nbs= p;            &= nbsp;           &nbs= p;(1 << 16)
+
+#define GENCLK_DIV  &= nbsp;           &nbs= p;            &= nbsp;  7
+
+#define DW_MMC_GPIO_CLK_D= IV(x)            &nb= sp;     (((x) & 0xf) << 8)
+#define DW_MMC_GPIO_USE_SAMPLE_DLY(x)       = ;    (((x) & 1) << 13)
+#define= DW_MMC_GPIO_CLK_ENABLE         &nb= sp;        BIT16
++#define UHSEXT_SAMPLE_PHASE(x)      &= nbsp;           (((x= ) & 0x1f) << 16)
+#define UHSEXT_SAMPLE_DRVPHASE(x)=             &n= bsp; (((x) & 0x1f) << 21)
+#define UHSEXT_SAMP= LE_DLY(x)            = ;        (((x) & 0x1f) <<= 26)
+
+#define DWMMC_DMA_BUF_SIZE   =             &nb= sp;      (512 * 8)
+#define DWM= MC_FIFO_THRESHOLD          &nb= sp;         16
+=
+#define DWMMC_INIT_CLOCK_FREQ      = ;            &n= bsp;400            &= nbsp; /* KHz */
+
+//
+// Th= e transfer modes supported by SD Host Controller
+// Simplifi= ed Spec 3.0 Table 1-2
+//
+typedef enum {
+  SdMmcNoData,
+  SdMmcPioMode,
+  SdMmcSdmaMode,
+  SdMmcAdmaMode
+} DW_MMC_HC_TRANSFER_MODE;
+
+//
+// The maximum data length of each descriptor line
+= //
+#define ADMA_MAX_DATA_PER_LINE     0x= 10000
+
+typedef struct {
+  = ;UINT32   Des0;
+  UINT32   Des1;+  UINT32   Des2;
+  UINT32 &= nbsp; Des3;
+} DW_MMC_HC_DMA_DESC_LINE;
+<= br class=3D"">+#define SD_MMC_SDMA_BOUNDARY      &= nbsp;   512 * 1024
+#define SD_MMC_SDMA_ROUND_= UP(x, n)    (((x) + n) & ~(n - 1))
+
+typedef struct {
+  UINT8    Fi= rstBar:3;        // bit 0:2
+  UINT8    Reserved:1;      = ;  // bit 3
+  UINT8    SlotNum= :3;         // bit 4:6
+  UINT8    Reserved1:1;     &nbs= p; // bit 7
+} DW_MMC_HC_SLOT_INFO;
+
+/**
+  Dump the content of SD/MMC host contro= ller's Capability Register.
+
+  @param[in= ]  Slot           &n= bsp;The slot number of the SD card to send the
c= ommand to.
+  @para= m[in]  Capability      The buffer to store th= e capability data.
+
+**/
+VOID+DumpCapabilityReg (
+  IN UINT8  &nbs= p;            &= nbsp;Slot,
+  IN DW_MMC_HC_SLOT_CAP   *Capabil= ity
+  );
+
+#if 0
+/**
+  Read SlotInfo register from SD/MMC host c= ontroller pci config space.
+
+  @param[in= ]  PciIo        The PCI IO protocol= instance.
+  @param[out] FirstBar    &nb= sp;The buffer to store the first BAR value.
+  @param[ou= t] SlotNum      The buffer to store the supported = slot number.
+
+  @retval EFI_SUCCESS &nbs= p;    The operation succeeds.
+  @re= tval Others           The= operation fails.
+
+**/
+EFI_STA= TUS
+EFIAPI
+DwMmcHcGetSlotInfo (
+  IN     EFI_PCI_IO_PROTOCOL   *PciIo,=
+     OUT UINT8     =             *Fi= rstBar,
+     OUT UINT8    = ;            &n= bsp;*SlotNum
+  );
+#endif
+=
+#ifdef DWMMC_PCI
+/**
+  R= ead/Write specified SD/MMC host controller mmio register.
++  @param[in]      PciIo  &= nbsp;     The PCI IO protocol instance.
+  @param[in]      BarIndex  &nbs= p;  The BAR index of the standard PCI
= Configuration
+  &n= bsp;            = ;            &n= bsp;   header to use as the base address for the memory
+           &nb= sp;            =        operation to perform.
+  @param[in]      Offset   &nbs= p;   The offset within the selected BAR to start the
+            =             &nb= sp;      memory operation.
+ &n= bsp;@param[in]      Read     &= nbsp;   A boolean to indicate it's read or write
operation.
+  @param[in]      Count    = ;    The width of the mmio register in bytes.
+            =             &nb= sp;      Must be 1, 2 , 4 or 8 bytes.
+  @param[in, out] Data       &nb= sp; For read operations, the destination buffer to
store
+  &n= bsp;            = ;            &n= bsp;   the results. For write operations, the source buffer<= br class=3D"">+           = ;            &n= bsp;       to write data from. The calle= r is responsible for
+       &n= bsp;            = ;           having o= wnership of the data buffer and ensuring its
+   &n= bsp;            = ;            &n= bsp;  size not less than Count bytes.
+
+  @retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the C= ount
is not valid.
+  @retval EFI_SUCCESS     &= nbsp;     The read/write operation succeeds.
+  @retval Others        &= nbsp;       The read/write operation fai= ls.
+
+**/
+EFI_STATUS
+EFIAPI
+DwMmcHcRwMmio (
+  IN &nbs= p;   EFI_PCI_IO_PROTOCOL   *PciIo,
+=  IN     UINT8       = ;          BarIndex,
+  IN     UINT32     = ;           Offset,<= br class=3D"">+  IN     BOOLEAN    =            Read,
+  IN     UINT8     = ;            Co= unt,
+  IN OUT VOID       =            *Data
+  );
+#else
+/**
+  Read/Write specified SD/MMC host controller mmio register.
+
+  @param[in]      Dev= Io        The DEVICE IO protocol instanc= e.
+  @param[in]      Offset &n= bsp;     The offset within the selected BAR to sta= rt the
+         &nbs= p;            &= nbsp;        memory operation.
+  @param[in]      Read   = ;      A boolean to indicate it's read or wri= te
operation.
+  @param[in]      Count &nb= sp;      The width of the mmio register in by= tes.
+          =             &nb= sp;        Must be 1, 2 , 4 or 8 by= tes.
+  @param[in, out] Data     &nb= sp;   For read operations, the destination buffer to
store
+             = ;            &n= bsp;     the results. For write operations, the so= urce buffer
+         = ;            &n= bsp;         to write data fro= m. The caller is responsible for
+     &n= bsp;            = ;            &n= bsp;having ownership of the data buffer and ensuring its
+ &n= bsp;            = ;            &n= bsp;    size not less than Count bytes.
+=
+  @retval EFI_INVALID_PARAMETER The PciIo or Data is N= ULL or the Count
is not valid.
+  @retval EFI_SUCCESS   &= nbsp;       The read/write operation suc= ceeds.
+  @retval Others      &= nbsp;         The read/write o= peration fails.
+
+**/
+EFI_STATU= S
+EFIAPI
+DwMmcHcRwMmio (
+ &nbs= p;IN     UINTN       &nbs= p;           DevBase= ,
+  IN     UINT32    = ;            &n= bsp;  Offset,
+  IN     BO= OLEAN            &nb= sp;     Read,
+  IN   = ;  UINT8          &n= bsp;         Count,
+  IN OUT VOID         =             *Da= ta
+  );
+#endif
+
+#ifdef DWMMC_PCI
+/**
+  Do OR ope= ration with the value of the specified SD/MMC host controller
mmio register.
+
+  @param[in] PciIo     &nb= sp;       The PCI IO protocol instance.<= br class=3D"">+  @param[in] BarIndex      &nb= sp;   The BAR index of the standard PCI
Configuration
+ &= nbsp;           &nbs= p;            &= nbsp;    header to use as the base address for the memo= ry
+          &n= bsp;            = ;        operation to perform.
+  @param[in] Offset       &nb= sp;    The offset within the selected BAR to start the<= br class=3D"">+           = ;            &n= bsp;       memory operation.
+  @param[in] Count         = ;    The width of the mmio register in bytes.
+            =             &nb= sp;      Must be 1, 2 , 4 or 8 bytes.
+  @param[in] OrData        =     The pointer to the data used to do OR
operation.
+             =             &nb= sp;     The caller is responsible for having owner= ship of
+         &nb= sp;            =          the data buffer and e= nsuring its size not less than
+     &nbs= p;            &= nbsp;           &nbs= p;Count bytes.
+
+  @retval EFI_INVALID_PA= RAMETER The PciIo or OrData is NULL or the
Count= is not valid.
+  @= retval EFI_SUCCESS          &n= bsp;The OR operation succeeds.
+  @retval Others  &= nbsp;           &nbs= p; The OR operation fails.
+
+**/
+EFI_STATUS
+EFIAPI
+DwMmcHcOrMmio (
+  IN  EFI_PCI_IO_PROTOCOL     &nb= sp;*PciIo,
+  IN  UINT8     &nb= sp;            =   BarIndex,
+  IN  UINT32   &nb= sp;            =    Offset,
+  IN  UINT8   =             &nb= sp;    Count,
+  IN  VOID  = ;            &n= bsp;      *OrData
+  );+#else
+/**
+  Do OR operation= with the value of the specified SD/MMC host controller
mmio register.
+=
+  @param[in] DevIo       = ;      The DEVICE IO protocol instance.
+  @param[in] BarIndex       &n= bsp;  The BAR index of the standard PCI
Configuration
+  =             &nb= sp;            =     header to use as the base address for the memory+           &= nbsp;           &nbs= p;       operation to perform.
+  @param[in] Offset        =     The offset within the selected BAR to start the
+           &n= bsp;            = ;       memory operation.
= +  @param[in] Count         &n= bsp;   The width of the mmio register in bytes.
+             = ;            &n= bsp;     Must be 1, 2 , 4 or 8 bytes.
+  @param[in] OrData         = ;   The pointer to the data used to do OR
operation.
+ &n= bsp;            = ;            &n= bsp;    The caller is responsible for having ownership = of
+          &n= bsp;            = ;        the data buffer and ensuri= ng its size not less than
+      &nb= sp;            =             Cou= nt bytes.
+
+  @retval EFI_INVALID_PARAMET= ER The PciIo or OrData is NULL or the
Count is n= ot valid.
+  @retva= l EFI_SUCCESS           T= he OR operation succeeds.
+  @retval Others   =             &nb= sp;The OR operation fails.
+
+**/
+EFI_STATUS
+EFIAPI
+DwMmcHcOrMmio (
+  IN     UINTN     &nb= sp;            =  DevBase,
+  IN  UINT32    &nbs= p;            &= nbsp; Offset,
+  IN  UINT8    &= nbsp;           &nbs= p;   Count,
+  IN  VOID   =             &nb= sp;     *OrData
+  );
+#endif
+
+#ifdef DWMMC_PCI
+/**
+  Do AND operation with the value of the specifi= ed SD/MMC host
controller mmio register.
+
+  @param[= in] PciIo            = ; The PCI IO protocol instance.
+  @param[in] BarIn= dex          The BAR index of = the standard PCI
Configuration
+       &nb= sp;            =            header to= use as the base address for the memory
+    &= nbsp;           &nbs= p;            &= nbsp; operation to perform.
+  @param[in] Offset &n= bsp;          The offset = within the selected BAR to start the
+    &nbs= p;            &= nbsp;           &nbs= p; memory operation.
+  @param[in] Count  &nbs= p;          The width of = the mmio register in bytes.
+      &= nbsp;           &nbs= p;            M= ust be 1, 2 , 4 or 8 bytes.
+  @param[in] AndData  =          The pointer to the da= ta used to do AND
operation.
+        = ;            &n= bsp;          The caller = is responsible for having ownership of
+    &n= bsp;            = ;            &n= bsp; the data buffer and ensuring its size not less than
+             =             &nb= sp;     Count bytes.
+
+  @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the<= br class=3D"">
Count is not valid.
+  @retval EFI_SUCCESS     =       The AND operation succeeds.
+  @retval Others         &= nbsp;      The AND operation fails.
+
+**/
+EFI_STATUS
+EFIAPI=
+DwMmcHcAndMmio (
+  IN  EFI_PCI_IO_= PROTOCOL      *PciIo,
+  IN &nb= sp;UINT8            =         BarIndex,
+ &= nbsp;IN  UINT32          =          Offset,
+  IN  UINT8         &nb= sp;          Count,
+  IN  VOID        &n= bsp;            = ;*AndData
+  );
+#else
+/**<= br class=3D"">+  Do AND operation with the value of the specified SD/M= MC host
controller mmio register.
=
+
+  @param[in] Dev= Io             = The DEVICE IO protocol instance.
+  @param[in] Offset &n= bsp;          The offset = within the selected BAR to start the
+    &nbs= p;            &= nbsp;           &nbs= p; memory operation.
+  @param[in] Count  &nbs= p;          The width of = the mmio register in bytes.
+      &= nbsp;           &nbs= p;            M= ust be 1, 2 , 4 or 8 bytes.
+  @param[in] AndData  =          The pointer to the da= ta used to do AND
operation.
+        = ;            &n= bsp;          The caller = is responsible for having ownership of
+    &n= bsp;            = ;            &n= bsp; the data buffer and ensuring its size not less than
+             =             &nb= sp;     Count bytes.
+
+  @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the<= br class=3D"">
Count is not valid.
+  @retval EFI_SUCCESS     =       The AND operation succeeds.
+  @retval Others         &= nbsp;      The AND operation fails.
+
+**/
+EFI_STATUS
+EFIAPI=
+DwMmcHcAndMmio (
+  IN  UINTN  = ;            &n= bsp;     DevBase,
+  IN  U= INT32            &nb= sp;      Offset,
+  IN &nb= sp;UINT8            =         Count,
+ &nbs= p;IN  VOID           = ;          *AndData
+  );
+#endif
+
+#i= fdef DWMMC_PCI
+/**
+  Wait for the value = of the specified MMIO register set to the test value.
+
+  @param[in]  PciIo       = ;  The PCI IO protocol instance.
+  @param[in]=  BarIndex      The BAR index of the standard= PCI
Configuration
+         &nb= sp;            =       header to use as the base address for t= he memory
+         &= nbsp;           &nbs= p;      operation to perform.
+=  @param[in]  Offset        Th= e offset within the selected BAR to start the
+   &= nbsp;           &nbs= p;            m= emory operation.
+  @param[in]  Count   &= nbsp;     The width of the mmio register in bytes.=
+          &nbs= p;            &= nbsp;    Must be 1, 2, 4 or 8 bytes.
+ &n= bsp;@param[in]  MaskValue     The mask value of me= mory.
+  @param[in]  TestValue    &n= bsp;The test value of memory.
+  @param[in]  Timeou= t       The time out value for wait memory se= t, uses 1
+         &= nbsp;           &nbs= p;      microsecond as a unit.
= +
+  @retval EFI_TIMEOUT      &= nbsp;The MMIO register hasn't expected value in
= timeout
+   &n= bsp;            = ;            ra= nge.
+  @retval EFI_SUCCESS     &nbs= p; The MMIO register has expected value.
+  @retval= Others            T= he MMIO operation fails.
+
+**/
+= EFI_STATUS
+EFIAPI
+DwMmcHcWaitMmioSet (
+  IN  EFI_PCI_IO_PROTOCOL      =  *PciIo,
+  IN  UINT8     =             &nb= sp;   BarIndex,
+  IN  UINT32  =             &nb= sp;     Offset,
+  IN  UIN= T8             =         Count,
+ &nbs= p;IN  UINT64          &nb= sp;         MaskValue,
+  IN  UINT64        &n= bsp;           TestV= alue,
+  IN  UINT64      &= nbsp;           &nbs= p; Timeout
+  );
+#else
+/**
+  Wait for the value of the specified MMIO regist= er set to the test value.
+
+  @param[in] =  DevIo         The DEVICE IO p= rotocol instance.
+  @param[in]  Offset   = ;     The offset within the selected BAR to start = the
+          &= nbsp;           &nbs= p;     memory operation.
+  @pa= ram[in]  Count         The wid= th of the mmio register in bytes.
+     &= nbsp;           &nbs= p;          Must be 1, 2,= 4 or 8 bytes.
+  @param[in]  MaskValue   = ;  The mask value of memory.
+  @param[in] &nb= sp;TestValue     The test value of memory.
+  @param[in]  Timeout       The = time out value for wait memory set, uses 1
+   &nbs= p;            &= nbsp;           micr= osecond as a unit.
+
+  @retval EFI_TIMEOU= T       The MMIO register hasn't expected val= ue in
timeout
+          &n= bsp;            = ;     range.
+  @retval EFI_SUC= CESS       The MMIO register has expected val= ue.
+  @retval Others      &nbs= p;     The MMIO operation fails.
++**/
+EFI_STATUS
+EFIAPI
+DwMmcHcWaitMmioSet (
+  IN  UINTN  &nb= sp;            =      DevBase,
+  IN  UINT3= 2             &= nbsp;      Offset,
+  IN &= nbsp;UINT8           &nbs= p;         Count,
+  IN  UINT64         &= nbsp;          MaskValue,=
+  IN  UINT64       =             &nb= sp;TestValue,
+  IN  UINT64     = ;            &n= bsp;  Timeout
+  );
+#endif
+
+#ifdef DWMMC_PCI
+/**
+  Software reset the specified SD/MMC host controller.
+
+  @param[in] PciIo      &n= bsp;   The PCI IO protocol instance.
+  @= param[in] Slot           = The slot number of the SD card to send the
comma= nd to.
+
+=  @retval EFI_SUCCESS       The software= reset executes successfully.
+  @retval Others  &n= bsp;         The software rese= t fails.
+
+**/
+EFI_STATUS
+DwMmcHcReset (
+fark
+  IN EFI_P= CI_IO_PROTOCOL    *PciIo,
+  IN UINT8 &nb= sp;            =     Slot,
+  IN DW_MMC_HC_SLOT_CAP &= nbsp;   Capability
+  );
+#= else
+/**
+  Software reset the specified = SD/MMC host controller.
+
+  @param[in] De= vIo          The DEVICE IO pro= tocol instance.
+
+  @retval EFI_SUCCESS &= nbsp;     The software reset executes successfully= .
+  @retval Others       =      The software reset fails.
+
+**/
+EFI_STATUS
+DwMmcHcReset (
+  IN UINTN         = ;           DevBase,=
+  IN DW_MMC_HC_SLOT_CAP     Capabi= lity
+  );
+#endif
+
+#ifdef DWMMC_PCI
+/**
+  Set all i= nterrupt status bits in Normal and Error Interrupt Status Enable
+  register.
+
+  @param[in] P= ciIo          The PCI IO proto= col instance.
+  @param[in] Slot     = ;      The slot number of the SD card to send= the
command to.
+
+  @retval EFI_SUCCESS  &nb= sp;    The operation executes successfully.
+  @retval Others         &= nbsp;  The operation fails.
+
+**/+EFI_STATUS
+DwMmcHcEnableInterrupt (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+=  IN UINT8           = ;       Slot
+  );+#else
+/**
+  Set all interru= pt status bits in Normal and Error Interrupt Status Enable
+ =  register.
+
+  @param[in] DevIo &nbs= p;        The DEVICE IO protocol in= stance.
+  @param[in] Slot      = ;     The slot number of the SD card to send the
command to.
+
+  @retval EFI_SUCCESS    = ;   The operation executes successfully.
+ &nb= sp;@retval Others          &nb= sp; The operation fails.
+
+**/
+EFI_STATUS
+DwMmcHcEnableInterrupt (
+ =  IN  UINTN          =           DevBase
+  );
+#endif
+
+#ifd= ef DWMMC_PCI
+/**
+  Get the capability da= ta from the specified slot.
+
+  @param[in= ]  PciIo           T= he PCI IO protocol instance.
+  @param[in]  Slot &n= bsp;          The slot nu= mber of the SD card to send the
command to.
+  @param[out] Capabili= ty      The buffer to store the capability data.+
+  @retval EFI_SUCCESS    =      The operation executes successfully.
+  @retval Others        &nb= sp;     The operation fails.
+
+**/
+EFI_STATUS
+DwMmcHcGetCapability= (
+  IN     EFI_PCI_IO_PROTOCOL &nb= sp;*PciIo,
+  IN     EFI_HANDLE &nbs= p;         Controller,
+  IN     UINT8     &nb= sp;          Slot,
+     OUT DW_MMC_HC_SLOT_CAP   *Capab= ility
+  );
+#else
+/**
+  Get the capability data from the specified slot.
+
+  @param[in]  DevIo    &nb= sp;      The DEVICE IO protocol instance.
+  @param[in]  Slot      &nbs= p;     The slot number of the SD card to send the<= br class=3D"">
command to.
+  @param[out] Capability      = ;The buffer to store the capability data.
+
+ &= nbsp;@retval EFI_SUCCESS         Th= e operation executes successfully.
+  @retval Others &nb= sp;            = The operation fails.
+
+**/
+EFI_= STATUS
+DwMmcHcGetCapability (
+  IN  = ;UINTN            &n= bsp;       DevBase,
+ &nbs= p;IN     EFI_HANDLE       = ;       Controller,
+ &nbs= p;IN     UINT8       &nbs= p;           Slot,+     OUT DW_MMC_HC_SLOT_CAP   &= nbsp;  *Capability
+  );
+#endif=
+
+#if 0
+/**
+ &n= bsp;Get the maximum current capability data from the specified slot.
+
+  @param[in]  PciIo    &n= bsp;      The PCI IO protocol instance.
+  @param[in]  Slot       =      The slot number of the SD card to send the
command to.
+  @param[out] MaxCurrent      T= he buffer to store the maximum current
capabilit= y data.
+
= +  @retval EFI_SUCCESS         = ;The operation executes successfully.
+  @retval Others =             &nb= sp;The operation fails.
+
+**/
+E= FI_STATUS
+DwMmcHcGetMaxCurrent (
+  IN &n= bsp;   EFI_PCI_IO_PROTOCOL  *PciIo,
+ &nb= sp;IN     UINT8       &nb= sp;        Slot,
+ &n= bsp;   OUT UINT64        =        *MaxCurrent
+  = ;);
+#endif
+
+#ifdef DWMMC_PCI+/**
+  Detect whether there is a SD/MMC ca= rd attached at the specified
SD/MMC host control= ler
+  slot.
+
+  Refer to SD Host Controller Simplified spec= 3.0 Section 3.1 for details.
+
+  @param[= in]  PciIo         The PCI IO = protocol instance.
+  @param[in]  Slot   =        The slot number of the SD card to= send the
command to.
+  @param[out] MediaPresent  The pointer= to the media present boolean
value.
+
+  @retval EFI= _SUCCESS       There is no media change happe= ned.
+  @retval EFI_MEDIA_CHANGED There is media change = happened.
+  @retval Others     &nbs= p;      The detection fails.
+<= br class=3D"">+**/
+EFI_STATUS
+DwMmcHcCardDete= ct (
+  IN     EFI_PCI_IO_PROTOCOL &= nbsp;*PciIo,
+  IN     EFI_HANDLE &n= bsp;         Controller,
+  IN     UINT8     &= nbsp;          Slot,
+     OUT BOOLEAN     &nb= sp;        *MediaPresent
+  );
+#else
+/**
+ &= nbsp;Detect whether there is a SD/MMC card attached at the specified
SD/MMC host controller
+  slot.
+
+  R= efer to SD Host Controller Simplified spec 3.0 Section 3.1 for details.
+
+  @param[in]  DevIo    = ;     The DEVICE IO protocol instance.
+  @param[in]  Slot        =   The slot number of the SD card to send the
command to.
+ &nb= sp;@param[out] MediaPresent  The pointer to the media present boolean<= br class=3D"">
value.
+
+  @retval EFI_SUCCESS    &nb= sp;  There is no media change happened.
+  @re= tval EFI_MEDIA_CHANGED There is media change happened.
+ &nbs= p;@retval Others          &nbs= p; The detection fails.
+
+**/
+EFI_STATUS
+DwMmcHcCardDetect (
+  IN =     UINTN        &nb= sp;          DevBase,
+  IN     EFI_HANDLE    =           Controller,
+  IN     UINT8     = ;            &n= bsp; Slot,
+     OUT BOOLEAN  &= nbsp;           &nbs= p;  *MediaPresent
+  );
+#endif<= br class=3D"">+
+#ifdef DWMMC_PCI
+/**
+  Stop SD/MMC card clock.
+
+ &nbs= p;Refer to SD Host Controller Simplified spec 3.0 Section 3.2.2 for details= .
+
+  @param[in] PciIo    =       The PCI IO protocol instance.
+  @param[in] Slot        &n= bsp;  The slot number of the SD card to send the
command to.
+=
+  @retval EFI_SUCCESS      &n= bsp;Succeed to stop SD/MMC clock.
+  @retval Others &nbs= p;          Fail to stop = SD/MMC clock.
+
+**/
+EFI_STATUS<= br class=3D"">+DwMmcHcStopClock (
+  IN EFI_PCI_IO_PROTO= COL    *PciIo,
+  IN UINT8   &n= bsp;            = ;  Slot
+  );
+
+/= **
+  SD/MMC card clock supply.
+
+  Refer to SD Host Controller Simplified spec 3.0 Section 3.2.= 1 for details.
+
+  @param[in] PciIo  = ;        The PCI IO protocol instan= ce.
+  @param[in] Slot      &nb= sp;    The slot number of the SD card to send the
command to.
+  @param[in] ClockFreq      The ma= x clock frequency to be set. The unit is
KHz.
+  @param[in] Capabil= ity     The capability of the slot.
+
+  @retval EFI_SUCCESS       = The clock is supplied successfully.
+  @retval Others &n= bsp;          The clock i= sn't supplied successfully.
+
+**/
+EFI_STATUS
+DwMmcHcClockSupply (
+  IN = EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT= 8             &= nbsp;    Slot,
+  IN UINT64  &n= bsp;            = ;  ClockFreq,
+  IN DW_MMC_HC_SLOT_CAP  &= nbsp;  Capability
+  );
+#else+/**
+  Stop SD/MMC card clock.
+
+  Refer to SD Host Controller Simplified spec 3.0 = Section 3.2.2 for details.
+
+  @param[in]= DevIo          The DEVICE IO = protocol instance.
+
+  @retval EFI_SUCCES= S       Succeed to stop SD/MMC clock.
+  @retval Others        &nb= sp;   Fail to stop SD/MMC clock.
+
+**/
+EFI_STATUS
+DwMmcHcStopClock (
+  IN  UINTN        &nb= sp;           DevBas= e
+  );
+
+/**
+  SD/MMC card clock supply.
+
+  Re= fer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for details.+
+  @param[in] DevIo    &nbs= p;     The DEVICE IO protocol instance.
+  @param[in] ClockFreq      The max c= lock frequency to be set. The unit is
KHz.
+  @param[in] Capability=     The capability of the slot.
+
+  @retval EFI_SUCCESS       The= clock is supplied successfully.
+  @retval Others  = ;          The clock isn'= t supplied successfully.
+
+**/
+= EFI_STATUS
+DwMmcHcClockSupply (
+  IN &nb= sp;UINTN            =         DevBase,
+ &n= bsp;IN UINT64           &= nbsp;     ClockFreq,
+  IN DW_M= MC_HC_SLOT_CAP     Capability
+  );<= br class=3D"">+#endif
+
+#if 0
+/= **
+  SD/MMC bus power control.
+
+  Refer to SD Host Controller Simplified spec 3.0 Section 3.3 = for details.
+
+  @param[in] PciIo  &= nbsp;       The PCI IO protocol instance= .
+  @param[in] Slot       = ;    The slot number of the SD card to send the
command to.
+  @param[in] PowerCtrl      The valu= e setting to the power control register.
+
+ &n= bsp;@retval TRUE          &nbs= p;   There is a SD/MMC card attached.
+  = @retval FALSE           &= nbsp; There is no a SD/MMC card attached.
+
+**/
+EFI_STATUS
+DwMmcHcPowerControl (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8         &nb= sp;        Slot,
+ &n= bsp;IN UINT8           &n= bsp;      PowerCtrl
+  );<= br class=3D"">+#endif
+
+#ifdef DWMMC_PCI
+/**
+  Set the SD/MMC bus width.
+
+  Refer to SD Host Controller Simplified spec 3.0 Se= ction 3.4 for details.
+
+  @param[in] Pci= Io          The PCI IO protoco= l instance.
+  @param[in] Slot     &= nbsp;     The slot number of the SD card to send t= he
command to.
+  @param[in] BusWidth      = ; The bus width used by the SD/MMC device, it
must be 1, 4 or 8.
+<= br class=3D"">+  @retval EFI_SUCCESS      &nb= sp;The bus width is set successfully.
+  @retval Others =            The bus w= idth isn't set successfully.
+
+**/
+EFI_STATUS
+DwMmcHcSetBusWidth (
+  IN= EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UIN= T8             =      Slot,
+  IN BOOLEAN  =             &nb= sp; IsDdr,
+  IN UINT16     &nb= sp;           BusWid= th
+  );
+#else
+/**
+  Set the SD/MMC bus width.
+
+ &n= bsp;Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for details= .
+
+  @param[in] DevIo    =       The DEVICE IO protocol instance.
+  @param[in] BusWidth       The= bus width used by the SD/MMC device, it
must be= 1, 4 or 8.
+
+  @retval EFI_SUCCESS       The = bus width is set successfully.
+  @retval Others  &= nbsp;         The bus width is= n't set successfully.
+
+**/
+EFI= _STATUS
+DwMmcHcSetBusWidth (
+  IN  = UINTN            &nb= sp;       DevBase,
+  = ;IN BOOLEAN           &nb= sp;    IsDdr,
+  IN UINT16  &nb= sp;            =   BusWidth
+  );
+#endif
+
+#ifdef DWMMC_PCI
+/**
+=  Supply SD/MMC card with lowest clock frequency at initialization.+
+  @param[in] PciIo    &nbs= p;     The PCI IO protocol instance.
+  @param[in] Slot         &n= bsp; The slot number of the SD card to send the
command to.
+  = ;@param[in] Capability     The capability of the slot.<= br class=3D"">+
+  @retval EFI_SUCCESS    = ;   The clock is supplied successfully.
+ &nbs= p;@retval Others          &nbs= p; The clock isn't supplied successfully.
+
+**/
+EFI_STATUS
+DwMmcHcInitClockFreq (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8         &nb= sp;        Slot,
+ &n= bsp;IN DW_MMC_HC_SLOT_CAP     Capability
= +  );
+#else
+/**
+  Su= pply SD/MMC card with lowest clock frequency at initialization.
+
+  @param[in] DevIo      &= nbsp;   The DEVICE IO protocol instance.
+ &nb= sp;@param[in] Capability     The capability of the slot= .
+
+  @retval EFI_SUCCESS   &nb= sp;   The clock is supplied successfully.
+ &n= bsp;@retval Others          &n= bsp; The clock isn't supplied successfully.
+
+**/
+EFI_STATUS
+DwMmcHcInitClockFreq (=
+  IN UINTN        &= nbsp;         DevBase,
+  IN DW_MMC_HC_SLOT_CAP     Capability
+  );
+#endif
+
+= #ifdef DWMMC_PCI
+/**
+  Supply SD/MMC car= d with maximum voltage at initialization.
+
+ &= nbsp;Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for detail= s.
+
+  @param[in] PciIo    = ;      The PCI IO protocol instance.
+  @param[in] Slot        &n= bsp;  The slot number of the SD card to send the
command to.
+=  @param[in] Capability     The capability of the = slot.
+
+  @retval EFI_SUCCESS   = ;    The voltage is supplied successfully.
+  @retval Others         &n= bsp;  The voltage isn't supplied successfully.
++**/
+EFI_STATUS
+DwMmcHcInitPowerV= oltage (
+  IN EFI_PCI_IO_PROTOCOL    *Pc= iIo,
+  IN UINT8       &nb= sp;          Slot,
+  IN DW_MMC_HC_SLOT_CAP     Capability+  );
+#else
+/**
+  Supply SD/MMC card with maximum voltage at initialization.
+
+  Refer to SD Host Controller Simplified spec= 3.0 Section 3.3 for details.
+
+  @param[= in] DevIo          The DEVICE = IO protocol instance.
+  @param[in] Capability  &nb= sp;  The capability of the slot.
+
+ =  @retval EFI_SUCCESS       The voltage i= s supplied successfully.
+  @retval Others   &= nbsp;        The voltage isn't supp= lied successfully.
+
+**/
+EFI_ST= ATUS
+DwMmcHcInitPowerVoltage (
+  IN UINT= N             &= nbsp;    DevBase,
+  IN DW_MMC_HC_SL= OT_CAP     Capability
+  );
+#endif
+
+#ifdef DWMMC_PCI
+/**
+  Initialize the Timeout Control register with m= ost conservative value at
initialization.
+
+  Refer = to SD Host Controller Simplified spec 3.0 Section 2.2.15 for details.
+
+  @param[in] PciIo     &= nbsp;    The PCI IO protocol instance.
+ =  @param[in] Slot          = ; The slot number of the SD card to send the
command to.
+
+  @retval EFI_SUCCESS       The = timeout control register is configured
successfu= lly.
+  @retval Oth= ers            The t= imeout control register isn't configured
success= fully.
+
+= **/
+EFI_STATUS
+DwMmcHcInitTimeoutCtrl (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT8         &nb= sp;        Slot
+ &nb= sp;);
+#else
+/**
+  Initial= ize the Timeout Control register with most conservative value at
initialization.
+
+  Refer to SD Host Controller Simplified = spec 3.0 Section 2.2.15 for details.
+
+  = @param[in] DevIo          The = DEVICE IO protocol instance.
+  @param[in] Slot  &n= bsp;        The slot number of the = SD card to send the
command to.
+
+  @retval EFI_SUCC= ESS       The timeout control register is con= figured
successfully.
+  @retval Others     &nb= sp;      The timeout control register isn't c= onfigured
successfully.
+
+**/
+EFI_STATUS+DwMmcHcInitTimeoutCtrl (
+  IN  UINTN=             &n= bsp;      DevBase
+  );+#endif
+
+#ifdef DWMMC_PCI
+/**
+  Initial SD/MMC host controller with lowes= t clock frequency, max power
and max timeout val= ue
+  at initializa= tion.
+
+  @param[in] PciIo   &n= bsp;      The PCI IO protocol instance.
+  @param[in] Slot        =    The slot number of the SD card to send the
=
command to.
+  @param[in] Capability     The capability of th= e slot.
+
+  @retval EFI_SUCCESS  &nb= sp;    The host controller is initialized successfully.=
+  @retval Others       &= nbsp;    The host controller isn't initialized successf= ully.
+
+**/
+EFI_STATUS
+DwMmcHcInitHost (
+  IN EFI_PCI_IO_PROTOCOL &nbs= p;  *PciIo,
+  IN UINT8    &nbs= p;            &= nbsp;Slot,
+  IN DW_MMC_HC_SLOT_CAP    &n= bsp;Capability
+  );
+#else
= +/**
+  Initial SD/MMC host controller with lowest clock= frequency, max power
and
+  max timeout value at initialization.+
+  @param[in] DevIo    &nb= sp;     The DEVICE IO protocol instance.
+  @param[in] Capability     The capability= of the slot.
+
+  @retval EFI_SUCCESS &nb= sp;     The host controller is initialized success= fully.
+  @retval Others      &= nbsp;     The host controller isn't initialized su= ccessfully.
+
+**/
+EFI_STATUS+DwMmcHcInitHost (
+  IN  UINTN  &= nbsp;           &nbs= p;     DevBase,
+  IN DW_MMC_HC= _SLOT_CAP        Capability
+  );
+#endif
+
+#endif /*= _DW_MMC_HCI_H_ */
diff --git a/EmbeddedPkg/Include/Protocol/= PlatformDwMmc.h
b/EmbeddedPkg/Include/Protocol/P= latformDwMmc.h
new file = mode 100644
index 000000000000..acbc3e153dac
--= - /dev/null
+++ b/EmbeddedPkg/Include/Protocol/PlatformDwMmc.= h
@@ -0,0 +1,79 @@
+/** @file
++  Copyright (c) 2018, Linaro. All rights reserved.
+
+  This program and the accompanying material= s are licensed and made
available
=
+  under the terms and conditions= of the BSD License which accompanies
this
+  distribution.  T= he full text of the license may be found at
+  http://open= source.org/licenses/bsd-license.php
+
+ &nb= sp;THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED.
+
+**/
+
+#ifnde= f __PLATFORM_DW_MMC_H__
+#define __PLATFORM_DW_MMC_H__
+
+typedef enum {
+  RemovableSlot= ,
+  EmbeddedSlot,
+  SharedBusSlot,<= br class=3D"">+  UnknownSlot
+} EFI_SD_MMC_SLOT_TYPE;+
+typedef enum {
+  UnknownCa= rdType,
+  SdCardType,
+  SdioCardTyp= e,
+  MmcCardType,
+  EmmcCardType+} SD_MMC_CARD_TYPE;
+
+typedef str= uct {
+  UINT32       &nbs= p;DefaultSpeed:1;    // bit 0
+  UINT32 &= nbsp;      HighSpeed:1;    &nb= sp;  // bit 1
+  UINT32    &nbs= p;   Sdr12:1;        &nbs= p;  // bit 2
+  UINT32     = ;   Sdr25:1;         = ;  // bit 3
+  UINT32     =    Sdr50:1;         =   // bit 4
+  UINT32     &= nbsp;  Sdr104:1;         =  // bit 5
+  UINT32      &= nbsp; Ddr50:1;          &= nbsp;// bit 6
+  UINT32      &n= bsp; SysBus64:1;        // bit 7+  UINT32        BusWid= th:4;        // bit 11:8
+=  UINT32        SlotType:2;  &= nbsp;     // bit 13:12
+  UINT3= 2        CardType:3;    &= nbsp;   // bit 16:14
+  UINT32  &nbs= p;     Voltage18:1;      =  // bit 17
+  UINT32      =   Voltage30:1;       // bit 18
+  UINT32        Voltage3= 3:1;       // bit 19
+  UI= NT32        BaseClkFreq;
+=  EFI_HANDLE    Controller;
+} DW_MMC_HC_= SLOT_CAP;
+
+//
+// Protocol inte= rface structure
+//
+typedef struct _PLATFORM_D= W_MMC_PROTOCOL
PLATFORM_DW_MMC_PROTOCOL;
+
+typedef
+EFI_STATUS
+(EFIAPI *PLATFORM_DW_MMC_GET_CAPABILITY)= (
+  IN     EFI_HANDLE   =           Controller,
+  IN     UINT8     = ;            &n= bsp;Slot,
+     OUT DW_MMC_HC_SLOT_CAP &n= bsp;   *Capability
+  );
+<= br class=3D"">+typedef
+BOOLEAN
+(EFIAPI *PLATF= ORM_DW_MMC_CARD_DETECT) (
+  IN EFI_HANDLE   &= nbsp;           &nbs= p; Controller,
+  IN UINT8     =             &nb= sp;    Slot
+  );
++struct _PLATFORM_DW_MMC_PROTOCOL {
+  PLATF= ORM_DW_MMC_GET_CAPABILITY         &= nbsp;     GetCapability;
+  PLA= TFORM_DW_MMC_CARD_DETECT         &n= bsp;        CardDetect;
+};
+
+extern EFI_GUID gPlatformDwMmcProtoco= lGuid;
+
+#endif /* __PLATFORM_DW_MMC_H__ */diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c
b/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c
new file mode 100644
index 000000000000..1edade69d091
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c
@@ -0,0 +1,214 @@
+/** @file
+  UEFI Comp= onent Name(2) protocol implementation for Designware
SD/MMC host
+  = ;controller driver.
+
+  Copyright (c) 201= 5, Intel Corporation. All rights reserved.<BR>
+  = Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
+
+  This program and the accompanying materials are l= icensed 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 PRO= GRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
BASIS,
+  W= ITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED.
+
+**/
+
+#include "DwMmcH= cDxe.h"
+
+//
+// EFI Component N= ame Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED=
EFI_COMPONENT_NAME_PROTOCOL gDwMmcHcComponentNa= me =3D {
+  DwMmcHc= ComponentNameGetDriverName,
+  DwMmcHcComponentNameGetCo= ntrollerName,
+  "eng"
+};
+=
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
EFI_COMPONENT_NAME2_PROTOCOL gDwMmcHcComponentName2 =3D {
+  (EFI_COMPONENT_NAME2_GE= T_DRIVER_NAME)
DwMmcHcComponentNameGetDriverName= ,
+  (EFI_COMPONENT= _NAME2_GET_CONTROLLER_NAME)
DwMmcHcComponentName= GetControllerName,
+ &nb= sp;"en"
+};
+
+GLOBAL_REMOVE_IF_U= NREFERENCED EFI_UNICODE_STRING_TABLE
mDwMmcHcDri= verNameTable[] =3D {
+ &= nbsp;{ "eng;en", L"Designware Sd/Mmc Host Controller Driver" },
+  { NULL , NULL }
+};
+
= +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
mDwMmcHcControllerNameTable[] =3D {
+  { "eng;en", L"Designware Sd/Mmc Host Controll= er" },
+  { NULL , NULL }
+};
+
+/**
+  Retrieves a Unicode string tha= t is the user readable name of the driver.
+
+ =  This function retrieves the user readable name of a driver in the for= m of
a
+  Unicode string. If the driver specified by This has a use= r readable name in
+  the language specified by Language= , then a pointer to the driver name is
+  returned in Dr= iverName, and EFI_SUCCESS is returned. If the driver
specified
+  b= y This does not support the language specified by Language,
+=  then EFI_UNSUPPORTED is returned.
+
+ &n= bsp;@param  This[in]         &= nbsp;    A pointer to the
EF= I_COMPONENT_NAME2_PROTOCOL or
+            =             &nb= sp;       EFI_COMPONENT_NAME_PROTOCOL in= stance.
+
+  @param  Language[in] &nb= sp;        A pointer to a Null-term= inated ASCII string
+       &nb= sp;            =             arr= ay indicating the language. This is the
+    &= nbsp;           &nbs= p;            &= nbsp;  language of the driver name that the caller is
+            &nbs= p;            &= nbsp;      requesting, and it must match one = of the
+         &nbs= p;            &= nbsp;         languages specif= ied in SupportedLanguages. The
+     &nbs= p;            &= nbsp;           &nbs= p; number of languages supported by a driver is up
+ &nb= sp;            =             &nb= sp;     to the driver writer. Language is specifie= d
+          &nb= sp;            =          in RFC 4646 or ISO 63= 9-2 language code format.
+
+  @param &nbs= p;DriverName[out]       A pointer to the Unic= ode string to return.
+       &= nbsp;           &nbs= p;            T= his Unicode string is the name of the
+    &nb= sp;            =             &nb= sp;  driver specified by This in the language
+ &nb= sp;            =             &nb= sp;     specified by Language.
+
+  @retval EFI_SUCCESS       =     The Unicode string for the Driver specified by
+           &nb= sp;            =         This and the language speci= fied by Language was
+       &n= bsp;            = ;            re= turned in DriverName.
+
+  @retval EFI_INV= ALID_PARAMETER Language is NULL.
+
+  @ret= val EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The dr= iver specified by This does not
support
+      = ;            &n= bsp;            = ; the language specified by Language.
+
+*= */
+EFI_STATUS
+EFIAPI
+DwMmcHcCo= mponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAM= E_PROTOCOL     *This,
+  IN  CH= AR8             = ;            &n= bsp; *Language,
+  OUT CHAR16    &nb= sp;            =          **DriverName
+  )
+{
+  return LookupUnicod= eString2 (
+         =   Language,
+       &= nbsp;   This->SupportedLanguages,
+  &= nbsp;        mDwMmcHcDriverNameTabl= e,
+          &n= bsp;DriverName,
+        &= nbsp;  (BOOLEAN)(This =3D=3D &gDwMmcHcComponentName)
+           );
+}
+
+/**
+  Retr= ieves a Unicode string that is the user readable name of the
=
controller
= +  that is being managed by a driver.
+
+ =  This function retrieves the user readable name of the controller spec= ified
by
+  ControllerHandle and ChildHandle in the form of a Unico= de string. If the
+  driver specified by This has a user= readable name in the language
specified by
+  Language, then a poi= nter to the controller name is returned in
Contr= ollerName,
+  and E= FI_SUCCESS is returned.  If the driver specified by This is not
currently
+  managing the controller specified by ControllerHandle and Ch= ildHandle,
+  then EFI_UNSUPPORTED is returned.  If= the driver specified by This does
not
+  support the language sp= ecified by Language, then EFI_UNSUPPORTED is
ret= urned.
+
+=  @param  This[in]        &nbs= p;     A pointer to the
EFI_COMPONENT_NAME2_PROTOCOL or
+           &nbs= p;            &= nbsp;       EFI_COMPONENT_NAME_PROTOCOL = instance.
+
+  @param  ControllerHand= le[in]  The handle of a controller that the driver
+ &nb= sp;            =             &nb= sp;     specified by This is managing.  This = handle
+         &nbs= p;            &= nbsp;         specifies the co= ntroller whose name is to be
+      =             &nb= sp;            =  returned.
+
+  @param  ChildHan= dle[in]       The handle of the child control= ler to retrieve
+        &= nbsp;           &nbs= p;           the nam= e of.  This is an optional parameter that
+   =             &nb= sp;            =     may be NULL.  It will be NULL for device
+           &nbs= p;            &= nbsp;       drivers.  It will also = be NULL for a bus drivers
+      &nb= sp;            =             &nb= sp;that wish to retrieve the name of the bus
+   &n= bsp;            = ;            &n= bsp;   controller.  It will not be NULL for a bus
+           &nbs= p;            &= nbsp;       driver that wishes to retrie= ve the name of a
+        =             &nb= sp;           child = controller.
+
+  @param  Language[in]=          A pointer to a Null-= terminated ASCII string
+       = ;            &n= bsp;            = ;array indicating the language.  This is the
+  &nb= sp;            =             &nb= sp;    language of the driver name that the caller is+           =             &nb= sp;        requesting, and it must = match one of the
+        =             &nb= sp;           langua= ges specified in SupportedLanguages. The
+    =             &nb= sp;            =    number of languages supported by a driver is up
+            =             &nb= sp;       to the driver writer. Language= is specified in
+        =             &nb= sp;           RFC 46= 46 or ISO 639-2 language code format.
+
+  = ;@param  ControllerName[out]   A pointer to the Unicode stri= ng to
return.
+          &n= bsp;            = ;         This Unicode string = is the name of the
+       &nbs= p;            &= nbsp;           cont= roller specified by ControllerHandle and
+    =             &nb= sp;            =    ChildHandle in the language specified by
+ =             &nb= sp;            =       Language from the point of view of the = driver
+         &nbs= p;            &= nbsp;         specified by Thi= s.
+
+  @retval EFI_SUCCESS   &n= bsp;       The Unicode string for the us= er readable
name in
+         &n= bsp;            = ;          the language s= pecified by Language for the
+      =             &nb= sp;            =  driver specified by This was returned in
+   =             &nb= sp;            =     DriverName.
+
+  @= retval EFI_INVALID_PARAMETER ControllerHandle is not a valid
=
EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not N= ULL and it is not a
valid
+        &n= bsp;            = ;           EFI_HAND= LE.
+
+  @retval EFI_INVALID_PARAMETER Lan= guage is NULL.
+
+  @retval EFI_INVALID_PA= RAMETER ControllerName is NULL.
+
+  @retv= al EFI_UNSUPPORTED       The driver specified= by This is not
currently
+        &n= bsp;            = ;           managing= the controller specified by
+      =             &nb= sp;            =  ControllerHandle and ChildHandle.
+
+ &nb= sp;@retval EFI_UNSUPPORTED       The driver s= pecified by This does not
support
=
+       =             &nb= sp;            = the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+DwMmcHcComponent= NameGetControllerName (
+  IN  EFI_COMPONENT_NAME_P= ROTOCOL     *This,
+  IN  EFI_H= ANDLE            &nb= sp;         ControllerHandle,<= br class=3D"">+  IN  EFI_HANDLE      &nb= sp;            =    ChildHandle, OPTIONAL
+  IN  CHAR= 8             &= nbsp;           &nbs= p; *Language,
+  OUT CHAR16     = ;            &n= bsp;        **ControllerName
+  )
+{
+  EFI_STATUS  &= nbsp;      Status;
+
+  if (Language =3D=3D NULL || ControllerName =3D=3D NULL) {+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  /= / This is a device driver, so ChildHandle must be NULL.
+ &nb= sp;//
+  if (ChildHandle !=3D NULL) {
+ &n= bsp;  return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Make sure this drive= r is currently managing ControllerHandle
+  //
+  Status =3D EfiTestManagedDevice (
+  &nbs= p;          ControllerHan= dle,
+          =    gDwMmcHcDriverBinding.DriverBindingHandle,
= +             &= amp;gEfiPciIoProtocolGuid
+      &nb= sp;      );
+  if (EFI_ERR= OR (Status)) {
+    return Status;
+  }
+
+  return LookupUnicodeStri= ng2 (
+          = ; Language,
+        =    This->SupportedLanguages,
+   =         mDwMmcHcControllerNameTable= ,
+          &nb= sp;ControllerName,
+       &nbs= p;   (BOOLEAN)(This =3D=3D &gDwMmcHcComponentName)
+           );+}
diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/D= wMmcHcDxe.c
b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwM= mcHcDxe.c
new file mode = 100644
index 000000000000..aea12170d2cc
--- /de= v/null
+++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c
@@ -0,0 +1,1296 @@
+/** @file
+  = ;This driver is used to manage Designware SD/MMC host controller.
+
+  It would expose EFI_SD_MMC_PASS_THRU_PROTOCO= L for upper layer
use.
+
+  Copyright (c) 2015 - 2021= , Intel Corporation. All rights reserved.<BR>
+  C= opyright (C) 2016 Marvell International Ltd. All rigths reserved.<BR>=
+  Copyright (C) 2018, Linaro Ltd. All rigths reserved.= <BR>
+
+  This program and the accom= panying materials
+  are licensed and made available und= er 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, EI= THER
EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include &l= t;Library/DebugLib.h>
+#include <Library/DevicePathLib.= h>
+#include <Library/IoLib.h>
+#inclu= de <Library/MemoryAllocationLib.h>
+#include <Protoc= ol/NonDiscoverableDevice.h>
+#include <Library/UefiBoot= ServicesTableLib.h>
+#include <Library/UefiDriverEntryP= oint.h>
+
+#include <Protocol/DevicePath.= h>
+#include <Protocol/PlatformDwMmc.h>
+
+#include "DwMmcHcDxe.h"
+
+/= /
+// Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gDwMmcHcDriverBinding =3D {
+ &= nbsp;DwMmcHcDriverBindingSupported,
+  DwMmcHcDriverBind= ingStart,
+  DwMmcHcDriverBindingStop,
+ &= nbsp;0x10,
+  NULL,
+  NULL
+};
+
+//
+// Template for= Designware SD/MMC host controller private data.
+//
+DW_MMC_HC_PRIVATE_DATA gDwMmcHcTemplate =3D {
+  = ;DW_MMC_HC_PRIVATE_SIGNATURE,      // Signature+  NULL,         &= nbsp;           &nbs= p;       // ControllerHandle
+  0x0,           = ;            &n= bsp;     // Mmio base address
+ &nbs= p;{             = ;            &n= bsp;       // PassThru
+ &= nbsp;  sizeof (UINT32),
+    DwMmcPa= ssThruPassThru,
+    DwMmcPassThruGetNextSlot,=
+    DwMmcPassThruBuildDevicePath,
+    DwMmcPassThruGetSlotNumber,
+ &nbs= p;  DwMmcPassThruResetDevice
+  },
+  NULL,          &nbs= p;            &= nbsp;     // PlatformDwMmc
+  0= ,             &= nbsp;           &nbs= p;      // PreviousSlot
+  = ;NULL,            &n= bsp;            = ;    // TimerEvent
+  NULL,  &n= bsp;            = ;            &n= bsp; // ConnectEvent
+      &nb= sp;            =             &nb= sp;    // Queue
+  INITIALIZE_LIST_H= EAD_VARIABLE (gDwMmcHcTemplate.Queue),
+  {   =             &nb= sp;            =      // Slot
+    {0,= UnknownSlot, 0, 0, 0}
+  },
+  { &nb= sp;            =             &nb= sp;      // Capability
+  =   {0}
+  },
+  {  &nbs= p;            &= nbsp;           &nbs= p;     // MaxCurrent
+   &= nbsp;0
+  },
+  0    &= nbsp;           &nbs= p;            &= nbsp;   // ControllerVersion
+};
+
+SD_DEVICE_PATH    mSdDpTemplate =3D {
+  {
+    MESSAGING_DEVICE_PATH= ,
+    MSG_SD_DP,
+   =  {
+      (UINT8) (sizeof (SD_D= EVICE_PATH)),
+      (UINT8) ((sizeo= f (SD_DEVICE_PATH)) >> 8)
+    }
+  },
+  0
+};
+=
+EMMC_DEVICE_PATH    mEmmcDpTemplate =3D {+  {
+    MESSAGING_DEVICE_PA= TH,
+    MSG_EMMC_DP,
+  &n= bsp; {
+      (UINT8) (sizeof (= EMMC_DEVICE_PATH)),
+      (UINT8) (= (sizeof (EMMC_DEVICE_PATH)) >> 8)
+    }=
+  },
+  0
+};
+
+//
+// Prioritized function list to d= etect card type.
+// User could add other card detection logi= c here.
+//
+DWMMC_CARD_TYPE_DETECT_ROUTINE
mCardTypeDetectRoutineTable[] =3D {
<= blockquote type=3D"cite" class=3D"">+  EmmcIdentification,
+  SdCardIdentification,
+  NULL
+= };
+
+/**
+  The entry point= for SD host controller driver, used to install this driver on
the ImageHandle.
+
+  @param[in]  ImageHandle   Th= e firmware allocated handle for this driver
imag= e.
+  @param[in] &n= bsp;SystemTable   Pointer to the EFI system table.
= +
+  @retval EFI_SUCCESS   Driver loaded.
+  @retval other        &= nbsp;Driver not loaded.
+
+**/
+E= FI_STATUS
+EFIAPI
+InitializeDwMmcHcDxe (
+  IN EFI_HANDLE        Im= ageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS &nbs= p;         Status;
+
+  Status =3D EfiLibInstallDriverBindingComponentNa= me2 (
+          = ;   ImageHandle,
+     &nb= sp;       SystemTable,
+ &= nbsp;           &= ;gDwMmcHcDriverBinding,
+       = ;      ImageHandle,
+  &nb= sp;          &gDwMmcH= cComponentName,
+        &= nbsp;    &gDwMmcHcComponentName2
+ &n= bsp;           );+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/*= *
+  Call back function when the timer event is signaled= .
+
+  @param[in]  Event   =   The Event this notify function registered to.
+ &= nbsp;@param[in]  Context   Pointer to the context data regis= tered to the
+        &nbs= p;            &= nbsp;  Event.
+
+**/
+V= OID
+EFIAPI
+ProcessAsyncTaskList (
+  IN EFI_EVENT         &nb= sp;Event,
+  IN VOID*      &nbs= p;       Context
+  )=
+{
+  DW_MMC_HC_PRIVATE_DATA   =            *Private;=
+  LIST_ENTRY        = ;            &n= bsp;     *Link;
+  DW_MMC_HC_TR= B             &= nbsp;         *Trb;
+  EFI_STATUS         &= nbsp;           &nbs= p;    Status;
+  EFI_SD_MMC_PASS_THR= U_COMMAND_PACKET *Packet;
+  BOOLEAN    &= nbsp;           &nbs= p;            I= nfiniteWait;
+  EFI_EVENT      =             &nb= sp;        TrbEvent;
= +
+  Private =3D (DW_MMC_HC_PRIVATE_DATA *)Context;
+
+  //
+  // Check if the = first entry in the async I/O queue is done or not.
+  //=
+  Status =3D EFI_SUCCESS;
+  Trb &n= bsp;  =3D NULL;
+  Link   =3D GetFir= stNode (&Private->Queue);
+  if (!IsNull (&Pr= ivate->Queue, Link)) {
+    Trb =3D DW_MMC_= HC_TRB_FROM_THIS (Link);
+    if (!Private->= ;Slot[Trb->Slot].MediaPresent) {
+     = ; Status =3D EFI_NO_MEDIA;
+     &nb= sp;goto Done;
+    }
+  &nb= sp; if (!Trb->Started) {
+     &n= bsp;//
+      // Check whether the c= md/data line is ready for transfer.
+     = ; //
+      Status =3D DwMmcChe= ckTrbEnv (Private, Trb);
+      if (= !EFI_ERROR (Status)) {
+       =  Trb->Started =3D TRUE;
+     &nb= sp;  Status =3D DwMmcExecTrb (Private, Trb);
+ &nbs= p;      if (EFI_ERROR (Status)) {
+          goto Done;
+        }
+ &nbs= p;    } else {
+     =    goto Done;
+      = }
+    }
+    Sta= tus =3D DwMmcCheckTrbResult (Private, Trb);
+  }
+
+Done:
+  if ((Trb !=3D NULL) &am= p;& (Status =3D=3D EFI_NOT_READY)) {
+    = Packet =3D Trb->Packet;
+    if (Packet->= ;Timeout =3D=3D 0) {
+      Infinite= Wait =3D TRUE;
+    } else {
+ &= nbsp;    InfiniteWait =3D FALSE;
+  =   }
+    if ((!InfiniteWait) &&a= mp; (Trb->Timeout-- =3D=3D 0)) {
+     = ; RemoveEntryList (Link);
+     &nbs= p;Trb->Packet->TransactionStatus =3D EFI_TIMEOUT;
+ &nb= sp;    TrbEvent =3D Trb->Event;
+ &nbs= p;    DwMmcFreeTrb (Trb);
+   &= nbsp;  DEBUG ((
+      &nb= sp; DEBUG_VERBOSE,
+       = ; "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n",
+        TrbEvent
+ &nb= sp;      ));
+   &nbs= p;  gBS->SignalEvent (TrbEvent);
+   &= nbsp;  return;
+    }
= +  }
+  if ((Trb !=3D NULL) && (Status !=3D= EFI_NOT_READY)) {
+    RemoveEntryList (Link)= ;
+    Trb->Packet->TransactionStatus = =3D Status;
+    TrbEvent =3D Trb->Event;<= br class=3D"">+    DwMmcFreeTrb (Trb);
+  = ;  DEBUG ((
+      DEBUG_V= ERBOSE,
+      "ProcessAsyncTaskList= (): Signal Event %p with %r\n",
+     &nb= sp;TrbEvent,
+      Status
+      ));
+   &nbs= p;gBS->SignalEvent (TrbEvent);
+  }
+ &= nbsp;return;
+}
+
+/**
+  Sd removable device enumeration callback function when the t= imer
event is signaled.
+
+  @param[in]  Event &= nbsp;   The Event this notify function registered to.
+  @param[in]  Context   Pointer to the context= data registered to the
+       = ;            &n= bsp;    Event.
+
+**/
+VOID
+EFIAPI
+DwMmcHcEnumerateDevice = (
+  IN EFI_EVENT       &n= bsp;  Event,
+  IN VOID*    &nb= sp;         Context
+  )
+{
+  DW_MMC_HC_PRIVATE_D= ATA             = ; *Private;
+  EFI_STATUS     &= nbsp;           &nbs= p;        Status;
+ &= nbsp;BOOLEAN           &n= bsp;            = ;     MediaPresent;
+  UINT32 &= nbsp;           &nbs= p;            &= nbsp;   RoutineNum;
+  DWMMC_CARD_TYPE_DE= TECT_ROUTINE      *Routine;
+  = UINTN            &nb= sp;            =       Index;
+  LIST_ENTRY=             &n= bsp;            = ;*Link;
+  LIST_ENTRY      &nbs= p;            &= nbsp;      *NextLink;
+  D= W_MMC_HC_TRB           &n= bsp;           *Trb;=
+  EFI_TPL        &n= bsp;            = ;        OldTpl;
++  Private =3D (DW_MMC_HC_PRIVATE_DATA *)Context;
+
+  if ((Private->Slot[0].Enable) &&<= br class=3D"">+      (Private->Slot[0].SlotType= =3D=3D RemovableSlot)) {
+    Status =3D DwMm= cHcCardDetect (
+        &= nbsp;      Private->DevBase,
+             =   Private->ControllerHandle,
+    = ;           0,
+           &nbs= p;   &MediaPresent
+    &nb= sp;          );
+    if ((Status =3D=3D EFI_MEDIA_CHANGED) &&= !MediaPresent) {
+      DEBUG ((+        DEBUG_INFO,
+        "DwMmcHcEnumerateDevice:= device disconnected at %p\n",
+     &nbs= p;  Private->DevBase
+     &= nbsp;  ));
+      Private-= >Slot[0].MediaPresent =3D FALSE;
+     = ; //
+      // Signal all async= task events at the slot with EFI_NO_MEDIA status.
+  &n= bsp;   //
+      OldT= pl =3D gBS->RaiseTPL (TPL_NOTIFY);
+    &nb= sp; for (Link =3D GetFirstNode (&Private->Queue);
+           !IsNull (&am= p;Private->Queue, Link);
+      &= nbsp;    Link =3D NextLink) {
+  &nb= sp;     NextLink =3D GetNextNode (&Private->= ;Queue, Link);
+        Tr= b =3D DW_MMC_HC_TRB_FROM_THIS (Link);
+    &nb= sp;   if (Trb->Slot =3D=3D 0) {
+  &nb= sp;       RemoveEntryList (Link);
+          Trb->Pac= ket->TransactionStatus =3D EFI_NO_MEDIA;
+   &nb= sp;      gBS->SignalEvent (Trb->Event);=
+          DwMm= cFreeTrb (Trb);
+        }=
+      }
+  &nbs= p;   gBS->RestoreTPL (OldTpl);
+  &nbs= p;   //
+      // Not= ify the upper layer the connect state change through
+  =     // ReinstallProtocolInterface.
+ &nbs= p;    //
+      = gBS->ReinstallProtocolInterface (
+    &nbs= p;       Private->ControllerHandle,+           =  &gEfiSdMmcPassThruProtocolGuid,
+    = ;        &Private->PassThru,=
+          &nbs= p; &Private->PassThru
+     &= nbsp;      );
+   &nb= sp;}
+    if ((Status =3D=3D EFI_MEDIA_CHANGED= ) && MediaPresent) {
+      = DEBUG ((
+        DEBUG_IN= FO,
+        "DwMmcHcEnume= rateDevice: device connected at %p\n",
+    &n= bsp;   Private->DevBase
+    = ;    ));
+      = //
+      // Initialize slot and sta= rt identification process for the new
+    &nb= sp; // attached device
+      /= /
+      Status =3D DwMmcHcInitHost = (Private->DevBase, Private->Capability[0]);
+  &nb= sp;   if (EFI_ERROR (Status)) {
+   =      return;
+    &nb= sp; }
+      //
+=      // Reset the specified slot of the SD/MMC Pc= i Host Controller
+      //
+      Status =3D DwMmcHcReset (Private->= ;DevBase, Private->Capability[0]);
+    &nb= sp; if (EFI_ERROR (Status)) {
+     =    return;
+      }+
+      Private->Sl= ot[0].MediaPresent =3D TRUE;
+      = RoutineNum =3D sizeof (mCardTypeDetectRoutineTable) /
+  = ;            &n= bsp;    sizeof (DWMMC_CARD_TYPE_DETECT_ROUTINE);
+      for (Index =3D 0; Index < Routin= eNum; Index++) {
+        = Routine =3D &mCardTypeDetectRoutineTable[Index];
+  =       if (*Routine !=3D NULL) {
+          Status =3D (*Routi= ne) (Private);
+        &n= bsp; if (!EFI_ERROR (Status)) {
+    &nbs= p;       break;
+  &n= bsp;       }
+   = ;     }
+     &n= bsp;}
+      //
+ &nbs= p;    // This card doesn't get initialized correctly.+      //
+   = ;   if (Index =3D=3D RoutineNum) {
+  &nb= sp;     return;
+    =   }
+
+      = ;//
+      // Notify the upper layer= the connect state change through
+     &= nbsp;// ReinstallProtocolInterface.
+     = ; //
+      gBS->ReinstallPr= otocolInterface (
+        = ;     Private->ControllerHandle,
= +             &= amp;gEfiSdMmcPassThruProtocolGuid,
+     =         &Private->PassThru,<= br class=3D"">+           = ;  &Private->PassThru
+    &n= bsp;        );
+ &nbs= p;  }
+  }
+
+ &nb= sp;return;
+}
+
+/**
+  Reset the specified SD/MMC host controller and enable all interru= pts.
+
+  @param[in] DevBase   &= nbsp;    The Mmio Device Base Address.
+<= br class=3D"">+  @retval EFI_SUCCESS      &nb= sp;The software reset executes successfully.
+  @retval = Others            Th= e software reset fails.
+
+**/
+E= FI_STATUS
+DwMmcHcReset (
+  IN UINTN &nbs= p;  DevBase,
+  IN DW_MMC_HC_SLOT_CAP  &n= bsp;     Capability
+  )
+{
+  EFI_STATUS      &= nbsp;         Status;
+  UINT32          = ;          BlkSize;
+
+  //
+  // Enable all int= errupt after reset all.
+  //
+  Stat= us =3D DwMmcHcEnableInterrupt (DevBase);
+  if (EFI_ERRO= R (Status)) {
+    DEBUG ((DEBUG_ERROR, "DwMmc= HcReset: enable interrupts fail:
%r\n", Status))= ;
+    re= turn Status;
+  }
+  Status =3D DwMmc= HcInitTimeoutCtrl (DevBase);
+  if (EFI_ERROR (Status)) = {
+    return Status;
+  }<= br class=3D"">+
+  BlkSize =3D DW_MMC_BLOCK_SIZE;
+  MmioWrite32 (DevBase + DW_MMC_BLKSIZ, BlkSize);
+
+  Status =3D DwMmcHcInitClockFreq (DevBase, Capabi= lity);
+  if (EFI_ERROR (Status)) {
+ &nbs= p;  return Status;
+  }
+
+  Status =3D DwMmcHcSetBusWidth (DevBase, FALSE, 1);
+
+  return Status;
+}
+
+/**
+  Tests to see if this driver su= pports a given controller. If a child device
+  is provi= ded, it further tests to see if this driver supports creating a
+  handle for the specified child device.
+
+  This function checks to see if the driver specified by This = supports the
+  device specified by ControllerHandle. Dr= ivers will typically use the device
+  path attached to = ControllerHandle and/or the services from the bus I/O
+  = ;abstraction attached to ControllerHandle to determine if the driver
supports
+  ControllerHandle. This function may be called many times dur= ing
platform
+  initialization. In order to reduce boot times, the = tests performed by this
+  function must be very small, = and take as little time as possible to
execute.<= br class=3D"">
+  This function mu= st not change the state of any hardware devices, and
this
+  functi= on must be aware that the device specified by ControllerHandle
may
+ &nb= sp;already be managed by the same driver or a different driver. This
function
+  must match its calls to AllocatePages() with FreePages(), Al= locatePool()
with
+  FreePool(), and OpenProtocol() with CloseProt= ocol(). Since
ControllerHandle
+  may have been previously started = by the same driver, if a protocol is
already
+  in the opened state= , then it must not be closed with CloseProtocol(). This
is
+  requi= red to guarantee the state of ControllerHandle is not modified by
this
+  function.
+
+  @param[in]  T= his             = ;    A pointer to the
EFI_DR= IVER_BINDING_PROTOCOL
+ =             &nb= sp;            =          instance.
+  @param[in]  ControllerHandle     The ha= ndle of the controller to test. This
+    &nbs= p;            &= nbsp;           &nbs= p;     handle must support a protocol interface th= at
+          &n= bsp;            = ;            su= pplies an I/O abstraction to the driver.
+  @param[in] &= nbsp;RemainingDevicePath  A pointer to the remaining portion of
a
+=             &n= bsp;            = ;         device path.  T= his parameter is ignored by
+      &= nbsp;           &nbs= p;            &= nbsp;   device drivers, and is optional for bus
+             = ;            &n= bsp;         drivers. For bus = drivers, if this parameter
+      &n= bsp;            = ;            &n= bsp;   is not NULL, then the bus driver must deter-
+            =             &nb= sp;          mine if the = bus controller specified by
+      &= nbsp;           &nbs= p;            &= nbsp;   ControllerHandle and the child controller
+            =             &nb= sp;          specified by= RemainingDevicePath are both
+      = ;            &n= bsp;            = ;    supported by this bus driver.
+
+  @retval EFI_SUCCESS       &= nbsp;      The device specified by Controller= Handle
and
+           = ;            &n= bsp;           Remai= ningDevicePath is supported by the
+     =             &nb= sp;            =      driver specified by This.
+ &nb= sp;@retval EFI_ALREADY_STARTED      The device spe= cified by
ControllerHandle and
+       &nb= sp;            =             &nb= sp;  RemainingDevicePath is already being managed
+=             &n= bsp;            = ;         by the driver specif= ied by This.
+  @retval EFI_ACCESS_DENIED   &n= bsp;    The device specified by
ControllerHandle and
+             =             &nb= sp;         RemainingDevicePat= h is already being managed
+      &n= bsp;            = ;            &n= bsp;   by a different driver or an application that
+            =             &nb= sp;          requires exc= lusive access.
+        &n= bsp;            = ;            &n= bsp; Currently not implemented.
+  @retval EFI_UNSU= PPORTED          The device sp= ecified by
ControllerHandle and
+       &n= bsp;            = ;            &n= bsp;  RemainingDevicePath is not supported by the
+=             &n= bsp;            = ;         driver specified by = This.
+**/
+EFI_STATUS
+EFIAPI+DwMmcHcDriverBindingSupported (
+  IN EFI_D= RIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE  &nb= sp;            =    Controller,
+  IN EFI_DEVICE_PATH_PROT= OCOL    *RemainingDevicePath
+  )
+{
+  EFI_STATUS      &n= bsp;         Status;
+  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
+  NON_DISCOVERABLE_DEVICE   *Dev;
+ &n= bsp;PLATFORM_DW_MMC_PROTOCOL  *PlatformDwMmc;
+
+  ParentDevicePath =3D NULL;
+
+ &= nbsp;Status =3D gBS->LocateProtocol (
+    =             &nb= sp; &gPlatformDwMmcProtocolGuid,
+    = ;            &n= bsp; NULL,
+        &= nbsp;         (VOID **) &P= latformDwMmc
+        &nbs= p;         );
+ =  if (EFI_ERROR (Status)) {
+    return St= atus;
+  }
+
+  Status = = =3D gBS->OpenProtocol (
+      &= nbsp;           Cont= roller,
+         &nb= sp;        &gEfiDevicePathProto= colGuid,
+         &n= bsp;        (VOID *) &ParentDev= icePath,
+         &n= bsp;        This->DriverBindingH= andle,
+         &nbs= p;        Controller,
+             =      EFI_OPEN_PROTOCOL_BY_DRIVER
+ &= nbsp;           &nbs= p;    );
+  if (EFI_ERROR (Status)) = {
+    //
+    //= EFI_ALREADY_STARTED is also an error.
+    //=
+    return Status;
+  }+  //
+  // Close the protocol because= we don't use it here.
+  //
+  gBS-&= gt;CloseProtocol (
+       &nbs= p;Controller,
+        &am= p;gEfiDevicePathProtocolGuid,
+      = ;  This->DriverBindingHandle,
+   &nbs= p;    Controller
+    &nbs= p;   );
+
+  //
+  // Now test the EmbeddedNonDiscoverableIoProtocol.
+  //
+  Status =3D gBS->OpenProtocol (
+            =       Controller,
+   = ;            &n= bsp;  &gEdkiiNonDiscoverableDeviceProtocolGuid,
+             =      (VOID **) &Dev,
+  &nb= sp;            =    This->DriverBindingHandle,
+   = ;            &n= bsp;  Controller,
+      &= nbsp;           EFI_= OPEN_PROTOCOL_BY_DRIVER
+       = ;           );
+  if (EFI_ERROR (Status)) {
+   &nbs= p;return Status;
+  }
+  gBS->Clos= eProtocol (
+         = ;Controller,
+        &nbs= p;&gEdkiiNonDiscoverableDeviceProtocolGuid,
+   = ;      This->DriverBindingHandle,
+         Controller
+         );
+=  return EFI_SUCCESS;
+}
+
+= /**
+  Starts a device controller or a bus controller.+
+  The Start() function is designed to be= invoked from the EFI boot service
+  ConnectController(= ).
+  As a result, much of the error checking on the par= ameters to Start() has
+  been moved into this
+  common boot service. It is legal to call Start() from other = locations,
+  but the following calling restrictions mus= t be followed or the system
+  behavior will not be dete= rministic.
+  1. ControllerHandle must be a valid EFI_HA= NDLE.
+  2. If RemainingDevicePath is not NULL, then it = must be a pointer to a
+     naturally al= igned EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling S= tart(), the Supported() function for the driver
+   = ;  specified by This must have been called with the same calling<= br class=3D"">
parameters,
+     and Supported() must have returned= EFI_SUCCESS.
+
+  @param[in]  This &= nbsp;           &nbs= p;   A pointer to the
EFI_DRIVER_= BINDING_PROTOCOL
+  = ;            &n= bsp;            = ;        instance.
+ =  @param[in]  ControllerHandle     The handle = of the controller to start.
This
<= blockquote type=3D"cite" class=3D"">+       &= nbsp;           &nbs= p;            &= nbsp;  handle must support a protocol interface
+ &= nbsp;           &nbs= p;            &= nbsp;        that supplies an I/O a= bstraction to the
+        = ;            &n= bsp;            = ;  driver.
+  @param[in]  RemainingDevice= Path  A pointer to the remaining portion of
a
+    &= nbsp;           &nbs= p;            &= nbsp;     device path.  This parameter is ign= ored by
+         &nb= sp;            =             &nb= sp;device drivers, and is optional for bus
+   &nbs= p;            &= nbsp;           &nbs= p;      drivers.
+   =             &nb= sp;            =        For a bus driver, if this paramet= er is NULL,
+         = ;            &n= bsp;            = ; then handles for all the children of
+   &nb= sp;            =             &nb= sp;      Controller are created by this drive= r.
+          &n= bsp;            = ;            If= this parameter is not NULL and the first
+    = ;            &n= bsp;            = ;      Device Path Node is not the End of Dev= ice
+          &= nbsp;           &nbs= p;            P= ath Node, then only the handle for the
+    &n= bsp;            = ;            &n= bsp;     child device specified by the first Devic= e
+          &nb= sp;            =             Pat= h Node of RemainingDevicePath is created
+    =             &nb= sp;            =       by this driver.
+  &= nbsp;           &nbs= p;            &= nbsp;       If the first Device Path Nod= e of
+          =             &nb= sp;            = RemainingDevicePath is the End of Device Path
+   &= nbsp;           &nbs= p;            &= nbsp;      Node, no child handle is created b= y this
+         &nbs= p;            &= nbsp;           &nbs= p;driver.
+
+  @retval EFI_SUCCESS  &= nbsp;           The = device was started.
+  @retval EFI_DEVICE_ERROR  &n= bsp;      The device could not be started due= to a
+          = ;            &n= bsp;            = ;device error. Currently not implemented.
+  @retval EFI= _OUT_OF_RESOURCES     The request could not be
completed due to a
+          &nbs= p;            &= nbsp;           lack= of resources.
+  @retval Others     = ;            &n= bsp; The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+= DwMmcHcDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PRO= TOCOL     *This,
+  IN EFI_HANDLE &n= bsp;            = ;        Controller,
= +  IN EFI_DEVICE_PATH_PROTOCOL       &nb= sp;*RemainingDevicePath
+  )
+{
+  EFI_STATUS         &= nbsp;           &nbs= p;Status;
+  DW_MMC_HC_PRIVATE_DATA    &n= bsp;     *Private;
+
+=  NON_DISCOVERABLE_DEVICE        &n= bsp;*Dev;
+
+  BOOLEAN    &= nbsp;           &nbs= p;        MediaPresent;
+  DWMMC_CARD_TYPE_DETECT_ROUTINE  *Routine;
+ &= nbsp;UINT8           &nbs= p;            &= nbsp;  Index;
+  UINT32    &nbs= p;            &= nbsp;        RoutineNum;
+  PLATFORM_DW_MMC_PROTOCOL       = ; *PlatformDwMmc;
+
+  Status =3D gBS= ->LocateProtocol (
+       &= nbsp;          &gPlat= formDwMmcProtocolGuid,
+       =            NULL,
+           &n= bsp;      (VOID **) &PlatformDwMmc
+            = ;      );
+  if (EFI_ERROR= (Status)) {
+  DEBUG ((DEBUG_ERROR, "err %d", __LINE__)= );
+    return Status;
+  }=
+
+  Status =3D gBS->OpenProtocol (+           &= nbsp;      Controller,
+  =             &nb= sp;   &gEdkiiNonDiscoverableDeviceProtocolGuid,
+            =       (VOID **) &Dev,
+ &nb= sp;            =     This->DriverBindingHandle,
+  = ;            &n= bsp;   Controller,
+     &= nbsp;           &nbs= p;EFI_OPEN_PROTOCOL_BY_DRIVER
+      = ;            );=
+  if (EFI_ERROR (Status)) {
+  DEBU= G ((DEBUG_ERROR, "err %d", __LINE__));
+    re= turn Status;
+  }
+
+  = Private =3D AllocateCopyPool (sizeof (DW_MMC_HC_PRIVATE_DATA),
&gDwMmcHcTemplate);
+  if (Private =3D=3D NULL) {
+  DEB= UG ((DEBUG_ERROR, "err %d", __LINE__));
+    S= tatus =3D EFI_OUT_OF_RESOURCES;
+    goto Done= ;
+  }
+
+  Private->= ;ControllerHandle =3D Controller;
+  Private->DevBase=          =3D Dev->Resource= s[0].AddrRangeMin;
+  Private->PlatformDwMmc  &n= bsp; =3D PlatformDwMmc;
+  InitializeListHead (&= ;Private->Queue);
+
+  Status =3D Priva= te->PlatformDwMmc->GetCapability (Controller, 0,
&Private->Capability[0]);
+
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  if (Private->Capability[0].BaseClkFreq =3D=3D 0= ) {
+    goto Done;
+  }+
+  DumpCapabilityReg (0, &Private->= Capability[0]);
+
+  MediaPresent =3D FALS= E;
+
+  Status =3D Private->PlatformDwM= mc->CardDetect (Controller, 0);
+  Status =3D DwMmcHc= CardDetect (Private->DevBase, Controller, 0,
= &MediaPresent);
+ &n= bsp;if (MediaPresent =3D=3D FALSE) {
+    goto= Done;
+  }
+
+  //
+  // Initialize slot and start identification process for = the new attached
device
+  //
+  Status =3D DwMm= cHcInitHost (Private->DevBase, Private->Capability[0]);
+  if (EFI_ERROR (Status)) {
+    goto D= one;
+  }
+
+  //
+  // Reset HC
+  //
+  = ;Status =3D DwMmcHcReset (Private->DevBase, Private->Capability[0]);<= br class=3D"">+  if (EFI_ERROR (Status)) {
+   = ; goto Done;
+  }
+
+ &= nbsp;Private->Slot[0].CardType =3D Private->Capability[0].CardType;+  Private->Slot[0].Enable =3D TRUE;
+ &= nbsp;Private->Slot[0].MediaPresent =3D TRUE;
+
+  RoutineNum =3D sizeof (mCardTypeDetectRoutineTable) / sizeof
(DWMMC_CARD_TYPE_DETECT_ROUTINE);
+  for (Index =3D 0; Index < Rout= ineNum; Index++) {
+    Routine =3D &mCard= TypeDetectRoutineTable[Index];
+    if (*Routi= ne !=3D NULL) {
+      Status =3D (*= Routine) (Private);
+      if (!EFI_= ERROR (Status)) {
+        = ;break;
+      }
+ &nb= sp;  }
+  }
+
+ &n= bsp;//
+  // Start the asynchronous I/O monitor
+  //
+  Status =3D gBS->CreateEvent (+           &= nbsp;      EVT_TIMER | EVT_NOTIFY_SIGNAL,
+           &n= bsp;      TPL_NOTIFY,
+  &= nbsp;           &nbs= p;   ProcessAsyncTaskList,
+    = ;            &n= bsp; Private,
+       &nbs= p;          &Private-= >TimerEvent
+        &n= bsp;         );
= +  if (EFI_ERROR (Status)) {
+    goto Do= ne;
+  }
+
+  Status = =3D gBS->SetTimer (Private->TimerEvent, TimerPeriodic,
DW_MMC_HC_ASYNC_TIMER);
+  if (EFI_ERROR (Status)) {
+   = ; goto Done;
+  }
+
+ &= nbsp;//
+  // Start the Sd removable device connection e= numeration
+  //
+  Status =3D gBS-&g= t;CreateEvent (
+        &= nbsp;         EVT_TIMER | EVT_= NOTIFY_SIGNAL,
+        &n= bsp;         TPL_CALLBACK,
+           &n= bsp;      DwMmcHcEnumerateDevice,
+            &nbs= p;     Private,
+    =             &nb= sp; &Private->ConnectEvent
+    &n= bsp;            = ; );
+  if (EFI_ERROR (Status)) {
+ &= nbsp;  goto Done;
+  }
+
+  Status =3D gBS->SetTimer (Private->ConnectEvent, Timer= Periodic,
DW_MMC_HC_ENUM_TIMER);
<= blockquote type=3D"cite" class=3D"">+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  Status =3D gBS->InstallMultipleProtocolInterf= aces (
+         &nbs= p;        &Controller,
+            =       &gEfiSdMmcPassThruProtocolGuid,
+           &n= bsp;      &(Private->PassThru),
+            = ;      NULL
+    = ;            &n= bsp; );
+
+  DEBUG ((DEBUG_INFO, "DwM= mcHcDriverBindingStart: %r End on %x\n",
Status,= Controller));
+
+Done:
+  if (EFI_ERROR (Status)) {
+    if ((Private !=3D NULL) && (Private->TimerE= vent !=3D NULL)) {
+      gBS->Cl= oseEvent (Private->TimerEvent);
+    }
+
+    if ((Private !=3D NULL) &= & (Private->ConnectEvent !=3D NULL)) {
+   &= nbsp;  gBS->CloseEvent (Private->ConnectEvent);
+    }
+
+    = if (Private !=3D NULL) {
+      Free= Pool (Private);
+    }
+  }=
+
+  return Status;
+}
+
+/**
+  Stops a device control= ler or a bus controller.
+
+  The Stop() f= unction is designed to be invoked from the EFI boot service
+=  DisconnectController().
+  As a result, much of t= he error checking on the parameters to Stop() has
been
+  moved int= o this common boot service. It is legal to call Stop() from other
+  locations, but the following calling restrictions must be fo= llowed or the
+  system behavior will not be determinist= ic.
+  1. ControllerHandle must be a valid EFI_HANDLE th= at was used on a
previous
+     call to this same dr= iver's Start() function.
+  2. The first NumberOfChildre= n handles of ChildHandleBuffer must all be a
val= id
+    &= nbsp;EFI_HANDLE. In addition, all of these handles must have been created
in
+     this driver's Start() function, and the St= art() function must have called
+     Ope= nProtocol() on ControllerHandle with an Attribute of
+  =    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
++  @param[in]  This      &nb= sp;       A pointer to the
EFI_DRIVER_BINDING_PROTOCOL
+          &= nbsp;           &nbs= p;         instance.
+  @param[in]  ControllerHandle  A handle to the devi= ce being stopped.
The handle
+        = ;            &n= bsp;           must = support a bus specific I/O protocol for the
+   &nb= sp;            =             &nb= sp;   driver to use to stop the device.
+ &nbs= p;@param[in]  NumberOfChildren  The number of child device handle= s in
+          =             &nb= sp;         ChildHandleBuffer.=
+  @param[in]  ChildHandleBuffer An array of child= handles to be freed.
May be
+        = ;            &n= bsp;           NULL = if NumberOfChildren is 0.
+
+  @retval EFI= _SUCCESS           The de= vice was stopped.
+  @retval EFI_DEVICE_ERROR  &nbs= p;   The device could not be stopped due to a
=
device
+ &n= bsp;            = ;            &n= bsp;     error.
+
+**/=
+EFI_STATUS
+EFIAPI
+DwMmcHcDriv= erBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL =     *This,
+  IN  EFI_HANDLE &n= bsp;            = ;        Controller,
= +  IN  UINTN         &nbs= p;            &= nbsp;    NumberOfChildren,
+  IN &nb= sp;EFI_HANDLE           &= nbsp;          *ChildHand= leBuffer
+  )
+{
+  EFI= _STATUS            &= nbsp;           &nbs= p; Status;
+  EFI_SD_MMC_PASS_THRU_PROTOCOL  &= nbsp;    *PassThru;
+  DW_MMC_HC_PRI= VATE_DATA            = ;  *Private;
+  LIST_ENTRY    &= nbsp;           &nbs= p;         *Link;
+  LIST_ENTRY          =             &nb= sp;   *NextLink;
+  DW_MMC_HC_TRB  &= nbsp;           &nbs= p;        *Trb;
+
+  DEBUG ((DEBUG_INFO, "DwMmcHcDriverBindingStop: Start\n")= );
+
+  Status =3D gBS->OpenProtocol (<= br class=3D"">+           = ;       Controller,
+ &nbs= p;            &= nbsp;   &gEfiSdMmcPassThruProtocolGuid,
+ =             &nb= sp;    (VOID**) &PassThru,
+  &n= bsp;            = ;   This->DriverBindingHandle,
+  &nbs= p;            &= nbsp;  Controller,
+      =             EFI= _OPEN_PROTOCOL_GET_PROTOCOL
+      &= nbsp;           );+  if (EFI_ERROR (Status)) {
+   =  return Status;
+  }
+
= +  Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+=  //
+  // Close Non-Blocking timer and free Task l= ist.
+  //
+  if (Private->TimerEv= ent !=3D NULL) {
+    gBS->CloseEvent (Priv= ate->TimerEvent);
+    Private->TimerEve= nt =3D NULL;
+  }
+  if (Private->= ConnectEvent !=3D NULL) {
+    gBS->CloseEv= ent (Private->ConnectEvent);
+    Private-&= gt;ConnectEvent =3D NULL;
+  }
+  //<= br class=3D"">+  // As the timer is closed, there is no needs to use T= PL lock to
+  // protect the critical region "queue".+  //
+  for (Link =3D GetFirstNode (&a= mp;Private->Queue);
+       = !IsNull (&Private->Queue, Link);
+    &= nbsp;  Link =3D NextLink) {
+    Nex= tLink =3D GetNextNode (&Private->Queue, Link);
+  = ;  RemoveEntryList (Link);
+    Trb = = =3D DW_MMC_HC_TRB_FROM_THIS (Link);
+    Trb-= >Packet->TransactionStatus =3D EFI_ABORTED;
+  &nb= sp; gBS->SignalEvent (Trb->Event);
+   &= nbsp;DwMmcFreeTrb (Trb);
+  }
+
+  //
+  // Uninstall Block I/O protocol fro= m the device handle
+  //
+  Status = =3D gBS->UninstallProtocolInterface (
+    = ;            &n= bsp; Controller,
+       &= nbsp;          &gEfiS= dMmcPassThruProtocolGuid,
+      &nb= sp;           &(= Private->PassThru)
+       &= nbsp;          );
+
+  if (EFI_ERROR (Status)) {
+ &n= bsp;  return Status;
+  }
+
+  gBS->CloseProtocol (
+    = ;     Controller,
+   &nbs= p;     &gEfiPciIoProtocolGuid,
+=         This->DriverBindingHand= le,
+         Control= ler
+         );
+
+  FreePool (Private);
+
+  DEBUG ((DEBUG_INFO, "DwMmcHcDriverBindingStop: End with %r= \n",
Status));
+
+  return Status;
+}+
+/**
+  Sends SD command to= an SD card that is attached to the SD controller.
+
+  The PassThru() function sends the SD command specified by Pa= cket to
the SD
+  card specified by Slot.
+
+  If Packet is successfully sent to the SD card, then EFI_SUCC= ESS is
returned.
+
+  If a device error occurs whil= e sending the Packet, then
EFI_DEVICE_ERROR is
+  returned.
+
+  If Slot is not in a valid range for the SD c= ontroller, then
+  EFI_INVALID_PARAMETER is returned.+
+  If Packet defines a data command but bo= th InDataBuffer and
OutDataBuffer are
+  NULL, EFI_INVALID_PARAM= ETER is returned.
+
+  @param[in]  &n= bsp;  This          =  A pointer to the
EFI_SD_MMC_PASS_THRU_PROT= OCOL
+    = ;            &n= bsp;            = ;   instance.
+  @param[in]   &= nbsp; Slot           = ;The slot number of the SD card to send the
+   &nb= sp;            =             &nb= sp;   command to.
+  @param[in,out] Packe= t         A pointer to the SD comma= nd data structure.
+  @param[in]     = ;Event          If Event is NU= LL, blocking I/O is performed. If
+     &= nbsp;           &nbs= p;            &= nbsp; Event is not NULL, then nonblocking I/O is
+  = ;            &n= bsp;            = ;     performed, and Event will be signaled when t= he
+          &n= bsp;            = ;         Packet completes.+
+  @retval EFI_SUCCESS    &= nbsp;      The SD Command Packet was sent by = the
host.
+  @retval EFI_DEVICE_ERROR      = ;A device error occurred while attempting
to sen= d
+    &n= bsp;            = ;            &n= bsp;  the SD command Packet.
+  @retval EFI_IN= VALID_PARAMETER Packet, Slot, or the contents of the
Packet is
+  &= nbsp;           &nbs= p;            &= nbsp;    invalid.
+  @retval EFI_INV= ALID_PARAMETER Packet defines a data command but
both
+   &nbs= p;            &= nbsp;           &nbs= p;   InDataBuffer and OutDataBuffer are NULL.
= +  @retval EFI_NO_MEDIA        &nbs= p; SD Device not present in the Slot.
+  @retval EF= I_UNSUPPORTED       The command described by = the SD
Command Packet
+         =             &nb= sp;          is not suppo= rted by the host controller.
+  @retval EFI_BAD_BUFFER_S= IZE   The InTransferLength or
OutTrans= ferLength
+   =             &nb= sp;            =     exceeds the limit supported by SD card
+             = ;            &n= bsp;      ( i.e. if the number of bytes excee= d the Last
+         =             &nb= sp;          LBA).
+
+**/
+EFI_STATUS
+EFIAP= I
+DwMmcPassThruPassThru (
+  IN  &nb= sp;  EFI_SD_MMC_PASS_THRU_PROTOCOL      =    *This,
+  IN     U= INT8            &nbs= p;            &= nbsp;       Slot,
+  = IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   *Packet,
+  IN     EFI_EVENT     &nb= sp;            =            Event &nb= sp;  OPTIONAL
+  )
+{
+  EFI_STATUS         &= nbsp;           &nbs= p;Status;
+  DW_MMC_HC_PRIVATE_DATA    &n= bsp;     *Private;
+  DW_MMC_HC= _TRB            &nbs= p;      *Trb;
+  EFI_TPL &= nbsp;           &nbs= p;           OldTpl;=
+
+  if ((This =3D=3D NULL) || (Packet = =3D=3D NULL)) {
+    return EFI_INVALID_PARAM= ETER;
+  }
+
+  if ((Pa= cket->SdMmcCmdBlk =3D=3D NULL) || (Packet->SdMmcStatusBlk =3D=3D
NULL)) {
+    return EFI_INVALID_PARAMETER;
+ &= nbsp;}
+
+  if ((Packet->OutDataBuffer = = =3D=3D NULL) && (Packet->OutTransferLength !=3D
<= /blockquote>0)) {
+ &nbs= p;  return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Packet->InDataBuffer =3D=3D NULL) &a= mp;& (Packet->InTransferLength !=3D 0))
{=
+    ret= urn EFI_INVALID_PARAMETER;
+  }
+
+  Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This);
+
+  if (!Private->Slot[Slot].Enable) {
+    return EFI_INVALID_PARAMETER;
+  = }
+
+  if (!Private->Slot[Slot].MediaPr= esent) {
+    return EFI_NO_MEDIA;
+  }
+
+  Trb =3D DwMmcCreateTrb (= Private, Slot, Packet, Event);
+  if (Trb =3D=3D NULL) {=
+    return EFI_OUT_OF_RESOURCES;
+  }
+  //
+  // Immediately = return for async I/O.
+  //
+  if (Ev= ent !=3D NULL) {
+    return EFI_SUCCESS;
+  }
+
+  //
= +  // Wait async I/O list is empty before execute sync I/O operation.<= br class=3D"">+  //
+  while (TRUE) {
+    OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY);
+    if (IsListEmpty (&Private->Queue)) {
+      gBS->RestoreTPL (OldTpl);
+      break;
+   &= nbsp;}
+    gBS->RestoreTPL (OldTpl);
+  }
+
+  Status =3D DwMmcWa= itTrbEnv (Private, Trb);
+  if (EFI_ERROR (Status)) {+    goto Done;
+  }
+
+  Status =3D DwMmcExecTrb (Private, Trb);
+  if (EFI_ERROR (Status)) {
+   &nb= sp;goto Done;
+  }
+
+  = ;Status =3D DwMmcWaitTrbResult (Private, Trb);
+  if (EF= I_ERROR (Status)) {
+    goto Done;
+  }
+
+Done:
+  = ;if (Trb !=3D NULL) {
+    DwMmcFreeTrb (Trb);=
+  }
+
+  return Statu= s;
+}
+
+/**
+ &nbs= p;Used to retrieve next slot numbers supported by the SD controller. The+  function returns information about all available slots = (populated or
+  not-populated).
+
+  The GetNextSlot() function retrieves the next slot number on= an SD
controller.
+  If on input Slot is 0xFF, then the slot numbe= r of the first slot on the SD
+  controller is returned.=
+
+  If Slot is a slot number that was re= turned on a previous call to
+  GetNextSlot(), then the = slot number of the next slot on the SD controller
is
+  returned.+
+  If Slot is not 0xFF and Slot was not r= eturned on a previous call to
+  GetNextSlot(), EFI_INVA= LID_PARAMETER is returned.
+
+  If Slot is= the slot number of the last slot on the SD controller, then
= +  EFI_NOT_FOUND is returned.
+
+  @p= aram[in]     This       &= nbsp;   A pointer to the
EFI_SD_M= MMC_PASS_THRU_PROTOCOL
+=             &n= bsp;            = ;      instance.
+  @param= [in,out] Slot           O= n input, a pointer to a slot number on the SD
+   &= nbsp;           &nbs= p;            &= nbsp;   controller.
+     =             &nb= sp;            =   On output, a pointer to the next slot number on
+=             &n= bsp;            = ;      the SD controller.
+ &nb= sp;            =             &nb= sp;     An input value of 0xFF retrieves the first= slot
+          = ;            &n= bsp;         number on the SD = controller.
+
+  @retval EFI_SUCCESS  = ;         The next slot number= on the SD controller
was
+        &n= bsp;            = ;           returned= in Slot.
+  @retval EFI_NOT_FOUND    &nb= sp;    There are no more slots on this SD
controller.
+  @retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not
returned on a
+          &nb= sp;            =          previous call to GetN= extSlot().
+
+**/
+EFI_STATUS
+EFIAPI
+DwMmcPassThruGetNextSlot (
= +  IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  &nbs= p;     *This,
+  IN OUT UINT8 &= nbsp;           &nbs= p;            &= nbsp;     *Slot
+  )
+{
+  DW_MMC_HC_PRIVATE_DATA    &n= bsp;     *Private;
+
+=  if ((This =3D=3D NULL) || (Slot =3D=3D NULL)) {
+ &nbs= p;  return EFI_INVALID_PARAMETER;
+  }
+
+  Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (Thi= s);
+
+  if (*Slot =3D=3D 0xFF) {
+    if (Private->Slot[0].Enable) {
= +      *Slot =3D 0;
+   &n= bsp;  Private->PreviousSlot =3D 0;
+   = ;   return EFI_SUCCESS;
+    }<= br class=3D"">+    return EFI_NOT_FOUND;
+ &nb= sp;} else if (*Slot =3D=3D Private->PreviousSlot) {
+ &nbs= p;  return EFI_NOT_FOUND;
+  } else {
+    return EFI_INVALID_PARAMETER;
+ &n= bsp;}
+}
+
+/**
+ &= nbsp;Used to allocate and build a device path node for an SD card on the SD=
+  controller.
+
+  Th= e BuildDevicePath() function allocates and builds a single device node
+  for the SD card specified by Slot.
+
+  If the SD card specified by Slot is not present on the SD c= ontroller, then
+  EFI_NOT_FOUND is returned.
+
+  If DevicePath is NULL, then EFI_INVALID_PARA= METER is returned.
+
+  If there are not e= nough resources to allocate the device path node, then
+ &nbs= p;EFI_OUT_OF_RESOURCES is returned.
+
+  O= therwise, DevicePath is allocated with the boot service AllocatePool(),
+  the contents of DevicePath are initialized to describe t= he SD card
specified
+  by Slot, and EFI_SUCCESS is returned.
+
+  @param[in]     This &n= bsp;         A pointer to the<= br class=3D"">
EFI_SD_MMMC_PASS_THRU_PROTOCOL
+       &nb= sp;            =             ins= tance.
+  @param[in]     Slot  =          Specifies the slot nu= mber of the SD card for
+       = ;            &n= bsp;            = ;which a device path node is to be allocated and
+  &nbs= p;            &= nbsp;           &nbs= p;    built.
+  @param[in,out] Devic= ePath     A pointer to a single device path node that+           =             &nb= sp;        describes the SD card sp= ecified by Slot. This
+       &= nbsp;           &nbs= p;            f= unction is responsible for allocating the
+    = ;            &n= bsp;            = ;   buffer DevicePath with the boot service
+ =             &nb= sp;            =       AllocatePool(). It is the caller's resp= onsi-
+          = ;            &n= bsp;         bility to free De= vicePath when the caller is
+      &= nbsp;           &nbs= p;            &= nbsp;finished with DevicePath.
+
+  @retva= l EFI_SUCCESS           T= he device path node that describes the SD
card
+     = ;            &n= bsp;            = ;  specified by Slot was allocated and returned in
= +             &= nbsp;           &nbs= p;      DevicePath.
+  @re= tval EFI_NOT_FOUND         The SD c= ard specified by Slot does not
exist on
+      = ;            &n= bsp;            = ; the SD controller.
+  @retval EFI_INVALID_PARAMET= ER DevicePath is NULL.
+  @retval EFI_OUT_OF_RESOURCES &= nbsp;There are not enough resources to
allocate<= br class=3D"">
+    &nbs= p;            &= nbsp;           &nbs= p;  DevicePath.
+
+**/
= +EFI_STATUS
+EFIAPI
+DwMmcPassThruBuildDevicePa= th (
+  IN     EFI_SD_MMC_PASS_THRU_= PROTOCOL       *This,
+  I= N     UINT8        &= nbsp;           &nbs= p;          Slot,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL     &nbs= p;      **DevicePath
+  )<= br class=3D"">+{
+  DW_MMC_HC_PRIVATE_DATA   &= nbsp;      *Private;
+  SD= _DEVICE_PATH           &n= bsp;      *SdNode;
+  EMMC= _DEVICE_PATH           &n= bsp;    *EmmcNode;
+
+ &nbs= p;if ((This =3D=3D NULL) || (DevicePath =3D=3D NULL) || (Slot >=3D
DW_MMC_HC_MAX_SLOT)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Private =3D DW_M= MC_HC_PRIVATE_FROM_THIS (This);
+
+  if ((= !Private->Slot[Slot].Enable) || (!Private->Slot[Slot].MediaPresent)) = {
+    return EFI_NOT_FOUND;
+ &= nbsp;}
+
+  if (Private->Slot[Slot].Car= dType =3D=3D SdCardType) {
+    SdNode =3D All= ocateCopyPool (sizeof (SD_DEVICE_PATH),
&mSd= DpTemplate);
+  &nb= sp; if (SdNode =3D=3D NULL) {
+     =  return EFI_OUT_OF_RESOURCES;
+    }
+    SdNode->SlotNumber =3D Slot;
+
+    *DevicePath =3D (EFI_DEVICE_PATH_PROTO= COL *) SdNode;
+  } else if (Private->Slot[Slot].Card= Type =3D=3D EmmcCardType) {
+    EmmcNode =3D = AllocateCopyPool (sizeof (EMMC_DEVICE_PATH),
&am= p;mEmmcDpTemplate);
+ &n= bsp;  if (EmmcNode =3D=3D NULL) {
+   &nb= sp;  return EFI_OUT_OF_RESOURCES;
+   &nb= sp;}
+    EmmcNode->SlotNumber =3D Slot;+
+    *DevicePath =3D (EFI_DEVICE= _PATH_PROTOCOL *) EmmcNode;
+  } else {
+ =    //
+    // Currently we only= support SD and EMMC two device nodes.
+    //=
+    return EFI_NOT_FOUND;
+ &n= bsp;}
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This functio= n retrieves an SD card slot number based on the input device
=
path.
+
+  The GetSlotNumber() function retrieves slot number for t= he SD card
specified
+  by the DevicePath node. If DevicePath is NU= LL,
EFI_INVALID_PARAMETER is
+  returned.
+
+  If DevicePath is not a device path node type that the SD Pas= s Thru driver
+  supports, EFI_UNSUPPORTED is returned.<= br class=3D"">+
+  @param[in]  This   &nb= sp;          A pointer to= the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+       = ;            &n= bsp;            = ;instance.
+  @param[in]  DevicePath   &n= bsp;    A pointer to the device path node that
describes
+            =             &nb= sp;       a SD card on the SD controller= .
+  @param[out] Slot      &nbs= p;       On return, points to the slot n= umber of an SD
+        &n= bsp;            = ;           card on = the SD controller.
+
+  @retval EFI_SUCCES= S           SD card slot = number is returned in Slot.
+  @retval EFI_INVALID_PARAM= ETER Slot or DevicePath is NULL.
+  @retval EFI_UNSUPPOR= TED       DevicePath is not a device path nod= e
type that
+          &nbs= p;            &= nbsp;        the SD Pass Thru drive= r supports.
+
+**/
+EFI_STATUS+EFIAPI
+DwMmcPassThruGetSlotNumber (
+  IN  EFI_SD_MMC_PASS_THRU_PROTOCOL     &= nbsp;    *This,
+  IN  EFI_DEVI= CE_PATH_PROTOCOL          &nbs= p;    *DevicePath,
+  OUT UINT8 &nbs= p;            &= nbsp;           &nbs= p;       *Slot
+  )+{
+  DW_MMC_HC_PRIVATE_DATA   &n= bsp;      *Private;
+  SD_= DEVICE_PATH           &nb= sp;      *SdNode;
+  EMMC_= DEVICE_PATH           &nb= sp;    *EmmcNode;
+  UINT8  &nb= sp;            =             Slo= tNumber;
+
+  if ((This =3D=3D NULL) || (D= evicePath =3D=3D NULL) || (Slot =3D=3D NULL)) {
+   = ; return EFI_INVALID_PARAMETER;
+  }
= +
+  Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This);
+
+  //
+  // Check whethe= r the DevicePath belongs to SD_DEVICE_PATH or
EM= MC_DEVICE_PATH
+  /= /
+  if ((DevicePath->Type !=3D MESSAGING_DEVICE_PATH= ) ||
+      ((DevicePath->SubType= !=3D MSG_SD_DP) &&
+      &= nbsp;(DevicePath->SubType !=3D MSG_EMMC_DP)) ||
+  &n= bsp;   (DevicePathNodeLength(DevicePath) !=3D sizeof(SD_DEVI= CE_PATH)) ||
+      (DevicePathNodeL= ength(DevicePath) !=3D
sizeof(EMMC_DEVICE_PATH))= ) {
+    = return EFI_UNSUPPORTED;
+  }
+
+  if (DevicePath->SubType =3D=3D MSG_SD_DP) {
+ &= nbsp;  SdNode =3D (SD_DEVICE_PATH *) DevicePath;
+ =    SlotNumber =3D SdNode->SlotNumber;
+ &nb= sp;} else {
+    EmmcNode =3D (EMMC_DEVICE_PAT= H *) DevicePath;
+    SlotNumber =3D EmmcNode-= >SlotNumber;
+  }
+
+ &nb= sp;if (SlotNumber >=3D DW_MMC_HC_MAX_SLOT) {
+   = ; return EFI_NOT_FOUND;
+  }
+
+  if (Private->Slot[SlotNumber].Enable) {
+ =    *Slot =3D SlotNumber;
+    r= eturn EFI_SUCCESS;
+  } else {
+  &nb= sp; return EFI_NOT_FOUND;
+  }
+}
+
+/**
+  Resets an SD card tha= t is connected to the SD controller.
+
+  = The ResetDevice() function resets the SD card specified by Slot.
+
+  If this SD controller does not support a dev= ice reset operation,
+  EFI_UNSUPPORTED is returned.
+
+  If Slot is not in a valid slot number fo= r this SD controller,
+  EFI_INVALID_PARAMETER is return= ed.
+
+  If the device reset operation is = completed, EFI_SUCCESS is returned.
+
+  @= param[in]  This          =     A pointer to the
EFI_SD_= MMC_PASS_THRU_PROTOCOL
+=             &n= bsp;            = ;      instance.
+  @param= [in]  Slot           = ;   Specifies the slot number of the SD card to be
+            =             &nb= sp;       reset.
+
+  @retval EFI_SUCCESS       &nbs= p;   The SD card specified by Slot was reset.
= +  @retval EFI_UNSUPPORTED       The SD = controller does not support a
device
+      &nb= sp;            =             &nb= sp;reset operation.
+  @retval EFI_INVALID_PARAMETER Slo= t number is invalid.
+  @retval EFI_NO_MEDIA   = ;       SD Device not present in the Slo= t.
+  @retval EFI_DEVICE_ERROR     &= nbsp;The reset command failed due to a device
er= ror
+
+**/=
+EFI_STATUS
+EFIAPI
+DwMmcPassTh= ruResetDevice (
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL &nbs= p;         *This,
+  IN UINT8          &n= bsp;            = ;            Sl= ot
+  )
+{
+  DW_MMC_HC= _PRIVATE_DATA          *Privat= e;
+  LIST_ENTRY       &nb= sp;            =   *Link;
+  LIST_ENTRY     = ;            &n= bsp;    *NextLink;
+  DW_MMC_HC_TRB =             &nb= sp;     *Trb;
+  EFI_TPL  =             &nb= sp;          OldTpl;
+
+  if (This =3D=3D NULL) {
+ &= nbsp;  return EFI_INVALID_PARAMETER;
+  }
+
+  Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (= This);
+
+  if (!Private->Slot[Slot].En= able) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!Private->= ;Slot[Slot].MediaPresent) {
+    return EFI_NO= _MEDIA;
+  }
+
+  //+  // Free all async I/O requests in the queue
+  //
+  OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY= );
+
+  for (Link =3D GetFirstNode (&P= rivate->Queue);
+       !IsN= ull (&Private->Queue, Link);
+     = ;  Link =3D NextLink) {
+    NextLin= k =3D GetNextNode (&Private->Queue, Link);
+  &nb= sp; RemoveEntryList (Link);
+    Trb =3D = DW_MMC_HC_TRB_FROM_THIS (Link);
+    Trb->P= acket->TransactionStatus =3D EFI_ABORTED;
+   &n= bsp;gBS->SignalEvent (Trb->Event);
+    = DwMmcFreeTrb (Trb);
+  }
+
+=  gBS->RestoreTPL (OldTpl);
+
+  r= eturn EFI_SUCCESS;
+}
diff --git a/EmbeddedPkg/= Drivers/DwMmcHcDxe/DwMmcHci.c
b/EmbeddedPkg/Driv= ers/DwMmcHcDxe/DwMmcHci.c
new file mode 100644
index 000000000000..b091f9803b2e
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/D= wMmcHci.c
@@ -0,0 +1,1602 @@
+/** @file
+  This driver is used to manage Designware SD/MMC PCI host con= trollers.
+
+  It would expose EFI_SD_MMC_= PASS_THRU_PROTOCOL for upper layer
use.
+
+  Copyrig= ht (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR= >
+
+  This program and the accompanyin= g materials are licensed and made
available
+  under the terms and = conditions of the BSD License which accompanies
= this
+  distributio= n.  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 <IndustryStandard/Emmc.h>
+#include <Industr= yStandard/Sd.h>
+
+#include <Library/ArmL= ib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DmaLib.h>
+#include <Libra= ry/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#incl= ude <Library/UefiBootServicesTableLib.h>
+
+#include "DwMmcHcDxe.h"
+
+/**
+  Dump the content of SD/MMC host controller's Capability Register.<= br class=3D"">+
+  @param[in]  Slot   &nb= sp;        The slot number of the S= D card to send the
+       &nbs= p;            &= nbsp;         command to.
+  @param[in]  Capability      = ;The buffer to store the capability data.
+
+**= /
+VOID
+DumpCapabilityReg (
+ &n= bsp;IN UINT8           &n= bsp;    Slot,
+  IN DW_MMC_HC_SLOT_C= AP   *Capability
+  )
+{
+  //
+  // Dump Capability Data
+  //
+  DEBUG ((
+   &n= bsp;DEBUG_INFO,
+    " =3D=3D Slot [%d] Capabi= lity is 0x%x =3D=3D\n",
+    Slot,
+    Capability
+    ));
+  DEBUG ((
+    DEBUG_INFO,+    "   Base Clk Freq   &n= bsp; %dKHz\n",
+    Capability->BaseCl= kFreq
+    ));
+  DEBUG ((<= br class=3D"">+    DEBUG_INFO,
+   &= nbsp;"   BusWidth         = ; %d\n",
+    Capability->BusWidth
+    ));
+  DEBUG ((
+    DEBUG_INFO,
+    " =   HighSpeed Support %a\n",
+    Capa= bility->HighSpeed ? "TRUE" : "FALSE"
+    )= );
+  DEBUG ((
+    DEBUG_I= NFO,
+    "   Voltage 1.8  &nbs= p;    %a\n",
+    Capabili= ty->Voltage18 ? "TRUE" : "FALSE"
+    ));+  DEBUG ((
+    DEBUG_INFO,=
+    "   64-bit Sys Bus   = ; %a\n",
+    Capability->SysBus64 ? "= TRUE" : "FALSE"
+    ));
+  = ;DEBUG ((DEBUG_INFO, "   SlotType      &= nbsp;   "));
+  if (Capability->SlotTy= pe =3D=3D 0x00) {
+    DEBUG ((DEBUG_INFO, "%a= \n", "Removable Slot"));
+  } else if (Capability->Sl= otType =3D=3D 0x01) {
+    DEBUG ((DEBUG_INFO,= "%a\n", "Embedded Slot"));
+  } else if (Capability->= ;SlotType =3D=3D 0x02) {
+    DEBUG ((DEBUG_IN= FO, "%a\n", "Shared Bus Slot"));
+  } else {
+    DEBUG ((DEBUG_INFO, "%a\n", "Reserved"));
+  }
+  DEBUG ((
+   = ; DEBUG_INFO,
+    "   SDR50 &n= bsp;Support    %a\n",
+    Capa= bility->Sdr50 ? "TRUE" : "FALSE"
+    ));+  DEBUG ((
+    DEBUG_INFO,=
+    "   SDR104 Support   = ; %a\n",
+    Capability->Sdr104 ? "TR= UE" : "FALSE"
+    ));
+  D= EBUG ((
+    DEBUG_INFO,
+  = ;  "   DDR50  Support    %a\n",
+    Capability->Ddr50 ? "TRUE" : "FALSE"
+    ));
+  return;
+}
+
+/**
+  Set all inte= rrupt status bits in Normal and Error Interrupt Status Enable
+  register.
+
+  @param[in] DevIo &= nbsp;        The DEVICE IO protocol= instance.
+
+  @retval EFI_SUCCESS  =      The operation executes successfully.
+  @retval Others        &nb= sp;   The operation fails.
+
+**= /
+EFI_STATUS
+DwMmcHcEnableInterrupt (
+  UINTN          =             &nb= sp;   DevBase
+  )
+{
+  UINT32         &nb= sp;          IntStatus;+  UINT32         = ;           IdIntEn;=
+  UINT32        &nb= sp;           IdSts;=
+
+  //
+  // Enable a= ll bits in Interrupt Mask Register
+  //
+=  IntStatus =3D 0;
+  MmioWrite32 (DevBase + DW_MMC= _INTMASK, IntStatus);
+
+  //
+  // Clear status in Interrupt Status Register
+ &nbs= p;//
+  IntStatus =3D ~0;
+  MmioWrit= e32 (DevBase + DW_MMC_RINTSTS, IntStatus);
+
+ =  IdIntEn =3D ~0;
+  MmioWrite32 (DevBase + DW_MMC_I= DINTEN, IdIntEn);
+
+  IdSts =3D ~0;
+  MmioWrite32 (DevBase + DW_MMC_IDSTS, IdSts);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DwMmcHcGetCapability (
+  IN     UINTN     &nb= sp;            =  DevBase,
+  IN     EFI_HANDLE =             &nb= sp;Controller,
+  IN     UINT8  = ;            &n= bsp;    Slot,
+     O= UT DW_MMC_HC_SLOT_CAP      *Capacity
+  )
+{
+  PLATFORM_DW_MMC_PROTOCOL =       *PlatformDwMmc;
+  E= FI_STATUS            = ;         Status;
+
+  if (Capacity =3D=3D NULL) {
+  = ;  return EFI_INVALID_PARAMETER;
+  }
+  Status =3D gBS->LocateProtocol (
+  &n= bsp;            = ;   &gPlatformDwMmcProtocolGuid,
+  &= nbsp;           &nbs= p;   NULL,
+      &nb= sp;           (VOID = **) &PlatformDwMmc
+       =            );
+  if (EFI_ERROR (Status)) {
+    = ;return Status;
+  }
+  Status =3D Pl= atformDwMmc->GetCapability (Controller, Slot, Capacity);
+=  return Status;
+}
+
+/**+  Detect whether there is a SD/MMC card attached at the = specified
SD/MMC host
+  controller slot.
+
+  Refer to SD Host Controller Simplified spec 3.0 Section 3.1 = for details.
+
+  @param[in]  DevIo &= nbsp;       The DEVICE IO protocol insta= nce.
+  @param[in]  Slot     &n= bsp;    The slot number of the SD card to send the
command
+            =             &nb= sp;   to.
+  @param[out] MediaPresent &nb= sp;The pointer to the media present boolean
valu= e.
+
+ &nb= sp;@retval EFI_SUCCESS       There is no medi= a change happened.
+  @retval EFI_MEDIA_CHANGED There is= media change happened.
+  @retval Others   &n= bsp;        The detection fails.+
+**/
+EFI_STATUS
+D= wMmcHcCardDetect (
+  IN     UINTN &= nbsp;           &nbs= p;    DevBase,
+  IN   &nb= sp; EFI_HANDLE          &= nbsp;  Controller,
+  IN    &nb= sp;UINT8            =       Slot,
+    = ; OUT BOOLEAN          &n= bsp;     *MediaPresent
+  )
+{
+  PLATFORM_DW_MMC_PROTOCOL  *Platfor= mDwMmc;
+  EFI_STATUS      &nbs= p;         Status;
+
+  if (MediaPresent =3D=3D NULL) {
+ =    return EFI_INVALID_PARAMETER;
+  }
+  Status =3D gBS->LocateProtocol (
+ &nbs= p;            &= nbsp;   &gPlatformDwMmcProtocolGuid,
+ &nb= sp;            =     NULL,
+      = ;            (V= OID **) &PlatformDwMmc
+      &n= bsp;           );+  if (EFI_ERROR (Status)) {
+   &= nbsp;return Status;
+  }
+  *MediaPre= sent =3D PlatformDwMmc->CardDetect (Controller, Slot);
+ &= nbsp;return EFI_SUCCESS;
+}
+
+ST= ATIC
+EFI_STATUS
+DwMmcHcUpdateClock (
+  IN UINTN         &nb= sp;        DevBase
+ =  )
+{
+  UINT32    &nb= sp;            =    Cmd;
+  UINT32     = ;            &n= bsp;  IntStatus;
+
+  Cmd =3D BI= T_CMD_WAIT_PRVDATA_COMPLETE |
BIT_CMD_UPDATE_CLO= CK_ONLY |
+   =      BIT_CMD_START;
+  MmioWrit= e32 (DevBase + DW_MMC_CMD, Cmd);
+
+  whil= e (1) {
+    Cmd =3D MmioRead32 (DevBase + DW_= MMC_CMD);
+
+    if (!(Cmd &= CMD_START_BIT)) {
+      break;
+    }
+
+  &nbs= p; IntStatus =3D MmioRead32 (DevBase + DW_MMC_RINTSTS);
= +
+    if (IntStatus & DW_MMC_INT_HLE) {+      DEBUG ((
+  = ;      DEBUG_ERROR,
+  &nb= sp;     "DwMmcHcUpdateClock: failed to update mmc = clock frequency\n"
+       &nbs= p;));
+      return EFI_DEVICE_ERROR= ;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Stop SD/MMC card clock.
+
+  @param[in] DevIo     &nb= sp;    The DEVICE IO protocol instance.
+=
+  @retval EFI_SUCCESS      &n= bsp;Succeed to stop SD/MMC clock.
+  @retval Others &nbs= p;          Fail to stop = SD/MMC clock.
+
+**/
+EFI_STATUS<= br class=3D"">+DwMmcHcStopClock (
+  IN UINTN  &nbs= p;            &= nbsp;  DevBase
+  )
+{
+  EFI_STATUS         &= nbsp;      Status;
+  UINT= 32             =        ClkEna;
+
+  //
+  // Disable MMC clock first
+  //
+  ClkEna =3D 0;
+  = ;MmioWrite32 (DevBase + DW_MMC_CLKENA, ClkEna);
+
+  Status =3D DwMmcHcUpdateClock (DevBase);
+  i= f (EFI_ERROR (Status)) {
+    return Status;+  }
+  return Status;
+= }
+
+/**
+  SD/MMC card cloc= k supply.
+
+  @param[in] DevIo  &nbs= p;       The DEVICE IO protocol instance= .
+  @param[in] ClockFreq      = The max clock frequency to be set. The unit is
K= Hz.
+  @param[in] C= apability     The capability of the slot.
+
+  @retval EFI_SUCCESS      =  The clock is supplied successfully.
+  @retval Oth= ers            The c= lock isn't supplied successfully.
+
+**/
+EFI_STATUS
+DwMmcHcClockSupply (
+ &nb= sp;IN UINTN           &nb= sp;      DevBase,
+  IN UI= NT64            &nbs= p;    ClockFreq,
+  IN DW_MMC_HC_SLO= T_CAP     Capability
+  )
+{
+  EFI_STATUS      &n= bsp;         Status;
+  UINT32          = ;          BaseClkFreq;+  UINT32         = ;           SettingF= req;
+  UINT32        = ;            Di= visor;
+  UINT32       &nb= sp;            = Remainder;
+  UINT32       = ;            &n= bsp;MmcStatus;
+  UINT32      &= nbsp;           &nbs= p; ClkEna;
+  UINT32      =             &nb= sp; ClkSrc;
+
+  //
+ &= nbsp;// Calculate a divisor for SD clock frequency
+  //=
+  ASSERT (Capability.BaseClkFreq !=3D 0);
+
+  BaseClkFreq =3D Capability.BaseClkFreq;
+  if (ClockFreq =3D=3D 0) {
+    = return EFI_INVALID_PARAMETER;
+  }
+
+  if (ClockFreq > BaseClkFreq) {
+  &n= bsp; ClockFreq =3D BaseClkFreq;
+  }
= +
+  //
+  // Calculate the divisor o= f base frequency.
+  //
+  Divisor &n= bsp;   =3D 0;
+  SettingFreq =3D BaseClkF= req;
+  while (ClockFreq < SettingFreq) {
+    Divisor++;
+
+  &nb= sp; SettingFreq =3D BaseClkFreq / (2 * Divisor);
+  = ;  Remainder   =3D BaseClkFreq % (2 * Divisor);
+    if ((ClockFreq =3D=3D SettingFreq) && (R= emainder =3D=3D 0)) {
+      break;<= br class=3D"">+    }
+    if ((= ClockFreq =3D=3D SettingFreq) && (Remainder !=3D 0)) {
+      SettingFreq ++;
+  &nb= sp; }
+  }
+
+  DE= BUG ((
+    DEBUG_INFO,
+  =   "BaseClkFreq %dKHz Divisor %d ClockFreq %dKhz\n",
+    BaseClkFreq,
+    Divisor= ,
+    ClockFreq
+   &= nbsp;));
+
+  //
+  // = Wait until MMC is idle
+  //
+  do {<= br class=3D"">+    MmcStatus =3D MmioRead32 (DevBase + DW_MM= C_STATUS);
+  } while (MmcStatus & DW_MMC_STS_DATA_B= USY);
+
+  do {
+  &nbs= p; Status =3D DwMmcHcStopClock (DevBase);
+  } whil= e (EFI_ERROR (Status));
+
+  do {
+    ClkSrc =3D 0;
+    = MmioWrite32 (DevBase + DW_MMC_CLKSRC, ClkSrc);
+   =  //
+    // Set clock divisor
+    //
+    MmioWrite32 (De= vBase + DW_MMC_CLKDIV, Divisor);
+    //
+    // Enable MMC clock
+  &nbs= p; //
+    ClkEna =3D 1;
+ =    MmioWrite32 (DevBase + DW_MMC_CLKENA, ClkEna);
+
+    Status =3D DwMmcHcUpdateClock (D= evBase);
+  } while (EFI_ERROR (Status));
= +
+  return EFI_SUCCESS;
+}
= +
+/**
+  Set the SD/MMC bus width.
+
+  Refer to SD Host Controller Simplified spec= 3.0 Section 3.4 for details.
+
+  @param[= in] DevIo          The DEVICE = IO protocol instance.
+  @param[in] IsDdr   &n= bsp;      A boolean to indicate it's dual dat= a rate or not.
+  @param[in] BusWidth    =    The bus width used by the SD/MMC device, it
must be
+ =             &nb= sp;            =   1, 4 or 8.
+
+  @retval EFI_SU= CCESS       The bus width is set successfully= .
+  @retval Others       =      The bus width isn't set successfully.
+
+**/
+EFI_STATUS
+DwMmcH= cSetBusWidth (
+  IN UINTN      = ;            De= vBase,
+  IN BOOLEAN       = ;         IsDdr,
+  IN UINT16          &n= bsp;      BusWidth
+  )+{
+  UINT32      &= nbsp;           &nbs= p; Ctype;
+  UINT32      &= nbsp;           &nbs= p; Uhs;
+
+  switch (BusWidth) {
+  case 1:
+    Ctype =3D MMC_1= BIT_MODE;
+    break;
+  ca= se 4:
+    Ctype =3D MMC_4BIT_MODE;
+    break;
+  case 8:
+    Ctype =3D MMC_8BIT_MODE;
+   = ; break;
+  default:
+   &n= bsp;return EFI_INVALID_PARAMETER;
+  }
+ &= nbsp;MmioWrite32 (DevBase + DW_MMC_CTYPE, Ctype);
+
+  Uhs =3D MmioRead32 (DevBase + DW_MMC_UHSREG);
= +
+  if (IsDdr) {
+    Uhs = |=3D UHS_DDR_MODE;
+  } else {
+  &nb= sp; Uhs &=3D ~(UHS_DDR_MODE);
+  }
+
+  MmioWrite32 (DevBase + DW_MMC_UHSREG, Uhs);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Supply SD/MMC card with= lowest clock frequency at initialization.
+
+ =  @param[in] DevIo         &nbs= p;The DEVICE IO protocol instance.
+  @param[in] Capabil= ity     The capability of the slot.
+
+  @retval EFI_SUCCESS       = The clock is supplied successfully.
+  @retval Others &n= bsp;          The clock i= sn't supplied successfully.
+
+**/
+EFI_STATUS
+DwMmcHcInitClockFreq (
+  I= N UINTN            &= nbsp;        DevBase,
+  IN DW_MMC_HC_SLOT_CAP        Ca= pability
+  )
+{
+  EFI= _STATUS            &= nbsp;   Status;
+  UINT32   &nb= sp;            =     InitFreq;
+
+  //<= br class=3D"">+  // Calculate a divisor for SD clock frequency
+  //
+  if (Capability.BaseClkFreq =3D=3D 0= ) {
+    //
+    = // Don't support get Base Clock Frequency information via another
method
+    //
+    return EFI_UNSU= PPORTED;
+  }
+  //
+ &= nbsp;// Supply 400KHz clock frequency at initialization phase.
+  //
+  InitFreq =3D DWMMC_INIT_CLOCK_FREQ;
+  Status =3D DwMmcHcClockSupply (DevBase, InitFreq, Capabil= ity);
+  if (EFI_ERROR (Status)) {
+  = ;  return Status;
+  }
+  M= icroSecondDelay (100);
+  return Status;
+= }
+
+/**
+  Supply SD/MMC ca= rd with maximum voltage at initialization.
+
+ =  @param[in] DevIo         &nbs= p;The DEVICE IO protocol instance.
+  @param[in] Capabil= ity     The capability of the slot.
+
+  @retval EFI_SUCCESS       = The voltage is supplied successfully.
+  @retval Others =            The volta= ge isn't supplied successfully.
+
+**/
+EFI_STATUS
+DwMmcHcInitPowerVoltage (
+=  IN UINTN DevBase,
+  IN DW_MMC_HC_SLOT_CAP  =    Capability
+  )
+{
+  UINT32         &nb= sp;          Data;
+  UINT32         &nbs= p;          Timeout;
+
+  Data =3D 0x1;
+  MmioW= rite32 (DevBase + DW_MMC_PWREN, Data);
+
+ &nbs= p;Data =3D DW_MMC_CTRL_RESET_ALL;
+  MmioWrite32 (DevBas= e + DW_MMC_CTRL, Data);
+
+  Timeout =3D D= W_MMC_HC_GENERIC_TIMEOUT;
+  while (Timeout > 0) {+    Data =3D MmioRead32 (DevBase + DW_MMC_CTRL)= ;
+
+    if ((Data & DW_MMC_= CTRL_RESET_ALL) =3D=3D 0) {
+      b= reak;
+    }
+    = ;gBS->Stall (1);
+
+    Timeo= ut--;
+  }
+
+  if (Tim= eout <=3D 0) {
+    DEBUG ((DEBUG_INFO,
+      "DwMmcHcInitPowerVoltage: reset = failed due to timeout"));
+
+    = ;return EFI_TIMEOUT;
+  }
+
= +  Data =3D DW_MMC_CTRL_INT_EN;
+  MmioWrite32 (Dev= Base + DW_MMC_CTRL, Data);
+
+  return EFI= _SUCCESS;
+}
+
+/**
+  Initialize the Timeout Control register with most conservative val= ue at
+  initialization.
+
+=  @param[in] DevIo         &nb= sp;The DEVICE IO protocol instance.
+
+  @= retval EFI_SUCCESS       The timeout control = register is configured
+       =             &nb= sp;        successfully.
+  @retval Others        &nb= sp;   The timeout control register isn't configured
+            =             &nb= sp;   successfully.
+
+**/
+EFI_STATUS
+DwMmcHcInitTimeoutCtrl (
= +  IN UINTN          &nbs= p;       DevBase
+  )=
+{
+  UINT32     &nbs= p;            &= nbsp; Data;
+
+  Data =3D ~0;
+  MmioWrite32 (DevBase + DW_MMC_TMOUT, Data);
+<= br class=3D"">+  Data =3D 0x00FFFFFF;
+  MmioWrite3= 2 (DevBase + DW_MMC_DEBNCE, Data);
+
+  re= turn EFI_SUCCESS;
+}
+
+/**
+  Initial SD/MMC host controller with lowest clock frequency= , max power
and
+  max timeout value at initialization.
+
+  @param[in] DevIo     &nb= sp;    The DEVICE IO protocol instance.
+=  @param[in] Slot         &nbs= p; The slot number of the SD card to send the
command
+   = ;            &n= bsp;            = ;to.
+  @param[in] Capability     Th= e capability of the slot.
+
+  @retval EFI= _SUCCESS       The host controller is initial= ized successfully.
+  @retval Others    &= nbsp;       The host controller isn't in= itialized successfully.
+
+**/
+E= FI_STATUS
+DwMmcHcInitHost (
+  IN UINTN &= nbsp;  DevBase,
+  IN DW_MMC_HC_SLOT_CAP  = ;      Capability
+  )
+{
+  EFI_STATUS     &nbs= p; Status;
+
+  Status =3D DwMmcHcIni= tPowerVoltage (DevBase, Capability);
+  if (EFI_ERROR (S= tatus)) {
+    return Status;
+ =  }
+  return Status;
+}
+
+EFI_STATUS
+DwMmcHcStartDma (
+  IN DW_MMC_HC_PRIVATE_DATA       &nbs= p;   *Private,
+  IN DW_MMC_HC_TRB  =             &nb= sp;     *Trb
+  )
+{
+  UINTN        &= nbsp;           &nbs= p;          DevBase;
+  UINT32         &n= bsp;            = ;        Ctrl;
+ &nbs= p;UINT32            =             &nb= sp;     Bmod;
+  UINT32  &= nbsp;           &nbs= p;            &= nbsp;  Timeout;
+  UINT32    &n= bsp;            = ;            &n= bsp;Data;
+
+//  DevIo  =3D Trb->P= rivate->DevIo;
+  DevBase =3D Trb->Private->Dev= Base;
+
+  //
+  // Res= et DMA
+  //
+  Ctrl =3D DW_MMC_CTRL_= DMA_RESET;
+  MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl);=
+
+  Timeout =3D DW_MMC_HC_GENERIC_TIMEOU= T;
+  while (Timeout > 0) {
+  &nb= sp; Data =3D MmioRead32 (DevBase + DW_MMC_CTRL);
+
+    if ((Data & DW_MMC_CTRL_DMA_RESET) =3D=3D = 0) {
+      break;
+ &= nbsp;  }
+    gBS->Stall (1);
+
+    Timeout--;
+ &= nbsp;}
+
+  if (Timeout <=3D 0) {
+    DEBUG ((DEBUG_ERROR, "Timed out waiting for CT= RL_DMA_RESET"));
+
+    return E= FI_TIMEOUT;
+  }
+
+  B= mod =3D DW_MMC_IDMAC_SWRESET | MmioRead32 (DevBase +
DW_MMC_BMOD);
+
+  MmioWrite32 (DevBase + DW_MMC_BMOD, Bmod);
+
+  //
+  // Select IDMAC
+  //
+  Ctrl =3D DW_MMC_CTRL_IDMAC_EN;
+  Ctrl |=3D MmioRead32 (DevBase + DW_MMC_CTRL);
+  MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl);
+
+  //
+  // Enable IDMAC
+ &= nbsp;//
+  Bmod =3D DW_MMC_IDMAC_ENABLE | DW_MMC_IDMAC_F= B;
+  Bmod |=3D MmioRead32 (DevBase + DW_MMC_BMOD);
+
+  MmioWrite32 (DevBase + DW_MMC_BMOD, Bmod)= ;
+
+  return EFI_SUCCESS;
+= }
+
+EFI_STATUS
+DwMmcHcStopDma (=
+  IN DW_MMC_HC_PRIVATE_DATA     &n= bsp;     *Private,
+  IN DW_MMC= _HC_TRB            &= nbsp;       *Trb
+  )=
+{
+  UINTN      = ;            &n= bsp;            = ;DevBase;
+  UINT32       =             &nb= sp;          Ctrl;
+  UINT32         &nbs= p;            &= nbsp;       Bmod;
+
+  DevBase =3D Trb->Private->DevBase;
++  //
+  // Disable and reset IDMAC
+  //
+  Ctrl =3D MmioRead32 (DevBase + = DW_MMC_CTRL);
+  Ctrl &=3D ~DW_MMC_CTRL_IDMAC_EN;+  Ctrl |=3D DW_MMC_CTRL_DMA_RESET;
+  = MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl);
+
+ =  //
+  // Stop IDMAC
+  //
+  Bmod =3D MmioRead32 (DevBase + DW_MMC_BMOD);
+  Bmod &=3D ~(DW_MMC_BMOD_FB | DW_MMC_BMOD_DE);
+ =  Bmod |=3D DW_MMC_BMOD_SWR;
+  MmioWrite32 (DevBase= + DW_MMC_BMOD, Bmod);
+
+  return EFI_SUC= CESS;
+}
+
+/**
+ &= nbsp;Build DMA descriptor table for transfer.
+
+  @param[in] Trb         &nb= sp;  The pointer to the DW_MMC_HC_TRB instance.
++  @retval EFI_SUCCESS      &nbs= p;The DMA descriptor table is created
successful= ly.
+  @retval Othe= rs            The DM= A descriptor table isn't created successfully.
+
+**/
+EFI_STATUS
+BuildDmaDescTable (
+  IN DW_MMC_HC_TRB        &= nbsp; *Trb
+  )
+{
+ &n= bsp;EFI_PHYSICAL_ADDRESS      Data;
= +  UINT64           =          DataLen;
+  UINT64          &nbs= p;         Entries;
+  UINT32          = ;          Index;
+  UINT64          = ;          Remaining;
+  UINTN         &n= bsp;           Table= Size;
+  UINTN        = ;            &n= bsp;DevBase;
+  EFI_STATUS      = ;          Status;
+  UINTN          = ;           Bytes;+  UINTN         =             Blo= cks;
+  DW_MMC_HC_DMA_DESC_LINE   *DmaDesc;+  UINT32         =            DmaDescPh= y;
+  UINT32        &= nbsp;           Idst= s;
+  UINT32        &= nbsp;           BytC= nt;
+  UINT32        =             Blk= Size;
+
+  Data    =3D Trb-= >DataPhy;
+  DataLen =3D Trb->DataLen;
+  DevBase =3D Trb->Private->DevBase;
+  /= /
+  // Only support 32bit DMA Descriptor Table
+  //
+  if ((Data >=3D 0x100000000ul) ||= ((Data + DataLen) > 0x100000000ul)) {
+    = ;return EFI_INVALID_PARAMETER;
+  }
+ &nbs= p;//
+  // Address field shall be set on 32-bit boundary= (Lower 2-bit is always set
+  // to 0) for 32-bit addre= ss descriptor table.
+  //
+  if ((Da= ta & (BIT0 | BIT1)) !=3D 0) {
+    DEBUG (= (
+      DEBUG_INFO,
+=      "The buffer [0x%x] to construct DMA desc is = not aligned to 4 bytes!\n",
+      D= ata
+      ));
+  = ;}
+
+  Entries   =3D (DataLen += DWMMC_DMA_BUF_SIZE - 1) /
DWMMC_DMA_BUF_SIZE;
+  TableSize =3D Ent= ries * sizeof (DW_MMC_HC_DMA_DESC_LINE);
+  Blocks  = ;  =3D (DataLen + DW_MMC_BLOCK_SIZE - 1) /
DW_MMC_BLOCK_SIZE;
= +
+  Trb->DmaDescPages =3D (UINT32)EFI_SIZE_TO_PAGES = (Entries *
DWMMC_DMA_BUF_SIZE);
+/*  Status =3D DevIo->AllocateB= uffer (
+         &nb= sp;          DevIo,
+           &nbs= p;        AllocateAnyPages,
+            =         EfiBootServicesData,
+            = ;        EFI_SIZE_TO_PAGES (TableSi= ze),
+          =           (EFI_PHYSICAL_A= DDRESS *)&Trb->DmaDesc
+      = ;            &n= bsp; );*/
+  Status =3D DmaAllocateBuffer (EfiBootS= ervicesData, EFI_SIZE_TO_PAGES
(TableSize),
+     &n= bsp;       (VOID *)&Trb->DmaDesc)= ;
+  if (EFI_ERROR (Status)) {
+  &nb= sp; return EFI_OUT_OF_RESOURCES;
+  }
+
+  ZeroMem (Trb->DmaDesc, TableSize);
+  Bytes  =3D TableSize;
+
+  = Status =3D DmaMap (MapOperationBusMasterCommonBuffer,
+  = ;           (EFI_PHY= SICAL_ADDRESS *)Trb->DmaDesc,
+     &n= bsp;       &Bytes, &Trb->DmaD= escPhy, &Trb->DmaMap);
+/*  Status =3D DevIo->= Map (
+          = ;          DevIo,
+            =         EfiBusMasterCommonBuffer,+           =          (EFI_PHYSICAL_ADDRESS= *)Trb->DmaDesc,
+       &nb= sp;            = &Bytes,
+         = ;           &Trb= ->DmaDescPhy,
+        =             &am= p;Trb->DmaMap
+        =             );*= /
+
+  if (EFI_ERROR (Status) || (Bytes != =3D TableSize)) {
+    //
+ &nb= sp;  // Map error or unable to map the whole RFis buffer into a c= ontiguous
+    // region.
+ &nbs= p;  //
+/*    DevIo->FreeBuffer (=
+          &nbs= p;  DevIo,
+       &n= bsp;     EFI_SIZE_TO_PAGES (TableSize),
+            =  (EFI_PHYSICAL_ADDRESS)Trb->DmaDesc
+   &nb= sp;         );*/
+    return EFI_OUT_OF_RESOURCES;
+  }+
+  if ((UINT64)(UINTN)Trb->DmaDescPhy = > 0x100000000ul) {
+    //
+ =    // The DMA doesn't support 64bit addressing.
+    //
+    DmaUnmap (Trb-&g= t;DmaMap);
+/*    DevIo->Unmap (
+      DevIo,
+   &= nbsp;  Trb->DmaMap
+    );*/
+    return EFI_DEVICE_ERROR;
+ &nbs= p;}
+
+  if (DataLen < DW_MMC_BLOCK_SIZ= E) {
+    BlkSize =3D DataLen;
+=    BytCnt =3D DataLen;
+    Re= maining =3D DataLen;
+  } else {
+  &= nbsp; BlkSize =3D DW_MMC_BLOCK_SIZE;
+    = ;BytCnt =3D DW_MMC_BLOCK_SIZE * Blocks;
+    R= emaining =3D DW_MMC_BLOCK_SIZE * Blocks;
+  }
+
+  MmioWrite32 (DevBase + DW_MMC_BLKSIZ, BlkSiz= e);
+  MmioWrite32 (DevBase + DW_MMC_BYTCNT, BytCnt);+  DmaDesc =3D Trb->DmaDesc;
+  for = (Index =3D 0; Index < Entries; Index++, DmaDesc++) {
+ &nb= sp;  DmaDesc->Des0 =3D DW_MMC_IDMAC_DES0_OWN |
<= /blockquote>DW_MMC_IDMAC_DES0_CH |
+           &n= bsp;        DW_MMC_IDMAC_DES0_DIC;<= br class=3D"">+    DmaDesc->Des1 =3D DW_MMC_IDMAC_DES1_BS= 1
(DWMMC_DMA_BUF_SIZE);
+    //
+  &nb= sp; // Buffer Address
+    //
+    DmaDesc->Des2 =3D (UINT32)((UINTN)Trb->DataPhy= +
+          &n= bsp;         (DWMMC_DMA_BUF_SI= ZE * Index));
+    //
+  &n= bsp; // Next Descriptor Address
+    //+    DmaDesc->Des3 =3D (UINT32)((UINTN)Trb-&= gt;DmaDescPhy +
+        &= nbsp;           size= of (DW_MMC_HC_DMA_DESC_LINE) * (Index + 1));
+   &n= bsp;Remaining =3D Remaining - DWMMC_DMA_BUF_SIZE;
+  }+  //
+  // First Descriptor
+  //
+  Trb->DmaDesc[0].Des0 |=3D DW_MMC= _IDMAC_DES0_FS;
+  //
+  // Last Desc= riptor
+  //
+  Trb->DmaDesc[Entri= es - 1].Des0 &=3D ~(DW_MMC_IDMAC_DES0_CH |
+   =             &nb= sp;            =         DW_MMC_IDMAC_DES0_DIC);
+  Trb->DmaDesc[Entries - 1].Des0 |=3D DW_MMC_IDMAC_DES0= _OWN |
+         &nbs= p;            &= nbsp;           &nbs= p; DW_MMC_IDMAC_DES0_LD;
+  Trb->DmaDesc[Entries= - 1].Des1 =3D DW_MMC_IDMAC_DES1_BS1
(Remaining = +
+    &n= bsp;            = ;            &n= bsp;     DWMMC_DMA_BUF_SIZE);
+ &nbs= p;//
+  // Set the next field of the Last Descriptor
+  //
+  Trb->DmaDesc[Entries - 1].De= s3 =3D 0;
+  DmaDescPhy =3D (UINT32)Trb->DmaDescPhy;<= br class=3D"">+
+  MmioWrite32 (DevBase + DW_MMC_DBADDR,= DmaDescPhy);
+
+  ArmDataSynchronizationB= arrier ();
+  ArmInstructionSynchronizationBarrier ();+  //
+  // Clear interrupts
+  //
+  Idsts =3D ~0;
+  = ;MmioWrite32 (DevBase + DW_MMC_IDSTS, Idsts);
+
+  return Status;
+}
+
+EFI= _STATUS
+TransferFifo (
+  IN DW_MMC_HC_TR= B          *Trb
= +  )
+{
+  UINTN    &n= bsp;            = ;    DevBase;
+  UINT32   =             &nb= sp;    Data;
+  UINT32   &= nbsp;           &nbs= p;    Received;
+  UINT32  &nbs= p;            &= nbsp;    Count;
+  UINT32  &nbs= p;            &= nbsp;    Intsts;
+  UINT32  &nb= sp;            =      Sts;
+  UINT32   = ;            &n= bsp;    FifoCount;
+  UINT32  &= nbsp;           &nbs= p;     Index;     /* count wit= h bytes */
+  UINT32       = ;            &n= bsp;Ascending;
+  UINT32      &= nbsp;           &nbs= p; Descending;
+
+  DevBase  &nb= sp;=3D Trb->Private->DevBase;
+  Received =3D 0;+  Count =3D 0;
+  Index =3D 0;
+  Ascending =3D 0;
+  Descending =3D ((Trb= ->DataLen + 3) & ~3) - 4;
+  do {
+=    Intsts =3D MmioRead32 (DevBase + DW_MMC_RINTSTS);
+
+    if (Trb->DataLen && = (Intsts & DW_MMC_INT_TXDR) && !Trb->Read) {
+ =      Sts =3D MmioRead32 (DevBase + DW_MMC_STATUS);=
+
+      while (!(DW_= MMC_STS_FIFO_FULL(Sts))
+       = ;       && (Received < Trb-&g= t;DataLen)
+         =      && (Intsts & DW_MMC_INT_TXDR)) {<= br class=3D"">+        if (Trb->UseBE= ) {
+          D= ata =3D SwapBytes32 (*(UINT32 *)((UINTN)Trb->Data + Descending));
+          Descending = = =3D Descending - 4;
+       &n= bsp;} else {
+        &nbs= p; Data =3D *(UINT32 *)((UINTN)Trb->Data + Ascending);
+          Ascending +=3D 4;=
+        }
= +        Index +=3D 4;
+ &= nbsp;      Received +=3D 4;
++        MmioWrite32 (DevBa= se + DW_MMC_FIFO_START, Data);
+
+   =      Intsts =3D DW_MMC_INT_TXDR;
+ &= nbsp;      MmioWrite32 (DevBase + DW_MMC_RINT= STS, Intsts);
+
+      = ;  Intsts =3D MmioRead32 (DevBase + DW_MMC_RINTSTS);
+        Sts =3D MmioRead32 (DevBase += DW_MMC_STATUS);
+        = }
+      continue;
+ &= nbsp;  }
+
+    if (Tr= b->DataLen && ((Intsts & DW_MMC_INT_RXDR) ||
+=       (Intsts & DW_MMC_INT_DTO)) &&a= mp; Trb->Read) {
+      Sts =3D M= mioRead32 (DevBase + DW_MMC_STATUS);
+    &nbs= p; //
+      // Convert to byte= s
+      //
+  &n= bsp;   FifoCount =3D GET_STS_FIFO_COUNT (Sts) << 2;+      if ((FifoCount =3D=3D 0) &&= amp; (Received < Trb->DataLen)) {
+    &= nbsp;   continue;
+     &n= bsp;}
+      Index =3D 0;
+      Count =3D (MIN (FifoCount, Trb->D= ataLen) + 3) & ~3;
+      while = (Index < Count) {
+       &n= bsp;Data =3D MmioRead32 (DevBase + DW_MMC_FIFO_START);
+
+        if (Trb->UseBE) {<= br class=3D"">+          *(UIN= T32 *)((UINTN)Trb->Data + Descending) =3D SwapBytes32 (Data);
+          Descending = =3D Descending - 4;
+       &n= bsp;} else {
+        &nbs= p; *(UINT32 *)((UINTN)Trb->Data + Ascending) =3D Data;
+          Ascending +=3D 4;=
+        }
= +        Index +=3D 4;
+ &= nbsp;      Received +=3D 4;
+ &= nbsp;    } /* while */
+   &nbs= p;} /* if */
+  } while (((Intsts & DW_MMC_INT_CMD_D= ONE) =3D=3D 0) || (Received < Trb-
DataLen));
+  //
+  // Clear RINTSTS
+  /= /
+  Intsts =3D ~0;
+  MmioWrite32 (D= evBase + DW_MMC_RINTSTS, Intsts);
+  return EFI_SUCCESS;=
+}
+
+/**
+  = Create a new TRB for the SD/MMC cmd request.
+
= +  @param[in] Private        A poin= ter to the DW_MMC_HC_PRIVATE_DATA
instance.
+  @param[in] Slot &nbs= p;         The slot number of = the SD card to send the
command
+       &n= bsp;            = ;        to.
+  = @param[in] Packet         A pointer= to the SD command data structure.
+  @param[in] Event &= nbsp;        If Event is NULL, bloc= king I/O is performed. If
+      &nb= sp;            =          Event is not NULL, th= en nonblocking I/O is
+       &= nbsp;           &nbs= p;        performed, and Event will= be signaled when the
+       &= nbsp;           &nbs= p;        Packet completes.
+
+  @return Created Trb or NULL.
+=
+**/
+DW_MMC_HC_TRB *
+DwMmcCrea= teTrb (
+  IN DW_MMC_HC_PRIVATE_DATA    &= nbsp;         *Private,
+  IN UINT8         &n= bsp;            = ;         Slot,
= +  IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet,
+ &nb= sp;IN EFI_EVENT           = ;            &n= bsp;   Event
+  )
+{
+  DW_MMC_HC_TRB        &nb= sp;        *Trb;
+ &n= bsp;EFI_STATUS           =          Status;
+  EFI_TPL          &nbs= p;            O= ldTpl;
+  EFI_IO_OPERATION_TYPE     =     Flag;
+  UINTN    = ;            &n= bsp;        MapLength;
+
+  Trb =3D AllocateZeroPool (sizeof (DW_MMC_HC_TRB))= ;
+  if (Trb =3D=3D NULL) {
+   =  return NULL;
+  }
+
+ =  Trb->Signature =3D DW_MMC_HC_TRB_SIG;
+  Trb-&g= t;Slot      =3D Slot;
+  Trb-&g= t;BlockSize =3D 0x200;
+  Trb->Packet   &nb= sp;=3D Packet;
+  Trb->Event     = = =3D Event;
+  Trb->Started   =3D FALSE;+  Trb->Timeout   =3D Packet->Timeout;
+  Trb->Private   =3D Private;
+=
+  if ((Packet->InTransferLength !=3D 0) && = (Packet->InDataBuffer !=3D NULL)) {
+    Tr= b->Data    =3D Packet->InDataBuffer;
+ &= nbsp;  Trb->DataLen =3D Packet->InTransferLength;
+    Trb->Read    =3D TRUE;
+    ZeroMem (Trb->Data, Trb->DataLen);
+  } else if (Packet->OutTransferLength && (Packet-&= gt;OutDataBuffer !=3D
NULL)) {
+    Trb->Data  &n= bsp; =3D Packet->OutDataBuffer;
+    T= rb->DataLen =3D Packet->OutTransferLength;
+  &nbs= p; Trb->Read    =3D FALSE;
+  } e= lse if (!Packet->InTransferLength && !Packet->OutTransferLeng= th) {
+    Trb->Data    =3D = NULL;
+    Trb->DataLen =3D 0;
+  } else {
+    goto Error;
+  }
+
+  if (((Private->Sl= ot[Trb->Slot].CardType =3D=3D EmmcCardType) &&
+ &= nbsp;     (Packet->SdMmcCmdBlk->CommandIndex= =3D=3D
EMMC_SEND_TUNING_BLOCK)) ||
+      ((Pr= ivate->Slot[Trb->Slot].CardType =3D=3D SdCardType) &&
+       (Packet->SdMmcCmdBlk->Co= mmandIndex =3D=3D
SD_SEND_TUNING_BLOCK))) {
+    Trb->= Mode =3D SdMmcPioMode;
+  } else {
+  = ;  if (Trb->Read) {
+     &n= bsp;Flag =3D EfiBusMasterWrite;
+    } else {<= br class=3D"">+      Flag =3D EfiBusMasterRead;+    }
+
+  &nb= sp; if (Private->Slot[Trb->Slot].CardType =3D=3D SdCardType) {+      Trb->UseFifo =3D TRUE;
+    } else {
+    &n= bsp; Trb->UseFifo =3D FALSE;
+    &nbs= p; if (Trb->DataLen) {
+     &nbs= p;  MapLength =3D Trb->DataLen;
+   &n= bsp;    Status =3D DmaMap (Flag, Trb->Data, &Map= Length, &Trb->DataPhy,
&Trb->DataM= ap);
+/*   &nb= sp;    Status =3D DevIo->Map (
+  = ;            &n= bsp;           DevIo= ,
+          &nb= sp;            =    Flag,
+       = ;            &n= bsp;      Trb->Data,
+  = ;            &n= bsp;           &= MapLength,
+         =             &nb= sp;    &Trb->DataPhy,
+  &nbs= p;            &= nbsp;          &Trb-&= gt;DataMap
+         =             &nb= sp;    );*/
+     &nb= sp;  if (EFI_ERROR (Status) || (Trb->DataLen !=3D MapLength)) = {
+          Sta= tus =3D EFI_BAD_BUFFER_SIZE;
+      =     goto Error;
+     = ;   }
+
+    &nbs= p;   Status =3D BuildDmaDescTable (Trb);
+ &nb= sp;      if (EFI_ERROR (Status)) {
+          DmaUnmap(Trb= ->DataMap);
+        &n= bsp; goto Error;
+       &= nbsp;}
+        Status =3D= DwMmcHcStartDma (Private, Trb);
+     &n= bsp;  if (EFI_ERROR (Status)) {
+    = ;      DmaUnmap(Trb->DataMap);
+          goto Error;
+        }
+ &nb= sp;    }
+    }
+  } /* TuningBlock */
+
+  if= (Event !=3D NULL) {
+    OldTpl =3D gBS->R= aiseTPL (TPL_NOTIFY);
+    InsertTailList (&am= p;Private->Queue, &Trb->TrbList);
+   &nb= sp;gBS->RestoreTPL (OldTpl);
+  }
+
+  return Trb;
+
+Error:
+  return NULL;
+}
+
+/**
+  Free the resource used by the TRB.
+
+  @param[in] Trb      &nbs= p;     The pointer to the DW_MMC_HC_TRB instance.<= br class=3D"">+
+**/
+VOID
+DwMmc= FreeTrb (
+  IN DW_MMC_HC_TRB     &n= bsp;     *Trb
+  )
+{
+  if (Trb->DmaMap !=3D NULL) {
+ =    DmaUnmap (Trb->DmaMap);
+  }
+  if (Trb->DataMap !=3D NULL) {
+  &nbs= p; DmaUnmap (Trb->DataMap);
+  }
+=  FreePool (Trb);
+}
+
+/**<= br class=3D"">+  Check if the env is ready for execute specified TRB.<= br class=3D"">+
+  @param[in] Private    =     A pointer to the DW_MMC_HC_PRIVATE_DATA
instance.
+  @param[in] Trb         &n= bsp;  The pointer to the DW_MMC_HC_TRB instance.
+<= br class=3D"">+  @retval EFI_SUCCESS      &nb= sp;The env is ready for TRB execution.
+  @retval EFI_NO= T_READY     The env is not ready for TRB execution.
+  @retval Others        = ;    Some erros happen.
+
+= **/
+EFI_STATUS
+DwMmcCheckTrbEnv (
+  IN DW_MMC_HC_PRIVATE_DATA       &n= bsp;   *Private,
+  IN DW_MMC_HC_TRB &nbs= p;            &= nbsp;     *Trb
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Wait for the env to be re= ady for execute specified TRB.
+
+  @param= [in] Private        A pointer to the DW_= MMC_HC_PRIVATE_DATA
instance.
+  @param[in] Trb    &= nbsp;       The pointer to the DW_MMC_HC= _TRB instance.
+
+  @retval EFI_SUCCESS &n= bsp;     The env is ready for TRB execution.
+  @retval EFI_TIMEOUT       Th= e env is not ready for TRB execution in time.
+  @retval= Others            S= ome erros happen.
+
+**/
+EFI_STA= TUS
+DwMmcWaitTrbEnv (
+  IN DW_MMC_HC_PRI= VATE_DATA           *Priv= ate,
+  IN DW_MMC_HC_TRB      &= nbsp;           &nbs= p; *Trb
+  )
+{
+  = ;EFI_STATUS           &nb= sp;            =   Status;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACK= ET *Packet;
+  UINT64      &nbs= p;            &= nbsp;          Timeout;+  BOOLEAN        &nbs= p;            &= nbsp;       InfiniteWait;
= +
+  //
+  // Wait Command Complete I= nterrupt Status bit in Normal Interrupt
Status
+  // Register
+  //
+  Packet  =3D Trb->Packet;<= br class=3D"">+  Timeout =3D Packet->Timeout;
+  = ;if (Timeout =3D=3D 0) {
+    InfiniteWait =3D= TRUE;
+  } else {
+    Inf= initeWait =3D FALSE;
+  }
+
= +  while (InfiniteWait || (Timeout > 0)) {
+  &n= bsp; //
+    // Check Trb execution resul= t by reading Normal Interrupt Status
register.
+    //+    Status =3D DwMmcCheckTrbEnv (Private, Trb);=
+    if (Status !=3D EFI_NOT_READY) {
+      return Status;
+  = ;  }
+    //
+  &= nbsp; // Stall for 1 microsecond.
+    //=
+    gBS->Stall (1);
+
+    Timeout--;
+  }
+
+  return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+DwEmmcExecTrb (
+  IN DW_MMC_HC_PRIVATE_DATA       &nbs= p;   *Private,
+  IN DW_MMC_HC_TRB  =             &nb= sp;     *Trb
+  )
+{
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
+  UINTN         &nb= sp;            =          DevBase;
+  UINT32          &nbs= p;            &= nbsp;      Cmd;
+  UINT32 =             &nb= sp;            =     MmcStatus;
+  UINT32   = ;            &n= bsp;            = ;  IntStatus;
+  UINT32    &nbs= p;            &= nbsp;           &nbs= p;Argument;
+  UINT32      &nbs= p;            &= nbsp;          ErrMask;+  UINT32         = ;            &n= bsp;        Timeout;
= +
+  Packet =3D Trb->Packet;
+  De= vBase =3D Trb->Private->DevBase;
+
+ &nbs= p;ArmDataSynchronizationBarrier ();
+  ArmInstructionSyn= chronizationBarrier ();
+  //
+  // W= ait until MMC is idle
+  //
+  do {+    MmcStatus =3D MmioRead32 (DevBase + DW_MMC= _STATUS);
+  } while (MmcStatus & DW_MMC_STS_DATA_BU= SY);
+
+  IntStatus =3D ~0;
= +  MmioWrite32 (DevBase + DW_MMC_RINTSTS, IntStatus);
+ =  Cmd =3D CMD_INDEX (Packet->SdMmcCmdBlk->CommandIndex);
+  if ((Packet->SdMmcCmdBlk->CommandType =3D=3D
SdMmcCommandTypeAc) ||
+      (Packet->SdMmcCmdB= lk->CommandType =3D=3D
SdMmcCommandTypeAdtc))= {
+    s= witch (Packet->SdMmcCmdBlk->CommandIndex) {
+  &nb= sp; case EMMC_SET_RELATIVE_ADDR:
+    &nb= sp; Cmd |=3D BIT_CMD_SEND_INIT;
+    &nbs= p; break;
+    case EMMC_SEND_STATUS:
+      Cmd |=3D BIT_CMD_WAIT_PRVDATA_CO= MPLETE;
+      break;
= +    case EMMC_STOP_TRANSMISSION:
+  &nbs= p;   Cmd |=3D BIT_CMD_STOP_ABORT_CMD;
+  =     break;
+    }
+    if (Packet->InTransferLength) {
+      Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE |
BIT_CMD_DATA_EXPECTED |
+         = ;    BIT_CMD_READ;
+    } = else if (Packet->OutTransferLength) {
+    =   Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE |
BIT_CMD_DATA_EXPECTED |
+            =  BIT_CMD_WRITE;
+    }
+ &n= bsp;  Cmd |=3D BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_CHECK_RESPONSE_CRC;
+  } else {
+    switch (Packet-&g= t;SdMmcCmdBlk->CommandIndex) {
+    case EM= MC_GO_IDLE_STATE:
+      Cmd |=3D BI= T_CMD_SEND_INIT;
+      break;
+    case EMMC_SEND_OP_COND:
+  =     Cmd |=3D BIT_CMD_RESPONSE_EXPECT;
+ &= nbsp;    break;
+    case = EMMC_ALL_SEND_CID:
+      Cmd |=3D B= IT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
+  &nbs= p;          BIT_CMD_CHECK= _RESPONSE_CRC | BIT_CMD_SEND_INIT;
+     =  break;
+    }
+  }+  switch (Packet->SdMmcCmdBlk->ResponseType) {
+  case SdMmcResponseTypeR2:
+   &nb= sp;Cmd |=3D BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_CH= ECK_RESPONSE_CRC |
+ &nb= sp;         BIT_CMD_LONG_RESPO= NSE;
+    break;
+  case Sd= MmcResponseTypeR3:
+    Cmd |=3D BIT_CMD_RESPO= NSE_EXPECT;
+    break;
+  = }
+  Cmd |=3D BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
+
+  Argument =3D Packet->SdMmcCmdBlk->C= ommandArgument;
+  MmioWrite32 (DevBase + DW_MMC_CMDARG,= Argument);
+
+  ArmDataSynchronizationBar= rier ();
+  ArmInstructionSynchronizationBarrier ();
+
+  MmioWrite32 (DevBase + DW_MMC_CMD, Cmd);=
+  ArmDataSynchronizationBarrier ();
+ &n= bsp;ArmInstructionSynchronizationBarrier ();
+
= +  ErrMask =3D DW_MMC_INT_EBE | DW_MMC_INT_HLE |
DW_MMC_INT_RTO |
+=            DW_MMC_I= NT_RCRC | DW_MMC_INT_RE;
+  ErrMask |=3D DW_MMC_INT_DCRC= | DW_MMC_INT_DRT |
DW_MMC_INT_SBE;
+  do {
+  &= nbsp; Timeout =3D 10000;
+    if (--Timeo= ut =3D=3D 0) {
+      break;
+    }
+    IntStatus = =3D MmioRead32 (DevBase + DW_MMC_RINTSTS);
+   &nb= sp;if (IntStatus & ErrMask) {
+     &= nbsp;return EFI_DEVICE_ERROR;
+    }
+    if (Trb->DataLen && ((IntStatus &= DW_MMC_INT_DTO) =3D=3D 0)) {
+      = ;//
+      // Transfer Not Done
+      //
+   &n= bsp;  MicroSecondDelay (10);
+    &n= bsp; continue;
+    }
+ &nb= sp;  MicroSecondDelay (10);
+  } while (!(IntS= tatus & DW_MMC_INT_CMD_DONE));
+  switch (Packet->= ;SdMmcCmdBlk->ResponseType) {
+    case SdM= mcResponseTypeR1:
+    case SdMmcResponseTypeR= 1b:
+    case SdMmcResponseTypeR3:
+    case SdMmcResponseTypeR4:
+  &nbs= p; case SdMmcResponseTypeR5:
+     &= nbsp;Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase +
DW_MMC_RESP0);
+      break;
+  &nb= sp; case SdMmcResponseTypeR2:
+     =  Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase +
DW_MMC_RESP0);
+      Packet->SdMmcStatusBlk->Re= sp1 =3D MmioRead32 (DevBase +
DW_MMC_RESP1);
+     &= nbsp;Packet->SdMmcStatusBlk->Resp2 =3D MmioRead32 (DevBase +
DW_MMC_RESP2);
+      Packet->SdMmcStatusBlk->Re= sp3 =3D MmioRead32 (DevBase +
DW_MMC_RESP3);
+     &= nbsp;break;
+  }
+
+  /= /
+  // The workaround on EMMC_SEND_CSD is used to be co= mpatible with
SDHC.
+  //
+  if (Packet->SdMm= cCmdBlk->CommandIndex =3D=3D EMMC_SEND_CSD) {
+  &nbs= p; {
+      UINT32   = Buf[4];
+      ZeroMem (Buf, sizeof = (Buf));
+      CopyMem (
+        (UINT8 *)Buf,
= +        (UINT8 *)&Packet->SdMmcS= tatusBlk->Resp0 + 1,
+       = ; sizeof (Buf) - 1
+       = ; );
+      CopyMem (
+        (UINT8 *)&Packet->= ;SdMmcStatusBlk->Resp0,
+      &n= bsp; (UINT8 *)Buf,
+       = ; sizeof (Buf) - 1
+       = ; );
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DwSdExecTrb (
+  IN DW_MMC_HC_PRIVATE_DATA      &nbs= p;    *Private,
+  IN DW_MMC_HC_TRB =             &nb= sp;      *Trb
+  )
+{
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet= ;
+  UINTN        &nb= sp;            =           DevBase;
+  UINT32         &nbs= p;            &= nbsp;       Cmd;
+  U= INT32            &nb= sp;            =      MmcStatus;
+  UINT32  = ;            &n= bsp;            = ;   IntStatus;
+  UINT32   &nbs= p;            &= nbsp;           &nbs= p; Argument;
+  UINT32     &nbs= p;            &= nbsp;           ErrM= ask;
+  UINT32        = ;            &n= bsp;         Timeout;
+  UINT32          = ;            &n= bsp;       Idsts;
+  = UINT32            &n= bsp;            = ;     BytCnt;
+  UINT32  &= nbsp;           &nbs= p;            &= nbsp;  BlkSize;
+  EFI_STATUS   &nbs= p;            &= nbsp;         Status;
+
+  Packet =3D Trb->Packet;
+ &= nbsp;DevBase  =3D Trb->Private->DevBase;
+
+  ArmDataSynchronizationBarrier ();
+  ArmI= nstructionSynchronizationBarrier ();
+  //
+  // Wait until MMC is idle
+  //
+=  do {
+    MmcStatus =3D MmioRead32 (Dev= Base + DW_MMC_STATUS);
+  } while (MmcStatus & DW_MM= C_STS_DATA_BUSY);
+
+  IntStatus =3D ~0;+  MmioWrite32 (DevBase + DW_MMC_RINTSTS, IntStatus);
+  Cmd =3D CMD_INDEX (Packet->SdMmcCmdBlk->CommandInd= ex);
+  if ((Packet->SdMmcCmdBlk->CommandType =3D= =3D
SdMmcCommandTypeAc) ||
+      (Packet->= SdMmcCmdBlk->CommandType =3D=3D
SdMmcCommandT= ypeAdtc)) {
+  &nbs= p; switch (Packet->SdMmcCmdBlk->CommandIndex) {
+ =    case SD_SET_RELATIVE_ADDR:
+   &n= bsp;  Cmd |=3D BIT_CMD_SEND_INIT;
+   &nb= sp;  break;
+    case SD_STOP_TRANSM= ISSION:
+      Cmd |=3D BIT_CMD_STOP= _ABORT_CMD;
+      break;
+    case SD_SEND_SCR:
+   &n= bsp;  Trb->UseBE =3D TRUE;
+    &= nbsp; break;
+    }
+  = ;  if (Packet->InTransferLength) {
+   = ;   Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE |
<= /blockquote>BIT_CMD_DATA_EXPECTED |
+           &= nbsp; BIT_CMD_READ;
+    } else if (Packe= t->OutTransferLength) {
+      Cm= d |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE |
BIT_CMD_D= ATA_EXPECTED |
+  &= nbsp;          BIT_CMD_WR= ITE;
+    }
+    = Cmd |=3D BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_CHECK= _RESPONSE_CRC |
+  =          BIT_CMD_SEND_AUTO_STO= P;
+  } else {
+    switch = (Packet->SdMmcCmdBlk->CommandIndex) {
+   &nb= sp;case SD_GO_IDLE_STATE:
+      Cmd= |=3D BIT_CMD_SEND_INIT;
+      brea= k;
+    }
+  }
+  switch (Packet->SdMmcCmdBlk->ResponseType) {
= +  case SdMmcResponseTypeR2:
+    Cmd |= =3D BIT_CMD_RESPONSE_EXPECT |
BIT_CMD_CHECK_RES= PONSE_CRC |
+  &nbs= p;        BIT_CMD_LONG_RESPONSE;+    break;
+  case SdMmcResp= onseTypeR3:
+    Cmd |=3D BIT_CMD_RESPONSE_EXP= ECT;
+    break;
+  case Sd= MmcResponseTypeR1b:
+  case SdMmcResponseTypeR4:
+  case SdMmcResponseTypeR6:
+  case SdMmcRe= sponseTypeR7:
+    Cmd |=3D BIT_CMD_RESPONSE_E= XPECT |
BIT_CMD_CHECK_RESPONSE_CRC;
+    break;
+  }
+  Cmd |=3D BIT_CMD_USE_HOLD_REG | BIT_= CMD_START;
+
+  if (Trb->UseFifo =3D=3D= TRUE) {
+    BytCnt =3D Trb->Read ? Packet= ->InTransferLength : Packet-
OutTransferLength;
+    MmioWrite32 (DevBase + DW_MMC_BYTCNT, BytCnt);+    if (Trb->Read) {
+  =     if (Packet->InTransferLength > DW_MMC_BLOCK_S= IZE) {
+        BlkSize = =3D DW_MMC_BLOCK_SIZE;
+      } els= e {
+        BlkSize =3D P= acket->InTransferLength;
+      }=
+    }
+    else= {
+      if (Packet->OutTransfer= Length > DW_MMC_BLOCK_SIZE) {
+     &n= bsp;  BlkSize =3D DW_MMC_BLOCK_SIZE;
+   =    } else {
+      &n= bsp; BlkSize =3D Packet->OutTransferLength;
+  &= nbsp;   }
+    }
= +
+    MmioWrite32 (DevBase + DW_MMC_BLKSIZ, B= lkSize);
+  }
+
+  Argu= ment =3D Packet->SdMmcCmdBlk->CommandArgument;
+  = MmioWrite32 (DevBase + DW_MMC_CMDARG, Argument);
+  ArmD= ataSynchronizationBarrier ();
+  ArmInstructionSynchroni= zationBarrier ();
+  MmioWrite32 (DevBase + DW_MMC_CMD, = Cmd);
+  ArmDataSynchronizationBarrier ();
+  ArmInstructionSynchronizationBarrier ();
+
+  ErrMask =3D DW_MMC_INT_EBE | DW_MMC_INT_HLE |
=
DW_MMC_INT_RTO |
+            = DW_MMC_INT_RCRC | DW_MMC_INT_RE;
+  ErrMask |=3D DW_MMC_= INT_DRT | DW_MMC_INT_SBE;
+  if (Packet->InTransferLe= ngth || Packet->OutTransferLength) {
+    E= rrMask |=3D DW_MMC_INT_DCRC;
+  }
+  = if (Trb->UseFifo =3D=3D TRUE) {
+    Status= =3D TransferFifo (Trb);
+    if (EFI_ERROR (S= tatus)) {
+      return Status;
+    }
+  } else {
+    Timeout =3D 10000;
+    = do {
+      if (--Timeout =3D=3D 0) = {
+        break;
+      }
+    =   IntStatus =3D MmioRead32 (DevBase + DW_MMC_RINTSTS);
+      if (IntStatus & ErrMask) {
+        return EFI_DEVICE_ERRO= R;
+      }
+  &n= bsp;   if (Trb->DataLen && ((IntStatus & DW_M= MC_INT_DTO) =3D=3D 0)) {
+      &nbs= p; //
+        // Tra= nsfer not Done
+        //=
+        MicroSecondDelay= (10);
+        continue;<= br class=3D"">+      }
+   = ;   MicroSecondDelay (10);
+    = ;} while (!(IntStatus & DW_MMC_INT_CMD_DONE));
+  &n= bsp; if (Packet->InTransferLength) {
+   &n= bsp;  do {
+       &n= bsp;Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS);
+  &n= bsp;   } while ((Idsts & DW_MMC_IDSTS_RI) =3D=3D 0);
+      Status =3D DwMmcHcStopDma (Priva= te, Trb);
+      if (EFI_ERROR (Stat= us)) {
+        return Sta= tus;
+      }
+  =   } else if (Packet->OutTransferLength) {
+ &nbs= p;    do {
+     &nbs= p;  Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS);
= +      } while ((Idsts & DW_MMC_IDSTS_TI) =3D= =3D 0);
+      Status =3D DwMmcHcSt= opDma (Private, Trb);
+      if (EFI= _ERROR (Status)) {
+       &nbs= p;return Status;
+      }
+    } /* Packet->InTransferLength */
+  } /* UseFifo */
+  switch (Packet->SdMmcCmd= Blk->ResponseType) {
+    case SdMmcRespons= eTypeR1:
+    case SdMmcResponseTypeR1b:
+    case SdMmcResponseTypeR3:
+ &nbs= p;  case SdMmcResponseTypeR4:
+    c= ase SdMmcResponseTypeR5:
+    case SdMmcRespon= seTypeR6:
+    case SdMmcResponseTypeR7:
+      Packet->SdMmcStatusBlk->Resp= 0 =3D MmioRead32 (DevBase +
DW_MMC_RESP0);
+     &nb= sp;break;
+    case SdMmcResponseTypeR2:
+      Packet->SdMmcStatusBlk->Resp= 0 =3D MmioRead32 (DevBase +
DW_MMC_RESP0);
+     &nb= sp;Packet->SdMmcStatusBlk->Resp1 =3D MmioRead32 (DevBase +
DW_MMC_RESP1);
+      Packet->SdMmcStatusBlk->Re= sp2 =3D MmioRead32 (DevBase +
DW_MMC_RESP2);
+     &= nbsp;Packet->SdMmcStatusBlk->Resp3 =3D MmioRead32 (DevBase +
DW_MMC_RESP3);
+      break;
+  }+
+  //
+  // The workar= ound on SD_SEND_CSD is used to be compatible with
SDHC.
+  //
+  if (Packet->SdMmcCmdBlk->CommandIndex =3D=3D SD_SEND= _CSD) {
+    {
+   &nb= sp;  UINT32   Buf[4];
+    = ;  ZeroMem (Buf, sizeof (Buf));
+    = ;  CopyMem (
+       =  (UINT8 *)Buf,
+       &nb= sp;(UINT8 *)&Packet->SdMmcStatusBlk->Resp0 + 1,
+ &= nbsp;      sizeof (Buf) - 1
+ &= nbsp;      );
+   &nb= sp;  CopyMem (
+      &nbs= p; (UINT8 *)&Packet->SdMmcStatusBlk->Resp0,
+ =        (UINT8 *)Buf,
+ &nb= sp;      sizeof (Buf) - 1
+ &nb= sp;      );
+    = ;}
+  }
+
+  return EFI= _SUCCESS;
+}
+
+/**
+  Execute the specified TRB.
+
+  @= param[in] Private        A pointer to th= e DW_MMC_HC_PRIVATE_DATA
instance.
+  @param[in] Trb   &n= bsp;        The pointer to the DW_M= MC_HC_TRB instance.
+
+  @retval EFI_SUCCE= SS       The TRB is sent to host controller s= uccessfully.
+  @retval Others     &= nbsp;      Some erros happen when sending thi= s request to
the
+         &nb= sp;            =       host controller.
+
+**/
+EFI_STATUS
+DwMmcExecTrb (
+  IN DW_MMC_HC_PRIVATE_DATA      &nb= sp;    *Private,
+  IN DW_MMC_HC_TRB=             &n= bsp;      *Trb
+  )
+{
+  EFI_STATUS      &= nbsp;           &nbs= p;       Status =3D EFI_SUCCESS;
+  UINT32          = ;            &n= bsp;       Slot;
+
+  Slot =3D Trb->Slot;
+  if (Private->= ;Slot[Slot].CardType =3D=3D EmmcCardType) {
+   &nb= sp;Status =3D DwEmmcExecTrb (Private, Trb);
+  } else if= (Private->Slot[Slot].CardType =3D=3D SdCardType) {
+ &nbs= p;  Status =3D DwSdExecTrb (Private, Trb);
+  = } else {
+    ASSERT (0);
+ &nbs= p;}
+  return Status;
+}
++/**
+  Check the TRB execution result.
+
+  @param[in] Private    &nb= sp;   A pointer to the DW_MMC_HC_PRIVATE_DATA
=
instance.
+=  @param[in] Trb          = ;  The pointer to the DW_MMC_HC_TRB instance.
+
+  @retval EFI_SUCCESS       = The TRB is executed successfully.
+  @retval EFI_NOT_REA= DY     The TRB is not completed for execution.
+  @retval Others        &nb= sp;   Some erros happen when executing this request.
+
+**/
+EFI_STATUS
+DwMmcC= heckTrbResult (
+  IN DW_MMC_HC_PRIVATE_DATA   = ;        *Private,
+ =  IN DW_MMC_HC_TRB         &nbs= p;          *Trb
+  )
+{
+  EFI_SD_MMC_PASS_THR= U_COMMAND_PACKET *Packet;
+  UINT32    &n= bsp;            = ;            &n= bsp;Idsts;
+  UINTN       =             &nb= sp;           DevBas= e;
+
+  DevBase =3D Private->DevBase;+  Packet  =3D Trb->Packet;
+  = ;if (Trb->UseFifo =3D=3D TRUE) {
+    retur= n EFI_SUCCESS;
+  }
+  if (Packet->= ;InTransferLength) {
+    do {
+=      Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS= );
+    } while ((Idsts & BIT1) =3D=3D 0);=
+  } else if (Packet->OutTransferLength) {
+    do {
+     &nb= sp;Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS);
+  &nb= sp; } while ((Idsts & BIT0) =3D=3D 0);
+  } els= e {
+    return EFI_SUCCESS;
+ &= nbsp;}
+  Idsts =3D ~0;
+  MmioWrite3= 2 (DevBase + DW_MMC_IDSTS, Idsts);
+
+  re= turn EFI_SUCCESS;
+}
+
+/**
+  Wait for the TRB execution result.
+
+  @param[in] Private        = ;A pointer to the DW_MMC_HC_PRIVATE_DATA
instanc= e.
+  @param[in] Tr= b            The poi= nter to the DW_MMC_HC_TRB instance.
+
+  @= retval EFI_SUCCESS       The TRB is executed = successfully.
+  @retval Others     =        Some erros happen when executing = this request.
+
+**/
+EFI_STATUS<= br class=3D"">+DwMmcWaitTrbResult (
+  IN DW_MMC_HC_PRIV= ATE_DATA           *Priva= te,
+  IN DW_MMC_HC_TRB      &n= bsp;            = ; *Trb
+  )
+{
+  = EFI_STATUS           &nbs= p;            &= nbsp; Status;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKE= T *Packet;
+  UINT64       = ;            &n= bsp;          Timeout;+  BOOLEAN         = ;            &n= bsp;       InfiniteWait;
+=
+  Packet =3D Trb->Packet;
+  //<= br class=3D"">+  // Wait Command Complete Interrupt Status bit in Norm= al Interrupt
Status
+  // Register
+  //
+  Timeout =3D Packet->Timeout;
+  if (Ti= meout =3D=3D 0) {
+    InfiniteWait =3D TRUE;<= br class=3D"">+  } else {
+    InfiniteWa= it =3D FALSE;
+  }
+
+  = ;while (InfiniteWait || (Timeout > 0)) {
+   &nb= sp;//
+    // Check Trb execution result by re= ading Normal Interrupt Status
register.
+    //
+    Status =3D DwMmcCheckTrbResult (Private, Trb);+    if (Status !=3D EFI_NOT_READY) {
+      return Status;
+  = ;  }
+    //
+  &= nbsp; // Stall for 1 microsecond.
+    //=
+    gBS->Stall (1);
+
+    Timeout--;
+  }
+
+  return EFI_TIMEOUT;
+}
diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c
<= /blockquote>b/EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c
new file mode 100644
index = 000000000000..b7a8688c4d2e
--- /dev/null
+++ b/= EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c
@@ -0,0 +1,1042 @= @
+/** @file
+  This file provides some he= lper functions which are specific for EMMC
devic= e.
+
+ &nb= sp;Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR= >
+  Copyright (c) 2018, Linaro. All rights reserved.= <BR>
+
+  This program and the accom= panying materials are licensed and made
availabl= e
+  under the term= s and conditions of the BSD License which accompanies
this
+  distr= ibution.  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, EI= THER
EXPRESS OR IMPLIED.
+
+**/
+
+#include <IndustryStandard/Emmc.h>
+
+#include <Library/BaseMemoryLib.h>
+#include &l= t;Library/DebugLib.h>
+#include <Library/UefiBootServic= esTableLib.h>
+
+#include "DwMmcHcDxe.h"
+
+#define EMMC_GET_STATE(x)    &nb= sp;            =   (((x) >> 9) & 0xf)
+#define EMMC_STATE_= IDLE            &nbs= p;        0
+#define = EMMC_STATE_READY          &nbs= p;         1
+#d= efine EMMC_STATE_IDENT         &nbs= p;          2
+#define EMMC_STATE_STBY         = ;            3<= br class=3D"">+#define EMMC_STATE_TRAN       =             &nb= sp; 4
+#define EMMC_STATE_DATA     &= nbsp;           &nbs= p;   5
+#define EMMC_STATE_RCV   &nb= sp;            =       6
+#define EMMC_STATE_PRG=             &n= bsp;        7
+#defin= e EMMC_STATE_DIS          &nbs= p;           8
+#define EMMC_STATE_BTST        = ;            &n= bsp;9
+#define EMMC_STATE_SLP      &= nbsp;           &nbs= p;   10
+
+#define EMMC_CMD1_CAP= ACITY_LESS_THAN_2GB    0x00FF8080 //
Capacity <=3D 2GB, byte addressing used
+#define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8= 080 //
Capacity > 2GB, 512-byte sector addres= sing used
+
+/**
+  Send command GO_IDLE_STATE (CMD0 with argument= of 0x00000000) to
the device to
<= blockquote type=3D"cite" class=3D"">+  make it go to Idle State.
+
+  Refer to EMMC Electrical Standard Spec 5.1= Section 6.4 for details.
+
+  @param[in] = PassThru       A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+         &nb= sp;            =       instance.
+  @param[= in] Slot           The sl= ot number of the SD card to send the
command
+     &= nbsp;           &nbs= p;          to.
+
+  @retval EFI_SUCCESS     =   The EMMC device is reset correctly.
+  @retv= al Others            = ;The device reset fails.
+
+**/
+= EFI_STATUS
+EmmcReset (
+  IN EFI_SD_MMC_P= ASS_THRU_PROTOCOL      *PassThru
+ &= nbsp;)
+{
+  EFI_SD_MMC_COMMAND_BLOCK &nbs= p;            S= dMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK    = ;           SdMmcSta= tusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET  &nb= sp;Packet;
+  EFI_STATUS      &= nbsp;           &nbs= p;         Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk))= ;
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBl= k));
+  ZeroMem (&Packet, sizeof (Packet));
+
+  Packet.SdMmcCmdBlk    =3D &am= p;SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMmcSt= atusBlk;
+  Packet.Timeout      = ;  =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+=  SdMmcCmdBlk.CommandIndex =3D EMMC_GO_IDLE_STATE;
+ &nb= sp;SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeBc;
+ &n= bsp;SdMmcCmdBlk.ResponseType =3D 0;
+  SdMmcCmdBlk.Comma= ndArgument =3D 0;
+
+  gBS->Stall (1000= );
+
+  Status =3D PassThru->PassThru (= PassThru, 0, &Packet, NULL);
+
+  retu= rn Status;
+}
+
+/**
+  Send command SEND_OP_COND to the EMMC device to get the data of
the OCR
+  register.
+
+  Refer to = EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
+<= br class=3D"">+  @param[in]      PassThru &nb= sp;A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCO= L
+    &n= bsp;            = ;           instance= .
+  @param[in, out] Argument  On input, the argume= nt of SEND_OP_COND
is to send
+       &nbs= p;            &= nbsp;       to the device.
+             =             &nb= sp;  On output, the argument is the value of OCR
+ =             &nb= sp;            =   register.
+
+  @retval EFI_SUC= CESS       The operation is done correctly.+  @retval Others       &nb= sp;    The operation fails.
+
+**/
+EFI_STATUS
+EmmcGetOcr (
+  IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *Pa= ssThru,
+  IN OUT UINT32      &= nbsp;           &nbs= p;      *Argument
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK   &n= bsp;          SdMmcCmdBlk= ;
+  EFI_SD_MMC_STATUS_BLOCK     &nb= sp;         SdMmcStatusBlk;+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;=
+  EFI_STATUS        = ;            &n= bsp;       Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeof (Packet));
++  Packet.SdMmcCmdBlk    =3D &SdMmcCmd= Blk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;+  Packet.Timeout       &nb= sp;=3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdM= mcCmdBlk.CommandIndex =3D EMMC_SEND_OP_COND;
+  SdMmcCmd= Blk.CommandType  =3D SdMmcCommandTypeBcr;
+  SdMmcC= mdBlk.ResponseType =3D SdMmcResponseTypeR3;
+  SdMmcCmdB= lk.CommandArgument =3D *Argument;
+
+  Sta= tus =3D PassThru->PassThru (PassThru, 0, &Packet, NULL);
+  if (!EFI_ERROR (Status)) {
+    //<= br class=3D"">+    // For details, refer to SD Host Controll= er Simplified Spec 3.0 Table 2-12.
+    //
+    *Argument =3D SdMmcStatusBlk.Resp0;
+  }
+
+  return Status;
+}
+
+/**
+  Broadc= ast command ALL_SEND_CID to the bus to ask all the EMMC
devices to send
= +  the data of their CID registers.
+
+ &n= bsp;Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
+
+  @param[in] PassThru    &n= bsp;  A pointer to the
EFI_SD_MMC_PASS= _THRU_PROTOCOL
+  &= nbsp;           &nbs= p;            &= nbsp;instance.
+
+  @retval EFI_SUCCESS &n= bsp;     The operation is done correctly.
+  @retval Others        &nb= sp;   The operation fails.
+
+**= /
+EFI_STATUS
+EmmcGetAllCid (
+ =  IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassT= hru
+  )
+{
+  EFI_SD_M= MC_COMMAND_BLOCK          &nbs= p;   SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BL= OCK             = ;  SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COM= MAND_PACKET   Packet;
+  EFI_STATUS  &nbs= p;            &= nbsp;           &nbs= p;Status;
+
+  ZeroMem (&SdMmcCmdBlk, = sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatusBlk, = sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeo= f (Packet));
+
+  Packet.SdMmcCmdBlk  = ;  =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatus= Blk =3D &SdMmcStatusBlk;
+  Packet.Timeout  &nb= sp;     =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D EMMC_ALL_SEND_CID;<= br class=3D"">+  SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeBcr= ;
+  SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2;+  SdMmcCmdBlk.CommandArgument =3D 0;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Pack= et, NULL);
+
+  return Status;
+}
+
+/**
+  Send command= SET_RELATIVE_ADDR to the EMMC device to assign a
Relative device
+ &nbs= p;Address (RCA).
+
+  Refer to EMMC Electr= ical Standard Spec 5.1 Section 6.4 for details.
+
+  @param[in] PassThru       A pointe= r to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+      = ;            &n= bsp;         instance.
+  @param[in] Rca        &nb= sp;   The relative device address to be assigned.
+
+  @retval EFI_SUCCESS     =   The operation is done correctly.
+  @retval = Others            Th= e operation fails.
+
+**/
+EFI_ST= ATUS
+EmmcSetRca (
+  IN EFI_SD_MMC_PASS_T= HRU_PROTOCOL      *PassThru,
+  = ;IN UINT16           &nbs= p;            &= nbsp;    Rca
+  )
+{+  EFI_SD_MMC_COMMAND_BLOCK      = ;        SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK        =        SdMmcStatusBlk;
+ &= nbsp;EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
= +  EFI_STATUS          &n= bsp;            = ;     Status;
+
+ &nbs= p;ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  Z= eroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+ &nbs= p;ZeroMem (&Packet, sizeof (Packet));
+
+ &= nbsp;Packet.SdMmcCmdBlk    =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;
+ &= nbsp;Packet.Timeout        =3D DW_MMC_HC= _GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.Command= Index =3D EMMC_SET_RELATIVE_ADDR;
+  SdMmcCmdBlk.Command= Type  =3D SdMmcCommandTypeAc;
+  SdMmcCmdBlk.Respon= seType =3D SdMmcResponseTypeR1;
+  SdMmcCmdBlk.CommandAr= gument =3D (UINT32)Rca << 16;
+
+  S= tatus =3D PassThru->PassThru (PassThru, 0, &Packet, NULL);
+
+  return Status;
+}
+
+/**
+  Send command SEND_CSD to the E= MMC device to get the data of the
CSD register.<= br class=3D"">
+
+  = Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
+
+  @param[in]  PassThru   &nb= sp;  A pointer to the
EFI_SD_MMC_PASS_= THRU_PROTOCOL
+  &n= bsp;            = ;            &n= bsp;instance.
+  @param[in]  Rca    =        The relative device address of se= lected device.
+  @param[out] Csd    &nbs= p;      The buffer to store the content of th= e CSD
register.
+         &nb= sp;            =       Note the caller should ignore the lowes= t byte of
+         &= nbsp;           &nbs= p;      this buffer as the content of this by= te is
+          = ;            &n= bsp;     meaningless even if the operation succeed= s.
+
+  @retval EFI_SUCCESS   &n= bsp;   The operation is done correctly.
+ &nbs= p;@retval Others          &nbs= p; The operation fails.
+
+**/
+EFI_STATUS
+EmmcGetCsd (
+  IN  &= nbsp;  EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
+  IN     UINT16      =             &nb= sp;      Rca,
+   &nb= sp; OUT EMMC_CSD          = ;            &n= bsp;*Csd
+  )
+{
+  EFI= _SD_MMC_COMMAND_BLOCK          = ;    SdMmcCmdBlk;
+  EFI_SD_MMC_STAT= US_BLOCK            =    SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THR= U_COMMAND_PACKET   Packet;
+  EFI_STATUS  = ;            &n= bsp;            = ; Status;
+
+  ZeroMem (&SdMmcCmd= Blk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatus= Blk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, = sizeof (Packet));
+
+  Packet.SdMmcCmdBlk =    =3D &SdMmcCmdBlk;
+  Packet.SdMmcS= tatusBlk =3D &SdMmcStatusBlk;
+  Packet.Timeout &nbs= p;      =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_CSD;=
+  SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeAc= ;
+  SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2;+  SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 1= 6;
+
+  Status =3D PassThru->PassThru (= PassThru, 0, &Packet, NULL);
+  if (!EFI_ERROR (Stat= us)) {
+    //
+   &nb= sp;// Copy 128bit data for CSD structure.
+    = ;//
+    CopyMem ((VOID *)Csd + 1, &SdMmcS= tatusBlk.Resp0, sizeof
(EMMC_CSD) - 1);
+  }
+
+  return Status;
+}
+
+/**
+  Send command SELECT_DESELECT_CARD to the = EMMC device to
select/deselect it.
+
+  Refer to EMMC= Electrical Standard Spec 5.1 Section 6.10.4 for details.
++  @param[in]  PassThru     &nbs= p;A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL=
+    &nb= sp;            =            instance.=
+  @param[in]  Rca      &= nbsp;    The relative device address of selected device= .
+
+  @retval EFI_SUCCESS   &nb= sp;   The operation is done correctly.
+  = ;@retval Others           = ; The operation fails.
+
+**/
+EFI_STATUS
+EmmcSelect (
+  IN EFI_SD_M= MC_PASS_THRU_PROTOCOL      *PassThru,
+  IN UINT16          &= nbsp;           &nbs= p;      Rca
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK    =           SdMmcCmdBlk;+  EFI_SD_MMC_STATUS_BLOCK      &= nbsp;        SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_STATUS        &nb= sp;            =        Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeof (Packet));
++  Packet.SdMmcCmdBlk    =3D &SdMmcCmd= Blk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;+  Packet.Timeout       &nb= sp;=3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdM= mcCmdBlk.CommandIndex =3D EMMC_SELECT_DESELECT_CARD;
+  = SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeAc;
+  = ;SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1;
+  Sd= MmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Packe= t, NULL);
+
+  return Status;
+}
+
+/**
+  Send command = SEND_EXT_CSD to the EMMC device to get the data of
the EXT_CSD
+  r= egister.
+
+  Refer to EMMC Electrical Sta= ndard Spec 5.1 Section 6.10.4 for details.
+
+ =  @param[in]  PassThru      A pointer to = the
EFI_SD_MMC_PASS_THRU_PROTOCOL
=
+       =             &nb= sp;        instance.
= +  @param[out] ExtCsd        The bu= ffer to store the content of the EXT_CSD
+    =             &nb= sp;           regist= er.
+
+  @retval EFI_SUCCESS   &= nbsp;   The operation is done correctly.
+ &nb= sp;@retval Others          &nb= sp; The operation fails.
+
+**/
+EFI_STATUS
+EmmcGetExtCsd (
+  IN =     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
+     OUT EMMC_EXT_CSD    &nbs= p;            &= nbsp; *ExtCsd
+  )
+{
+=  EFI_SD_MMC_COMMAND_BLOCK        &= nbsp;     SdMmcCmdBlk;
+  EFI_S= D_MMC_STATUS_BLOCK          &n= bsp;    SdMmcStatusBlk;
+  EFI_SD_MM= C_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_ST= ATUS            &nbs= p;            &= nbsp;  Status;
+
+  ZeroMem (&am= p;SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&S= dMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&am= p;Packet, sizeof (Packet));
+
+  Packet.Sd= MmcCmdBlk    =3D &SdMmcCmdBlk;
+  Pac= ket.SdMmcStatusBlk =3D &SdMmcStatusBlk;
+  Packet.Ti= meout        =3D DW_MMC_HC_GENERIC_TIMEO= UT;
+
+  SdMmcCmdBlk.CommandIndex =3D EMMC= _SEND_EXT_CSD;
+  SdMmcCmdBlk.CommandType  =3D SdMm= cCommandTypeAdtc;
+  SdMmcCmdBlk.ResponseType =3D SdMmcR= esponseTypeR1;
+  SdMmcCmdBlk.CommandArgument =3D 0x0000= 0000;
+
+  Packet.InDataBuffer   = ;  =3D ExtCsd;
+  Packet.InTransferLength =3D = sizeof (EMMC_EXT_CSD);
+
+  Status =3D Pas= sThru->PassThru (PassThru, 0, &Packet, NULL);
+  = return Status;
+}
+
+/**
+  Send command SWITCH to the EMMC device to switch the mode of=
operation of the
+  selected Device or modifies the EXT_CSD regis= ters.
+
+  Refer to EMMC Electrical Standa= rd Spec 5.1 Section 6.10.4 for details.
+
+ &nb= sp;@param[in]  PassThru      A pointer to the=
EFI_SD_MMC_PASS_THRU_PROTOCOL
+       &nb= sp;            =         instance.
+ &= nbsp;@param[in]  Access        The = access mode of SWTICH command.
+  @param[in]  Index=         The offset of the field to= be access.
+  @param[in]  Value    =      The value to be set to the specified field of=
+          &nbs= p;            &= nbsp;    EXT_CSD register.
+  @param= [in]  CmdSet        The value of Cm= dSet field of EXT_CSD register.
+
+  @retv= al EFI_SUCCESS       The operation is done co= rrectly.
+  @retval Others      = ;      The operation fails.
++**/
+EFI_STATUS
+EmmcSwitch (
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL     = ; *PassThru,
+  IN UINT8     &n= bsp;            = ;            Ac= cess,
+  IN UINT8       &n= bsp;            = ;          Index,
+  IN UINT8         &nb= sp;            =         Value,
+ &nbs= p;IN UINT8           &nbs= p;            &= nbsp;     CmdSet
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK    =           SdMmcCmdBlk;+  EFI_SD_MMC_STATUS_BLOCK      &= nbsp;        SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_STATUS        &nb= sp;            =        Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeof (Packet));
++  Packet.SdMmcCmdBlk    =3D &SdMmcCmd= Blk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;+  Packet.Timeout       &nb= sp;=3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdM= mcCmdBlk.CommandIndex =3D EMMC_SWITCH;
+  SdMmcCmdBlk.Co= mmandType  =3D SdMmcCommandTypeAc;
+  SdMmcCmdBlk.R= esponseType =3D SdMmcResponseTypeR1b;
+  SdMmcCmdBlk.Com= mandArgument =3D (Access << 24) | (Index << 16) | \
+            &nbs= p;            &= nbsp;      (Value << 8) | CmdSet;
+
+  Status =3D PassThru->PassThru (PassThru= , 0, &Packet, NULL);
+
+  return Statu= s;
+}
+
+/**
+ &nbs= p;Send command SEND_STATUS to the addressed EMMC device to get its
status
+  register.
+
+  Refer to EMMC El= ectrical Standard Spec 5.1 Section 6.10.4 for details.
+
+  @param[in]  PassThru      A= pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+     =             &nb= sp;          instance.+  @param[in]  Rca      &nbs= p;    The relative device address of addressed device.<= br class=3D"">+  @param[out] DevStatus     The ret= urned device status.
+
+  @retval EFI_SUCC= ESS       The operation is done correctly.+  @retval Others       &nbs= p;    The operation fails.
+
+**/
+EFI_STATUS
+EmmcSendStatus (
+  IN     EFI_SD_MMC_PASS_THRU_PROTOCOL &nb= sp;*PassThru,
+  IN     UINT16  = ;            &n= bsp;          Rca,
+     OUT UINT32      =             &nb= sp;      *DevStatus
+  )+{
+  EFI_SD_MMC_COMMAND_BLOCK   =            SdMmcCmdB= lk;
+  EFI_SD_MMC_STATUS_BLOCK     &= nbsp;         SdMmcStatusBlk;<= br class=3D"">+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packe= t;
+  EFI_STATUS       &nb= sp;            =         Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeof (Packet));
+<= br class=3D"">+  Packet.SdMmcCmdBlk    =3D &SdMmcCm= dBlk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;<= br class=3D"">+  Packet.Timeout       &n= bsp;=3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  Sd= MmcCmdBlk.CommandIndex =3D EMMC_SEND_STATUS;
+  SdMmcCmd= Blk.CommandType  =3D SdMmcCommandTypeAc;
+  SdMmcCm= dBlk.ResponseType =3D SdMmcResponseTypeR1;
+  SdMmcCmdBl= k.CommandArgument =3D (UINT32)Rca << 16;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL)= ;
+  if (!EFI_ERROR (Status)) {
+  &n= bsp; *DevStatus =3D SdMmcStatusBlk.Resp0;
+  }
+
+  return Status;
+}
+
+/**
+  Send command SEND_TUNING_= BLOCK to the EMMC device for HS200
optimal sampl= ing
+  point detect= ion.
+
+  It may be sent up to 40 times un= til the host finishes the tuning
procedure.
+
+  Refe= r to EMMC Electrical Standard Spec 5.1 Section 6.6.8 for details.
+
+  @param[in] PassThru     =   A pointer to the
EFI_SD_MMC_PASS_THR= U_PROTOCOL
+   = ;            &n= bsp;            = ;instance.
+  @param[in] BusWidth    &nbs= p;  The bus width to work.
+
+  = @retval EFI_SUCCESS       The operation is do= ne correctly.
+  @retval Others     =        The operation fails.
+
+**/
+EFI_STATUS
+EmmcSendTun= ingBlk (
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL   = ;   *PassThru,
+  IN UINT8   &n= bsp;            = ;            &n= bsp; BusWidth
+  )
+{
+=  EFI_SD_MMC_COMMAND_BLOCK        &= nbsp;     SdMmcCmdBlk;
+  EFI_S= D_MMC_STATUS_BLOCK          &n= bsp;    SdMmcStatusBlk;
+  EFI_SD_MM= C_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_ST= ATUS            &nbs= p;            &= nbsp;  Status;
+  UINT8    &nbs= p;            &= nbsp;           &nbs= p;   TuningBlock[128];
+
+  = ;ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  Ze= roMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  = ;ZeroMem (&Packet, sizeof (Packet));
+
+ &n= bsp;Packet.SdMmcCmdBlk    =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;
+ &n= bsp;Packet.Timeout        =3D DW_MMC_HC_= GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandI= ndex =3D EMMC_SEND_TUNING_BLOCK;
+  SdMmcCmdBlk.CommandT= ype  =3D SdMmcCommandTypeAdtc;
+  SdMmcCmdBlk.Respo= nseType =3D SdMmcResponseTypeR1;
+  SdMmcCmdBlk.CommandA= rgument =3D 0;
+
+  Packet.InDataBuffer = =3D TuningBlock;
+  if (BusWidth =3D=3D 8) {
+    Packet.InTransferLength =3D sizeof (TuningBlock)= ;
+  } else {
+    Packet.I= nTransferLength =3D 64;
+  }
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL= );
+
+  return Status;
+}+
+/**
+  Tunning the clock to= get HS200 optimal sampling point.
+
+  Co= mmand SEND_TUNING_BLOCK may be sent up to 40 times until the
=
host finishes
+  the tuning procedure.
+
+  Refe= r to EMMC Electrical Standard Spec 5.1 Section 6.6.8.
+
+  @param[in] DevIo        = ;  A pointer to the EFI_DEVICE_IO_PROTOCOL
instance.
+  @= param[in] PassThru       A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+        &= nbsp;           &nbs= p;       instance.
+  = ;@param[in] BusWidth       The bus width to w= ork.
+
+  @retval EFI_SUCCESS   =     The operation is done correctly.
+ &n= bsp;@retval Others          &n= bsp; The operation fails.
+
+**/
+EFI_STATUS
+EmmcTuningClkForHs200 (
+ &= nbsp;IN UINTN           &= nbsp;           &nbs= p;      DevBase,
+  IN EFI= _SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
+  IN UINT8         &nb= sp;            =         BusWidth
+ &n= bsp;)
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Switch t= he bus width to specified width.
+
+  Refe= r to EMMC Electrical Standard Spec 5.1 Section 6.6.9.
+
+  @param[in] DevIo        = ;  A pointer to the EFI_DEVICE_IO_PROTOCOL
instance.
+  @= param[in] PassThru       A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+        &= nbsp;           &nbs= p;       instance.
+  = ;@param[in] Rca           = ; The relative device address to be assigned.
+  @p= aram[in] IsDdr          If TRU= E, use dual data rate data simpling method.
+   &nb= sp;            =             Oth= erwise use single data rate data simpling method.
+  @pa= ram[in] BusWidth       The bus width to be se= t, it could be 4 or 8.
+
+  @retval EFI_SU= CCESS       The operation is done correctly.<= br class=3D"">+  @retval Others       &n= bsp;    The operation fails.
+
+**/
+EFI_STATUS
+EmmcSwitchBusWidth (+  IN UINTN        &nb= sp;            =          DevBase,
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *P= assThru,
+  IN UINT16      &nbs= p;            &= nbsp;         Rca,
+  IN BOOLEAN          = ;            &n= bsp;     IsDdr,
+  IN UINT8 &nb= sp;            =             &nb= sp;   BusWidth
+  )
+{
+  EFI_STATUS        &nbs= p; Status;
+  UINT8      &= nbsp;        Access;
= +  UINT8           &= nbsp;   Index;
+  UINT8    = ;           Value;+  UINT8         =       CmdSet;
+  UINT32 &n= bsp;            = ;DevStatus;
+
+  //
+  = // Write Byte, the Value field is written into the byte pointed by Index.+  //
+  Access =3D 0x03;
+  Index  =3D OFFSET_OF (EMMC_EXT_CSD, BusWidth);
+  if (BusWidth =3D=3D 1) {
+    Value = =3D 0;
+  } else {
+    if= (BusWidth =3D=3D 4) {
+      Value = = =3D 1;
+    } else if (BusWidth =3D=3D 8) {+      Value =3D 2;
+ &= nbsp;  } else {
+      ret= urn EFI_INVALID_PARAMETER;
+    }
+
+    if (IsDdr) {
+  &n= bsp;   Value +=3D 4;
+    }
+  }
+
+  CmdSet =3D 0;+  Status =3D EmmcSwitch (PassThru, Access, Index, Value, = CmdSet);
+  if (EFI_ERROR (Status)) {
+ &n= bsp;  DEBUG ((
+      DEBU= G_ERROR,
+      "EmmcSwitchBusWidth:= Switch to bus width %d fails with %r\n",
+    = ;  BusWidth,
+      Status=
+      ));
+  &n= bsp; return Status;
+  }
+
+  do {
+    Status =3D EmmcSendSt= atus (PassThru, Rca, &DevStatus);
+    if = (EFI_ERROR (Status)) {
+      DEBUG = ((
+        DEBUG_ERROR,+        "EmmcSwitchBusWidt= h: Send status fails with %r\n",
+     &n= bsp;  Status
+       =  ));
+      return Status;
+    }
+    //
+    // Check the switch operation is really success= ful or not.
+    //
+  } wh= ile ((DevStatus & 0xf) =3D=3D EMMC_STATE_PRG);
+
+  Status =3D DwMmcHcSetBusWidth (DevBase, IsDdr, BusWidth);+  if (EFI_ERROR (Status)) {
+   &= nbsp;return Status;
+  }
+
+=  return Status;
+}
+
+/**+  Switch the clock frequency to the specified value.
+
+  Refer to EMMC Electrical Standard Spec 5= .1 Section 6.6.
+
+  @param[in] DevIo &nbs= p;        A pointer to the EFI_DEVI= CE_IO_PROTOCOL
instance.
+  @param[in] PassThru    &= nbsp;  A pointer to the
EFI_SD_MMC_PAS= S_THRU_PROTOCOL
+  =             &nb= sp;            =  instance.
+  @param[in] Rca    &nbs= p;       The relative device address to = be assigned.
+  @param[in] HsTiming    &n= bsp;  The value to be written to HS_TIMING field of
+             =             &nb= sp;  EXT_CSD register.
+  @param[in] ClockFreq=      The max clock frequency to be set, the unit = is
MHz.
+
+  @retval EFI_SUCCESS    &n= bsp;  The operation is done correctly.
+  @ret= val Others           &nbs= p;The operation fails.
+
+**/
+EF= I_STATUS
+EmmcSwitchClockFreq (
+  IN UINT= N             &= nbsp;           &nbs= p;    DevBase,
+  IN EFI_SD_MMC_PASS= _THRU_PROTOCOL      *PassThru,
+ &nb= sp;IN UINT16           &n= bsp;            = ;     Rca,
+  IN UINT8  &n= bsp;            = ;            &n= bsp;  HsTiming,
+  IN UINT32    = ;            &n= bsp;            = ;ClockFreq
+  )
+{
+  E= FI_STATUS            = ;    Status;
+  UINT8   &n= bsp;            = ;     Access;
+  UINT8  &n= bsp;            = ;      Index;
+  UINT8 &nb= sp;            =        Value;
+  UINT= 8             &= nbsp;       CmdSet;
+ &nbs= p;UINT32            =         DevStatus;
+ =  DW_MMC_HC_PRIVATE_DATA    *Private;
++  Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+  //
+  // Write Byte, the Value field = is written into the byte pointed by Index.
+  //
+  Access =3D 0x03;
+  Index  =3D OFFSE= T_OF (EMMC_EXT_CSD, HsTiming);
+  Value  =3D HsTimi= ng;
+  CmdSet =3D 0;
+
+ &nb= sp;Status =3D EmmcSwitch (PassThru, Access, Index, Value, CmdSet);
+  if (EFI_ERROR (Status)) {
+    = DEBUG ((
+      DEBUG_ERROR,
+      "EmmcSwitchClockFreq: Switch to hsti= ming %d fails with %r\n",
+      HsT= iming,
+      Status
+=      ));
+    return= Status;
+  }
+
+  Stat= us =3D EmmcSendStatus (PassThru, Rca, &DevStatus);
+ &nbs= p;if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+ &nbs= p;    "EmmcSwitchClockFreq: Send status fails with %r\n= ",
+      Status
+ &nb= sp;    ));
+    return Sta= tus;
+  }
+  //
+  = ;// Check the switch operation is really successful or not.
+=  //
+  if ((DevStatus & BIT7) !=3D 0) {
+    DEBUG ((
+    &nbs= p; DEBUG_ERROR,
+      "EmmcSwi= tchClockFreq: The switch operation fails as DevStatus
0x%08x\n",
+  = ;    DevStatus
+     =  ));
+    return EFI_DEVICE_ERROR;
+  }
+  //
+  // Convert= the clock freq unit from MHz to KHz.
+  //
+  Status =3D DwMmcHcClockSupply (DevBase, ClockFreq * 1000, Private= -
Capability[0]);
+
+  retur= n Status;
+}
+
+/**
+  Switch to the High Speed timing according to request.
+
+  Refer to EMMC Electrical Standard Spec 5.1 Sectio= n 6.6.8.
+
+  @param[in] DevIo   = ;       A pointer to the EFI_DEVICE_IO_P= ROTOCOL
instance.
+  @param[in] PassThru     &= nbsp; A pointer to the
EFI_SD_MMC_PASS_THRU= _PROTOCOL
+   =             &nb= sp;            = instance.
+  @param[in] Rca     &nbs= p;      The relative device address to be ass= igned.
+  @param[in] ClockFreq     &= nbsp;The max clock frequency to be set.
+  @param[in] Is= Ddr          If TRUE, use dual= data rate data simpling method.
+     &n= bsp;            = ;          Otherwise use = single data rate data simpling method.
+  @param[in] Bus= Width       The bus width to be set, it could= be 4 or 8.
+
+  @retval EFI_SUCCESS  = ;     The operation is done correctly.
+  @retval Others         &= nbsp;  The operation fails.
+
+**/+EFI_STATUS
+EmmcSwitchToHighSpeed (
+  IN UINTN          &n= bsp;            = ;       DevBase,
+  I= N EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,+  IN UINT16        &nb= sp;            =         Rca,
+  = IN UINT32            = ;            &n= bsp;    ClockFreq,
+  IN BOOLEAN &nb= sp;            =             &nb= sp; IsDdr,
+  IN UINT8     &nbs= p;            &= nbsp;           BusW= idth
+  )
+{
+  EFI_STA= TUS          Status;
+  UINT8          =      HsTiming;
+
+ &nb= sp;HsTiming =3D 1;
+  Status =3D EmmcSwitchClockFreq (De= vBase, PassThru, Rca, HsTiming,
ClockFreq);
+  if (EFI_ERROR (Statu= s)) {
+    return Status;
+ &nbs= p;}
+  Status =3D EmmcSwitchBusWidth (DevBase, PassThru,= Rca, IsDdr,
BusWidth);
+  if (EFI_ERROR (Status)) {
= +    return Status;
+  }
+ =  return EFI_SUCCESS;
+}
+
+/= **
+  Switch to the HS200 timing according to request.+
+  Refer to EMMC Electrical Standard Spec= 5.1 Section 6.6.8.
+
+  @param[in] DevIo =          A pointer to the EFI_= DEVICE_IO_PROTOCOL
instance.
+  @param[in] PassThru   &nb= sp;   A pointer to the
EFI_SD_MMC= _PASS_THRU_PROTOCOL
+ &n= bsp;            = ;            &n= bsp; instance.
+  @param[in] Rca    =         The relative device address= to be assigned.
+  @param[in] ClockFreq   &nb= sp;  The max clock frequency to be set.
+  @pa= ram[in] BusWidth       The bus width to be se= t, it could be 4 or 8.
+
+  @retval EFI_SU= CCESS       The operation is done correctly.<= br class=3D"">+  @retval Others       &n= bsp;    The operation fails.
+
+**/
+EFI_STATUS
+EmmcSwitchToHS200 (+  IN UINTN        &nbs= p;            &= nbsp;        DevBase,
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *Pa= ssThru,
+  IN UINT16       = ;            &n= bsp;         Rca,
+  IN UINT32          &= nbsp;           &nbs= p;      ClockFreq,
+  IN U= INT8            &nbs= p;            &= nbsp;    BusWidth
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Switch the high speed timing a= ccording to request.
+
+  Refer to EMMC El= ectrical Standard Spec 5.1 Section 6.6.8.
+
+ &= nbsp;@param[in] DevIo          = ;A pointer to the EFI_DEVICE_IO_PROTOCOL
instanc= e.
+  @param[in] Pa= ssThru       A pointer to the
<= /blockquote>EFI_SD_MMC_PASS_THRU_PROTOCOL
+          &= nbsp;           &nbs= p;     instance.
+  @param[in] = Rca            The r= elative device address to be assigned.
+
+ &nbs= p;@retval EFI_SUCCESS       The operation is = done correctly.
+  @retval Others    &nbs= p;       The operation fails.
+
+**/
+EFI_STATUS
+EmmcSe= tBusMode (
+  IN UINTN      &nb= sp;            =            DevBase,<= br class=3D"">+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL    &n= bsp; *PassThru,
+  IN UINT16    &nbs= p;            &= nbsp;           Rca<= br class=3D"">+  )
+{
+  EFI_STATUS &= nbsp;           &nbs= p;      Status;
+  EMMC_CS= D             &= nbsp;        Csd;
+ &= nbsp;EMMC_EXT_CSD          &nb= sp;       ExtCsd;
+  = UINT8            &nb= sp;            = HsTiming;
+  BOOLEAN       = ;            &n= bsp;   IsDdr;
+  UINT32    = ;            &n= bsp;       DevStatus;
+ &n= bsp;UINT32           &nbs= p;            C= lockFreq;
+  UINT8       &= nbsp;           &nbs= p;     BusWidth;
+  DW_MMC_HC_P= RIVATE_DATA        *Private;
+
+  Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThr= u);
+  ASSERT (Private->Capability[0].BaseClkFreq != =3D 0);
+
+  Status =3D EmmcGetCsd (PassT= hru, Rca, &Csd);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetCsd fa= ils with %r\n",
Status));
+    return Status;
+  }
+
+  Status =3D EmmcSelect (P= assThru, Rca);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Select fails wi= th %r\n",
Status));
+    return Status;
+ &= nbsp;}
+
+  do {
+  &nb= sp; Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus);
+    if (EFI_ERROR (Status)) {
+  =     DEBUG ((
+     &n= bsp;  DEBUG_ERROR,
+      =   "EmmcSetBusMode: Get Status fails with %r\n",
+ &= nbsp;      Status
+   = ;     ));
+     =  return Status;
+    }
+ &n= bsp;} while (EMMC_GET_STATE (DevStatus) !=3D EMMC_STATE_TRAN);
+
+  BusWidth =3D 1;
+  Status =3D = EmmcSwitchBusWidth (DevBase, PassThru, Rca, FALSE,
BusWidth);
+  if= (EFI_ERROR (Status)) {
+    return Status;+  }
+
+  BusWidth =3D Pr= ivate->Capability[0].BusWidth;
+  //
+ =  // Get Deivce_Type from EXT_CSD register.
+  //+  Status =3D EmmcGetExtCsd (PassThru, &ExtCsd);
+  if (EFI_ERROR (Status)) {
+   &nbs= p;DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails with
=
%r\n", Status));
+    return Status;
+  }
+
+  //
+  // Calculate suppor= ted bus speed/bus width/clock frequency.
+  //
+  HsTiming  =3D 0;
+  IsDdr  &nbs= p;  =3D FALSE;
+  ClockFreq =3D 0;
+  if (((ExtCsd.DeviceType & (BIT4 | BIT5)) !=3D 0) &&<= br class=3D"">+      (Private->Capability[0].Sd= r104 !=3D 0)) {
+    HsTiming  =3D 2;
+    IsDdr     =3D FALSE;
+    ClockFreq =3D 200;
+  } e= lse if (((ExtCsd.DeviceType & (BIT2 | BIT3)) !=3D 0) &&
+            =  (Private->Capability[0].Ddr50 !=3D 0)) {
+  &nb= sp; HsTiming  =3D 1;
+    IsDdr &nbs= p;   =3D TRUE;
+    ClockFreq = =3D 52;
+  } else if (((ExtCsd.DeviceType & BIT1) != = =3D 0) &&
+       &nbs= p;     (Private->Capability[0].HighSpeed !=3D 0= )) {
+    HsTiming  =3D 1;
= +    IsDdr     =3D FALSE;
= +    ClockFreq =3D 52;
+  } else if (((Ex= tCsd.DeviceType & BIT0) !=3D 0) &&
+   =           (Private->Ca= pability[0].HighSpeed !=3D 0)) {
+    HsTiming=  =3D 1;
+    IsDdr    &nb= sp;=3D FALSE;
+    ClockFreq =3D 26;
+  }
+
+  if ((ClockFreq =3D= =3D 0) || (HsTiming =3D=3D 0)) {
+    //
+    // Continue using default setting.
+    //
+    return EFI_= SUCCESS;
+  }
+
+  DEBU= G ((
+    DEBUG_INFO,
+  &n= bsp; "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr
%a\n",
+    HsTiming,
+    ClockFre= q,
+    BusWidth,
+   =  IsDdr ? "TRUE" : "FALSE"
+    ));
+
+  if (HsTiming =3D=3D 2) {
+ &n= bsp;  //
+    // Execute HS200 timin= g switch procedure
+    //
+ &nb= sp;  Status =3D EmmcSwitchToHS200 (DevBase, PassThru, Rca, ClockF= req,
BusWidth);
+  } else {
+    //=
+    // Execute High Speed timing switch proc= edure
+    //
+   &nbs= p;Status =3D EmmcSwitchToHighSpeed (
+    &nbs= p;          DevBase,
+           &nb= sp;   PassThru,
+     &nbs= p;         Rca,
= +             &= nbsp; ClockFreq,
+       &= nbsp;       IsDdr,
+  = ;            &n= bsp;BusWidth
+        &nbs= p;      );
+  }
+
+  DEBUG ((
+    D= EBUG_INFO,
+    "EmmcSetBusMode: Switch to %a = %r\n",
+    (HsTiming =3D=3D 3) ? "HS400" : ((= HsTiming =3D=3D 2) ? "HS200" : "HighSpeed"),
+   &n= bsp;Status
+    ));
+
+  return Status;
+}
+
+/**
+  Execute EMMC device identification procedure.<= br class=3D"">+
+  Refer to EMMC Electrical Standard Spe= c 5.1 Section 6.4 for details.
+
+  @param= [in] Private        A pointer to the DW_= MMC_HC_PRIVATE_DATA
instance.
+
+  @retval EFI_SUCCES= S       There is a EMMC card.
+=  @retval Others          = ;  There is not a EMMC card.
+
+**/+EFI_STATUS
+EmmcIdentification (
= +  IN DW_MMC_HC_PRIVATE_DATA        = ;     *Private
+  )
+{
+  EFI_STATUS       =             &nb= sp; Status;
+  UINTN      =             &nb= sp;       DevBase;
+  = ;EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru;
+  UINT3= 2             &= nbsp;           Ocr;=
+  UINT16        &nb= sp;            =     Rca;
+  UINT32    = ;            &n= bsp;        DevStatus;
+  UINT32          &nbs= p;            &= nbsp; Timeout;
+
+  DevBase  &nb= sp; =3D Private->DevBase;
+  PassThru =3D &P= rivate->PassThru;
+
+  Status =3D EmmcR= eset (PassThru);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+     = ; DEBUG_INFO,
+      "EmmcIdent= ification: Executing Cmd0 fails with %r\n",
+   &nb= sp;  Status
+      ));
+    return Status;
+  }
+
+  Timeout =3D 100;
+  do = {
+    Ocr =3D EMMC_CMD1_CAPACITY_GREATER_THAN= _2GB;
+    Status =3D EmmcGetOcr (PassThru, &a= mp;Ocr);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+  &nbs= p;     DEBUG_INFO,
+   &nb= sp;    "EmmcIdentification: Executing Cmd1 fails with %= r\n",
+        Status
+        ));
+ &= nbsp;    return Status;
+   &nb= sp;}
+    if (--Timeout <=3D 0) {
+      return EFI_DEVICE_ERROR;
+    }
+    MicroSecondDelay= (100);
+  } while ((Ocr & BIT31) =3D=3D 0);
+
+  Status =3D EmmcGetAllCid (PassThru);
+  if (EFI_ERROR (Status)) {
+    = DEBUG ((
+      DEBUG_INFO,
+      "EmmcIdentification: Executing Cmd2 = fails with %r\n",
+      Status
+      ));
+   &= nbsp;return Status;
+  }
+  //
+  // valid RCA starts from 1.
+  // Here w= e takes a simple formula to calculate the RCA.
+  // Don= 't support multiple devices on the slot, that is
+  // s= hared bus slot feature.
+  //
+  Rca =    =3D 1;
+  Status =3D EmmcSetRca (PassT= hru, Rca);
+  if (EFI_ERROR (Status)) {
+ =    DEBUG ((
+      DE= BUG_INFO,
+      "EmmcIdentification= : Executing Cmd3 fails with %r\n",
+     =  Status
+      ));
+    return Status;
+  }
= +  //
+  // Enter Data Tranfer Mode.
= +  //
+  DEBUG ((
+    = ;DEBUG_INFO,
+    "EmmcIdentification: Found a= EMMC device at RCA [%d]\n",
+    Rca
+    ));
+  Private->Slot[0].Ca= rdType =3D EmmcCardType;
+
+  Status =3D E= mmcSetBusMode (DevBase, PassThru, Rca);
+  if (EFI_ERROR= (Status)) {
+    return Status;
+  }
+
+  //
+  /= / Exit DATA Mode.
+  //
+  do {
+    Status =3D EmmcSendStatus (PassThru, Rca, &= ;DevStatus);
+    if (EFI_ERROR (Status)) {+      DEBUG ((
+  =       DEBUG_INFO,
+   = ;     "EmmcSwitchBusWidth: Send status fails with = %r\n",
+        Status
+        ));
+ =      return Status;
+   &n= bsp;}
+  } while ((DevStatus & 0xf) =3D=3D EMMC_STAT= E_DATA);
+
+  return Status;
+}
diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c
b/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c
new file mode 100644
index 000000000000..63246637b6dd
--- /dev/null
+++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c
@@ -0,= 0 +1,1105 @@
+/** @file
+  This file provi= des some helper functions which are specific for SD card
+ &n= bsp;device.
+
+  Copyright (c) 2015 - 2021= , Intel Corporation. All rights reserved.<BR>
+  C= opyright (c) 2018, Linaro. All rights reserved.<BR>
++  This program and the accompanying materials are licens= ed 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/lice= nses/bsd-license.php
+
+  THE PROGRAM = IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
BASIS,
+  WITHOU= T WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED.
= +
+**/
+
+#include <IndustrySt= andard/Sd.h>
+
+#include <Library/BaseMem= oryLib.h>
+#include <Library/DebugLib.h>
+
+#include "DwMmcHcDxe.h"
+
+= /**
+  Send command GO_IDLE_STATE to the device to make = it go to Idle State.
+
+  Refer to SD Phys= ical Layer Simplified Spec 4.1 Section 4.7 for details.
+
+  @param[in] PassThru       = A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+     = ;            &n= bsp;          instance.+
+  @retval EFI_SUCCESS    =    The SD device is reset correctly.
+  @= retval Others           &= nbsp;The device reset fails.
+
+**/
+EFI_STATUS
+SdCardReset (
+  IN EFI_SD= _MMC_PASS_THRU_PROTOCOL      *PassThru
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOC= K             &= nbsp;SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK   = ;            Sd= MmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET &nb= sp; Packet;
+  EFI_STATUS     &= nbsp;           &nbs= p;          Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCm= dBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcSt= atusBlk));
+  ZeroMem (&Packet, sizeof (Packet));+
+  Packet.SdMmcCmdBlk    = =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &= ;SdMmcStatusBlk;
+  Packet.Timeout    &nb= sp;   =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D SD_GO_IDLE_STATE;
+  SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeBc;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &a= mp;Packet, NULL);
+  //Status =3D PassThru->PassThru = (PassThru, 0, &Packet, NULL);
+
+  ret= urn Status;
+}
+
+/**
+  Send command SEND_IF_COND to the device to inquiry the SD Memory=
Card
+  interface condition.
+
+  = ;Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.+
+  @param[in] PassThru    &= nbsp;  A pointer to the
EFI_SD_MMC_PAS= S_THRU_PROTOCOL
+  =             &nb= sp;            =  instance.
+  @param[in] SupplyVoltage  The su= pplied voltage by the host.
+  @param[in] CheckPattern &= nbsp; The check pattern to be sent to the device.
+
+  @retval EFI_SUCCESS       T= he operation is done correctly.
+  @retval Others  =           The operation f= ails.
+
+**/
+EFI_STATUS
+SdCardVoltageCheck (
+  IN EFI_SD_MMC_PASS_THRU_= PROTOCOL      *PassThru,
+  IN = UINT8            &nb= sp;            =      SupplyVoltage,
+  IN UINT8=             &n= bsp;            = ;    CheckPattern
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK     =          SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK       =         SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_STATUS         &= nbsp;           &nbs= p;      Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+ =  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeof (Packet));
+
+  Packet.SdMmcCmdBlk    =3D &SdMmcCmdBlk;+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;
+  Packet.Timeout        =3D= DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdB= lk.CommandIndex =3D SD_SEND_IF_COND;
+  SdMmcCmdBlk.Comm= andType  =3D SdMmcCommandTypeBcr;
+  SdMmcCmdBlk.Re= sponseType =3D SdMmcResponseTypeR7;
+  SdMmcCmdBlk.Comma= ndArgument =3D (SupplyVoltage << 8) |
Chec= kPattern;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL)= ;
+
+  if (!EFI_ERROR (Status)) {
+    if (SdMmcStatusBlk.Resp0 !=3D SdMmcCmdBlk.Comman= dArgument) {
+      return EFI_DEVIC= E_ERROR;
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Send command SDIO_SEND_OP_CON= D to the device to see whether it is
SDIO device= .
+
+ &nbs= p;Refer to SDIO Simplified Spec 3 Section 3.2 for details.
+<= br class=3D"">+  @param[in] PassThru      &nb= sp;A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCO= L
+    &n= bsp;            = ;           instance= .
+  @param[in] VoltageWindow  The supply voltage w= indow.
+  @param[in] S18R      =      The boolean to show if it should switch to 1.= 8v.
+
+  @retval EFI_SUCCESS   &= nbsp;   The operation is done correctly.
+ &nb= sp;@retval Others          &nb= sp; The operation fails.
+
+**/
+EFI_STATUS
+SdioSendOpCond (
+  IN= EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
+  IN UINT32        &nbs= p;            &= nbsp;       VoltageWindow,
+  IN BOOLEAN          &= nbsp;           &nbs= p;     S18R
+  )
= +{
+  EFI_SD_MMC_COMMAND_BLOCK     &= nbsp;        SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK       =         SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_STATUS         &= nbsp;           &nbs= p;      Status;
+  UINT32 =             &nb= sp;            =       Switch;
+
+=  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+ &n= bsp;ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+=  ZeroMem (&Packet, sizeof (Packet));
+
+  Packet.SdMmcCmdBlk    =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;
+  Packet.Timeout        =3D DW_M= MC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.Co= mmandIndex =3D SDIO_SEND_OP_COND;
+  SdMmcCmdBlk.Command= Type  =3D SdMmcCommandTypeBcr;
+  SdMmcCmdBlk.Respo= nseType =3D SdMmcResponseTypeR4;
+
+  Swit= ch =3D S18R ? BIT24 : 0;
+
+  SdMmcCmdBlk.= CommandArgument =3D (VoltageWindow & 0xFFFFFF) |
Switch;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Packet, = NULL);
+
+  return Status;
+= }
+
+/**
+  Send command SD_= SEND_OP_COND to the device to see whether it is
= SDIO device.
+
+  Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 f= or details.
+
+  @param[in]  PassThru=       A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+           &= nbsp;           &nbs= p;     instance.
+  @param[in] =  Rca            = ;The relative device address of addressed device.
+  @pa= ram[in]  VoltageWindow  The supply voltage window.
= +  @param[in]  S18R        &nb= sp;  The boolean to show if it should switch to 1.8v.
+  @param[in]  Xpc        &= nbsp;   The boolean to show if it should provide 0.36w
+           &nbs= p;            &= nbsp;    power control.
+  @param[in= ]  Hcs           &nb= sp;The boolean to show if it support host capacity
+  &n= bsp;            = ;            &n= bsp; info.
+  @param[out] Ocr    &nb= sp;       The buffer to store returned O= CR register value.
+
+  @retval EFI_SUCCES= S        The operation is done correctly= .
+  @retval Others       =       The operation fails.
++**/
+EFI_STATUS
+SdCardSendOpCond = (
+  IN     EFI_SD_MMC_PASS_THRU_PRO= TOCOL  *PassThru,
+  IN     UIN= T16             = ;            Rc= a,
+  IN     UINT32   &nbs= p;            &= nbsp;        VoltageWindow,
+  IN     BOOLEAN     &= nbsp;           &nbs= p;      S18R,
+  IN  =    BOOLEAN         &= nbsp;           &nbs= p;  Xpc,
+  IN     BOOLEAN=             &n= bsp;          Hcs,
+     OUT UINT32      =             &nb= sp;      *Ocr
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK    =           SdMmcCmdBlk;+  EFI_SD_MMC_STATUS_BLOCK      &= nbsp;        SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_STATUS        &nb= sp;            =        Status;
+  UIN= T32             = ;            &n= bsp;      Switch;
+  UINT3= 2             &= nbsp;           &nbs= p;      MaxPower;
+  UINT3= 2             &= nbsp;           &nbs= p;      HostCapacity;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, sizeof (Packet));
++  Packet.SdMmcCmdBlk    =3D &SdMmcCmd= Blk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;+  Packet.Timeout       &nb= sp;=3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdM= mcCmdBlk.CommandIndex =3D SD_APP_CMD;
+  SdMmcCmdBlk.Com= mandType  =3D SdMmcCommandTypeAc;
+  SdMmcCmdBlk.Re= sponseType =3D SdMmcResponseTypeR1;
+  SdMmcCmdBlk.Comma= ndArgument =3D (UINT32)Rca << 16;
+
+ &nb= sp;Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL);
+  if (EFI_ERROR (Status)) {
+   &nbs= p;return Status;
+  }
+
+ &n= bsp;SdMmcCmdBlk.CommandIndex =3D SD_SEND_OP_COND;
+  SdM= mcCmdBlk.CommandType  =3D SdMmcCommandTypeBcr;
+  S= dMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR3;
+
+  Switch       =3D S18R ? BIT24 = : 0;
+  MaxPower     =3D Xpc ? BIT28= : 0;
+  HostCapacity =3D Hcs ? BIT30 : 0;
+
+  SdMmcCmdBlk.CommandArgument =3D (VoltageWindow &am= p; 0xFFFFFF) |
Switch | \
+        &n= bsp;            = ;           MaxPower= | HostCapacity;
+
+  Status =3D PassThru-= >PassThru (PassThru, 0, &Packet, NULL);
+  if (!E= FI_ERROR (Status)) {
+    *Ocr =3D SdMmcStatus= Blk.Resp0;
+  }
+
+  re= turn Status;
+}
+
+/**
+  Broadcast command ALL_SEND_CID to the bus to ask all the SD = devices
to send
+  the data of their CID registers.
+
+  Refer to SD Physical Layer Simplified Spec 4.1 Se= ction 4.7 for details.
+
+  @param[in] Pas= sThru       A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+          &n= bsp;            = ;     instance.
+
+ &n= bsp;@retval EFI_SUCCESS       The operation i= s done correctly.
+  @retval Others    &n= bsp;       The operation fails.
+
+**/
+EFI_STATUS
+SdCard= AllSendCid (
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL  &= nbsp;   *PassThru
+  )
+{+  EFI_SD_MMC_COMMAND_BLOCK      = ;        SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK        =        SdMmcStatusBlk;
+ &= nbsp;EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
= +  EFI_STATUS          &n= bsp;            = ;     Status;
+
+ &nbs= p;ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  Z= eroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+ &nbs= p;ZeroMem (&Packet, sizeof (Packet));
+
+ &= nbsp;Packet.SdMmcCmdBlk    =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;
+ &= nbsp;Packet.Timeout        =3D DW_MMC_HC= _GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.Command= Index =3D SD_ALL_SEND_CID;
+  SdMmcCmdBlk.CommandType &n= bsp;=3D SdMmcCommandTypeBcr;
+  SdMmcCmdBlk.ResponseType= =3D SdMmcResponseTypeR2;
+
+  Status =3D = PassThru->PassThru (PassThru, 0, &Packet, NULL);
+
+  return Status;
+}
+
+/**
+  Send command SET_RELATIVE_ADDR to the SD = device to assign a
Relative device
+  Address (RCA).
= +
+  Refer to SD Physical Layer Simplified Spec 4.1 Sect= ion 4.7 for details.
+
+  @param[in]  = ;PassThru      A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+          &nbs= p;            &= nbsp;    instance.
+  @param[out] Rc= a           The relative = device address to assign.
+
+  @retval EFI= _SUCCESS       The operation is done correctl= y.
+  @retval Others       = ;     The operation fails.
+
+**/
+EFI_STATUS
+SdCardSetRca (
+  IN     EFI_SD_MMC_PASS_THRU_PROTOCOL &nb= sp;*PassThru,
+     OUT UINT16  &nbs= p;            &= nbsp;         *Rca
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOC= K             &= nbsp;SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK   = ;            Sd= MmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET &nb= sp; Packet;
+  EFI_STATUS     &= nbsp;           &nbs= p;          Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCm= dBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcSt= atusBlk));
+  ZeroMem (&Packet, sizeof (Packet));+
+  Packet.SdMmcCmdBlk    = =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &= ;SdMmcStatusBlk;
+  Packet.Timeout    &nb= sp;   =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D SD_SET_RELATIVE_ADDR;
+  SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeBcr;
+  SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR6;
+
+  Status =3D PassThru->PassThru (PassThru, = 0, &Packet, NULL);
+  if (!EFI_ERROR (Status)) {
+    *Rca =3D (UINT16)(SdMmcStatusBlk.Resp0 >&= gt; 16);
+  }
+
+  retu= rn Status;
+}
+
+/**
+  Send command SEND_CSD to the SD device to get the data of the CSD=
register.
+
+  Refer to SD Physical Layer Simplified= Spec 4.1 Section 4.7 for details.
+
+  @p= aram[in]  PassThru      A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+        &n= bsp;            = ;       instance.
+  = @param[in]  Rca          =  The relative device address of selected device.
+  = ;@param[out] Csd          &nbs= p;The buffer to store the content of the CSD
reg= ister.
+   &nb= sp;            =             Not= e the caller should ignore the lowest byte of
+   &= nbsp;           &nbs= p;            t= his buffer as the content of this byte is meaning-
+  &n= bsp;            = ;            &n= bsp;less even if the operation succeeds.
+
+ &n= bsp;@retval EFI_SUCCESS       The operation i= s done correctly.
+  @retval Others    &n= bsp;       The operation fails.
+
+**/
+EFI_STATUS
+SdCard= GetCsd (
+  IN     EFI_SD_MMC_PASS_T= HRU_PROTOCOL  *PassThru,
+  IN    &n= bsp;UINT16           &nbs= p;            &= nbsp;Rca,
+     OUT SD_CSD   &n= bsp;            = ;         *Csd
+=  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK &n= bsp;            = ;SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK   &nb= sp;           SdMmcS= tatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET  &= nbsp;Packet;
+  EFI_STATUS      = ;            &n= bsp;         Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdB= lk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStat= usBlk));
+  ZeroMem (&Packet, sizeof (Packet));
+
+  Packet.SdMmcCmdBlk    =3D = &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMm= cStatusBlk;
+  Packet.Timeout     &n= bsp;  =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D SD_SEND_CSD;
+  S= dMmcCmdBlk.CommandType  =3D SdMmcCommandTypeAc;
+  = SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2;
+  SdM= mcCmdBlk.CommandArgument =3D (UINT32)Rca << 16;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Packet= , NULL);
+  if (!EFI_ERROR (Status)) {
+ &= nbsp;  CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, siz= eof
(SD_CSD) - 1);
+  }
+
+  retur= n Status;
+}
+
+/**
+  Send command SEND_CSD to the SD device to get the data of the CSD<= br class=3D"">
register.
+
+  Refer to SD Physical Layer Simplified = Spec 4.1 Section 4.7 for details.
+
+  @pa= ram[in]  PassThru      A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+        &nb= sp;            =        instance.
+  @= param[in]  Rca          &= nbsp;The relative device address of selected device.
+  = @param[out] Scr           = ;The buffer to store the content of the SCR
regi= ster.
+
+ =  @retval EFI_SUCCESS       The operation= is done correctly.
+  @retval Others    =         The operation fails.
+
+**/
+EFI_STATUS
+SdCar= dGetScr (
+  IN     EFI_SD_MMC_PASS_= THRU_PROTOCOL  *PassThru,
+  IN    &= nbsp;UINT16           &nb= sp;            =  Rca,
+     OUT SD_SCR   &= nbsp;           &nbs= p;         *Scr
= +  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK &= nbsp;           &nbs= p;SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK   &n= bsp;           SdMmc= StatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET  =  Packet;
+  EFI_STATUS     &nbs= p;            &= nbsp;         Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdB= lk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStat= usBlk));
+  ZeroMem (&Packet, sizeof (Packet));
+
+  Packet.SdMmcCmdBlk    =3D = &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMm= cStatusBlk;
+  Packet.Timeout     &n= bsp;  =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D SD_APP_CMD;
+  Sd= MmcCmdBlk.CommandType  =3D SdMmcCommandTypeAc;
+  S= dMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1;
+  SdMm= cCmdBlk.CommandArgument =3D (UINT32)Rca << 16;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Packet,= NULL);
+  if (EFI_ERROR (Status)) {
+ &nb= sp;  return Status;
+  }
+
+  SdMmcCmdBlk.CommandIndex =3D SD_SEND_SCR;
+ =  SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeAdtc;
+  SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1;
+<= br class=3D"">+  Packet.InDataBuffer     =3D Scr;<= br class=3D"">+  Packet.InTransferLength =3D sizeof (SD_SCR);
+
+  Status =3D PassThru->PassThru (PassThru, = 0, &Packet, NULL);
+
+  return Status;=
+}
+
+/**
+  = Send command SELECT_DESELECT_CARD to the SD device to
select/deselect it.
+
+  Refer to SD Physical Layer Simplified Spec 4.1 Se= ction 4.7 for details.
+
+  @param[in] &nb= sp;PassThru      A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+          &n= bsp;            = ;     instance.
+  @param[in] &= nbsp;Rca           The re= lative device address of selected device.
+
+ &= nbsp;@retval EFI_SUCCESS       The operation = is done correctly.
+  @retval Others    &= nbsp;       The operation fails.
+
+**/
+EFI_STATUS
+SdCard= Select (
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL   = ;   *PassThru,
+  IN UINT16   &= nbsp;           &nbs= p;            &= nbsp;Rca
+  )
+{
+  EFI= _SD_MMC_COMMAND_BLOCK          = ;    SdMmcCmdBlk;
+  EFI_SD_MMC_STAT= US_BLOCK            =    SdMmcStatusBlk;
+  EFI_SD_MMC_PASS_THR= U_COMMAND_PACKET   Packet;
+  EFI_STATUS  = ;            &n= bsp;            = ; Status;
+
+  ZeroMem (&SdMmcCmd= Blk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcStatus= Blk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Packet, = sizeof (Packet));
+
+  Packet.SdMmcCmdBlk =    =3D &SdMmcCmdBlk;
+  Packet.SdMmcS= tatusBlk =3D &SdMmcStatusBlk;
+  Packet.Timeout &nbs= p;      =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D SD_SELECT_DESE= LECT_CARD;
+  SdMmcCmdBlk.CommandType  =3D SdMmcCom= mandTypeAc;
+  if (Rca !=3D 0) {
+  &= nbsp; SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1b;
+  }
+  SdMmcCmdBlk.CommandArgument =3D (UINT32)Rc= a << 16;
+
+  Status =3D PassThru-&g= t;PassThru (PassThru, 0, &Packet, NULL);
+
= +  return Status;
+}
+
+/**<= br class=3D"">+  Send command VOLTAGE_SWITCH to the SD device to switc= h the voltage
of the
+  device.
+
+ &nb= sp;Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.<= br class=3D"">+
+  @param[in]  PassThru   = ;   A pointer to the
EFI_SD_MMC_P= ASS_THRU_PROTOCOL
+ &nbs= p;            &= nbsp;           &nbs= p; instance.
+
+  @retval EFI_SUCCESS=       The operation is done correctly.
+  @retval Others        &= nbsp;   The operation fails.
+
+= **/
+EFI_STATUS
+SdCardVoltageSwitch (
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL     &nb= sp;*PassThru
+  )
+{
+  = ;EFI_SD_MMC_COMMAND_BLOCK         &= nbsp;    SdMmcCmdBlk;
+  EFI_SD_MMC_= STATUS_BLOCK           &n= bsp;   SdMmcStatusBlk;
+  EFI_SD_MMC_PASS= _THRU_COMMAND_PACKET   Packet;
+  EFI_STATUS &= nbsp;           &nbs= p;            &= nbsp; Status;
+
+  ZeroMem (&SdMm= cCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&SdMmcSt= atusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem (&Pack= et, sizeof (Packet));
+
+  Packet.SdMmcCmd= Blk    =3D &SdMmcCmdBlk;
+  Packet.Sd= MmcStatusBlk =3D &SdMmcStatusBlk;
+  Packet.Timeout =        =3D DW_MMC_HC_GENERIC_TIMEOUT;+
+  SdMmcCmdBlk.CommandIndex =3D SD_VOLTAGE= _SWITCH;
+  SdMmcCmdBlk.CommandType  =3D SdMmcComma= ndTypeAc;
+  SdMmcCmdBlk.ResponseType =3D SdMmcResponseT= ypeR1;
+  SdMmcCmdBlk.CommandArgument =3D 0;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &= amp;Packet, NULL);
+
+  return Status;
+}
+
+/**
+  Send= command SET_BUS_WIDTH to the SD device to set the bus width.
+
+  Refer to SD Physical Layer Simplified Spec 4.1 Sec= tion 4.7 for details.
+
+  @param[in] Pass= Thru       A pointer to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+          &nb= sp;            =      instance.
+  @param[in] Rc= a            The rel= ative device address of addressed device.
+  @param[in] = BusWidth       The bus width to be set, it co= uld be 1 or 4.
+
+  @retval EFI_SUCCESS &n= bsp;     The operation is done correctly.
+  @retval Others        &nb= sp;   The operation fails.
+
+**= /
+EFI_STATUS
+SdCardSetBusWidth (
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *P= assThru,
+  IN UINT16      &nbs= p;            &= nbsp;         Rca,
+  IN UINT8          &= nbsp;           &nbs= p;       BusWidth
+  = )
+{
+  EFI_SD_MMC_COMMAND_BLOCK  &nb= sp;           SdMmcC= mdBlk;
+  EFI_SD_MMC_STATUS_BLOCK    &nbs= p;          SdMmcStatusBl= k;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Pa= cket;
+  EFI_STATUS       =             &nb= sp;        Status;
+ =  UINT8           &nb= sp;            =          Value;
= +
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk))= ;
+  ZeroMem (&Packet, sizeof (Packet));
+
+  Packet.SdMmcCmdBlk    =3D &Sd= MmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatus= Blk;
+  Packet.Timeout      &nb= sp; =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+ &nb= sp;SdMmcCmdBlk.CommandIndex =3D SD_APP_CMD;
+  SdMmcCmdB= lk.CommandType  =3D SdMmcCommandTypeAc;
+  SdMmcCmd= Blk.ResponseType =3D SdMmcResponseTypeR1;
+  SdMmcCmdBlk= .CommandArgument =3D (UINT32)Rca << 16;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL);=
+  if (EFI_ERROR (Status)) {
+  &nbs= p; return Status;
+  }
+
+  SdMmcCmdBlk.CommandIndex =3D SD_SET_BUS_WIDTH;
+ &n= bsp;SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeAc;
+ &= nbsp;SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1;
+
+  if (BusWidth =3D=3D 1) {
+   &nbs= p;Value =3D 0;
+  } else if (BusWidth =3D=3D 4) {
+    Value =3D 2;
+  } else {
+    return EFI_INVALID_PARAMETER;
= +  }
+
+  SdMmcCmdBlk.CommandArgument= =3D Value & 0x3;
+
+  Status =3D Pass= Thru->PassThru (PassThru, 0, &Packet, NULL);
+  r= eturn Status;
+}
+
+/**
+  Send command SWITCH_FUNC to the SD device to check switchabl= e
function or
+  switch card function.
+
+  Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for de= tails.
+
+  @param[in]  PassThru &nbs= p;    A pointer to the
EFI_S= D_MMC_PASS_THRU_PROTOCOL
+             =             &nb= sp;  instance.
+  @param[in]  AccessMode =    The value for access mode group.
+  @p= aram[in]  CommandSystem The value for command set group.
+  @param[in]  DriveStrength The value for drive length group.+  @param[in]  PowerLimit    The valu= e for power limit group.
+  @param[in]  Mode  =         Switch or check function.+  @param[out] SwitchResp    The return sw= itch function status.
+
+  @retval EFI_SUC= CESS       The operation is done correctly.+  @retval Others       &nb= sp;    The operation fails.
+
+**/
+EFI_STATUS
+SdCardSwitch (
+  IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *= PassThru,
+  IN     UINT8  &nbs= p;            &= nbsp;          AccessMode= ,
+  IN     UINT8    =             &nb= sp;         CommandSystem,
+  IN     UINT8     = ;            &n= bsp;        DriveStrength,
+  IN     UINT8     &nb= sp;            =         PowerLimit,
+=  IN     BOOLEAN      &nb= sp;            =      Mode,
+     = ;OUT UINT8           &nbs= p;            &= nbsp; *SwitchResp
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOCK       &nb= sp;      SdMmcCmdBlk;
+  E= FI_SD_MMC_STATUS_BLOCK         &nbs= p;     SdMmcStatusBlk;
+  EFI_S= D_MMC_PASS_THRU_COMMAND_PACKET   Packet;
+  EF= I_STATUS            =             &nb= sp;   Status;
+  UINT32    = ;            &n= bsp;            = ;   ModeValue;
+
+  ZeroMem= (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  ZeroMem (&= amp;SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  ZeroMem= (&Packet, sizeof (Packet));
+
+  Pack= et.SdMmcCmdBlk    =3D &SdMmcCmdBlk;
+ &nbs= p;Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;
+  Pack= et.Timeout        =3D DW_MMC_HC_GENERIC_= TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D= SD_SWITCH_FUNC;
+  SdMmcCmdBlk.CommandType  =3D Sd= MmcCommandTypeAdtc;
+  SdMmcCmdBlk.ResponseType =3D SdMm= cResponseTypeR1;
+
+  ModeValue =3D Mode ?= BIT31 : 0;
+  SdMmcCmdBlk.CommandArgument =3D (AccessMo= de & 0xF) |           = ; \
+         &n= bsp;            = ;          ((PowerLimit &= amp; 0xF) << 4) |     \
+  &nb= sp;            =             &nb= sp;    ((DriveStrength & 0xF) << 8) |  \=
+          &nbs= p;            &= nbsp;        ((DriveStrength & = 0xF) << 12) | \
+       &= nbsp;           &nbs= p;            M= odeValue;
+
+  Packet.InDataBuffer  &= nbsp;  =3D SwitchResp;
+  Packet.InTransferLen= gth =3D 64;
+
+  Status =3D PassThru->P= assThru (PassThru, 0, &Packet, NULL);
+
+ &= nbsp;return Status;
+}
+
+/**
+  Send command SEND_STATUS to the addressed SD device to g= et its
status
+  register.
+
+  Re= fer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
+
+  @param[in]  PassThru   &nbs= p;  A pointer to the
EFI_SD_MMC_PASS_T= HRU_PROTOCOL
+  &nb= sp;            =             &nb= sp;instance.
+  @param[in]  Rca    &= nbsp;      The relative device address of add= ressed device.
+  @param[out] DevStatus   &nbs= p; The returned device status.
+
+  @= retval EFI_SUCCESS       The operation is don= e correctly.
+  @retval Others     &= nbsp;      The operation fails.
+
+**/
+EFI_STATUS
+SdCardSendSt= atus (
+  IN     EFI_SD_MMC_PASS_THR= U_PROTOCOL  *PassThru,
+  IN    &nbs= p;UINT16            =             &nb= sp;Rca,
+     OUT UINT32   &nbs= p;            &= nbsp;        *DevStatus
+  )
+{
+  EFI_SD_MMC_COMMAND_BLOC= K             &= nbsp;SdMmcCmdBlk;
+  EFI_SD_MMC_STATUS_BLOCK   = ;            Sd= MmcStatusBlk;
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET &nb= sp; Packet;
+  EFI_STATUS     &= nbsp;           &nbs= p;          Status;
+
+  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCm= dBlk));
+  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcSt= atusBlk));
+  ZeroMem (&Packet, sizeof (Packet));+
+  Packet.SdMmcCmdBlk    = =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &= ;SdMmcStatusBlk;
+  Packet.Timeout    &nb= sp;   =3D DW_MMC_HC_GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandIndex =3D SD_SEND_STATUS;
+=  SdMmcCmdBlk.CommandType  =3D SdMmcCommandTypeAc;
= +  SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1;
+ &= nbsp;SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16;
+
+  Status =3D PassThru->PassThru (PassThru, 0, &am= p;Packet, NULL);
+  if (!EFI_ERROR (Status)) {
+    *DevStatus =3D SdMmcStatusBlk.Resp0;
+  }
+
+  return Status;
+}
+
+/**
+  Send com= mand SEND_TUNING_BLOCK to the SD device for HS200
optimal sampling
+ &nb= sp;point detection.
+
+  It may be sent up= to 40 times until the host finishes the tuning
= procedure.
+
+  Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for d= etails.
+
+  @param[in] PassThru  &nb= sp;    A pointer to the
EFI_= SD_MMC_PASS_THRU_PROTOCOL
+             = ;            &n= bsp;  instance.
+
+  @retval EFI= _SUCCESS       The operation is done correctl= y.
+  @retval Others       = ;     The operation fails.
+
+**/
+EFI_STATUS
+SdCardSendTuningBlk (<= br class=3D"">+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL    &n= bsp; *PassThru
+  )
+{
= +  EFI_SD_MMC_COMMAND_BLOCK        =       SdMmcCmdBlk;
+  EFI_= SD_MMC_STATUS_BLOCK          &= nbsp;    SdMmcStatusBlk;
+  EFI_SD_M= MC_PASS_THRU_COMMAND_PACKET   Packet;
+  EFI_S= TATUS            &nb= sp;            =    Status;
+  UINT8    &nb= sp;            =             &nb= sp;   TuningBlock[64];
+
+  = ;ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+  Ze= roMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+  = ;ZeroMem (&Packet, sizeof (Packet));
+
+ &n= bsp;Packet.SdMmcCmdBlk    =3D &SdMmcCmdBlk;
+  Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk;
+ &n= bsp;Packet.Timeout        =3D DW_MMC_HC_= GENERIC_TIMEOUT;
+
+  SdMmcCmdBlk.CommandI= ndex =3D SD_SEND_TUNING_BLOCK;
+  SdMmcCmdBlk.CommandTyp= e  =3D SdMmcCommandTypeAdtc;
+  SdMmcCmdBlk.Respons= eType =3D SdMmcResponseTypeR1;
+  SdMmcCmdBlk.CommandArg= ument =3D 0;
+
+  Packet.InDataBuffer &nbs= p;   =3D TuningBlock;
+  Packet.InTransfe= rLength =3D sizeof (TuningBlock);
+
+  Sta= tus =3D PassThru->PassThru (PassThru, 0, &Packet, NULL);
+
+  return Status;
+}
+<= br class=3D"">+/**
+  Switch the bus width to specified = width.
+
+  Refer to SD Physical Layer Sim= plified Spec 4.1 Section 4.7 and
+  SD Host Controller S= implified Spec 3.0 section Figure 3-7 for details.
+
+  @param[in] PciIo        &= nbsp; A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ &= nbsp;@param[in] PassThru       A pointer to t= he
EFI_SD_MMC_PASS_THRU_PROTOCOL
<= blockquote type=3D"cite" class=3D"">+       &= nbsp;           &nbs= p;        instance.
+=  @param[in] Rca          = ;  The relative device address to be assigned.
+ &n= bsp;@param[in] BusWidth       The bus width t= o be set, it could be 4 or 8.
+
+  @retval= EFI_SUCCESS       The operation is done corr= ectly.
+  @retval Others      &= nbsp;     The operation fails.
+
+**/
+EFI_STATUS
+SdCardSwitchBusWid= th (
+  IN UINTN       &nb= sp;            =           DevBase,
+  IN EFI_SD_MMC_PASS_THRU_PROTOCOL     &n= bsp;*PassThru,
+  IN UINT16     &nbs= p;            &= nbsp;          Rca,
+  IN BOOLEAN         = ;            &n= bsp;      IsDdr,
+  IN UIN= T8             =             &nb= sp;    BusWidth
+  )
+= {
+  EFI_STATUS       &nbs= p;  Status;
+  UINT32     =          DevStatus;
+
+  Status =3D SdCardSetBusWidth (PassThru, Rca,= BusWidth);
+  if (EFI_ERROR (Status)) {
+=    DEBUG ((
+      D= EBUG_ERROR,
+      "SdCardSwitchBusW= idth: Switch to bus width %d fails with %r\n",
+   =    BusWidth,
+      S= tatus
+      ));
+ &nb= sp;  return Status;
+  }
+
+  Status =3D SdCardSendStatus (PassThru, Rca, &DevStatus= );
+  if (EFI_ERROR (Status)) {
+  &n= bsp; DEBUG ((
+      DEBUG_ERRO= R,
+      "SdCardSwitchBusWidth: Sen= d status fails with %r\n",
+      St= atus
+      ));
+ &nbs= p;  return Status;
+  }
+  = //
+  // Check the switch operation is really successful= or not.
+  //
+  if ((DevStatus >= > 16) !=3D 0) {
+    DEBUG ((
+      DEBUG_ERROR,
+   &= nbsp;  "SdCardSwitchBusWidth: The switch operation fails as DevSt= atus
0x%08x\n",
+      DevStatus
+      ));
+    re= turn EFI_DEVICE_ERROR;
+  }
+
+  Status =3D DwMmcHcSetBusWidth (DevBase, IsDdr, BusWidth);
+
+  return Status;
+}
+
+/**
+  Switch the high speed timing a= ccording to request.
+
+  Refer to SD Phys= ical Layer Simplified Spec 4.1 Section 4.7 for details.
+
+  @param[in] PciIo       &nb= sp;  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param[in] PassThru       A pointer = to the
EFI_SD_MMC_PASS_THRU_PROTOCOL
+      &nb= sp;            =          instance.
+  @param[in] Rca         &= nbsp;  The relative device address to be assigned.
= +  @param[in] S18A         &nb= sp; The boolean to show if it's a UHS-I SD card.
+  = ;@param[in] BusWidths      The bus width of the SD= card.
+
+  @retval EFI_SUCCESS  &nbs= p;    The operation is done correctly.
+ =  @retval Others          =   The operation fails.
+
+**/
+EFI_STATUS
+SdCardSetBusMode (
+  = IN UINTN            =             &nb= sp;     DevBase,
+  IN EFI_SD_M= MC_PASS_THRU_PROTOCOL      *PassThru,
+  IN UINT16          &= nbsp;           &nbs= p;      Rca,
+  IN BOOLEAN=             &n= bsp;            = ;  S18A,
+  IN UINT32     =             &nb= sp;           BusWid= ths
+  )
+{
+  EFI_STAT= US             =       Status;
+  DW_MMC_HC= _SLOT_CAP           *Capa= bility;
+  UINT32       &n= bsp;            = ;   ClockFreq;
+  UINT8    = ;            &n= bsp;       AccessMode;
+ &= nbsp;UINT8           &nbs= p;            S= witchResp[64];
+  DW_MMC_HC_PRIVATE_DATA   &nb= sp;   *Private;
+  BOOLEAN   &n= bsp;            = ;      IsDdr;
+
+=  Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+<= br class=3D"">+  Capability =3D &Private->Capability[0];
+
+  if ((Capability->BusWidth =3D=3D 1) || (= Capability->BusWidth =3D=3D 4)) {
+    BusW= idths &=3D Capability[0].BusWidth;
+  } else {
+    DEBUG ((
+    &nb= sp; DEBUG_ERROR,
+      "SdCard= SetBusMode: BusWidths (%d) in capability are wrong\n",
+ &nbs= p;    Capability->BusWidth
+  &nb= sp;   ));
+    return EFI_INVAL= ID_PARAMETER;
+  }
+
+  = ;if (BusWidths =3D=3D 0) {
+    DEBUG ((
+      DEBUG_ERROR,
+  = ;    "SdCardSetBusMode: Get wrong BusWidths:%d\n",
+      BusWidths
+  &= nbsp;   ));
+    return EFI_INV= ALID_PARAMETER;
+  }
+
+ &nb= sp;if (Private->Capability[0].Ddr50) {
+    = ;IsDdr =3D TRUE;
+  } else {
+   = ; IsDdr =3D FALSE;
+  }
+
+  Status =3D SdCardSwitchBusWidth (DevBase, PassThru, Rca, IsDdr,<= br class=3D"">
BusWidths);
+  if (EFI_ERROR (Status)) {
+  &nbs= p; DEBUG ((
+      DEBUG_ERROR,=
+      "SdCardSetBusMode: Executing= SdCardSwitchBusWidth fails with
%r\n",
+      = ;Status
+      ));
+ &= nbsp;  return Status;
+  }
+
+  //
+  // Get the supported bus speed = from SWITCH cmd return data group #1.
+  //
+  Status =3D SdCardSwitch (PassThru, 0xF, 0xF, 0xF, 0xF, FALSE, Swi= tchResp);
+  if (EFI_ERROR (Status)) {
+ &= nbsp;  return Status;
+  }
+ &nb= sp;//
+  // Calculate supported bus speed/bus width/cloc= k frequency by host and
device
+  // capability.
+ &n= bsp;//
+  ClockFreq =3D 0;
+  if (S18= A && (Capability->Sdr104 !=3D 0) && ((SwitchResp[13] &am= p; BIT3) !=3D 0)) {
+    ClockFreq =3D 208;+    AccessMode =3D 3;
+  } e= lse if (S18A && (Capability->Sdr50 !=3D 0) &&
+            =  ((SwitchResp[13] & BIT2) !=3D 0)) {
+   &= nbsp;ClockFreq =3D 100;
+    AccessMode =3D 2;=
+  } else if (S18A && (Capability->Ddr50 != =3D 0) &&
+       &nbs= p;     ((SwitchResp[13] & BIT4) !=3D 0)) {
+    ClockFreq =3D 50;
+  &nbs= p; AccessMode =3D 4;
+  } else if ((SwitchResp[13] = & BIT1) !=3D 0) {
+    ClockFreq =3D 50;+    AccessMode =3D 1;
+  } = else {
+    ClockFreq =3D 25;
+ =    AccessMode =3D 0;
+  }
+=
+  Status =3D SdCardSwitch (PassThru, AccessMode, 0xF, = 0xF, 0xF, TRUE,
SwitchResp);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((SwitchResp[16] & 0xF) !=3D AccessMo= de) {
+    DEBUG ((
+  &nbs= p;   DEBUG_ERROR,
+     &n= bsp;"SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d fails!
The Switch response is 0x%1x\n",
+      AccessMode,+      ClockFreq,
+ &nbs= p;    SwitchResp[16] & 0xF
+  &n= bsp;   ));
+    return EFI_DEVI= CE_ERROR;
+  }
+
+  DEB= UG ((
+    DEBUG_INFO,
+  &= nbsp; "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d \n",
+    AccessMode,
+   &nbs= p;ClockFreq
+    ));
+
+  Status =3D DwMmcHcClockSupply (DevBase, ClockFreq * 1000, *C= apability);
+  if (EFI_ERROR (Status)) {
+=    return Status;
+  }
++  return Status;
+}
+
+EFI_STATUS
+SdCardIdentification (
+ &= nbsp;IN DW_MMC_HC_PRIVATE_DATA        &n= bsp;    *Private
+  )
= +{
+  EFI_STATUS       &nb= sp;            =  Status;
+  UINTN      &nb= sp;            =        DevBase;
+  EF= I_SD_MMC_PASS_THRU_PROTOCOL  *PassThru;
+  UINT32 &= nbsp;           &nbs= p;           Ocr;+  UINT16         =             &nb= sp;   Rca;
+  BOOLEAN    &= nbsp;           &nbs= p;       Xpc;
+  BOOL= EAN             = ;           S18r;+  UINT64         =             &nb= sp;   MaxCurrent;
+  SD_SCR   &= nbsp;           &nbs= p;         Scr;
= +  SD_CSD           =             &nb= sp; Csd;
+
+  DevBase   &nb= sp;=3D Private->DevBase;
+  PassThru =3D &Private= ->PassThru;
+  //
+  // 1. Send Cm= d0 to the device
+  //
+  Status =3D = SdCardReset (PassThru);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+    &= nbsp; DEBUG_INFO,
+      "SdCar= dIdentification: Executing Cmd0 fails with %r\n",
+  &nb= sp;   Status
+      )= );
+    return Status;
+  }=
+  MicroSecondDelay (10000);
+  //+  // 2. Send Cmd8 to the device
+  //=
+  Status =3D SdCardVoltageCheck (PassThru, 0x1, 0xFF);=
+  if (EFI_ERROR (Status)) {
+  &nbs= p; DEBUG ((
+      DEBUG_INFO,<= br class=3D"">+      "SdCardIdentification: Execut= ing Cmd8 fails with %r\n",
+      St= atus
+      ));
+ &nbs= p;  return Status;
+  }
+  = //
+  // 3. Send Acmd41 with voltage window 0 to the dev= ice
+  //
+  Status =3D SdCardSendOpC= ond (PassThru, 0, 0, FALSE, FALSE, FALSE, &Ocr);
+  = if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_INFO,
+  &= nbsp;   "SdCardIdentification: Executing SdCardSendOpCond fa= ils with %r\n",
+      Status
+      ));
+   &nb= sp;return EFI_DEVICE_ERROR;
+  }
+
+  if (Private->Capability[0].Voltage33 !=3D 0) {
+    //
+    // Support = 3.3V
+    //
+    = ;MaxCurrent =3D ((UINT32)Private->MaxCurrent[0] & 0xFF) * 4;
+    S18r =3D FALSE;
+  } else if = (Private->Capability[0].Voltage30 !=3D 0) {
+   =  //
+    // Support 3.0V
+ =    //
+    MaxCurrent =3D (((UI= NT32)Private->MaxCurrent[0] >> 8) & 0xFF) * 4;
+=    S18r =3D FALSE;
+  } else if (Private= ->Capability[0].Voltage18 !=3D 0) {
+    //=
+    // Support 1.8V
+  &n= bsp; //
+    MaxCurrent =3D (((UINT32)Pri= vate->MaxCurrent[0] >> 16) & 0xFF) * 4;
+  =   S18r =3D TRUE;
+  } else {
+ &= nbsp;  ASSERT (FALSE);
+    return E= FI_DEVICE_ERROR;
+  }
+
+ &n= bsp;if (MaxCurrent >=3D 150) {
+    Xpc =3D= TRUE;
+  } else {
+    Xpc= =3D FALSE;
+  }
+
+  /= /
+  // 4. Repeatly send Acmd41 with supply voltage wind= ow to the device.
+  //    Note here we o= nly support the cards complied with SD physical
+  // &n= bsp;  layer simplified spec version 2.0 and version 3.0 and above= .
+  //
+  do {
+  = ;  Status =3D SdCardSendOpCond (PassThru, 0, Ocr, S18r, Xpc, TRUE= , &Ocr);
+    if (EFI_ERROR (Status)) {+      DEBUG ((
+  =       DEBUG_ERROR,
+  &nbs= p;     "SdCardIdentification: SdCardSendOpCond fai= ls with %r Ocr %x, S18r
%x, Xpc %x\n",
+      = ;  Status,
+       &n= bsp;Ocr,
+        S18r,+        Xpc
+=        ));
+   =    return EFI_DEVICE_ERROR;
+   &nbs= p;}
+  } while ((Ocr & BIT31) =3D=3D 0);
+
+  Status =3D SdCardAllSendCid (PassThru);
+  if (EFI_ERROR (Status)) {
+    = DEBUG ((
+      DEBUG_ERROR,
+      "SdCardIdentification: Executing SdC= ardAllSendCid fails with %r\n",
+     &nb= sp;Status
+      ));
+=    return Status;
+  }
++  Status =3D SdCardSetRca (PassThru, &Rca);
+  if (EFI_ERROR (Status)) {
+    = DEBUG ((
+      DEBUG_ERROR,
+      "SdCardIdentification: Executing SdC= ardSetRca fails with %r\n",
+      S= tatus
+      ));
+ &nb= sp;  return Status;
+  }
+
+  Status =3D SdCardGetCsd (PassThru, Rca, &Csd);
+  if (EFI_ERROR (Status)) {
+    = DEBUG ((
+      DEBUG_ERROR,
+      "SdCardIdentification: Executing SdC= ardGetCsd fails with %r\n",
+      S= tatus
+      ));
+ &nb= sp;  return Status;
+  }
+
+  Status =3D SdCardSelect (PassThru, Rca);
+ &= nbsp;if (EFI_ERROR (Status)) {
+    DEBUG ((+      DEBUG_ERROR,
+ &= nbsp;    "SdCardIdentification: Selecting card fails wi= th %r\n",
+      Status
+      ));
+    ret= urn Status;
+  }
+
+  S= tatus =3D SdCardGetScr (PassThru, Rca, &Scr);
+  if = (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+  &= nbsp;   "SdCardIdentification: Executing SdCardGetScr fails = with %r\n",
+      Status
+      ));
+   &nbs= p;return Status;
+  }
+
+ &n= bsp;//
+  // Enter Data Tranfer Mode.
+ &n= bsp;//
+  DEBUG ((DEBUG_INFO, "SdCardIdentification: Fou= nd a SD device\n"));
+  Private->Slot[0].CardType =3D= SdCardType;
+
+  Status =3D SdCardSetBusM= ode (DevBase, PassThru, Rca, S18r,
Scr.SdBusWidt= hs);
+  if (EFI_ERR= OR (Status)) {
+    return Status;
+  }
+
+  Private->Slot[0].Init= ialized =3D TRUE;
+
+  return Status;
+}
--
2.12.3




--Apple-Mail=_F3B2F092-F088-4876-A0B5-24429692734D--