.../BroxtonPlatformPkg/PlatformDsc/Components.dsc | 11 +- Platform/BroxtonPlatformPkg/PlatformPkg.fdf | 10 +- .../Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c | 162 ++ .../Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c | 1529 ++++++++++++ .../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c | 613 +++++ .../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h | 585 +++++ .../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf | 59 + .../Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c | 159 ++ .../Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c | 666 ++++++ .../Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c | 2524 ++++++++++++++++++++ .../Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c | 605 +++++ .../MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf | 71 + .../Sdio/Dxe/SD/SdControllerDxe/ComponentName.c | 233 ++ .../Sdio/Dxe/SD/SdControllerDxe/ComponentName.h | 145 ++ .../Sdio/Dxe/SD/SdControllerDxe/SdController.c | 1804 ++++++++++++++ .../Sdio/Dxe/SD/SdControllerDxe/SdController.h | 314 +++ .../Dxe/SD/SdControllerDxe/SdControllerDxe.inf | 59 + .../Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c | 638 +++++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c | 384 +++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c | 219 ++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h | 145 ++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c | 547 +++++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c | 1661 +++++++++++++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c | 324 +++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h | 466 ++++ .../Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf | 64 + 26 files changed, 13989 insertions(+), 8 deletions(-) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf
Add Platform eMMC/SD driver.
This reverts commit 66d48af2d24645263b8068e261abc58d84cc2b93.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: lushifex <shifeix.a.lu@intel.com>
---
.../BroxtonPlatformPkg/PlatformDsc/Components.dsc | 11 +-
Platform/BroxtonPlatformPkg/PlatformPkg.fdf | 10 +-
.../Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c | 162 ++
.../Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c | 1529 ++++++++++++
.../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c | 613 +++++
.../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h | 585 +++++
.../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf | 59 +
.../Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c | 159 ++
.../Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c | 666 ++++++
.../Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c | 2524 ++++++++++++++++++++
.../Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c | 605 +++++
.../MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf | 71 +
.../Sdio/Dxe/SD/SdControllerDxe/ComponentName.c | 233 ++
.../Sdio/Dxe/SD/SdControllerDxe/ComponentName.h | 145 ++
.../Sdio/Dxe/SD/SdControllerDxe/SdController.c | 1804 ++++++++++++++
.../Sdio/Dxe/SD/SdControllerDxe/SdController.h | 314 +++
.../Dxe/SD/SdControllerDxe/SdControllerDxe.inf | 59 +
.../Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c | 638 +++++
.../Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c | 384 +++
.../Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c | 219 ++
.../Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h | 145 ++
.../Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c | 547 +++++
.../Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c | 1661 +++++++++++++
.../Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c | 324 +++
.../Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h | 466 ++++
.../Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf | 64 +
26 files changed, 13989 insertions(+), 8 deletions(-)
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h
create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf
diff --git a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc b/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc
index 7efcdb4..1322576 100644
--- a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc
+++ b/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc
@@ -386,11 +386,14 @@
$(PLATFORM_PACKAGE_COMMON)/Console/LpssUartSerialDxe/LpssUartSerialDxe.inf
#
- # eMMC/SD Card
+ # SDIO
#
- MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
- MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
- MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
+ $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf
+
+ $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf
+
+ $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf
+ $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf
!if $(ACPI50_ENABLE) == TRUE
diff --git a/Platform/BroxtonPlatformPkg/PlatformPkg.fdf b/Platform/BroxtonPlatformPkg/PlatformPkg.fdf
index 73174af..ac09ac3 100644
--- a/Platform/BroxtonPlatformPkg/PlatformPkg.fdf
+++ b/Platform/BroxtonPlatformPkg/PlatformPkg.fdf
@@ -434,14 +434,16 @@ APRIORI DXE {
INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
#
- # eMMC/SD Card
+ # SDIO
#
!if $(EMMC_DRIVER_ENABLE) == TRUE
- INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
- INF MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
- INF MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
+ INF $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf
+ INF $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf
!endif
+ INF $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf
+ INF $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf
+
INF MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
INF IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c
new file mode 100644
index 0000000..f099fa8
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c
@@ -0,0 +1,162 @@
+/** @file
+ Component Name protocol implementation
+
+ Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "MmcHostDriver.h"
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gMmcHostComponentName = {
+ MmcHostComponentNameGetDriverName,
+ MmcHostComponentNameGetControllerName,
+ "eng"
+};
+
+
+static EFI_UNICODE_STRING_TABLE mMmcHostDriverNameTable[] = {
+ { "eng", L"UEFI MMC Host Controller Driver" },
+ { NULL , NULL }
+};
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language 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
+MmcHostComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString (
+ Language,
+ gMmcHostComponentName.SupportedLanguages,
+ mMmcHostDriverNameTable,
+ DriverName
+ );
+}
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device 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 name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language
+ specified by Language from the point of view of the
+ driver specified by This.
+
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in the
+ language specified by Language for 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
+MmcHostComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle, OPTIONAL
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ MMCHOST_DATA *MmcHostData;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiMmcHostIoProtocolGuid,
+ (VOID **) &MmcHostIo,
+ gMmcHostDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (MmcHostIo);
+
+ return LookupUnicodeString (
+ Language,
+ gMmcHostComponentName.SupportedLanguages,
+ MmcHostData->ControllerNameTable,
+ ControllerName
+ );
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c
new file mode 100644
index 0000000..f3cd50e
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c
@@ -0,0 +1,1529 @@
+/** @file
+ MMC Host I/O protocol implementation
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "MmcHostDriver.h"
+
+#define MMC_HOST_DEBUG(a) do { \
+ if (MmcHostData->EnableVerboseDebug) { \
+ DEBUG (a); \
+ } \
+ } while (0);
+
+UINT32 gMmcHostDebugLevel = DEBUG_INFO;
+
+/**
+ Get Error Reason
+
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] ErrorCode Mmchost specific error code
+
+ @retval EFI_DEVICE_ERROR
+ @retval EFI_TIMEOUT
+ @retval EFI_CRC_ERROR
+
+**/
+STATIC
+EFI_STATUS
+GetErrorReason (
+ IN UINT16 CommandIndex,
+ IN UINT16 ErrorCode
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_DEVICE_ERROR;
+ DEBUG ((gMmcHostDebugLevel, "[%2d] -- ", CommandIndex));
+
+ if (ErrorCode & BIT0) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((gMmcHostDebugLevel, "Command Timeout Error"));
+ }
+
+ if (ErrorCode & BIT1) {
+ Status = EFI_CRC_ERROR;
+ DEBUG ((gMmcHostDebugLevel, "Command CRC Error"));
+ }
+
+ if (ErrorCode & BIT2) {
+ DEBUG ((gMmcHostDebugLevel, "Command End Bit Error"));
+ }
+
+ if (ErrorCode & BIT3) {
+ DEBUG ((gMmcHostDebugLevel, "Command Index Error"));
+ }
+ if (ErrorCode & BIT4) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((gMmcHostDebugLevel, "Data Timeout Error"));
+ }
+
+ if (ErrorCode & BIT5) {
+ Status = EFI_CRC_ERROR;
+ DEBUG ((gMmcHostDebugLevel, "Data CRC Error"));
+ }
+
+ if (ErrorCode & BIT6) {
+ DEBUG ((gMmcHostDebugLevel, "Data End Bit Error"));
+ }
+
+ if (ErrorCode & BIT7) {
+ DEBUG ((gMmcHostDebugLevel, "Current Limit Error"));
+ }
+
+ if (ErrorCode & BIT8) {
+ DEBUG ((gMmcHostDebugLevel, "Auto CMD12 Error"));
+ }
+
+ if (ErrorCode & BIT9) {
+ DEBUG ((gMmcHostDebugLevel, "ADMA Error"));
+ }
+
+ DEBUG ((gMmcHostDebugLevel, "\n"));
+
+ return Status;
+}
+
+
+/**
+ Read MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Width Signifies the width of the memory or I/O operations.
+ @param[in] Offset Offset of the MMC Card
+ @param[in, out] Buffer Buffer read from MMC Card
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+STATIC
+EFI_STATUS
+MmcHostRead (
+ IN MMCHOST_DATA *MmcHost,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Offset,
+ IN OUT VOID *Buffer
+ )
+{
+ return MmcHost->PciIo->Mem.Read (
+ MmcHost->PciIo,
+ Width,
+ 0,
+ (UINT64) Offset,
+ 1,
+ Buffer
+ );
+}
+
+
+/**
+ Read MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the MMC Card
+
+ @retval Data Data read from MMC Card
+
+**/
+UINT8
+MmcHostRead8 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset
+ )
+{
+ UINT8 Data;
+
+ MmcHostRead (MmcHost, EfiPciIoWidthUint8, Offset, &Data);
+
+ return Data;
+}
+
+
+/**
+ Read MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the MMC Card
+
+ @retval Data Data read from MMC Card
+
+**/
+UINT16
+MmcHostRead16 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset
+ )
+{
+ UINT16 Data;
+
+ MmcHostRead (MmcHost, EfiPciIoWidthUint16, Offset, &Data);
+
+ return Data;
+}
+
+
+/**
+ Read MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the MMC Card
+
+ @retval Data Data read from MMC Card
+
+**/
+UINT32
+MmcHostRead32 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset
+ )
+{
+ UINT32 Data;
+
+ MmcHostRead (MmcHost, EfiPciIoWidthUint32, Offset, &Data);
+
+ return Data;
+}
+
+
+/**
+ Dump MMC host registers
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+
+ @retval None
+
+**/
+VOID
+DebugPrintMmcHostRegisters (
+ IN MMCHOST_DATA *MmcHost
+ )
+{
+#ifdef VERBOSE_REGISTER_ACCESS_DEBUG
+ UINTN Loop;
+
+ if (!MmcHost->EnableVerboseDebug) {
+ return;
+ }
+
+ for (Loop = 0; Loop < 0x40; Loop++) {
+ DEBUG ((EFI_D_INFO, " %02x", MmcHostRead8 (MmcHost, Loop)));
+ if ((Loop % 0x10) == 0xf) {
+ DEBUG ((EFI_D_INFO, "\n"));
+ }
+ }
+
+#endif
+}
+
+
+/**
+ Dump MMC host registers before write
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+
+ @retval None
+
+**/
+VOID
+DebugPreMmcHostWrite (
+ IN MMCHOST_DATA *MmcHost
+ )
+{
+#ifdef VERBOSE_REGISTER_ACCESS_DEBUG
+ STATIC UINTN DebugCount = 0;
+
+ if (!MmcHost->EnableVerboseDebug) {
+ return;
+ }
+
+ DebugCount++;
+
+ if (DebugCount < 0x100) {
+ DEBUG ((EFI_D_INFO, "MMC HOST Registers before write:\n"));
+ DebugPrintMmcHostRegisters (MmcHost);
+ }
+#endif
+}
+
+
+/**
+ Dump MMC host registers after write
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+
+ @retval None
+
+**/
+VOID
+DebugPostMmcHostWrite (
+ IN MMCHOST_DATA *MmcHost
+ )
+{
+#ifdef VERBOSE_REGISTER_ACCESS_DEBUG
+ STATIC UINTN DebugCount = 0;
+
+ if (!MmcHost->EnableVerboseDebug) {
+ return;
+ }
+
+ DebugCount++;
+
+ if (DebugCount < 0x10) {
+ DEBUG ((EFI_D_INFO, "MMC HOST Registers after write:\n"));
+ DebugPrintMmcHostRegisters (MmcHost);
+ }
+#endif
+}
+
+
+/**
+ Write MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Width Signifies the width of the memory or I/O operations.
+ @param[in] Offset Offset of the MMC Card
+ @param[in, out] Buffer Buffer read from MMC Card
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+STATIC
+EFI_STATUS
+MmcHostWrite (
+ IN MMCHOST_DATA *MmcHost,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Offset,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ DebugPreMmcHostWrite (MmcHost);
+ Status = MmcHost->PciIo->Mem.Write (
+ MmcHost->PciIo,
+ Width,
+ 0,
+ (UINT64) Offset,
+ 1,
+ Buffer
+ );
+
+ DebugPostMmcHostWrite (MmcHost);
+
+ return Status;
+}
+
+
+/**
+ Write MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the MMC Card
+ @param[in] Data Data write to MMC Card
+
+ @retval Data Written to MmcHost
+
+**/
+UINT8
+MmcHostWrite8 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset,
+ IN UINT8 Data
+ )
+{
+ MmcHostWrite (MmcHost, EfiPciIoWidthUint8, Offset, &Data);
+
+ return Data;
+}
+
+
+/**
+ Write MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the MMC Card
+ @param[in] Data Data write to MMC Card
+
+ @retval Data Data written to MMC Card
+
+**/
+UINT16
+MmcHostWrite16 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset,
+ IN UINT16 Data
+ )
+{
+ MmcHostWrite (MmcHost, EfiPciIoWidthUint16, Offset, &Data);
+
+ return Data;
+}
+
+
+/**
+ Write MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the MMC Card
+ @param[in] Data Data write to MMC Card
+
+ @retval Data Data written to MMC Card
+
+**/
+UINT32
+MmcHostWrite32 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset,
+ IN UINT32 Data
+ )
+{
+ MmcHostWrite (MmcHost, EfiPciIoWidthUint32, Offset, &Data);
+
+ return Data;
+}
+
+
+/**
+ Check Controller Version
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+
+ @retval Data Written to MmcHost
+
+**/
+UINT32
+CheckControllerVersion (
+ IN MMCHOST_DATA *MmcHost
+ )
+{
+ UINT16 Data16;
+
+ Data16 = MmcHostRead16 (MmcHost, MMIO_CTRLRVER);
+ DEBUG ((EFI_D_INFO, "CheckControllerVersion: %x \n", Data16 & 0xFF));
+
+ return (Data16 & 0xFF);
+}
+
+
+/**
+ Power on/off the LED associated with the slot
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Enable TRUE to set LED on, FALSE to set LED off
+
+ @retval EFI_SUCCESS
+
+**/
+STATIC
+EFI_STATUS
+HostLEDEnable (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ MMCHOST_DATA *MmcHostData;
+ UINT8 Data;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+ Data = MmcHostRead8 (MmcHostData, MMIO_HOSTCTL);
+
+ if (Enable) {
+ //
+ //LED On
+ //
+ Data |= BIT0;
+ } else {
+ //
+ //LED Off
+ //
+ Data &= ~BIT0;
+ }
+
+ MmcHostWrite8 (MmcHostData, MMIO_HOSTCTL, Data);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The main function used to send the command to the card inserted into the MMC host
+ slot.
+ It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] Argument Command argument to set the argument field of command register
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out
+ @param[in] Buffer Contains the data read from / write to the device
+ @param[in] BufferSize The size of the buffer
+ @param[in] ResponseType RESPONSE_TYPE
+ @param[in] TimeOut Time out value in 1 ms unit
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SendCommand (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ MMCHOST_DATA *MmcHostData;
+ UINT32 ResponseDataCount;
+ UINT16 Data16;
+ UINT32 Data32;
+ UINT64 Data64;
+ UINT8 Index;
+ BOOLEAN CommandCompleted;
+ INT32 Timeout = 1000;
+
+ Status = EFI_SUCCESS;
+ ResponseDataCount = 1;
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ if (Buffer != NULL && DataType == NoData) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((gMmcHostDebugLevel, "SendCommand: Invalid parameter -> \n"));
+ goto Exit;
+ }
+
+ if (((UINTN) Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN) NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((gMmcHostDebugLevel, "SendCommand: Invalid parameter -> \n"));
+ goto Exit;
+ }
+
+ DEBUG ((DEBUG_INFO, "SendCommand: CMD%d \n", CommandIndex));
+ if (MmcHostData->EnableVerboseDebug) {
+ DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C)));
+ DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C)));
+ DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C)));
+ DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C)));
+ DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C)));
+ DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C)));
+ }
+
+ //
+ // Check CMD INHIBIT and DATA INHIBIT before send command
+ //
+ do {
+ Data32 = MmcHostRead32 (MmcHostData, MMIO_PSTATE);
+ if (MmcHostData->EnableVerboseDebug) {
+ DEBUG ((EFI_D_INFO, "Wait CMD INHIBIT %x\n",Data32 ));
+ }
+ } while (Timeout-- > 0 && Data32 & BIT0);
+
+ Timeout = 1000;
+ do {
+ Data32 = MmcHostRead32 (MmcHostData, MMIO_PSTATE);
+ if (MmcHostData->EnableVerboseDebug) {
+ DEBUG ((EFI_D_INFO, "Wait DATA INHIBIT %x\n",Data32 ));
+ }
+ } while (Timeout-- >0 && Data32 & BIT1);
+
+ //
+ //Clear status bits
+ //
+ MMC_HOST_DEBUG ((EFI_D_INFO, "NINTSTS(0x30) <- 0x%x\n", (UINTN) 0xffff));
+ MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, 0xffff);
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS (0x30): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_NINTSTS)));
+
+ MMC_HOST_DEBUG ((EFI_D_INFO, "ERINTSTS <- 0x%x\n", (UINTN) 0xffff));
+ MmcHostWrite16 (MmcHostData, MMIO_ERINTSTS, 0xffff);
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: ERINTSTS (0x32): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_ERINTSTS)));
+
+ Data16 = MmcHostRead16 (MmcHostData, MMIO_NINTEN);
+ MmcHostWrite16 (MmcHostData, MMIO_NINTEN, (Data16 | BIT3));
+ MMC_HOST_DEBUG ((DEBUG_INFO, "SendCommand: NINTEN (0x34) <- 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_NINTEN)));
+ MMC_HOST_DEBUG ((DEBUG_INFO, "SendCommand: DMAADR (0x00) <- 0x%x\n", (UINTN) Buffer));
+ MmcHostWrite32 (MmcHostData, MMIO_DMAADR, (UINT32) (UINTN) Buffer);
+
+ if (Buffer != NULL) {
+ Data16 = MmcHostRead16 (MmcHostData, MMIO_BLKSZ);
+ Data16 &= ~(0xFFF);
+ if (BufferSize <= MmcHostData->BlockLength) {
+ Data16 |= BufferSize;
+ } else {
+ Data16 |= MmcHostData->BlockLength;
+ }
+ Data16 |= 0x7000; // Set to 512KB for SDMA block size
+ } else {
+ Data16 = 0;
+ }
+
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: BLKSZ(0x04) <- 0x%x\n", Data16));
+ MmcHostWrite16 (MmcHostData, MMIO_BLKSZ, Data16);
+
+ if (Buffer != NULL) {
+ if (BufferSize <= MmcHostData->BlockLength) {
+ Data16 = 1;
+ } else {
+ Data16 = (UINT16) (BufferSize / MmcHostData->BlockLength);
+ }
+ } else {
+ Data16 = 0;
+ }
+
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: BLKCNT(0x06) <- 0x%x\n", Data16));
+ MmcHostWrite16 (MmcHostData, MMIO_BLKCNT, Data16);
+
+ //
+ // Argument
+ //
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: CMDARG (0x08) <- 0x%x\n", Argument));
+ MmcHostWrite32 (MmcHostData, MMIO_CMDARG, Argument);
+
+ //
+ // Transfer Mode
+ //
+ Data16 = MmcHostRead16 (MmcHostData, MMIO_XFRMODE);
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: XFRMODE (0x0C) mode read 0x%x\n", Data16));
+
+ //
+ // BIT0 DMA Enable
+ // BIT2 Auto Cmd12
+ //
+ if (DataType == InData) {
+ Data16 |= BIT4 | BIT0;
+ } else if (DataType == OutData) {
+ Data16 &= ~BIT4;
+ Data16 |= BIT0;
+ } else {
+ Data16 &= ~(BIT4 | BIT0);
+ }
+
+ if (BufferSize <= MmcHostData->BlockLength) {
+ Data16 &= ~ (BIT5 | BIT1 | BIT2);
+ } else {
+ if (MmcHostData->IsAutoStopCmd && !MmcHostData->IsEmmc) {
+ Data16 |= (BIT5 | BIT1 | BIT2);
+ } else {
+ Data16 |= (BIT5 | BIT1);
+ }
+ }
+ if (CommandIndex == SEND_EXT_CSD) {
+ Data16 |= BIT1;
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand:Enable bit 1, XFRMODE <- 0x%x\n", Data16));
+ }
+
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: XFRMODE (0x0C) <- 0x%x\n", Data16));
+ MmcHostWrite16 (MmcHostData, MMIO_XFRMODE, Data16);
+
+ switch (ResponseType) {
+ case ResponseNo:
+ Data16 = (CommandIndex << 8);
+ ResponseDataCount = 0;
+ break;
+
+ case ResponseR1:
+ case ResponseR5:
+ case ResponseR6:
+ case ResponseR7:
+ Data16 = (CommandIndex << 8) | BIT1 | BIT4| BIT3;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR1b:
+ case ResponseR5b:
+ Data16 = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR2:
+ Data16 = (CommandIndex << 8) | BIT0 | BIT3;
+ ResponseDataCount = 4;
+ break;
+
+ case ResponseR3:
+ case ResponseR4:
+ Data16 = (CommandIndex << 8) | BIT1;
+ ResponseDataCount = 1;
+ break;
+
+ default:
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (DataType != NoData) {
+ Data16 |= BIT5;
+ }
+
+ HostLEDEnable (This, TRUE);
+
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: SDCMD(0x0E) <- 0x%x\n", Data16));
+ CommandCompleted = FALSE;
+ MmcHostWrite16 (MmcHostData, MMIO_SDCMD, Data16);
+
+ if (MmcHostData->EnableVerboseDebug) {
+ DEBUG ((EFI_D_INFO, "After write to Command\n"));
+ DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C)));
+ DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C)));
+ DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C)));
+ DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C)));
+ DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C)));
+ DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C)));
+ }
+
+ TimeOut *= 1000; //ms to us conversion
+ do {
+ Data16 = MmcHostRead16 (MmcHostData, MMIO_ERINTSTS);
+ if (MmcHostData->EnableVerboseDebug && (Data16 != 0)) {
+ DEBUG ((EFI_D_INFO, "SendCommand: ERINTSTS (0x32): 0x%x\n", Data16));
+ DEBUG ((EFI_D_INFO, "SendCommand: ERINTEN (0x36): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_ERINTEN)));
+ DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS (0x30): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_NINTSTS)));
+ DEBUG ((EFI_D_INFO, "SendCommand: NINTEN (0x34): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_NINTEN)));
+ }
+
+ if ((Data16 & 0x17FF) != 0) {
+ Status = GetErrorReason (CommandIndex, Data16);
+ DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C)));
+ DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C)));
+ DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C)));
+ DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C)));
+ DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C)));
+ DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C)));
+ goto Exit;
+ }
+
+ Data16 = MmcHostRead16 (MmcHostData, MMIO_NINTSTS) & 0x1ff;
+ if (MmcHostData->EnableVerboseDebug && (Data16 > 1)) {
+ DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS (0x30): 0x%x\n", Data16));
+ }
+
+ if ((Data16 & BIT0) == BIT0) {
+ //
+ // Command completed
+ //
+ CommandCompleted = TRUE;
+
+ MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, BIT0);
+
+ if ((DataType == NoData) && (ResponseType != ResponseR1b)) {
+ break;
+ }
+ }
+
+ if (CommandCompleted) {
+ //
+ // DMA interrupted
+ //
+ if ((Data16 & BIT3) == BIT3) {
+ MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, BIT3);
+ Data32 = MmcHostRead32 (MmcHostData, MMIO_DMAADR);
+ MMC_HOST_DEBUG ((DEBUG_INFO, "SendCommand: DMAADR (0x00) <- 0x%x\n", Data32));
+ MmcHostWrite32 (MmcHostData, MMIO_DMAADR, Data32);
+ }
+
+ //
+ // Transfer completed
+ //
+ if ((Data16 & BIT1) == BIT1) {
+ MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, BIT1);
+ break;
+ }
+ }
+
+ gBS->Stall (1);
+ TimeOut --;
+
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((gMmcHostDebugLevel, "SendCommand: Time out \n"));
+ goto Exit;
+ }
+
+ if (ResponseData != NULL) {
+ UINT32 *ResDataPtr = NULL;
+
+ ResDataPtr = ResponseData;
+ for (Index = 0; Index < ResponseDataCount; Index++) {
+ *ResDataPtr = MmcHostRead32 (MmcHostData, MMIO_RESP + Index * 4);
+ ResDataPtr++;
+ }
+ MMC_HOST_DEBUG ((EFI_D_INFO, "Reponse Data 0: RESPONSE (0x10) <- 0x%x\n", *ResponseData));
+
+ if (ResponseType == ResponseR2) {
+ //
+ // Adjustment for R2 response
+ //
+ Data32 = 1;
+ for (Index = 0; Index < ResponseDataCount; Index++) {
+ Data64 = LShiftU64 (*ResponseData, 8);
+ *ResponseData = (UINT32) ((Data64 & 0xFFFFFFFF) | Data32);
+ Data32 = (UINT32) RShiftU64 (Data64, 32);
+ ResponseData++;
+ }
+ }
+ }
+
+ if (MmcHostData->EnableVerboseDebug) {
+ DEBUG ((EFI_D_INFO, "Before Exit Send Command\n"));
+ DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C)));
+ DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C)));
+ DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C)));
+ DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C)));
+ DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C)));
+ DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C)));
+ }
+
+Exit:
+ HostLEDEnable (This, FALSE);
+ MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: Status -> %r\n", Status));
+
+ return Status;
+}
+
+
+/**
+ Set clock frequency of the host, the actual frequency
+ may not be the same as MaxFrequencyInKHz. It depends on
+ the max frequency the host can support, divider, and host
+ speed mode.
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] MaxFrequency Max frequency in HZ
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetClockFrequency (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 MaxFrequency
+ )
+{
+ UINT16 Data16;
+ UINT32 Frequency;
+ UINT32 Divider = 0;
+ MMCHOST_DATA *MmcHostData;
+ UINT32 TimeOutCount;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: BaseClockInMHz = %d \n", MmcHostData->BaseClockInMHz));
+
+ Frequency = (MmcHostData->BaseClockInMHz * 1000 * 1000) / MaxFrequency;
+ DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: FrequencyInHz = %d \n", Frequency));
+
+ if ((MmcHostData->BaseClockInMHz * 1000 * 1000 % MaxFrequency) != 0) {
+ Frequency += 1;
+ }
+
+ Divider = 1;
+ while (Frequency > Divider) {
+ Divider = Divider * 2;
+ }
+
+ if (Divider >= 0x400) {
+ Divider = 0x200;
+ }
+ DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: before shift: Base Clock Divider = 0x%x \n", Divider));
+ Divider = Divider >> 1;
+ DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: before shift: Base Clock Divider = 0x%x \n", Divider));
+
+ MmcHostData->CurrentClockInKHz = (MmcHostData->BaseClockInMHz * 1000);
+ if (Divider != 0) {
+ MmcHostData->CurrentClockInKHz = MmcHostData->CurrentClockInKHz / (Divider * 2);
+ }
+
+ if (2 == CheckControllerVersion (MmcHostData)) {
+ Data16 = (UINT16) ((Divider & 0xFF) << 8 | (((Divider & 0xFF00) >>8)<<6));
+ } else {
+ Data16 = (UINT16) ( Divider << 8);
+ }
+
+ DEBUG ((gMmcHostDebugLevel,
+ "SetClockFrequency: base=%dMHz, clkctl=0x%04x, f=%dKHz\n",
+ MmcHostData->BaseClockInMHz,
+ Data16,
+ MmcHostData->CurrentClockInKHz
+ ));
+ DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: set MMIO_CLKCTL value = 0x%x \n", Data16));
+ MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, Data16);
+
+ gBS->Stall (10);
+ Data16 |= BIT0;
+ MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, Data16);
+
+ TimeOutCount = TIME_OUT_1S;
+ do {
+ Data16 = MmcHostRead16 (MmcHostData, MMIO_CLKCTL);
+ gBS->Stall (10);
+ TimeOutCount --;
+ if (TimeOutCount == 0) {
+ DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: Timeout\n"));
+ return EFI_TIMEOUT;
+ }
+ } while ((Data16 & BIT1) != BIT1);
+
+ gBS->Stall (10);
+ Data16 |= BIT2;
+ MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, Data16);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set bus width of the host
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] BusWidth Bus width in 1, 4, 8 bits
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusWidth (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 BusWidth
+ )
+{
+ MMCHOST_DATA *MmcHostData;
+ UINT8 Data;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) {
+ DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Invalid parameter \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((MmcHostData->MmcHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) {
+ DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Invalid parameter \r\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ Data = MmcHostRead8 (MmcHostData, MMIO_HOSTCTL);
+
+ if (BusWidth == 8) {
+ DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Bus Width is 8-bit ... \r\n"));
+ Data |= BIT5;
+ } else if (BusWidth == 4) {
+ DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Bus Width is 4-bit ... \r\n"));
+ Data &= ~BIT5;
+ Data |= BIT1;
+ } else {
+ DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Bus Width is 1-bit ... \r\n"));
+ Data &= ~BIT5;
+ Data &= ~BIT1;
+ }
+ MmcHostWrite8 (MmcHostData, MMIO_HOSTCTL, Data);
+ DEBUG ((gMmcHostDebugLevel, "SetBusWidth: MMIO_HOSTCTL value: 0x%x \n", MmcHostRead8 (MmcHostData, MMIO_HOSTCTL)));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set voltage which could supported by the host.
+ Support 0(Power off the host), 1.8V, 3.0V, 3.3V
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Voltage Units in 0.1 V
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostVoltage (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 Voltage
+ )
+{
+ MMCHOST_DATA *MmcHostData;
+ UINT8 Data;
+ EFI_STATUS Status;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+ Status = EFI_SUCCESS;
+
+ Data = MmcHostRead8 (MmcHostData, MMIO_PWRCTL);
+
+ if (Voltage == 0) {
+ //
+ //Power Off the host
+ //
+ Data &= ~BIT0;
+ } else if (Voltage <= 18 && This->HostCapability.V18Support) {
+ //
+ //1.8V
+ //
+ Data |= (BIT1 | BIT3 | BIT0);
+ } else if (Voltage > 18 && Voltage <= 30 && This->HostCapability.V30Support) {
+ //
+ //3.0V
+ //
+ Data |= (BIT2 | BIT3 | BIT0);
+ } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) {
+ //
+ //3.3V
+ //
+ Data |= (BIT1 | BIT2 | BIT3 | BIT0);
+ } else {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ MmcHostWrite8 (MmcHostData, MMIO_PWRCTL, Data);
+ gBS->Stall (10);
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Set Host High Speed
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] HighSpeed True for High Speed Mode set, false for normal mode
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostSpeedMode(
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 HighSpeed
+ )
+{
+ EFI_STATUS Status;
+ MMCHOST_DATA *MmcHostData;
+ UINT8 Data8;
+
+ Status = EFI_SUCCESS;
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ if (MmcHostData->IsEmmc) {
+ Data8 = MmcHostRead8 (MmcHostData, MMIO_HOSTCTL);
+ Data8 &= ~(BIT2);
+ if (HighSpeed) {
+ Data8 |= BIT2;
+ DEBUG ((gMmcHostDebugLevel, "High Speed mode: Data8=0x%x \n", Data8));
+ } else {
+ DEBUG ((gMmcHostDebugLevel, "Normal Speed mode: Data8=0x%x \n", Data8));
+ }
+ MmcHostWrite8 (MmcHostData, MMIO_HOSTCTL, Data8);
+ gBS->Stall (10);
+ DEBUG ((gMmcHostDebugLevel, "MMIO_HOSTCTL value: 0x%x \n", MmcHostRead8 (MmcHostData, MMIO_HOSTCTL)));
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+
+/**
+ Set Host mode in DDR
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] SetHostDdrMode True for DDR Mode set, false returns EFI_SUCCESS
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostDdrMode(
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 DdrMode
+ )
+{
+ EFI_STATUS Status;
+ MMCHOST_DATA *MmcHostData;
+ UINT16 ModeSet;
+
+ Status = EFI_SUCCESS;
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ if (MmcHostData->IsEmmc) {
+ ModeSet = MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2);
+ ModeSet &= ~(BIT0 | BIT1 | BIT2);
+ if (DdrMode) {
+ ModeSet |= 0x0004;
+ ModeSet |= BIT3; //1.8v
+ DEBUG ((gMmcHostDebugLevel, "DDR mode: Data16=0x%x \n", ModeSet));
+ } else {
+ if (CheckControllerVersion (MmcHostData) != 2) {
+ ModeSet = 0x0;
+ }
+ }
+
+ MmcHostWrite16 (MmcHostData, MMIO_HOST_CTL2, ModeSet);
+ gBS->Stall (10);
+ DEBUG ((gMmcHostDebugLevel, "MMIO_HOST_CTL2 value: 0x%x \n", MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2)));
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+
+/**
+ Set Host SDR Mode
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] DdrMode True for SDR Mode set, false for normal mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostSdrMode(
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 SdrMode
+ )
+{
+ MMCHOST_DATA *MmcHostData;
+ UINT16 ModeSet;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ if (MmcHostData->IsEmmc) {
+ ModeSet = MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2);
+ ModeSet &= ~(BIT0 | BIT1 | BIT2);
+ if (SdrMode) {
+ if (MmcHostData->MmcHostIo.HostCapability.SDR104Support) {
+ ModeSet |= 3;
+ } else if (MmcHostData->MmcHostIo.HostCapability.SDR50Support) {
+ ModeSet |= 2;
+ }
+ ModeSet |= 1;
+ DEBUG ((gMmcHostDebugLevel, "SDR mode: Data16=0x%x \n", ModeSet));
+ } else {
+ if (CheckControllerVersion (MmcHostData) != 2) {
+ ModeSet = 0x0;
+ }
+ }
+
+ MmcHostWrite16 (MmcHostData, MMIO_HOST_CTL2, ModeSet);
+ gBS->Stall (10);
+ DEBUG ((gMmcHostDebugLevel, "MMIO_HOST_CTL2 value: 0x%x \n", MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2)));
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+
+/**
+ Reset the host
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] ResetType Reset data/cmd all
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT The timeout time expired.
+
+**/
+EFI_STATUS
+EFIAPI
+ResetMmcHost (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN RESET_TYPE ResetType
+ )
+{
+ MMCHOST_DATA *MmcHostData;
+ UINT8 Data8;
+ UINT32 Data;
+ UINT16 ErrStatus;
+ UINT8 Mask;
+ UINT32 TimeOutCount;
+ UINT16 SaveClkCtl;
+ UINT16 SavePwrCtl = 0;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+ MmcHostData->IsEmmc = TRUE;
+ Mask = 0;
+ ErrStatus = 0;
+
+ if (ResetType == Reset_Auto) {
+ ErrStatus = MmcHostRead16 (MmcHostData, MMIO_ERINTSTS);
+ if ((ErrStatus & 0xF) != 0) {
+ //
+ //Command Line
+ //
+ Mask |= BIT1;
+ }
+ if ((ErrStatus & 0x70) != 0) {
+ //
+ //Data Line
+ //
+ Mask |= BIT2;
+ }
+ }
+
+ if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) {
+ Mask |= BIT2;
+ }
+ if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) {
+ Mask |= BIT1;
+ }
+ if (ResetType == Reset_All) {
+ Mask = BIT0;
+ }
+ if (ResetType == Reset_HW) {
+ SavePwrCtl = MmcHostRead16 (MmcHostData, MMIO_PWRCTL);
+ DEBUG ((gMmcHostDebugLevel, "Write SavePwrCtl: %x \n", (SavePwrCtl | BIT4)));
+
+ MmcHostWrite16 (MmcHostData, MMIO_PWRCTL, SavePwrCtl | BIT4);
+ gBS->Stall (10);
+ DEBUG ((gMmcHostDebugLevel, "Write SavePwrCtl: %x \n", (SavePwrCtl &(~BIT4))));
+ MmcHostWrite16 (MmcHostData, MMIO_PWRCTL, SavePwrCtl &(~BIT4));
+ gBS->Stall (10);
+ }
+
+ if (Mask == 0) {
+ return EFI_SUCCESS;
+ }
+
+ SaveClkCtl = MmcHostRead16 (MmcHostData, MMIO_CLKCTL);
+
+ MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, 0);
+
+ gBS->Stall (10);
+
+ //
+ // Reset the MMC host controller
+ //
+ MmcHostWrite8 (MmcHostData, MMIO_SWRST, Mask);
+
+ Data = 0;
+ TimeOutCount = TIME_OUT_1S;
+ do {
+ gBS->Stall (10);
+ TimeOutCount --;
+
+ Data8 = MmcHostRead8 (MmcHostData, MMIO_SWRST);
+ if ((Data8 & Mask) == 0) {
+ break;
+ }
+ } while (TimeOutCount > 0);
+
+ //
+ // We now restore the MMIO_CLKCTL register which we set to 0 above.
+ //
+ MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, SaveClkCtl);
+
+ if (TimeOutCount == 0) {
+ DEBUG ((gMmcHostDebugLevel, "ResetMMCHost: Time out \n"));
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Enable AutoStop Cmd
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Enable TRUE to enable
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+EFIAPI
+EnableAutoStopCmd (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ MMCHOST_DATA *MmcHostData;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ MmcHostData->IsAutoStopCmd = Enable;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set the Block length
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] BlockLength card supportes block length
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetBlockLength (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 BlockLength
+ )
+{
+ MMCHOST_DATA *MmcHostData;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ DEBUG ((gMmcHostDebugLevel, "SetBlockLength: Block length on the host controller: %d \n", BlockLength));
+ MmcHostData->BlockLength = BlockLength;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Detect card and init Sd host
+ Find whether these is a card inserted into the slot. If so
+ init the host. If not, return EFI_NOT_FOUND.
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+DetectCardAndInitHost (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This
+ )
+{
+ MMCHOST_DATA *MmcHostData;
+ UINT16 Data16;
+ UINT32 Data;
+ EFI_STATUS Status;
+ UINT8 Voltages[] = { 33, 30, 18 };
+ UINTN Loop;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ Data = 0;
+ Data = MmcHostRead32 (MmcHostData, MMIO_PSTATE);
+
+ if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) {
+ //
+ // Has no card inserted
+ //
+ DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: No card\n"));
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: Card present\n"));
+
+ //
+ //Enable normal status change
+ //
+ MmcHostWrite16 (MmcHostData, MMIO_NINTEN, BIT1 | BIT0);
+
+ //
+ // Enable error status change
+ //
+ Data16 = MmcHostRead16 (MmcHostData, MMIO_ERINTEN);
+ Data16 |= 0xFFFF; //(BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8);
+ MmcHostWrite16 (MmcHostData, MMIO_ERINTEN, Data16);
+
+ //
+ // Data transfer Timeout control
+ //
+ MmcHostWrite8 (MmcHostData, MMIO_TOCTL, 0x0E);
+
+ //
+ // Stall 1 milliseconds to increase MMC stability.
+ //
+ gBS->Stall (10);
+
+ Status = SetClockFrequency (This, FREQUENCY_OD);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: SetClockFrequency failed\n"));
+ goto Exit;
+ }
+ DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: SetClockFrequency done\n"));
+
+ Status = EFI_NOT_FOUND;
+ for (Loop = 0; Loop < sizeof (Voltages); Loop++) {
+ DEBUG ((
+ EFI_D_INFO,
+ "DetectCardAndInitHost: SetHostVoltage %d.%dV\n",
+ Voltages[Loop] / 10,
+ Voltages[Loop] % 10
+ ));
+ Status = SetHostVoltage (This, Voltages[Loop]);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: SetHostVoltage failed\n"));
+ } else {
+ DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: SetHostVoltage done\n"));
+ break;
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: Failed to SetHostVoltage\n"));
+ goto Exit;
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Setup the MMC Host Device
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetupDevice (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This
+ )
+{
+ UINT32 tempD = 0;
+ INT32 timeOut = 1000;
+ UINT8 temp8 = 0;
+ UINT16 temp16 = 0;
+ MMCHOST_DATA *MmcHostData;
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (This);
+
+ //
+ // Reset HC and wait for self-clear
+ //
+ MmcHostWrite8 (MmcHostData, MMIO_SWRST, 0x7);
+ gBS->Stall (1000);
+ timeOut = 1000;
+ do {
+ temp8 = MmcHostRead8 (MmcHostData, MMIO_SWRST);
+ timeOut--;
+ } while ((temp8 & (1 << 0)) && (timeOut > 0));
+
+ DEBUG ((EFI_D_INFO, "Reset HC and wait for self-clear Done\n"));
+
+ //
+ // Enable all interrupt status bits (NO CARD_INTERRUPT!)
+ //
+ MmcHostWrite16 (MmcHostData, MMIO_NINTEN, 0x3);
+
+ //
+ // Clear all interrupt status bits
+ //
+ MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, 0xFFFF);
+ MmcHostWrite16 (MmcHostData, MMIO_ERINTEN, 0xFFFF);
+
+ if (2 == CheckControllerVersion (MmcHostData))
+ temp16 = (UINT16) (0x1 << 6);
+ else
+ temp16 = (UINT16) (0x80 << 8);
+ //
+ // Set to 400KB, enable internal clock and wait for stability
+ //
+ MmcHostWrite32 (MmcHostData, MMIO_CLKCTL, (1<<0) | temp16);
+
+ gBS->Stall (1000);
+ do {
+ tempD = MmcHostRead32 (MmcHostData, MMIO_CLKCTL);
+ timeOut--;
+ } while ((!(tempD & (1 << 1))) && (timeOut > 0));
+ gBS->Stall (1000);
+
+ //
+ // Enable MMC clock
+ //
+ tempD |= (1 << 2);
+ MmcHostWrite32 (MmcHostData, MMIO_CLKCTL, tempD);
+ gBS->Stall (1000);
+
+ temp8 = MmcHostRead8 (MmcHostData, MMIO_PWRCTL);
+ DEBUG ((DEBUG_INFO, "==========%a, %d, offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8));
+
+ //
+ // Apply 1.8V to the bus
+ //
+ temp8 = (0x5 << (1) );
+ MmcHostWrite8 (MmcHostData, MMIO_PWRCTL, temp8);
+ gBS->Stall (1000);
+ temp8 = MmcHostRead8 (MmcHostData, MMIO_PWRCTL);
+ DEBUG ((DEBUG_INFO, "==========%a, %d, set (0x5 << 1):offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8));
+
+ //
+ // Set 1.8V sigaling Enabled
+ //
+ temp16 = MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2);
+ temp16 &= ~BIT3;
+ MmcHostWrite16 (MmcHostData, MMIO_HOST_CTL2, temp16);
+ DEBUG ((gMmcHostDebugLevel, "Set 1.8 V signaling Enable:0x%x \r\n", MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2)));
+
+ //
+ // Apply power to MMC
+ //
+ temp8 = MmcHostRead8 (MmcHostData, MMIO_PWRCTL);
+ DEBUG ((DEBUG_INFO, "==========%a, %d, read offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8));
+
+ temp8 |= (1 << (0));
+ DEBUG ((DEBUG_INFO, "==========%a, %d, set 1<<0:offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8));
+
+ MmcHostWrite8 (MmcHostData, MMIO_PWRCTL, temp8);
+ gBS->Stall (1000); ///<synced to byt-cr pei. bxt power on used (50 * 1000)
+ temp8 = MmcHostRead8 (MmcHostData, MMIO_PWRCTL);
+
+ DEBUG ((DEBUG_INFO, "==========%a, %d, read offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8));
+
+ //
+ // MAX out the DATA_TIMEOUT
+ //
+ MmcHostWrite8 (MmcHostData, MMIO_TOCTL, 0xE);
+ gBS->Stall (1000);
+
+ if (MmcHostData->EnableVerboseDebug) {
+ DEBUG ((EFI_D_INFO, "==========%a, Start. RegMap================\n", __FUNCTION__));
+ DEBUG ((DEBUG_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C)));
+ DEBUG ((DEBUG_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C)));
+ DEBUG ((DEBUG_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C)));
+ DEBUG ((DEBUG_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C)));
+ DEBUG ((DEBUG_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C)));
+ DEBUG ((DEBUG_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C)));
+ DEBUG ((DEBUG_INFO, "==========%a, END. RegMap================\n", __FUNCTION__));
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c
new file mode 100644
index 0000000..f94dc1d
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c
@@ -0,0 +1,613 @@
+/** @file
+ UEFI Driver Entry and Binding support.
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "MmcHostDriver.h"
+#include <PiDxe.h>
+
+//
+// MMCSDIOController Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gMmcHostDriverBinding = {
+ MmcHostDriverBindingSupported,
+ MmcHostDriverBindingStart,
+ MmcHostDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+
+EFI_MMC_HOST_IO_PROTOCOL mMmcHostIo = {
+ EFI_MMC_HOST_IO_PROTOCOL_REVISION_01,
+ {
+ 0, ///< HighSpeedSupport
+ 0, ///< V18Support
+ 0, ///< V30Support
+ 0, ///< V33Support
+ 0, ///< HS400Support
+ 0, ///< BusWidth4
+ 0, ///< BusWidth8
+ 0, ///< Reserved1
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, ///< ADMA2Support
+ 0, ///< DmaMode
+ 0, ///< ReTune Timer
+ 0, ///< ReTune Mode
+ 0, ///< Reserved2
+ (512 * 1024) ///<BoundarySize 512 KB
+ },
+ SendCommand,
+ SetClockFrequency,
+ SetBusWidth,
+ SetHostVoltage,
+ SetHostDdrMode,
+ SetHostSdrMode,
+ ResetMmcHost,
+ EnableAutoStopCmd,
+ DetectCardAndInitHost,
+ SetBlockLength,
+ SetupDevice,
+ SetHostSpeedMode
+};
+
+
+/**
+ Entry point for MMC Host EFI drivers.
+
+ @param[in] ImageHandle EFI_HANDLE
+ @param[in] SystemTable EFI_SYSTEM_TABLE
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_DEVICE_ERROR The function failed to complete
+
+**/
+EFI_STATUS
+EFIAPI
+MmcHostDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallAllDriverProtocols (
+ ImageHandle,
+ SystemTable,
+ &gMmcHostDriverBinding,
+ ImageHandle,
+ &gMmcHostComponentName,
+ NULL,
+ NULL
+ );
+}
+
+
+/**
+ Test to see if this MMC Host driver supports ControllerHandle.
+ Any ControllerHandle that has installed will be supported.
+
+ @param[in] This Protocol instance pointer
+ @param[in] Controller Handle of device to test
+ @param[in] RemainingDevicePath Not used
+
+ @retval EFI_SUCCESS This driver supports this device
+ @retval EFI_UNSUPPORTED This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+MmcHostDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ PCI_CLASSC PciClass;
+ UINT32 VidDid;
+ UINT32 Bar0 = 0;
+ UINT32 Bar1 = 0;
+ UINTN Seg, Bus, Dev, Func;
+
+ //
+ // Verify the MMC IO Protocol, which installed by the
+ // IdeController module.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ (VOID **) &MmcHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "MmcHost controller already started, Controller: 0x%016Lx\r\n", (UINT64) (UINTN) Controller));
+ Status = EFI_ALREADY_STARTED;
+ return Status;
+ }
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID**) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_VENDOR_ID_OFFSET,
+ 1,
+ &VidDid
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (PCI_CLASSC) / sizeof (UINT8),
+ &PciClass
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BASE_ADDRESSREG_OFFSET,
+ 1,
+ &Bar0
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BASE_ADDRESSREG_OFFSET + 4,
+ 1,
+ &Bar1
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ Status = PciIo->GetLocation (
+ PciIo,
+ &Seg,
+ &Bus,
+ &Dev,
+ &Func
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ if ((Seg != 0) || (Bus != 0) || (Dev != 28) || (Func != 0)) {
+ //
+ // This is not the eMMC controller, bail.
+ //
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) ||
+ (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) ||
+ ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA))
+ ) {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported0: Seg %d, bus:%d, Dev:%d, Func:%d\n", Seg, Bus, Dev, Func));
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported1: VidDid %08x\n", VidDid));
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported1: Base Code %x\n", PciClass.BaseCode));
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported1: SubClassCode %x\n", PciClass.SubClassCode));
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported1: PI %x\n", PciClass.PI));
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported0: MEMIO Base0 %x\n", Bar0));
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported0: MEMIO Base1 %x\n", Bar1));
+
+Exit:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+}
+
+
+/**
+ Starting the MMC Host Driver
+
+ @param[in] This Protocol instance pointer
+ @param[in] Controller Handle of device to start
+ @param[in] RemainingDevicePath Not used
+
+ @retval EFI_SUCCESS This driver start this device
+ @retval EFI_UNSUPPORTED This driver does not support this device
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error
+ @retval EFI_OUT_OF_RESOURCES This driver cannot allocate resources
+
+**/
+EFI_STATUS
+EFIAPI
+MmcHostDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ MMCHOST_DATA *MmcHostData;
+ UINT32 Data;
+ UINT16 Data16;
+ UINT32 VidDid;
+ UINT32 Bar0 = 0;
+ UINT32 Bar1 = 0;
+ UINTN Seg, Bus, Dev, Func;
+
+ MmcHostData = NULL;
+ Data = 0;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Start\n"));
+
+ //
+ // Open PCI I/O Protocol and save pointer to open protocol
+ // in private data area.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Enable the MMC Host Controller MMIO space
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+
+ MmcHostData = (MMCHOST_DATA *) AllocateZeroPool (sizeof (MMCHOST_DATA));
+ if (MmcHostData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ MmcHostData->Signature = MMCHOST_DATA_SIGNATURE;
+ MmcHostData->PciIo = PciIo;
+
+ CopyMem (&MmcHostData->MmcHostIo, &mMmcHostIo, sizeof (EFI_MMC_HOST_IO_PROTOCOL));
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_VENDOR_ID_OFFSET,
+ 1,
+ &VidDid
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: VidDid = 0x%08x\n", VidDid));
+
+ Status = PciIo->GetLocation (
+ PciIo,
+ &Seg,
+ &Bus,
+ &Dev,
+ &Func
+ );
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Seg %d, bus:%d,Dev:%d,Func:%d\n", Seg, Bus, Dev,Func));
+
+ MmcHostData->PciVid = (UINT16) (VidDid & 0xffff);
+ MmcHostData->PciDid = (UINT16) (VidDid >> 16);
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BASE_ADDRESSREG_OFFSET,
+ 1,
+ &Bar0
+ );
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BASE_ADDRESSREG_OFFSET + 4,
+ 1,
+ &Bar1
+ );
+
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MEMIO Base0 %x\n", Bar0));
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MEMIO Base1 %x\n", Bar1));
+
+
+ MmcHostData->MmcHostIo.ResetMmcHost (&MmcHostData->MmcHostIo, Reset_All);
+ MmcHostData->EnableVerboseDebug = FALSE;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CTRLRVER,
+ 1,
+ &Data16
+ );
+
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MMIO_CTRLRVER = 0x%08x\n", Data16));
+
+ MmcHostData->ControllerVersion = Data16 & 0xFF;
+ switch (MmcHostData->ControllerVersion) {
+ case 0: DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MMC Host Controller Version 1.0\n")); break;
+ case 1: DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MMC Host Controller Version 2.0\n")); break;
+ case 2: DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MMC Host Controller Version 3.0\n")); break;
+ default:
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Unknown MMC Host Controller Version, Stopping Driver!!\n"));
+ goto Exit;
+ }
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT32) MMIO_CAP,
+ 1,
+ &Data
+ );
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Low MMIO_CAP = 0x%08x\n", Data));
+
+ if ((Data & BIT18) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.BusWidth8 = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: BusWidth8\n"));
+ }
+
+ MmcHostData->MmcHostIo.HostCapability.BusWidth4 = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: BusWidth4\n"));
+
+ if ((Data & BIT19) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.ADMA2Support = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: ADMA2Support\n"));
+ }
+
+ if ((Data & BIT21) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.HighSpeedSupport = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: HighSpeedSupport\n"));
+ }
+
+ if ((Data & BIT22) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.SDMASupport = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: SDMASupport\n"));
+ }
+
+ if ((Data & BIT24) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.V33Support = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: V33Support\n"));
+ }
+
+ if ((Data & BIT25) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.V30Support = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: V30Support\n"));
+ }
+
+ if ((Data & BIT26) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.V18Support = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: V18Support\n"));
+ }
+
+ if (((Data) & (BIT30 | BIT31)) == 0) {
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Removable Card Slot\n"));
+ } else if ((Data & BIT30) && (Data & (~BIT31))) {
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Embedded Slot for One Device\n"));
+ }
+ MmcHostData->BaseClockInMHz = (Data >> 8) & 0xFF;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT32) (MMIO_CAP + 4),
+ 1,
+ &Data
+ );
+
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: High MMIO_CAP = 0x%08x\n", Data));
+
+
+
+ if ((Data & 0x1<<(32-32)) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.SDR50Support= TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: SDR50Support\n"));
+ }
+
+ if ((Data & 0x1<<(33-32)) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.SDR104Support= TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: SDR104Support\n"));
+ }
+
+ if ((Data & 0x1<<(34-32)) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.DDR50Support= TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: DDR50Support\n"));
+ }
+
+ if ((Data & 0x1<<(63-32)) != 0) {
+ MmcHostData->MmcHostIo.HostCapability.HS400Support = TRUE;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: HS400Support\n"));
+ }
+
+ if (MmcHostData->ControllerVersion >= 2) {
+ MmcHostData->MmcHostIo.HostCapability.ReTuneMode = (Data >> (46-32)) & 0x3;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: ReTuneMode = 0x%08x\n", MmcHostData->MmcHostIo.HostCapability.ReTuneMode));
+
+ MmcHostData->MmcHostIo.HostCapability.ReTuneTimer = (Data>>(40-32)) & 0xF;
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: ReTuneTimer = 0x%08x\n", MmcHostData->MmcHostIo.HostCapability.ReTuneTimer));
+ }
+
+
+ MmcHostData->BlockLength = BLOCK_SIZE;
+ MmcHostData->IsAutoStopCmd = TRUE;
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &MmcHostData->MmcHostIo
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Component name protocol
+ //
+ Status = AddUnicodeString (
+ "eng",
+ gMmcHostComponentName.SupportedLanguages,
+ &MmcHostData->ControllerNameTable,
+ L"MMC Host Controller"
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ &MmcHostData->MmcHostIo
+ );
+ }
+
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Host Started\n"));
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ if (MmcHostData != NULL) {
+ FreePool (MmcHostData);
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ return Status;
+}
+
+
+/**
+ Stop MMC Host driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param[in] This Protocol instance pointer
+ @param[in] Controller Handle of device to stop driver on
+ @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer
+ @param[in] ChildHandleBuffer List of handles for the children we need to stop
+
+ @retval EFI_SUCCESS This driver stop this device
+ @retval EFI_DEVICE_ERROR This driver cannot be stop due to device Error
+
+**/
+EFI_STATUS
+EFIAPI
+MmcHostDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ MMCHOST_DATA *MmcHostData;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ (VOID **) &MmcHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto _exit_MmcHostDriverBindingStop;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ MmcHostData = MMCHOST_DATA_FROM_THIS (MmcHostIo);
+
+ //
+ // Uninstall Block I/O protocol from the device handle
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ &MmcHostData->MmcHostIo
+ );
+ if (EFI_ERROR (Status)) {
+ goto _exit_MmcHostDriverBindingStop;
+ }
+
+ FreeUnicodeStringTable (MmcHostData->ControllerNameTable);
+ FreePool (MmcHostData);
+
+_exit_MmcHostDriverBindingStop:
+ DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStop exited with Status %r\n", Status));
+
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h
new file mode 100644
index 0000000..f724061
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h
@@ -0,0 +1,585 @@
+/** @file
+ Header file for MMC driver.
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _MMC_HOST_DRIVER_H
+#define _MMC_HOST_DRIVER_H
+
+#include <Uefi.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/SdCard.h>
+#include <ScAccess.h>
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+
+//
+// Driver Produced Protocol Prototypes
+//
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/MmcHostIo.h>
+
+extern EFI_COMPONENT_NAME_PROTOCOL gMmcHostComponentName;
+extern EFI_DRIVER_BINDING_PROTOCOL gMmcHostDriverBinding;
+
+#define MMCHOST_DATA_SIGNATURE SIGNATURE_32 ('m', 'c', 'h', 's')
+
+#define MMCHOST_DATA_FROM_THIS(a) \
+ CR (a, MMCHOST_DATA, MmcHostIo, MMCHOST_DATA_SIGNATURE)
+
+#define BLOCK_SIZE 0x200
+#define TIME_OUT_1S 1000
+
+#define INTEL_VENDOR_ID 0x8086
+
+#define BUFFER_CTL_REGISTER 0x84
+
+#pragma pack(1)
+//
+// PCI Class Code structure
+//
+typedef struct {
+ UINT8 PI;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} PCI_CLASSC;
+
+#pragma pack()
+
+//
+// MMCHOST_DATA structure
+//
+typedef struct {
+ UINTN Signature;
+ EFI_MMC_HOST_IO_PROTOCOL MmcHostIo;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT16 PciVid;
+ UINT16 PciDid;
+ BOOLEAN IsAutoStopCmd;
+ BOOLEAN IsEmmc;
+ BOOLEAN EnableVerboseDebug;
+ UINT32 BaseClockInMHz;
+ UINT32 CurrentClockInKHz;
+ UINT32 BlockLength;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+ UINT32 ControllerVersion;
+} MMCHOST_DATA;
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+/**
+ Entry point for MMC Host EFI drivers.
+
+ @param[in] ImageHandle EFI_HANDLE
+ @param[in] SystemTable EFI_SYSTEM_TABLE
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_DEVICE_ERROR The function failed to complete
+
+**/
+EFI_STATUS
+EFIAPI
+MmcHostDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Test to see if this MMC Host driver supports ControllerHandle.
+ Any ControllerHandle that has installed will be supported.
+
+ @param[in] This Protocol instance pointer
+ @param[in] Controller Handle of device to test
+ @param[in] RemainingDevicePath Not used
+
+ @retval EFI_SUCCESS This driver supports this device
+ @retval EFI_UNSUPPORTED This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+MmcHostDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starting the MMC Host Driver
+
+ @param[in] This Protocol instance pointer
+ @param[in] Controller Handle of device to start
+ @param[in] RemainingDevicePath Not used
+
+ @retval EFI_SUCCESS This driver start this device
+ @retval EFI_UNSUPPORTED This driver does not support this device
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error
+ @retval EFI_OUT_OF_RESOURCES This driver cannot allocate resources
+
+**/
+EFI_STATUS
+EFIAPI
+MmcHostDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop MMC Host driver on ControllerHandle. Support stopping any child handles
+ created by this driver.
+
+ @param[in] This Protocol instance pointer
+ @param[in] Controller Handle of device to stop driver on
+ @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer
+ @param[in] ChildHandleBuffer List of handles for the children we need to stop
+
+ @retval EFI_SUCCESS This driver stop this device
+ @retval EFI_DEVICE_ERROR This driver cannot be stop due to device Error
+
+**/
+EFI_STATUS
+EFIAPI
+MmcHostDriverBindingStop (
+ 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 EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language 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
+MmcHostComponentNameGetDriverName (
+ 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 an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device 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 name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language
+ specified by Language from the point of view of the
+ driver specified by This.
+
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in the
+ language specified by Language for 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
+MmcHostComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle, OPTIONAL
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ The main function used to send the command to the card inserted into the MMC host
+ slot.
+ It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData
+
+ @param[in] This Pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] Argument Command argument to set the argument field of command register
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out
+ @param[in] Buffer Contains the data read from / write to the device
+ @param[in] BufferSize The size of the buffer
+ @param[in] ResponseType RESPONSE_TYPE
+ @param[in] TimeOut Time out value in 1 ms unit
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+ @retval EFI_TIMEOUT
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+SendCommand (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData OPTIONAL
+ );
+
+/**
+ Set max clock frequency of the host, the actual frequency
+ may not be the same as MaxFrequencyInKHz. It depends on
+ the max frequency the host can support, divider, and host
+ speed mode.
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] MaxFrequency Max frequency in HZ
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+EFIAPI
+SetClockFrequency (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 MaxFrequencyInKHz
+ );
+
+/**
+ Set bus width of the host
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] BusWidth Bus width in 1, 4, 8 bits
+
+
+ @retval EFI_STATUS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusWidth (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 BusWidth
+ );
+
+/**
+ Set voltage which could supported by the host.
+ Support 0(Power off the host), 1.8V, 3.0V, 3.3V
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Voltage Units in 0.1 V
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostVoltage (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 Voltage
+ );
+
+/**
+ Set Host mode in DDR
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] DdrMode True for DDR Mode set, false returns EFI_SUCCESS
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostDdrMode (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 DdrMode
+ );
+
+/**
+ Set Host SDR Mode
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] DdrMode True for SDR Mode set, false for normal mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostSdrMode (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 SdrMode
+ );
+
+/**
+ Set Host High Speed
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] HighSpeed True for High Speed Mode set, false for normal mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostSpeedMode (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 HighSpeed
+ );
+
+/**
+ Reset the host
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] ResetAll TRUE to reset all
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT The timeout time expired.
+
+**/
+EFI_STATUS
+EFIAPI
+ResetMmcHost (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN RESET_TYPE ResetType
+ );
+
+/**
+ Reset the host
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] ResetAll TRUE to reset all
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT The timeout time expired.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableAutoStopCmd (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+/**
+ Find whether these is a card inserted into the slot. If so
+ init the host. If not, return EFI_NOT_FOUND.
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Fail
+
+**/
+EFI_STATUS
+EFIAPI
+DetectCardAndInitHost (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This
+ );
+
+/**
+ Set the Block length
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] BlockLength card supports block length
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Fail
+
+**/
+EFI_STATUS
+EFIAPI
+SetBlockLength (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT32 BlockLength
+ );
+
+/**
+ Setup Device
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Fail
+
+**/
+EFI_STATUS
+EFIAPI
+SetupDevice(
+ IN EFI_MMC_HOST_IO_PROTOCOL *This
+ );
+
+/**
+ Read MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the eMMC
+
+ @retval Data Data read from eMMC
+
+**/
+UINT8
+MmcHostRead8 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset
+ );
+
+/**
+ Read MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the eMMC
+
+ @retval Data Data read from eMMC
+
+**/
+UINT16
+MmcHostRead16 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset
+ );
+
+/**
+ Read MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the eMMC
+
+ @retval Data Data read from eMMC
+
+**/
+UINT32
+MmcHostRead32 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset
+ );
+
+/**
+ Write MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the eMMC
+ @param[in] Data Data write to eMMC
+
+ @retval Data Written to MmcHost
+
+**/
+UINT8
+MmcHostWrite8 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset,
+ IN UINT8 Data
+ );
+
+/**
+ Write MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the eMMC
+ @param[in] Data Data write to eMMC
+
+ @retval Data Data written to eMMC
+
+**/
+UINT16
+MmcHostWrite16 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset,
+ IN UINT16 Data
+ );
+
+/**
+ Write MMC host register
+
+ @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] Offset Offset of the eMMC
+ @param[in] Data Data write to eMMC
+
+ @retval Data Data written to eMMC
+
+**/
+UINT32
+MmcHostWrite32 (
+ IN MMCHOST_DATA *MmcHost,
+ IN UINTN Offset,
+ IN UINT32 Data
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf
new file mode 100644
index 0000000..0433019
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf
@@ -0,0 +1,59 @@
+## @file
+# MMC Host module
+#
+# Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# 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 = 0x00010005
+ BASE_NAME = MmcHost
+ FILE_GUID = D86DB3C5-57FE-44CF-A82A-74C4AD5B1C2E
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MmcHostDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ ComponentName.c
+ MmcHostDriver.h
+ MmcHostDriver.c
+ MmcHostController.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiLib
+ DevicePathLib
+ IoLib
+ PcdLib
+ HobLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## CONSUMES
+ gEfiMmcHostIoProtocolGuid ## BY_START
+
+[Guids]
+ gEfiBootMediaHobGuid ## UNDEFINED
+
+[Pcd]
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c
new file mode 100644
index 0000000..a0b0940
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c
@@ -0,0 +1,159 @@
+/** @file
+ Header file for ComponentName.
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 <MediaDeviceDriver.h>
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gMediaDeviceComponentName = {
+ MediaDeviceComponentNameGetDriverName,
+ MediaDeviceComponentNameGetControllerName,
+ "eng"
+};
+
+
+static EFI_UNICODE_STRING_TABLE mMediaDeviceDriverNameTable[] = {
+ { "eng", L"UEFI MMC/SD Media Device Driver" },
+ { NULL , NULL }
+};
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language 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
+MediaDeviceComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString (
+ Language,
+ gMediaDeviceComponentName.SupportedLanguages,
+ mMediaDeviceDriverNameTable,
+ DriverName
+ );
+}
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device 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 name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language
+ specified by Language from the point of view of the
+ driver specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in the
+ language specified by Language for 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
+MediaDeviceComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle, OPTIONAL
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ CARD_DATA *CardData;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ gMediaDeviceDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CardData = CARD_DATA_FROM_THIS (BlockIo);
+ return LookupUnicodeString (
+ Language,
+ gMediaDeviceComponentName.SupportedLanguages,
+ CardData->ControllerNameTable,
+ ControllerName
+ );
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c
new file mode 100644
index 0000000..5c91190
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c
@@ -0,0 +1,666 @@
+/** @file
+ Block I/O protocol for MMC/SD device.
+
+ Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ 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 <MediaDeviceDriver.h>
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] ExtendedVerification Indicates that the driver may perform a more
+ exhaustive verification operation of the device during reset.
+ (This parameter is ingored in this driver.)
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ CARD_DATA *CardData;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+
+ CardData = CARD_DATA_FROM_THIS (This);
+ MmcHostIo = CardData->MmcHostIo;
+
+ DEBUG ((EFI_D_INFO, "MMC SD Block: Resetting host\n"));
+
+ return MmcHostIo->ResetMmcHost (MmcHostIo, Reset_DAT_CMD);
+}
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] MediaId The media id that the read request is for.
+ @param[in] LBA The starting logical block address to read from on the device.
+ @param[in] BufferSiz The size of the Buffer in bytes. This must be a multiple of
+ the intrinsic block size of the device.
+ @param[out] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ CARD_DATA *CardData;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ UINT32 RemainingLength;
+ UINT32 TransferLength;
+ UINT8 *BufferPointer;
+ BOOLEAN SectorAddressing;
+ UINT64 CardSize;
+ MMC_PARTITION_DATA *Partition;
+ UINTN TotalBlock;
+
+ Status = EFI_SUCCESS;
+ Partition = CARD_PARTITION_DATA_FROM_THIS (This);
+ CardData = Partition->CardData;
+ MmcHostIo = CardData->MmcHostIo;
+
+ //
+ // Media ID has high priority that need to be verify first
+ //
+ if (MediaId != Partition->BlockIoMedia.MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ Status = MmcSelectPartition (Partition);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // BufferSize must be a multiple of the intrinsic block size of the device.
+ //
+ if (ModU64x32 (BufferSize,Partition->BlockIoMedia.BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ CardSize = MultU64x32 (CardData->BlockNumber, CardData->BlockLen);
+
+ if ((CardData->CardType == SdMemoryCard2High) || (CardSize >= SIZE_2GB)) {
+ SectorAddressing = TRUE;
+ } else {
+ SectorAddressing = FALSE;
+ }
+
+ if (SectorAddressing) {
+ //
+ // Sector Address
+ //
+ Address = (UINT32) DivU64x32 (MultU64x32 (LBA, Partition->BlockIoMedia.BlockSize), 512);
+ } else {
+ //
+ // Byte Address
+ //
+ Address = (UINT32) MultU64x32 (LBA, Partition->BlockIoMedia.BlockSize);
+ }
+
+ TotalBlock = (UINTN) DivU64x32 (BufferSize, Partition->BlockIoMedia.BlockSize);
+ //
+ // Make sure the range to read is valid.
+ //
+ if (LBA + TotalBlock > Partition->BlockIoMedia.LastBlock + 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!(Partition->BlockIoMedia.MediaPresent)) {
+ return EFI_NO_MEDIA;
+ }
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Invalid parameter \n"));
+ goto Done;
+ }
+
+ if ((BufferSize % Partition->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Bad buffer size \n"));
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ BufferPointer = Buffer;
+ RemainingLength = (UINT32) BufferSize;
+
+ while (RemainingLength > 0) {
+ if ((BufferSize >= Partition->BlockIoMedia.BlockSize)) {
+ if (RemainingLength > MmcHostIo->HostCapability.BoundarySize) {
+ TransferLength = MmcHostIo->HostCapability.BoundarySize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ if (CardData->CardType == MMCCard) {
+ if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) {
+ Status = SendCommand (
+ MmcHostIo,
+ SET_BLOCKLEN,
+ Partition->BlockIoMedia.BlockSize,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ Status = SendCommand (
+ MmcHostIo,
+ SET_BLOCK_COUNT,
+ TransferLength / Partition->BlockIoMedia.BlockSize,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ Status = SendCommand (
+ MmcHostIo,
+ READ_MULTIPLE_BLOCK,
+ Address,
+ InData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n"));
+ break;
+ }
+ } else {
+ if (RemainingLength > Partition->BlockIoMedia.BlockSize) {
+ TransferLength = Partition->BlockIoMedia.BlockSize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ Status = SendCommand (
+ MmcHostIo,
+ READ_SINGLE_BLOCK,
+ Address,
+ InData,
+ CardData->AlignedBuffer,
+ (UINT32) TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32*) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n"));
+ break;
+ }
+ }
+
+ CopyMem (BufferPointer, CardData->AlignedBuffer, TransferLength);
+
+ if (SectorAddressing) {
+ //
+ // Sector Address
+ //
+ Address += TransferLength / 512;
+ } else {
+ //
+ // Byte Address
+ //
+ Address += TransferLength;
+ }
+ BufferPointer += TransferLength;
+ RemainingLength -= TransferLength;
+ }
+
+ if (EFI_ERROR (Status)) {
+ if ((CardData->CardType == SdMemoryCard) ||
+ (CardData->CardType == SdMemoryCard2)||
+ (CardData->CardType == SdMemoryCard2High)) {
+ SendCommand (
+ MmcHostIo,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ } else {
+ SendCommand (
+ MmcHostIo,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ }
+ }
+
+Done:
+ return Status;
+}
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] MediaId The media id that the write request is for.
+ @param[in] LBA The starting logical block address to be written.
+ The caller is responsible for writing to only
+ legitimate locations.
+ @param[in] BufferSize
+ The size of the Buffer in bytes. This must be a multiple of
+ the intrinsic block size of the device.
+ @param[in] Buffer A pointer to the source buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ CARD_DATA *CardData;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ UINT32 RemainingLength;
+ UINT32 TransferLength;
+ UINT8 *BufferPointer;
+ BOOLEAN SectorAddressing;
+ UINT64 CardSize;
+ MMC_PARTITION_DATA *Partition;
+
+ Status = EFI_SUCCESS;
+ Partition = CARD_PARTITION_DATA_FROM_THIS (This);
+ CardData = Partition->CardData;
+ MmcHostIo = CardData->MmcHostIo;
+
+ Status = MmcSelectPartition (Partition);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CardSize = MultU64x32 (CardData->BlockNumber, CardData->BlockLen);
+
+ if ((CardData->CardType == SdMemoryCard2High) || (CardSize >= SIZE_2GB)) {
+ SectorAddressing = TRUE;
+ } else {
+ SectorAddressing = FALSE;
+ }
+
+ if (SectorAddressing) {
+ //
+ // Sector Address
+ //
+ Address = (UINT32) DivU64x32 (MultU64x32 (LBA, Partition->BlockIoMedia.BlockSize), 512);
+ } else {
+ //
+ // Byte Address
+ //
+ Address = (UINT32) MultU64x32 (LBA, Partition->BlockIoMedia.BlockSize);
+ }
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Invalid parameter \n"));
+ goto Done;
+ }
+
+ if ((BufferSize % Partition->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Bad buffer size \n"));
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ if (This->Media->ReadOnly == TRUE) {
+ Status = EFI_WRITE_PROTECTED;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Write protected \n"));
+ goto Done;
+ }
+
+ BufferPointer = Buffer;
+ RemainingLength = (UINT32) BufferSize;
+
+ while (RemainingLength > 0) {
+ if ((BufferSize >= Partition->BlockIoMedia.BlockSize) ) {
+ if (RemainingLength > MmcHostIo->HostCapability.BoundarySize) {
+ TransferLength = MmcHostIo->HostCapability.BoundarySize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ if ((CardData->CardType == SdMemoryCard) ||
+ (CardData->CardType == SdMemoryCard2)||
+ (CardData->CardType == SdMemoryCard2High)) {
+ //
+ // Write performance improvement
+ //
+ if ((TransferLength / Partition->BlockIoMedia.BlockSize) > 64) {
+ Status = SendAppCommand (
+ CardData,
+ SET_WR_BLK_ERASE_COUNT,
+ (UINT32) (TransferLength / Partition->BlockIoMedia.BlockSize),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ }
+ } else if (CardData->CardType == MMCCard) {
+
+ if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) {
+ Status = SendCommand (
+ MmcHostIo,
+ SET_BLOCKLEN,
+ Partition->BlockIoMedia.BlockSize,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ Status = SendCommand (
+ MmcHostIo,
+ SET_BLOCK_COUNT,
+ TransferLength / Partition->BlockIoMedia.BlockSize,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);
+
+ Status = SendCommand (
+ MmcHostIo,
+ WRITE_MULTIPLE_BLOCK,
+ Address,
+ OutData,
+ CardData->AlignedBuffer,
+ (UINT32) TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n"));
+ break;
+ }
+ } else {
+ if (RemainingLength > Partition->BlockIoMedia.BlockSize) {
+ TransferLength = Partition->BlockIoMedia.BlockSize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);
+
+ Status = SendCommand (
+ MmcHostIo,
+ WRITE_BLOCK,
+ Address,
+ OutData,
+ CardData->AlignedBuffer,
+ (UINT32) TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ }
+
+ if (SectorAddressing) {
+ //
+ // Sector Address
+ //
+ Address += TransferLength / 512;
+ } else {
+ //
+ // Byte Address
+ //
+ Address += TransferLength;
+ }
+ BufferPointer += TransferLength;
+ RemainingLength -= TransferLength;
+ }
+
+ if (EFI_ERROR (Status)) {
+ SendCommand (
+ MmcHostIo,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ }
+
+Done:
+ return Status;
+}
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
+ (In this driver, this function just returns EFI_SUCCESS.)
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Success
+
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ MMC/SD card BlockIo init function
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_SUCCESS Success
+
+**/
+EFI_STATUS
+MMCSDBlockIoInit (
+ IN CARD_DATA *CardData
+ )
+{
+ UINTN Loop;
+ MMC_PARTITION_DATA *Partition;
+ EXT_CSD *ExtCsd;
+ UINT64 GP_CHUNK_SIZE;
+ UINT32 GP_SIZE_MULT;
+ UINT64 GppSize;
+ UINTN GppIndex=0;
+
+ Partition = CardData->Partitions;
+ ExtCsd = &CardData->ExtCSDRegister;
+
+ //
+ // Determine GP partitioning chunk size
+ //
+ GP_CHUNK_SIZE = 0;
+ if (((ExtCsd->PARTITIONING_SUPPORT & BIT0) == BIT0) &&
+ ((ExtCsd->PARTITION_SETTING_COMPLETED & BIT0) == BIT0)) {
+ GP_CHUNK_SIZE = MultU64x32 (ExtCsd->HC_WP_GRP_SIZE, ExtCsd->HC_ERASE_GRP_SIZE);
+ GP_CHUNK_SIZE = MultU64x32 (GP_CHUNK_SIZE, SIZE_512KB);
+ }
+
+ for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Partition++, Loop++) {
+ //
+ // BlockIO protocol
+ //
+ Partition->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
+ Partition->BlockIo.Media = &(Partition->BlockIoMedia);
+ Partition->BlockIo.Reset = MMCSDBlockReset;
+ Partition->BlockIo.ReadBlocks = MMCSDBlockReadBlocks ;
+ Partition->BlockIo.WriteBlocks = MMCSDBlockWriteBlocks;
+ Partition->BlockIo.FlushBlocks = MMCSDBlockFlushBlocks;
+
+ Partition->BlockIoMedia.MediaId = 0;
+ Partition->BlockIoMedia.RemovableMedia = FALSE;
+ Partition->BlockIoMedia.MediaPresent = TRUE;
+ Partition->BlockIoMedia.LogicalPartition = FALSE;
+
+ //
+ // Force the User partition to be enabled
+ //
+ if (Loop == 0) {
+ Partition->Present = TRUE;
+ }
+
+ if (CardData->CSDRegister.PERM_WRITE_PROTECT || CardData->CSDRegister.TMP_WRITE_PROTECT) {
+ Partition->BlockIoMedia.ReadOnly = TRUE;
+ } else {
+ Partition->BlockIoMedia.ReadOnly = FALSE;
+ }
+
+ Partition->BlockIoMedia.WriteCaching = FALSE;
+ Partition->BlockIoMedia.BlockSize = CardData->BlockLen;
+ Partition->BlockIoMedia.IoAlign = 1;
+ Partition->BlockIoMedia.LastBlock = (EFI_LBA) (CardData->BlockNumber - 1);
+
+ //
+ // Handle GPP partitions
+ //
+ GppSize = 0;
+ if ((GP_CHUNK_SIZE != 0) && (Loop >= 4)) {
+ Partition->BlockIoMedia.LastBlock = (EFI_LBA) 0;
+ GppIndex = Loop - 4;
+ GP_SIZE_MULT = MmcGetExtCsd24 (
+ CardData,
+ OFFSET_OF (EXT_CSD, GP_SIZE_MULT_1) + (3 * GppIndex)
+ );
+ GppSize = MultU64x32 (GP_SIZE_MULT, (UINT32) GP_CHUNK_SIZE);
+ }
+
+ if (GppSize != 0) {
+ Partition->BlockIoMedia.LastBlock =
+ DivU64x32 (GppSize, Partition->BlockIoMedia.BlockSize) - 1;
+ DEBUG ((EFI_D_INFO,
+ "GPP%d last-block: 0x%lx\n",
+ GppIndex + 1,
+ Partition->BlockIoMedia.LastBlock
+ ));
+ Partition->Present = TRUE;
+ }
+
+ if (CardData->CardType == MMCCard) {
+ //
+ // Handle Boot partitions
+ //
+ if ((Loop == 1) || (Loop == 2)) {
+ Partition->BlockIoMedia.LastBlock = 128 * 1024 * ((UINTN) MmcGetExtCsd8 (CardData, OFFSET_OF (EXT_CSD, BOOT_SIZE_MULTI))) / 512;
+ Partition->Present = TRUE;
+ }
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "MMC SD Block I/O: Initialized\n"));
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c
new file mode 100644
index 0000000..13258de
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c
@@ -0,0 +1,2524 @@
+/** @file
+ SMMC transfer specific functions.
+
+ Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ 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 <MediaDeviceDriver.h>
+#include <HeciRegs.h>
+#include <Private/Guid/ScPolicyHobGuid.h>
+#include <SeCAccess.h>
+#include <Library/SteppingLib.h>
+#include <Library/ConfigBlockLib.h>
+
+
+/**
+ Set Mmc ExtCsd register
+
+ @param[in] PeiCardData Pointer to CARD_DATA
+ @param[in] Index
+ @param[in] Value
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcSetExtCsd8 (
+ IN CARD_DATA *CardData,
+ IN UINT8 Index,
+ IN UINT8 Value
+ );
+
+EFI_EVENT mSetEmmcWpOnEvent = NULL;
+
+
+/**
+ Check card status, print the debug info and check the error
+
+ @param[in] Status Status got from card status register
+
+ @retval EFI_DEVICE_ERROR
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+CheckCardStatus (
+ IN UINT32 Status
+ )
+{
+ CARD_STATUS *CardStatus;
+ CardStatus = (CARD_STATUS *) (&Status);
+
+ if (CardStatus->ADDRESS_OUT_OF_RANGE) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_OUT_OF_RANGE\n"));
+ }
+
+ if (CardStatus->ADDRESS_MISALIGN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_MISALIGN\n"));
+ }
+
+ if (CardStatus->BLOCK_LEN_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: BLOCK_LEN_ERROR\n"));
+ }
+
+ if (CardStatus->ERASE_SEQ_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_SEQ_ERROR\n"));
+ }
+
+ if (CardStatus->ERASE_PARAM) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_PARAM\n"));
+ }
+
+ if (CardStatus->WP_VIOLATION) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: WP_VIOLATION\n"));
+ }
+
+ if (CardStatus->CARD_IS_LOCKED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CARD_IS_LOCKED\n"));
+ }
+
+ if (CardStatus->LOCK_UNLOCK_FAILED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: LOCK_UNLOCK_FAILED\n"));
+ }
+
+ if (CardStatus->COM_CRC_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: COM_CRC_ERROR\n"));
+ }
+
+ if (CardStatus->ILLEGAL_COMMAND) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ILLEGAL_COMMAND\n"));
+ }
+
+ if (CardStatus->CARD_ECC_FAILED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CARD_ECC_FAILED\n"));
+ }
+
+ if (CardStatus->CC_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CC_ERROR\n"));
+ }
+
+ if (CardStatus->ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERROR\n"));
+ }
+
+ if (CardStatus->UNDERRUN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: UNDERRUN\n"));
+ }
+
+ if (CardStatus->OVERRUN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: OVERRUN\n"));
+ }
+
+ if (CardStatus->CID_CSD_OVERWRITE) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CID_CSD_OVERWRITE\n"));
+ }
+
+ if (CardStatus->WP_ERASE_SKIP) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: WP_ERASE_SKIP\n"));
+ }
+
+ if (CardStatus->ERASE_RESET) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_RESET\n"));
+ }
+
+ if (CardStatus->SWITCH_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: SWITCH_ERROR\n"));
+ }
+
+ if ((Status & 0xFCFFA080) != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Send command by using Host IO protocol
+
+ @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] Argument Command argument to set the argument field of command register
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out
+ @param[in] Buffer Contains the data read from / write to the device
+ @param[in] BufferSize The size of the buffer
+ @param[in] ResponseType RESPONSE_TYPE
+ @param[in] TimeOut Time out value in 1 ms unit
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SendCommand (
+ IN EFI_MMC_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+
+ EFI_STATUS Status;
+
+ Status = This->SendCommand (
+ This,
+ CommandIndex,
+ Argument,
+ DataType,
+ Buffer,
+ BufferSize,
+ ResponseType,
+ TimeOut,
+ ResponseData
+ );
+ if (!EFI_ERROR (Status)) {
+ if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {
+ if (ResponseData == NULL) {
+ ASSERT(ResponseData != NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = CheckCardStatus (*ResponseData);
+ }
+ } else {
+ This->ResetMmcHost (This, Reset_DAT_CMD);
+ }
+
+ return Status;
+}
+
+
+/**
+ Send the card APP_CMD command with the following command indicated
+ by CommandIndex
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] Argument Command argument to set the argument field of command register
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out
+ @param[in] Buffer Contains the data read from / write to the device
+ @param[in] BufferSize The size of the buffer
+ @param[in] ResponseType RESPONSE_TYPE
+ @param[in] TimeOut Time out value in 1 ms unit
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SendAppCommand (
+ IN CARD_DATA *CardData,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ UINT8 Index;
+
+ MmcHostIo = CardData->MmcHostIo;
+ Status = EFI_SUCCESS;
+
+ for (Index = 0; Index < 2; Index++) {
+ Status = MmcHostIo->SendCommand (
+ MmcHostIo,
+ APP_CMD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = CheckCardStatus (*(UINT32 *) &(CardData->CardStatus));
+ if (CardData->CardStatus.SAPP_CMD != 1) {
+ Status = EFI_DEVICE_ERROR;
+ }
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ } else {
+ MmcHostIo->ResetMmcHost (MmcHostIo, Reset_Auto);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = MmcHostIo->SendCommand (
+ MmcHostIo,
+ CommandIndex,
+ Argument,
+ DataType,
+ Buffer,
+ BufferSize,
+ ResponseType,
+ TimeOut,
+ ResponseData
+ );
+ if (!EFI_ERROR (Status)) {
+ if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {
+ if (ResponseData == NULL) {
+ ASSERT(ResponseData != NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = CheckCardStatus (*ResponseData);
+ }
+ } else {
+ MmcHostIo->ResetMmcHost (MmcHostIo, Reset_Auto);
+ }
+
+ return Status;
+}
+
+
+/**
+ Dump Mmc Decode OCR register
+
+ @param[in] OCRReg Pointer to OCR
+
+ @retval None
+
+**/
+EFI_STATUS
+MmcDecodeOCR (
+ IN OCR *OCRReg
+ )
+{
+ DEBUG ((DEBUG_INFO, "\n==========DECODE MMC OCR REGISTER==================\n"));
+ DEBUG ((DEBUG_INFO, " OCR = 0x%08X\n", *((UINT32 *) OCRReg)));
+ DEBUG ((DEBUG_INFO, " CARD_NOT_BUSY = 0x%X\n", OCRReg->Busy));
+ DEBUG ((DEBUG_INFO, " ACCESS_MODE = 0x%X\n", OCRReg->AccessMode));
+ DEBUG ((DEBUG_INFO, " VDD_270_360 = 0x%X\n", OCRReg->V270_V360));
+ DEBUG ((DEBUG_INFO, " VDD_200_260 = 0x%X\n", OCRReg->V200_V260));
+ DEBUG ((DEBUG_INFO, " VDD_170_195 = 0x%X\n", OCRReg->V170_V195));
+ DEBUG ((DEBUG_INFO, "==================================================\n"));
+ return 0;
+}
+
+
+/**
+ Dump Mmc Decode CID value
+
+ @param[in] CIDReg Pointer to CIDReg
+
+ @retval None
+
+**/
+EFI_STATUS
+MmcDecodeCID (
+ IN CID *CIDReg
+ )
+{
+ UINT32 i = 0;
+
+ DEBUG ((EFI_D_INFO, "\n==========DECODE MMC CID REGISTER==================\n"));
+ DEBUG ((EFI_D_INFO, " CID = 0x%032X\n", CIDReg));
+ DEBUG ((EFI_D_INFO, " MANUFACTURER_ID = 0x%X\n", CIDReg->MID));
+ DEBUG ((EFI_D_INFO, " CARD_OR_BGA = 0x%X\n", (CIDReg->OID & 0xFF00)>>6));
+ DEBUG ((EFI_D_INFO, " OEM_APPLICATION_ID = 0x%X\n", (CIDReg->OID>>8) &0xFF));
+ DEBUG ((EFI_D_INFO, " PRODUCT_NAME = "));
+
+ for (i=0; i < 6; i++) {
+ DEBUG ((EFI_D_INFO, "%c", CIDReg->PNM[i]));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+ DEBUG ((EFI_D_INFO, " PRODUCT_REVISION = 0x%X\n", CIDReg->PRV));
+ DEBUG ((EFI_D_INFO, " PRODUCT_SERIAL_NUM = 0x%X\n", CIDReg->PSN));
+ DEBUG ((EFI_D_INFO, " MANUFACTURE_DATE = 0x%X\n", CIDReg->MDT));
+ DEBUG ((EFI_D_INFO, "==================================================\n"));
+ return 0;
+}
+
+
+/**
+ Dump Mmc Decode CSD value
+
+ @param[in] CSDReg Pointer to CSDReg
+
+ @retval None
+
+**/
+EFI_STATUS
+MmcDecodeCSD (
+ IN CSD *CSDReg
+ )
+{
+ DEBUG ((EFI_D_INFO, "\n==========DECODE MMC CSD REGISTER==================\n"));
+ DEBUG ((EFI_D_INFO, "csd_struct : [0x%0x] \n", CSDReg->CSD_STRUCTURE));
+ DEBUG ((EFI_D_INFO, "specs_ver : [0x%0x] \n", CSDReg->SPEC_VERS));
+ DEBUG ((EFI_D_INFO, "reserve2 : [0x%0x] \n", CSDReg->Reserved2));
+ DEBUG ((EFI_D_INFO, "taac : [0x%0x] \n", CSDReg->TAAC));
+ DEBUG ((EFI_D_INFO, "nsac : [0x%0x] \n", CSDReg->NSAC));
+ DEBUG ((EFI_D_INFO, "tran_speed : [0x%0x] \n", CSDReg->TRAN_SPEED));
+ DEBUG ((EFI_D_INFO, "ccc : [0x%0x] \n", CSDReg->CCC));
+ DEBUG ((EFI_D_INFO, "read_bl_len : [0x%0x] \n", CSDReg->READ_BL_LEN));
+ DEBUG ((EFI_D_INFO, "read_partial : [0x%0x] \n", CSDReg->READ_BL_PARTIAL));
+ DEBUG ((EFI_D_INFO, "write_misalign : [0x%0x] \n", CSDReg->WRITE_BLK_MISALIGN));
+ DEBUG ((EFI_D_INFO, "read_misalign : [0x%0x] \n", CSDReg->READ_BLK_MISALIGN));
+ DEBUG ((EFI_D_INFO, "dsr_imp : [0x%0x] \n", CSDReg->DSR_IMP));
+ DEBUG ((EFI_D_INFO, "reserve1 : [0x%0x] \n", CSDReg->Reserved1));
+ DEBUG ((EFI_D_INFO, "c_size : [0x%0x] \n", CSDReg->C_SIZELow2 | CSDReg->C_SIZEHigh10<<2));
+ DEBUG ((EFI_D_INFO, "vdd_r_curr_min : [0x%0x] \n", CSDReg->VDD_R_CURR_MIN));
+ DEBUG ((EFI_D_INFO, "vdd_r_curr_max : [0x%0x] \n", CSDReg->VDD_R_CURR_MAX));
+ DEBUG ((EFI_D_INFO, "vdd_w_curr_min : [0x%0x] \n", CSDReg->VDD_W_CURR_MIN));
+ DEBUG ((EFI_D_INFO, "vdd_w_curr_max : [0x%0x] \n", CSDReg->VDD_W_CURR_MAX));
+ DEBUG ((EFI_D_INFO, "c_size_mult : [0x%0x] \n", CSDReg->C_SIZE_MULT));
+ DEBUG ((EFI_D_INFO, "erase_grp_size : [0x%0x] \n", CSDReg->ERASE_GRP_SIZE));
+ DEBUG ((EFI_D_INFO, "erase_grp_mult : [0x%0x] \n", CSDReg->ERASE_GRP_MULT));
+ DEBUG ((EFI_D_INFO, "wp_grp_size : [0x%0x] \n", CSDReg->WP_GRP_SIZE));
+ DEBUG ((EFI_D_INFO, "wp_grp_enable : [0x%0x] \n", CSDReg->WP_GRP_ENABLE));
+ DEBUG ((EFI_D_INFO, "default_ecc : [0x%0x] \n", CSDReg->DEFAULT_ECC));
+ DEBUG ((EFI_D_INFO, "r2w_factor : [0x%0x] \n", CSDReg->R2W_FACTOR));
+ DEBUG ((EFI_D_INFO, "write_bl_len : [0x%0x] \n", CSDReg->WRITE_BL_LEN));
+ DEBUG ((EFI_D_INFO, "write_partial : [0x%0x] \n", CSDReg->WRITE_BL_PARTIAL));
+ DEBUG ((EFI_D_INFO, "reserve0 : [0x%0x] \n", CSDReg->Reserved0));
+ DEBUG ((EFI_D_INFO, "content_prot_app : [0x%0x] \n", CSDReg->CONTENT_PROT_APP));
+ DEBUG ((EFI_D_INFO, "file_format_grp : [0x%0x] \n", CSDReg->FILE_FORMAT_GRP));
+ DEBUG ((EFI_D_INFO, "copy : [0x%0x] \n", CSDReg->COPY));
+ DEBUG ((EFI_D_INFO, "perm_write_protect: [0x%0x] \n", CSDReg->PERM_WRITE_PROTECT));
+ DEBUG ((EFI_D_INFO, "tmp_write_prot : [0x%0x] \n", CSDReg->TMP_WRITE_PROTECT));
+ DEBUG ((EFI_D_INFO, "file_format : [0x%0x] \n", CSDReg->FILE_FORMAT));
+ DEBUG ((EFI_D_INFO, "ecc : [0x%0x] \n", CSDReg->ECC));
+ DEBUG ((EFI_D_INFO, "==================================================\n"));
+
+ return 0;
+}
+
+
+/**
+ Dump Mmc Decode Ext CSD value
+
+ @param[in] ExtCSDReg Pointer to ExtCSDReg
+
+ @retval None
+
+**/
+EFI_STATUS
+MmcDecodeExtCSD (
+ IN EXT_CSD *ExtCSDReg
+ )
+{
+ DEBUG ((EFI_D_INFO, "\n==========DECODE MMC EXT CSD REGISTER==================\n"));
+ DEBUG ((EFI_D_INFO, " SUPPORTED_CMD_SETS = 0x%X\n", ExtCSDReg->CMD_SET));
+ DEBUG ((EFI_D_INFO, " HPI_FEATURES = 0x%X\n", ExtCSDReg->HPI_FEATURES));
+ DEBUG ((EFI_D_INFO, " BKOPS_SUPPORT = 0x%X\n", ExtCSDReg->BKOPS_SUPPORT));
+ DEBUG ((EFI_D_INFO, " BKOPS_STATUS = 0x%X\n", ExtCSDReg->BKOPS_STATUS));
+ DEBUG ((EFI_D_INFO, " CORRECTLY_PRG_SECTORS_NUM = 0x%X%X%X%X\n", ExtCSDReg->CORRECTLY_PRG_SECTORS_NUM[3], \
+ ExtCSDReg->CORRECTLY_PRG_SECTORS_NUM[2], ExtCSDReg->CORRECTLY_PRG_SECTORS_NUM[1], ExtCSDReg->CORRECTLY_PRG_SECTORS_NUM[0]));
+ DEBUG ((EFI_D_INFO, " INI_TIMEOUT_AP = 0x%X\n", ExtCSDReg->INI_TIMEOUT_AP));
+ DEBUG ((EFI_D_INFO, " PWR_CL_DDR_52_195 = 0x%X\n", ExtCSDReg->PWR_CL_DDR_52_195));
+ DEBUG ((EFI_D_INFO, " PWR_CL_DDR_52_360 = 0x%X\n", ExtCSDReg->PWR_CL_DDR_52_360));
+ DEBUG ((EFI_D_INFO, " MIN_PRF_DDR_W_8_52 = 0x%X\n", ExtCSDReg->MIN_PERF_DDR_W_8_52));
+ DEBUG ((EFI_D_INFO, " MIN_PRF_DDR_R_8_52 = 0x%X\n", ExtCSDReg->MIN_PERF_DDR_R_8_52));
+ DEBUG ((EFI_D_INFO, " TRIM_MULT = 0x%X\n", ExtCSDReg->TRIM_MULT));
+ DEBUG ((EFI_D_INFO, " SEC_FEATURE_SUPP = 0x%X\n", ExtCSDReg->SEC_FEATURE_SUPPORT));
+ DEBUG ((EFI_D_INFO, " SEC_ERASE_MULT = 0x%X\n", ExtCSDReg->SEC_ERASE_MULT));
+ DEBUG ((EFI_D_INFO, " SEC_TRIM_MULT = 0x%X\n", ExtCSDReg->SEC_TRIM_MULT));
+ DEBUG ((EFI_D_INFO, " BOOT_INFO = 0x%X\n", ExtCSDReg->BOOT_INFO));
+ DEBUG ((EFI_D_INFO, " BOOT_PART_SIZE = 0x%X\n", ExtCSDReg->BOOT_SIZE_MULTI));
+ DEBUG ((EFI_D_INFO, " ACCESS_SIZE = 0x%X\n", ExtCSDReg->ACC_SIZE));
+ DEBUG ((EFI_D_INFO, " HI_CAP_ER_GRP_SIZE = 0x%X\n", ExtCSDReg->HC_ERASE_GRP_SIZE));
+ DEBUG ((EFI_D_INFO, " HI_CAP_ER_TIMEOUT = 0x%X\n", ExtCSDReg->ERASE_TIMEOUT_MULT));
+ DEBUG ((EFI_D_INFO, " REL_WR_SECTOR_CNT = 0x%X\n", ExtCSDReg->REL_WR_SEC_C));
+ DEBUG ((EFI_D_INFO, " HI_CAP_WP_GRP_SIZE = 0x%X\n", ExtCSDReg->HC_WP_GRP_SIZE));
+ DEBUG ((EFI_D_INFO, " SLEEP_CURRENT_VCC = 0x%X\n", ExtCSDReg->S_C_VCC));
+ DEBUG ((EFI_D_INFO, " SLEEP_CURRENT_VCCQ = 0x%X\n", ExtCSDReg->S_C_VCCQ));
+ DEBUG ((EFI_D_INFO, " SLP_AWK_TIMEOUT = 0x%X\n", ExtCSDReg->S_A_TIMEOUT));
+ DEBUG ((EFI_D_INFO, " SECTOR_COUNT = 0x%X\n", *(UINT32*) ((UINT8 *) &ExtCSDReg->SEC_COUNT)));
+ DEBUG ((EFI_D_INFO, " MIN_PERF_W_8_52 = 0x%X\n", ExtCSDReg->MIN_PERF_W_8_52));
+ DEBUG ((EFI_D_INFO, " MIN_PERF_R_8_52 = 0x%X\n", ExtCSDReg->MIN_PERF_R_8_52));
+ DEBUG ((EFI_D_INFO, " MIN_PERF_W_8_26_4_52 = 0x%X\n", ExtCSDReg->MIN_PERF_W_8_26_4_52));
+ DEBUG ((EFI_D_INFO, " MIN_PERF_W_8_26_4_52 = 0x%X\n", ExtCSDReg->MIN_PERF_W_8_26_4_52));
+ DEBUG ((EFI_D_INFO, " MIN_PERF_W_4_26 = 0x%X\n", ExtCSDReg->MIN_PERF_W_4_26));
+ DEBUG ((EFI_D_INFO, " MIN_PERF_R_4_26 = 0x%X\n", ExtCSDReg->MIN_PERF_R_4_26));
+ DEBUG ((EFI_D_INFO, " PWR_CLASS_26_360 = 0x%X\n", ExtCSDReg->PWR_CL_26_360));
+ DEBUG ((EFI_D_INFO, " PWR_CLASS_52_360 = 0x%X\n", ExtCSDReg->PWR_CL_52_360));
+ DEBUG ((EFI_D_INFO, " PWR_CLASS_26_195 = 0x%X\n", ExtCSDReg->PWR_CL_26_195));
+ DEBUG ((EFI_D_INFO, " PWR_CLASS_52_195 = 0x%X\n", ExtCSDReg->PWR_CL_52_195));
+ DEBUG ((EFI_D_INFO, " PARTITION_SWITCH_TIME = 0x%X\n", ExtCSDReg->PARTITION_SWITCH_TIME));
+ DEBUG ((EFI_D_INFO, " OUT_OF_INTERRUPT_TIME = 0x%X\n", ExtCSDReg->OUT_OF_INTERRUPT_TIME));
+ DEBUG ((EFI_D_INFO, " CARD_TYPE = 0x%X\n", ExtCSDReg->CARD_TYPE));
+ DEBUG ((EFI_D_INFO, " CSD_STRUCTURE = 0x%X\n", ExtCSDReg->CSD_STRUCTURE));
+ DEBUG ((EFI_D_INFO, " EXT_CSD_REV = 0x%X\n", ExtCSDReg->EXT_CSD_REV));
+ DEBUG ((EFI_D_INFO, " CMD_SET = 0x%X\n", ExtCSDReg->CMD_SET));
+ DEBUG ((EFI_D_INFO, " CMD_SET_REV = 0x%X\n", ExtCSDReg->CMD_SET_REV));
+ DEBUG ((EFI_D_INFO, " PWR_CLASS = 0x%X\n", ExtCSDReg->POWER_CLASS));
+ DEBUG ((EFI_D_INFO, " HI_SPEED_TIMING = 0x%X\n", ExtCSDReg->HS_TIMING));
+ DEBUG ((EFI_D_INFO, " BUS_WIDTH_MODE = 0x%X\n", ExtCSDReg->BUS_WIDTH));
+ DEBUG ((EFI_D_INFO, " ERASED_MEM_CONTENT = 0x%X\n", ExtCSDReg->ERASED_MEM_CONT));
+ DEBUG ((EFI_D_INFO, " PARTITION_CONFIG = 0x%X\n", ExtCSDReg->PARTITION_CONFIG));
+ DEBUG ((EFI_D_INFO, " BOOT_CONFIG_PROT = 0x%X\n", ExtCSDReg->BOOT_CONFIG_PROT));
+ DEBUG ((EFI_D_INFO, " BOOT_BUS_WIDTH = 0x%X\n", ExtCSDReg->BOOT_BUS_WIDTH));
+ DEBUG ((EFI_D_INFO, " HI_DEN_ER_GRP_DEF = 0x%X\n", ExtCSDReg->ERASE_GROUP_DEF));
+ DEBUG ((EFI_D_INFO, " BOOT_WP = 0x%X\n", ExtCSDReg->BOOT_WP));
+ DEBUG ((EFI_D_INFO, " USER_WP = 0x%X\n", ExtCSDReg->USER_WP));
+ DEBUG ((EFI_D_INFO, " FW_CONFIG = 0x%X\n", ExtCSDReg->FW_CONFIG));
+ DEBUG ((EFI_D_INFO, " RPMB_SIZE_MULT = 0x%X\n", ExtCSDReg->RPMB_SIZE_MULT));
+ DEBUG ((EFI_D_INFO, " RST_N_FUNCTION = 0x%X\n", ExtCSDReg->RST_n_FUNCTION));
+ DEBUG ((EFI_D_INFO, " PARTITIONING_SUPP = 0x%X\n", ExtCSDReg->PARTITIONING_SUPPORT));
+ DEBUG ((EFI_D_INFO, " MAX_ENH_SIZE_MULT = 0x%02X%02X%02X\n", ExtCSDReg->MAX_ENH_SIZE_MULT[2],ExtCSDReg->MAX_ENH_SIZE_MULT[1], ExtCSDReg->MAX_ENH_SIZE_MULT[0]));
+ DEBUG ((EFI_D_INFO, " PART_ATTRIBUTE = 0x%X\n", ExtCSDReg->PARTITIONS_ATTRIBUTES));
+ DEBUG ((EFI_D_INFO, " PART_SETTING_COMP = 0x%X\n", ExtCSDReg->PARTITION_SETTING_COMPLETED));
+ DEBUG ((EFI_D_INFO, " GP_SIZE_MULT = 0x%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", ExtCSDReg->GP_SIZE_MULT_4[2], ExtCSDReg->GP_SIZE_MULT_4[1], ExtCSDReg->GP_SIZE_MULT_4[0],
+ ExtCSDReg->GP_SIZE_MULT_3[2], ExtCSDReg->GP_SIZE_MULT_3[1], ExtCSDReg->GP_SIZE_MULT_3[0],
+ ExtCSDReg->GP_SIZE_MULT_2[2], ExtCSDReg->GP_SIZE_MULT_2[1], ExtCSDReg->GP_SIZE_MULT_2[0],
+ ExtCSDReg->GP_SIZE_MULT_1[2], ExtCSDReg->GP_SIZE_MULT_1[1], ExtCSDReg->GP_SIZE_MULT_1[0]));
+ DEBUG ((EFI_D_INFO, " ENH_SIZE_MULT = 0x%02X%02X%02X\n", ExtCSDReg->ENH_SIZE_MULT[2], ExtCSDReg->ENH_SIZE_MULT[1], ExtCSDReg->ENH_SIZE_MULT[0]));
+ DEBUG ((EFI_D_INFO, " ENH_START_ADDR = 0x%02X%02X%02X%02X\n", ExtCSDReg->ENH_START_ADDR[3], ExtCSDReg->ENH_START_ADDR[2], ExtCSDReg->ENH_START_ADDR[1], ExtCSDReg->ENH_START_ADDR[0]));
+ DEBUG ((EFI_D_INFO, " SEC_BAD_BLK_MGMNT = 0x%X\n", ExtCSDReg->SEC_BAD_BLOCK_MGMNT));
+ DEBUG ((EFI_D_INFO, "==================================================\n"));
+
+ return 0;
+}
+
+
+/**
+ Send the card FAST_IO command
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] RegisterAddress Register Address
+ @param[in, out] RegisterData Pointer to register Data
+ @param[in] Write TRUE for write, FALSE for read
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+FastIO (
+ IN CARD_DATA *CardData,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT8 *RegisterData,
+ IN BOOLEAN Write
+ )
+{
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ EFI_STATUS Status;
+ UINT32 Argument;
+ UINT32 Data;
+
+ Status = EFI_SUCCESS;
+ MmcHostIo = CardData->MmcHostIo;
+
+ if (RegisterData == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Argument = (CardData->Address << 16) | (RegisterAddress << 8);
+ if (Write) {
+ Argument |= BIT15 | (*RegisterData);
+ }
+
+ Status = SendCommand (
+ MmcHostIo,
+ FAST_IO,
+ Argument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR4,
+ TIMEOUT_COMMAND,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Data & BIT15) == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ if (!Write) {
+ *RegisterData = (UINT8)Data;
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Send the card GO_INACTIVE_STATE command
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+PutCardInactive (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ EFI_STATUS Status;
+
+ MmcHostIo = CardData->MmcHostIo;
+
+ Status = SendCommand (
+ MmcHostIo,
+ GO_INACTIVE_STATE,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+
+ gBS->Stall(1000);
+
+ return Status;
+}
+
+
+/**
+ Get card interested information for CSD rergister
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+CalculateCardParameter (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Frequency;
+ UINT32 Multiple;
+ UINT32 CSize;
+ CSD_SDV2 *CsdSDV2;
+
+ Status = EFI_SUCCESS;
+
+ switch (CardData->CSDRegister.TRAN_SPEED & 0x7) {
+ case 0:
+ Frequency = 100 * 1000;
+ break;
+
+ case 1:
+ Frequency = 1 * 1000 * 1000;
+ break;
+
+ case 2:
+ Frequency = 10 * 1000 * 1000;
+ break;
+
+ case 3:
+ Frequency = 100 * 1000 * 1000;
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "Invalid CSD TRAN_SPEED Frequency: 0x%x\n", CardData->CSDRegister.TRAN_SPEED & 0x7));
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ switch ((CardData->CSDRegister.TRAN_SPEED >> 3) & 0xF) {
+ case 1:
+ Multiple = 10;
+ break;
+
+ case 2:
+ Multiple = 12;
+ break;
+
+ case 3:
+ Multiple = 13;
+ break;
+
+ case 4:
+ Multiple = 15;
+ break;
+
+ case 5:
+ Multiple = 20;
+ break;
+
+ case 6:
+ if (CardData->CardType == MMCCard) {
+ Multiple = 26;
+ } else {
+ Multiple = 25;
+ }
+ break;
+
+ case 7:
+ Multiple = 30;
+ break;
+
+ case 8:
+ Multiple = 35;
+ break;
+
+ case 9:
+ Multiple = 40;
+ break;
+
+ case 10:
+ Multiple = 45;
+ break;
+
+ case 11:
+ if (CardData->CardType == MMCCard) {
+ Multiple = 52;
+ } else {
+ Multiple = 50;
+ }
+ break;
+
+ case 12:
+ Multiple = 55;
+ break;
+
+ case 13:
+ Multiple = 60;
+ break;
+
+ case 14:
+ Multiple = 70;
+ break;
+
+ case 15:
+ Multiple = 80;
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "CalculateCardParameter: Invalid CSD TRAN_SPEED Multiple: 0x%x\n", CardData->CSDRegister.TRAN_SPEED >> 3));
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Frequency = Frequency * Multiple / 10;
+ CardData->MaxFrequency = Frequency;
+
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2) ||
+ (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) {
+ CardData->BlockLen = 512;
+ } else {
+ CardData->BlockLen = 1 << CardData->CSDRegister.READ_BL_LEN;
+ }
+
+ if (CardData->CardType == SdMemoryCard2High) {
+ ASSERT(CardData->CSDRegister.CSD_STRUCTURE == 1);
+ CsdSDV2 = (CSD_SDV2 *) &CardData->CSDRegister;
+ //
+ // the K here means 1024 not 1000
+ //
+ CardData->BlockNumber = DivU64x32 (MultU64x32 (CsdSDV2->C_SIZE + 1, 512 * 1024) , CardData->BlockLen);
+ } else {
+ //
+ // For MMC card > 2G, the block number will be recaculate later
+ //
+ CSize = CardData->CSDRegister.C_SIZELow2 | (CardData->CSDRegister.C_SIZEHigh10 << 2);
+ CardData->BlockNumber = MultU64x32 (LShiftU64 (1, CardData->CSDRegister.C_SIZE_MULT + 2), CSize + 1);
+ }
+
+ //
+ //For >= 2G card, BlockLen may be 1024, but the transfer size is still 512 bytes
+ //
+ if (CardData->BlockLen > 512) {
+ CardData->BlockNumber = DivU64x32 (MultU64x32 (CardData->BlockNumber, CardData->BlockLen), 512);
+ CardData->BlockLen = 512;
+ }
+
+ DEBUG ((DEBUG_INFO, "CalculateCardParameter: Card Size: 0x%lx\n", MultU64x32 (CardData->BlockNumber, CardData->BlockLen)
+ ));
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Test the bus width setting for MMC card
+ It is used only for verification purpose
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Width 1, 4, 8 bits
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MMCCardBusWidthTest (
+ IN CARD_DATA *CardData,
+ IN UINT32 Width
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ UINT64 Data;
+ UINT64 Value;
+
+ if (CardData == NULL) {
+ ASSERT(CardData != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmcHostIo = CardData->MmcHostIo;
+ Value = 0;
+
+ switch (Width) {
+ case 1:
+ Data = 0x80;
+ break;
+
+ case 4:
+ Data = 0x5A;
+ break;
+
+ case 8:
+ Data = 0xAA55;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ CopyMem (CardData->AlignedBuffer, &Data, Width);
+ Status = SendCommand (
+ MmcHostIo,
+ BUSTEST_W,
+ 0,
+ OutData,
+ CardData->AlignedBuffer,
+ Width,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Data = 0;
+ gBS->Stall(10000);
+
+ Status = SendCommand (
+ MmcHostIo,
+ BUSTEST_R,
+ 0,
+ InData,
+ CardData->AlignedBuffer,
+ Width,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CopyMem (&Data, CardData->AlignedBuffer, Width);
+
+ switch (Width) {
+ case 1:
+ Value = (~(Data ^ 0x80)) & 0xC0;
+ break;
+ case 4:
+ Value = (~(Data ^ 0x5A)) & 0xFF;
+ break;
+ case 8:
+ Value = (~(Data ^ 0xAA55)) & 0xFFFF;
+ break;
+ }
+
+ if (Value == 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ This function can detect these card types
+ 1. MMC card
+ 2. SD 1.1 card
+ 3. SD 2.0 standard card
+ 3. SD 2.0 high capacity card
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+GetCardType (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ UINT32 TimeOut=5000;
+ MmcHostIo = CardData->MmcHostIo;
+
+ CardData->CardType = MMCCard;
+ MmcHostIo->SetupDevice (MmcHostIo);
+
+ //
+ // To bring back the normal MMC card to work
+ // after sending the SD command. Otherwise some
+ // card could not work
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ GO_IDLE_STATE,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));
+ }
+
+ DEBUG (( DEBUG_INFO, "Sending first CMD1.\n"));
+
+ //
+ // CE-ATA device needs long delay
+ //
+ gBS->Stall (1 * 1000);
+
+ //
+ // Get OCR register to check voltage support, first time the OCR is 0
+ //
+ DEBUG (( DEBUG_INFO, "Sending first CMD1 with 0 .\n"));
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_OP_COND,
+ 0x0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->OCRRegister)
+ );
+
+ DEBUG ((DEBUG_INFO, "Check OCR register for busy 0x%x\n", *((UINT32 *) &CardData->OCRRegister )));
+
+ gBS->Stall (1 * 1000);
+
+ while (CardData->OCRRegister.Busy != 1) {
+ CardData->OCRRegister.AccessMode = 2;
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_OP_COND,
+ *(UINT32 *) &(CardData->OCRRegister),
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->OCRRegister)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ gBS->Stall (1 * 1000);
+ TimeOut--;
+ if (TimeOut == 0) {
+ DEBUG ((EFI_D_ERROR, "Card is always in busy state\n"));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ MMC card high/low voltage selection function
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+ @retval EFI_BAD_BUFFER_SIZE
+
+**/
+EFI_STATUS
+MMCCardVoltageSelection (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ UINT8 Index;
+ UINT8 Retry;
+ UINT32 TimeOut;
+
+ MmcHostIo = CardData->MmcHostIo;
+ Status = EFI_SUCCESS;
+
+ if (FALSE) {
+ //
+ //First try the high voltage, then if supported choose the low voltage
+ //
+ for (Index = 0; Index < 2; Index++) {
+ for (Retry = 0; Retry < 3; Retry++) {
+ //
+ // To bring back the normal MMC card to work
+ // after sending the SD command. Otherwise some
+ // card could not work
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ GO_IDLE_STATE,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));
+ continue;
+ }
+ //
+ //CE-ATA device needs long delay
+ //
+ gBS->Stall ((Retry + 1) * 50 * 1000);
+
+ //
+ //Get OCR register to check voltage support, first time the OCR is 0
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_OP_COND,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->OCRRegister)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (Retry == 3) {
+ DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ if (CardData->OCRRegister.V170_V195 == 1) {
+ CardData->DualVoltage = TRUE;
+ }
+ if (CardData->OCRRegister.V270_V360 != 0x1F &&
+ CardData->OCRRegister.V200_V260 != 0) {
+ DEBUG ((EFI_D_ERROR, "Incompatiable voltage device\n"));
+ PutCardInactive (CardData);
+ Status = EFI_INCOMPATIBLE_VERSION;
+ goto Exit;
+ }
+
+ if (Index == 0) {
+ //
+ // Choose the high voltage first
+ //
+ CardData->OCRRegister.V170_V195 = 0;
+ } else {
+ //
+ // Choose the low voltage
+ //
+ CardData->OCRRegister.V170_V195 = 1;
+ CardData->OCRRegister.V270_V360 = 0;
+ }
+
+ //
+ // Set sector mode
+ //
+ CardData->OCRRegister.AccessMode |= 2;
+
+ //
+ // TimeOut Value, 5000 * 100 * 1000 = 5 s
+ //
+ TimeOut = 5000;
+
+ do {
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_OP_COND,
+ *(UINT32 *) &(CardData->OCRRegister),
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->OCRRegister)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ gBS->Stall (1 * 1000);
+ TimeOut--;
+ if (TimeOut == 0) {
+ DEBUG ((EFI_D_ERROR, "Card is always in busy state\n"));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ } while (CardData->OCRRegister.Busy != 1);
+
+ if (CardData->DualVoltage == TRUE && MmcHostIo->HostCapability.V18Support == TRUE) {
+ //
+ //Power Off the card and then power on into low voltage
+ //
+ MmcHostIo->SetHostVoltage (MmcHostIo, 0);
+ gBS->Stall (1 * 1000);
+ MmcHostIo->SetHostVoltage (MmcHostIo, 18);
+ } else {
+ //
+ //Not support the low voltage, exit
+ //
+ break;
+ }
+ }
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ This function set the bus and device width for MMC card
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] BusWidth 1, 4, 8 bits
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MMCCardSetBusWidth (
+ IN CARD_DATA *CardData,
+ IN UINT8 BusWidth
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ SWITCH_ARGUMENT SwitchArgument;
+ UINT8 Value;
+
+ MmcHostIo = CardData->MmcHostIo;
+ Value = 0;
+ switch (BusWidth) {
+ case 28: //20 in 28 indicates DDR in 8 bit bus
+ Value = 6;
+ break;
+
+ case 24: //20 in 24 indicates DDR in 4 bit bus
+ Value = 5;
+ break;
+
+ case 8:
+ Value = 2;
+ break;
+
+ case 4:
+ Value = 1;
+ break;
+
+ case 1:
+ Value = 0;
+ break;
+
+ default:
+ ASSERT (0);
+ }
+
+ //
+ // HS_TIMING must be set to 0x1 before setting BUS_WIDTH for dual data rate operation (values 5 or 6)
+ //
+ if (Value == 5 || Value == 6 ) {
+ ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = 0x1;
+ SwitchArgument.Index = (UINT32) ((UINTN)
+ (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN) (&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ MmcHostIo,
+ SWITCH,
+ *(UINT32 *) &SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ } else {
+ DEBUG ((DEBUG_ERROR, "SWITCH Fail in HS Timing setting\n"));
+ }
+ }
+
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = Value;
+ SwitchArgument.Index = (UINT32) ((UINTN)
+ (&(CardData->ExtCSDRegister.BUS_WIDTH)) - (UINTN) (&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ MmcHostIo,
+ SWITCH,
+ *(UINT32 *) &SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SWITCH %d bits Fail\n", BusWidth));
+ goto Exit;
+ } else {
+ if ((BusWidth == 24) || (BusWidth == 28)) {
+ Status = MmcHostIo->SetBusWidth (MmcHostIo, BusWidth - 20);
+ } else {
+ Status = MmcHostIo->SetBusWidth (MmcHostIo, BusWidth);
+ }
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ gBS->Stall (5 * 1000);
+ }
+ }
+ if ((BusWidth == 24) || (BusWidth == 28)) {
+ goto Exit;
+ } else {
+ Status = MMCCardBusWidthTest (CardData, BusWidth);
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCCardBusWidthTest %d bit Fail\n", BusWidth));
+ goto Exit;
+ }
+
+ CardData->CurrentBusWidth = BusWidth;
+
+Exit:
+ return Status;
+}
+
+
+/**
+ MMC/SD card init function
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+ @retval EFI_BAD_BUFFER_SIZE
+
+**/
+EFI_STATUS
+MMCSDCardInit (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ SWITCH_ARGUMENT SwitchArgument;
+ UINT32 Data;
+ UINT32 Argument;
+ UINT32 HsTimingValue;
+ UINT8 PowerValue;
+ UINT8 DoubleSpeed;
+ UINTN Offset;
+
+ if (CardData == NULL) {
+ ASSERT (CardData != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+ MmcHostIo = CardData->MmcHostIo;
+ CardData->CurrentBusWidth = 1;
+
+ Status = GetCardType (CardData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "GetCardType -> %r\n", Status));
+ goto Exit;
+ }
+
+ ASSERT (CardData->CardType != UnknownCard);
+ //
+ //MMC, SD card need host auto stop command support
+ //
+ MmcHostIo->EnableAutoStopCmd (MmcHostIo, TRUE);
+
+
+ //
+ // Get CID Register, but the info is not used currently
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ ALL_SEND_CID,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR2,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CIDRegister)
+ );
+
+ PcdSet8S (PcdEmmcManufacturerId, CardData->CIDRegister.MID);
+ PcdSet32S (PcdProductSerialNumber, CardData->CIDRegister.PSN);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ALL_SEND_CID -> %r\n", Status));
+ goto Exit;
+ }
+
+ //
+ //SET_RELATIVE_ADDR
+ //
+ if (CardData->CardType == MMCCard) {
+ CardData->Address = 1;
+ //
+ // Set RCA Register
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ SET_RELATIVE_ADDR,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_RELATIVE_ADDR -> %r\n", Status));
+ goto Exit;
+ }
+ }
+
+ //
+ // Get CSD Register
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_CSD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR2,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CSDRegister)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SEND_CSD -> %r\n", Status));
+ goto Exit;
+ }
+
+ MmcDecodeCSD(&CardData->CSDRegister);
+
+ Status = CalculateCardParameter (CardData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CalculateCardParameter -> %r\n", Status));
+ goto Exit;
+ }
+
+ //
+ // Put the card into tran state
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ SELECT_DESELECT_CARD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SELECT_DESELECT_CARD -> %r\n", Status));
+ goto Exit;
+ }
+
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SELECT_DESELECT_CARD SEND_STATUS Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ if (CardData->CardType == MMCCard) {
+ //
+ // Only V4.0 and above supports more than 1 bits and high speed
+ //
+ if (CardData->CSDRegister.SPEC_VERS >= 4) {
+ Offset = OFFSET_OF (EXT_CSD, ERASE_GROUP_DEF);
+ Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, 0x01);
+ //
+ // Get ExtCSDRegister
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_EXT_CSD,
+ 0,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (EXT_CSD),
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SEND_EXT_CSD -> %r\n", Status));
+ goto Exit;
+ }
+
+ CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof (EXT_CSD));
+
+ MmcDecodeExtCSD (&CardData->ExtCSDRegister);
+
+ //
+ // Recaculate the block number for >2G MMC card
+ //
+ Data = (CardData->ExtCSDRegister.SEC_COUNT[0]) |
+ (CardData->ExtCSDRegister.SEC_COUNT[1] << 8) |
+ (CardData->ExtCSDRegister.SEC_COUNT[2] << 16) |
+ (CardData->ExtCSDRegister.SEC_COUNT[3] << 24);
+
+ if (Data != 0) {
+ CardData->BlockNumber = Data;
+ }
+ DEBUG ((DEBUG_INFO, "CardData->BlockNumber %d\n", Data));
+
+ //
+ // Check the DDR setting
+ //
+ DoubleSpeed = 0 ;
+ DEBUG ((DEBUG_INFO, "CardData->ExtCSDRegister.CARD_TYPE -> %d\n", (UINTN) CardData->ExtCSDRegister.CARD_TYPE));
+ if (CardData->ExtCSDRegister.CARD_TYPE & BIT0) {
+ DEBUG ((DEBUG_INFO, "High-Speed e MMC @ 26MHz - at rated device voltage(s) supported\n"));
+ }
+ if (CardData->ExtCSDRegister.CARD_TYPE & BIT1) {
+ DEBUG ((DEBUG_INFO, "High-Speed e MMC @ 52MHz - at rated device voltage(s) supported\n"));
+ }
+ if (CardData->ExtCSDRegister.CARD_TYPE & BIT2) {
+ DEBUG ((DEBUG_INFO, "High-Speed Dual Data Rate e MMC @ 52MHz - 1.8V or 3V I/O supported\n"));
+ }
+ if (CardData->ExtCSDRegister.CARD_TYPE & BIT3) {
+ DEBUG ((DEBUG_INFO, "High-Speed Dual Data Rate e MMC @ 52MHz - 1.2V I/O supported\n"));
+ }
+ if (CardData->ExtCSDRegister.CARD_TYPE & BIT4) {
+ DEBUG ((DEBUG_INFO, "HS200 Single Data Rate e MMC @ 200 MHz - 1.8V I/O supported\n"));
+ }
+ if (CardData->ExtCSDRegister.CARD_TYPE & BIT5) {
+ DEBUG ((DEBUG_INFO, "HS200 Single Data Rate e MMC @ 200 MHz - 1.2V I/O supported\n"));
+ }
+ if (CardData->ExtCSDRegister.CARD_TYPE & BIT6) {
+ DEBUG ((DEBUG_INFO, "HS400 Dual Data Rate e MMC @ 200MHz - 1.8V I/O supported\n"));
+ }
+ if (CardData->ExtCSDRegister.CARD_TYPE & BIT7) {
+ DEBUG ((DEBUG_INFO, "HS400 Dual Data Rate e MMC @ 200MHz - 1.2V I/O supported\n"));
+ }
+
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2) || (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) {
+ DEBUG ((DEBUG_INFO, "Card support DDR\n"));
+ DoubleSpeed = 20; //Add 20 for double speed, decoded in MMCCardSetBusWidth()
+ }
+
+ DEBUG ((EFI_D_INFO, "%a(%d): %a() no more FPGA doublespeed workaround needed\n", __FILE__, __LINE__, __FUNCTION__));
+
+ if (MmcHostIo->HostCapability.HighSpeedSupport) {
+
+ HsTimingValue = 1;
+
+ //
+ // Change to high frequency mode
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = HsTimingValue;
+ SwitchArgument.Index = (UINT32) ((UINTN)
+ (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN) (&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ CardData->MmcHostIo,
+ SWITCH,
+ *(UINT32 *) &SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SWITCH frequency -> %r\n", Status));
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Enable the high speed mode
+ //
+ if (DoubleSpeed != 0) {
+ Status = MmcHostIo->SetHostDdrMode (MmcHostIo, TRUE);
+ DEBUG ((DEBUG_INFO, "Set to DDR50 mode \n", Status));
+ } else {
+ Status = MmcHostIo->SetHostSpeedMode (MmcHostIo, 1);
+ DEBUG ((DEBUG_ERROR, "Set to HS mode \n", Status));
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ //
+ // Change host clock
+ //
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ Status = MmcHostIo->SetClockFrequency (MmcHostIo, FREQUENCY_MMC_PP_HIGH);
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ Status = MmcHostIo->SetClockFrequency (MmcHostIo, FREQUENCY_MMC_PP);
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // It seems no need to stall after changing bus freqeuncy.
+ // It is said that the freqeuncy can be changed at any time. Just appends 8 clocks after command.
+ // But SetClock alreay has delay.
+ //
+ }
+ }
+ }
+
+ //
+ // Prefer wide bus width for performance
+ //
+ //
+ // Set to BusWidth bits mode, only version 4.0 or above support more than 1 bits
+ //
+ if (MmcHostIo->HostCapability.BusWidth8 == 1) {
+ Status = MMCCardSetBusWidth (CardData, DoubleSpeed + 8);
+ if (EFI_ERROR (Status)) {
+ //
+ // CE-ATA may support 8 bits and 4 bits, but has no software method for detection
+ //
+ Status = MMCCardSetBusWidth (CardData, DoubleSpeed + 4);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+ } else if (MmcHostIo->HostCapability.BusWidth4 == 1) {
+ Status = MMCCardSetBusWidth (CardData, DoubleSpeed + 4);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+
+ PowerValue = 0;
+
+ if (CardData->CurrentBusWidth == 8) {
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;
+ PowerValue = PowerValue >> 4;
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;
+ PowerValue = PowerValue >> 4;
+ }
+ } else if (CardData->CurrentBusWidth == 4) {
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;
+ PowerValue = PowerValue & 0xF;
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;
+ PowerValue = PowerValue & 0xF;
+ }
+ }
+
+ if (PowerValue != 0) {
+ //
+ // Update Power Class
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = PowerValue;
+ SwitchArgument.Index = (UINT32) ((UINTN)
+ (&(CardData->ExtCSDRegister.POWER_CLASS)) - (UINTN) (&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ MmcHostIo,
+ SWITCH,
+ *(UINT32 *) &SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SWITCH Power Class -> %r\n", Status));
+ }
+
+ }
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "MMC Card version %d only supportes 1 bits at lower transfer speed\n", CardData->CSDRegister.SPEC_VERS));
+ }
+
+ //
+ // Register for Ready to Boot event to enable Write protection
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ SetEmmcWpOnEvent,
+ CardData,
+ &gEfiEventReadyToBootGuid,
+ &mSetEmmcWpOnEvent
+ );
+
+ } else {
+ //
+ // Pin 1, at power up this line has a 50KOhm pull up enabled in the card.
+ // This pull-up should be disconnected by the user, during regular data transfer,
+ // with SET_CLR_CARD_DETECT (ACMD42) command
+ //
+ Status = SendAppCommand (
+ CardData,
+ SET_CLR_CARD_DETECT,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_CLR_CARD_DETECT Fail -> %r\n", Status));
+ goto Exit;
+ }
+
+ //
+ // Set Bus Width to 4
+ //
+ Status = SendAppCommand (
+ CardData,
+ SET_BUS_WIDTH,
+ SD_BUS_WIDTH_4,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_BUS_WIDTH 4 bits -> %r\n", Status));
+ goto Exit;
+ }
+
+ Status = MmcHostIo->SetBusWidth (MmcHostIo, 4);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CardData->CurrentBusWidth = 4;
+
+ if ((MmcHostIo->HostCapability.HighSpeedSupport == FALSE) ||
+ ((CardData->CSDRegister.CCC & BIT10) != BIT10)) {
+ //
+ // Host must support high speed
+ // Card must support Switch function
+ //
+ goto Exit;
+ }
+
+ //
+ // Mode = 0, group 1, function 1, check operation
+ //
+ Argument = 0xFFFF01;
+ ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));
+
+ Status = SendCommand (
+ MmcHostIo,
+ SWITCH_FUNC,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (SWITCH_STATUS),
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));
+
+ if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||
+ ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {
+ //
+ // 1. SD 1.1 card does not suppport busy bit
+ // 2. Ready state
+ //
+ //
+ //
+ // Mode = 1, group 1, function 1, BIT31 set means set mode
+ //
+ Argument = 0xFFFF01 | BIT31;
+ ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));
+
+ Status = SendCommand (
+ MmcHostIo,
+ SWITCH_FUNC,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (SWITCH_STATUS),
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));
+
+ if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||
+ ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {
+ //
+ // 1. SD 1.1 card does not suppport busy bit
+ // 2. Ready state
+ //
+ //
+ // 8 clocks, (1/ 25M) * 8 ==> 320 us, so 1ms > 0.32 ms
+ //
+ gBS->Stall (1000);
+ }
+ }
+ }
+ if (!((CardData->ExtCSDRegister.CARD_TYPE & BIT2) ||
+ (CardData->ExtCSDRegister.CARD_TYPE & BIT3))) {
+ //
+ // Set Block Length, to improve compatibility in case of some cards
+ //
+ Status = SendCommand (
+ MmcHostIo,
+ SET_BLOCKLEN,
+ 512,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_BLOCKLEN -> %r\n", Status));
+ goto Exit;
+ }
+ }
+ MmcHostIo->SetBlockLength (MmcHostIo, 512);
+
+Exit:
+ if (Status) {
+
+ }
+
+ return Status;
+}
+
+
+/**
+ MmcSelect
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Select
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+MmcSelect (
+ IN CARD_DATA *CardData,
+ IN BOOLEAN Select
+ )
+{
+ return SendCommand (
+ CardData->MmcHostIo,
+ SELECT_DESELECT_CARD,
+ Select ? (CardData->Address << 16) : ~(CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+}
+
+
+/**
+ MmcSendSwitch
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] SwitchArgument Pointer to SWITCH_ARGUMENT
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcSendSwitch (
+ IN CARD_DATA *CardData,
+ IN SWITCH_ARGUMENT *SwitchArgument
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+
+ MmcHostIo = CardData->MmcHostIo;
+
+ Status = SendCommand (
+ MmcHostIo,
+ SWITCH,
+ *(UINT32 *) SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ MmcHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SWITCH FAILURE\n"));
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ MmcUpdateCardStatus
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcUpdateCardStatus (
+ IN CARD_DATA *CardData
+ )
+{
+ return SendCommand (
+ CardData->MmcHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+}
+
+
+/**
+ MmcMoveToTranState
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcMoveToTranState (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (CardData->CardStatus.CURRENT_STATE != Tran_STATE) {
+ //
+ // Put the card into tran state
+ //
+ Status = MmcSelect (CardData, TRUE);
+ MmcUpdateCardStatus (CardData);
+ }
+
+ if (CardData->CardStatus.CURRENT_STATE != Tran_STATE) {
+ DEBUG ((EFI_D_ERROR, "MmcMoveToTranState: Unable to put card into tran state\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+
+/**
+ MmcReadExtCsd
+
+ @param[in,out] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcReadExtCsd (
+ IN OUT CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MmcMoveToTranState (CardData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SendCommand (
+ CardData->MmcHostIo,
+ SEND_EXT_CSD,
+ 0,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (EXT_CSD),
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ DEBUG ((EFI_D_INFO, "MmcReadExtCsd: SEND_EXT_CSD -> %r\n", Status));
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof (EXT_CSD));
+
+ return Status;
+}
+
+
+/**
+ MmcSetExtCsd8
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Index
+ @param[in] Value
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcSetExtCsd8 (
+ IN CARD_DATA *CardData,
+ IN UINT8 Index,
+ IN UINT8 Value
+ )
+{
+ EFI_STATUS Status;
+ SWITCH_ARGUMENT SwitchArgument;
+
+ Status = MmcMoveToTranState (CardData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = (UINT8) Value;
+ SwitchArgument.Index = (UINT8) Index;
+ SwitchArgument.Access = WriteByte_Mode; // SetBits_Mode;
+
+ return MmcSendSwitch (CardData, &SwitchArgument);
+}
+
+
+/**
+ MmcSetExtCsd24
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Index
+ @param[in] Value
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcSetExtCsd24 (
+ IN CARD_DATA *CardData,
+ IN UINT8 Index,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ UINTN Loop;
+
+ ASSERT ((Value & 0xff000000ULL) == 0);
+
+ for (Loop = 0; Loop < 3; Loop++) {
+ Status = MmcSetExtCsd8 (CardData, Index + (UINT8) Loop, Value & 0xff);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Value = Value >> 8;
+ }
+
+ return Status;
+}
+
+
+/**
+ MmcGetExtCsd8
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Offset
+
+ @retval CSD Register value
+
+**/
+UINT32
+MmcGetExtCsd8 (
+ IN CARD_DATA *CardData,
+ IN UINTN Offset
+ )
+{
+ ASSERT (Offset < sizeof (CardData->ExtCSDRegister));
+ return ((UINT8 *) &CardData->ExtCSDRegister)[Offset];
+}
+
+
+/**
+ MmcGetExtCsd32
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Offset
+
+ @retval CSD Register value
+
+**/
+UINT32
+MmcGetExtCsd32 (
+ IN CARD_DATA *CardData,
+ IN UINTN Offset
+ )
+{
+ return *(UINT32 *) (((UINT8 *) &CardData->ExtCSDRegister) + Offset);
+}
+
+
+/**
+ MmcGetExtCsd24
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Offset
+
+ @retval CSD Register value
+
+**/
+UINT32
+MmcGetExtCsd24 (
+ IN CARD_DATA *CardData,
+ IN UINTN Offset
+ )
+{
+ return MmcGetExtCsd32 (CardData, Offset) & 0xffffff;
+}
+
+
+/**
+ MmcGetCurrentPartitionNum
+
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval Current Partition Num
+
+**/
+UINTN
+MmcGetCurrentPartitionNum (
+ IN CARD_DATA *CardData
+ )
+{
+ return MmcGetExtCsd8 (
+ CardData,
+ OFFSET_OF (EXT_CSD, PARTITION_CONFIG)
+ ) & 0x7;
+}
+
+
+/**
+ SetEmmcWpOnEvent
+
+ @param[in] Event
+ @param[in] Context
+
+ @retval None
+
+**/
+VOID
+EFIAPI
+SetEmmcWpOnEvent(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ CARD_DATA *CardData;
+ UINT8 TempData;
+ UINTN WriteProtectAddress;
+ UINTN WriteProtectSize;
+ UINTN WriteProtectGroupSize;
+ static BOOLEAN WriteProtectDone = FALSE;
+ HECI_FWS_REGISTER SecFwStatus;
+ SC_POLICY_HOB *ScPolicy;
+ EFI_PEI_HOB_POINTERS HobList;
+ SC_SCS_CONFIG *ScsConfig;
+
+ DEBUG ((EFI_D_INFO, "eMMC Write Protection Config Checkpoint\n"));
+
+ CardData = (CARD_DATA *) Context;
+ //
+ // Enable the eMMC protection
+ //
+ if (FALSE) {
+ if (!WriteProtectDone) {
+ Status = MmcReadExtCsd (CardData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Read EXT_CSD failed\n"));
+ }
+ DEBUG ((EFI_D_INFO, "\nBOOT_WP 0x%02x", (UINT8) (CardData->ExtCSDRegister.BOOT_WP)));
+ DEBUG ((EFI_D_INFO, "\nBOOT_WP_STATUS 0x%02x", (UINT8) (CardData->ExtCSDRegister.BOOT_WP_STATUS)));
+ DEBUG ((EFI_D_INFO, "\nUSER_WP 0x%02x", (UINT8) (CardData->ExtCSDRegister.USER_WP)));
+ DEBUG ((EFI_D_INFO, "\nRST_n_FUNCTION 0x%02x\n", (UINT8) (CardData->ExtCSDRegister.RST_n_FUNCTION)));
+
+ if (BxtStepping() >= BxtPB0) { //For BXTP-B and above, BIOS to toggle rst_n_function from 2'b00 to 2'b01
+ if ((CardData->ExtCSDRegister.RST_n_FUNCTION & 0x3) != 1) {
+ Offset = OFFSET_OF (EXT_CSD, RST_n_FUNCTION);
+ Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, 0x01);
+ if (Status) {
+ DEBUG ((EFI_D_INFO, "Setting RST_n_FUNCTION failed\n"));
+ }
+ }
+ }
+
+ // Protect and BP
+ // Update Power on write protection bit in USER_WP and BP_WP EXT_CSD registers
+ //
+ Offset = OFFSET_OF (EXT_CSD, ERASE_GROUP_DEF);
+ Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, 0x01);
+ if (Status) {
+ DEBUG ((EFI_D_INFO, "Setting ERASE_GROUP_DEF failed\n"));
+ }
+
+ if (BxtStepping() != BxtPA0) { // program WP only if it's not Bxtp-A0
+ Offset = OFFSET_OF (EXT_CSD, BOOT_WP);
+ TempData = (CardData->ExtCSDRegister.BOOT_WP) | B_PWR_WP_EN | B_PERM_WP_DIS;
+ Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, TempData);
+ if (Status) {
+ DEBUG ((EFI_D_INFO, "BP Write protect failed\n"));
+ }
+ }
+
+ HobList.Guid = GetFirstGuidHob (&gScPolicyHobGuid);
+ ASSERT (HobList.Guid != NULL);
+ ScPolicy = (SC_POLICY_HOB *) GET_GUID_HOB_DATA (HobList.Guid);
+ Status = GetConfigBlock ((VOID *) ScPolicy, &gScsConfigGuid, (VOID *) &ScsConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ SecFwStatus.ul = HeciPciRead32 (R_SEC_FW_STS0);
+
+ if (SecFwStatus.r.ManufacturingMode == 0) {
+ DEBUG ((EFI_D_INFO, "SEC F/W is not in Manufacturing mode and is ready for production \n"));
+ } else if (SecFwStatus.r.SeCOperationMode != SEC_OPERATION_MODE_SECOVR_JMPR) {
+ DEBUG ((EFI_D_INFO, "Flash Descriptor Override HW strap not set\n"));
+ }
+
+ if (((SecFwStatus.r.ManufacturingMode == 0) // if EOM is set
+ && (SecFwStatus.r.SeCOperationMode != SEC_OPERATION_MODE_SECOVR_JMPR)) // Flash Descriptor Override HW strap not set
+ || (ScsConfig->GppLock == 1) // OR GPP Partition Lock Policy is set
+ ) {
+ //
+ // Protect GPP1
+ //
+ Status = MmcSelectPartitionNum (CardData, 4); // Switch to GPP1 before issuing CMD28
+ if (!EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "\nSwitch to GPP Partition Successful\n"));
+ WriteProtectSize = (((UINTN) (CardData->ExtCSDRegister.GP_SIZE_MULT_1[2] *( 0x1<<16)))
+ +((UINTN) (CardData->ExtCSDRegister.GP_SIZE_MULT_1[1] *( 0x1<<8)))
+ +((UINTN) (CardData->ExtCSDRegister.GP_SIZE_MULT_1[0])))
+ * ((UINTN) (CardData->ExtCSDRegister.HC_WP_GRP_SIZE))
+ * 512 * 1024 * ((UINTN) (CardData->ExtCSDRegister.HC_ERASE_GRP_SIZE));
+
+ DEBUG ((EFI_D_INFO, "WriteProtectSize = 0x%x\n", WriteProtectSize));
+
+ Offset = OFFSET_OF (EXT_CSD, USER_WP);
+ TempData = (CardData->ExtCSDRegister.USER_WP) | US_PWR_WP_EN | US_PERM_WP_DIS;
+ Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, TempData);
+ if (Status) {
+ DEBUG ((EFI_D_INFO, "GPP Write protect failed\n"));
+ }
+ if (CardData->ExtCSDRegister.ERASE_GROUP_DEF) {
+ WriteProtectGroupSize = ((UINTN) (CardData->ExtCSDRegister.HC_WP_GRP_SIZE))
+ * 512 * 1024 * ((UINTN) (CardData->ExtCSDRegister.HC_ERASE_GRP_SIZE));
+ } else {
+ WriteProtectGroupSize = (CardData->CSDRegister.WP_GRP_SIZE + 1)
+ * ((UINTN) CardData->CSDRegister.ERASE_GRP_SIZE + 1)
+ * ((UINTN) CardData->CSDRegister.ERASE_GRP_MULT + 1)
+ * ((UINTN) (CardData->Partitions[4].BlockIoMedia.BlockSize));
+ }
+
+ DEBUG ((EFI_D_INFO, "WriteProtectGroupSize = 0x%x\n", WriteProtectGroupSize));
+
+ for (WriteProtectAddress = 0; WriteProtectAddress < WriteProtectSize; WriteProtectAddress+=WriteProtectGroupSize) {
+ //
+ // Send Write protect command
+ //
+ DEBUG ((EFI_D_INFO, "Send Write protect command Address = 0x%x\n", WriteProtectAddress));
+ Status = SendCommand (
+ CardData->MmcHostIo,
+ SET_WRITE_PROT,
+ (UINT32) (WriteProtectAddress / 0x200),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (Status) {
+ DEBUG ((EFI_D_INFO, "GPP1 Write protect failed\n"));
+ break;
+ }
+ }
+
+ }
+
+ }
+ }
+
+ Status = MmcReadExtCsd (CardData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Read EXT_CSD failed\n"));
+ }
+
+ DEBUG ((EFI_D_INFO, "\nBOOT_WP 0x%02x", (UINT8) (CardData->ExtCSDRegister.BOOT_WP)));
+ DEBUG ((EFI_D_INFO, "\nBOOT_WP_STATUS 0x%02x", (UINT8) (CardData->ExtCSDRegister.BOOT_WP_STATUS)));
+ DEBUG ((EFI_D_INFO, "\nUSER_WP 0x%02x", (UINT8) (CardData->ExtCSDRegister.USER_WP)));
+ DEBUG ((EFI_D_INFO, "\nRST_n_FUNCTION 0x%02x\n", (UINT8) (CardData->ExtCSDRegister.RST_n_FUNCTION)));
+ WriteProtectDone = TRUE;
+ }
+}
+
+
+/**
+ MmcSelectPartitionNum
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Partition
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcSelectPartitionNum (
+ IN CARD_DATA *CardData,
+ IN UINT8 Partition
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINT8 *ExtByte;
+ UINTN CurrentPartition;
+
+ if (Partition > 7) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CurrentPartition = MmcGetCurrentPartitionNum (CardData);
+ if (Partition == CurrentPartition) {
+ return EFI_SUCCESS;
+ }
+ MmcMoveToTranState (CardData);
+ Status = MmcReadExtCsd (CardData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO,
+ "MmcSelectPartitionNum: Switch partition: %d => %d\n",
+ CurrentPartition,
+ Partition
+ ));
+
+ Offset = OFFSET_OF (EXT_CSD, PARTITION_CONFIG);
+ Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, Partition);
+
+#if 1
+ Status = MmcReadExtCsd (CardData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CurrentPartition = MmcGetCurrentPartitionNum (CardData);
+ if (Partition != CurrentPartition) {
+ DEBUG ((EFI_D_INFO, "MmcSelectPartitionNum: Switch partition failed!\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ ExtByte = NULL;
+#else
+ if (!EFI_ERROR (Status)) {
+ ExtByte = ((UINT8 *) &CardData->ExtCSDRegister) + Offset;
+ *ExtByte = (UINT8) ((*ExtByte & 0xF7) | Partition);
+ }
+#endif
+ MmcMoveToTranState (CardData);
+
+ return Status;
+}
+
+
+/**
+ MmcSelectPartitionNum
+
+ @param[in] Partition Pointer to MMC_PARTITION_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcSelectPartition (
+ IN MMC_PARTITION_DATA *Partition
+ )
+{
+ return MmcSelectPartitionNum (
+ Partition->CardData,
+ (UINT8) CARD_DATA_PARTITION_NUM (Partition)
+ );
+}
+
+
+/**
+ MmcSetPartition
+
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Value 0: user partition; 1: boot partition 1; 2:boot partition 2
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MmcSetPartition (
+ IN CARD_DATA *CardData,
+ IN UINT8 Value
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINT32 Data;
+
+ Offset = OFFSET_OF (EXT_CSD, PARTITION_CONFIG);
+ Data = MmcGetExtCsd8 (CardData, Offset);
+ Data &= 0xf8;
+ Data |= Value;
+ Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, (UINT8) Data);
+
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c
new file mode 100644
index 0000000..7f5bd11
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c
@@ -0,0 +1,605 @@
+/** @file
+ UEFI Driver Entry and Binding support.
+
+ Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ 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 <MediaDeviceDriver.h>
+#include <Protocol/EmmcCardInfoProtocol.h>
+
+//
+// MMCSDIOController Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gMediaDeviceDriverBinding = {
+ MediaDeviceDriverBindingSupported,
+ MediaDeviceDriverBindingStart,
+ MediaDeviceDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_EMMC_CARD_INFO_PROTOCOL *gEfiEmmcCardInfo = NULL;
+
+/**
+ Entry point for EFI drivers.
+
+ @param[in] ImageHandle EFI_HANDLE
+ @param[in] SystemTable EFI_SYSTEM_TABLE
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Fail
+
+**/
+EFI_STATUS
+EFIAPI
+MediaDeviceDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallAllDriverProtocols (
+ ImageHandle,
+ SystemTable,
+ &gMediaDeviceDriverBinding,
+ ImageHandle,
+ &gMediaDeviceComponentName,
+ NULL,
+ NULL
+ );
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ that has installed will be supported.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controlle Handle of device to test
+ @param[in] RemainingDevicePath Not used
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+MediaDeviceDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+
+ //
+ // Test whether there is MMCHostIO Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ (VOID **) &MmcHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Starting the Media Device Driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test
+ @param[in] RemainingDevicePath Not used
+
+ @retval EFI_SUCCESS supports this device.
+ @retval EFI_UNSUPPORTED do not support this device.
+ @retval EFI_DEVICE_ERROR cannot be started due to device Error
+ @retval EFI_OUT_OF_RESOURCES cannot allocate resources
+
+**/
+EFI_STATUS
+EFIAPI
+MediaDeviceDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo;
+ CARD_DATA *CardData;
+ UINTN Loop;
+ EFI_EMMC_CARD_INFO_PROTOCOL *EfiEmmcCardInfoRegister;
+
+ DEBUG ((EFI_D_INFO, "%a(%d): %a()\n", __FILE__, __LINE__, __FUNCTION__));
+
+ EfiEmmcCardInfoRegister = NULL;
+ CardData = NULL;
+ MmcHostIo = NULL;
+
+ //
+ // Alloc memory for EfiEmmcCardInfoRegister variable
+ //
+ EfiEmmcCardInfoRegister = (EFI_EMMC_CARD_INFO_PROTOCOL *) AllocateZeroPool (sizeof (EFI_EMMC_CARD_INFO_PROTOCOL));
+ if (EfiEmmcCardInfoRegister == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Open PCI I/O Protocol and save pointer to open protocol
+ // in private data area.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ (VOID **) &MmcHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStart: Fail to open gEfiMmcHostIoProtocolGuid \n"));
+ goto Exit;
+ }
+
+ Status = MmcHostIo->DetectCardAndInitHost (MmcHostIo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Fail to DetectCardAndInitHost %r\n", Status));
+ goto Exit;
+ }
+
+ CardData = (CARD_DATA *) AllocateZeroPool (sizeof (CARD_DATA));
+ if (CardData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStart: Fail to AllocateZeroPool(CARD_DATA) \n"));
+ goto Exit;
+ }
+
+ ASSERT (MmcHostIo->HostCapability.BoundarySize >= 4 * 1024);
+
+ CardData->RawBufferPointer = (UINT8*) (UINTN) 0xffffffff;
+
+ DEBUG ((EFI_D_INFO, "CardData->RawBufferPointer = 0x%x \n",CardData->RawBufferPointer));
+ DEBUG ((EFI_D_INFO, "requesting 0x%x pages \n",EFI_SIZE_TO_PAGES(2 * MmcHostIo->HostCapability.BoundarySize)));
+
+ //
+ // Allocated the buffer under 4G
+ //
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (2 * MmcHostIo->HostCapability.BoundarySize),
+ (EFI_PHYSICAL_ADDRESS *) (&(CardData->RawBufferPointer))
+ );
+ DEBUG ((EFI_D_INFO, "CardData->RawBufferPointer = 0x%x \n",CardData->RawBufferPointer));
+ if (!EFI_ERROR (Status)) {
+ CardData->RawBufferPointer = ZeroMem (CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * MmcHostIo->HostCapability.BoundarySize));
+ } else {
+ DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Fail to AllocateZeroPool(2*x) \n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ CardData->AlignedBuffer = CardData->RawBufferPointer - ((UINTN) (CardData->RawBufferPointer) & (MmcHostIo->HostCapability.BoundarySize - 1)) + MmcHostIo->HostCapability.BoundarySize;
+
+ CardData->Signature = CARD_DATA_SIGNATURE;
+ CardData->MmcHostIo = MmcHostIo;
+ CardData->Handle = Controller;
+ for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Loop++) {
+ CardData->Partitions[Loop].Signature = CARD_PARTITION_SIGNATURE;
+ }
+ Status = MMCSDCardInit (CardData);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStart: Fail to MMCSDCardInit \n"));
+ goto Exit;
+ }
+
+ DEBUG ((DEBUG_INFO, "MediaDeviceDriverBindingStart: MMC SD card\n"));
+ Status = MMCSDBlockIoInit (CardData);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Card BlockIo init failed\n"));
+ goto Exit;
+ }
+
+
+ Status = MediaDeviceDriverInstallBlockIo (This, CardData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Fail to install gEfiBlockIoProtocolGuid \n"));
+ goto Exit;
+ }
+
+ //
+ // Component name protocol
+ //
+ Status = AddUnicodeString (
+ "eng",
+ gMediaDeviceComponentName.SupportedLanguages,
+ &CardData->ControllerNameTable,
+ L"MMC/SD Media Device"
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Loop++) {
+ if (!CardData->Partitions[Loop].Present) {
+ continue;
+ }
+ gBS->UninstallMultipleProtocolInterfaces (
+ CardData->Partitions[Loop].Handle,
+ &gEfiBlockIoProtocolGuid,
+ &CardData->Partitions[Loop].BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ CardData->Partitions[Loop].DevPath,
+ NULL
+ );
+ }
+ goto Exit;
+ }
+ if (EfiEmmcCardInfoRegister != NULL) {
+
+ //
+ // assign to protocol
+ //
+ EfiEmmcCardInfoRegister->CardData = CardData;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiEmmcCardInfoProtocolGuid,
+ EfiEmmcCardInfoRegister,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Install eMMC Card info protocol failed\n"));
+ for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Loop++) {
+ if (!CardData->Partitions[Loop].Present) {
+ continue;
+ }
+ gBS->UninstallMultipleProtocolInterfaces (
+ CardData->Partitions[Loop].Handle,
+ &gEfiBlockIoProtocolGuid,
+ &CardData->Partitions[Loop].BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ CardData->Partitions[Loop].DevPath,
+ NULL
+ );
+ }
+
+ goto Exit;
+ }
+
+ gEfiEmmcCardInfo = EfiEmmcCardInfoRegister;
+ }
+
+ DEBUG ((DEBUG_INFO, "MediaDeviceDriverBindingStart: Started\n"));
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStart: End with failure\n"));
+ if (CardData != NULL && MmcHostIo != NULL) {
+ if (CardData->RawBufferPointer != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (MmcHostIo->HostCapability.BoundarySize * 2));
+ }
+ FreePool (CardData);
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ return Status;
+}
+
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to stop driver on
+ @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer
+ @param[in] ChildHandleBuffer List of handles for the children we need to stop.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Fail
+
+**/
+EFI_STATUS
+EFIAPI
+MediaDeviceDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ UINTN Pages = 0;
+
+ Status = EFI_SUCCESS;
+ CardData = gEfiEmmcCardInfo->CardData;
+
+ if (NumberOfChildren == 0) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiEmmcCardInfoProtocolGuid,
+ gEfiEmmcCardInfo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStop: UNINSTALL gEfiEmmcCardInfoProtocolGuid FAILURE\n"));
+ return Status;
+ }
+
+ FreeUnicodeStringTable (CardData->ControllerNameTable);
+
+ Pages = (2 * (CardData->MmcHostIo->HostCapability.BoundarySize));
+ if (CardData->RawBufferPointer != NULL) {
+ FreePages (CardData->RawBufferPointer, EFI_SIZE_TO_PAGES(Pages));
+ }
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiMmcHostIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ if (MediaDeviceDriverAllPartitionNotPresent(CardData)) {
+ FreePool (CardData);
+ FreePool (gEfiEmmcCardInfo);
+ gEfiEmmcCardInfo = NULL;
+ }
+
+ return Status;
+ }
+
+ AllChildrenStopped = TRUE;
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = MediaDeviceDriverUninstallBlockIo(This, CardData, ChildHandleBuffer[Index]);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStop: UNINSTALL block io FAILURE\n"));
+ AllChildrenStopped = FALSE;
+ break;
+ }
+ }
+
+ return Status;
+}
+
+
+BOOLEAN
+MediaDeviceDriverAllPartitionNotPresent (
+ IN CARD_DATA *CardData
+ )
+{
+ BOOLEAN AllPartitionNotPresent;
+ UINTN Loop;
+ MMC_PARTITION_DATA *Partition;
+
+ Partition = CardData->Partitions;
+
+ AllPartitionNotPresent = TRUE;
+
+ for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Partition++, Loop++) {
+ if (Partition->Present) {
+ AllPartitionNotPresent = FALSE;
+ break;
+ }
+ }
+
+ return AllPartitionNotPresent;
+}
+
+
+STATIC
+struct {
+ DEVICE_LOGICAL_UNIT_DEVICE_PATH LogicalUnit;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} EmmcDevPathTemplate = {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_DEVICE_LOGICAL_UNIT_DP,
+ {
+ sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH),
+ 0
+ },
+ },
+ 0
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+
+/**
+ MediaDeviceDriverInstallBlockIo
+
+ @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
+ @param[in] CardData Pointer to CARD_DATA
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MediaDeviceDriverInstallBlockIo (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Loop;
+ MMC_PARTITION_DATA *Partition;
+ EFI_DEVICE_PATH_PROTOCOL *MainPath;
+ EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo = NULL;
+
+ Partition = CardData->Partitions;
+
+ Status = gBS->HandleProtocol (
+ CardData->Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &MainPath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Partition++, Loop++) {
+ if (!Partition->Present) {
+ continue;
+ }
+
+ DEBUG ((EFI_D_INFO, "MediaDeviceDriverInstallBlockIo: Installing Block I/O for partition %d\n", Loop));
+
+ Partition->Handle = NULL;
+ Partition->CardData = CardData;
+
+ EmmcDevPathTemplate.LogicalUnit.Lun = Loop;
+ Partition->DevPath =
+ AppendDevicePath (
+ MainPath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &EmmcDevPathTemplate
+ );
+ if (Partition->DevPath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &(Partition->Handle),
+ &gEfiDevicePathProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ Partition->DevPath
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &(Partition->Handle),
+ &gEfiBlockIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Partition->BlockIo
+ );
+
+ //
+ // Open parent controller by child
+ //
+ Status = gBS->OpenProtocol (
+ CardData->Handle,
+ &gEfiMmcHostIoProtocolGuid,
+ (VOID **) &MmcHostIo,
+ This->DriverBindingHandle,
+ Partition->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ }
+
+ return Status;
+}
+
+
+/**
+ MediaDeviceDriverUninstallBlockIo
+
+ @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
+ @param[in] CardData Pointer to CARD_DATA
+ @param[in] Handle Handle of Partition
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+MediaDeviceDriverUninstallBlockIo (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN CARD_DATA *CardData,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ UINTN Loop;
+ MMC_PARTITION_DATA *Partition;
+
+ Partition = CardData->Partitions;
+ Status = EFI_SUCCESS;
+
+ for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Partition++, Loop++) {
+ if (!Partition->Present || Partition->Handle != Handle) {
+ continue;
+ }
+
+ //
+ // Close MmcHostIoProtocol by child
+ //
+ Status = gBS->CloseProtocol (
+ CardData->Handle,
+ &gEfiMmcHostIoProtocolGuid,
+ This->DriverBindingHandle,
+ Partition->Handle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CloseProtocol gEfiMmcHostIoProtocolGuid FAILURE \n"));
+ return Status;
+ }
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Partition->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &Partition->BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ Partition->DevPath,
+ NULL
+ );
+ Partition->Present = FALSE;
+ DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStop gEfiBlockIoProtocolGuid removed. %x\n", Status));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MediaDeviceDriverUninstallBlockIo UNISTALL FAILURE \n"));
+ }
+ return Status;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf
new file mode 100644
index 0000000..500d1de
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf
@@ -0,0 +1,71 @@
+## @file
+# SD Host module
+#
+# Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# 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 = 0x00010005
+ BASE_NAME = MmcMediaDevice
+ FILE_GUID = 1CFD8F87-355A-4954-859F-DDC5D8876D44
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MediaDeviceDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ ComponentName.c
+ MediaDeviceDriver.c
+ MMCSDBlockIo.c
+ MMCSDTransfer.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiLib
+ DevicePathLib
+ IoLib
+ PcdLib
+ HobLib
+ PciLib
+ SteppingLib
+ ConfigBlockLib
+
+[Guids]
+ gEfiEventReadyToBootGuid ## UNDEFINED
+ gScPolicyHobGuid
+ gEfiUnbootablePartitionGuid ## PRODUCE ## GUID
+ gScsConfigGuid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## BY_START
+ gEfiMmcHostIoProtocolGuid ## CONSUMES
+ gEfiBlockIoProtocolGuid ## BY_START
+ gEfiEmmcCardInfoProtocolGuid ## BY_START
+ gEfiEmmcBootPartitionProtocolGuid ## BY_START
+
+[Pcd]
+ gEfiBxtTokenSpaceGuid.PcdEmmcManufacturerId ## PRODUCES
+ gEfiBxtTokenSpaceGuid.PcdProductSerialNumber ## PRODUCES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c
new file mode 100644
index 0000000..0bc9861
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c
@@ -0,0 +1,233 @@
+/** @file
+ UEFI Component Name(2) protocol implementation for SD controller driver.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SdController.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSdControllerName = {
+ SdControllerGetDriverName,
+ SdControllerGetControllerName,
+ "eng"
+};
+
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSdControllerName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SdControllerGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SdControllerGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdControllerDriverNameTable[] = {
+ { "eng;en", L"EFI SD Host Controller Driver" },
+ { NULL, NULL }
+};
+
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form 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 name 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] Language 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 SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+
+ @param[out] DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language 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
+SdControllerGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mSdControllerDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gSdControllerName)
+ );
+}
+
+
+/**
+ 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 specified by
+ ControllerHandle and ChildHandle in the form 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 controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param[in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ 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 name of a
+ child controller.
+
+ @param[in] Language 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 SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+
+ @param[out] ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for 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
+SdControllerGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ SDHOST_DATA *SdHostData;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure this driver is currently managing ControllerHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gSdControllerDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSdHostIoProtocolGuid,
+ (VOID **) &SdHostIo,
+ gSdControllerDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SdHostData = SDHOST_DATA_FROM_THIS (SdHostIo);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ SdHostData->ControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gSdControllerName)
+ );
+
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h
new file mode 100644
index 0000000..89d8a27
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h
@@ -0,0 +1,145 @@
+/** @file
+ This file contains the declarations for component name routines.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 _COMPONENT_NAME_H_
+#define _COMPONENT_NAME_H_
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form 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 name 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] Language 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 SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+
+ @param[out] DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language 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
+SdControllerGetDriverName (
+ 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 specified by
+ ControllerHandle and ChildHandle in the form 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 controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param[in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ 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 name of a
+ child controller.
+
+ @param[in] Language 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 SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+
+ @param[out] ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for 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
+SdControllerGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c
new file mode 100644
index 0000000..f481196
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c
@@ -0,0 +1,1804 @@
+/** @file
+ The SD host controller driver model and HC protocol routines.
+
+ Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SdController.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gSdControllerDriverBinding = {
+ SdControllerSupported,
+ SdControllerStart,
+ SdControllerStop,
+ 0x20,
+ NULL,
+ NULL
+};
+
+
+EFI_SD_HOST_IO_PROTOCOL mSdHostIo = {
+ EFI_SD_HOST_IO_PROTOCOL_REVISION_01,
+ {
+ 0, // HighSpeedSupport
+ 0, // V18Support
+ 0, // V30Support
+ 0, // V33Support
+ 0, // Reserved0
+ 0, // BusWidth4
+ 0, // BusWidth8
+ 0, // Reserved1
+ 0, // Reserved1
+ (512 * 1024) // BoundarySize
+ },
+
+ SendCommand,
+ SetClockFrequency,
+ SetBusWidth,
+ SetHostVoltage,
+ ResetSdHost,
+ EnableAutoStopCmd,
+ DetectCardAndInitHost,
+ SetBlockLength,
+ SetHighSpeedMode,
+ SetDDRMode
+};
+
+
+/**
+ Find sdclk_freq_sel and upr_sdclk_freq_sel bits
+ for Clock Control Register (CLK_CTL)Offset 2Ch when using 8bit or 10bit
+ divided clock mode.
+
+ @param[in] BaseClockFreg Base Clock Frequency in Hz For SD Clock in the
+ Capabilities register.
+ @param[in] TargetFreq Target Frequency in Hz to reach.
+ @param[in] Is8BitMode True if 8-bit Divided Clock Mode else 10bit mode.
+ @param[out] Bits sdclk_freq_sel and upr_sdclk_freq_sel bits for
+ TargetFreq.
+
+ @retval EFI_SUCCESS Bits setup.
+ @retval EFI_UNSUPPORTED Cannot divide base clock to reach target clock.
+
+**/
+EFI_STATUS
+DividedClockModeBits (
+ IN CONST UINTN BaseClockFreg,
+ IN CONST UINTN TargetFreq,
+ IN CONST BOOLEAN Is8BitMode,
+ OUT UINT16 *Bits
+ )
+{
+ UINTN N;
+ UINTN CurrFreq;
+
+ *Bits = 0;
+ CurrFreq = BaseClockFreg;
+ N = 0;
+ //
+ // N == 0 same for 8bit & 10bit mode i.e. BaseClockFreg of controller.
+ //
+ if (TargetFreq < CurrFreq) {
+ if (Is8BitMode) {
+ N = 1;
+ do {
+ //
+ // N values for 8bit mode when N > 0.
+ // Bit[15:8] SDCLK Frequency Select at offset 2Ch
+ // 80h - base clock divided by 256
+ // 40h - base clock divided by 128
+ // 20h - base clock divided by 64
+ // 10h - base clock divided by 32
+ // 08h - base clock divided by 16
+ // 04h - base clock divided by 8
+ // 02h - base clock divided by 4
+ // 01h - base clock divided by 2
+ //
+ CurrFreq = BaseClockFreg / (2 * N);
+ if (TargetFreq >= CurrFreq) {
+ break;
+ }
+ N *= 2;
+ if (N > V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL) {
+ return EFI_UNSUPPORTED;
+ }
+ } while (TRUE);
+ } else {
+ N = 1;
+ CurrFreq = BaseClockFreg / (2 * N);
+ //
+ // (try N = 0 or 1 first since don't want divide by 0).
+ //
+ if (TargetFreq < CurrFreq) {
+ //
+ // If still no match then calculate it for 10bit.
+ // N values for 10bit mode.
+ // N 1/2N Divided Clock (Duty 50%).
+ // from Spec "The length of divider is extended to 10 bits and all
+ // divider values shall be supported.
+ //
+ N = (BaseClockFreg / TargetFreq) / 2;
+
+ //
+ // Can only be N or N+1;
+ //
+ CurrFreq = BaseClockFreg / (2 * N);
+ if (TargetFreq < CurrFreq) {
+ N++;
+ CurrFreq = BaseClockFreg / (2 * N);
+ }
+
+ if (N > V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Set upper bits of SDCLK Frequency Select (bits 7:6 of reg 0x2c).
+ //
+ *Bits |= ((UINT16) ((N >> 2) & B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK));
+ }
+ }
+ }
+
+ //
+ // Set lower bits of SDCLK Frequency Select (bits 15:8 of reg 0x2c).
+ //
+ *Bits |= ((UINT16) ((UINT8) N) << 8);
+ DEBUG (
+ (EFI_D_INFO,
+ "SDIO:DividedClockModeBits: %dbit mode Want %dHz Got %dHz bits = %04x\r\n",
+ (Is8BitMode) ? 8 : 10,
+ TargetFreq,
+ CurrFreq,
+ (UINTN) *Bits
+ ));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Print type of error and command index
+
+ @param[in] CommandIndex Command index to set the command index field of command register.
+ @param[in] ErrorCode Error interrupt status read from host controller
+
+ @retval EFI_DEVICE_ERROR
+ @retval EFI_TIMEOUT
+ @retval EFI_CRC_ERROR
+
+**/
+EFI_STATUS
+GetErrorReason (
+ IN UINT16 CommandIndex,
+ IN UINT16 ErrorCode
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((EFI_D_ERROR, "[%2d] -- ", CommandIndex));
+
+ if (ErrorCode & BIT0) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((EFI_D_ERROR, "Command Timeout Erro"));
+ }
+
+ if (ErrorCode & BIT1) {
+ Status = EFI_CRC_ERROR;
+ DEBUG ((EFI_D_ERROR, "Command CRC Error"));
+ }
+
+ if (ErrorCode & BIT2) {
+ DEBUG ((EFI_D_ERROR, "Command End Bit Error"));
+ }
+
+ if (ErrorCode & BIT3) {
+ DEBUG ((EFI_D_ERROR, "Command Index Error"));
+ }
+ if (ErrorCode & BIT4) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((EFI_D_ERROR, "Data Timeout Error"));
+ }
+
+ if (ErrorCode & BIT5) {
+ Status = EFI_CRC_ERROR;
+ DEBUG ((EFI_D_ERROR, "Data CRC Error"));
+ }
+
+ if (ErrorCode & BIT6) {
+ DEBUG ((EFI_D_ERROR, "Data End Bit Error"));
+ }
+
+ if (ErrorCode & BIT7) {
+ DEBUG ((EFI_D_ERROR, "Current Limit Error"));
+ }
+
+ if (ErrorCode & BIT8) {
+ DEBUG ((EFI_D_ERROR, "Auto CMD12 Error"));
+ }
+
+ if (ErrorCode & BIT9) {
+ DEBUG ((EFI_D_ERROR, "ADMA Error"));
+ }
+
+ DEBUG ((EFI_D_ERROR, "\n"));
+
+ return Status;
+}
+
+
+/**
+ Enable/Disable High Speed transfer mode
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] Enable TRUE to Enable, FALSE to Disable
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetHighSpeedMode (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ UINT32 Data;
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SdHostData->PciIo;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ if (Enable) {
+ DEBUG ((EFI_D_INFO, "Enable High Speed transfer mode ... \r\n"));
+ Data |= BIT2;
+ } else {
+ Data &= ~BIT2;
+ }
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ return EFI_SUCCESS;
+}
+EFI_STATUS
+EFIAPI
+SetDDRMode (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ UINT16 Data;
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SdHostData->PciIo;
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_HOSTCTL2,
+ 1,
+ &Data
+ );
+
+ Data &= 0xFFF0;
+ if (Enable) {
+ Data |= 0x0004; // Enable DDR50 by default, later should enable other mode like HS200/400
+ Data |= BIT3; // Enable 1.8V Signaling
+ }
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_HOSTCTL2,
+ 1,
+ &Data
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Power on/off the LED associated with the slot
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] Enable TRUE to set LED on, FALSE to set LED off
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+HostLEDEnable (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 Data;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SdHostData->PciIo;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ if (Enable) {
+ //
+ // LED On
+ //
+ Data |= BIT0;
+ } else {
+ //
+ // LED Off
+ //
+ Data &= ~BIT0;
+ }
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The main function used to send the command to the card inserted into the SD host slot.
+ It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] CommandIndex The command index to set the command index field of command register.
+ @param[in] Argument Command argument to set the argument field of command register.
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param[in] Buffer Contains the data read from / write to the device.
+ @param[in] BufferSize The size of the buffer.
+ @param[in] ResponseType RESPONSE_TYPE.
+ @param[in] TimeOut Time out value in 1 ms unit.
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+ @retval EFI_TIMEOUT
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+SendCommand (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 ResponseDataCount;
+ UINT32 Data;
+ UINT64 Data64;
+ UINT8 Index;
+ INTN TimeOut2;
+ BOOLEAN AutoCMD12Enable = FALSE;
+
+ Status = EFI_SUCCESS;
+ ResponseDataCount = 1;
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SdHostData->PciIo;
+ AutoCMD12Enable = (CommandIndex & AUTO_CMD12_ENABLE) ? TRUE : FALSE;
+ CommandIndex = CommandIndex & CMD_INDEX_MASK;
+
+ if (Buffer != NULL && DataType == NoData) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
+ goto Exit;
+ }
+
+ if (((UINTN) Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN) NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
+ goto Exit;
+ }
+
+ DEBUG ((EFI_D_INFO, "SendCommand: Command Index = %d \r\n", CommandIndex));
+
+ TimeOut2 = 1000; // 10 ms
+ do {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64) MMIO_PSTATE,
+ 1,
+ &Data
+ );
+
+ gBS->Stall (10);
+ } while ((TimeOut2-- > 0) && (Data &BIT0));
+ TimeOut2 = 1000; // 10 ms
+ do {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64) MMIO_PSTATE,
+ 1,
+ &Data
+ );
+
+ gBS->Stall (10);
+ } while ((TimeOut2-- > 0) && (Data & BIT1));
+
+ //
+ // Clear status bits
+ //
+ Data = 0xFFFF;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_NINTSTS,
+ 1,
+ &Data
+ );
+
+ Data = 0xFFFF;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_ERINTSTS,
+ 1,
+ &Data
+ );
+
+
+ if (Buffer != NULL) {
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64) MMIO_DMAADR,
+ 1,
+ &Buffer
+ );
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_BLKSZ,
+ 1,
+ &Data
+ );
+
+ Data &= ~(0xFFF);
+ if (BufferSize <= SdHostData->BlockLength) {
+ Data |= (BufferSize | 0x7000);
+ } else {
+ Data |= (SdHostData->BlockLength | 0x7000);
+ }
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_BLKSZ,
+ 1,
+ &Data
+ );
+
+ if (BufferSize <= SdHostData->BlockLength) {
+ Data = 1;
+ } else {
+ Data = BufferSize / SdHostData->BlockLength;
+ }
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_BLKCNT,
+ 1,
+ &Data
+ );
+
+ } else {
+ Data = 0;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_BLKSZ,
+ 1,
+ &Data
+ );
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_BLKCNT,
+ 1,
+ &Data
+ );
+ }
+
+ //
+ // Argument
+ //
+ Data = Argument;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64) MMIO_CMDARG,
+ 1,
+ &Data
+ );
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_XFRMODE,
+ 1,
+ &Data
+ );
+
+ DEBUG ((EFI_D_INFO, "Transfer mode read = 0x%x \r\n", (Data & 0xFFFF)));
+
+ //
+ // BIT0 - DMA Enable
+ // BIT2 - Auto Cmd12
+ //
+ if (DataType == InData) {
+ Data |= BIT4 | BIT0;
+ } else if (DataType == OutData){
+ Data &= ~BIT4;
+ Data |= BIT0;
+ } else {
+ Data &= ~(BIT4 | BIT0);
+ }
+
+ if (BufferSize <= SdHostData->BlockLength) {
+ Data &= ~(BIT5 | BIT1 | BIT2);
+ Data |= BIT1; // Enable block count always
+ } else {
+ if (SdHostData->IsAutoStopCmd && AutoCMD12Enable) {
+ Data |= (BIT5 | BIT1 | BIT2);
+ } else {
+ Data |= (BIT5 | BIT1);
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "Transfer mode write = 0x%x \r\n", (Data & 0xffff)));
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_XFRMODE,
+ 1,
+ &Data
+ );
+
+ //
+ //Command
+ //
+ //ResponseTypeSelect IndexCheck CRCCheck ResponseType
+ // 00 0 0 NoResponse
+ // 01 0 1 R2
+ // 10 0 0 R3, R4
+ // 10 1 1 R1, R5, R6, R7
+ // 11 1 1 R1b, R5b
+ //
+ switch (ResponseType) {
+ case ResponseNo:
+ Data = (CommandIndex << 8);
+ ResponseDataCount = 0;
+ break;
+
+ case ResponseR1:
+ case ResponseR5:
+ case ResponseR6:
+ case ResponseR7:
+ Data = (CommandIndex << 8) | BIT1 | BIT4| BIT3;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR1b:
+ case ResponseR5b:
+ Data = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR2:
+ Data = (CommandIndex << 8) | BIT0 | BIT3;
+ ResponseDataCount = 4;
+ break;
+
+ case ResponseR3:
+ case ResponseR4:
+ Data = (CommandIndex << 8) | BIT1;
+ ResponseDataCount = 1;
+ break;
+
+ default:
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
+ goto Exit;
+ }
+
+ if (DataType != NoData) {
+ Data |= BIT5;
+ }
+
+ HostLEDEnable (This, TRUE);
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_SDCMD,
+ 1,
+ &Data
+ );
+
+ Data = 0;
+ do {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_ERINTSTS,
+ 1,
+ &Data
+ );
+
+ if ((Data & 0x07FF) != 0) {
+ Status = GetErrorReason (CommandIndex, (UINT16) Data);
+ DEBUG ((EFI_D_ERROR, "SendCommand: Error happens \r\n"));
+ goto Exit;
+ }
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_NINTSTS,
+ 1,
+ &Data
+ );
+
+ if ((Data & BIT0) == BIT0) {
+ //
+ //Command completed, can read response
+ //
+ if (DataType == NoData) {
+ break;
+ } else {
+ //
+ // Transfer completed
+ //
+ if ((Data & BIT1) == BIT1) {
+ break;
+ }
+ }
+ }
+
+ gBS->Stall (1 * 1000);
+
+ TimeOut --;
+
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((EFI_D_ERROR, "SendCommand: Time out \r\n"));
+ goto Exit;
+ }
+
+ if (ResponseData != NULL) {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64) MMIO_RESP,
+ ResponseDataCount,
+ ResponseData
+ );
+
+ if (ResponseType == ResponseR2) {
+ //
+ // Adjustment for R2 response
+ //
+ Data = 1;
+ for (Index = 0; Index < ResponseDataCount; Index++) {
+ Data64 = LShiftU64 (*ResponseData, 8);
+ *ResponseData = (UINT32) ((Data64 & 0xFFFFFFFF) | Data);
+ Data = (UINT32) RShiftU64 (Data64, 32);
+ ResponseData++;
+ }
+ }
+ }
+
+Exit:
+ HostLEDEnable (This, FALSE);
+ return Status;
+}
+
+
+/**
+ Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.
+ It depends on the max frequency the host can support, divider, and host speed mode.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] MaxFrequency Max frequency in HZ.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+SetClockFrequency (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 MaxFrequency
+ )
+{
+ UINT32 Data;
+ UINT16 FreqSelBits;
+ EFI_STATUS Status;
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 TimeOutCount;
+ UINT32 Revision;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SdHostData->PciIo;
+ Data = 0;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_CTRLRVER,
+ 1,
+ &Revision
+ );
+
+ Revision &= 0x000000FF;
+
+ Status = DividedClockModeBits (
+ SdHostData->BaseClockInMHz * 1000 * 1000,
+ MaxFrequency,
+ (Revision < SDHCI_SPEC_300),
+ &FreqSelBits
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Cannot reach MaxFrequency with SdHostData->BaseClockInMHz.
+ //
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Data = 0;
+
+ //
+ // Enable internal clock and Stop Clock Enable
+ //
+ Data = BIT0;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ TimeOutCount = TIME_OUT_1S;
+ do {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ gBS->Stall (1 * 1000);
+ TimeOutCount --;
+ if (TimeOutCount == 0) {
+ DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));
+ return EFI_TIMEOUT;
+ }
+ } while ((Data & BIT1) != BIT1);
+
+ DEBUG ((EFI_D_INFO, "Base Clock In MHz: %d\r\n", SdHostData->BaseClockInMHz));
+
+ Data = (BIT0 | ((UINT32) FreqSelBits));
+ DEBUG ((EFI_D_INFO, "Data write to MMIO_CLKCTL: 0x%04x \r\n", Data));
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ TimeOutCount = TIME_OUT_1S;
+ do {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ gBS->Stall (1 * 1000);
+ TimeOutCount --;
+ if (TimeOutCount == 0) {
+ DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));
+ return EFI_TIMEOUT;
+ }
+ } while ((Data & BIT1) != BIT1);
+ gBS->Stall (20 * 1000);
+ Data |= BIT2;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set bus width of the host controller
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] BusWidth Bus width in 1, 4, 8 bits.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusWidth (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BusWidth
+ )
+{
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Data;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+
+ if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) {
+ DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((SdHostData->SdHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) {
+ DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciIo = SdHostData->PciIo;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+ //
+ // BIT5 8-bit MMC Support (MMC8):
+ // If set, IOH supports 8-bit MMC. When cleared, IOH does not support this feature
+ //
+ if (BusWidth == 8) {
+ DEBUG ((EFI_D_INFO, "Bus Width is 8-bit ... \r\n"));
+ Data |= BIT5;
+ } else if (BusWidth == 4) {
+ DEBUG ((EFI_D_INFO, "Bus Width is 4-bit ... \r\n"));
+ Data &= ~BIT5;
+ Data |= BIT1;
+ } else {
+ DEBUG ((EFI_D_INFO, "Bus Width is 1-bit ... \r\n"));
+ Data &= ~BIT5;
+ Data &= ~BIT1;
+ }
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set voltage which could supported by the host controller.
+ Support 0(Power off the host), 1.8V, 3.0V, 3.3V
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] Voltage Units in 0.1 V.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostVoltage (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 Voltage
+ )
+{
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Data;
+ EFI_STATUS Status;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SdHostData->PciIo;
+ Status = EFI_SUCCESS;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_PWRCTL,
+ 1,
+ &Data
+ );
+
+ if (Voltage == 0) {
+ //
+ // Power Off the host
+ //
+ Data &= ~BIT0;
+ } else if (Voltage <= 18 && This->HostCapability.V18Support) {
+ //
+ // 1.8V
+ //
+ Data |= (BIT1 | BIT3 | BIT0);
+ } else if (Voltage > 18 && Voltage <= 30 && This->HostCapability.V30Support) {
+ //
+ // 3.0V
+ //
+ Data |= (BIT2 | BIT3 | BIT0);
+ } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) {
+ //
+ // 3.3V
+ //
+ Data |= (BIT1 | BIT2 | BIT3 | BIT0);
+ } else {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_PWRCTL,
+ 1,
+ &Data
+ );
+
+ gBS->Stall (10 * 1000);
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Reset the host controller.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] ResetAll TRUE to reset all.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+ResetSdHost (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN RESET_TYPE ResetType
+ )
+{
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 Data;
+ UINT16 ErrStatus;
+ UINT32 Mask;
+ UINT32 TimeOutCount;
+ UINT16 SaveClkCtl;
+ UINT16 ZeroClkCtl;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SdHostData->PciIo;
+ Mask = 0;
+ ErrStatus = 0;
+
+ if (ResetType == Reset_Auto) {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_ERINTSTS,
+ 1,
+ &ErrStatus
+ );
+
+ if ((ErrStatus & 0xF) != 0) {
+ //
+ // Command Line
+ //
+ Mask |= BIT1;
+ }
+ if ((ErrStatus & 0x70) != 0) {
+ //
+ // Data Line
+ //
+ Mask |= BIT2;
+ }
+ }
+
+ if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) {
+ Mask |= BIT2;
+ }
+ if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) {
+ Mask |= BIT1;
+ }
+ if (ResetType == Reset_All) {
+ Mask = BIT0;
+ }
+
+ if (Mask == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // To improve SD stability, we zero the MMIO_CLKCTL register and
+ // stall for 50 microseconds before reseting the controller. We
+ // restore the register setting following the reset operation.
+ //
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &SaveClkCtl
+ );
+
+ ZeroClkCtl = (UINT16) 0;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &ZeroClkCtl
+ );
+
+ gBS->Stall (50);
+
+ //
+ // Reset the SD host controller
+ //
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_SWRST,
+ 1,
+ &Mask
+ );
+
+ Data = 0;
+ TimeOutCount = TIME_OUT_1S;
+ do {
+
+ gBS->Stall (1 * 1000);
+
+ TimeOutCount --;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_SWRST,
+ 1,
+ &Data
+ );
+
+ if ((Data & Mask) == 0) {
+ break;
+ }
+ } while (TimeOutCount > 0);
+
+ //
+ // We now restore the MMIO_CLKCTL register which we set to 0 above.
+ //
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CLKCTL,
+ 1,
+ &SaveClkCtl
+ );
+
+ if (TimeOutCount == 0) {
+ DEBUG ((EFI_D_ERROR, "ResetSdHost: Time out \r\n"));
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Enable auto stop on the host controller.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] Enable TRUE to enable, FALSE to disable.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+EnableAutoStopCmd (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ SDHOST_DATA *SdHostData;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+
+ SdHostData->IsAutoStopCmd = Enable;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set the Block length on the host controller.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] BlockLength card supportes block length.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+SetBlockLength (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BlockLength
+ )
+{
+ SDHOST_DATA *SdHostData;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+
+ DEBUG ((EFI_D_INFO, "Block length on the host controller: %d \r\n", BlockLength));
+ SdHostData->BlockLength = BlockLength;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Find whether these is a card inserted into the slot. If so init the host.
+ If not, return EFI_NOT_FOUND.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_FOUND
+
+**/
+EFI_STATUS
+EFIAPI
+DetectCardAndInitHost (
+ IN EFI_SD_HOST_IO_PROTOCOL *This
+ )
+{
+ SDHOST_DATA *SdHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 Data;
+ EFI_STATUS Status;
+ UINT8 Voltages[] = { 33, 30, 18 };
+ UINTN Loop;
+
+ SdHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SdHostData->PciIo;
+ Status = EFI_NOT_FOUND;
+
+ Data = 0;
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64) MMIO_PSTATE,
+ 1,
+ &Data
+ );
+
+ if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) {
+ //
+ // Has no card inserted
+ //
+ DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: No Cards \r\n"));
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: Find Cards \r\n"));
+
+ Status = EFI_NOT_FOUND;
+ for (Loop = 0; Loop < sizeof (Voltages); Loop++) {
+ DEBUG ((
+ EFI_D_INFO,
+ "DetectCardAndInitHost: SetHostVoltage %d.%dV \r\n",
+ Voltages[Loop] / 10,
+ Voltages[Loop] % 10
+ ));
+ Status = SetHostVoltage (This, Voltages[Loop]);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [failed]\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [success]\n"));
+ break;
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set voltage \r\n"));
+ goto Exit;
+ }
+
+ Status = SetClockFrequency (This, FREQUENCY_OD);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set frequency \r\n"));
+ goto Exit;
+ }
+ SetBusWidth (This, 1);
+
+ //
+ // Enable normal status change
+ //
+ Data = (BIT0 | BIT1);
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_NINTEN,
+ 1,
+ &Data
+ );
+
+ //
+ // Enable error status change
+ //
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_ERINTEN,
+ 1,
+ &Data
+ );
+
+ Data |= (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8);
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_ERINTEN,
+ 1,
+ &Data
+ );
+
+ //
+ // Data transfer Timeout control
+ //
+ Data = 0x0E;
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64) MMIO_TOCTL,
+ 1,
+ &Data
+ );
+ //
+ // Set Default Bus width as 1 bit
+ //
+
+Exit:
+ return Status;
+
+}
+
+
+/**
+ Entry point for EFI drivers.
+
+ @param[in] ImageHandle EFI_HANDLE.
+ @param[in] SystemTable EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS Driver is successfully loaded.
+ @retval Others Failed.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSdController (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSdControllerDriverBinding,
+ ImageHandle,
+ &gSdControllerName,
+ &gSdControllerName2
+ );
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has SdHostIoProtocol installed will be supported.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SdControllerSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS OpenStatus;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_CLASSC PciClass;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ UINTN Seg, Bus, Dev, Func;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSdHostIoProtocolGuid,
+ (VOID **) &SdHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ DEBUG (( DEBUG_INFO, "SdHost controller is already started\n"));
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (OpenStatus)) {
+ return OpenStatus;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (PCI_CLASSC) / sizeof (UINT8),
+ &PciClass
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Test whether the controller belongs to SD type
+ //
+ if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) ||
+ (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) ||
+ ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA))
+ ) {
+
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ Status = PciIo->GetLocation (
+ PciIo,
+ &Seg,
+ &Bus,
+ &Dev,
+ &Func
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ if ((Seg != 0) || (Bus != 0) || (Dev != 27) || (Func != 0)) {
+ //
+ // This is not the SD controller, bail.
+ //
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ DEBUG ((EFI_D_INFO, "%a(#%d) - Seg %d, bus:%d, Dev:%d, Func:%d\n", __FUNCTION__, __LINE__, Seg, Bus, Dev, Func));
+
+ON_EXIT:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+
+/**
+ Starting the SD Host Controller Driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+SdControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ SDHOST_DATA *SdHostData;
+ UINT32 Data;
+
+ SdHostData = NULL;
+ Data = 0;
+
+ //
+ // Open PCI I/O Protocol and save pointer to open protocol
+ // in private data area.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Enable the SD Host Controller MMIO space
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ SdHostData = (SDHOST_DATA *) AllocateZeroPool (sizeof (SDHOST_DATA));
+ if (SdHostData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ SdHostData->Signature = SDHOST_DATA_SIGNATURE;
+ SdHostData->PciIo = PciIo;
+
+ CopyMem (&SdHostData->SdHostIo, &mSdHostIo, sizeof (EFI_SD_HOST_IO_PROTOCOL));
+
+ ResetSdHost (&SdHostData->SdHostIo, Reset_All);
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64) MMIO_CTRLRVER,
+ 1,
+ &Data
+ );
+
+ SdHostData->SdHostIo.HostCapability.HostVersion = Data & 0xFF;
+ DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: HostVersion 0x%x \r\n", SdHostData->SdHostIo.HostCapability.HostVersion));
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64) MMIO_CAP,
+ 1,
+ &Data
+ );
+
+ DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MMIO_CAP 0x%x \r\n", Data));
+ if ((Data & BIT18) != 0) {
+ SdHostData->SdHostIo.HostCapability.BusWidth8 = TRUE;
+ }
+
+ if ((Data & BIT21) != 0) {
+ SdHostData->SdHostIo.HostCapability.HighSpeedSupport = TRUE;
+ }
+
+ if ((Data & BIT24) != 0) {
+ SdHostData->SdHostIo.HostCapability.V33Support = TRUE;
+ }
+
+ if ((Data & BIT25) != 0) {
+ SdHostData->SdHostIo.HostCapability.V30Support = TRUE;
+ }
+
+ if ((Data & BIT26) != 0) {
+ SdHostData->SdHostIo.HostCapability.V18Support = TRUE;
+ }
+
+ SdHostData->SdHostIo.HostCapability.BusWidth4 = TRUE;
+
+ if (SdHostData->SdHostIo.HostCapability.HostVersion < SDHCI_SPEC_300) {
+ SdHostData->BaseClockInMHz = (Data >> 8) & 0x3F;
+ } else {
+ SdHostData->BaseClockInMHz = (Data >> 8) & 0xFF;
+
+ }
+
+ SdHostData->BlockLength = 512 << ((Data >> 16) & 0x03);
+ DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: BlockLength 0x%x \r\n", SdHostData->BlockLength));
+ SdHostData->IsAutoStopCmd = TRUE;
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiSdHostIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &SdHostData->SdHostIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Install the component name protocol
+ //
+ SdHostData->ControllerNameTable = NULL;
+
+ AddUnicodeString2 (
+ "eng",
+ gSdControllerName.SupportedLanguages,
+ &SdHostData->ControllerNameTable,
+ L"SD Host Controller",
+ TRUE
+ );
+
+ AddUnicodeString2 (
+ "en",
+ gSdControllerName2.SupportedLanguages,
+ &SdHostData->ControllerNameTable,
+ L"SD Host Controller",
+ FALSE
+ );
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ if (SdHostData != NULL) {
+ FreePool (SdHostData);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to stop driver on.
+ @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param[in] ChildHandleBuffer List of handles for the children we need to stop.
+
+ @retval EFI_SUCCESS
+ @retval others
+
+**/
+EFI_STATUS
+EFIAPI
+SdControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ SDHOST_DATA *SdHostData;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSdHostIoProtocolGuid,
+ (VOID **) &SdHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ //
+ // Test whether the Controller handler passed in is a valid
+ // Usb controller handle that should be supported, if not,
+ // return the error status directly
+ //
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SetHostVoltage (SdHostIo, 0);
+
+ SdHostData = SDHOST_DATA_FROM_THIS(SdHostIo);
+
+ //
+ // Uninstall Block I/O protocol from the device handle
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiSdHostIoProtocolGuid,
+ SdHostIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FreeUnicodeStringTable (SdHostData->ControllerNameTable);
+
+ FreePool (SdHostData);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h
new file mode 100644
index 0000000..a702565
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h
@@ -0,0 +1,314 @@
+/** @file
+ The definition for SD host controller driver model and HC protocol routines.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 _SD_CONTROLLER_H_
+#define _SD_CONTROLLER_H_
+
+#include <Uefi.h>
+#include <Protocol/PciIo.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/GpioLib.h>
+#include "ComponentName.h"
+#include "SdHostIo.h"
+
+extern EFI_DRIVER_BINDING_PROTOCOL gSdControllerDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gSdControllerName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gSdControllerName2;
+
+#define SDHOST_DATA_SIGNATURE SIGNATURE_32 ('s', 'd', 'h', 's')
+
+#define BLOCK_SIZE 0x200
+#define TIME_OUT_1S 1000
+
+#pragma pack(1)
+
+//
+// PCI Class Code structure
+//
+typedef struct {
+ UINT8 PI;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} PCI_CLASSC;
+
+#pragma pack()
+
+typedef struct {
+ UINTN Signature;
+ EFI_SD_HOST_IO_PROTOCOL SdHostIo;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ BOOLEAN IsAutoStopCmd;
+ UINT32 BaseClockInMHz;
+ UINT32 CurrentClockInKHz;
+ UINT32 BlockLength;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} SDHOST_DATA;
+
+#define SDHOST_DATA_FROM_THIS(a) \
+ CR(a, SDHOST_DATA, SdHostIo, SDHOST_DATA_SIGNATURE)
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has SdHostIoProtocol installed will be supported.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SdControllerSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starting the SD Host Controller Driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+SdControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to stop driver on.
+ @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param[in] ChildHandleBuffer List of handles for the children we need to stop.
+
+ @retval EFI_SUCCESS
+ @retval others
+
+**/
+EFI_STATUS
+EFIAPI
+SdControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ The main function used to send the command to the card inserted into the SD host slot.
+ It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] CommandIndex The command index to set the command index field of command register.
+ @param[in] Argument Command argument to set the argument field of command register.
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param[in] Buffer Contains the data read from / write to the device.
+ @param[in] BufferSize The size of the buffer.
+ @param[in] ResponseType RESPONSE_TYPE.
+ @param[in] TimeOut Time out value in 1 ms unit.
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+ @retval EFI_TIMEOUT
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+SendCommand (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData OPTIONAL
+ );
+
+/**
+ Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.
+ It depends on the max frequency the host can support, divider, and host speed mode.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] MaxFrequency Max frequency in HZ.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+SetClockFrequency (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 MaxFrequencyInKHz
+ );
+
+/**
+ Set bus width of the host controller
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] BusWidth Bus width in 1, 4, 8 bits.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusWidth (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BusWidth
+ );
+
+/**
+ Set voltage which could supported by the host controller.
+ Support 0(Power off the host), 1.8V, 3.0V, 3.3V
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] Voltage Units in 0.1 V.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostVoltage (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 Voltage
+ );
+
+/**
+ Reset the host controller.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] ResetAll TRUE to reset all.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+ResetSdHost (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN RESET_TYPE ResetType
+ );
+
+/**
+ Enable auto stop on the host controller.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] Enable TRUE to enable, FALSE to disable.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+EnableAutoStopCmd (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+/**
+ Find whether these is a card inserted into the slot. If so init the host.
+ If not, return EFI_NOT_FOUND.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_FOUND
+
+**/
+EFI_STATUS
+EFIAPI
+DetectCardAndInitHost (
+ IN EFI_SD_HOST_IO_PROTOCOL *This
+ );
+
+/**
+ Set the Block length on the host controller.
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] BlockLength card supportes block length.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+SetBlockLength (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BlockLength
+ );
+
+/**
+ Enable/Disable High Speed transfer mode
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] Enable TRUE to Enable, FALSE to Disable
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+SetHighSpeedMode (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+EFI_STATUS
+EFIAPI
+SetDDRMode (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf
new file mode 100644
index 0000000..499c9b7
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf
@@ -0,0 +1,59 @@
+## @file
+# Component Description File For SdControllerDxe Module.
+#
+# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# 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 = 0x00010005
+ BASE_NAME = SdController
+ FILE_GUID = 90A330BD-6F89-4900-933A-C25EB4356348
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSdController
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gSdControllerDriverBinding
+# COMPONENT_NAME = gSdControllerName
+# COMPONENT_NAME2 = gSdControllerName2
+#
+
+[Sources]
+ SdController.c
+ SdController.h
+ ComponentName.c
+ ComponentName.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiSdHostIoProtocolGuid ## BY_START
+
+[FeaturePcd]
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c
new file mode 100644
index 0000000..cb7a1bb
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c
@@ -0,0 +1,638 @@
+/** @file
+ CEATA specific functions implementation
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SdMediaDevice.h"
+
+/**
+ Send RW_MULTIPLE_REGISTER command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] Address Register address.
+ @param[in] ByteCount Buffer size.
+ @param[in] Write TRUE means write, FALSE means read.
+ @param[in] Buffer Buffer pointer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadWriteMultipleRegister (
+ IN CARD_DATA *CardData,
+ IN UINT16 Address,
+ IN UINT8 ByteCount,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Argument;
+
+ Status = EFI_SUCCESS;
+
+ if ((Address % 4 != 0) || (ByteCount % 4 != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Argument = (Address << 16) | ByteCount;
+ if (Write) {
+ Argument |= BIT31;
+ }
+
+ if (Write) {
+ CopyMem (CardData->AlignedBuffer, Buffer, ByteCount);
+
+ Status = SendCommand (
+ CardData,
+ RW_MULTIPLE_REGISTER,
+ Argument,
+ OutData,
+ CardData->AlignedBuffer,
+ ByteCount,
+ ResponseR1b,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ } else {
+ Status = SendCommand (
+ CardData,
+ RW_MULTIPLE_REGISTER,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ ByteCount,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Buffer, CardData->AlignedBuffer, ByteCount);
+ }
+ }
+Exit:
+ return Status;
+}
+
+
+/**
+ Send ReadWriteMultipleBlock command with RW_MULTIPLE_REGISTER command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] DataUnitCount Buffer size in 512 bytes unit.
+ @param[in] Write TRUE means write, FALSE means read.
+ @param[in] Buffer Buffer pointer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadWriteMultipleBlock (
+ IN CARD_DATA *CardData,
+ IN UINT16 DataUnitCount,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ UINT32 TransferLength;
+
+ Status = EFI_SUCCESS;
+ SdHostIo = CardData->SdHostIo;
+
+ TransferLength = DataUnitCount * DATA_UNIT_SIZE;
+ if (TransferLength > SdHostIo->HostCapability.BoundarySize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Write) {
+ CopyMem (CardData->AlignedBuffer, Buffer, TransferLength);
+
+ Status = SendCommand (
+ CardData,
+ RW_MULTIPLE_BLOCK,
+ (DataUnitCount | BIT31),
+ OutData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1b,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ } else {
+ Status = SendCommand (
+ CardData,
+ RW_MULTIPLE_BLOCK,
+ DataUnitCount,
+ InData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Buffer, CardData->AlignedBuffer, TransferLength);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Send software reset
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SoftwareReset (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data;
+ UINT32 TimeOut;
+
+ Data = BIT2;
+
+ Status = FastIO (CardData, Reg_Control, &Data, TRUE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ TimeOut = 5 * 1000;
+
+ do {
+ gBS->Stall (1 * 1000);
+ Status = FastIO (CardData, Reg_Control, &Data, FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Data & BIT2) == BIT2) {
+ break;
+ }
+
+ TimeOut--;
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+ Data &= ~BIT2;
+ Status = FastIO (CardData, Reg_Control, &Data, TRUE);
+
+ TimeOut = 5 * 1000;
+
+ do {
+ gBS->Stall (1 * 1000);
+ Status = FastIO (CardData, Reg_Control, &Data, FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Data & BIT2) != BIT2) {
+ break;
+ }
+
+ TimeOut--;
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ SendATACommand specificed in Taskfile
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] TaskFile Pointer to TASK_FILE.
+ @param[in] Write TRUE means write, FALSE means read.
+ @param[in] Buffer If NULL, means no data transfer, neither read nor write.
+ @param[in] SectorCount Buffer size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SendATACommand (
+ IN CARD_DATA *CardData,
+ IN TASK_FILE *TaskFile,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data;
+ UINT32 TimeOut;
+
+ //
+ // Write register
+ //
+ Status = ReadWriteMultipleRegister (
+ CardData,
+ 0,
+ sizeof (TASK_FILE),
+ TRUE,
+ (UINT8 *) TaskFile
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ReadWriteMultipleRegister 0x%x\n", Status));
+ goto Exit;
+ }
+
+ TimeOut = 5000;
+ do {
+ gBS->Stall (1 * 1000);
+ Data = 0;
+ Status = FastIO (
+ CardData,
+ Reg_Command_Status,
+ &Data,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (((Data & BIT7) == 0) && ((Data & BIT6) == BIT6)) {
+ break;
+ }
+
+ TimeOut --;
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ DEBUG ((EFI_D_ERROR, "ReadWriteMultipleRegister FastIO EFI_TIMEOUT 0x%x\n", Data));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+ if (Buffer != NULL) {
+ Status = ReadWriteMultipleBlock (
+ CardData,
+ SectorCount,
+ Write,
+ (UINT8 *) Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ReadWriteMultipleBlock EFI_TIMEOUT 0x%x\n", Status));
+ goto Exit;
+ }
+
+ TimeOut = 5 * 1000;
+ do {
+ gBS->Stall (1 * 1000);
+ Data = 0;
+ Status = FastIO (
+ CardData,
+ Reg_Command_Status,
+ &Data,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (((Data & BIT7) == 0) && ((Data & BIT3) == 0)) {
+ break;
+ }
+
+ TimeOut --;
+ } while (TimeOut > 0);
+ if (TimeOut == 0) {
+ DEBUG ((EFI_D_ERROR, "ReadWriteMultipleBlock FastIO EFI_TIMEOUT 0x%x\n", Data));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+ if (((Data & BIT6) == BIT6) && (Data & BIT0) == 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ SoftwareReset (CardData);
+ }
+
+ return Status;
+}
+
+
+/**
+ IDENTIFY_DEVICE command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+IndentifyDevice (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ // The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = IDENTIFY_DEVICE;
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ (UINT8 *) &(CardData->IndentifyDeviceData),
+ 1
+ );
+
+ return Status;
+}
+
+
+/**
+ FLUSH_CACHE_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+FlushCache (
+ IN CARD_DATA *CardData
+ )
+{
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ STANDBY_IMMEDIATE command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+StandByImmediate (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ // The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = STANDBY_IMMEDIATE;
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ READ_DMA_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] LBA The starting logical block address to read from on the device.
+ @param[in] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param[in] SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ // The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = READ_DMA_EXT;
+
+ CardData->TaskFile.SectorCount = (UINT8) SectorCount;
+ CardData->TaskFile.SectorCount_Exp = (UINT8) (SectorCount >> 8);
+
+ CardData->TaskFile.LBALow = (UINT8) LBA;
+ CardData->TaskFile.LBAMid = (UINT8) RShiftU64 (LBA, 8);
+ CardData->TaskFile.LBAHigh = (UINT8) RShiftU64 (LBA, 16);
+
+ CardData->TaskFile.LBALow_Exp = (UINT8) RShiftU64 (LBA, 24);
+ CardData->TaskFile.LBAMid_Exp = (UINT8) RShiftU64 (LBA, 32);
+ CardData->TaskFile.LBAHigh_Exp = (UINT8) RShiftU64 (LBA, 40);
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ Buffer,
+ SectorCount
+ );
+
+ return Status;
+}
+
+
+/**
+ WRITE_DMA_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] LBA The starting logical block address to read from on the device.
+ @param[in] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param[in] SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+WriteDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ // The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = WRITE_DMA_EXT;
+
+ CardData->TaskFile.SectorCount = (UINT8) SectorCount;
+ CardData->TaskFile.SectorCount_Exp = (UINT8) (SectorCount >> 8);
+
+ CardData->TaskFile.LBALow = (UINT8) LBA;
+ CardData->TaskFile.LBAMid = (UINT8) RShiftU64 (LBA, 8);
+ CardData->TaskFile.LBAHigh = (UINT8) RShiftU64 (LBA, 16);
+
+ CardData->TaskFile.LBALow_Exp = (UINT8) RShiftU64 (LBA, 24);
+ CardData->TaskFile.LBAMid_Exp = (UINT8) RShiftU64 (LBA, 32);
+ CardData->TaskFile.LBAHigh_Exp = (UINT8) RShiftU64 (LBA, 40);
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ TRUE,
+ Buffer,
+ SectorCount
+ );
+
+ return Status;
+
+}
+
+
+/**
+ Judge whether it is CE-ATA device or not.
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval TRUE
+ @retval FALSE
+
+**/
+BOOLEAN
+IsCEATADevice (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ Status = ReadWriteMultipleRegister (
+ CardData,
+ 0,
+ sizeof (TASK_FILE),
+ FALSE,
+ (UINT8 *) &CardData->TaskFile
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // To bring back the normal MMC card to work
+ //
+ CardData->SdHostIo->ResetSdHost (CardData->SdHostIo, Reset_DAT_CMD);
+ return FALSE;
+ }
+
+ if (CardData->TaskFile.LBAMid == CE_ATA_SIG_CE &&
+ CardData->TaskFile.LBAHigh == CE_ATA_SIG_AA
+ ) {
+ //
+ // Disable Auto CMD for CE-ATA
+ //
+ CardData->SdHostIo->EnableAutoStopCmd (CardData->SdHostIo, FALSE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c
new file mode 100644
index 0000000..55fd085
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c
@@ -0,0 +1,384 @@
+/** @file
+ Block I/O protocol for CE-ATA device
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SdMediaDevice.h"
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive.
+ verification operation of the device during reset.
+ (This parameter is ingored in this driver.)
+
+ @retval EFI_SUCCESS Success
+
+**/
+EFI_STATUS
+EFIAPI
+CEATABlockReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+
+ CardData = CARD_DATA_FROM_THIS (This);
+ SdHostIo = CardData->SdHostIo;
+
+ if (!ExtendedVerification) {
+ Status = SoftwareReset (CardData);
+ } else {
+ Status = SdHostIo->ResetSdHost (SdHostIo, Reset_DAT_CMD);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" ));
+ return Status;
+ }
+ Status = MMCSDCardInit (CardData);
+ }
+
+ return Status;
+}
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] MediaId The media id that the write request is for.
+ @param[in] LBA The starting logical block address to read from on the device.
+ The caller is responsible for writing to only legitimate locations.
+ @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple of the
+ intrinsic block size of the device.
+ @param[out] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+EFIAPI
+CEATABlockReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ UINT32 TransferSize;
+ UINT8 *pBuf;
+ UINT32 Index;
+ UINT64 Address;
+ UINT32 Remainder;
+ UINT64 CEATALBA;
+ UINT32 BoundarySize;
+
+ Status = EFI_SUCCESS;
+ CardData = CARD_DATA_FROM_THIS (This);
+ pBuf = Buffer;
+ Index = 0;
+ Address = MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);
+ BoundarySize = CardData->SdHostIo->HostCapability.BoundarySize;
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));
+ goto Exit;
+ }
+
+ if (MediaId != CardData->BlockIoMedia.MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ DEBUG ((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" ));
+ goto Exit;
+ }
+
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" ));
+ goto Exit;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));
+ goto Exit;
+ }
+
+ do {
+ if (BufferSize < BoundarySize) {
+ TransferSize = (UINT32) BufferSize;
+ } else {
+ TransferSize = BoundarySize;
+ }
+
+ Address += Index * TransferSize;
+ CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);
+ ASSERT(Remainder == 0);
+
+ Status = ReadDMAExt (
+ CardData,
+ CEATALBA,
+ pBuf,
+ (UINT16) (TransferSize / DATA_UNIT_SIZE)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));
+ This->Reset (This, TRUE);
+ goto Exit;
+ }
+
+ BufferSize -= TransferSize;
+ pBuf += TransferSize;
+ Index ++;
+ } while (BufferSize != 0);
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] MediaId The media id that the write request is for.
+ @param[in] LBA The starting logical block address to read from on the device.
+ The caller is responsible for writing to only legitimate locations.
+ @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple of the
+ intrinsic block size of the device.
+ @param[in] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+EFIAPI
+CEATABlockWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ UINT32 TransferSize;
+ UINT8 *pBuf;
+ UINT32 Index;
+ UINT64 Address;
+ UINT32 Remainder;
+ UINT64 CEATALBA;
+ UINT32 BoundarySize;
+
+ Status = EFI_SUCCESS;
+ CardData = CARD_DATA_FROM_THIS (This);
+ pBuf = Buffer;
+ Index = 0;
+ Address = MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);
+ BoundarySize = CardData->SdHostIo->HostCapability.BoundarySize;
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (MediaId != CardData->BlockIoMedia.MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ goto Exit;
+ }
+
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Exit;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ if (CardData->BlockIoMedia.ReadOnly) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+
+ if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ CardData->NeedFlush = TRUE;
+
+ do {
+ if (BufferSize < BoundarySize) {
+ TransferSize = (UINT32) BufferSize;
+ } else {
+ TransferSize = BoundarySize;
+ }
+
+ Address += Index * TransferSize;
+ CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);
+ ASSERT (Remainder == 0);
+
+ Status = WriteDMAExt (
+ CardData,
+ CEATALBA,
+ pBuf,
+ (UINT16) (TransferSize / DATA_UNIT_SIZE)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));
+ This->Reset (This, TRUE);
+ goto Exit;
+ }
+
+ BufferSize -= TransferSize;
+ pBuf += TransferSize;
+ Index ++;
+ } while (BufferSize != 0);
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
+ (In this driver, this function just returns EFI_SUCCESS.)
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+**/
+EFI_STATUS
+EFIAPI
+CEATABlockFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+
+ CARD_DATA *CardData;
+
+ CardData = CARD_DATA_FROM_THIS (This);
+
+ if (CardData->NeedFlush) {
+ CardData->NeedFlush = FALSE;
+ FlushCache (CardData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ CEATA card BlockIo init function.
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+**/
+EFI_STATUS
+CEATABlockIoInit (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT64 MaxSize;
+ UINT32 Remainder;
+
+ //
+ // BlockIO protocol
+ //
+ CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
+ CardData->BlockIo.Media = &(CardData->BlockIoMedia);
+ CardData->BlockIo.Reset = CEATABlockReset;
+ CardData->BlockIo.ReadBlocks = CEATABlockReadBlocks ;
+ CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;
+ CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;
+
+ CardData->BlockIoMedia.MediaId = 0;
+ CardData->BlockIoMedia.RemovableMedia = FALSE;
+ CardData->BlockIoMedia.MediaPresent = TRUE;
+ CardData->BlockIoMedia.LogicalPartition = FALSE;
+
+ if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {
+ CardData->BlockIoMedia.ReadOnly = TRUE;
+ } else {
+ CardData->BlockIoMedia.ReadOnly = FALSE;
+ }
+
+ CardData->BlockIoMedia.WriteCaching = FALSE;
+ CardData->BlockIoMedia.IoAlign = 1;
+
+ Status = IndentifyDevice (CardData);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ //Some device does not support this feature
+ //
+ if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {
+ CardData->BlockIoMedia.ReadOnly = TRUE;
+ }
+
+ CardData->BlockIoMedia.BlockSize = (1 << CardData->IndentifyDeviceData.Sectorsize);
+ ASSERT (CardData->BlockIoMedia.BlockSize >= 12);
+
+
+ MaxSize = *(UINT64 *) (CardData->IndentifyDeviceData.MaximumLBA);
+ MaxSize = MultU64x32 (MaxSize, 512);
+
+ Remainder = 0;
+ CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);
+ ASSERT (Remainder == 0);
+
+ CardData->BlockIoMedia.LastBlock = (EFI_LBA) (CardData->BlockNumber - 1);
+
+Exit:
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c
new file mode 100644
index 0000000..15fdaf6
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c
@@ -0,0 +1,219 @@
+/** @file
+ UEFI Component Name(2) protocol implementation for SD media device driver.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SdMediaDevice.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSdMediaDeviceName = {
+ SdMediaDeviceGetDriverName,
+ SdMediaDeviceGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSdMediaDeviceName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SdMediaDeviceGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SdMediaDeviceGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdMediaDeviceDriverNameTable[] = {
+ { "eng;en", L"UEFI MMC/SD Media Device Driver" },
+ { NULL, NULL }
+};
+
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form 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 name 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] Language 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 SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+
+ @param[out] DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language 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
+SdMediaDeviceGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mSdMediaDeviceDriverNameTable,
+ DriverName,
+ (BOOLEAN) (This == &gSdMediaDeviceName)
+ );
+}
+
+
+/**
+ 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 specified by
+ ControllerHandle and ChildHandle in the form 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 controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param[in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ 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 name of a
+ child controller.
+
+ @param[in] Language 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 SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+
+ @param[out] ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for 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
+SdMediaDeviceGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ CARD_DATA *CardData;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ gSdMediaDeviceDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CardData = CARD_DATA_FROM_THIS (BlockIo);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ CardData->ControllerNameTable,
+ ControllerName,
+ (BOOLEAN) (This == &gSdMediaDeviceName)
+ );
+
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h
new file mode 100644
index 0000000..3dea441
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h
@@ -0,0 +1,145 @@
+/** @file
+ This file contains the declarations for component name routines.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 _COMPONENT_NAME_H_
+#define _COMPONENT_NAME_H_
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form 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 name 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] Language 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 SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+
+ @param[out] DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language 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
+SdMediaDeviceGetDriverName (
+ 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 specified by
+ ControllerHandle and ChildHandle in the form 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 controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param[in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ 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 name of a
+ child controller.
+
+ @param[in] Language 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 SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+
+ @param[out] ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for 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
+SdMediaDeviceGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c
new file mode 100644
index 0000000..6180a25
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c
@@ -0,0 +1,547 @@
+/** @file
+ Block I/O protocol for MMC/SD device.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SdMediaDevice.h"
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive.
+ verification operation of the device during reset.
+ (This parameter is ignored in this driver.)
+
+ @retval EFI_SUCCESS Success
+
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ CARD_DATA *CardData;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+
+ CardData = CARD_DATA_FROM_THIS (This);
+ SdHostIo = CardData->SdHostIo;
+
+ return SdHostIo->ResetSdHost (SdHostIo, Reset_DAT_CMD);
+ }
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] MediaId The media id that the write request is for.
+ @param[in] LBA The starting logical block address to read from on the device.
+ The caller is responsible for writing to only legitimate locations.
+ @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple of the
+ intrinsic block size of the device.
+ @param[out] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ CARD_DATA *CardData;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ UINT32 RemainingLength;
+ UINT32 TransferLength;
+ UINT8 *BufferPointer;
+ BOOLEAN SectorAddressing;
+ UINTN TotalBlock;
+
+ DEBUG ((EFI_D_INFO, "Read(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));
+ Status = EFI_SUCCESS;
+ CardData = CARD_DATA_FROM_THIS (This);
+ SdHostIo = CardData->SdHostIo;
+
+ if (MediaId != CardData->BlockIoMedia.MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (ModU64x32 (BufferSize, CardData->BlockIoMedia.BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ if ((CardData->CardType == SdMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) {
+ SectorAddressing = TRUE;
+ } else {
+ SectorAddressing = FALSE;
+ }
+ if (SectorAddressing) {
+ //
+ //Block Address
+ //
+ Address = (UINT32) DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);
+ } else {
+ //
+ //Byte Address
+ //
+ Address = (UINT32) MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);
+ }
+ TotalBlock = (UINTN) DivU64x32 (BufferSize, CardData->BlockIoMedia.BlockSize);
+ if (LBA + TotalBlock > CardData->BlockIoMedia.LastBlock + 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks:Invalid parameter \r\n"));
+ goto Done;
+ }
+
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Bad buffer size \r\n"));
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ BufferPointer = Buffer;
+ RemainingLength = (UINT32) BufferSize;
+
+ while (RemainingLength > 0) {
+ if ((BufferSize > CardData->BlockIoMedia.BlockSize)) {
+ if (RemainingLength > SdHostIo->HostCapability.BoundarySize) {
+ TransferLength = SdHostIo->HostCapability.BoundarySize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {
+ if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) {
+ Status = SendCommand (
+ CardData,
+ SET_BLOCKLEN,
+ CardData->BlockIoMedia.BlockSize,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ Status = SendCommand (
+ CardData,
+ SET_BLOCK_COUNT,
+ TransferLength / CardData->BlockIoMedia.BlockSize,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ Status = SendCommand (
+ CardData,
+ READ_MULTIPLE_BLOCK,
+ Address,
+ InData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n"));
+ break;
+ }
+ } else {
+ if (RemainingLength > CardData->BlockIoMedia.BlockSize) {
+ TransferLength = CardData->BlockIoMedia.BlockSize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ Status = SendCommand (
+ CardData,
+ READ_SINGLE_BLOCK,
+ Address,
+ InData,
+ CardData->AlignedBuffer,
+ (UINT32) TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n"));
+ break;
+ }
+ }
+ CopyMem (BufferPointer, CardData->AlignedBuffer, TransferLength);
+ if (SectorAddressing) {
+ //
+ //Block Address
+ //
+ Address += TransferLength / 512;
+ } else {
+ //
+ //Byte Address
+ //
+ Address += TransferLength;
+ }
+ BufferPointer += TransferLength;
+ RemainingLength -= TransferLength;
+ }
+
+ if (EFI_ERROR (Status)) {
+ if ((CardData->CardType == SdMemoryCard) ||
+ (CardData->CardType == SdMemoryCard2)||
+ (CardData->CardType == SdMemoryCard2High)) {
+ SendCommand (
+ CardData,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ } else {
+ SendCommand (
+ CardData,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+ }
+
+ }
+
+Done:
+ DEBUG ((EFI_D_INFO, "MMCSDBlockReadBlocks: Status = %r\n", Status));
+ return Status;
+}
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param[in] MediaId The media id that the write request is for.
+ @param[in] LBA The starting logical block address to read from on the device.
+ The caller is responsible for writing to only legitimate locations.
+ @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple of the
+ intrinsic block size of the device.
+ @param[in] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ CARD_DATA *CardData;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ UINT32 RemainingLength;
+ UINT32 TransferLength;
+ UINT8 *BufferPointer;
+ BOOLEAN SectorAddressing;
+
+ DEBUG ((EFI_D_INFO, "Write(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));
+ Status = EFI_SUCCESS;
+ CardData = CARD_DATA_FROM_THIS (This);
+ SdHostIo = CardData->SdHostIo;
+ if ((CardData->CardType == SdMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) {
+ SectorAddressing = TRUE;
+ } else {
+ SectorAddressing = FALSE;
+ }
+ if (SectorAddressing) {
+ //
+ //Block Address
+ //
+ Address = (UINT32) DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);
+ } else {
+ //
+ //Byte Address
+ //
+ Address = (UINT32) MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);
+ }
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Invalid parameter \r\n"));
+ goto Done;
+ }
+
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Bad buffer size \r\n"));
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ if (This->Media->ReadOnly == TRUE) {
+ Status = EFI_WRITE_PROTECTED;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Write protected \r\n"));
+ goto Done;
+ }
+
+ BufferPointer = Buffer;
+ RemainingLength = (UINT32) BufferSize;
+
+ while (RemainingLength > 0) {
+ if ((BufferSize > CardData->BlockIoMedia.BlockSize) ) {
+ if (RemainingLength > SdHostIo->HostCapability.BoundarySize) {
+ TransferLength = SdHostIo->HostCapability.BoundarySize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {
+
+ if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) {
+ Status = SendCommand (
+ CardData,
+ SET_BLOCKLEN,
+ CardData->BlockIoMedia.BlockSize,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ Status = SendCommand (
+ CardData,
+ SET_BLOCK_COUNT,
+ TransferLength / CardData->BlockIoMedia.BlockSize,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);
+
+ Status = SendCommand (
+ CardData,
+ WRITE_MULTIPLE_BLOCK,
+ Address,
+ OutData,
+ CardData->AlignedBuffer,
+ (UINT32) TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n"));
+ break;
+ }
+ } else {
+ if (RemainingLength > CardData->BlockIoMedia.BlockSize) {
+ TransferLength = CardData->BlockIoMedia.BlockSize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);
+
+ Status = SendCommand (
+ CardData,
+ WRITE_BLOCK,
+ Address,
+ OutData,
+ CardData->AlignedBuffer,
+ (UINT32) TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ }
+
+ if (SectorAddressing) {
+ //
+ //Block Address
+ //
+ Address += TransferLength / 512;
+ } else {
+ //
+ //Byte Address
+ //
+ Address += TransferLength;
+ }
+ BufferPointer += TransferLength;
+ RemainingLength -= TransferLength;
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ SendCommand (
+ CardData,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ }
+
+Done:
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
+ (In this driver, this function just returns EFI_SUCCESS.)
+
+ @param[in] This The EFI_BLOCK_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ MMC/SD card BlockIo init function.
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+**/
+EFI_STATUS
+MMCSDBlockIoInit (
+ IN CARD_DATA *CardData
+ )
+{
+
+ //
+ // BlockIO protocol
+ //
+ CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
+ CardData->BlockIo.Media = &(CardData->BlockIoMedia);
+ CardData->BlockIo.Reset = MMCSDBlockReset;
+ CardData->BlockIo.ReadBlocks = MMCSDBlockReadBlocks ;
+ CardData->BlockIo.WriteBlocks = MMCSDBlockWriteBlocks;
+ CardData->BlockIo.FlushBlocks = MMCSDBlockFlushBlocks;
+
+ CardData->BlockIoMedia.MediaId = 0;
+ CardData->BlockIoMedia.RemovableMedia = FALSE;
+ CardData->BlockIoMedia.MediaPresent = TRUE;
+ CardData->BlockIoMedia.LogicalPartition = FALSE;
+
+ if (CardData->CSDRegister.PERM_WRITE_PROTECT || CardData->CSDRegister.TMP_WRITE_PROTECT) {
+ CardData->BlockIoMedia.ReadOnly = TRUE;
+ } else {
+ CardData->BlockIoMedia.ReadOnly = FALSE;
+ }
+
+ CardData->BlockIoMedia.WriteCaching = FALSE;
+ CardData->BlockIoMedia.BlockSize = CardData->BlockLen;
+ CardData->BlockIoMedia.IoAlign = 1;
+ CardData->BlockIoMedia.LastBlock = (EFI_LBA) (CardData->BlockNumber - 1);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c
new file mode 100644
index 0000000..e0304de
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c
@@ -0,0 +1,1661 @@
+/** @file
+ MMC/SD transfer specific functions
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SdMediaDevice.h"
+
+
+/**
+ Check card status, print the debug info and check the error
+
+ @param[in] Status Status got from card status register.
+
+ @retval EFI_SUCCESS
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+CheckCardStatus (
+ IN UINT32 Status
+ )
+{
+ CARD_STATUS *CardStatus;
+ CardStatus = (CARD_STATUS *) (&Status);
+
+ if (CardStatus->ADDRESS_OUT_OF_RANGE) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_OUT_OF_RANGE\n"));
+ }
+
+ if (CardStatus->ADDRESS_MISALIGN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_MISALIGN\n"));
+ }
+
+ if (CardStatus->BLOCK_LEN_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: BLOCK_LEN_ERROR\n"));
+ }
+
+ if (CardStatus->ERASE_SEQ_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_SEQ_ERROR\n"));
+ }
+
+ if (CardStatus->ERASE_PARAM) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_PARAM\n"));
+ }
+
+ if (CardStatus->WP_VIOLATION) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: WP_VIOLATION\n"));
+ }
+
+ if (CardStatus->CARD_IS_LOCKED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CARD_IS_LOCKED\n"));
+ }
+
+ if (CardStatus->LOCK_UNLOCK_FAILED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: LOCK_UNLOCK_FAILED\n"));
+ }
+
+ if (CardStatus->COM_CRC_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: COM_CRC_ERROR\n"));
+ }
+
+ if (CardStatus->ILLEGAL_COMMAND) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ILLEGAL_COMMAND\n"));
+ }
+
+ if (CardStatus->CARD_ECC_FAILED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CARD_ECC_FAILED\n"));
+ }
+
+ if (CardStatus->CC_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CC_ERROR\n"));
+ }
+
+ if (CardStatus->ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERROR\n"));
+ }
+
+ if (CardStatus->UNDERRUN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: UNDERRUN\n"));
+ }
+
+ if (CardStatus->OVERRUN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: OVERRUN\n"));
+ }
+
+ if (CardStatus->CID_CSD_OVERWRITE) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CID_CSD_OVERWRITE\n"));
+ }
+
+ if (CardStatus->WP_ERASE_SKIP) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: WP_ERASE_SKIP\n"));
+ }
+
+ if (CardStatus->ERASE_RESET) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_RESET\n"));
+ }
+
+ if (CardStatus->SWITCH_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: SWITCH_ERROR\n"));
+ }
+
+ if ((Status & 0xFCFFA080) != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Send command by using Host IO protocol
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] CommandIndex The command index to set the command index field of command register.
+ @param[in] Argument Command argument to set the argument field of command register.
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param[in] Buffer Contains the data read from / write to the device.
+ @param[in] BufferSize The size of the buffer.
+ @param[in] ResponseType RESPONSE_TYPE.
+ @param[in] TimeOut Time out value in 1 ms unit.
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+SendCommand (
+ IN CARD_DATA *CardData,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+
+ SdHostIo = CardData->SdHostIo;
+ if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) {
+ CommandIndex |= AUTO_CMD12_ENABLE;
+ }
+ Status = SdHostIo->SendCommand (
+ SdHostIo,
+ CommandIndex,
+ Argument,
+ DataType,
+ Buffer,
+ BufferSize,
+ ResponseType,
+ TimeOut,
+ ResponseData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {
+ ASSERT (ResponseData != NULL);
+ Status = CheckCardStatus (*ResponseData);
+ }
+ } else {
+ SdHostIo->ResetSdHost (SdHostIo, Reset_DAT_CMD);
+ }
+
+ return Status;
+}
+
+
+/**
+ Send the card APP_CMD command with the following command indicated by CommandIndex
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] CommandIndex The command index to set the command index field of command register.
+ @param[in] Argument Command argument to set the argument field of command register.
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param[in] Buffer Contains the data read from / write to the device.
+ @param[in] BufferSize The size of the buffer.
+ @param[in] ResponseType RESPONSE_TYPE.
+ @param[in] TimeOut Time out value in 1 ms unit.
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+SendAppCommand (
+ IN CARD_DATA *CardData,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ UINT8 Index;
+
+ SdHostIo = CardData->SdHostIo;
+ Status = EFI_SUCCESS;
+
+ for (Index = 0; Index < 2; Index++) {
+ Status = SdHostIo->SendCommand (
+ SdHostIo,
+ APP_CMD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = CheckCardStatus (*(UINT32 *) &(CardData->CardStatus));
+ if (CardData->CardStatus.SAPP_CMD != 1) {
+ Status = EFI_DEVICE_ERROR;
+ }
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ } else {
+ SdHostIo->ResetSdHost (SdHostIo, Reset_Auto);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) {
+ CommandIndex |= AUTO_CMD12_ENABLE;
+ }
+
+ Status = SdHostIo->SendCommand (
+ SdHostIo,
+ CommandIndex,
+ Argument,
+ DataType,
+ Buffer,
+ BufferSize,
+ ResponseType,
+ TimeOut,
+ ResponseData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {
+ ASSERT (ResponseData != NULL);
+ Status = CheckCardStatus (*ResponseData);
+ }
+ } else {
+ SdHostIo->ResetSdHost (SdHostIo, Reset_Auto);
+ }
+
+ return Status;
+}
+
+
+/**
+ Send the card FAST_IO command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] RegisterAddress Register Address.
+ @param[in, out] RegisterData Pointer to register Data.
+ @param[in] Write TRUE for write, FALSE for read.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+FastIO (
+ IN CARD_DATA *CardData,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT8 *RegisterData,
+ IN BOOLEAN Write
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Argument;
+ UINT32 Data;
+
+ Status = EFI_SUCCESS;
+
+ if (RegisterData == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Argument = (CardData->Address << 16) | (RegisterAddress << 8);
+ if (Write) {
+ Argument |= BIT15 | (*RegisterData);
+ }
+
+ Status = SendCommand (
+ CardData,
+ FAST_IO,
+ Argument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR4,
+ TIMEOUT_COMMAND,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Data & BIT15) == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ if (!Write) {
+ *RegisterData = (UINT8) Data;
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Send the card GO_INACTIVE_STATE command.
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval others
+
+**/
+EFI_STATUS
+PutCardInactive (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+
+ Status = SendCommand (
+ CardData,
+ GO_INACTIVE_STATE,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+
+ return Status;
+
+}
+
+
+/**
+ Get card interested information for CSD rergister
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+CaculateCardParameter (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Frequency;
+ UINT32 Multiple;
+ UINT32 CSize;
+ CSD_SDV2 *CsdSDV2;
+
+ Status = EFI_SUCCESS;
+
+ switch (CardData->CSDRegister.TRAN_SPEED & 0x7) {
+ case 0:
+ Frequency = 100 * 1000;
+ break;
+
+ case 1:
+ Frequency = 1 * 1000 * 1000;
+ break;
+
+ case 2:
+ Frequency = 10 * 1000 * 1000;
+ break;
+
+ case 3:
+ Frequency = 100 * 1000 * 1000;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ switch ((CardData->CSDRegister.TRAN_SPEED >> 3) & 0xF) {
+ case 1:
+ Multiple = 10;
+ break;
+
+ case 2:
+ Multiple = 12;
+ break;
+
+ case 3:
+ Multiple = 13;
+ break;
+
+ case 4:
+ Multiple = 15;
+ break;
+
+ case 5:
+ Multiple = 20;
+ break;
+
+ case 6:
+ if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {
+ Multiple = 26;
+ } else {
+ Multiple = 25;
+ }
+ break;
+
+ case 7:
+ Multiple = 30;
+ break;
+
+ case 8:
+ Multiple = 35;
+ break;
+
+ case 9:
+ Multiple = 40;
+ break;
+
+ case 10:
+ Multiple = 45;
+ break;
+
+ case 11:
+ if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {
+ Multiple = 52;
+ } else {
+ Multiple = 50;
+ }
+ break;
+
+ case 12:
+ Multiple = 55;
+ break;
+
+ case 13:
+ Multiple = 60;
+ break;
+
+ case 14:
+ Multiple = 70;
+ break;
+
+ case 15:
+ Multiple = 80;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Frequency = Frequency * Multiple / 10;
+ CardData->MaxFrequency = Frequency;
+
+ CardData->BlockLen = 1 << CardData->CSDRegister.READ_BL_LEN;
+
+ if (CardData->CardType == SdMemoryCard2High) {
+ ASSERT (CardData->CSDRegister.CSD_STRUCTURE == 1);
+ CsdSDV2 = (CSD_SDV2 *) &CardData->CSDRegister;
+
+ //
+ // the K here means 1024 not 1000
+ //
+ CardData->BlockNumber = DivU64x32 (MultU64x32 (CsdSDV2->C_SIZE + 1, 512 * 1024) , CardData->BlockLen);
+ } else {
+ //
+ // For MMC card > 2G, the block number will be recaculate later
+ //
+ CSize = CardData->CSDRegister.C_SIZELow2 | (CardData->CSDRegister.C_SIZEHigh10 << 2);
+ CardData->BlockNumber = MultU64x32 (LShiftU64 (1, CardData->CSDRegister.C_SIZE_MULT + 2), CSize + 1);
+ }
+
+ //
+ //For >= 2G card, BlockLen may be 1024, but the transfer size is still 512 bytes
+ //
+ if (CardData->BlockLen > 512) {
+ CardData->BlockNumber = DivU64x32 (MultU64x32 (CardData->BlockNumber, CardData->BlockLen), 512);
+ CardData->BlockLen = 512;
+ }
+
+ DEBUG ((
+ EFI_D_INFO,
+ "CalculateCardParameter: Card Size: 0x%lx\n", MultU64x32 (CardData->BlockNumber, CardData->BlockLen)
+ ));
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Test the bus width setting for MMC card.It is used only for verification purpose.
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] Width 1, 4, 8 bits.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+MMCCardBusWidthTest (
+ IN CARD_DATA *CardData,
+ IN UINT32 Width
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Data;
+ UINT64 Value;
+
+ ASSERT(CardData != NULL);
+
+ Value = 0;
+
+ switch (Width) {
+ case 1:
+ Data = 0x80;
+ break;
+
+ case 4:
+ Data = 0x5A;
+ break;
+
+ case 8:
+ Data = 0xAA55;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ CopyMem (CardData->AlignedBuffer, &Data, Width);
+ Status = SendCommand (
+ CardData,
+ BUSTEST_W,
+ 0,
+ OutData,
+ CardData->AlignedBuffer,
+ Width,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_W 0x%x\n", *(UINT32*)&(CardData->CardStatus)));
+ goto Exit;
+ }
+
+ gBS->Stall (10 * 1000);
+
+ Data = 0;
+
+ Status = SendCommand (
+ CardData,
+ BUSTEST_R,
+ 0,
+ InData,
+ CardData->AlignedBuffer,
+ Width,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_R 0x%x\n", *(UINT32 *) &(CardData->CardStatus)));
+ goto Exit;
+ }
+ CopyMem (&Data, CardData->AlignedBuffer, Width);
+
+ switch (Width) {
+ case 1:
+ Value = (~(Data ^ 0x80)) & 0xC0;
+ break;
+
+ case 4:
+ Value = (~(Data ^ 0x5A)) & 0xFF;
+ break;
+
+ case 8:
+ Value = (~(Data ^ 0xAA55)) & 0xFFFF;
+ break;
+ }
+
+ if (Value == 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ This function can detect these card types:
+ 1. MMC card
+ 2. SD 1.1 card
+ 3. SD 2.0 standard card
+ 3. SD 2.0 high capacity card
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval others
+
+**/
+EFI_STATUS
+GetCardType (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ UINT32 Argument;
+ UINT32 ResponseData;
+ UINT32 Count;
+ BOOLEAN SdCommand8Support;
+
+ SdHostIo = CardData->SdHostIo;
+
+ //
+ // Reset the card
+ //
+ Status = SendCommand (
+ CardData,
+ GO_IDLE_STATE,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ gBS->Stall (10 * 1000);
+
+ //
+ // Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass
+ // MMC and SD1.1 card will fail this command
+ //
+ Argument = (VOLTAGE_27_36 << 8) | CHECK_PATTERN;
+ ResponseData = 0;
+ SdCommand8Support = FALSE;
+
+ Status = SendCommand (
+ CardData,
+ SEND_IF_COND,
+ Argument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR7,
+ TIMEOUT_COMMAND,
+ &ResponseData
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_TIMEOUT) {
+ DEBUG ((EFI_D_ERROR, "SEND_IF_COND Fail, none time out error\n"));
+ goto Exit;
+ }
+ } else {
+ if (ResponseData != Argument) {
+ DEBUG ((EFI_D_ERROR, "SEND_IF_COND Fail, respond data does not match send data\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ SdCommand8Support = TRUE;
+ }
+
+ Argument = 0;
+
+ if (SdHostIo->HostCapability.V30Support == TRUE) {
+ Argument |= BIT17 | BIT18;
+ } else if (SdHostIo->HostCapability.V33Support == TRUE) {
+ Argument |= BIT20 | BIT21;
+ }
+
+ if (SdCommand8Support) {
+ Argument |= BIT30;
+ }
+
+ Count = 20;
+ do {
+ Status = SendAppCommand (
+ CardData,
+ SD_SEND_OP_COND,
+ Argument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->OCRRegister)
+ );
+
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_TIMEOUT) && (!SdCommand8Support)) {
+ CardData->CardType = MMCCard;
+ Status = EFI_SUCCESS;
+ DEBUG ((EFI_D_INFO, "SD_SEND_OP_COND, MMC card was identified\n"));
+ } else {
+ DEBUG ((EFI_D_ERROR, "SD_SEND_OP_COND Fail, check whether it is neither a MMC card nor a SD card\n"));
+ }
+ goto Exit;
+ }
+ //
+ // Avoid waiting if sucess. Busy bit 0 means not ready
+ //
+ if (CardData->OCRRegister.Busy == 1) {
+ break;
+ }
+
+ gBS->Stall (50 * 1000);
+ Count--;
+ if (Count == 0) {
+ DEBUG ((EFI_D_ERROR, "Card is always in busy state\n"));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ } while (1);
+
+ //
+ // Check supported voltage
+ //
+ Argument = 0;
+ if (SdHostIo->HostCapability.V30Support == TRUE) {
+ if ((CardData->OCRRegister.V270_V360 & BIT2) == BIT2) {
+ Argument |= BIT17;
+ } else if ((CardData->OCRRegister.V270_V360 & BIT3) == BIT3) {
+ Argument |= BIT18;
+ }
+ } else if (SdHostIo->HostCapability.V33Support == TRUE) {
+ if ((CardData->OCRRegister.V270_V360 & BIT5) == BIT5) {
+ Argument |= BIT20;
+ } else if ((CardData->OCRRegister.V270_V360 & BIT6) == BIT6) {
+ Argument |= BIT21;
+ }
+ }
+
+ if (Argument == 0) {
+ //
+ // No matched support voltage
+ //
+ PutCardInactive (CardData);
+ DEBUG ((EFI_D_ERROR, "No matched voltage for this card\n"));
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ CardData->CardType = SdMemoryCard;
+ if (SdCommand8Support == TRUE) {
+ CardData->CardType = SdMemoryCard2;
+ DEBUG ((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above standard card was identified\n"));
+ }
+
+ if ((CardData->OCRRegister.AccessMode & BIT1) == BIT1) {
+ CardData->CardType = SdMemoryCard2High;
+ DEBUG ((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above high capacity card was identified\n"));
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ MMC card high/low voltage selection function
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_BAD_BUFFER_SIZE
+
+**/
+EFI_STATUS
+MMCCardVoltageSelection (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Retry;
+ UINT32 TimeOut;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // First try the high voltage, then if supported choose the low voltage
+ //
+ for (Retry = 0; Retry < 3; Retry++) {
+ //
+ // To bring back the normal MMC card to work
+ // after sending the SD command. Otherwise some
+ // card could not work
+
+ Status = SendCommand (
+ CardData,
+ GO_IDLE_STATE,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));
+ continue;
+ }
+ //
+ //CE-ATA device needs long delay
+ //
+ gBS->Stall ((Retry + 1) * 50 * 1000);
+
+ //
+ // Get OCR register to check voltage support, first time the OCR is 0
+ //
+ Status = SendCommand (
+ CardData,
+ SEND_OP_COND,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->OCRRegister)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (Retry == 3) {
+ DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ //
+ // TimeOut Value, 5000 * 100 * 1000 = 5 s
+ //
+ TimeOut = 5000;
+
+ do {
+ Status = SendCommand (
+ CardData,
+ SEND_OP_COND,
+ 0x40300000,
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->OCRRegister)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ gBS->Stall (1 * 1000);
+ TimeOut--;
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((EFI_D_ERROR, "Card is always in busy state\n"));
+ goto Exit;
+ }
+ } while (CardData->OCRRegister.Busy != 1);
+
+ if (CardData->OCRRegister.AccessMode == 2) {
+ DEBUG ((EFI_D_INFO, "eMMC Card is High Capacity\n"));
+ CardData->CardType = MMCCardHighCap;
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ This function set the bus and device width for MMC card.
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] BusWidth 1, 4, 8 bits.
+ @param[in] EnableDDRMode Enable DDR Mode.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+MMCCardSetBusWidth (
+ IN CARD_DATA *CardData,
+ IN UINT8 BusWidth,
+ IN BOOLEAN EnableDDRMode
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ SWITCH_ARGUMENT SwitchArgument;
+ UINT8 Value;
+
+ SdHostIo = CardData->SdHostIo;
+ Value = 0;
+ switch (BusWidth) {
+ case 8:
+ if (EnableDDRMode)
+ Value = 6;
+ else
+ Value = 2;
+ break;
+
+ case 4:
+ if (EnableDDRMode)
+ Value = 5;
+ else
+ Value = 1;
+ break;
+
+ case 1:
+ if (EnableDDRMode) // Bus width 1 is not supported in ddr mode
+ return EFI_UNSUPPORTED;
+ Value = 0;
+ break;
+
+ default:
+ ASSERT (0);
+ }
+
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = Value;
+ SwitchArgument.Index = (UINT32) ((UINTN)
+ (&(CardData->ExtCSDRegister.BUS_WIDTH)) - (UINTN) (&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ CardData,
+ SWITCH,
+ *(UINT32 *) &SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ CardData,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SWITCH %d bits Fail\n", BusWidth));
+ goto Exit;
+ } else {
+ DEBUG ((EFI_D_ERROR, "MMCCardSetBusWidth:SWITCH Card Status:0x%x\n", *(UINT32 *) &(CardData->CardStatus)));
+ Status = SdHostIo->SetBusWidth (SdHostIo, BusWidth);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SWITCH set %d bits Fail\n", BusWidth));
+ goto Exit;
+ }
+ gBS->Stall (5 * 1000);
+ }
+ }
+
+ if (!EnableDDRMode) { // CMD19 and CMD14 are illegal commands in ddr mode
+
+ Status = MMCCardBusWidthTest (CardData, BusWidth);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCCardBusWidthTest %d bit Fail\n", BusWidth));
+ goto Exit;
+ }
+ }
+
+ CardData->CurrentBusWidth = BusWidth;
+
+Exit:
+ return Status;
+}
+
+
+/**
+ MMC/SD card init function
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval others
+
+**/
+EFI_STATUS
+MMCSDCardInit (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ SWITCH_ARGUMENT SwitchArgument;
+ UINT32 Data;
+ UINT32 Argument;
+ UINT32 nIndex;
+ UINT8 PowerValue;
+ BOOLEAN EnableDDRMode;
+
+ ASSERT (CardData != NULL);
+ SdHostIo = CardData->SdHostIo;
+ EnableDDRMode = FALSE;
+
+ CardData->CardType = UnknownCard;
+ Status = GetCardType (CardData);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ DEBUG ((DEBUG_INFO, "CardData->CardType 0x%x\n", CardData->CardType));
+
+ ASSERT (CardData->CardType != UnknownCard);
+
+ //
+ // MMC, SD card need host auto stop command support
+ //
+ SdHostIo->EnableAutoStopCmd (SdHostIo, TRUE);
+
+ if (CardData->CardType == MMCCard) {
+ Status = MMCCardVoltageSelection (CardData);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+
+ //
+ // Get CID Register
+ //
+ Status = SendCommand (
+ CardData,
+ ALL_SEND_CID,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR2,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CIDRegister)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ALL_SEND_CID Fail Status = 0x%x\n", Status));
+ goto Exit;
+ } else {
+ //
+ // Dump out the Card ID data
+ //
+ DEBUG ((EFI_D_INFO, "Product Name: "));
+ for (nIndex=0; nIndex<6; nIndex++ ) {
+ DEBUG ((EFI_D_INFO, "%c", CardData->CIDRegister.PNM[nIndex]));
+ }
+ DEBUG ((EFI_D_INFO, "\nApplication ID : %d\n", CardData->CIDRegister.OID));
+ DEBUG ((EFI_D_INFO, "Manufacturer ID : %d\n", CardData->CIDRegister.MID));
+ DEBUG ((EFI_D_INFO, "Revision ID : %d\n", CardData->CIDRegister.PRV));
+ DEBUG ((EFI_D_INFO, "Serial Number : %d\n", CardData->CIDRegister.PSN));
+ }
+
+ //
+ // SET_RELATIVE_ADDR
+ //
+ if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {
+ //
+ // Hard code the RCA address
+ //
+ CardData->Address = 1;
+
+ //
+ // Set RCA Register
+ //
+ Status = SendCommand (
+ CardData,
+ SET_RELATIVE_ADDR,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ } else {
+ Data = 0;
+ Status = SendCommand (
+ CardData,
+ SET_RELATIVE_ADDR,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR6,
+ TIMEOUT_COMMAND,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ CardData->Address = (UINT16) (Data >> 16);
+ *(UINT32 *) &CardData->CardStatus = Data & 0x1FFF;
+ CardData->CardStatus.ERROR = (Data >> 13) & 0x1;
+ CardData->CardStatus.ILLEGAL_COMMAND = (Data >> 14) & 0x1;
+ CardData->CardStatus.COM_CRC_ERROR = (Data >> 15) & 0x1;
+ Status = CheckCardStatus (*(UINT32 *) &CardData->CardStatus);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ }
+
+ //
+ // Get CSD Register
+ //
+ Status = SendCommand (
+ CardData,
+ SEND_CSD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR2,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CSDRegister)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SEND_CSD Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ DEBUG ((EFI_D_INFO, "CardData->CSDRegister.SPEC_VERS = 0x%x\n", CardData->CSDRegister.SPEC_VERS));
+ DEBUG ((EFI_D_INFO, "CardData->CSDRegister.CSD_STRUCTURE = 0x%x\n", CardData->CSDRegister.CSD_STRUCTURE));
+
+ Status = CaculateCardParameter (CardData);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+
+ //
+ // It is platform and hardware specific, need hadrware engineer input
+ //
+ if (CardData->CSDRegister.DSR_IMP == 1) {
+ //
+ // Default is 0x404
+ //
+ Status = SendCommand (
+ CardData,
+ SET_DSR,
+ (DEFAULT_DSR_VALUE << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_DSR Fail Status = 0x%x\n", Status));
+ //
+ // Assume can operate even fail
+ //
+ }
+ }
+ //
+ // Change clock frequency from 400KHz to max supported when not in high speed mode
+ //
+ Status = SdHostIo->SetClockFrequency (SdHostIo, CardData->MaxFrequency);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n"));
+ goto Exit;
+ }
+
+ //
+ // Put the card into tran state
+ //
+ Status = SendCommand (
+ CardData,
+ SELECT_DESELECT_CARD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SELECT_DESELECT_CARD Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ gBS->Stall (5 * 1000);
+ //
+ // No need to do so
+ //
+ //
+ Status = SendCommand (
+ CardData,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SELECT_DESELECT_CARD SEND_STATUS Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {
+ //
+ // Only V4.0 and above supports more than 1 bits and high speed
+ //
+ if (CardData->CSDRegister.SPEC_VERS >= 4) {
+ //
+ // Get ExtCSDRegister
+ //
+ Status = SendCommand (
+ CardData,
+ SEND_EXT_CSD,
+ 0x0,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (EXT_CSD),
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SEND_EXT_CSD Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof(EXT_CSD));
+
+ //
+ // Recaculate the block number for >2G MMC card
+ //
+ Data = (CardData->ExtCSDRegister.SEC_COUNT[0]) |
+ (CardData->ExtCSDRegister.SEC_COUNT[1] << 8) |
+ (CardData->ExtCSDRegister.SEC_COUNT[2] << 16) |
+ (CardData->ExtCSDRegister.SEC_COUNT[3] << 24);
+
+ if (Data != 0) {
+ CardData->BlockNumber = Data;
+ }
+ DEBUG ((DEBUG_INFO, "CardData->BlockNumber %d\n", Data));
+ DEBUG ((EFI_D_ERROR, "CardData->ExtCSDRegister.CARD_TYPE -> %d\n", (UINTN)CardData->ExtCSDRegister.CARD_TYPE));
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2)||
+ (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) {
+
+ }
+ //
+ // Check current chipset capability and the plugged-in card
+ // whether supports HighSpeed
+ //
+ if (SdHostIo->HostCapability.HighSpeedSupport) {
+
+ //
+ // Change card timing to high speed interface timing
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = 1;
+ SwitchArgument.Index = (UINT32) ((UINTN)
+ (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN) (&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ CardData,
+ SWITCH,
+ *(UINT32 *) &SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDCardInit:SWITCH frequency Fail Status = 0x%x\n", Status));
+ }
+
+ gBS->Stall (5 * 1000);
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ CardData,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (EnableDDRMode) {
+ DEBUG ((EFI_D_ERROR, "Enable ddr mode on host controller\n"));
+ SdHostIo->SetDDRMode (SdHostIo, TRUE);
+ } else {
+ DEBUG ((EFI_D_ERROR, "Enable high speed mode on host controller\n"));
+ SdHostIo->SetHighSpeedMode (SdHostIo, TRUE);
+ }
+ //
+ // Change host clock to support high speed and enable chispet to
+ // support speed
+ //
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ Status = SdHostIo->SetClockFrequency (SdHostIo, FREQUENCY_MMC_PP_HIGH);
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ Status = SdHostIo->SetClockFrequency (SdHostIo, FREQUENCY_MMC_PP);
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n"));
+ goto Exit;
+ }
+ //
+ // It seems no need to stall after changing bus freqeuncy.
+ // It is said that the freqeuncy can be changed at any time. Just appends 8 clocks after command.
+ // But SetClock alreay has delay.
+ //
+ }
+ }
+
+ }
+
+ //
+ // Prefer wide bus width for performance
+ //
+ //
+ // Set to BusWidth bits mode, only version 4.0 or above support more than 1 bits
+ //
+ if (SdHostIo->HostCapability.BusWidth8 == TRUE) {
+ Status = MMCCardSetBusWidth (CardData, 8, EnableDDRMode);
+ if (EFI_ERROR (Status)) {
+ //
+ // CE-ATA may support 8 bits and 4 bits, but has no software method for detection
+ //
+ Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+ } else if (SdHostIo->HostCapability.BusWidth4 == TRUE) {
+ Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+
+ PowerValue = 0;
+
+ if (CardData->CurrentBusWidth == 8) {
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;
+ PowerValue = PowerValue >> 4;
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;
+ PowerValue = PowerValue >> 4;
+ }
+ } else if (CardData->CurrentBusWidth == 4) {
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;
+ PowerValue = PowerValue & 0xF;
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;
+ PowerValue = PowerValue & 0xF;
+ }
+ }
+
+ if (PowerValue != 0) {
+ //
+ // Update Power Class
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = PowerValue;
+ SwitchArgument.Index = (UINT32) ((UINTN)
+ (&(CardData->ExtCSDRegister.POWER_CLASS)) - (UINTN) (&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ CardData,
+ SWITCH,
+ *(UINT32 *) &SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ CardData,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SWITCH Power Class Fail Status = 0x%x\n", Status));
+ }
+ }
+ }
+
+ } else {
+ DEBUG ((EFI_D_ERROR, "MMC Card version %d only supportes 1 bits at lower transfer speed\n",CardData->CSDRegister.SPEC_VERS));
+ }
+ } else {
+ //
+ // Pin 1, at power up this line has a 50KOhm pull up enabled in the card.
+ // This pull-up should be disconnected by the user, during regular data transfer,
+ // with SET_CLR_CARD_DETECT (ACMD42) command
+ //
+ Status = SendAppCommand (
+ CardData,
+ SET_CLR_CARD_DETECT,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_CLR_CARD_DETECT Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ //
+ // Set Bus Width to 4
+ //
+ Status = SendAppCommand (
+ CardData,
+ SET_BUS_WIDTH,
+ SD_BUS_WIDTH_4,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_BUS_WIDTH 4 bits Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ Status = SdHostIo->SetBusWidth (SdHostIo, 4);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CardData->CurrentBusWidth = 4;
+
+ if ((SdHostIo->HostCapability.HighSpeedSupport == FALSE) ||
+ ((CardData->CSDRegister.CCC & BIT10) != BIT10)) {
+ //
+ // Host must support high speed
+ // Card must support Switch function
+ //
+ goto Exit;
+ }
+
+ //
+ // Mode = 0, group 1, function 1, check operation
+ //
+ Argument = 0xFFFF01;
+ ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));
+
+ Status = SendCommand (
+ CardData,
+ SWITCH_FUNC,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (SWITCH_STATUS),
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));
+
+ if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||
+ ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {
+ Argument = 0xFFFF01 | BIT31;
+ ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));
+
+ Status = SendCommand (
+ CardData,
+ SWITCH_FUNC,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (SWITCH_STATUS),
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));
+
+ if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||
+ ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {
+ gBS->Stall (1000);
+
+ //
+ // Change host clock
+ //
+ Status = SdHostIo->SetClockFrequency (SdHostIo, FREQUENCY_SD_PP_HIGH);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ }
+ }
+ }
+ if (!((CardData->ExtCSDRegister.CARD_TYPE & BIT2) ||
+ (CardData->ExtCSDRegister.CARD_TYPE & BIT3))) {
+
+ //
+ // Set Block Length, to improve compatibility in case of some cards
+ //
+ Status = SendCommand (
+ CardData,
+ SET_BLOCKLEN,
+ 512,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SET_BLOCKLEN Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ }
+ SdHostIo->SetBlockLength (SdHostIo, 512);
+
+Exit:
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c
new file mode 100644
index 0000000..ad0eb2c
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c
@@ -0,0 +1,324 @@
+/** @file
+ The definition for SD media device driver model and blkio protocol routines.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SdMediaDevice.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gSdMediaDeviceDriverBinding = {
+ SdMediaDeviceSupported,
+ SdMediaDeviceStart,
+ SdMediaDeviceStop,
+ 0x20,
+ NULL,
+ NULL
+};
+
+
+/**
+ Entry point for EFI drivers.
+
+ @param[in] ImageHandle EFI_HANDLE.
+ @param[in] SystemTable EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS Driver is successfully loaded.
+ @retval Others Failed.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSdMediaDevice (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSdMediaDeviceDriverBinding,
+ ImageHandle,
+ &gSdMediaDeviceName,
+ &gSdMediaDeviceName2
+ );
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has BlockIoProtocol installed will be supported.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SdMediaDeviceSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSdHostIoProtocolGuid,
+ (VOID **) &SdHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSdHostIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+Exit:
+ return Status;
+}
+
+
+/**
+ Starting the SD Media Device Driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+SdMediaDeviceStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ CARD_DATA *CardData;
+
+ CardData = NULL;
+
+ //
+ // Open PCI I/O Protocol and save pointer to open protocol
+ // in private data area.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSdHostIoProtocolGuid,
+ (VOID **) &SdHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to open gEfiSdHostIoProtocolGuid \r\n"));
+ goto Exit;
+ }
+
+ Status = SdHostIo->DetectCardAndInitHost (SdHostIo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "SdMediaDeviceStart: Fail to DetectCardAndInitHost \r\n"));
+ goto Exit;
+ }
+
+ CardData = (CARD_DATA *) AllocateZeroPool (sizeof (CARD_DATA));
+ if (CardData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to AllocateZeroPool(CARD_DATA) \r\n"));
+ goto Exit;
+ }
+
+ ASSERT (SdHostIo->HostCapability.BoundarySize >= 4 * 1024);
+ CardData->RawBufferPointer = (UINT8 *) ((UINTN) DMA_MEMORY_TOP);
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (2 * SdHostIo->HostCapability.BoundarySize),
+ (EFI_PHYSICAL_ADDRESS *) (&CardData->RawBufferPointer)
+ );
+
+ if (CardData->RawBufferPointer == NULL) {
+ DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to AllocateZeroPool(2*x) \r\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ CardData->AlignedBuffer = CardData->RawBufferPointer - ((UINTN) (CardData->RawBufferPointer) & (SdHostIo->HostCapability.BoundarySize - 1)) + SdHostIo->HostCapability.BoundarySize;
+
+ CardData->Signature = CARD_DATA_SIGNATURE;
+ CardData->SdHostIo = SdHostIo;
+
+ Status = MMCSDCardInit (CardData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to MMCSDCardInit \r\n"));
+ goto Exit;
+ }
+ DEBUG ((EFI_D_INFO, "SdMediaDeviceStart: MMCSDCardInit SuccessFul\n"));
+
+ if (CardData->CardType == CEATACard) {
+ Status = CEATABlockIoInit (CardData);
+ } else {
+ Status = MMCSDBlockIoInit (CardData);
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to BlockIoInit \r\n"));
+ goto Exit;
+ }
+ DEBUG ((EFI_D_INFO, "SdMediaDeviceStart: BlockIo is successfully installed\n"));
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiBlockIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &CardData->BlockIo
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to install gEfiBlockIoProtocolGuid \r\n"));
+ goto Exit;
+ }
+
+ //
+ // Install the component name protocol
+ //
+ CardData->ControllerNameTable = NULL;
+
+ AddUnicodeString2 (
+ "eng",
+ gSdMediaDeviceName.SupportedLanguages,
+ &CardData->ControllerNameTable,
+ L"MMC/SD Media Device",
+ TRUE
+ );
+
+ AddUnicodeString2 (
+ "en",
+ gSdMediaDeviceName2.SupportedLanguages,
+ &CardData->ControllerNameTable,
+ L"MMC/Sd Media Device",
+ FALSE
+ );
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "SdMediaDeviceStart: End with failure\r\n"));
+ if (CardData != NULL) {
+ if (CardData->RawBufferPointer != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * SdHostIo->HostCapability.BoundarySize));
+ }
+ FreePool (CardData);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to stop driver on.
+ @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param[in] ChildHandleBuffer List of handles for the children we need to stop.
+
+ @retval EFI_SUCCESS
+ @retval others
+
+**/
+EFI_STATUS
+EFIAPI
+SdMediaDeviceStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ //
+ // First find BlockIo Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CardData = CARD_DATA_FROM_THIS (BlockIo);
+
+ //
+ // Uninstall Block I/O protocol from the device handle
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ BlockIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CardData != NULL) {
+ if (CardData->RawBufferPointer != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * CardData->SdHostIo->HostCapability.BoundarySize));
+ }
+ FreeUnicodeStringTable (CardData->ControllerNameTable);
+ FreePool (CardData);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSdHostIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h
new file mode 100644
index 0000000..fe3c4fa
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h
@@ -0,0 +1,466 @@
+/** @file
+ The definition for SD media device driver model and blkio protocol routines.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ 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 _SD_MEDIA_DEVICE_H_
+#define _SD_MEDIA_DEVICE_H_
+
+#include <Uefi.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/BlockIo.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Pci22.h>
+#include "ComponentName.h"
+#include "SdHostIo.h"
+
+extern EFI_DRIVER_BINDING_PROTOCOL gSdMediaDeviceDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gSdMediaDeviceName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gSdMediaDeviceName2;
+
+//
+// Define the region of memory used for DMA memory
+//
+#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL
+#define CARD_DATA_SIGNATURE SIGNATURE_32 ('c', 'a', 'r', 'd')
+
+//
+// Command timeout will be max 100 ms
+//
+#define TIMEOUT_COMMAND 100
+#define TIMEOUT_DATA 5000
+
+typedef enum{
+ UnknownCard = 0,
+ MMCCard, // MMC card
+ MMCCardHighCap, // MMC Card High Capacity
+ CEATACard, // CE-ATA device
+ SdMemoryCard, // SD 1.1 card
+ SdMemoryCard2, // SD 2.0 or above standard card
+ SdMemoryCard2High // SD 2.0 or above high capacity card
+} CARD_TYPE;
+
+typedef struct {
+ //
+ // BlockIO
+ //
+ UINTN Signature;
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ EFI_BLOCK_IO_MEDIA BlockIoMedia;
+
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+ CARD_TYPE CardType;
+
+ UINT8 CurrentBusWidth;
+ BOOLEAN DualVoltage;
+ BOOLEAN NeedFlush;
+ UINT8 Reserved[3];
+
+ UINT16 Address;
+ UINT32 BlockLen;
+ UINT32 MaxFrequency;
+ UINT64 BlockNumber;
+
+ //
+ // Common used
+ //
+ CARD_STATUS CardStatus;
+ OCR OCRRegister;
+ CID CIDRegister;
+ CSD CSDRegister;
+ EXT_CSD ExtCSDRegister;
+ UINT8 *RawBufferPointer;
+ UINT8 *AlignedBuffer;
+
+ //
+ // CE-ATA specific
+ //
+ TASK_FILE TaskFile;
+ IDENTIFY_DEVICE_DATA IndentifyDeviceData;
+
+ //
+ //SD specific
+ //
+ SCR SCRRegister;
+ SD_STATUS_REG SdSattus;
+ SWITCH_STATUS SwitchStatus;
+} CARD_DATA;
+
+#define CARD_DATA_FROM_THIS(a) \
+ CR(a, CARD_DATA, BlockIo, CARD_DATA_SIGNATURE)
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has BlockIoProtocol installed will be supported.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SdMediaDeviceSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starting the SD Media Device Driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+SdMediaDeviceStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to stop driver on.
+ @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param[in] ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+SdMediaDeviceStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ MMC/SD card init function
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+MMCSDCardInit (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ Send command by using Host IO protocol
+
+ @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param[in] CommandIndex The command index to set the command index field of command register.
+ @param[in] Argument Command argument to set the argument field of command register.
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param[in] Buffer Contains the data read from / write to the device.
+ @param[in] BufferSize The size of the buffer.
+ @param[in] ResponseType RESPONSE_TYPE.
+ @param[in] TimeOut Time out value in 1 ms unit.
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+SendCommand (
+ IN CARD_DATA *CardData,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ );
+
+/**
+ Send the card APP_CMD command with the following command indicated by CommandIndex
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] CommandIndex The command index to set the command index field of command register.
+ @param[in] Argument Command argument to set the argument field of command register.
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param[in] Buffer Contains the data read from / write to the device.
+ @param[in] BufferSize The size of the buffer.
+ @param[in] ResponseType RESPONSE_TYPE.
+ @param[in] TimeOut Time out value in 1 ms unit.
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+SendAppCommand (
+ IN CARD_DATA *CardData,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ );
+
+/**
+ Send the card FAST_IO command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] RegisterAddress Register Address.
+ @param[in, out] RegisterData Pointer to register Data.
+ @param[in] Write TRUE for write, FALSE for read.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+FastIO (
+ IN CARD_DATA *CardData,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT8 *RegisterData,
+ IN BOOLEAN Write
+ );
+
+/**
+ Judge whether it is CE-ATA device or not.
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval TRUE
+ @retval FALSE
+
+**/
+BOOLEAN
+IsCEATADevice (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ Send software reset
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SoftwareReset (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ SendATACommand specificed in Taskfile
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] TaskFile Pointer to TASK_FILE.
+ @param[in] Write TRUE means write, FALSE means read.
+ @param[in] Buffer If NULL, means no data transfer, neither read nor write.
+ @param[in] SectorCount Buffer size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SendATACommand (
+ IN CARD_DATA *CardData,
+ IN TASK_FILE *TaskFile,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ );
+
+/**
+ IDENTIFY_DEVICE command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+IndentifyDevice (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ FLUSH_CACHE_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+FlushCache (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ STANDBY_IMMEDIATE command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+StandByImmediate (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ READ_DMA_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] LBA The starting logical block address to read from on the device.
+ @param[in] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param[in] SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ );
+
+/**
+ WRITE_DMA_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] LBA The starting logical block address to read from on the device.
+ @param[in] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param[in] SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+WriteDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ );
+
+/**
+ CEATA card BlockIo init function.
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+**/
+EFI_STATUS
+CEATABlockIoInit (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ MMC/SD card BlockIo init function.
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+**/
+EFI_STATUS
+MMCSDBlockIoInit (
+ IN CARD_DATA *CardData
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf
new file mode 100644
index 0000000..e352b1d
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf
@@ -0,0 +1,64 @@
+## @file
+# Component Description File For SdMediaDeviceDxe Module.
+#
+# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# 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 = 0x00010005
+ BASE_NAME = SdMediaDevice
+ FILE_GUID = E076205A-6EDC-4F68-A535-93C5D790B1DA
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSdMediaDevice
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gSdMediaDeviceDriverBinding
+# COMPONENT_NAME = gSdMediaDeviceName
+# COMPONENT_NAME2 = gSdMediaDeviceName2
+#
+
+[Sources]
+ SdMediaDevice.c
+ SdMediaDevice.h
+ MMCSDTransfer.c
+ CEATA.c
+ CEATABlockIo.c
+ MMCSDBlockIo.c
+ ComponentName.c
+ ComponentName.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiSdHostIoProtocolGuid ## TO_START
+ gEfiBlockIoProtocolGuid ## BY_START
+
+[Pcd.common]
--
2.7.0.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Reviewed-by: zwei4 <david.wei@intel.com> Thanks, David Wei -----Original Message----- From: Lu, ShifeiX A Sent: Friday, June 09, 2017 1:26 PM To: edk2-devel@lists.01.org Cc: Wei, David <david.wei@intel.com> Subject: [Patch][edk2-platforms/devel-MinnowBoard3-UDK2017] Add eMMC/SD. Add Platform eMMC/SD driver. This reverts commit 66d48af2d24645263b8068e261abc58d84cc2b93. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: lushifex <shifeix.a.lu@intel.com> --- .../BroxtonPlatformPkg/PlatformDsc/Components.dsc | 11 +- Platform/BroxtonPlatformPkg/PlatformPkg.fdf | 10 +- .../Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c | 162 ++ .../Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c | 1529 ++++++++++++ .../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c | 613 +++++ .../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h | 585 +++++ .../Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf | 59 + .../Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c | 159 ++ .../Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c | 666 ++++++ .../Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c | 2524 ++++++++++++++++++++ .../Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c | 605 +++++ .../MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf | 71 + .../Sdio/Dxe/SD/SdControllerDxe/ComponentName.c | 233 ++ .../Sdio/Dxe/SD/SdControllerDxe/ComponentName.h | 145 ++ .../Sdio/Dxe/SD/SdControllerDxe/SdController.c | 1804 ++++++++++++++ .../Sdio/Dxe/SD/SdControllerDxe/SdController.h | 314 +++ .../Dxe/SD/SdControllerDxe/SdControllerDxe.inf | 59 + .../Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c | 638 +++++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c | 384 +++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c | 219 ++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h | 145 ++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c | 547 +++++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c | 1661 +++++++++++++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c | 324 +++ .../Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h | 466 ++++ .../Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf | 64 + 26 files changed, 13989 insertions(+), 8 deletions(-) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf diff --git a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc b/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc index 7efcdb4..1322576 100644 --- a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc +++ b/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc @@ -386,11 +386,14 @@ $(PLATFORM_PACKAGE_COMMON)/Console/LpssUartSerialDxe/LpssUartSerialDxe.inf # - # eMMC/SD Card + # SDIO # - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf - MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf - MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf + $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf + + $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf + + $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf + $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf !if $(ACPI50_ENABLE) == TRUE diff --git a/Platform/BroxtonPlatformPkg/PlatformPkg.fdf b/Platform/BroxtonPlatformPkg/PlatformPkg.fdf index 73174af..ac09ac3 100644 --- a/Platform/BroxtonPlatformPkg/PlatformPkg.fdf +++ b/Platform/BroxtonPlatformPkg/PlatformPkg.fdf @@ -434,14 +434,16 @@ APRIORI DXE { INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf # - # eMMC/SD Card + # SDIO # !if $(EMMC_DRIVER_ENABLE) == TRUE - INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf - INF MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf - INF MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf + INF $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf + INF $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf !endif + INF $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf + INF $(PLATFORM_SI_PACKAGE)/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf + INF MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf INF IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c new file mode 100644 index 0000000..f099fa8 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/ComponentName.c @@ -0,0 +1,162 @@ +/** @file + Component Name protocol implementation + + Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "MmcHostDriver.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gMmcHostComponentName = { + MmcHostComponentNameGetDriverName, + MmcHostComponentNameGetControllerName, + "eng" +}; + + +static EFI_UNICODE_STRING_TABLE mMmcHostDriverNameTable[] = { + { "eng", L"UEFI MMC Host Controller Driver" }, + { NULL , NULL } +}; + + +/** + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param[out] DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language 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 +MmcHostComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString ( + Language, + gMmcHostComponentName.SupportedLanguages, + mMmcHostDriverNameTable, + DriverName + ); +} + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device 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 name of a child controller. + @param[in] Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param[out] ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + + @retval EFI_SUCCESS The Unicode string for the user readable name in the + language specified by Language for 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 +MmcHostComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + MMCHOST_DATA *MmcHostData; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiMmcHostIoProtocolGuid, + (VOID **) &MmcHostIo, + gMmcHostDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + MmcHostData = MMCHOST_DATA_FROM_THIS (MmcHostIo); + + return LookupUnicodeString ( + Language, + gMmcHostComponentName.SupportedLanguages, + MmcHostData->ControllerNameTable, + ControllerName + ); +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c new file mode 100644 index 0000000..f3cd50e --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostController.c @@ -0,0 +1,1529 @@ +/** @file + MMC Host I/O protocol implementation + + Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "MmcHostDriver.h" + +#define MMC_HOST_DEBUG(a) do { \ + if (MmcHostData->EnableVerboseDebug) { \ + DEBUG (a); \ + } \ + } while (0); + +UINT32 gMmcHostDebugLevel = DEBUG_INFO; + +/** + Get Error Reason + + @param[in] CommandIndex The command index to set the command index field of command register + @param[in] ErrorCode Mmchost specific error code + + @retval EFI_DEVICE_ERROR + @retval EFI_TIMEOUT + @retval EFI_CRC_ERROR + +**/ +STATIC +EFI_STATUS +GetErrorReason ( + IN UINT16 CommandIndex, + IN UINT16 ErrorCode + ) +{ + EFI_STATUS Status; + + Status = EFI_DEVICE_ERROR; + DEBUG ((gMmcHostDebugLevel, "[%2d] -- ", CommandIndex)); + + if (ErrorCode & BIT0) { + Status = EFI_TIMEOUT; + DEBUG ((gMmcHostDebugLevel, "Command Timeout Error")); + } + + if (ErrorCode & BIT1) { + Status = EFI_CRC_ERROR; + DEBUG ((gMmcHostDebugLevel, "Command CRC Error")); + } + + if (ErrorCode & BIT2) { + DEBUG ((gMmcHostDebugLevel, "Command End Bit Error")); + } + + if (ErrorCode & BIT3) { + DEBUG ((gMmcHostDebugLevel, "Command Index Error")); + } + if (ErrorCode & BIT4) { + Status = EFI_TIMEOUT; + DEBUG ((gMmcHostDebugLevel, "Data Timeout Error")); + } + + if (ErrorCode & BIT5) { + Status = EFI_CRC_ERROR; + DEBUG ((gMmcHostDebugLevel, "Data CRC Error")); + } + + if (ErrorCode & BIT6) { + DEBUG ((gMmcHostDebugLevel, "Data End Bit Error")); + } + + if (ErrorCode & BIT7) { + DEBUG ((gMmcHostDebugLevel, "Current Limit Error")); + } + + if (ErrorCode & BIT8) { + DEBUG ((gMmcHostDebugLevel, "Auto CMD12 Error")); + } + + if (ErrorCode & BIT9) { + DEBUG ((gMmcHostDebugLevel, "ADMA Error")); + } + + DEBUG ((gMmcHostDebugLevel, "\n")); + + return Status; +} + + +/** + Read MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Width Signifies the width of the memory or I/O operations. + @param[in] Offset Offset of the MMC Card + @param[in, out] Buffer Buffer read from MMC Card + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +MmcHostRead ( + IN MMCHOST_DATA *MmcHost, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Offset, + IN OUT VOID *Buffer + ) +{ + return MmcHost->PciIo->Mem.Read ( + MmcHost->PciIo, + Width, + 0, + (UINT64) Offset, + 1, + Buffer + ); +} + + +/** + Read MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the MMC Card + + @retval Data Data read from MMC Card + +**/ +UINT8 +MmcHostRead8 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset + ) +{ + UINT8 Data; + + MmcHostRead (MmcHost, EfiPciIoWidthUint8, Offset, &Data); + + return Data; +} + + +/** + Read MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the MMC Card + + @retval Data Data read from MMC Card + +**/ +UINT16 +MmcHostRead16 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset + ) +{ + UINT16 Data; + + MmcHostRead (MmcHost, EfiPciIoWidthUint16, Offset, &Data); + + return Data; +} + + +/** + Read MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the MMC Card + + @retval Data Data read from MMC Card + +**/ +UINT32 +MmcHostRead32 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset + ) +{ + UINT32 Data; + + MmcHostRead (MmcHost, EfiPciIoWidthUint32, Offset, &Data); + + return Data; +} + + +/** + Dump MMC host registers + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + + @retval None + +**/ +VOID +DebugPrintMmcHostRegisters ( + IN MMCHOST_DATA *MmcHost + ) +{ +#ifdef VERBOSE_REGISTER_ACCESS_DEBUG + UINTN Loop; + + if (!MmcHost->EnableVerboseDebug) { + return; + } + + for (Loop = 0; Loop < 0x40; Loop++) { + DEBUG ((EFI_D_INFO, " %02x", MmcHostRead8 (MmcHost, Loop))); + if ((Loop % 0x10) == 0xf) { + DEBUG ((EFI_D_INFO, "\n")); + } + } + +#endif +} + + +/** + Dump MMC host registers before write + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + + @retval None + +**/ +VOID +DebugPreMmcHostWrite ( + IN MMCHOST_DATA *MmcHost + ) +{ +#ifdef VERBOSE_REGISTER_ACCESS_DEBUG + STATIC UINTN DebugCount = 0; + + if (!MmcHost->EnableVerboseDebug) { + return; + } + + DebugCount++; + + if (DebugCount < 0x100) { + DEBUG ((EFI_D_INFO, "MMC HOST Registers before write:\n")); + DebugPrintMmcHostRegisters (MmcHost); + } +#endif +} + + +/** + Dump MMC host registers after write + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + + @retval None + +**/ +VOID +DebugPostMmcHostWrite ( + IN MMCHOST_DATA *MmcHost + ) +{ +#ifdef VERBOSE_REGISTER_ACCESS_DEBUG + STATIC UINTN DebugCount = 0; + + if (!MmcHost->EnableVerboseDebug) { + return; + } + + DebugCount++; + + if (DebugCount < 0x10) { + DEBUG ((EFI_D_INFO, "MMC HOST Registers after write:\n")); + DebugPrintMmcHostRegisters (MmcHost); + } +#endif +} + + +/** + Write MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Width Signifies the width of the memory or I/O operations. + @param[in] Offset Offset of the MMC Card + @param[in, out] Buffer Buffer read from MMC Card + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +MmcHostWrite ( + IN MMCHOST_DATA *MmcHost, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Offset, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + + DebugPreMmcHostWrite (MmcHost); + Status = MmcHost->PciIo->Mem.Write ( + MmcHost->PciIo, + Width, + 0, + (UINT64) Offset, + 1, + Buffer + ); + + DebugPostMmcHostWrite (MmcHost); + + return Status; +} + + +/** + Write MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the MMC Card + @param[in] Data Data write to MMC Card + + @retval Data Written to MmcHost + +**/ +UINT8 +MmcHostWrite8 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset, + IN UINT8 Data + ) +{ + MmcHostWrite (MmcHost, EfiPciIoWidthUint8, Offset, &Data); + + return Data; +} + + +/** + Write MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the MMC Card + @param[in] Data Data write to MMC Card + + @retval Data Data written to MMC Card + +**/ +UINT16 +MmcHostWrite16 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset, + IN UINT16 Data + ) +{ + MmcHostWrite (MmcHost, EfiPciIoWidthUint16, Offset, &Data); + + return Data; +} + + +/** + Write MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the MMC Card + @param[in] Data Data write to MMC Card + + @retval Data Data written to MMC Card + +**/ +UINT32 +MmcHostWrite32 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset, + IN UINT32 Data + ) +{ + MmcHostWrite (MmcHost, EfiPciIoWidthUint32, Offset, &Data); + + return Data; +} + + +/** + Check Controller Version + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + + @retval Data Written to MmcHost + +**/ +UINT32 +CheckControllerVersion ( + IN MMCHOST_DATA *MmcHost + ) +{ + UINT16 Data16; + + Data16 = MmcHostRead16 (MmcHost, MMIO_CTRLRVER); + DEBUG ((EFI_D_INFO, "CheckControllerVersion: %x \n", Data16 & 0xFF)); + + return (Data16 & 0xFF); +} + + +/** + Power on/off the LED associated with the slot + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Enable TRUE to set LED on, FALSE to set LED off + + @retval EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +HostLEDEnable ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ) +{ + MMCHOST_DATA *MmcHostData; + UINT8 Data; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + Data = MmcHostRead8 (MmcHostData, MMIO_HOSTCTL); + + if (Enable) { + // + //LED On + // + Data |= BIT0; + } else { + // + //LED Off + // + Data &= ~BIT0; + } + + MmcHostWrite8 (MmcHostData, MMIO_HOSTCTL, Data); + + return EFI_SUCCESS; +} + + +/** + The main function used to send the command to the card inserted into the MMC host + slot. + It will assemble the arguments to set the command register and wait for the command + and transfer completed until timeout. Then it will read the response register to fill + the ResponseData + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] CommandIndex The command index to set the command index field of command register + @param[in] Argument Command argument to set the argument field of command register + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out + @param[in] Buffer Contains the data read from / write to the device + @param[in] BufferSize The size of the buffer + @param[in] ResponseType RESPONSE_TYPE + @param[in] TimeOut Time out value in 1 ms unit + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SendCommand ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData OPTIONAL + ) +{ + EFI_STATUS Status; + MMCHOST_DATA *MmcHostData; + UINT32 ResponseDataCount; + UINT16 Data16; + UINT32 Data32; + UINT64 Data64; + UINT8 Index; + BOOLEAN CommandCompleted; + INT32 Timeout = 1000; + + Status = EFI_SUCCESS; + ResponseDataCount = 1; + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + if (Buffer != NULL && DataType == NoData) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((gMmcHostDebugLevel, "SendCommand: Invalid parameter -> \n")); + goto Exit; + } + + if (((UINTN) Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN) NULL) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((gMmcHostDebugLevel, "SendCommand: Invalid parameter -> \n")); + goto Exit; + } + + DEBUG ((DEBUG_INFO, "SendCommand: CMD%d \n", CommandIndex)); + if (MmcHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C))); + } + + // + // Check CMD INHIBIT and DATA INHIBIT before send command + // + do { + Data32 = MmcHostRead32 (MmcHostData, MMIO_PSTATE); + if (MmcHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "Wait CMD INHIBIT %x\n",Data32 )); + } + } while (Timeout-- > 0 && Data32 & BIT0); + + Timeout = 1000; + do { + Data32 = MmcHostRead32 (MmcHostData, MMIO_PSTATE); + if (MmcHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "Wait DATA INHIBIT %x\n",Data32 )); + } + } while (Timeout-- >0 && Data32 & BIT1); + + // + //Clear status bits + // + MMC_HOST_DEBUG ((EFI_D_INFO, "NINTSTS(0x30) <- 0x%x\n", (UINTN) 0xffff)); + MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, 0xffff); + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS (0x30): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_NINTSTS))); + + MMC_HOST_DEBUG ((EFI_D_INFO, "ERINTSTS <- 0x%x\n", (UINTN) 0xffff)); + MmcHostWrite16 (MmcHostData, MMIO_ERINTSTS, 0xffff); + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: ERINTSTS (0x32): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_ERINTSTS))); + + Data16 = MmcHostRead16 (MmcHostData, MMIO_NINTEN); + MmcHostWrite16 (MmcHostData, MMIO_NINTEN, (Data16 | BIT3)); + MMC_HOST_DEBUG ((DEBUG_INFO, "SendCommand: NINTEN (0x34) <- 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_NINTEN))); + MMC_HOST_DEBUG ((DEBUG_INFO, "SendCommand: DMAADR (0x00) <- 0x%x\n", (UINTN) Buffer)); + MmcHostWrite32 (MmcHostData, MMIO_DMAADR, (UINT32) (UINTN) Buffer); + + if (Buffer != NULL) { + Data16 = MmcHostRead16 (MmcHostData, MMIO_BLKSZ); + Data16 &= ~(0xFFF); + if (BufferSize <= MmcHostData->BlockLength) { + Data16 |= BufferSize; + } else { + Data16 |= MmcHostData->BlockLength; + } + Data16 |= 0x7000; // Set to 512KB for SDMA block size + } else { + Data16 = 0; + } + + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: BLKSZ(0x04) <- 0x%x\n", Data16)); + MmcHostWrite16 (MmcHostData, MMIO_BLKSZ, Data16); + + if (Buffer != NULL) { + if (BufferSize <= MmcHostData->BlockLength) { + Data16 = 1; + } else { + Data16 = (UINT16) (BufferSize / MmcHostData->BlockLength); + } + } else { + Data16 = 0; + } + + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: BLKCNT(0x06) <- 0x%x\n", Data16)); + MmcHostWrite16 (MmcHostData, MMIO_BLKCNT, Data16); + + // + // Argument + // + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: CMDARG (0x08) <- 0x%x\n", Argument)); + MmcHostWrite32 (MmcHostData, MMIO_CMDARG, Argument); + + // + // Transfer Mode + // + Data16 = MmcHostRead16 (MmcHostData, MMIO_XFRMODE); + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: XFRMODE (0x0C) mode read 0x%x\n", Data16)); + + // + // BIT0 DMA Enable + // BIT2 Auto Cmd12 + // + if (DataType == InData) { + Data16 |= BIT4 | BIT0; + } else if (DataType == OutData) { + Data16 &= ~BIT4; + Data16 |= BIT0; + } else { + Data16 &= ~(BIT4 | BIT0); + } + + if (BufferSize <= MmcHostData->BlockLength) { + Data16 &= ~ (BIT5 | BIT1 | BIT2); + } else { + if (MmcHostData->IsAutoStopCmd && !MmcHostData->IsEmmc) { + Data16 |= (BIT5 | BIT1 | BIT2); + } else { + Data16 |= (BIT5 | BIT1); + } + } + if (CommandIndex == SEND_EXT_CSD) { + Data16 |= BIT1; + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand:Enable bit 1, XFRMODE <- 0x%x\n", Data16)); + } + + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: XFRMODE (0x0C) <- 0x%x\n", Data16)); + MmcHostWrite16 (MmcHostData, MMIO_XFRMODE, Data16); + + switch (ResponseType) { + case ResponseNo: + Data16 = (CommandIndex << 8); + ResponseDataCount = 0; + break; + + case ResponseR1: + case ResponseR5: + case ResponseR6: + case ResponseR7: + Data16 = (CommandIndex << 8) | BIT1 | BIT4| BIT3; + ResponseDataCount = 1; + break; + + case ResponseR1b: + case ResponseR5b: + Data16 = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3; + ResponseDataCount = 1; + break; + + case ResponseR2: + Data16 = (CommandIndex << 8) | BIT0 | BIT3; + ResponseDataCount = 4; + break; + + case ResponseR3: + case ResponseR4: + Data16 = (CommandIndex << 8) | BIT1; + ResponseDataCount = 1; + break; + + default: + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + if (DataType != NoData) { + Data16 |= BIT5; + } + + HostLEDEnable (This, TRUE); + + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: SDCMD(0x0E) <- 0x%x\n", Data16)); + CommandCompleted = FALSE; + MmcHostWrite16 (MmcHostData, MMIO_SDCMD, Data16); + + if (MmcHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "After write to Command\n")); + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C))); + } + + TimeOut *= 1000; //ms to us conversion + do { + Data16 = MmcHostRead16 (MmcHostData, MMIO_ERINTSTS); + if (MmcHostData->EnableVerboseDebug && (Data16 != 0)) { + DEBUG ((EFI_D_INFO, "SendCommand: ERINTSTS (0x32): 0x%x\n", Data16)); + DEBUG ((EFI_D_INFO, "SendCommand: ERINTEN (0x36): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_ERINTEN))); + DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS (0x30): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_NINTSTS))); + DEBUG ((EFI_D_INFO, "SendCommand: NINTEN (0x34): 0x%x\n", MmcHostRead16 (MmcHostData, MMIO_NINTEN))); + } + + if ((Data16 & 0x17FF) != 0) { + Status = GetErrorReason (CommandIndex, Data16); + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C))); + goto Exit; + } + + Data16 = MmcHostRead16 (MmcHostData, MMIO_NINTSTS) & 0x1ff; + if (MmcHostData->EnableVerboseDebug && (Data16 > 1)) { + DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS (0x30): 0x%x\n", Data16)); + } + + if ((Data16 & BIT0) == BIT0) { + // + // Command completed + // + CommandCompleted = TRUE; + + MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, BIT0); + + if ((DataType == NoData) && (ResponseType != ResponseR1b)) { + break; + } + } + + if (CommandCompleted) { + // + // DMA interrupted + // + if ((Data16 & BIT3) == BIT3) { + MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, BIT3); + Data32 = MmcHostRead32 (MmcHostData, MMIO_DMAADR); + MMC_HOST_DEBUG ((DEBUG_INFO, "SendCommand: DMAADR (0x00) <- 0x%x\n", Data32)); + MmcHostWrite32 (MmcHostData, MMIO_DMAADR, Data32); + } + + // + // Transfer completed + // + if ((Data16 & BIT1) == BIT1) { + MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, BIT1); + break; + } + } + + gBS->Stall (1); + TimeOut --; + + } while (TimeOut > 0); + + if (TimeOut == 0) { + Status = EFI_TIMEOUT; + DEBUG ((gMmcHostDebugLevel, "SendCommand: Time out \n")); + goto Exit; + } + + if (ResponseData != NULL) { + UINT32 *ResDataPtr = NULL; + + ResDataPtr = ResponseData; + for (Index = 0; Index < ResponseDataCount; Index++) { + *ResDataPtr = MmcHostRead32 (MmcHostData, MMIO_RESP + Index * 4); + ResDataPtr++; + } + MMC_HOST_DEBUG ((EFI_D_INFO, "Reponse Data 0: RESPONSE (0x10) <- 0x%x\n", *ResponseData)); + + if (ResponseType == ResponseR2) { + // + // Adjustment for R2 response + // + Data32 = 1; + for (Index = 0; Index < ResponseDataCount; Index++) { + Data64 = LShiftU64 (*ResponseData, 8); + *ResponseData = (UINT32) ((Data64 & 0xFFFFFFFF) | Data32); + Data32 = (UINT32) RShiftU64 (Data64, 32); + ResponseData++; + } + } + } + + if (MmcHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "Before Exit Send Command\n")); + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C))); + } + +Exit: + HostLEDEnable (This, FALSE); + MMC_HOST_DEBUG ((EFI_D_INFO, "SendCommand: Status -> %r\n", Status)); + + return Status; +} + + +/** + Set clock frequency of the host, the actual frequency + may not be the same as MaxFrequencyInKHz. It depends on + the max frequency the host can support, divider, and host + speed mode. + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] MaxFrequency Max frequency in HZ + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetClockFrequency ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 MaxFrequency + ) +{ + UINT16 Data16; + UINT32 Frequency; + UINT32 Divider = 0; + MMCHOST_DATA *MmcHostData; + UINT32 TimeOutCount; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: BaseClockInMHz = %d \n", MmcHostData->BaseClockInMHz)); + + Frequency = (MmcHostData->BaseClockInMHz * 1000 * 1000) / MaxFrequency; + DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: FrequencyInHz = %d \n", Frequency)); + + if ((MmcHostData->BaseClockInMHz * 1000 * 1000 % MaxFrequency) != 0) { + Frequency += 1; + } + + Divider = 1; + while (Frequency > Divider) { + Divider = Divider * 2; + } + + if (Divider >= 0x400) { + Divider = 0x200; + } + DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: before shift: Base Clock Divider = 0x%x \n", Divider)); + Divider = Divider >> 1; + DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: before shift: Base Clock Divider = 0x%x \n", Divider)); + + MmcHostData->CurrentClockInKHz = (MmcHostData->BaseClockInMHz * 1000); + if (Divider != 0) { + MmcHostData->CurrentClockInKHz = MmcHostData->CurrentClockInKHz / (Divider * 2); + } + + if (2 == CheckControllerVersion (MmcHostData)) { + Data16 = (UINT16) ((Divider & 0xFF) << 8 | (((Divider & 0xFF00) >>8)<<6)); + } else { + Data16 = (UINT16) ( Divider << 8); + } + + DEBUG ((gMmcHostDebugLevel, + "SetClockFrequency: base=%dMHz, clkctl=0x%04x, f=%dKHz\n", + MmcHostData->BaseClockInMHz, + Data16, + MmcHostData->CurrentClockInKHz + )); + DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: set MMIO_CLKCTL value = 0x%x \n", Data16)); + MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, Data16); + + gBS->Stall (10); + Data16 |= BIT0; + MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, Data16); + + TimeOutCount = TIME_OUT_1S; + do { + Data16 = MmcHostRead16 (MmcHostData, MMIO_CLKCTL); + gBS->Stall (10); + TimeOutCount --; + if (TimeOutCount == 0) { + DEBUG ((gMmcHostDebugLevel, "SetClockFrequency: Timeout\n")); + return EFI_TIMEOUT; + } + } while ((Data16 & BIT1) != BIT1); + + gBS->Stall (10); + Data16 |= BIT2; + MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, Data16); + + return EFI_SUCCESS; +} + + +/** + Set bus width of the host + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] BusWidth Bus width in 1, 4, 8 bits + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetBusWidth ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 BusWidth + ) +{ + MMCHOST_DATA *MmcHostData; + UINT8 Data; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) { + DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Invalid parameter \n")); + return EFI_INVALID_PARAMETER; + } + + if ((MmcHostData->MmcHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) { + DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Invalid parameter \r\n")); + return EFI_INVALID_PARAMETER; + } + Data = MmcHostRead8 (MmcHostData, MMIO_HOSTCTL); + + if (BusWidth == 8) { + DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Bus Width is 8-bit ... \r\n")); + Data |= BIT5; + } else if (BusWidth == 4) { + DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Bus Width is 4-bit ... \r\n")); + Data &= ~BIT5; + Data |= BIT1; + } else { + DEBUG ((gMmcHostDebugLevel, "SetBusWidth: Bus Width is 1-bit ... \r\n")); + Data &= ~BIT5; + Data &= ~BIT1; + } + MmcHostWrite8 (MmcHostData, MMIO_HOSTCTL, Data); + DEBUG ((gMmcHostDebugLevel, "SetBusWidth: MMIO_HOSTCTL value: 0x%x \n", MmcHostRead8 (MmcHostData, MMIO_HOSTCTL))); + + return EFI_SUCCESS; +} + + +/** + Set voltage which could supported by the host. + Support 0(Power off the host), 1.8V, 3.0V, 3.3V + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Voltage Units in 0.1 V + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetHostVoltage ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 Voltage + ) +{ + MMCHOST_DATA *MmcHostData; + UINT8 Data; + EFI_STATUS Status; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + Status = EFI_SUCCESS; + + Data = MmcHostRead8 (MmcHostData, MMIO_PWRCTL); + + if (Voltage == 0) { + // + //Power Off the host + // + Data &= ~BIT0; + } else if (Voltage <= 18 && This->HostCapability.V18Support) { + // + //1.8V + // + Data |= (BIT1 | BIT3 | BIT0); + } else if (Voltage > 18 && Voltage <= 30 && This->HostCapability.V30Support) { + // + //3.0V + // + Data |= (BIT2 | BIT3 | BIT0); + } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) { + // + //3.3V + // + Data |= (BIT1 | BIT2 | BIT3 | BIT0); + } else { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + MmcHostWrite8 (MmcHostData, MMIO_PWRCTL, Data); + gBS->Stall (10); + +Exit: + return Status; +} + + +/** + Set Host High Speed + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] HighSpeed True for High Speed Mode set, false for normal mode + + @retval EFI_INVALID_PARAMETER + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetHostSpeedMode( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 HighSpeed + ) +{ + EFI_STATUS Status; + MMCHOST_DATA *MmcHostData; + UINT8 Data8; + + Status = EFI_SUCCESS; + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + if (MmcHostData->IsEmmc) { + Data8 = MmcHostRead8 (MmcHostData, MMIO_HOSTCTL); + Data8 &= ~(BIT2); + if (HighSpeed) { + Data8 |= BIT2; + DEBUG ((gMmcHostDebugLevel, "High Speed mode: Data8=0x%x \n", Data8)); + } else { + DEBUG ((gMmcHostDebugLevel, "Normal Speed mode: Data8=0x%x \n", Data8)); + } + MmcHostWrite8 (MmcHostData, MMIO_HOSTCTL, Data8); + gBS->Stall (10); + DEBUG ((gMmcHostDebugLevel, "MMIO_HOSTCTL value: 0x%x \n", MmcHostRead8 (MmcHostData, MMIO_HOSTCTL))); + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + + +/** + Set Host mode in DDR + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] SetHostDdrMode True for DDR Mode set, false returns EFI_SUCCESS + + @retval EFI_INVALID_PARAMETER + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetHostDdrMode( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 DdrMode + ) +{ + EFI_STATUS Status; + MMCHOST_DATA *MmcHostData; + UINT16 ModeSet; + + Status = EFI_SUCCESS; + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + if (MmcHostData->IsEmmc) { + ModeSet = MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2); + ModeSet &= ~(BIT0 | BIT1 | BIT2); + if (DdrMode) { + ModeSet |= 0x0004; + ModeSet |= BIT3; //1.8v + DEBUG ((gMmcHostDebugLevel, "DDR mode: Data16=0x%x \n", ModeSet)); + } else { + if (CheckControllerVersion (MmcHostData) != 2) { + ModeSet = 0x0; + } + } + + MmcHostWrite16 (MmcHostData, MMIO_HOST_CTL2, ModeSet); + gBS->Stall (10); + DEBUG ((gMmcHostDebugLevel, "MMIO_HOST_CTL2 value: 0x%x \n", MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2))); + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + + +/** + Set Host SDR Mode + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] DdrMode True for SDR Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. + +**/ +EFI_STATUS +EFIAPI +SetHostSdrMode( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 SdrMode + ) +{ + MMCHOST_DATA *MmcHostData; + UINT16 ModeSet; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + if (MmcHostData->IsEmmc) { + ModeSet = MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2); + ModeSet &= ~(BIT0 | BIT1 | BIT2); + if (SdrMode) { + if (MmcHostData->MmcHostIo.HostCapability.SDR104Support) { + ModeSet |= 3; + } else if (MmcHostData->MmcHostIo.HostCapability.SDR50Support) { + ModeSet |= 2; + } + ModeSet |= 1; + DEBUG ((gMmcHostDebugLevel, "SDR mode: Data16=0x%x \n", ModeSet)); + } else { + if (CheckControllerVersion (MmcHostData) != 2) { + ModeSet = 0x0; + } + } + + MmcHostWrite16 (MmcHostData, MMIO_HOST_CTL2, ModeSet); + gBS->Stall (10); + DEBUG ((gMmcHostDebugLevel, "MMIO_HOST_CTL2 value: 0x%x \n", MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2))); + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + + +/** + Reset the host + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] ResetType Reset data/cmd all + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. + +**/ +EFI_STATUS +EFIAPI +ResetMmcHost ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN RESET_TYPE ResetType + ) +{ + MMCHOST_DATA *MmcHostData; + UINT8 Data8; + UINT32 Data; + UINT16 ErrStatus; + UINT8 Mask; + UINT32 TimeOutCount; + UINT16 SaveClkCtl; + UINT16 SavePwrCtl = 0; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + MmcHostData->IsEmmc = TRUE; + Mask = 0; + ErrStatus = 0; + + if (ResetType == Reset_Auto) { + ErrStatus = MmcHostRead16 (MmcHostData, MMIO_ERINTSTS); + if ((ErrStatus & 0xF) != 0) { + // + //Command Line + // + Mask |= BIT1; + } + if ((ErrStatus & 0x70) != 0) { + // + //Data Line + // + Mask |= BIT2; + } + } + + if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) { + Mask |= BIT2; + } + if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) { + Mask |= BIT1; + } + if (ResetType == Reset_All) { + Mask = BIT0; + } + if (ResetType == Reset_HW) { + SavePwrCtl = MmcHostRead16 (MmcHostData, MMIO_PWRCTL); + DEBUG ((gMmcHostDebugLevel, "Write SavePwrCtl: %x \n", (SavePwrCtl | BIT4))); + + MmcHostWrite16 (MmcHostData, MMIO_PWRCTL, SavePwrCtl | BIT4); + gBS->Stall (10); + DEBUG ((gMmcHostDebugLevel, "Write SavePwrCtl: %x \n", (SavePwrCtl &(~BIT4)))); + MmcHostWrite16 (MmcHostData, MMIO_PWRCTL, SavePwrCtl &(~BIT4)); + gBS->Stall (10); + } + + if (Mask == 0) { + return EFI_SUCCESS; + } + + SaveClkCtl = MmcHostRead16 (MmcHostData, MMIO_CLKCTL); + + MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, 0); + + gBS->Stall (10); + + // + // Reset the MMC host controller + // + MmcHostWrite8 (MmcHostData, MMIO_SWRST, Mask); + + Data = 0; + TimeOutCount = TIME_OUT_1S; + do { + gBS->Stall (10); + TimeOutCount --; + + Data8 = MmcHostRead8 (MmcHostData, MMIO_SWRST); + if ((Data8 & Mask) == 0) { + break; + } + } while (TimeOutCount > 0); + + // + // We now restore the MMIO_CLKCTL register which we set to 0 above. + // + MmcHostWrite16 (MmcHostData, MMIO_CLKCTL, SaveClkCtl); + + if (TimeOutCount == 0) { + DEBUG ((gMmcHostDebugLevel, "ResetMMCHost: Time out \n")); + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + + +/** + Enable AutoStop Cmd + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Enable TRUE to enable + + @retval EFI_SUCCESS The function completed successfully + +**/ +EFI_STATUS +EFIAPI +EnableAutoStopCmd ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ) +{ + MMCHOST_DATA *MmcHostData; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + MmcHostData->IsAutoStopCmd = Enable; + + return EFI_SUCCESS; +} + + +/** + Set the Block length + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] BlockLength card supportes block length + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetBlockLength ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 BlockLength + ) +{ + MMCHOST_DATA *MmcHostData; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + DEBUG ((gMmcHostDebugLevel, "SetBlockLength: Block length on the host controller: %d \n", BlockLength)); + MmcHostData->BlockLength = BlockLength; + + return EFI_SUCCESS; +} + + +/** + Detect card and init Sd host + Find whether these is a card inserted into the slot. If so + init the host. If not, return EFI_NOT_FOUND. + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +DetectCardAndInitHost ( + IN EFI_MMC_HOST_IO_PROTOCOL *This + ) +{ + MMCHOST_DATA *MmcHostData; + UINT16 Data16; + UINT32 Data; + EFI_STATUS Status; + UINT8 Voltages[] = { 33, 30, 18 }; + UINTN Loop; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + Data = 0; + Data = MmcHostRead32 (MmcHostData, MMIO_PSTATE); + + if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) { + // + // Has no card inserted + // + DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: No card\n")); + Status = EFI_NOT_FOUND; + goto Exit; + } + DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: Card present\n")); + + // + //Enable normal status change + // + MmcHostWrite16 (MmcHostData, MMIO_NINTEN, BIT1 | BIT0); + + // + // Enable error status change + // + Data16 = MmcHostRead16 (MmcHostData, MMIO_ERINTEN); + Data16 |= 0xFFFF; //(BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8); + MmcHostWrite16 (MmcHostData, MMIO_ERINTEN, Data16); + + // + // Data transfer Timeout control + // + MmcHostWrite8 (MmcHostData, MMIO_TOCTL, 0x0E); + + // + // Stall 1 milliseconds to increase MMC stability. + // + gBS->Stall (10); + + Status = SetClockFrequency (This, FREQUENCY_OD); + if (EFI_ERROR (Status)) { + DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: SetClockFrequency failed\n")); + goto Exit; + } + DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: SetClockFrequency done\n")); + + Status = EFI_NOT_FOUND; + for (Loop = 0; Loop < sizeof (Voltages); Loop++) { + DEBUG (( + EFI_D_INFO, + "DetectCardAndInitHost: SetHostVoltage %d.%dV\n", + Voltages[Loop] / 10, + Voltages[Loop] % 10 + )); + Status = SetHostVoltage (This, Voltages[Loop]); + if (EFI_ERROR (Status)) { + DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: SetHostVoltage failed\n")); + } else { + DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: SetHostVoltage done\n")); + break; + } + } + if (EFI_ERROR (Status)) { + DEBUG ((gMmcHostDebugLevel, "DetectCardAndInitHost: Failed to SetHostVoltage\n")); + goto Exit; + } + +Exit: + return Status; +} + + +/** + Setup the MMC Host Device + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetupDevice ( + IN EFI_MMC_HOST_IO_PROTOCOL *This + ) +{ + UINT32 tempD = 0; + INT32 timeOut = 1000; + UINT8 temp8 = 0; + UINT16 temp16 = 0; + MMCHOST_DATA *MmcHostData; + + MmcHostData = MMCHOST_DATA_FROM_THIS (This); + + // + // Reset HC and wait for self-clear + // + MmcHostWrite8 (MmcHostData, MMIO_SWRST, 0x7); + gBS->Stall (1000); + timeOut = 1000; + do { + temp8 = MmcHostRead8 (MmcHostData, MMIO_SWRST); + timeOut--; + } while ((temp8 & (1 << 0)) && (timeOut > 0)); + + DEBUG ((EFI_D_INFO, "Reset HC and wait for self-clear Done\n")); + + // + // Enable all interrupt status bits (NO CARD_INTERRUPT!) + // + MmcHostWrite16 (MmcHostData, MMIO_NINTEN, 0x3); + + // + // Clear all interrupt status bits + // + MmcHostWrite16 (MmcHostData, MMIO_NINTSTS, 0xFFFF); + MmcHostWrite16 (MmcHostData, MMIO_ERINTEN, 0xFFFF); + + if (2 == CheckControllerVersion (MmcHostData)) + temp16 = (UINT16) (0x1 << 6); + else + temp16 = (UINT16) (0x80 << 8); + // + // Set to 400KB, enable internal clock and wait for stability + // + MmcHostWrite32 (MmcHostData, MMIO_CLKCTL, (1<<0) | temp16); + + gBS->Stall (1000); + do { + tempD = MmcHostRead32 (MmcHostData, MMIO_CLKCTL); + timeOut--; + } while ((!(tempD & (1 << 1))) && (timeOut > 0)); + gBS->Stall (1000); + + // + // Enable MMC clock + // + tempD |= (1 << 2); + MmcHostWrite32 (MmcHostData, MMIO_CLKCTL, tempD); + gBS->Stall (1000); + + temp8 = MmcHostRead8 (MmcHostData, MMIO_PWRCTL); + DEBUG ((DEBUG_INFO, "==========%a, %d, offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + + // + // Apply 1.8V to the bus + // + temp8 = (0x5 << (1) ); + MmcHostWrite8 (MmcHostData, MMIO_PWRCTL, temp8); + gBS->Stall (1000); + temp8 = MmcHostRead8 (MmcHostData, MMIO_PWRCTL); + DEBUG ((DEBUG_INFO, "==========%a, %d, set (0x5 << 1):offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + + // + // Set 1.8V sigaling Enabled + // + temp16 = MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2); + temp16 &= ~BIT3; + MmcHostWrite16 (MmcHostData, MMIO_HOST_CTL2, temp16); + DEBUG ((gMmcHostDebugLevel, "Set 1.8 V signaling Enable:0x%x \r\n", MmcHostRead16 (MmcHostData, MMIO_HOST_CTL2))); + + // + // Apply power to MMC + // + temp8 = MmcHostRead8 (MmcHostData, MMIO_PWRCTL); + DEBUG ((DEBUG_INFO, "==========%a, %d, read offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + + temp8 |= (1 << (0)); + DEBUG ((DEBUG_INFO, "==========%a, %d, set 1<<0:offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + + MmcHostWrite8 (MmcHostData, MMIO_PWRCTL, temp8); + gBS->Stall (1000); ///<synced to byt-cr pei. bxt power on used (50 * 1000) + temp8 = MmcHostRead8 (MmcHostData, MMIO_PWRCTL); + + DEBUG ((DEBUG_INFO, "==========%a, %d, read offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + + // + // MAX out the DATA_TIMEOUT + // + MmcHostWrite8 (MmcHostData, MMIO_TOCTL, 0xE); + gBS->Stall (1000); + + if (MmcHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "==========%a, Start. RegMap================\n", __FUNCTION__)); + DEBUG ((DEBUG_INFO, "00 -10: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x00), MmcHostRead32 (MmcHostData, 0x04), MmcHostRead32 (MmcHostData, 0x08), MmcHostRead32 (MmcHostData, 0x0C))); + DEBUG ((DEBUG_INFO, "10 -20: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x10), MmcHostRead32 (MmcHostData, 0x14), MmcHostRead32 (MmcHostData, 0x18), MmcHostRead32 (MmcHostData, 0x1C))); + DEBUG ((DEBUG_INFO, "20 -30: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x20), MmcHostRead32 (MmcHostData, 0x24), MmcHostRead32 (MmcHostData, 0x28), MmcHostRead32 (MmcHostData, 0x2C))); + DEBUG ((DEBUG_INFO, "30 -40: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x30), MmcHostRead32 (MmcHostData, 0x34), MmcHostRead32 (MmcHostData, 0x38), MmcHostRead32 (MmcHostData, 0x3C))); + DEBUG ((DEBUG_INFO, "40 -50: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x40), MmcHostRead32 (MmcHostData, 0x44), MmcHostRead32 (MmcHostData, 0x48), MmcHostRead32 (MmcHostData, 0x4C))); + DEBUG ((DEBUG_INFO, "50 -60: %08x %08x %08x %08x \n", MmcHostRead32 (MmcHostData, 0x50), MmcHostRead32 (MmcHostData, 0x54), MmcHostRead32 (MmcHostData, 0x58), MmcHostRead32 (MmcHostData, 0x5C))); + DEBUG ((DEBUG_INFO, "==========%a, END. RegMap================\n", __FUNCTION__)); + } + return EFI_SUCCESS; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c new file mode 100644 index 0000000..f94dc1d --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.c @@ -0,0 +1,613 @@ +/** @file + UEFI Driver Entry and Binding support. + + Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "MmcHostDriver.h" +#include <PiDxe.h> + +// +// MMCSDIOController Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gMmcHostDriverBinding = { + MmcHostDriverBindingSupported, + MmcHostDriverBindingStart, + MmcHostDriverBindingStop, + 0x10, + NULL, + NULL +}; + + +EFI_MMC_HOST_IO_PROTOCOL mMmcHostIo = { + EFI_MMC_HOST_IO_PROTOCOL_REVISION_01, + { + 0, ///< HighSpeedSupport + 0, ///< V18Support + 0, ///< V30Support + 0, ///< V33Support + 0, ///< HS400Support + 0, ///< BusWidth4 + 0, ///< BusWidth8 + 0, ///< Reserved1 + 0, + 0, + 0, + 0, + 0, ///< ADMA2Support + 0, ///< DmaMode + 0, ///< ReTune Timer + 0, ///< ReTune Mode + 0, ///< Reserved2 + (512 * 1024) ///<BoundarySize 512 KB + }, + SendCommand, + SetClockFrequency, + SetBusWidth, + SetHostVoltage, + SetHostDdrMode, + SetHostSdrMode, + ResetMmcHost, + EnableAutoStopCmd, + DetectCardAndInitHost, + SetBlockLength, + SetupDevice, + SetHostSpeedMode +}; + + +/** + Entry point for MMC Host EFI drivers. + + @param[in] ImageHandle EFI_HANDLE + @param[in] SystemTable EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function failed to complete + +**/ +EFI_STATUS +EFIAPI +MmcHostDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gMmcHostDriverBinding, + ImageHandle, + &gMmcHostComponentName, + NULL, + NULL + ); +} + + +/** + Test to see if this MMC Host driver supports ControllerHandle. + Any ControllerHandle that has installed will be supported. + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to test + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver supports this device + @retval EFI_UNSUPPORTED This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +MmcHostDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + PCI_CLASSC PciClass; + UINT32 VidDid; + UINT32 Bar0 = 0; + UINT32 Bar1 = 0; + UINTN Seg, Bus, Dev, Func; + + // + // Verify the MMC IO Protocol, which installed by the + // IdeController module. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiMmcHostIoProtocolGuid, + (VOID **) &MmcHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "MmcHost controller already started, Controller: 0x%016Lx\r\n", (UINT64) (UINTN) Controller)); + Status = EFI_ALREADY_STARTED; + return Status; + } + + // + // Test whether there is PCI IO Protocol attached on the controller handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID**) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_VENDOR_ID_OFFSET, + 1, + &VidDid + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CLASSCODE_OFFSET, + sizeof (PCI_CLASSC) / sizeof (UINT8), + &PciClass + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_BASE_ADDRESSREG_OFFSET, + 1, + &Bar0 + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_BASE_ADDRESSREG_OFFSET + 4, + 1, + &Bar1 + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + Status = PciIo->GetLocation ( + PciIo, + &Seg, + &Bus, + &Dev, + &Func + ); + + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + if ((Seg != 0) || (Bus != 0) || (Dev != 28) || (Func != 0)) { + // + // This is not the eMMC controller, bail. + // + Status = EFI_UNSUPPORTED; + goto Exit; + } + + if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) || + (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) || + ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA)) + ) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported0: Seg %d, bus:%d, Dev:%d, Func:%d\n", Seg, Bus, Dev, Func)); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported1: VidDid %08x\n", VidDid)); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported1: Base Code %x\n", PciClass.BaseCode)); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported1: SubClassCode %x\n", PciClass.SubClassCode)); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported1: PI %x\n", PciClass.PI)); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported0: MEMIO Base0 %x\n", Bar0)); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingSupported0: MEMIO Base1 %x\n", Bar1)); + +Exit: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; +} + + +/** + Starting the MMC Host Driver + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to start + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver start this device + @retval EFI_UNSUPPORTED This driver does not support this device + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error + @retval EFI_OUT_OF_RESOURCES This driver cannot allocate resources + +**/ +EFI_STATUS +EFIAPI +MmcHostDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + MMCHOST_DATA *MmcHostData; + UINT32 Data; + UINT16 Data16; + UINT32 VidDid; + UINT32 Bar0 = 0; + UINT32 Bar1 = 0; + UINTN Seg, Bus, Dev, Func; + + MmcHostData = NULL; + Data = 0; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Start\n")); + + // + // Open PCI I/O Protocol and save pointer to open protocol + // in private data area. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Enable the MMC Host Controller MMIO space + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + + MmcHostData = (MMCHOST_DATA *) AllocateZeroPool (sizeof (MMCHOST_DATA)); + if (MmcHostData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + MmcHostData->Signature = MMCHOST_DATA_SIGNATURE; + MmcHostData->PciIo = PciIo; + + CopyMem (&MmcHostData->MmcHostIo, &mMmcHostIo, sizeof (EFI_MMC_HOST_IO_PROTOCOL)); + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_VENDOR_ID_OFFSET, + 1, + &VidDid + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: VidDid = 0x%08x\n", VidDid)); + + Status = PciIo->GetLocation ( + PciIo, + &Seg, + &Bus, + &Dev, + &Func + ); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Seg %d, bus:%d,Dev:%d,Func:%d\n", Seg, Bus, Dev,Func)); + + MmcHostData->PciVid = (UINT16) (VidDid & 0xffff); + MmcHostData->PciDid = (UINT16) (VidDid >> 16); + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_BASE_ADDRESSREG_OFFSET, + 1, + &Bar0 + ); + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_BASE_ADDRESSREG_OFFSET + 4, + 1, + &Bar1 + ); + + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MEMIO Base0 %x\n", Bar0)); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MEMIO Base1 %x\n", Bar1)); + + + MmcHostData->MmcHostIo.ResetMmcHost (&MmcHostData->MmcHostIo, Reset_All); + MmcHostData->EnableVerboseDebug = FALSE; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CTRLRVER, + 1, + &Data16 + ); + + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MMIO_CTRLRVER = 0x%08x\n", Data16)); + + MmcHostData->ControllerVersion = Data16 & 0xFF; + switch (MmcHostData->ControllerVersion) { + case 0: DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MMC Host Controller Version 1.0\n")); break; + case 1: DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MMC Host Controller Version 2.0\n")); break; + case 2: DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: MMC Host Controller Version 3.0\n")); break; + default: + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Unknown MMC Host Controller Version, Stopping Driver!!\n")); + goto Exit; + } + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT32) MMIO_CAP, + 1, + &Data + ); + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Low MMIO_CAP = 0x%08x\n", Data)); + + if ((Data & BIT18) != 0) { + MmcHostData->MmcHostIo.HostCapability.BusWidth8 = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: BusWidth8\n")); + } + + MmcHostData->MmcHostIo.HostCapability.BusWidth4 = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: BusWidth4\n")); + + if ((Data & BIT19) != 0) { + MmcHostData->MmcHostIo.HostCapability.ADMA2Support = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: ADMA2Support\n")); + } + + if ((Data & BIT21) != 0) { + MmcHostData->MmcHostIo.HostCapability.HighSpeedSupport = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: HighSpeedSupport\n")); + } + + if ((Data & BIT22) != 0) { + MmcHostData->MmcHostIo.HostCapability.SDMASupport = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: SDMASupport\n")); + } + + if ((Data & BIT24) != 0) { + MmcHostData->MmcHostIo.HostCapability.V33Support = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: V33Support\n")); + } + + if ((Data & BIT25) != 0) { + MmcHostData->MmcHostIo.HostCapability.V30Support = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: V30Support\n")); + } + + if ((Data & BIT26) != 0) { + MmcHostData->MmcHostIo.HostCapability.V18Support = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: V18Support\n")); + } + + if (((Data) & (BIT30 | BIT31)) == 0) { + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Removable Card Slot\n")); + } else if ((Data & BIT30) && (Data & (~BIT31))) { + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Embedded Slot for One Device\n")); + } + MmcHostData->BaseClockInMHz = (Data >> 8) & 0xFF; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT32) (MMIO_CAP + 4), + 1, + &Data + ); + + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: High MMIO_CAP = 0x%08x\n", Data)); + + + + if ((Data & 0x1<<(32-32)) != 0) { + MmcHostData->MmcHostIo.HostCapability.SDR50Support= TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: SDR50Support\n")); + } + + if ((Data & 0x1<<(33-32)) != 0) { + MmcHostData->MmcHostIo.HostCapability.SDR104Support= TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: SDR104Support\n")); + } + + if ((Data & 0x1<<(34-32)) != 0) { + MmcHostData->MmcHostIo.HostCapability.DDR50Support= TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: DDR50Support\n")); + } + + if ((Data & 0x1<<(63-32)) != 0) { + MmcHostData->MmcHostIo.HostCapability.HS400Support = TRUE; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: HS400Support\n")); + } + + if (MmcHostData->ControllerVersion >= 2) { + MmcHostData->MmcHostIo.HostCapability.ReTuneMode = (Data >> (46-32)) & 0x3; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: ReTuneMode = 0x%08x\n", MmcHostData->MmcHostIo.HostCapability.ReTuneMode)); + + MmcHostData->MmcHostIo.HostCapability.ReTuneTimer = (Data>>(40-32)) & 0xF; + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: ReTuneTimer = 0x%08x\n", MmcHostData->MmcHostIo.HostCapability.ReTuneTimer)); + } + + + MmcHostData->BlockLength = BLOCK_SIZE; + MmcHostData->IsAutoStopCmd = TRUE; + + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiMmcHostIoProtocolGuid, + EFI_NATIVE_INTERFACE, + &MmcHostData->MmcHostIo + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Component name protocol + // + Status = AddUnicodeString ( + "eng", + gMmcHostComponentName.SupportedLanguages, + &MmcHostData->ControllerNameTable, + L"MMC Host Controller" + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + gBS->UninstallProtocolInterface ( + Controller, + &gEfiMmcHostIoProtocolGuid, + &MmcHostData->MmcHostIo + ); + } + + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStart: Host Started\n")); + +Exit: + if (EFI_ERROR (Status)) { + if (MmcHostData != NULL) { + FreePool (MmcHostData); + } + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + return Status; +} + + +/** + Stop MMC Host driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to stop driver on + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer + @param[in] ChildHandleBuffer List of handles for the children we need to stop + + @retval EFI_SUCCESS This driver stop this device + @retval EFI_DEVICE_ERROR This driver cannot be stop due to device Error + +**/ +EFI_STATUS +EFIAPI +MmcHostDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + MMCHOST_DATA *MmcHostData; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiMmcHostIoProtocolGuid, + (VOID **) &MmcHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto _exit_MmcHostDriverBindingStop; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + MmcHostData = MMCHOST_DATA_FROM_THIS (MmcHostIo); + + // + // Uninstall Block I/O protocol from the device handle + // + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiMmcHostIoProtocolGuid, + &MmcHostData->MmcHostIo + ); + if (EFI_ERROR (Status)) { + goto _exit_MmcHostDriverBindingStop; + } + + FreeUnicodeStringTable (MmcHostData->ControllerNameTable); + FreePool (MmcHostData); + +_exit_MmcHostDriverBindingStop: + DEBUG ((EFI_D_INFO, "MmcHostDriverBindingStop exited with Status %r\n", Status)); + + return Status; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h new file mode 100644 index 0000000..f724061 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDriver.h @@ -0,0 +1,585 @@ +/** @file + Header file for MMC driver. + + Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR> + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MMC_HOST_DRIVER_H +#define _MMC_HOST_DRIVER_H + +#include <Uefi.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiLib.h> +#include <Library/DevicePathLib.h> +#include <Library/IoLib.h> +#include <IndustryStandard/Pci.h> +#include <IndustryStandard/SdCard.h> +#include <ScAccess.h> + +// +// Driver Consumed Protocol Prototypes +// +#include <Protocol/DevicePath.h> +#include <Protocol/PciIo.h> + +// +// Driver Produced Protocol Prototypes +// +#include <Protocol/DriverBinding.h> +#include <Protocol/ComponentName.h> +#include <Protocol/ComponentName2.h> +#include <Protocol/MmcHostIo.h> + +extern EFI_COMPONENT_NAME_PROTOCOL gMmcHostComponentName; +extern EFI_DRIVER_BINDING_PROTOCOL gMmcHostDriverBinding; + +#define MMCHOST_DATA_SIGNATURE SIGNATURE_32 ('m', 'c', 'h', 's') + +#define MMCHOST_DATA_FROM_THIS(a) \ + CR (a, MMCHOST_DATA, MmcHostIo, MMCHOST_DATA_SIGNATURE) + +#define BLOCK_SIZE 0x200 +#define TIME_OUT_1S 1000 + +#define INTEL_VENDOR_ID 0x8086 + +#define BUFFER_CTL_REGISTER 0x84 + +#pragma pack(1) +// +// PCI Class Code structure +// +typedef struct { + UINT8 PI; + UINT8 SubClassCode; + UINT8 BaseCode; +} PCI_CLASSC; + +#pragma pack() + +// +// MMCHOST_DATA structure +// +typedef struct { + UINTN Signature; + EFI_MMC_HOST_IO_PROTOCOL MmcHostIo; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT16 PciVid; + UINT16 PciDid; + BOOLEAN IsAutoStopCmd; + BOOLEAN IsEmmc; + BOOLEAN EnableVerboseDebug; + UINT32 BaseClockInMHz; + UINT32 CurrentClockInKHz; + UINT32 BlockLength; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + UINT32 ControllerVersion; +} MMCHOST_DATA; + +// +// Prototypes +// Driver model protocol interface +// +/** + Entry point for MMC Host EFI drivers. + + @param[in] ImageHandle EFI_HANDLE + @param[in] SystemTable EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function failed to complete + +**/ +EFI_STATUS +EFIAPI +MmcHostDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Test to see if this MMC Host driver supports ControllerHandle. + Any ControllerHandle that has installed will be supported. + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to test + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver supports this device + @retval EFI_UNSUPPORTED This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +MmcHostDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Starting the MMC Host Driver + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to start + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver start this device + @retval EFI_UNSUPPORTED This driver does not support this device + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error + @retval EFI_OUT_OF_RESOURCES This driver cannot allocate resources + +**/ +EFI_STATUS +EFIAPI +MmcHostDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop MMC Host driver on ControllerHandle. Support stopping any child handles + created by this driver. + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to stop driver on + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer + @param[in] ChildHandleBuffer List of handles for the children we need to stop + + @retval EFI_SUCCESS This driver stop this device + @retval EFI_DEVICE_ERROR This driver cannot be stop due to device Error + +**/ +EFI_STATUS +EFIAPI +MmcHostDriverBindingStop ( + 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 EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param[out] DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language 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 +MmcHostComponentNameGetDriverName ( + 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 an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device 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 name of a child controller. + @param[in] Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param[out] ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + + @retval EFI_SUCCESS The Unicode string for the user readable name in the + language specified by Language for 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 +MmcHostComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/** + The main function used to send the command to the card inserted into the MMC host + slot. + It will assemble the arguments to set the command register and wait for the command + and transfer completed until timeout. Then it will read the response register to fill + the ResponseData + + @param[in] This Pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] CommandIndex The command index to set the command index field of command register + @param[in] Argument Command argument to set the argument field of command register + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out + @param[in] Buffer Contains the data read from / write to the device + @param[in] BufferSize The size of the buffer + @param[in] ResponseType RESPONSE_TYPE + @param[in] TimeOut Time out value in 1 ms unit + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_OUT_OF_RESOURCES + @retval EFI_TIMEOUT + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +EFIAPI +SendCommand ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData OPTIONAL + ); + +/** + Set max clock frequency of the host, the actual frequency + may not be the same as MaxFrequencyInKHz. It depends on + the max frequency the host can support, divider, and host + speed mode. + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] MaxFrequency Max frequency in HZ + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT +**/ +EFI_STATUS +EFIAPI +SetClockFrequency ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 MaxFrequencyInKHz + ); + +/** + Set bus width of the host + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] BusWidth Bus width in 1, 4, 8 bits + + + @retval EFI_STATUS + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +EFIAPI +SetBusWidth ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 BusWidth + ); + +/** + Set voltage which could supported by the host. + Support 0(Power off the host), 1.8V, 3.0V, 3.3V + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Voltage Units in 0.1 V + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +EFIAPI +SetHostVoltage ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 Voltage + ); + +/** + Set Host mode in DDR + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] DdrMode True for DDR Mode set, false returns EFI_SUCCESS + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +EFIAPI +SetHostDdrMode ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 DdrMode + ); + +/** + Set Host SDR Mode + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] DdrMode True for SDR Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. + +**/ +EFI_STATUS +EFIAPI +SetHostSdrMode ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 SdrMode + ); + +/** + Set Host High Speed + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] HighSpeed True for High Speed Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. + +**/ +EFI_STATUS +EFIAPI +SetHostSpeedMode ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 HighSpeed + ); + +/** + Reset the host + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] ResetAll TRUE to reset all + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. + +**/ +EFI_STATUS +EFIAPI +ResetMmcHost ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN RESET_TYPE ResetType + ); + +/** + Reset the host + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] ResetAll TRUE to reset all + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. + +**/ +EFI_STATUS +EFIAPI +EnableAutoStopCmd ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ); + +/** + Find whether these is a card inserted into the slot. If so + init the host. If not, return EFI_NOT_FOUND. + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Fail + +**/ +EFI_STATUS +EFIAPI +DetectCardAndInitHost ( + IN EFI_MMC_HOST_IO_PROTOCOL *This + ); + +/** + Set the Block length + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] BlockLength card supports block length + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Fail + +**/ +EFI_STATUS +EFIAPI +SetBlockLength ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT32 BlockLength + ); + +/** + Setup Device + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Fail + +**/ +EFI_STATUS +EFIAPI +SetupDevice( + IN EFI_MMC_HOST_IO_PROTOCOL *This + ); + +/** + Read MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the eMMC + + @retval Data Data read from eMMC + +**/ +UINT8 +MmcHostRead8 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset + ); + +/** + Read MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the eMMC + + @retval Data Data read from eMMC + +**/ +UINT16 +MmcHostRead16 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset + ); + +/** + Read MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the eMMC + + @retval Data Data read from eMMC + +**/ +UINT32 +MmcHostRead32 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset + ); + +/** + Write MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the eMMC + @param[in] Data Data write to eMMC + + @retval Data Written to MmcHost + +**/ +UINT8 +MmcHostWrite8 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset, + IN UINT8 Data + ); + +/** + Write MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the eMMC + @param[in] Data Data write to eMMC + + @retval Data Data written to eMMC + +**/ +UINT16 +MmcHostWrite16 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset, + IN UINT16 Data + ); + +/** + Write MMC host register + + @param[in] MmcHost Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] Offset Offset of the eMMC + @param[in] Data Data write to eMMC + + @retval Data Data written to eMMC + +**/ +UINT32 +MmcHostWrite32 ( + IN MMCHOST_DATA *MmcHost, + IN UINTN Offset, + IN UINT32 Data + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf new file mode 100644 index 0000000..0433019 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcHostDxe/MmcHostDxe.inf @@ -0,0 +1,59 @@ +## @file +# MMC Host module +# +# Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR> +# +# 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 = 0x00010005 + BASE_NAME = MmcHost + FILE_GUID = D86DB3C5-57FE-44CF-A82A-74C4AD5B1C2E + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = MmcHostDriverEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + ComponentName.c + MmcHostDriver.h + MmcHostDriver.c + MmcHostController.c + +[Packages] + MdePkg/MdePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + UefiBootServicesTableLib + BaseMemoryLib + MemoryAllocationLib + UefiLib + DevicePathLib + IoLib + PcdLib + HobLib + +[Protocols] + gEfiPciIoProtocolGuid ## CONSUMES + gEfiMmcHostIoProtocolGuid ## BY_START + +[Guids] + gEfiBootMediaHobGuid ## UNDEFINED + +[Pcd] diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c new file mode 100644 index 0000000..a0b0940 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/ComponentName.c @@ -0,0 +1,159 @@ +/** @file + Header file for ComponentName. + + Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 <MediaDeviceDriver.h> + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gMediaDeviceComponentName = { + MediaDeviceComponentNameGetDriverName, + MediaDeviceComponentNameGetControllerName, + "eng" +}; + + +static EFI_UNICODE_STRING_TABLE mMediaDeviceDriverNameTable[] = { + { "eng", L"UEFI MMC/SD Media Device Driver" }, + { NULL , NULL } +}; + + +/** + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param[out] DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language 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 +MediaDeviceComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString ( + Language, + gMediaDeviceComponentName.SupportedLanguages, + mMediaDeviceDriverNameTable, + DriverName + ); +} + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device 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 name of a child controller. + @param[in] Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param[out] ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in the + language specified by Language for 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 +MediaDeviceComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + CARD_DATA *CardData; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gMediaDeviceDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + CardData = CARD_DATA_FROM_THIS (BlockIo); + return LookupUnicodeString ( + Language, + gMediaDeviceComponentName.SupportedLanguages, + CardData->ControllerNameTable, + ControllerName + ); +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c new file mode 100644 index 0000000..5c91190 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDBlockIo.c @@ -0,0 +1,666 @@ +/** @file + Block I/O protocol for MMC/SD device. + + Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.<BR> + + 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 <MediaDeviceDriver.h> + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.Reset() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] ExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device during reset. + (This parameter is ingored in this driver.) + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +MMCSDBlockReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + CARD_DATA *CardData; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + + CardData = CARD_DATA_FROM_THIS (This); + MmcHostIo = CardData->MmcHostIo; + + DEBUG ((EFI_D_INFO, "MMC SD Block: Resetting host\n")); + + return MmcHostIo->ResetMmcHost (MmcHostIo, Reset_DAT_CMD); +} + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] MediaId The media id that the read request is for. + @param[in] LBA The starting logical block address to read from on the device. + @param[in] BufferSiz The size of the Buffer in bytes. This must be a multiple of + the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +EFIAPI +MMCSDBlockReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT32 Address; + CARD_DATA *CardData; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + UINT32 RemainingLength; + UINT32 TransferLength; + UINT8 *BufferPointer; + BOOLEAN SectorAddressing; + UINT64 CardSize; + MMC_PARTITION_DATA *Partition; + UINTN TotalBlock; + + Status = EFI_SUCCESS; + Partition = CARD_PARTITION_DATA_FROM_THIS (This); + CardData = Partition->CardData; + MmcHostIo = CardData->MmcHostIo; + + // + // Media ID has high priority that need to be verify first + // + if (MediaId != Partition->BlockIoMedia.MediaId) { + return EFI_MEDIA_CHANGED; + } + + Status = MmcSelectPartition (Partition); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // BufferSize must be a multiple of the intrinsic block size of the device. + // + if (ModU64x32 (BufferSize,Partition->BlockIoMedia.BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + CardSize = MultU64x32 (CardData->BlockNumber, CardData->BlockLen); + + if ((CardData->CardType == SdMemoryCard2High) || (CardSize >= SIZE_2GB)) { + SectorAddressing = TRUE; + } else { + SectorAddressing = FALSE; + } + + if (SectorAddressing) { + // + // Sector Address + // + Address = (UINT32) DivU64x32 (MultU64x32 (LBA, Partition->BlockIoMedia.BlockSize), 512); + } else { + // + // Byte Address + // + Address = (UINT32) MultU64x32 (LBA, Partition->BlockIoMedia.BlockSize); + } + + TotalBlock = (UINTN) DivU64x32 (BufferSize, Partition->BlockIoMedia.BlockSize); + // + // Make sure the range to read is valid. + // + if (LBA + TotalBlock > Partition->BlockIoMedia.LastBlock + 1) { + return EFI_INVALID_PARAMETER; + } + + if (!(Partition->BlockIoMedia.MediaPresent)) { + return EFI_NO_MEDIA; + } + + if (!Buffer) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Invalid parameter \n")); + goto Done; + } + + if ((BufferSize % Partition->BlockIoMedia.BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Bad buffer size \n")); + goto Done; + } + + if (BufferSize == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + BufferPointer = Buffer; + RemainingLength = (UINT32) BufferSize; + + while (RemainingLength > 0) { + if ((BufferSize >= Partition->BlockIoMedia.BlockSize)) { + if (RemainingLength > MmcHostIo->HostCapability.BoundarySize) { + TransferLength = MmcHostIo->HostCapability.BoundarySize; + } else { + TransferLength = RemainingLength; + } + + if (CardData->CardType == MMCCard) { + if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) { + Status = SendCommand ( + MmcHostIo, + SET_BLOCKLEN, + Partition->BlockIoMedia.BlockSize, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + if (EFI_ERROR (Status)) { + break; + } + } + + Status = SendCommand ( + MmcHostIo, + SET_BLOCK_COUNT, + TransferLength / Partition->BlockIoMedia.BlockSize, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + if (EFI_ERROR (Status)) { + break; + } + } + + Status = SendCommand ( + MmcHostIo, + READ_MULTIPLE_BLOCK, + Address, + InData, + CardData->AlignedBuffer, + TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n")); + break; + } + } else { + if (RemainingLength > Partition->BlockIoMedia.BlockSize) { + TransferLength = Partition->BlockIoMedia.BlockSize; + } else { + TransferLength = RemainingLength; + } + + Status = SendCommand ( + MmcHostIo, + READ_SINGLE_BLOCK, + Address, + InData, + CardData->AlignedBuffer, + (UINT32) TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32*) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n")); + break; + } + } + + CopyMem (BufferPointer, CardData->AlignedBuffer, TransferLength); + + if (SectorAddressing) { + // + // Sector Address + // + Address += TransferLength / 512; + } else { + // + // Byte Address + // + Address += TransferLength; + } + BufferPointer += TransferLength; + RemainingLength -= TransferLength; + } + + if (EFI_ERROR (Status)) { + if ((CardData->CardType == SdMemoryCard) || + (CardData->CardType == SdMemoryCard2)|| + (CardData->CardType == SdMemoryCard2High)) { + SendCommand ( + MmcHostIo, + STOP_TRANSMISSION, + 0, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + } else { + SendCommand ( + MmcHostIo, + STOP_TRANSMISSION, + 0, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + } + } + +Done: + return Status; +} + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] MediaId The media id that the write request is for. + @param[in] LBA The starting logical block address to be written. + The caller is responsible for writing to only + legitimate locations. + @param[in] BufferSize + The size of the Buffer in bytes. This must be a multiple of + the intrinsic block size of the device. + @param[in] Buffer A pointer to the source buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +EFIAPI +MMCSDBlockWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT32 Address; + CARD_DATA *CardData; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + UINT32 RemainingLength; + UINT32 TransferLength; + UINT8 *BufferPointer; + BOOLEAN SectorAddressing; + UINT64 CardSize; + MMC_PARTITION_DATA *Partition; + + Status = EFI_SUCCESS; + Partition = CARD_PARTITION_DATA_FROM_THIS (This); + CardData = Partition->CardData; + MmcHostIo = CardData->MmcHostIo; + + Status = MmcSelectPartition (Partition); + if (EFI_ERROR (Status)) { + return Status; + } + + CardSize = MultU64x32 (CardData->BlockNumber, CardData->BlockLen); + + if ((CardData->CardType == SdMemoryCard2High) || (CardSize >= SIZE_2GB)) { + SectorAddressing = TRUE; + } else { + SectorAddressing = FALSE; + } + + if (SectorAddressing) { + // + // Sector Address + // + Address = (UINT32) DivU64x32 (MultU64x32 (LBA, Partition->BlockIoMedia.BlockSize), 512); + } else { + // + // Byte Address + // + Address = (UINT32) MultU64x32 (LBA, Partition->BlockIoMedia.BlockSize); + } + + if (!Buffer) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Invalid parameter \n")); + goto Done; + } + + if ((BufferSize % Partition->BlockIoMedia.BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Bad buffer size \n")); + goto Done; + } + + if (BufferSize == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + if (This->Media->ReadOnly == TRUE) { + Status = EFI_WRITE_PROTECTED; + DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Write protected \n")); + goto Done; + } + + BufferPointer = Buffer; + RemainingLength = (UINT32) BufferSize; + + while (RemainingLength > 0) { + if ((BufferSize >= Partition->BlockIoMedia.BlockSize) ) { + if (RemainingLength > MmcHostIo->HostCapability.BoundarySize) { + TransferLength = MmcHostIo->HostCapability.BoundarySize; + } else { + TransferLength = RemainingLength; + } + + if ((CardData->CardType == SdMemoryCard) || + (CardData->CardType == SdMemoryCard2)|| + (CardData->CardType == SdMemoryCard2High)) { + // + // Write performance improvement + // + if ((TransferLength / Partition->BlockIoMedia.BlockSize) > 64) { + Status = SendAppCommand ( + CardData, + SET_WR_BLK_ERASE_COUNT, + (UINT32) (TransferLength / Partition->BlockIoMedia.BlockSize), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + } + } else if (CardData->CardType == MMCCard) { + + if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) { + Status = SendCommand ( + MmcHostIo, + SET_BLOCKLEN, + Partition->BlockIoMedia.BlockSize, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + break; + } + } + Status = SendCommand ( + MmcHostIo, + SET_BLOCK_COUNT, + TransferLength / Partition->BlockIoMedia.BlockSize, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + if (EFI_ERROR (Status)) { + break; + } + } + + CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength); + + Status = SendCommand ( + MmcHostIo, + WRITE_MULTIPLE_BLOCK, + Address, + OutData, + CardData->AlignedBuffer, + (UINT32) TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n")); + break; + } + } else { + if (RemainingLength > Partition->BlockIoMedia.BlockSize) { + TransferLength = Partition->BlockIoMedia.BlockSize; + } else { + TransferLength = RemainingLength; + } + + CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength); + + Status = SendCommand ( + MmcHostIo, + WRITE_BLOCK, + Address, + OutData, + CardData->AlignedBuffer, + (UINT32) TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + } + + if (SectorAddressing) { + // + // Sector Address + // + Address += TransferLength / 512; + } else { + // + // Byte Address + // + Address += TransferLength; + } + BufferPointer += TransferLength; + RemainingLength -= TransferLength; + } + + if (EFI_ERROR (Status)) { + SendCommand ( + MmcHostIo, + STOP_TRANSMISSION, + 0, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + } + +Done: + return Status; +} + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function. + (In this driver, this function just returns EFI_SUCCESS.) + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + + @retval EFI_SUCCESS Success + +**/ +EFI_STATUS +EFIAPI +MMCSDBlockFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + + +/** + MMC/SD card BlockIo init function + + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_SUCCESS Success + +**/ +EFI_STATUS +MMCSDBlockIoInit ( + IN CARD_DATA *CardData + ) +{ + UINTN Loop; + MMC_PARTITION_DATA *Partition; + EXT_CSD *ExtCsd; + UINT64 GP_CHUNK_SIZE; + UINT32 GP_SIZE_MULT; + UINT64 GppSize; + UINTN GppIndex=0; + + Partition = CardData->Partitions; + ExtCsd = &CardData->ExtCSDRegister; + + // + // Determine GP partitioning chunk size + // + GP_CHUNK_SIZE = 0; + if (((ExtCsd->PARTITIONING_SUPPORT & BIT0) == BIT0) && + ((ExtCsd->PARTITION_SETTING_COMPLETED & BIT0) == BIT0)) { + GP_CHUNK_SIZE = MultU64x32 (ExtCsd->HC_WP_GRP_SIZE, ExtCsd->HC_ERASE_GRP_SIZE); + GP_CHUNK_SIZE = MultU64x32 (GP_CHUNK_SIZE, SIZE_512KB); + } + + for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Partition++, Loop++) { + // + // BlockIO protocol + // + Partition->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + Partition->BlockIo.Media = &(Partition->BlockIoMedia); + Partition->BlockIo.Reset = MMCSDBlockReset; + Partition->BlockIo.ReadBlocks = MMCSDBlockReadBlocks ; + Partition->BlockIo.WriteBlocks = MMCSDBlockWriteBlocks; + Partition->BlockIo.FlushBlocks = MMCSDBlockFlushBlocks; + + Partition->BlockIoMedia.MediaId = 0; + Partition->BlockIoMedia.RemovableMedia = FALSE; + Partition->BlockIoMedia.MediaPresent = TRUE; + Partition->BlockIoMedia.LogicalPartition = FALSE; + + // + // Force the User partition to be enabled + // + if (Loop == 0) { + Partition->Present = TRUE; + } + + if (CardData->CSDRegister.PERM_WRITE_PROTECT || CardData->CSDRegister.TMP_WRITE_PROTECT) { + Partition->BlockIoMedia.ReadOnly = TRUE; + } else { + Partition->BlockIoMedia.ReadOnly = FALSE; + } + + Partition->BlockIoMedia.WriteCaching = FALSE; + Partition->BlockIoMedia.BlockSize = CardData->BlockLen; + Partition->BlockIoMedia.IoAlign = 1; + Partition->BlockIoMedia.LastBlock = (EFI_LBA) (CardData->BlockNumber - 1); + + // + // Handle GPP partitions + // + GppSize = 0; + if ((GP_CHUNK_SIZE != 0) && (Loop >= 4)) { + Partition->BlockIoMedia.LastBlock = (EFI_LBA) 0; + GppIndex = Loop - 4; + GP_SIZE_MULT = MmcGetExtCsd24 ( + CardData, + OFFSET_OF (EXT_CSD, GP_SIZE_MULT_1) + (3 * GppIndex) + ); + GppSize = MultU64x32 (GP_SIZE_MULT, (UINT32) GP_CHUNK_SIZE); + } + + if (GppSize != 0) { + Partition->BlockIoMedia.LastBlock = + DivU64x32 (GppSize, Partition->BlockIoMedia.BlockSize) - 1; + DEBUG ((EFI_D_INFO, + "GPP%d last-block: 0x%lx\n", + GppIndex + 1, + Partition->BlockIoMedia.LastBlock + )); + Partition->Present = TRUE; + } + + if (CardData->CardType == MMCCard) { + // + // Handle Boot partitions + // + if ((Loop == 1) || (Loop == 2)) { + Partition->BlockIoMedia.LastBlock = 128 * 1024 * ((UINTN) MmcGetExtCsd8 (CardData, OFFSET_OF (EXT_CSD, BOOT_SIZE_MULTI))) / 512; + Partition->Present = TRUE; + } + } + } + + DEBUG ((EFI_D_INFO, "MMC SD Block I/O: Initialized\n")); + + return EFI_SUCCESS; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c new file mode 100644 index 0000000..13258de --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MMCSDTransfer.c @@ -0,0 +1,2524 @@ +/** @file + SMMC transfer specific functions. + + Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR> + + 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 <MediaDeviceDriver.h> +#include <HeciRegs.h> +#include <Private/Guid/ScPolicyHobGuid.h> +#include <SeCAccess.h> +#include <Library/SteppingLib.h> +#include <Library/ConfigBlockLib.h> + + +/** + Set Mmc ExtCsd register + + @param[in] PeiCardData Pointer to CARD_DATA + @param[in] Index + @param[in] Value + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcSetExtCsd8 ( + IN CARD_DATA *CardData, + IN UINT8 Index, + IN UINT8 Value + ); + +EFI_EVENT mSetEmmcWpOnEvent = NULL; + + +/** + Check card status, print the debug info and check the error + + @param[in] Status Status got from card status register + + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +EFI_STATUS +CheckCardStatus ( + IN UINT32 Status + ) +{ + CARD_STATUS *CardStatus; + CardStatus = (CARD_STATUS *) (&Status); + + if (CardStatus->ADDRESS_OUT_OF_RANGE) { + DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_OUT_OF_RANGE\n")); + } + + if (CardStatus->ADDRESS_MISALIGN) { + DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_MISALIGN\n")); + } + + if (CardStatus->BLOCK_LEN_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: BLOCK_LEN_ERROR\n")); + } + + if (CardStatus->ERASE_SEQ_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_SEQ_ERROR\n")); + } + + if (CardStatus->ERASE_PARAM) { + DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_PARAM\n")); + } + + if (CardStatus->WP_VIOLATION) { + DEBUG ((EFI_D_ERROR, "CardStatus: WP_VIOLATION\n")); + } + + if (CardStatus->CARD_IS_LOCKED) { + DEBUG ((EFI_D_ERROR, "CardStatus: CARD_IS_LOCKED\n")); + } + + if (CardStatus->LOCK_UNLOCK_FAILED) { + DEBUG ((EFI_D_ERROR, "CardStatus: LOCK_UNLOCK_FAILED\n")); + } + + if (CardStatus->COM_CRC_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: COM_CRC_ERROR\n")); + } + + if (CardStatus->ILLEGAL_COMMAND) { + DEBUG ((EFI_D_ERROR, "CardStatus: ILLEGAL_COMMAND\n")); + } + + if (CardStatus->CARD_ECC_FAILED) { + DEBUG ((EFI_D_ERROR, "CardStatus: CARD_ECC_FAILED\n")); + } + + if (CardStatus->CC_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: CC_ERROR\n")); + } + + if (CardStatus->ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: ERROR\n")); + } + + if (CardStatus->UNDERRUN) { + DEBUG ((EFI_D_ERROR, "CardStatus: UNDERRUN\n")); + } + + if (CardStatus->OVERRUN) { + DEBUG ((EFI_D_ERROR, "CardStatus: OVERRUN\n")); + } + + if (CardStatus->CID_CSD_OVERWRITE) { + DEBUG ((EFI_D_ERROR, "CardStatus: CID_CSD_OVERWRITE\n")); + } + + if (CardStatus->WP_ERASE_SKIP) { + DEBUG ((EFI_D_ERROR, "CardStatus: WP_ERASE_SKIP\n")); + } + + if (CardStatus->ERASE_RESET) { + DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_RESET\n")); + } + + if (CardStatus->SWITCH_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: SWITCH_ERROR\n")); + } + + if ((Status & 0xFCFFA080) != 0) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Send command by using Host IO protocol + + @param[in] This Pointer to EFI_MMC_HOST_IO_PROTOCOL + @param[in] CommandIndex The command index to set the command index field of command register + @param[in] Argument Command argument to set the argument field of command register + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out + @param[in] Buffer Contains the data read from / write to the device + @param[in] BufferSize The size of the buffer + @param[in] ResponseType RESPONSE_TYPE + @param[in] TimeOut Time out value in 1 ms unit + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +EFI_STATUS +SendCommand ( + IN EFI_MMC_HOST_IO_PROTOCOL *This, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData + ) +{ + + EFI_STATUS Status; + + Status = This->SendCommand ( + This, + CommandIndex, + Argument, + DataType, + Buffer, + BufferSize, + ResponseType, + TimeOut, + ResponseData + ); + if (!EFI_ERROR (Status)) { + if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) { + if (ResponseData == NULL) { + ASSERT(ResponseData != NULL); + return EFI_OUT_OF_RESOURCES; + } + Status = CheckCardStatus (*ResponseData); + } + } else { + This->ResetMmcHost (This, Reset_DAT_CMD); + } + + return Status; +} + + +/** + Send the card APP_CMD command with the following command indicated + by CommandIndex + + @param[in] CardData Pointer to CARD_DATA + @param[in] CommandIndex The command index to set the command index field of command register + @param[in] Argument Command argument to set the argument field of command register + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out + @param[in] Buffer Contains the data read from / write to the device + @param[in] BufferSize The size of the buffer + @param[in] ResponseType RESPONSE_TYPE + @param[in] TimeOut Time out value in 1 ms unit + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +EFI_STATUS +SendAppCommand ( + IN CARD_DATA *CardData, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData + ) +{ + + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + UINT8 Index; + + MmcHostIo = CardData->MmcHostIo; + Status = EFI_SUCCESS; + + for (Index = 0; Index < 2; Index++) { + Status = MmcHostIo->SendCommand ( + MmcHostIo, + APP_CMD, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + if (!EFI_ERROR (Status)) { + Status = CheckCardStatus (*(UINT32 *) &(CardData->CardStatus)); + if (CardData->CardStatus.SAPP_CMD != 1) { + Status = EFI_DEVICE_ERROR; + } + if (!EFI_ERROR (Status)) { + break; + } + } else { + MmcHostIo->ResetMmcHost (MmcHostIo, Reset_Auto); + } + } + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = MmcHostIo->SendCommand ( + MmcHostIo, + CommandIndex, + Argument, + DataType, + Buffer, + BufferSize, + ResponseType, + TimeOut, + ResponseData + ); + if (!EFI_ERROR (Status)) { + if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) { + if (ResponseData == NULL) { + ASSERT(ResponseData != NULL); + return EFI_OUT_OF_RESOURCES; + } + Status = CheckCardStatus (*ResponseData); + } + } else { + MmcHostIo->ResetMmcHost (MmcHostIo, Reset_Auto); + } + + return Status; +} + + +/** + Dump Mmc Decode OCR register + + @param[in] OCRReg Pointer to OCR + + @retval None + +**/ +EFI_STATUS +MmcDecodeOCR ( + IN OCR *OCRReg + ) +{ + DEBUG ((DEBUG_INFO, "\n==========DECODE MMC OCR REGISTER==================\n")); + DEBUG ((DEBUG_INFO, " OCR = 0x%08X\n", *((UINT32 *) OCRReg))); + DEBUG ((DEBUG_INFO, " CARD_NOT_BUSY = 0x%X\n", OCRReg->Busy)); + DEBUG ((DEBUG_INFO, " ACCESS_MODE = 0x%X\n", OCRReg->AccessMode)); + DEBUG ((DEBUG_INFO, " VDD_270_360 = 0x%X\n", OCRReg->V270_V360)); + DEBUG ((DEBUG_INFO, " VDD_200_260 = 0x%X\n", OCRReg->V200_V260)); + DEBUG ((DEBUG_INFO, " VDD_170_195 = 0x%X\n", OCRReg->V170_V195)); + DEBUG ((DEBUG_INFO, "==================================================\n")); + return 0; +} + + +/** + Dump Mmc Decode CID value + + @param[in] CIDReg Pointer to CIDReg + + @retval None + +**/ +EFI_STATUS +MmcDecodeCID ( + IN CID *CIDReg + ) +{ + UINT32 i = 0; + + DEBUG ((EFI_D_INFO, "\n==========DECODE MMC CID REGISTER==================\n")); + DEBUG ((EFI_D_INFO, " CID = 0x%032X\n", CIDReg)); + DEBUG ((EFI_D_INFO, " MANUFACTURER_ID = 0x%X\n", CIDReg->MID)); + DEBUG ((EFI_D_INFO, " CARD_OR_BGA = 0x%X\n", (CIDReg->OID & 0xFF00)>>6)); + DEBUG ((EFI_D_INFO, " OEM_APPLICATION_ID = 0x%X\n", (CIDReg->OID>>8) &0xFF)); + DEBUG ((EFI_D_INFO, " PRODUCT_NAME = ")); + + for (i=0; i < 6; i++) { + DEBUG ((EFI_D_INFO, "%c", CIDReg->PNM[i])); + } + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, " PRODUCT_REVISION = 0x%X\n", CIDReg->PRV)); + DEBUG ((EFI_D_INFO, " PRODUCT_SERIAL_NUM = 0x%X\n", CIDReg->PSN)); + DEBUG ((EFI_D_INFO, " MANUFACTURE_DATE = 0x%X\n", CIDReg->MDT)); + DEBUG ((EFI_D_INFO, "==================================================\n")); + return 0; +} + + +/** + Dump Mmc Decode CSD value + + @param[in] CSDReg Pointer to CSDReg + + @retval None + +**/ +EFI_STATUS +MmcDecodeCSD ( + IN CSD *CSDReg + ) +{ + DEBUG ((EFI_D_INFO, "\n==========DECODE MMC CSD REGISTER==================\n")); + DEBUG ((EFI_D_INFO, "csd_struct : [0x%0x] \n", CSDReg->CSD_STRUCTURE)); + DEBUG ((EFI_D_INFO, "specs_ver : [0x%0x] \n", CSDReg->SPEC_VERS)); + DEBUG ((EFI_D_INFO, "reserve2 : [0x%0x] \n", CSDReg->Reserved2)); + DEBUG ((EFI_D_INFO, "taac : [0x%0x] \n", CSDReg->TAAC)); + DEBUG ((EFI_D_INFO, "nsac : [0x%0x] \n", CSDReg->NSAC)); + DEBUG ((EFI_D_INFO, "tran_speed : [0x%0x] \n", CSDReg->TRAN_SPEED)); + DEBUG ((EFI_D_INFO, "ccc : [0x%0x] \n", CSDReg->CCC)); + DEBUG ((EFI_D_INFO, "read_bl_len : [0x%0x] \n", CSDReg->READ_BL_LEN)); + DEBUG ((EFI_D_INFO, "read_partial : [0x%0x] \n", CSDReg->READ_BL_PARTIAL)); + DEBUG ((EFI_D_INFO, "write_misalign : [0x%0x] \n", CSDReg->WRITE_BLK_MISALIGN)); + DEBUG ((EFI_D_INFO, "read_misalign : [0x%0x] \n", CSDReg->READ_BLK_MISALIGN)); + DEBUG ((EFI_D_INFO, "dsr_imp : [0x%0x] \n", CSDReg->DSR_IMP)); + DEBUG ((EFI_D_INFO, "reserve1 : [0x%0x] \n", CSDReg->Reserved1)); + DEBUG ((EFI_D_INFO, "c_size : [0x%0x] \n", CSDReg->C_SIZELow2 | CSDReg->C_SIZEHigh10<<2)); + DEBUG ((EFI_D_INFO, "vdd_r_curr_min : [0x%0x] \n", CSDReg->VDD_R_CURR_MIN)); + DEBUG ((EFI_D_INFO, "vdd_r_curr_max : [0x%0x] \n", CSDReg->VDD_R_CURR_MAX)); + DEBUG ((EFI_D_INFO, "vdd_w_curr_min : [0x%0x] \n", CSDReg->VDD_W_CURR_MIN)); + DEBUG ((EFI_D_INFO, "vdd_w_curr_max : [0x%0x] \n", CSDReg->VDD_W_CURR_MAX)); + DEBUG ((EFI_D_INFO, "c_size_mult : [0x%0x] \n", CSDReg->C_SIZE_MULT)); + DEBUG ((EFI_D_INFO, "erase_grp_size : [0x%0x] \n", CSDReg->ERASE_GRP_SIZE)); + DEBUG ((EFI_D_INFO, "erase_grp_mult : [0x%0x] \n", CSDReg->ERASE_GRP_MULT)); + DEBUG ((EFI_D_INFO, "wp_grp_size : [0x%0x] \n", CSDReg->WP_GRP_SIZE)); + DEBUG ((EFI_D_INFO, "wp_grp_enable : [0x%0x] \n", CSDReg->WP_GRP_ENABLE)); + DEBUG ((EFI_D_INFO, "default_ecc : [0x%0x] \n", CSDReg->DEFAULT_ECC)); + DEBUG ((EFI_D_INFO, "r2w_factor : [0x%0x] \n", CSDReg->R2W_FACTOR)); + DEBUG ((EFI_D_INFO, "write_bl_len : [0x%0x] \n", CSDReg->WRITE_BL_LEN)); + DEBUG ((EFI_D_INFO, "write_partial : [0x%0x] \n", CSDReg->WRITE_BL_PARTIAL)); + DEBUG ((EFI_D_INFO, "reserve0 : [0x%0x] \n", CSDReg->Reserved0)); + DEBUG ((EFI_D_INFO, "content_prot_app : [0x%0x] \n", CSDReg->CONTENT_PROT_APP)); + DEBUG ((EFI_D_INFO, "file_format_grp : [0x%0x] \n", CSDReg->FILE_FORMAT_GRP)); + DEBUG ((EFI_D_INFO, "copy : [0x%0x] \n", CSDReg->COPY)); + DEBUG ((EFI_D_INFO, "perm_write_protect: [0x%0x] \n", CSDReg->PERM_WRITE_PROTECT)); + DEBUG ((EFI_D_INFO, "tmp_write_prot : [0x%0x] \n", CSDReg->TMP_WRITE_PROTECT)); + DEBUG ((EFI_D_INFO, "file_format : [0x%0x] \n", CSDReg->FILE_FORMAT)); + DEBUG ((EFI_D_INFO, "ecc : [0x%0x] \n", CSDReg->ECC)); + DEBUG ((EFI_D_INFO, "==================================================\n")); + + return 0; +} + + +/** + Dump Mmc Decode Ext CSD value + + @param[in] ExtCSDReg Pointer to ExtCSDReg + + @retval None + +**/ +EFI_STATUS +MmcDecodeExtCSD ( + IN EXT_CSD *ExtCSDReg + ) +{ + DEBUG ((EFI_D_INFO, "\n==========DECODE MMC EXT CSD REGISTER==================\n")); + DEBUG ((EFI_D_INFO, " SUPPORTED_CMD_SETS = 0x%X\n", ExtCSDReg->CMD_SET)); + DEBUG ((EFI_D_INFO, " HPI_FEATURES = 0x%X\n", ExtCSDReg->HPI_FEATURES)); + DEBUG ((EFI_D_INFO, " BKOPS_SUPPORT = 0x%X\n", ExtCSDReg->BKOPS_SUPPORT)); + DEBUG ((EFI_D_INFO, " BKOPS_STATUS = 0x%X\n", ExtCSDReg->BKOPS_STATUS)); + DEBUG ((EFI_D_INFO, " CORRECTLY_PRG_SECTORS_NUM = 0x%X%X%X%X\n", ExtCSDReg->CORRECTLY_PRG_SECTORS_NUM[3], \ + ExtCSDReg->CORRECTLY_PRG_SECTORS_NUM[2], ExtCSDReg->CORRECTLY_PRG_SECTORS_NUM[1], ExtCSDReg->CORRECTLY_PRG_SECTORS_NUM[0])); + DEBUG ((EFI_D_INFO, " INI_TIMEOUT_AP = 0x%X\n", ExtCSDReg->INI_TIMEOUT_AP)); + DEBUG ((EFI_D_INFO, " PWR_CL_DDR_52_195 = 0x%X\n", ExtCSDReg->PWR_CL_DDR_52_195)); + DEBUG ((EFI_D_INFO, " PWR_CL_DDR_52_360 = 0x%X\n", ExtCSDReg->PWR_CL_DDR_52_360)); + DEBUG ((EFI_D_INFO, " MIN_PRF_DDR_W_8_52 = 0x%X\n", ExtCSDReg->MIN_PERF_DDR_W_8_52)); + DEBUG ((EFI_D_INFO, " MIN_PRF_DDR_R_8_52 = 0x%X\n", ExtCSDReg->MIN_PERF_DDR_R_8_52)); + DEBUG ((EFI_D_INFO, " TRIM_MULT = 0x%X\n", ExtCSDReg->TRIM_MULT)); + DEBUG ((EFI_D_INFO, " SEC_FEATURE_SUPP = 0x%X\n", ExtCSDReg->SEC_FEATURE_SUPPORT)); + DEBUG ((EFI_D_INFO, " SEC_ERASE_MULT = 0x%X\n", ExtCSDReg->SEC_ERASE_MULT)); + DEBUG ((EFI_D_INFO, " SEC_TRIM_MULT = 0x%X\n", ExtCSDReg->SEC_TRIM_MULT)); + DEBUG ((EFI_D_INFO, " BOOT_INFO = 0x%X\n", ExtCSDReg->BOOT_INFO)); + DEBUG ((EFI_D_INFO, " BOOT_PART_SIZE = 0x%X\n", ExtCSDReg->BOOT_SIZE_MULTI)); + DEBUG ((EFI_D_INFO, " ACCESS_SIZE = 0x%X\n", ExtCSDReg->ACC_SIZE)); + DEBUG ((EFI_D_INFO, " HI_CAP_ER_GRP_SIZE = 0x%X\n", ExtCSDReg->HC_ERASE_GRP_SIZE)); + DEBUG ((EFI_D_INFO, " HI_CAP_ER_TIMEOUT = 0x%X\n", ExtCSDReg->ERASE_TIMEOUT_MULT)); + DEBUG ((EFI_D_INFO, " REL_WR_SECTOR_CNT = 0x%X\n", ExtCSDReg->REL_WR_SEC_C)); + DEBUG ((EFI_D_INFO, " HI_CAP_WP_GRP_SIZE = 0x%X\n", ExtCSDReg->HC_WP_GRP_SIZE)); + DEBUG ((EFI_D_INFO, " SLEEP_CURRENT_VCC = 0x%X\n", ExtCSDReg->S_C_VCC)); + DEBUG ((EFI_D_INFO, " SLEEP_CURRENT_VCCQ = 0x%X\n", ExtCSDReg->S_C_VCCQ)); + DEBUG ((EFI_D_INFO, " SLP_AWK_TIMEOUT = 0x%X\n", ExtCSDReg->S_A_TIMEOUT)); + DEBUG ((EFI_D_INFO, " SECTOR_COUNT = 0x%X\n", *(UINT32*) ((UINT8 *) &ExtCSDReg->SEC_COUNT))); + DEBUG ((EFI_D_INFO, " MIN_PERF_W_8_52 = 0x%X\n", ExtCSDReg->MIN_PERF_W_8_52)); + DEBUG ((EFI_D_INFO, " MIN_PERF_R_8_52 = 0x%X\n", ExtCSDReg->MIN_PERF_R_8_52)); + DEBUG ((EFI_D_INFO, " MIN_PERF_W_8_26_4_52 = 0x%X\n", ExtCSDReg->MIN_PERF_W_8_26_4_52)); + DEBUG ((EFI_D_INFO, " MIN_PERF_W_8_26_4_52 = 0x%X\n", ExtCSDReg->MIN_PERF_W_8_26_4_52)); + DEBUG ((EFI_D_INFO, " MIN_PERF_W_4_26 = 0x%X\n", ExtCSDReg->MIN_PERF_W_4_26)); + DEBUG ((EFI_D_INFO, " MIN_PERF_R_4_26 = 0x%X\n", ExtCSDReg->MIN_PERF_R_4_26)); + DEBUG ((EFI_D_INFO, " PWR_CLASS_26_360 = 0x%X\n", ExtCSDReg->PWR_CL_26_360)); + DEBUG ((EFI_D_INFO, " PWR_CLASS_52_360 = 0x%X\n", ExtCSDReg->PWR_CL_52_360)); + DEBUG ((EFI_D_INFO, " PWR_CLASS_26_195 = 0x%X\n", ExtCSDReg->PWR_CL_26_195)); + DEBUG ((EFI_D_INFO, " PWR_CLASS_52_195 = 0x%X\n", ExtCSDReg->PWR_CL_52_195)); + DEBUG ((EFI_D_INFO, " PARTITION_SWITCH_TIME = 0x%X\n", ExtCSDReg->PARTITION_SWITCH_TIME)); + DEBUG ((EFI_D_INFO, " OUT_OF_INTERRUPT_TIME = 0x%X\n", ExtCSDReg->OUT_OF_INTERRUPT_TIME)); + DEBUG ((EFI_D_INFO, " CARD_TYPE = 0x%X\n", ExtCSDReg->CARD_TYPE)); + DEBUG ((EFI_D_INFO, " CSD_STRUCTURE = 0x%X\n", ExtCSDReg->CSD_STRUCTURE)); + DEBUG ((EFI_D_INFO, " EXT_CSD_REV = 0x%X\n", ExtCSDReg->EXT_CSD_REV)); + DEBUG ((EFI_D_INFO, " CMD_SET = 0x%X\n", ExtCSDReg->CMD_SET)); + DEBUG ((EFI_D_INFO, " CMD_SET_REV = 0x%X\n", ExtCSDReg->CMD_SET_REV)); + DEBUG ((EFI_D_INFO, " PWR_CLASS = 0x%X\n", ExtCSDReg->POWER_CLASS)); + DEBUG ((EFI_D_INFO, " HI_SPEED_TIMING = 0x%X\n", ExtCSDReg->HS_TIMING)); + DEBUG ((EFI_D_INFO, " BUS_WIDTH_MODE = 0x%X\n", ExtCSDReg->BUS_WIDTH)); + DEBUG ((EFI_D_INFO, " ERASED_MEM_CONTENT = 0x%X\n", ExtCSDReg->ERASED_MEM_CONT)); + DEBUG ((EFI_D_INFO, " PARTITION_CONFIG = 0x%X\n", ExtCSDReg->PARTITION_CONFIG)); + DEBUG ((EFI_D_INFO, " BOOT_CONFIG_PROT = 0x%X\n", ExtCSDReg->BOOT_CONFIG_PROT)); + DEBUG ((EFI_D_INFO, " BOOT_BUS_WIDTH = 0x%X\n", ExtCSDReg->BOOT_BUS_WIDTH)); + DEBUG ((EFI_D_INFO, " HI_DEN_ER_GRP_DEF = 0x%X\n", ExtCSDReg->ERASE_GROUP_DEF)); + DEBUG ((EFI_D_INFO, " BOOT_WP = 0x%X\n", ExtCSDReg->BOOT_WP)); + DEBUG ((EFI_D_INFO, " USER_WP = 0x%X\n", ExtCSDReg->USER_WP)); + DEBUG ((EFI_D_INFO, " FW_CONFIG = 0x%X\n", ExtCSDReg->FW_CONFIG)); + DEBUG ((EFI_D_INFO, " RPMB_SIZE_MULT = 0x%X\n", ExtCSDReg->RPMB_SIZE_MULT)); + DEBUG ((EFI_D_INFO, " RST_N_FUNCTION = 0x%X\n", ExtCSDReg->RST_n_FUNCTION)); + DEBUG ((EFI_D_INFO, " PARTITIONING_SUPP = 0x%X\n", ExtCSDReg->PARTITIONING_SUPPORT)); + DEBUG ((EFI_D_INFO, " MAX_ENH_SIZE_MULT = 0x%02X%02X%02X\n", ExtCSDReg->MAX_ENH_SIZE_MULT[2],ExtCSDReg->MAX_ENH_SIZE_MULT[1], ExtCSDReg->MAX_ENH_SIZE_MULT[0])); + DEBUG ((EFI_D_INFO, " PART_ATTRIBUTE = 0x%X\n", ExtCSDReg->PARTITIONS_ATTRIBUTES)); + DEBUG ((EFI_D_INFO, " PART_SETTING_COMP = 0x%X\n", ExtCSDReg->PARTITION_SETTING_COMPLETED)); + DEBUG ((EFI_D_INFO, " GP_SIZE_MULT = 0x%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", ExtCSDReg->GP_SIZE_MULT_4[2], ExtCSDReg->GP_SIZE_MULT_4[1], ExtCSDReg->GP_SIZE_MULT_4[0], + ExtCSDReg->GP_SIZE_MULT_3[2], ExtCSDReg->GP_SIZE_MULT_3[1], ExtCSDReg->GP_SIZE_MULT_3[0], + ExtCSDReg->GP_SIZE_MULT_2[2], ExtCSDReg->GP_SIZE_MULT_2[1], ExtCSDReg->GP_SIZE_MULT_2[0], + ExtCSDReg->GP_SIZE_MULT_1[2], ExtCSDReg->GP_SIZE_MULT_1[1], ExtCSDReg->GP_SIZE_MULT_1[0])); + DEBUG ((EFI_D_INFO, " ENH_SIZE_MULT = 0x%02X%02X%02X\n", ExtCSDReg->ENH_SIZE_MULT[2], ExtCSDReg->ENH_SIZE_MULT[1], ExtCSDReg->ENH_SIZE_MULT[0])); + DEBUG ((EFI_D_INFO, " ENH_START_ADDR = 0x%02X%02X%02X%02X\n", ExtCSDReg->ENH_START_ADDR[3], ExtCSDReg->ENH_START_ADDR[2], ExtCSDReg->ENH_START_ADDR[1], ExtCSDReg->ENH_START_ADDR[0])); + DEBUG ((EFI_D_INFO, " SEC_BAD_BLK_MGMNT = 0x%X\n", ExtCSDReg->SEC_BAD_BLOCK_MGMNT)); + DEBUG ((EFI_D_INFO, "==================================================\n")); + + return 0; +} + + +/** + Send the card FAST_IO command + + @param[in] CardData Pointer to CARD_DATA + @param[in] RegisterAddress Register Address + @param[in, out] RegisterData Pointer to register Data + @param[in] Write TRUE for write, FALSE for read + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +EFI_STATUS +FastIO ( + IN CARD_DATA *CardData, + IN UINT8 RegisterAddress, + IN OUT UINT8 *RegisterData, + IN BOOLEAN Write + ) +{ + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + EFI_STATUS Status; + UINT32 Argument; + UINT32 Data; + + Status = EFI_SUCCESS; + MmcHostIo = CardData->MmcHostIo; + + if (RegisterData == NULL) { + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + Argument = (CardData->Address << 16) | (RegisterAddress << 8); + if (Write) { + Argument |= BIT15 | (*RegisterData); + } + + Status = SendCommand ( + MmcHostIo, + FAST_IO, + Argument, + NoData, + NULL, + 0, + ResponseR4, + TIMEOUT_COMMAND, + &Data + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + + if ((Data & BIT15) == 0) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + if (!Write) { + *RegisterData = (UINT8)Data; + } + +Exit: + return Status; +} + + +/** + Send the card GO_INACTIVE_STATE command + + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +PutCardInactive ( + IN CARD_DATA *CardData + ) +{ + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + EFI_STATUS Status; + + MmcHostIo = CardData->MmcHostIo; + + Status = SendCommand ( + MmcHostIo, + GO_INACTIVE_STATE, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseNo, + TIMEOUT_COMMAND, + NULL + ); + + gBS->Stall(1000); + + return Status; +} + + +/** + Get card interested information for CSD rergister + + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +CalculateCardParameter ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + UINT32 Frequency; + UINT32 Multiple; + UINT32 CSize; + CSD_SDV2 *CsdSDV2; + + Status = EFI_SUCCESS; + + switch (CardData->CSDRegister.TRAN_SPEED & 0x7) { + case 0: + Frequency = 100 * 1000; + break; + + case 1: + Frequency = 1 * 1000 * 1000; + break; + + case 2: + Frequency = 10 * 1000 * 1000; + break; + + case 3: + Frequency = 100 * 1000 * 1000; + break; + + default: + DEBUG ((EFI_D_ERROR, "Invalid CSD TRAN_SPEED Frequency: 0x%x\n", CardData->CSDRegister.TRAN_SPEED & 0x7)); + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + switch ((CardData->CSDRegister.TRAN_SPEED >> 3) & 0xF) { + case 1: + Multiple = 10; + break; + + case 2: + Multiple = 12; + break; + + case 3: + Multiple = 13; + break; + + case 4: + Multiple = 15; + break; + + case 5: + Multiple = 20; + break; + + case 6: + if (CardData->CardType == MMCCard) { + Multiple = 26; + } else { + Multiple = 25; + } + break; + + case 7: + Multiple = 30; + break; + + case 8: + Multiple = 35; + break; + + case 9: + Multiple = 40; + break; + + case 10: + Multiple = 45; + break; + + case 11: + if (CardData->CardType == MMCCard) { + Multiple = 52; + } else { + Multiple = 50; + } + break; + + case 12: + Multiple = 55; + break; + + case 13: + Multiple = 60; + break; + + case 14: + Multiple = 70; + break; + + case 15: + Multiple = 80; + break; + + default: + DEBUG ((EFI_D_ERROR, "CalculateCardParameter: Invalid CSD TRAN_SPEED Multiple: 0x%x\n", CardData->CSDRegister.TRAN_SPEED >> 3)); + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + Frequency = Frequency * Multiple / 10; + CardData->MaxFrequency = Frequency; + + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2) || + (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) { + CardData->BlockLen = 512; + } else { + CardData->BlockLen = 1 << CardData->CSDRegister.READ_BL_LEN; + } + + if (CardData->CardType == SdMemoryCard2High) { + ASSERT(CardData->CSDRegister.CSD_STRUCTURE == 1); + CsdSDV2 = (CSD_SDV2 *) &CardData->CSDRegister; + // + // the K here means 1024 not 1000 + // + CardData->BlockNumber = DivU64x32 (MultU64x32 (CsdSDV2->C_SIZE + 1, 512 * 1024) , CardData->BlockLen); + } else { + // + // For MMC card > 2G, the block number will be recaculate later + // + CSize = CardData->CSDRegister.C_SIZELow2 | (CardData->CSDRegister.C_SIZEHigh10 << 2); + CardData->BlockNumber = MultU64x32 (LShiftU64 (1, CardData->CSDRegister.C_SIZE_MULT + 2), CSize + 1); + } + + // + //For >= 2G card, BlockLen may be 1024, but the transfer size is still 512 bytes + // + if (CardData->BlockLen > 512) { + CardData->BlockNumber = DivU64x32 (MultU64x32 (CardData->BlockNumber, CardData->BlockLen), 512); + CardData->BlockLen = 512; + } + + DEBUG ((DEBUG_INFO, "CalculateCardParameter: Card Size: 0x%lx\n", MultU64x32 (CardData->BlockNumber, CardData->BlockLen) + )); + +Exit: + return Status; +} + + +/** + Test the bus width setting for MMC card + It is used only for verification purpose + + @param[in] CardData Pointer to CARD_DATA + @param[in] Width 1, 4, 8 bits + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MMCCardBusWidthTest ( + IN CARD_DATA *CardData, + IN UINT32 Width + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + UINT64 Data; + UINT64 Value; + + if (CardData == NULL) { + ASSERT(CardData != NULL); + return EFI_INVALID_PARAMETER; + } + + MmcHostIo = CardData->MmcHostIo; + Value = 0; + + switch (Width) { + case 1: + Data = 0x80; + break; + + case 4: + Data = 0x5A; + break; + + case 8: + Data = 0xAA55; + break; + + default: + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + CopyMem (CardData->AlignedBuffer, &Data, Width); + Status = SendCommand ( + MmcHostIo, + BUSTEST_W, + 0, + OutData, + CardData->AlignedBuffer, + Width, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + + Data = 0; + gBS->Stall(10000); + + Status = SendCommand ( + MmcHostIo, + BUSTEST_R, + 0, + InData, + CardData->AlignedBuffer, + Width, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + CopyMem (&Data, CardData->AlignedBuffer, Width); + + switch (Width) { + case 1: + Value = (~(Data ^ 0x80)) & 0xC0; + break; + case 4: + Value = (~(Data ^ 0x5A)) & 0xFF; + break; + case 8: + Value = (~(Data ^ 0xAA55)) & 0xFFFF; + break; + } + + if (Value == 0) { + Status = EFI_SUCCESS; + } else { + Status = EFI_UNSUPPORTED; + } + +Exit: + return Status; +} + + +/** + This function can detect these card types + 1. MMC card + 2. SD 1.1 card + 3. SD 2.0 standard card + 3. SD 2.0 high capacity card + + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +GetCardType ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + UINT32 TimeOut=5000; + MmcHostIo = CardData->MmcHostIo; + + CardData->CardType = MMCCard; + MmcHostIo->SetupDevice (MmcHostIo); + + // + // To bring back the normal MMC card to work + // after sending the SD command. Otherwise some + // card could not work + // + Status = SendCommand ( + MmcHostIo, + GO_IDLE_STATE, + 0, + NoData, + NULL, + 0, + ResponseNo, + TIMEOUT_COMMAND, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status)); + } + + DEBUG (( DEBUG_INFO, "Sending first CMD1.\n")); + + // + // CE-ATA device needs long delay + // + gBS->Stall (1 * 1000); + + // + // Get OCR register to check voltage support, first time the OCR is 0 + // + DEBUG (( DEBUG_INFO, "Sending first CMD1 with 0 .\n")); + Status = SendCommand ( + MmcHostIo, + SEND_OP_COND, + 0x0, + NoData, + NULL, + 0, + ResponseR3, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->OCRRegister) + ); + + DEBUG ((DEBUG_INFO, "Check OCR register for busy 0x%x\n", *((UINT32 *) &CardData->OCRRegister ))); + + gBS->Stall (1 * 1000); + + while (CardData->OCRRegister.Busy != 1) { + CardData->OCRRegister.AccessMode = 2; + Status = SendCommand ( + MmcHostIo, + SEND_OP_COND, + *(UINT32 *) &(CardData->OCRRegister), + NoData, + NULL, + 0, + ResponseR3, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->OCRRegister) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status)); + goto Exit; + } + + gBS->Stall (1 * 1000); + TimeOut--; + if (TimeOut == 0) { + DEBUG ((EFI_D_ERROR, "Card is always in busy state\n")); + Status = EFI_TIMEOUT; + goto Exit; + } + } + +Exit: + return Status; +} + + +/** + MMC card high/low voltage selection function + + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + @retval EFI_BAD_BUFFER_SIZE + +**/ +EFI_STATUS +MMCCardVoltageSelection ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + UINT8 Index; + UINT8 Retry; + UINT32 TimeOut; + + MmcHostIo = CardData->MmcHostIo; + Status = EFI_SUCCESS; + + if (FALSE) { + // + //First try the high voltage, then if supported choose the low voltage + // + for (Index = 0; Index < 2; Index++) { + for (Retry = 0; Retry < 3; Retry++) { + // + // To bring back the normal MMC card to work + // after sending the SD command. Otherwise some + // card could not work + // + Status = SendCommand ( + MmcHostIo, + GO_IDLE_STATE, + 0, + NoData, + NULL, + 0, + ResponseNo, + TIMEOUT_COMMAND, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status)); + continue; + } + // + //CE-ATA device needs long delay + // + gBS->Stall ((Retry + 1) * 50 * 1000); + + // + //Get OCR register to check voltage support, first time the OCR is 0 + // + Status = SendCommand ( + MmcHostIo, + SEND_OP_COND, + 0, + NoData, + NULL, + 0, + ResponseR3, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->OCRRegister) + ); + + if (!EFI_ERROR (Status)) { + break; + } + } + + if (Retry == 3) { + DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status)); + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + if (CardData->OCRRegister.V170_V195 == 1) { + CardData->DualVoltage = TRUE; + } + if (CardData->OCRRegister.V270_V360 != 0x1F && + CardData->OCRRegister.V200_V260 != 0) { + DEBUG ((EFI_D_ERROR, "Incompatiable voltage device\n")); + PutCardInactive (CardData); + Status = EFI_INCOMPATIBLE_VERSION; + goto Exit; + } + + if (Index == 0) { + // + // Choose the high voltage first + // + CardData->OCRRegister.V170_V195 = 0; + } else { + // + // Choose the low voltage + // + CardData->OCRRegister.V170_V195 = 1; + CardData->OCRRegister.V270_V360 = 0; + } + + // + // Set sector mode + // + CardData->OCRRegister.AccessMode |= 2; + + // + // TimeOut Value, 5000 * 100 * 1000 = 5 s + // + TimeOut = 5000; + + do { + Status = SendCommand ( + MmcHostIo, + SEND_OP_COND, + *(UINT32 *) &(CardData->OCRRegister), + NoData, + NULL, + 0, + ResponseR3, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->OCRRegister) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status)); + goto Exit; + } + + gBS->Stall (1 * 1000); + TimeOut--; + if (TimeOut == 0) { + DEBUG ((EFI_D_ERROR, "Card is always in busy state\n")); + Status = EFI_TIMEOUT; + goto Exit; + } + } while (CardData->OCRRegister.Busy != 1); + + if (CardData->DualVoltage == TRUE && MmcHostIo->HostCapability.V18Support == TRUE) { + // + //Power Off the card and then power on into low voltage + // + MmcHostIo->SetHostVoltage (MmcHostIo, 0); + gBS->Stall (1 * 1000); + MmcHostIo->SetHostVoltage (MmcHostIo, 18); + } else { + // + //Not support the low voltage, exit + // + break; + } + } + } + +Exit: + return Status; +} + + +/** + This function set the bus and device width for MMC card + + @param[in] CardData Pointer to CARD_DATA + @param[in] BusWidth 1, 4, 8 bits + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MMCCardSetBusWidth ( + IN CARD_DATA *CardData, + IN UINT8 BusWidth + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + SWITCH_ARGUMENT SwitchArgument; + UINT8 Value; + + MmcHostIo = CardData->MmcHostIo; + Value = 0; + switch (BusWidth) { + case 28: //20 in 28 indicates DDR in 8 bit bus + Value = 6; + break; + + case 24: //20 in 24 indicates DDR in 4 bit bus + Value = 5; + break; + + case 8: + Value = 2; + break; + + case 4: + Value = 1; + break; + + case 1: + Value = 0; + break; + + default: + ASSERT (0); + } + + // + // HS_TIMING must be set to 0x1 before setting BUS_WIDTH for dual data rate operation (values 5 or 6) + // + if (Value == 5 || Value == 6 ) { + ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT)); + SwitchArgument.CmdSet = 0; + SwitchArgument.Value = 0x1; + SwitchArgument.Index = (UINT32) ((UINTN) + (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN) (&(CardData->ExtCSDRegister))); + SwitchArgument.Access = WriteByte_Mode; + Status = SendCommand ( + MmcHostIo, + SWITCH, + *(UINT32 *) &SwitchArgument, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + Status = SendCommand ( + MmcHostIo, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + } else { + DEBUG ((DEBUG_ERROR, "SWITCH Fail in HS Timing setting\n")); + } + } + + ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT)); + SwitchArgument.CmdSet = 0; + SwitchArgument.Value = Value; + SwitchArgument.Index = (UINT32) ((UINTN) + (&(CardData->ExtCSDRegister.BUS_WIDTH)) - (UINTN) (&(CardData->ExtCSDRegister))); + SwitchArgument.Access = WriteByte_Mode; + Status = SendCommand ( + MmcHostIo, + SWITCH, + *(UINT32 *) &SwitchArgument, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + Status = SendCommand ( + MmcHostIo, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SWITCH %d bits Fail\n", BusWidth)); + goto Exit; + } else { + if ((BusWidth == 24) || (BusWidth == 28)) { + Status = MmcHostIo->SetBusWidth (MmcHostIo, BusWidth - 20); + } else { + Status = MmcHostIo->SetBusWidth (MmcHostIo, BusWidth); + } + if (EFI_ERROR (Status)) { + goto Exit; + } + + gBS->Stall (5 * 1000); + } + } + if ((BusWidth == 24) || (BusWidth == 28)) { + goto Exit; + } else { + Status = MMCCardBusWidthTest (CardData, BusWidth); + } + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCCardBusWidthTest %d bit Fail\n", BusWidth)); + goto Exit; + } + + CardData->CurrentBusWidth = BusWidth; + +Exit: + return Status; +} + + +/** + MMC/SD card init function + + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + @retval EFI_BAD_BUFFER_SIZE + +**/ +EFI_STATUS +MMCSDCardInit ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + SWITCH_ARGUMENT SwitchArgument; + UINT32 Data; + UINT32 Argument; + UINT32 HsTimingValue; + UINT8 PowerValue; + UINT8 DoubleSpeed; + UINTN Offset; + + if (CardData == NULL) { + ASSERT (CardData != NULL); + return EFI_INVALID_PARAMETER; + } + MmcHostIo = CardData->MmcHostIo; + CardData->CurrentBusWidth = 1; + + Status = GetCardType (CardData); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "GetCardType -> %r\n", Status)); + goto Exit; + } + + ASSERT (CardData->CardType != UnknownCard); + // + //MMC, SD card need host auto stop command support + // + MmcHostIo->EnableAutoStopCmd (MmcHostIo, TRUE); + + + // + // Get CID Register, but the info is not used currently + // + Status = SendCommand ( + MmcHostIo, + ALL_SEND_CID, + 0, + NoData, + NULL, + 0, + ResponseR2, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CIDRegister) + ); + + PcdSet8S (PcdEmmcManufacturerId, CardData->CIDRegister.MID); + PcdSet32S (PcdProductSerialNumber, CardData->CIDRegister.PSN); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "ALL_SEND_CID -> %r\n", Status)); + goto Exit; + } + + // + //SET_RELATIVE_ADDR + // + if (CardData->CardType == MMCCard) { + CardData->Address = 1; + // + // Set RCA Register + // + Status = SendCommand ( + MmcHostIo, + SET_RELATIVE_ADDR, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_RELATIVE_ADDR -> %r\n", Status)); + goto Exit; + } + } + + // + // Get CSD Register + // + Status = SendCommand ( + MmcHostIo, + SEND_CSD, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR2, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CSDRegister) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SEND_CSD -> %r\n", Status)); + goto Exit; + } + + MmcDecodeCSD(&CardData->CSDRegister); + + Status = CalculateCardParameter (CardData); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "CalculateCardParameter -> %r\n", Status)); + goto Exit; + } + + // + // Put the card into tran state + // + Status = SendCommand ( + MmcHostIo, + SELECT_DESELECT_CARD, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SELECT_DESELECT_CARD -> %r\n", Status)); + goto Exit; + } + + Status = SendCommand ( + MmcHostIo, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SELECT_DESELECT_CARD SEND_STATUS Fail Status = 0x%x\n", Status)); + goto Exit; + } + + if (CardData->CardType == MMCCard) { + // + // Only V4.0 and above supports more than 1 bits and high speed + // + if (CardData->CSDRegister.SPEC_VERS >= 4) { + Offset = OFFSET_OF (EXT_CSD, ERASE_GROUP_DEF); + Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, 0x01); + // + // Get ExtCSDRegister + // + Status = SendCommand ( + MmcHostIo, + SEND_EXT_CSD, + 0, + InData, + CardData->AlignedBuffer, + sizeof (EXT_CSD), + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SEND_EXT_CSD -> %r\n", Status)); + goto Exit; + } + + CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof (EXT_CSD)); + + MmcDecodeExtCSD (&CardData->ExtCSDRegister); + + // + // Recaculate the block number for >2G MMC card + // + Data = (CardData->ExtCSDRegister.SEC_COUNT[0]) | + (CardData->ExtCSDRegister.SEC_COUNT[1] << 8) | + (CardData->ExtCSDRegister.SEC_COUNT[2] << 16) | + (CardData->ExtCSDRegister.SEC_COUNT[3] << 24); + + if (Data != 0) { + CardData->BlockNumber = Data; + } + DEBUG ((DEBUG_INFO, "CardData->BlockNumber %d\n", Data)); + + // + // Check the DDR setting + // + DoubleSpeed = 0 ; + DEBUG ((DEBUG_INFO, "CardData->ExtCSDRegister.CARD_TYPE -> %d\n", (UINTN) CardData->ExtCSDRegister.CARD_TYPE)); + if (CardData->ExtCSDRegister.CARD_TYPE & BIT0) { + DEBUG ((DEBUG_INFO, "High-Speed e MMC @ 26MHz - at rated device voltage(s) supported\n")); + } + if (CardData->ExtCSDRegister.CARD_TYPE & BIT1) { + DEBUG ((DEBUG_INFO, "High-Speed e MMC @ 52MHz - at rated device voltage(s) supported\n")); + } + if (CardData->ExtCSDRegister.CARD_TYPE & BIT2) { + DEBUG ((DEBUG_INFO, "High-Speed Dual Data Rate e MMC @ 52MHz - 1.8V or 3V I/O supported\n")); + } + if (CardData->ExtCSDRegister.CARD_TYPE & BIT3) { + DEBUG ((DEBUG_INFO, "High-Speed Dual Data Rate e MMC @ 52MHz - 1.2V I/O supported\n")); + } + if (CardData->ExtCSDRegister.CARD_TYPE & BIT4) { + DEBUG ((DEBUG_INFO, "HS200 Single Data Rate e MMC @ 200 MHz - 1.8V I/O supported\n")); + } + if (CardData->ExtCSDRegister.CARD_TYPE & BIT5) { + DEBUG ((DEBUG_INFO, "HS200 Single Data Rate e MMC @ 200 MHz - 1.2V I/O supported\n")); + } + if (CardData->ExtCSDRegister.CARD_TYPE & BIT6) { + DEBUG ((DEBUG_INFO, "HS400 Dual Data Rate e MMC @ 200MHz - 1.8V I/O supported\n")); + } + if (CardData->ExtCSDRegister.CARD_TYPE & BIT7) { + DEBUG ((DEBUG_INFO, "HS400 Dual Data Rate e MMC @ 200MHz - 1.2V I/O supported\n")); + } + + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2) || (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) { + DEBUG ((DEBUG_INFO, "Card support DDR\n")); + DoubleSpeed = 20; //Add 20 for double speed, decoded in MMCCardSetBusWidth() + } + + DEBUG ((EFI_D_INFO, "%a(%d): %a() no more FPGA doublespeed workaround needed\n", __FILE__, __LINE__, __FUNCTION__)); + + if (MmcHostIo->HostCapability.HighSpeedSupport) { + + HsTimingValue = 1; + + // + // Change to high frequency mode + // + ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT)); + SwitchArgument.CmdSet = 0; + SwitchArgument.Value = HsTimingValue; + SwitchArgument.Index = (UINT32) ((UINTN) + (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN) (&(CardData->ExtCSDRegister))); + SwitchArgument.Access = WriteByte_Mode; + Status = SendCommand ( + CardData->MmcHostIo, + SWITCH, + *(UINT32 *) &SwitchArgument, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SWITCH frequency -> %r\n", Status)); + } + + if (!EFI_ERROR (Status)) { + Status = SendCommand ( + MmcHostIo, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + // + // Enable the high speed mode + // + if (DoubleSpeed != 0) { + Status = MmcHostIo->SetHostDdrMode (MmcHostIo, TRUE); + DEBUG ((DEBUG_INFO, "Set to DDR50 mode \n", Status)); + } else { + Status = MmcHostIo->SetHostSpeedMode (MmcHostIo, 1); + DEBUG ((DEBUG_ERROR, "Set to HS mode \n", Status)); + } + + if (EFI_ERROR (Status)) { + goto Exit; + } + // + // Change host clock + // + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { + Status = MmcHostIo->SetClockFrequency (MmcHostIo, FREQUENCY_MMC_PP_HIGH); + } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { + Status = MmcHostIo->SetClockFrequency (MmcHostIo, FREQUENCY_MMC_PP); + } else { + Status = EFI_UNSUPPORTED; + } + + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // It seems no need to stall after changing bus freqeuncy. + // It is said that the freqeuncy can be changed at any time. Just appends 8 clocks after command. + // But SetClock alreay has delay. + // + } + } + } + + // + // Prefer wide bus width for performance + // + // + // Set to BusWidth bits mode, only version 4.0 or above support more than 1 bits + // + if (MmcHostIo->HostCapability.BusWidth8 == 1) { + Status = MMCCardSetBusWidth (CardData, DoubleSpeed + 8); + if (EFI_ERROR (Status)) { + // + // CE-ATA may support 8 bits and 4 bits, but has no software method for detection + // + Status = MMCCardSetBusWidth (CardData, DoubleSpeed + 4); + if (EFI_ERROR (Status)) { + goto Exit; + } + } + } else if (MmcHostIo->HostCapability.BusWidth4 == 1) { + Status = MMCCardSetBusWidth (CardData, DoubleSpeed + 4); + if (EFI_ERROR (Status)) { + goto Exit; + } + } + + PowerValue = 0; + + if (CardData->CurrentBusWidth == 8) { + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { + PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360; + PowerValue = PowerValue >> 4; + } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { + PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360; + PowerValue = PowerValue >> 4; + } + } else if (CardData->CurrentBusWidth == 4) { + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { + PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360; + PowerValue = PowerValue & 0xF; + } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { + PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360; + PowerValue = PowerValue & 0xF; + } + } + + if (PowerValue != 0) { + // + // Update Power Class + // + ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT)); + SwitchArgument.CmdSet = 0; + SwitchArgument.Value = PowerValue; + SwitchArgument.Index = (UINT32) ((UINTN) + (&(CardData->ExtCSDRegister.POWER_CLASS)) - (UINTN) (&(CardData->ExtCSDRegister))); + SwitchArgument.Access = WriteByte_Mode; + Status = SendCommand ( + MmcHostIo, + SWITCH, + *(UINT32 *) &SwitchArgument, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + Status = SendCommand ( + MmcHostIo, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SWITCH Power Class -> %r\n", Status)); + } + + } + } + } else { + DEBUG ((EFI_D_ERROR, "MMC Card version %d only supportes 1 bits at lower transfer speed\n", CardData->CSDRegister.SPEC_VERS)); + } + + // + // Register for Ready to Boot event to enable Write protection + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + SetEmmcWpOnEvent, + CardData, + &gEfiEventReadyToBootGuid, + &mSetEmmcWpOnEvent + ); + + } else { + // + // Pin 1, at power up this line has a 50KOhm pull up enabled in the card. + // This pull-up should be disconnected by the user, during regular data transfer, + // with SET_CLR_CARD_DETECT (ACMD42) command + // + Status = SendAppCommand ( + CardData, + SET_CLR_CARD_DETECT, + 0, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_CLR_CARD_DETECT Fail -> %r\n", Status)); + goto Exit; + } + + // + // Set Bus Width to 4 + // + Status = SendAppCommand ( + CardData, + SET_BUS_WIDTH, + SD_BUS_WIDTH_4, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_BUS_WIDTH 4 bits -> %r\n", Status)); + goto Exit; + } + + Status = MmcHostIo->SetBusWidth (MmcHostIo, 4); + if (EFI_ERROR (Status)) { + goto Exit; + } + CardData->CurrentBusWidth = 4; + + if ((MmcHostIo->HostCapability.HighSpeedSupport == FALSE) || + ((CardData->CSDRegister.CCC & BIT10) != BIT10)) { + // + // Host must support high speed + // Card must support Switch function + // + goto Exit; + } + + // + // Mode = 0, group 1, function 1, check operation + // + Argument = 0xFFFF01; + ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS)); + + Status = SendCommand ( + MmcHostIo, + SWITCH_FUNC, + Argument, + InData, + CardData->AlignedBuffer, + sizeof (SWITCH_STATUS), + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS)); + + if ((CardData->SwitchStatus.DataStructureVersion == 0x0) || + ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) { + // + // 1. SD 1.1 card does not suppport busy bit + // 2. Ready state + // + // + // + // Mode = 1, group 1, function 1, BIT31 set means set mode + // + Argument = 0xFFFF01 | BIT31; + ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS)); + + Status = SendCommand ( + MmcHostIo, + SWITCH_FUNC, + Argument, + InData, + CardData->AlignedBuffer, + sizeof (SWITCH_STATUS), + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS)); + + if ((CardData->SwitchStatus.DataStructureVersion == 0x0) || + ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) { + // + // 1. SD 1.1 card does not suppport busy bit + // 2. Ready state + // + // + // 8 clocks, (1/ 25M) * 8 ==> 320 us, so 1ms > 0.32 ms + // + gBS->Stall (1000); + } + } + } + if (!((CardData->ExtCSDRegister.CARD_TYPE & BIT2) || + (CardData->ExtCSDRegister.CARD_TYPE & BIT3))) { + // + // Set Block Length, to improve compatibility in case of some cards + // + Status = SendCommand ( + MmcHostIo, + SET_BLOCKLEN, + 512, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_BLOCKLEN -> %r\n", Status)); + goto Exit; + } + } + MmcHostIo->SetBlockLength (MmcHostIo, 512); + +Exit: + if (Status) { + + } + + return Status; +} + + +/** + MmcSelect + + @param[in] CardData Pointer to CARD_DATA + @param[in] Select + + @retval EFI_STATUS + +**/ +EFI_STATUS +MmcSelect ( + IN CARD_DATA *CardData, + IN BOOLEAN Select + ) +{ + return SendCommand ( + CardData->MmcHostIo, + SELECT_DESELECT_CARD, + Select ? (CardData->Address << 16) : ~(CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); +} + + +/** + MmcSendSwitch + + @param[in] CardData Pointer to CARD_DATA + @param[in] SwitchArgument Pointer to SWITCH_ARGUMENT + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcSendSwitch ( + IN CARD_DATA *CardData, + IN SWITCH_ARGUMENT *SwitchArgument + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + + MmcHostIo = CardData->MmcHostIo; + + Status = SendCommand ( + MmcHostIo, + SWITCH, + *(UINT32 *) SwitchArgument, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + Status = SendCommand ( + MmcHostIo, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SWITCH FAILURE\n")); + } + } + + return Status; +} + + +/** + MmcUpdateCardStatus + + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcUpdateCardStatus ( + IN CARD_DATA *CardData + ) +{ + return SendCommand ( + CardData->MmcHostIo, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); +} + + +/** + MmcMoveToTranState + + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcMoveToTranState ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (CardData->CardStatus.CURRENT_STATE != Tran_STATE) { + // + // Put the card into tran state + // + Status = MmcSelect (CardData, TRUE); + MmcUpdateCardStatus (CardData); + } + + if (CardData->CardStatus.CURRENT_STATE != Tran_STATE) { + DEBUG ((EFI_D_ERROR, "MmcMoveToTranState: Unable to put card into tran state\n")); + return EFI_DEVICE_ERROR; + } + + return Status; +} + + +/** + MmcReadExtCsd + + @param[in,out] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcReadExtCsd ( + IN OUT CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + + Status = MmcMoveToTranState (CardData); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SendCommand ( + CardData->MmcHostIo, + SEND_EXT_CSD, + 0, + InData, + CardData->AlignedBuffer, + sizeof (EXT_CSD), + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + DEBUG ((EFI_D_INFO, "MmcReadExtCsd: SEND_EXT_CSD -> %r\n", Status)); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof (EXT_CSD)); + + return Status; +} + + +/** + MmcSetExtCsd8 + + @param[in] CardData Pointer to CARD_DATA + @param[in] Index + @param[in] Value + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcSetExtCsd8 ( + IN CARD_DATA *CardData, + IN UINT8 Index, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + SWITCH_ARGUMENT SwitchArgument; + + Status = MmcMoveToTranState (CardData); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT)); + SwitchArgument.CmdSet = 0; + SwitchArgument.Value = (UINT8) Value; + SwitchArgument.Index = (UINT8) Index; + SwitchArgument.Access = WriteByte_Mode; // SetBits_Mode; + + return MmcSendSwitch (CardData, &SwitchArgument); +} + + +/** + MmcSetExtCsd24 + + @param[in] CardData Pointer to CARD_DATA + @param[in] Index + @param[in] Value + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcSetExtCsd24 ( + IN CARD_DATA *CardData, + IN UINT8 Index, + IN UINT32 Value + ) +{ + EFI_STATUS Status; + UINTN Loop; + + ASSERT ((Value & 0xff000000ULL) == 0); + + for (Loop = 0; Loop < 3; Loop++) { + Status = MmcSetExtCsd8 (CardData, Index + (UINT8) Loop, Value & 0xff); + if (EFI_ERROR (Status)) { + return Status; + } + Value = Value >> 8; + } + + return Status; +} + + +/** + MmcGetExtCsd8 + + @param[in] CardData Pointer to CARD_DATA + @param[in] Offset + + @retval CSD Register value + +**/ +UINT32 +MmcGetExtCsd8 ( + IN CARD_DATA *CardData, + IN UINTN Offset + ) +{ + ASSERT (Offset < sizeof (CardData->ExtCSDRegister)); + return ((UINT8 *) &CardData->ExtCSDRegister)[Offset]; +} + + +/** + MmcGetExtCsd32 + + @param[in] CardData Pointer to CARD_DATA + @param[in] Offset + + @retval CSD Register value + +**/ +UINT32 +MmcGetExtCsd32 ( + IN CARD_DATA *CardData, + IN UINTN Offset + ) +{ + return *(UINT32 *) (((UINT8 *) &CardData->ExtCSDRegister) + Offset); +} + + +/** + MmcGetExtCsd24 + + @param[in] CardData Pointer to CARD_DATA + @param[in] Offset + + @retval CSD Register value + +**/ +UINT32 +MmcGetExtCsd24 ( + IN CARD_DATA *CardData, + IN UINTN Offset + ) +{ + return MmcGetExtCsd32 (CardData, Offset) & 0xffffff; +} + + +/** + MmcGetCurrentPartitionNum + + @param[in] CardData Pointer to CARD_DATA + + @retval Current Partition Num + +**/ +UINTN +MmcGetCurrentPartitionNum ( + IN CARD_DATA *CardData + ) +{ + return MmcGetExtCsd8 ( + CardData, + OFFSET_OF (EXT_CSD, PARTITION_CONFIG) + ) & 0x7; +} + + +/** + SetEmmcWpOnEvent + + @param[in] Event + @param[in] Context + + @retval None + +**/ +VOID +EFIAPI +SetEmmcWpOnEvent( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN Offset; + CARD_DATA *CardData; + UINT8 TempData; + UINTN WriteProtectAddress; + UINTN WriteProtectSize; + UINTN WriteProtectGroupSize; + static BOOLEAN WriteProtectDone = FALSE; + HECI_FWS_REGISTER SecFwStatus; + SC_POLICY_HOB *ScPolicy; + EFI_PEI_HOB_POINTERS HobList; + SC_SCS_CONFIG *ScsConfig; + + DEBUG ((EFI_D_INFO, "eMMC Write Protection Config Checkpoint\n")); + + CardData = (CARD_DATA *) Context; + // + // Enable the eMMC protection + // + if (FALSE) { + if (!WriteProtectDone) { + Status = MmcReadExtCsd (CardData); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "Read EXT_CSD failed\n")); + } + DEBUG ((EFI_D_INFO, "\nBOOT_WP 0x%02x", (UINT8) (CardData->ExtCSDRegister.BOOT_WP))); + DEBUG ((EFI_D_INFO, "\nBOOT_WP_STATUS 0x%02x", (UINT8) (CardData->ExtCSDRegister.BOOT_WP_STATUS))); + DEBUG ((EFI_D_INFO, "\nUSER_WP 0x%02x", (UINT8) (CardData->ExtCSDRegister.USER_WP))); + DEBUG ((EFI_D_INFO, "\nRST_n_FUNCTION 0x%02x\n", (UINT8) (CardData->ExtCSDRegister.RST_n_FUNCTION))); + + if (BxtStepping() >= BxtPB0) { //For BXTP-B and above, BIOS to toggle rst_n_function from 2'b00 to 2'b01 + if ((CardData->ExtCSDRegister.RST_n_FUNCTION & 0x3) != 1) { + Offset = OFFSET_OF (EXT_CSD, RST_n_FUNCTION); + Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, 0x01); + if (Status) { + DEBUG ((EFI_D_INFO, "Setting RST_n_FUNCTION failed\n")); + } + } + } + + // Protect and BP + // Update Power on write protection bit in USER_WP and BP_WP EXT_CSD registers + // + Offset = OFFSET_OF (EXT_CSD, ERASE_GROUP_DEF); + Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, 0x01); + if (Status) { + DEBUG ((EFI_D_INFO, "Setting ERASE_GROUP_DEF failed\n")); + } + + if (BxtStepping() != BxtPA0) { // program WP only if it's not Bxtp-A0 + Offset = OFFSET_OF (EXT_CSD, BOOT_WP); + TempData = (CardData->ExtCSDRegister.BOOT_WP) | B_PWR_WP_EN | B_PERM_WP_DIS; + Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, TempData); + if (Status) { + DEBUG ((EFI_D_INFO, "BP Write protect failed\n")); + } + } + + HobList.Guid = GetFirstGuidHob (&gScPolicyHobGuid); + ASSERT (HobList.Guid != NULL); + ScPolicy = (SC_POLICY_HOB *) GET_GUID_HOB_DATA (HobList.Guid); + Status = GetConfigBlock ((VOID *) ScPolicy, &gScsConfigGuid, (VOID *) &ScsConfig); + ASSERT_EFI_ERROR (Status); + + SecFwStatus.ul = HeciPciRead32 (R_SEC_FW_STS0); + + if (SecFwStatus.r.ManufacturingMode == 0) { + DEBUG ((EFI_D_INFO, "SEC F/W is not in Manufacturing mode and is ready for production \n")); + } else if (SecFwStatus.r.SeCOperationMode != SEC_OPERATION_MODE_SECOVR_JMPR) { + DEBUG ((EFI_D_INFO, "Flash Descriptor Override HW strap not set\n")); + } + + if (((SecFwStatus.r.ManufacturingMode == 0) // if EOM is set + && (SecFwStatus.r.SeCOperationMode != SEC_OPERATION_MODE_SECOVR_JMPR)) // Flash Descriptor Override HW strap not set + || (ScsConfig->GppLock == 1) // OR GPP Partition Lock Policy is set + ) { + // + // Protect GPP1 + // + Status = MmcSelectPartitionNum (CardData, 4); // Switch to GPP1 before issuing CMD28 + if (!EFI_ERROR(Status)) { + DEBUG ((EFI_D_INFO, "\nSwitch to GPP Partition Successful\n")); + WriteProtectSize = (((UINTN) (CardData->ExtCSDRegister.GP_SIZE_MULT_1[2] *( 0x1<<16))) + +((UINTN) (CardData->ExtCSDRegister.GP_SIZE_MULT_1[1] *( 0x1<<8))) + +((UINTN) (CardData->ExtCSDRegister.GP_SIZE_MULT_1[0]))) + * ((UINTN) (CardData->ExtCSDRegister.HC_WP_GRP_SIZE)) + * 512 * 1024 * ((UINTN) (CardData->ExtCSDRegister.HC_ERASE_GRP_SIZE)); + + DEBUG ((EFI_D_INFO, "WriteProtectSize = 0x%x\n", WriteProtectSize)); + + Offset = OFFSET_OF (EXT_CSD, USER_WP); + TempData = (CardData->ExtCSDRegister.USER_WP) | US_PWR_WP_EN | US_PERM_WP_DIS; + Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, TempData); + if (Status) { + DEBUG ((EFI_D_INFO, "GPP Write protect failed\n")); + } + if (CardData->ExtCSDRegister.ERASE_GROUP_DEF) { + WriteProtectGroupSize = ((UINTN) (CardData->ExtCSDRegister.HC_WP_GRP_SIZE)) + * 512 * 1024 * ((UINTN) (CardData->ExtCSDRegister.HC_ERASE_GRP_SIZE)); + } else { + WriteProtectGroupSize = (CardData->CSDRegister.WP_GRP_SIZE + 1) + * ((UINTN) CardData->CSDRegister.ERASE_GRP_SIZE + 1) + * ((UINTN) CardData->CSDRegister.ERASE_GRP_MULT + 1) + * ((UINTN) (CardData->Partitions[4].BlockIoMedia.BlockSize)); + } + + DEBUG ((EFI_D_INFO, "WriteProtectGroupSize = 0x%x\n", WriteProtectGroupSize)); + + for (WriteProtectAddress = 0; WriteProtectAddress < WriteProtectSize; WriteProtectAddress+=WriteProtectGroupSize) { + // + // Send Write protect command + // + DEBUG ((EFI_D_INFO, "Send Write protect command Address = 0x%x\n", WriteProtectAddress)); + Status = SendCommand ( + CardData->MmcHostIo, + SET_WRITE_PROT, + (UINT32) (WriteProtectAddress / 0x200), + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (Status) { + DEBUG ((EFI_D_INFO, "GPP1 Write protect failed\n")); + break; + } + } + + } + + } + } + + Status = MmcReadExtCsd (CardData); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "Read EXT_CSD failed\n")); + } + + DEBUG ((EFI_D_INFO, "\nBOOT_WP 0x%02x", (UINT8) (CardData->ExtCSDRegister.BOOT_WP))); + DEBUG ((EFI_D_INFO, "\nBOOT_WP_STATUS 0x%02x", (UINT8) (CardData->ExtCSDRegister.BOOT_WP_STATUS))); + DEBUG ((EFI_D_INFO, "\nUSER_WP 0x%02x", (UINT8) (CardData->ExtCSDRegister.USER_WP))); + DEBUG ((EFI_D_INFO, "\nRST_n_FUNCTION 0x%02x\n", (UINT8) (CardData->ExtCSDRegister.RST_n_FUNCTION))); + WriteProtectDone = TRUE; + } +} + + +/** + MmcSelectPartitionNum + + @param[in] CardData Pointer to CARD_DATA + @param[in] Partition + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcSelectPartitionNum ( + IN CARD_DATA *CardData, + IN UINT8 Partition + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINT8 *ExtByte; + UINTN CurrentPartition; + + if (Partition > 7) { + return EFI_INVALID_PARAMETER; + } + + CurrentPartition = MmcGetCurrentPartitionNum (CardData); + if (Partition == CurrentPartition) { + return EFI_SUCCESS; + } + MmcMoveToTranState (CardData); + Status = MmcReadExtCsd (CardData); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((EFI_D_INFO, + "MmcSelectPartitionNum: Switch partition: %d => %d\n", + CurrentPartition, + Partition + )); + + Offset = OFFSET_OF (EXT_CSD, PARTITION_CONFIG); + Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, Partition); + +#if 1 + Status = MmcReadExtCsd (CardData); + if (EFI_ERROR (Status)) { + return Status; + } + + CurrentPartition = MmcGetCurrentPartitionNum (CardData); + if (Partition != CurrentPartition) { + DEBUG ((EFI_D_INFO, "MmcSelectPartitionNum: Switch partition failed!\n")); + return EFI_DEVICE_ERROR; + } + + ExtByte = NULL; +#else + if (!EFI_ERROR (Status)) { + ExtByte = ((UINT8 *) &CardData->ExtCSDRegister) + Offset; + *ExtByte = (UINT8) ((*ExtByte & 0xF7) | Partition); + } +#endif + MmcMoveToTranState (CardData); + + return Status; +} + + +/** + MmcSelectPartitionNum + + @param[in] Partition Pointer to MMC_PARTITION_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcSelectPartition ( + IN MMC_PARTITION_DATA *Partition + ) +{ + return MmcSelectPartitionNum ( + Partition->CardData, + (UINT8) CARD_DATA_PARTITION_NUM (Partition) + ); +} + + +/** + MmcSetPartition + + @param[in] CardData Pointer to CARD_DATA + @param[in] Value 0: user partition; 1: boot partition 1; 2:boot partition 2 + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MmcSetPartition ( + IN CARD_DATA *CardData, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINT32 Data; + + Offset = OFFSET_OF (EXT_CSD, PARTITION_CONFIG); + Data = MmcGetExtCsd8 (CardData, Offset); + Data &= 0xf8; + Data |= Value; + Status = MmcSetExtCsd8 (CardData, (UINT8) Offset, (UINT8) Data); + + return Status; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c new file mode 100644 index 0000000..7f5bd11 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MediaDeviceDriver.c @@ -0,0 +1,605 @@ +/** @file + UEFI Driver Entry and Binding support. + + Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR> + + 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 <MediaDeviceDriver.h> +#include <Protocol/EmmcCardInfoProtocol.h> + +// +// MMCSDIOController Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gMediaDeviceDriverBinding = { + MediaDeviceDriverBindingSupported, + MediaDeviceDriverBindingStart, + MediaDeviceDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_EMMC_CARD_INFO_PROTOCOL *gEfiEmmcCardInfo = NULL; + +/** + Entry point for EFI drivers. + + @param[in] ImageHandle EFI_HANDLE + @param[in] SystemTable EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Fail + +**/ +EFI_STATUS +EFIAPI +MediaDeviceDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gMediaDeviceDriverBinding, + ImageHandle, + &gMediaDeviceComponentName, + NULL, + NULL + ); +} + + +/** + Test to see if this driver supports ControllerHandle. Any ControllerHandle + that has installed will be supported. + + @param[in] This Protocol instance pointer. + @param[in] Controlle Handle of device to test + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +MediaDeviceDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + + // + // Test whether there is MMCHostIO Protocol attached on the controller handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiMmcHostIoProtocolGuid, + (VOID **) &MmcHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + gBS->CloseProtocol ( + Controller, + &gEfiMmcHostIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + +Exit: + return Status; +} + + +/** + Starting the Media Device Driver + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS supports this device. + @retval EFI_UNSUPPORTED do not support this device. + @retval EFI_DEVICE_ERROR cannot be started due to device Error + @retval EFI_OUT_OF_RESOURCES cannot allocate resources + +**/ +EFI_STATUS +EFIAPI +MediaDeviceDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo; + CARD_DATA *CardData; + UINTN Loop; + EFI_EMMC_CARD_INFO_PROTOCOL *EfiEmmcCardInfoRegister; + + DEBUG ((EFI_D_INFO, "%a(%d): %a()\n", __FILE__, __LINE__, __FUNCTION__)); + + EfiEmmcCardInfoRegister = NULL; + CardData = NULL; + MmcHostIo = NULL; + + // + // Alloc memory for EfiEmmcCardInfoRegister variable + // + EfiEmmcCardInfoRegister = (EFI_EMMC_CARD_INFO_PROTOCOL *) AllocateZeroPool (sizeof (EFI_EMMC_CARD_INFO_PROTOCOL)); + if (EfiEmmcCardInfoRegister == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + // + // Open PCI I/O Protocol and save pointer to open protocol + // in private data area. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiMmcHostIoProtocolGuid, + (VOID **) &MmcHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStart: Fail to open gEfiMmcHostIoProtocolGuid \n")); + goto Exit; + } + + Status = MmcHostIo->DetectCardAndInitHost (MmcHostIo); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Fail to DetectCardAndInitHost %r\n", Status)); + goto Exit; + } + + CardData = (CARD_DATA *) AllocateZeroPool (sizeof (CARD_DATA)); + if (CardData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStart: Fail to AllocateZeroPool(CARD_DATA) \n")); + goto Exit; + } + + ASSERT (MmcHostIo->HostCapability.BoundarySize >= 4 * 1024); + + CardData->RawBufferPointer = (UINT8*) (UINTN) 0xffffffff; + + DEBUG ((EFI_D_INFO, "CardData->RawBufferPointer = 0x%x \n",CardData->RawBufferPointer)); + DEBUG ((EFI_D_INFO, "requesting 0x%x pages \n",EFI_SIZE_TO_PAGES(2 * MmcHostIo->HostCapability.BoundarySize))); + + // + // Allocated the buffer under 4G + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + EFI_SIZE_TO_PAGES (2 * MmcHostIo->HostCapability.BoundarySize), + (EFI_PHYSICAL_ADDRESS *) (&(CardData->RawBufferPointer)) + ); + DEBUG ((EFI_D_INFO, "CardData->RawBufferPointer = 0x%x \n",CardData->RawBufferPointer)); + if (!EFI_ERROR (Status)) { + CardData->RawBufferPointer = ZeroMem (CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * MmcHostIo->HostCapability.BoundarySize)); + } else { + DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Fail to AllocateZeroPool(2*x) \n")); + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + CardData->AlignedBuffer = CardData->RawBufferPointer - ((UINTN) (CardData->RawBufferPointer) & (MmcHostIo->HostCapability.BoundarySize - 1)) + MmcHostIo->HostCapability.BoundarySize; + + CardData->Signature = CARD_DATA_SIGNATURE; + CardData->MmcHostIo = MmcHostIo; + CardData->Handle = Controller; + for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Loop++) { + CardData->Partitions[Loop].Signature = CARD_PARTITION_SIGNATURE; + } + Status = MMCSDCardInit (CardData); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStart: Fail to MMCSDCardInit \n")); + goto Exit; + } + + DEBUG ((DEBUG_INFO, "MediaDeviceDriverBindingStart: MMC SD card\n")); + Status = MMCSDBlockIoInit (CardData); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Card BlockIo init failed\n")); + goto Exit; + } + + + Status = MediaDeviceDriverInstallBlockIo (This, CardData); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Fail to install gEfiBlockIoProtocolGuid \n")); + goto Exit; + } + + // + // Component name protocol + // + Status = AddUnicodeString ( + "eng", + gMediaDeviceComponentName.SupportedLanguages, + &CardData->ControllerNameTable, + L"MMC/SD Media Device" + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Loop++) { + if (!CardData->Partitions[Loop].Present) { + continue; + } + gBS->UninstallMultipleProtocolInterfaces ( + CardData->Partitions[Loop].Handle, + &gEfiBlockIoProtocolGuid, + &CardData->Partitions[Loop].BlockIo, + &gEfiDevicePathProtocolGuid, + CardData->Partitions[Loop].DevPath, + NULL + ); + } + goto Exit; + } + if (EfiEmmcCardInfoRegister != NULL) { + + // + // assign to protocol + // + EfiEmmcCardInfoRegister->CardData = CardData; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiEmmcCardInfoProtocolGuid, + EfiEmmcCardInfoRegister, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MediaDeviceDriverBindingStart: Install eMMC Card info protocol failed\n")); + for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Loop++) { + if (!CardData->Partitions[Loop].Present) { + continue; + } + gBS->UninstallMultipleProtocolInterfaces ( + CardData->Partitions[Loop].Handle, + &gEfiBlockIoProtocolGuid, + &CardData->Partitions[Loop].BlockIo, + &gEfiDevicePathProtocolGuid, + CardData->Partitions[Loop].DevPath, + NULL + ); + } + + goto Exit; + } + + gEfiEmmcCardInfo = EfiEmmcCardInfoRegister; + } + + DEBUG ((DEBUG_INFO, "MediaDeviceDriverBindingStart: Started\n")); + +Exit: + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStart: End with failure\n")); + if (CardData != NULL && MmcHostIo != NULL) { + if (CardData->RawBufferPointer != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (MmcHostIo->HostCapability.BoundarySize * 2)); + } + FreePool (CardData); + } + gBS->CloseProtocol ( + Controller, + &gEfiMmcHostIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + return Status; +} + + +/** + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to stop driver on + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer + @param[in] ChildHandleBuffer List of handles for the children we need to stop. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Fail + +**/ +EFI_STATUS +EFIAPI +MediaDeviceDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + CARD_DATA *CardData; + BOOLEAN AllChildrenStopped; + UINTN Index; + UINTN Pages = 0; + + Status = EFI_SUCCESS; + CardData = gEfiEmmcCardInfo->CardData; + + if (NumberOfChildren == 0) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiEmmcCardInfoProtocolGuid, + gEfiEmmcCardInfo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStop: UNINSTALL gEfiEmmcCardInfoProtocolGuid FAILURE\n")); + return Status; + } + + FreeUnicodeStringTable (CardData->ControllerNameTable); + + Pages = (2 * (CardData->MmcHostIo->HostCapability.BoundarySize)); + if (CardData->RawBufferPointer != NULL) { + FreePages (CardData->RawBufferPointer, EFI_SIZE_TO_PAGES(Pages)); + } + + Status = gBS->CloseProtocol ( + Controller, + &gEfiMmcHostIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if (MediaDeviceDriverAllPartitionNotPresent(CardData)) { + FreePool (CardData); + FreePool (gEfiEmmcCardInfo); + gEfiEmmcCardInfo = NULL; + } + + return Status; + } + + AllChildrenStopped = TRUE; + for (Index = 0; Index < NumberOfChildren; Index++) { + Status = MediaDeviceDriverUninstallBlockIo(This, CardData, ChildHandleBuffer[Index]); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStop: UNINSTALL block io FAILURE\n")); + AllChildrenStopped = FALSE; + break; + } + } + + return Status; +} + + +BOOLEAN +MediaDeviceDriverAllPartitionNotPresent ( + IN CARD_DATA *CardData + ) +{ + BOOLEAN AllPartitionNotPresent; + UINTN Loop; + MMC_PARTITION_DATA *Partition; + + Partition = CardData->Partitions; + + AllPartitionNotPresent = TRUE; + + for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Partition++, Loop++) { + if (Partition->Present) { + AllPartitionNotPresent = FALSE; + break; + } + } + + return AllPartitionNotPresent; +} + + +STATIC +struct { + DEVICE_LOGICAL_UNIT_DEVICE_PATH LogicalUnit; + EFI_DEVICE_PATH_PROTOCOL End; +} EmmcDevPathTemplate = { + { + { + MESSAGING_DEVICE_PATH, + MSG_DEVICE_LOGICAL_UNIT_DP, + { + sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH), + 0 + }, + }, + 0 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + + +/** + MediaDeviceDriverInstallBlockIo + + @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL. + @param[in] CardData Pointer to CARD_DATA + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MediaDeviceDriverInstallBlockIo ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + UINT8 Loop; + MMC_PARTITION_DATA *Partition; + EFI_DEVICE_PATH_PROTOCOL *MainPath; + EFI_MMC_HOST_IO_PROTOCOL *MmcHostIo = NULL; + + Partition = CardData->Partitions; + + Status = gBS->HandleProtocol ( + CardData->Handle, + &gEfiDevicePathProtocolGuid, + (VOID **) &MainPath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Partition++, Loop++) { + if (!Partition->Present) { + continue; + } + + DEBUG ((EFI_D_INFO, "MediaDeviceDriverInstallBlockIo: Installing Block I/O for partition %d\n", Loop)); + + Partition->Handle = NULL; + Partition->CardData = CardData; + + EmmcDevPathTemplate.LogicalUnit.Lun = Loop; + Partition->DevPath = + AppendDevicePath ( + MainPath, + (EFI_DEVICE_PATH_PROTOCOL *) &EmmcDevPathTemplate + ); + if (Partition->DevPath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + Status = gBS->InstallProtocolInterface ( + &(Partition->Handle), + &gEfiDevicePathProtocolGuid, + EFI_NATIVE_INTERFACE, + Partition->DevPath + ); + if (EFI_ERROR (Status)) { + break; + } + + Status = gBS->InstallProtocolInterface ( + &(Partition->Handle), + &gEfiBlockIoProtocolGuid, + EFI_NATIVE_INTERFACE, + &Partition->BlockIo + ); + + // + // Open parent controller by child + // + Status = gBS->OpenProtocol ( + CardData->Handle, + &gEfiMmcHostIoProtocolGuid, + (VOID **) &MmcHostIo, + This->DriverBindingHandle, + Partition->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } + + return Status; +} + + +/** + MediaDeviceDriverUninstallBlockIo + + @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL. + @param[in] CardData Pointer to CARD_DATA + @param[in] Handle Handle of Partition + + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +EFI_STATUS +MediaDeviceDriverUninstallBlockIo ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN CARD_DATA *CardData, + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + UINTN Loop; + MMC_PARTITION_DATA *Partition; + + Partition = CardData->Partitions; + Status = EFI_SUCCESS; + + for (Loop = 0; Loop < MAX_NUMBER_OF_PARTITIONS; Partition++, Loop++) { + if (!Partition->Present || Partition->Handle != Handle) { + continue; + } + + // + // Close MmcHostIoProtocol by child + // + Status = gBS->CloseProtocol ( + CardData->Handle, + &gEfiMmcHostIoProtocolGuid, + This->DriverBindingHandle, + Partition->Handle + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "CloseProtocol gEfiMmcHostIoProtocolGuid FAILURE \n")); + return Status; + } + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Partition->Handle, + &gEfiBlockIoProtocolGuid, + &Partition->BlockIo, + &gEfiDevicePathProtocolGuid, + Partition->DevPath, + NULL + ); + Partition->Present = FALSE; + DEBUG ((EFI_D_ERROR, "MediaDeviceDriverBindingStop gEfiBlockIoProtocolGuid removed. %x\n", Status)); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MediaDeviceDriverUninstallBlockIo UNISTALL FAILURE \n")); + } + return Status; + } + + return EFI_INVALID_PARAMETER; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf new file mode 100644 index 0000000..500d1de --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/MMC/MmcMediaDeviceDxe/MmcMediaDeviceDxe.inf @@ -0,0 +1,71 @@ +## @file +# SD Host module +# +# Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR> +# +# 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 = 0x00010005 + BASE_NAME = MmcMediaDevice + FILE_GUID = 1CFD8F87-355A-4954-859F-DDC5D8876D44 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = MediaDeviceDriverEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + ComponentName.c + MediaDeviceDriver.c + MMCSDBlockIo.c + MMCSDTransfer.c + +[Packages] + MdePkg/MdePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + BroxtonSiPkg/BroxtonSiPrivate.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + UefiBootServicesTableLib + BaseMemoryLib + MemoryAllocationLib + UefiLib + DevicePathLib + IoLib + PcdLib + HobLib + PciLib + SteppingLib + ConfigBlockLib + +[Guids] + gEfiEventReadyToBootGuid ## UNDEFINED + gScPolicyHobGuid + gEfiUnbootablePartitionGuid ## PRODUCE ## GUID + gScsConfigGuid + +[Protocols] + gEfiDevicePathProtocolGuid ## BY_START + gEfiMmcHostIoProtocolGuid ## CONSUMES + gEfiBlockIoProtocolGuid ## BY_START + gEfiEmmcCardInfoProtocolGuid ## BY_START + gEfiEmmcBootPartitionProtocolGuid ## BY_START + +[Pcd] + gEfiBxtTokenSpaceGuid.PcdEmmcManufacturerId ## PRODUCES + gEfiBxtTokenSpaceGuid.PcdProductSerialNumber ## PRODUCES diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c new file mode 100644 index 0000000..0bc9861 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.c @@ -0,0 +1,233 @@ +/** @file + UEFI Component Name(2) protocol implementation for SD controller driver. + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "SdController.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSdControllerName = { + SdControllerGetDriverName, + SdControllerGetControllerName, + "eng" +}; + + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSdControllerName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SdControllerGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SdControllerGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdControllerDriverNameTable[] = { + { "eng;en", L"EFI SD Host Controller Driver" }, + { NULL, NULL } +}; + + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form 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 name 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param[in] Language 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 SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 3066 or ISO 639-2 language code format. + + @param[out] DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language 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 +SdControllerGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mSdControllerDriverNameTable, + DriverName, + (BOOLEAN)(This == &gSdControllerName) + ); +} + + +/** + 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 specified by + ControllerHandle and ChildHandle in the form 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 controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param[in] ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param[in] ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + 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 name of a + child controller. + + @param[in] Language 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 SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 3066 or ISO 639-2 language code format. + + @param[out] ControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for 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 +SdControllerGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + SDHOST_DATA *SdHostData; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure this driver is currently managing ControllerHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gSdControllerDriverBinding.DriverBindingHandle, + &gEfiPciIoProtocolGuid + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSdHostIoProtocolGuid, + (VOID **) &SdHostIo, + gSdControllerDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + SdHostData = SDHOST_DATA_FROM_THIS (SdHostIo); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + SdHostData->ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gSdControllerName) + ); + +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h new file mode 100644 index 0000000..89d8a27 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/ComponentName.h @@ -0,0 +1,145 @@ +/** @file + This file contains the declarations for component name routines. + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 _COMPONENT_NAME_H_ +#define _COMPONENT_NAME_H_ + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form 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 name 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param[in] Language 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 SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 3066 or ISO 639-2 language code format. + + @param[out] DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language 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 +SdControllerGetDriverName ( + 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 specified by + ControllerHandle and ChildHandle in the form 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 controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param[in] ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param[in] ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + 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 name of a + child controller. + + @param[in] Language 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 SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 3066 or ISO 639-2 language code format. + + @param[out] ControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for 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 +SdControllerGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c new file mode 100644 index 0000000..f481196 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c @@ -0,0 +1,1804 @@ +/** @file + The SD host controller driver model and HC protocol routines. + + Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR> + + 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 "SdController.h" + +EFI_DRIVER_BINDING_PROTOCOL gSdControllerDriverBinding = { + SdControllerSupported, + SdControllerStart, + SdControllerStop, + 0x20, + NULL, + NULL +}; + + +EFI_SD_HOST_IO_PROTOCOL mSdHostIo = { + EFI_SD_HOST_IO_PROTOCOL_REVISION_01, + { + 0, // HighSpeedSupport + 0, // V18Support + 0, // V30Support + 0, // V33Support + 0, // Reserved0 + 0, // BusWidth4 + 0, // BusWidth8 + 0, // Reserved1 + 0, // Reserved1 + (512 * 1024) // BoundarySize + }, + + SendCommand, + SetClockFrequency, + SetBusWidth, + SetHostVoltage, + ResetSdHost, + EnableAutoStopCmd, + DetectCardAndInitHost, + SetBlockLength, + SetHighSpeedMode, + SetDDRMode +}; + + +/** + Find sdclk_freq_sel and upr_sdclk_freq_sel bits + for Clock Control Register (CLK_CTL)Offset 2Ch when using 8bit or 10bit + divided clock mode. + + @param[in] BaseClockFreg Base Clock Frequency in Hz For SD Clock in the + Capabilities register. + @param[in] TargetFreq Target Frequency in Hz to reach. + @param[in] Is8BitMode True if 8-bit Divided Clock Mode else 10bit mode. + @param[out] Bits sdclk_freq_sel and upr_sdclk_freq_sel bits for + TargetFreq. + + @retval EFI_SUCCESS Bits setup. + @retval EFI_UNSUPPORTED Cannot divide base clock to reach target clock. + +**/ +EFI_STATUS +DividedClockModeBits ( + IN CONST UINTN BaseClockFreg, + IN CONST UINTN TargetFreq, + IN CONST BOOLEAN Is8BitMode, + OUT UINT16 *Bits + ) +{ + UINTN N; + UINTN CurrFreq; + + *Bits = 0; + CurrFreq = BaseClockFreg; + N = 0; + // + // N == 0 same for 8bit & 10bit mode i.e. BaseClockFreg of controller. + // + if (TargetFreq < CurrFreq) { + if (Is8BitMode) { + N = 1; + do { + // + // N values for 8bit mode when N > 0. + // Bit[15:8] SDCLK Frequency Select at offset 2Ch + // 80h - base clock divided by 256 + // 40h - base clock divided by 128 + // 20h - base clock divided by 64 + // 10h - base clock divided by 32 + // 08h - base clock divided by 16 + // 04h - base clock divided by 8 + // 02h - base clock divided by 4 + // 01h - base clock divided by 2 + // + CurrFreq = BaseClockFreg / (2 * N); + if (TargetFreq >= CurrFreq) { + break; + } + N *= 2; + if (N > V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL) { + return EFI_UNSUPPORTED; + } + } while (TRUE); + } else { + N = 1; + CurrFreq = BaseClockFreg / (2 * N); + // + // (try N = 0 or 1 first since don't want divide by 0). + // + if (TargetFreq < CurrFreq) { + // + // If still no match then calculate it for 10bit. + // N values for 10bit mode. + // N 1/2N Divided Clock (Duty 50%). + // from Spec "The length of divider is extended to 10 bits and all + // divider values shall be supported. + // + N = (BaseClockFreg / TargetFreq) / 2; + + // + // Can only be N or N+1; + // + CurrFreq = BaseClockFreg / (2 * N); + if (TargetFreq < CurrFreq) { + N++; + CurrFreq = BaseClockFreg / (2 * N); + } + + if (N > V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL) { + return EFI_UNSUPPORTED; + } + + // + // Set upper bits of SDCLK Frequency Select (bits 7:6 of reg 0x2c). + // + *Bits |= ((UINT16) ((N >> 2) & B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK)); + } + } + } + + // + // Set lower bits of SDCLK Frequency Select (bits 15:8 of reg 0x2c). + // + *Bits |= ((UINT16) ((UINT8) N) << 8); + DEBUG ( + (EFI_D_INFO, + "SDIO:DividedClockModeBits: %dbit mode Want %dHz Got %dHz bits = %04x\r\n", + (Is8BitMode) ? 8 : 10, + TargetFreq, + CurrFreq, + (UINTN) *Bits + )); + + return EFI_SUCCESS; +} + + +/** + Print type of error and command index + + @param[in] CommandIndex Command index to set the command index field of command register. + @param[in] ErrorCode Error interrupt status read from host controller + + @retval EFI_DEVICE_ERROR + @retval EFI_TIMEOUT + @retval EFI_CRC_ERROR + +**/ +EFI_STATUS +GetErrorReason ( + IN UINT16 CommandIndex, + IN UINT16 ErrorCode + ) +{ + EFI_STATUS Status; + + Status = EFI_DEVICE_ERROR; + + DEBUG ((EFI_D_ERROR, "[%2d] -- ", CommandIndex)); + + if (ErrorCode & BIT0) { + Status = EFI_TIMEOUT; + DEBUG ((EFI_D_ERROR, "Command Timeout Erro")); + } + + if (ErrorCode & BIT1) { + Status = EFI_CRC_ERROR; + DEBUG ((EFI_D_ERROR, "Command CRC Error")); + } + + if (ErrorCode & BIT2) { + DEBUG ((EFI_D_ERROR, "Command End Bit Error")); + } + + if (ErrorCode & BIT3) { + DEBUG ((EFI_D_ERROR, "Command Index Error")); + } + if (ErrorCode & BIT4) { + Status = EFI_TIMEOUT; + DEBUG ((EFI_D_ERROR, "Data Timeout Error")); + } + + if (ErrorCode & BIT5) { + Status = EFI_CRC_ERROR; + DEBUG ((EFI_D_ERROR, "Data CRC Error")); + } + + if (ErrorCode & BIT6) { + DEBUG ((EFI_D_ERROR, "Data End Bit Error")); + } + + if (ErrorCode & BIT7) { + DEBUG ((EFI_D_ERROR, "Current Limit Error")); + } + + if (ErrorCode & BIT8) { + DEBUG ((EFI_D_ERROR, "Auto CMD12 Error")); + } + + if (ErrorCode & BIT9) { + DEBUG ((EFI_D_ERROR, "ADMA Error")); + } + + DEBUG ((EFI_D_ERROR, "\n")); + + return Status; +} + + +/** + Enable/Disable High Speed transfer mode + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] Enable TRUE to Enable, FALSE to Disable + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetHighSpeedMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ) +{ + UINT32 Data; + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + PciIo = SdHostData->PciIo; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_HOSTCTL, + 1, + &Data + ); + + if (Enable) { + DEBUG ((EFI_D_INFO, "Enable High Speed transfer mode ... \r\n")); + Data |= BIT2; + } else { + Data &= ~BIT2; + } + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_HOSTCTL, + 1, + &Data + ); + + return EFI_SUCCESS; +} +EFI_STATUS +EFIAPI +SetDDRMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ) +{ + UINT16 Data; + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + PciIo = SdHostData->PciIo; + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_HOSTCTL2, + 1, + &Data + ); + + Data &= 0xFFF0; + if (Enable) { + Data |= 0x0004; // Enable DDR50 by default, later should enable other mode like HS200/400 + Data |= BIT3; // Enable 1.8V Signaling + } + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_HOSTCTL2, + 1, + &Data + ); + + return EFI_SUCCESS; +} + + +/** + Power on/off the LED associated with the slot + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] Enable TRUE to set LED on, FALSE to set LED off + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +HostLEDEnable ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ) +{ + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 Data; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + PciIo = SdHostData->PciIo; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_HOSTCTL, + 1, + &Data + ); + + if (Enable) { + // + // LED On + // + Data |= BIT0; + } else { + // + // LED Off + // + Data &= ~BIT0; + } + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_HOSTCTL, + 1, + &Data + ); + + return EFI_SUCCESS; +} + + +/** + The main function used to send the command to the card inserted into the SD host slot. + It will assemble the arguments to set the command register and wait for the command + and transfer completed until timeout. Then it will read the response register to fill + the ResponseData. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] CommandIndex The command index to set the command index field of command register. + @param[in] Argument Command argument to set the argument field of command register. + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out. + @param[in] Buffer Contains the data read from / write to the device. + @param[in] BufferSize The size of the buffer. + @param[in] ResponseType RESPONSE_TYPE. + @param[in] TimeOut Time out value in 1 ms unit. + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_OUT_OF_RESOURCES + @retval EFI_TIMEOUT + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +EFIAPI +SendCommand ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData OPTIONAL + ) +{ + EFI_STATUS Status; + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 ResponseDataCount; + UINT32 Data; + UINT64 Data64; + UINT8 Index; + INTN TimeOut2; + BOOLEAN AutoCMD12Enable = FALSE; + + Status = EFI_SUCCESS; + ResponseDataCount = 1; + SdHostData = SDHOST_DATA_FROM_THIS (This); + PciIo = SdHostData->PciIo; + AutoCMD12Enable = (CommandIndex & AUTO_CMD12_ENABLE) ? TRUE : FALSE; + CommandIndex = CommandIndex & CMD_INDEX_MASK; + + if (Buffer != NULL && DataType == NoData) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n")); + goto Exit; + } + + if (((UINTN) Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN) NULL) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n")); + goto Exit; + } + + DEBUG ((EFI_D_INFO, "SendCommand: Command Index = %d \r\n", CommandIndex)); + + TimeOut2 = 1000; // 10 ms + do { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT64) MMIO_PSTATE, + 1, + &Data + ); + + gBS->Stall (10); + } while ((TimeOut2-- > 0) && (Data &BIT0)); + TimeOut2 = 1000; // 10 ms + do { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT64) MMIO_PSTATE, + 1, + &Data + ); + + gBS->Stall (10); + } while ((TimeOut2-- > 0) && (Data & BIT1)); + + // + // Clear status bits + // + Data = 0xFFFF; + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_NINTSTS, + 1, + &Data + ); + + Data = 0xFFFF; + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_ERINTSTS, + 1, + &Data + ); + + + if (Buffer != NULL) { + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT64) MMIO_DMAADR, + 1, + &Buffer + ); + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_BLKSZ, + 1, + &Data + ); + + Data &= ~(0xFFF); + if (BufferSize <= SdHostData->BlockLength) { + Data |= (BufferSize | 0x7000); + } else { + Data |= (SdHostData->BlockLength | 0x7000); + } + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_BLKSZ, + 1, + &Data + ); + + if (BufferSize <= SdHostData->BlockLength) { + Data = 1; + } else { + Data = BufferSize / SdHostData->BlockLength; + } + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_BLKCNT, + 1, + &Data + ); + + } else { + Data = 0; + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_BLKSZ, + 1, + &Data + ); + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_BLKCNT, + 1, + &Data + ); + } + + // + // Argument + // + Data = Argument; + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT64) MMIO_CMDARG, + 1, + &Data + ); + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_XFRMODE, + 1, + &Data + ); + + DEBUG ((EFI_D_INFO, "Transfer mode read = 0x%x \r\n", (Data & 0xFFFF))); + + // + // BIT0 - DMA Enable + // BIT2 - Auto Cmd12 + // + if (DataType == InData) { + Data |= BIT4 | BIT0; + } else if (DataType == OutData){ + Data &= ~BIT4; + Data |= BIT0; + } else { + Data &= ~(BIT4 | BIT0); + } + + if (BufferSize <= SdHostData->BlockLength) { + Data &= ~(BIT5 | BIT1 | BIT2); + Data |= BIT1; // Enable block count always + } else { + if (SdHostData->IsAutoStopCmd && AutoCMD12Enable) { + Data |= (BIT5 | BIT1 | BIT2); + } else { + Data |= (BIT5 | BIT1); + } + } + + DEBUG ((EFI_D_INFO, "Transfer mode write = 0x%x \r\n", (Data & 0xffff))); + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_XFRMODE, + 1, + &Data + ); + + // + //Command + // + //ResponseTypeSelect IndexCheck CRCCheck ResponseType + // 00 0 0 NoResponse + // 01 0 1 R2 + // 10 0 0 R3, R4 + // 10 1 1 R1, R5, R6, R7 + // 11 1 1 R1b, R5b + // + switch (ResponseType) { + case ResponseNo: + Data = (CommandIndex << 8); + ResponseDataCount = 0; + break; + + case ResponseR1: + case ResponseR5: + case ResponseR6: + case ResponseR7: + Data = (CommandIndex << 8) | BIT1 | BIT4| BIT3; + ResponseDataCount = 1; + break; + + case ResponseR1b: + case ResponseR5b: + Data = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3; + ResponseDataCount = 1; + break; + + case ResponseR2: + Data = (CommandIndex << 8) | BIT0 | BIT3; + ResponseDataCount = 4; + break; + + case ResponseR3: + case ResponseR4: + Data = (CommandIndex << 8) | BIT1; + ResponseDataCount = 1; + break; + + default: + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n")); + goto Exit; + } + + if (DataType != NoData) { + Data |= BIT5; + } + + HostLEDEnable (This, TRUE); + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_SDCMD, + 1, + &Data + ); + + Data = 0; + do { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_ERINTSTS, + 1, + &Data + ); + + if ((Data & 0x07FF) != 0) { + Status = GetErrorReason (CommandIndex, (UINT16) Data); + DEBUG ((EFI_D_ERROR, "SendCommand: Error happens \r\n")); + goto Exit; + } + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_NINTSTS, + 1, + &Data + ); + + if ((Data & BIT0) == BIT0) { + // + //Command completed, can read response + // + if (DataType == NoData) { + break; + } else { + // + // Transfer completed + // + if ((Data & BIT1) == BIT1) { + break; + } + } + } + + gBS->Stall (1 * 1000); + + TimeOut --; + + } while (TimeOut > 0); + + if (TimeOut == 0) { + Status = EFI_TIMEOUT; + DEBUG ((EFI_D_ERROR, "SendCommand: Time out \r\n")); + goto Exit; + } + + if (ResponseData != NULL) { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT64) MMIO_RESP, + ResponseDataCount, + ResponseData + ); + + if (ResponseType == ResponseR2) { + // + // Adjustment for R2 response + // + Data = 1; + for (Index = 0; Index < ResponseDataCount; Index++) { + Data64 = LShiftU64 (*ResponseData, 8); + *ResponseData = (UINT32) ((Data64 & 0xFFFFFFFF) | Data); + Data = (UINT32) RShiftU64 (Data64, 32); + ResponseData++; + } + } + } + +Exit: + HostLEDEnable (This, FALSE); + return Status; +} + + +/** + Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency. + It depends on the max frequency the host can support, divider, and host speed mode. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] MaxFrequency Max frequency in HZ. + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT + +**/ +EFI_STATUS +EFIAPI +SetClockFrequency ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 MaxFrequency + ) +{ + UINT32 Data; + UINT16 FreqSelBits; + EFI_STATUS Status; + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 TimeOutCount; + UINT32 Revision; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + PciIo = SdHostData->PciIo; + Data = 0; + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &Data + ); + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_CTRLRVER, + 1, + &Revision + ); + + Revision &= 0x000000FF; + + Status = DividedClockModeBits ( + SdHostData->BaseClockInMHz * 1000 * 1000, + MaxFrequency, + (Revision < SDHCI_SPEC_300), + &FreqSelBits + ); + + if (EFI_ERROR (Status)) { + // + // Cannot reach MaxFrequency with SdHostData->BaseClockInMHz. + // + ASSERT_EFI_ERROR (Status); + return Status; + } + + Data = 0; + + // + // Enable internal clock and Stop Clock Enable + // + Data = BIT0; + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &Data + ); + + TimeOutCount = TIME_OUT_1S; + do { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &Data + ); + + gBS->Stall (1 * 1000); + TimeOutCount --; + if (TimeOutCount == 0) { + DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n")); + return EFI_TIMEOUT; + } + } while ((Data & BIT1) != BIT1); + + DEBUG ((EFI_D_INFO, "Base Clock In MHz: %d\r\n", SdHostData->BaseClockInMHz)); + + Data = (BIT0 | ((UINT32) FreqSelBits)); + DEBUG ((EFI_D_INFO, "Data write to MMIO_CLKCTL: 0x%04x \r\n", Data)); + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &Data + ); + + TimeOutCount = TIME_OUT_1S; + do { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &Data + ); + + gBS->Stall (1 * 1000); + TimeOutCount --; + if (TimeOutCount == 0) { + DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n")); + return EFI_TIMEOUT; + } + } while ((Data & BIT1) != BIT1); + gBS->Stall (20 * 1000); + Data |= BIT2; + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &Data + ); + + return EFI_SUCCESS; +} + + +/** + Set bus width of the host controller + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] BusWidth Bus width in 1, 4, 8 bits. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +EFIAPI +SetBusWidth ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BusWidth + ) +{ + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Data; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) { + DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n")); + return EFI_INVALID_PARAMETER; + } + + if ((SdHostData->SdHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) { + DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n")); + return EFI_INVALID_PARAMETER; + } + + PciIo = SdHostData->PciIo; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_HOSTCTL, + 1, + &Data + ); + // + // BIT5 8-bit MMC Support (MMC8): + // If set, IOH supports 8-bit MMC. When cleared, IOH does not support this feature + // + if (BusWidth == 8) { + DEBUG ((EFI_D_INFO, "Bus Width is 8-bit ... \r\n")); + Data |= BIT5; + } else if (BusWidth == 4) { + DEBUG ((EFI_D_INFO, "Bus Width is 4-bit ... \r\n")); + Data &= ~BIT5; + Data |= BIT1; + } else { + DEBUG ((EFI_D_INFO, "Bus Width is 1-bit ... \r\n")); + Data &= ~BIT5; + Data &= ~BIT1; + } + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_HOSTCTL, + 1, + &Data + ); + + return EFI_SUCCESS; +} + + +/** + Set voltage which could supported by the host controller. + Support 0(Power off the host), 1.8V, 3.0V, 3.3V + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] Voltage Units in 0.1 V. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +EFIAPI +SetHostVoltage ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 Voltage + ) +{ + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Data; + EFI_STATUS Status; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + PciIo = SdHostData->PciIo; + Status = EFI_SUCCESS; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_PWRCTL, + 1, + &Data + ); + + if (Voltage == 0) { + // + // Power Off the host + // + Data &= ~BIT0; + } else if (Voltage <= 18 && This->HostCapability.V18Support) { + // + // 1.8V + // + Data |= (BIT1 | BIT3 | BIT0); + } else if (Voltage > 18 && Voltage <= 30 && This->HostCapability.V30Support) { + // + // 3.0V + // + Data |= (BIT2 | BIT3 | BIT0); + } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) { + // + // 3.3V + // + Data |= (BIT1 | BIT2 | BIT3 | BIT0); + } else { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_PWRCTL, + 1, + &Data + ); + + gBS->Stall (10 * 1000); + +Exit: + return Status; +} + + +/** + Reset the host controller. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] ResetAll TRUE to reset all. + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT + +**/ +EFI_STATUS +EFIAPI +ResetSdHost ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN RESET_TYPE ResetType + ) +{ + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 Data; + UINT16 ErrStatus; + UINT32 Mask; + UINT32 TimeOutCount; + UINT16 SaveClkCtl; + UINT16 ZeroClkCtl; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + PciIo = SdHostData->PciIo; + Mask = 0; + ErrStatus = 0; + + if (ResetType == Reset_Auto) { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_ERINTSTS, + 1, + &ErrStatus + ); + + if ((ErrStatus & 0xF) != 0) { + // + // Command Line + // + Mask |= BIT1; + } + if ((ErrStatus & 0x70) != 0) { + // + // Data Line + // + Mask |= BIT2; + } + } + + if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) { + Mask |= BIT2; + } + if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) { + Mask |= BIT1; + } + if (ResetType == Reset_All) { + Mask = BIT0; + } + + if (Mask == 0) { + return EFI_SUCCESS; + } + + // + // To improve SD stability, we zero the MMIO_CLKCTL register and + // stall for 50 microseconds before reseting the controller. We + // restore the register setting following the reset operation. + // + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &SaveClkCtl + ); + + ZeroClkCtl = (UINT16) 0; + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &ZeroClkCtl + ); + + gBS->Stall (50); + + // + // Reset the SD host controller + // + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_SWRST, + 1, + &Mask + ); + + Data = 0; + TimeOutCount = TIME_OUT_1S; + do { + + gBS->Stall (1 * 1000); + + TimeOutCount --; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_SWRST, + 1, + &Data + ); + + if ((Data & Mask) == 0) { + break; + } + } while (TimeOutCount > 0); + + // + // We now restore the MMIO_CLKCTL register which we set to 0 above. + // + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CLKCTL, + 1, + &SaveClkCtl + ); + + if (TimeOutCount == 0) { + DEBUG ((EFI_D_ERROR, "ResetSdHost: Time out \r\n")); + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + + +/** + Enable auto stop on the host controller. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] Enable TRUE to enable, FALSE to disable. + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT + +**/ +EFI_STATUS +EFIAPI +EnableAutoStopCmd ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ) +{ + SDHOST_DATA *SdHostData; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + SdHostData->IsAutoStopCmd = Enable; + + return EFI_SUCCESS; +} + + +/** + Set the Block length on the host controller. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] BlockLength card supportes block length. + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT + +**/ +EFI_STATUS +EFIAPI +SetBlockLength ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BlockLength + ) +{ + SDHOST_DATA *SdHostData; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + DEBUG ((EFI_D_INFO, "Block length on the host controller: %d \r\n", BlockLength)); + SdHostData->BlockLength = BlockLength; + + return EFI_SUCCESS; +} + + +/** + Find whether these is a card inserted into the slot. If so init the host. + If not, return EFI_NOT_FOUND. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + + @retval EFI_SUCCESS + @retval EFI_NOT_FOUND + +**/ +EFI_STATUS +EFIAPI +DetectCardAndInitHost ( + IN EFI_SD_HOST_IO_PROTOCOL *This + ) +{ + SDHOST_DATA *SdHostData; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 Data; + EFI_STATUS Status; + UINT8 Voltages[] = { 33, 30, 18 }; + UINTN Loop; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + PciIo = SdHostData->PciIo; + Status = EFI_NOT_FOUND; + + Data = 0; + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT64) MMIO_PSTATE, + 1, + &Data + ); + + if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) { + // + // Has no card inserted + // + DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: No Cards \r\n")); + Status = EFI_NOT_FOUND; + goto Exit; + } + DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: Find Cards \r\n")); + + Status = EFI_NOT_FOUND; + for (Loop = 0; Loop < sizeof (Voltages); Loop++) { + DEBUG (( + EFI_D_INFO, + "DetectCardAndInitHost: SetHostVoltage %d.%dV \r\n", + Voltages[Loop] / 10, + Voltages[Loop] % 10 + )); + Status = SetHostVoltage (This, Voltages[Loop]); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [failed]\n")); + } else { + DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [success]\n")); + break; + } + } + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set voltage \r\n")); + goto Exit; + } + + Status = SetClockFrequency (This, FREQUENCY_OD); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set frequency \r\n")); + goto Exit; + } + SetBusWidth (This, 1); + + // + // Enable normal status change + // + Data = (BIT0 | BIT1); + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_NINTEN, + 1, + &Data + ); + + // + // Enable error status change + // + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_ERINTEN, + 1, + &Data + ); + + Data |= (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8); + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_ERINTEN, + 1, + &Data + ); + + // + // Data transfer Timeout control + // + Data = 0x0E; + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + 0, + (UINT64) MMIO_TOCTL, + 1, + &Data + ); + // + // Set Default Bus width as 1 bit + // + +Exit: + return Status; + +} + + +/** + Entry point for EFI drivers. + + @param[in] ImageHandle EFI_HANDLE. + @param[in] SystemTable EFI_SYSTEM_TABLE. + + @retval EFI_SUCCESS Driver is successfully loaded. + @retval Others Failed. + +**/ +EFI_STATUS +EFIAPI +InitializeSdController ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gSdControllerDriverBinding, + ImageHandle, + &gSdControllerName, + &gSdControllerName2 + ); +} + + +/** + Test to see if this driver supports ControllerHandle. Any + ControllerHandle that has SdHostIoProtocol installed will be supported. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test. + @param[in] RemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +SdControllerSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS OpenStatus; + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_CLASSC PciClass; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + UINTN Seg, Bus, Dev, Func; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSdHostIoProtocolGuid, + (VOID **) &SdHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + DEBUG (( DEBUG_INFO, "SdHost controller is already started\n")); + return EFI_ALREADY_STARTED; + } + + // + // Test whether there is PCI IO Protocol attached on the controller handle. + // + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (OpenStatus)) { + return OpenStatus; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CLASSCODE_OFFSET, + sizeof (PCI_CLASSC) / sizeof (UINT8), + &PciClass + ); + + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + } + + // + // Test whether the controller belongs to SD type + // + if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) || + (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) || + ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA)) + ) { + + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + } + + Status = PciIo->GetLocation ( + PciIo, + &Seg, + &Bus, + &Dev, + &Func + ); + + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + } + + if ((Seg != 0) || (Bus != 0) || (Dev != 27) || (Func != 0)) { + // + // This is not the SD controller, bail. + // + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + } + + DEBUG ((EFI_D_INFO, "%a(#%d) - Seg %d, bus:%d, Dev:%d, Func:%d\n", __FUNCTION__, __LINE__, Seg, Bus, Dev, Func)); + +ON_EXIT: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + + +/** + Starting the SD Host Controller Driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test. + @param[in] RemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error. + EFI_OUT_OF_RESOURCES- Failed due to resource shortage. + +**/ +EFI_STATUS +EFIAPI +SdControllerStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + SDHOST_DATA *SdHostData; + UINT32 Data; + + SdHostData = NULL; + Data = 0; + + // + // Open PCI I/O Protocol and save pointer to open protocol + // in private data area. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Enable the SD Host Controller MMIO space + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + SdHostData = (SDHOST_DATA *) AllocateZeroPool (sizeof (SDHOST_DATA)); + if (SdHostData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + SdHostData->Signature = SDHOST_DATA_SIGNATURE; + SdHostData->PciIo = PciIo; + + CopyMem (&SdHostData->SdHostIo, &mSdHostIo, sizeof (EFI_SD_HOST_IO_PROTOCOL)); + + ResetSdHost (&SdHostData->SdHostIo, Reset_All); + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64) MMIO_CTRLRVER, + 1, + &Data + ); + + SdHostData->SdHostIo.HostCapability.HostVersion = Data & 0xFF; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: HostVersion 0x%x \r\n", SdHostData->SdHostIo.HostCapability.HostVersion)); + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT64) MMIO_CAP, + 1, + &Data + ); + + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MMIO_CAP 0x%x \r\n", Data)); + if ((Data & BIT18) != 0) { + SdHostData->SdHostIo.HostCapability.BusWidth8 = TRUE; + } + + if ((Data & BIT21) != 0) { + SdHostData->SdHostIo.HostCapability.HighSpeedSupport = TRUE; + } + + if ((Data & BIT24) != 0) { + SdHostData->SdHostIo.HostCapability.V33Support = TRUE; + } + + if ((Data & BIT25) != 0) { + SdHostData->SdHostIo.HostCapability.V30Support = TRUE; + } + + if ((Data & BIT26) != 0) { + SdHostData->SdHostIo.HostCapability.V18Support = TRUE; + } + + SdHostData->SdHostIo.HostCapability.BusWidth4 = TRUE; + + if (SdHostData->SdHostIo.HostCapability.HostVersion < SDHCI_SPEC_300) { + SdHostData->BaseClockInMHz = (Data >> 8) & 0x3F; + } else { + SdHostData->BaseClockInMHz = (Data >> 8) & 0xFF; + + } + + SdHostData->BlockLength = 512 << ((Data >> 16) & 0x03); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: BlockLength 0x%x \r\n", SdHostData->BlockLength)); + SdHostData->IsAutoStopCmd = TRUE; + + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiSdHostIoProtocolGuid, + EFI_NATIVE_INTERFACE, + &SdHostData->SdHostIo + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Install the component name protocol + // + SdHostData->ControllerNameTable = NULL; + + AddUnicodeString2 ( + "eng", + gSdControllerName.SupportedLanguages, + &SdHostData->ControllerNameTable, + L"SD Host Controller", + TRUE + ); + + AddUnicodeString2 ( + "en", + gSdControllerName2.SupportedLanguages, + &SdHostData->ControllerNameTable, + L"SD Host Controller", + FALSE + ); + +Exit: + if (EFI_ERROR (Status)) { + if (SdHostData != NULL) { + FreePool (SdHostData); + } + } + + return Status; +} + + +/** + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to stop driver on. + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer. + @param[in] ChildHandleBuffer List of handles for the children we need to stop. + + @retval EFI_SUCCESS + @retval others + +**/ +EFI_STATUS +EFIAPI +SdControllerStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + SDHOST_DATA *SdHostData; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSdHostIoProtocolGuid, + (VOID **) &SdHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + // + // Test whether the Controller handler passed in is a valid + // Usb controller handle that should be supported, if not, + // return the error status directly + // + if (EFI_ERROR (Status)) { + return Status; + } + + SetHostVoltage (SdHostIo, 0); + + SdHostData = SDHOST_DATA_FROM_THIS(SdHostIo); + + // + // Uninstall Block I/O protocol from the device handle + // + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSdHostIoProtocolGuid, + SdHostIo + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + FreeUnicodeStringTable (SdHostData->ControllerNameTable); + + FreePool (SdHostData); + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h new file mode 100644 index 0000000..a702565 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.h @@ -0,0 +1,314 @@ +/** @file + The definition for SD host controller driver model and HC protocol routines. + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 _SD_CONTROLLER_H_ +#define _SD_CONTROLLER_H_ + +#include <Uefi.h> +#include <Protocol/PciIo.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/BaseLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <IndustryStandard/Pci22.h> +#include <Library/GpioLib.h> +#include "ComponentName.h" +#include "SdHostIo.h" + +extern EFI_DRIVER_BINDING_PROTOCOL gSdControllerDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gSdControllerName; +extern EFI_COMPONENT_NAME2_PROTOCOL gSdControllerName2; + +#define SDHOST_DATA_SIGNATURE SIGNATURE_32 ('s', 'd', 'h', 's') + +#define BLOCK_SIZE 0x200 +#define TIME_OUT_1S 1000 + +#pragma pack(1) + +// +// PCI Class Code structure +// +typedef struct { + UINT8 PI; + UINT8 SubClassCode; + UINT8 BaseCode; +} PCI_CLASSC; + +#pragma pack() + +typedef struct { + UINTN Signature; + EFI_SD_HOST_IO_PROTOCOL SdHostIo; + EFI_PCI_IO_PROTOCOL *PciIo; + BOOLEAN IsAutoStopCmd; + UINT32 BaseClockInMHz; + UINT32 CurrentClockInKHz; + UINT32 BlockLength; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} SDHOST_DATA; + +#define SDHOST_DATA_FROM_THIS(a) \ + CR(a, SDHOST_DATA, SdHostIo, SDHOST_DATA_SIGNATURE) + +/** + Test to see if this driver supports ControllerHandle. Any + ControllerHandle that has SdHostIoProtocol installed will be supported. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test. + @param[in] RemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +SdControllerSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Starting the SD Host Controller Driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test. + @param[in] RemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error. + EFI_OUT_OF_RESOURCES- Failed due to resource shortage. + +**/ +EFI_STATUS +EFIAPI +SdControllerStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to stop driver on. + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer. + @param[in] ChildHandleBuffer List of handles for the children we need to stop. + + @retval EFI_SUCCESS + @retval others + +**/ +EFI_STATUS +EFIAPI +SdControllerStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + The main function used to send the command to the card inserted into the SD host slot. + It will assemble the arguments to set the command register and wait for the command + and transfer completed until timeout. Then it will read the response register to fill + the ResponseData. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] CommandIndex The command index to set the command index field of command register. + @param[in] Argument Command argument to set the argument field of command register. + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out. + @param[in] Buffer Contains the data read from / write to the device. + @param[in] BufferSize The size of the buffer. + @param[in] ResponseType RESPONSE_TYPE. + @param[in] TimeOut Time out value in 1 ms unit. + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_OUT_OF_RESOURCES + @retval EFI_TIMEOUT + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +EFIAPI +SendCommand ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData OPTIONAL + ); + +/** + Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency. + It depends on the max frequency the host can support, divider, and host speed mode. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] MaxFrequency Max frequency in HZ. + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT + +**/ +EFI_STATUS +EFIAPI +SetClockFrequency ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 MaxFrequencyInKHz + ); + +/** + Set bus width of the host controller + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] BusWidth Bus width in 1, 4, 8 bits. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +EFIAPI +SetBusWidth ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BusWidth + ); + +/** + Set voltage which could supported by the host controller. + Support 0(Power off the host), 1.8V, 3.0V, 3.3V + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] Voltage Units in 0.1 V. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +EFIAPI +SetHostVoltage ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 Voltage + ); + +/** + Reset the host controller. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] ResetAll TRUE to reset all. + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT + +**/ +EFI_STATUS +EFIAPI +ResetSdHost ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN RESET_TYPE ResetType + ); + +/** + Enable auto stop on the host controller. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] Enable TRUE to enable, FALSE to disable. + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT + +**/ +EFI_STATUS +EFIAPI +EnableAutoStopCmd ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ); + +/** + Find whether these is a card inserted into the slot. If so init the host. + If not, return EFI_NOT_FOUND. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + + @retval EFI_SUCCESS + @retval EFI_NOT_FOUND + +**/ +EFI_STATUS +EFIAPI +DetectCardAndInitHost ( + IN EFI_SD_HOST_IO_PROTOCOL *This + ); + +/** + Set the Block length on the host controller. + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] BlockLength card supportes block length. + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT + +**/ +EFI_STATUS +EFIAPI +SetBlockLength ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BlockLength + ); + +/** + Enable/Disable High Speed transfer mode + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] Enable TRUE to Enable, FALSE to Disable + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +SetHighSpeedMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ); + +EFI_STATUS +EFIAPI +SetDDRMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf new file mode 100644 index 0000000..499c9b7 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdControllerDxe.inf @@ -0,0 +1,59 @@ +## @file +# Component Description File For SdControllerDxe Module. +# +# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> +# +# 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 = 0x00010005 + BASE_NAME = SdController + FILE_GUID = 90A330BD-6F89-4900-933A-C25EB4356348 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeSdController + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gSdControllerDriverBinding +# COMPONENT_NAME = gSdControllerName +# COMPONENT_NAME2 = gSdControllerName2 +# + +[Sources] + SdController.c + SdController.h + ComponentName.c + ComponentName.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + PcdLib + +[Protocols] + gEfiPciIoProtocolGuid ## TO_START + gEfiSdHostIoProtocolGuid ## BY_START + +[FeaturePcd] diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c new file mode 100644 index 0000000..cb7a1bb --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c @@ -0,0 +1,638 @@ +/** @file + CEATA specific functions implementation + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "SdMediaDevice.h" + +/** + Send RW_MULTIPLE_REGISTER command + + @param[in] CardData Pointer to CARD_DATA. + @param[in] Address Register address. + @param[in] ByteCount Buffer size. + @param[in] Write TRUE means write, FALSE means read. + @param[in] Buffer Buffer pointer. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +ReadWriteMultipleRegister ( + IN CARD_DATA *CardData, + IN UINT16 Address, + IN UINT8 ByteCount, + IN BOOLEAN Write, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINT32 Argument; + + Status = EFI_SUCCESS; + + if ((Address % 4 != 0) || (ByteCount % 4 != 0)) { + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + Argument = (Address << 16) | ByteCount; + if (Write) { + Argument |= BIT31; + } + + if (Write) { + CopyMem (CardData->AlignedBuffer, Buffer, ByteCount); + + Status = SendCommand ( + CardData, + RW_MULTIPLE_REGISTER, + Argument, + OutData, + CardData->AlignedBuffer, + ByteCount, + ResponseR1b, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + } else { + Status = SendCommand ( + CardData, + RW_MULTIPLE_REGISTER, + Argument, + InData, + CardData->AlignedBuffer, + ByteCount, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + CopyMem (Buffer, CardData->AlignedBuffer, ByteCount); + } + } +Exit: + return Status; +} + + +/** + Send ReadWriteMultipleBlock command with RW_MULTIPLE_REGISTER command + + @param[in] CardData Pointer to CARD_DATA. + @param[in] DataUnitCount Buffer size in 512 bytes unit. + @param[in] Write TRUE means write, FALSE means read. + @param[in] Buffer Buffer pointer. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +ReadWriteMultipleBlock ( + IN CARD_DATA *CardData, + IN UINT16 DataUnitCount, + IN BOOLEAN Write, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + UINT32 TransferLength; + + Status = EFI_SUCCESS; + SdHostIo = CardData->SdHostIo; + + TransferLength = DataUnitCount * DATA_UNIT_SIZE; + if (TransferLength > SdHostIo->HostCapability.BoundarySize) { + return EFI_INVALID_PARAMETER; + } + + if (Write) { + CopyMem (CardData->AlignedBuffer, Buffer, TransferLength); + + Status = SendCommand ( + CardData, + RW_MULTIPLE_BLOCK, + (DataUnitCount | BIT31), + OutData, + CardData->AlignedBuffer, + TransferLength, + ResponseR1b, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + } else { + Status = SendCommand ( + CardData, + RW_MULTIPLE_BLOCK, + DataUnitCount, + InData, + CardData->AlignedBuffer, + TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + CopyMem (Buffer, CardData->AlignedBuffer, TransferLength); + } + } + + return Status; +} + + +/** + Send software reset + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +SoftwareReset ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + UINT8 Data; + UINT32 TimeOut; + + Data = BIT2; + + Status = FastIO (CardData, Reg_Control, &Data, TRUE); + if (EFI_ERROR (Status)) { + goto Exit; + } + + TimeOut = 5 * 1000; + + do { + gBS->Stall (1 * 1000); + Status = FastIO (CardData, Reg_Control, &Data, FALSE); + if (EFI_ERROR (Status)) { + goto Exit; + } + + if ((Data & BIT2) == BIT2) { + break; + } + + TimeOut--; + } while (TimeOut > 0); + + if (TimeOut == 0) { + Status = EFI_TIMEOUT; + goto Exit; + } + + Data &= ~BIT2; + Status = FastIO (CardData, Reg_Control, &Data, TRUE); + + TimeOut = 5 * 1000; + + do { + gBS->Stall (1 * 1000); + Status = FastIO (CardData, Reg_Control, &Data, FALSE); + if (EFI_ERROR (Status)) { + goto Exit; + } + + if ((Data & BIT2) != BIT2) { + break; + } + + TimeOut--; + } while (TimeOut > 0); + + if (TimeOut == 0) { + Status = EFI_TIMEOUT; + goto Exit; + } + +Exit: + return Status; +} + + +/** + SendATACommand specificed in Taskfile + + @param[in] CardData Pointer to CARD_DATA. + @param[in] TaskFile Pointer to TASK_FILE. + @param[in] Write TRUE means write, FALSE means read. + @param[in] Buffer If NULL, means no data transfer, neither read nor write. + @param[in] SectorCount Buffer size in 512 bytes unit. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +SendATACommand ( + IN CARD_DATA *CardData, + IN TASK_FILE *TaskFile, + IN BOOLEAN Write, + IN UINT8 *Buffer, + IN UINT16 SectorCount + ) +{ + EFI_STATUS Status; + UINT8 Data; + UINT32 TimeOut; + + // + // Write register + // + Status = ReadWriteMultipleRegister ( + CardData, + 0, + sizeof (TASK_FILE), + TRUE, + (UINT8 *) TaskFile + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "ReadWriteMultipleRegister 0x%x\n", Status)); + goto Exit; + } + + TimeOut = 5000; + do { + gBS->Stall (1 * 1000); + Data = 0; + Status = FastIO ( + CardData, + Reg_Command_Status, + &Data, + FALSE + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if (((Data & BIT7) == 0) && ((Data & BIT6) == BIT6)) { + break; + } + + TimeOut --; + } while (TimeOut > 0); + + if (TimeOut == 0) { + DEBUG ((EFI_D_ERROR, "ReadWriteMultipleRegister FastIO EFI_TIMEOUT 0x%x\n", Data)); + Status = EFI_TIMEOUT; + goto Exit; + } + + if (Buffer != NULL) { + Status = ReadWriteMultipleBlock ( + CardData, + SectorCount, + Write, + (UINT8 *) Buffer + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "ReadWriteMultipleBlock EFI_TIMEOUT 0x%x\n", Status)); + goto Exit; + } + + TimeOut = 5 * 1000; + do { + gBS->Stall (1 * 1000); + Data = 0; + Status = FastIO ( + CardData, + Reg_Command_Status, + &Data, + FALSE + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if (((Data & BIT7) == 0) && ((Data & BIT3) == 0)) { + break; + } + + TimeOut --; + } while (TimeOut > 0); + if (TimeOut == 0) { + DEBUG ((EFI_D_ERROR, "ReadWriteMultipleBlock FastIO EFI_TIMEOUT 0x%x\n", Data)); + Status = EFI_TIMEOUT; + goto Exit; + } + + if (((Data & BIT6) == BIT6) && (Data & BIT0) == 0) { + Status = EFI_SUCCESS; + } else { + Status = EFI_DEVICE_ERROR; + } + } + +Exit: + if (EFI_ERROR (Status)) { + SoftwareReset (CardData); + } + + return Status; +} + + +/** + IDENTIFY_DEVICE command + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +IndentifyDevice ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + + ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE)); + + // + // The host only supports nIEN = 0 + // + CardData->TaskFile.Command_Status = IDENTIFY_DEVICE; + Status = SendATACommand ( + CardData, + &CardData->TaskFile, + FALSE, + (UINT8 *) &(CardData->IndentifyDeviceData), + 1 + ); + + return Status; +} + + +/** + FLUSH_CACHE_EXT command + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +FlushCache ( + IN CARD_DATA *CardData + ) +{ + + return EFI_SUCCESS; +} + + +/** + STANDBY_IMMEDIATE command + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +StandByImmediate ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + + ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE)); + + // + // The host only supports nIEN = 0 + // + CardData->TaskFile.Command_Status = STANDBY_IMMEDIATE; + Status = SendATACommand ( + CardData, + &CardData->TaskFile, + FALSE, + NULL, + 0 + ); + + return Status; +} + + +/** + READ_DMA_EXT command + + @param[in] CardData Pointer to CARD_DATA. + @param[in] LBA The starting logical block address to read from on the device. + @param[in] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + @param[in] SectorCount Size in 512 bytes unit. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +ReadDMAExt ( + IN CARD_DATA *CardData, + IN EFI_LBA LBA, + IN UINT8 *Buffer, + IN UINT16 SectorCount + ) +{ + EFI_STATUS Status; + + ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE)); + + // + // The host only supports nIEN = 0 + // + CardData->TaskFile.Command_Status = READ_DMA_EXT; + + CardData->TaskFile.SectorCount = (UINT8) SectorCount; + CardData->TaskFile.SectorCount_Exp = (UINT8) (SectorCount >> 8); + + CardData->TaskFile.LBALow = (UINT8) LBA; + CardData->TaskFile.LBAMid = (UINT8) RShiftU64 (LBA, 8); + CardData->TaskFile.LBAHigh = (UINT8) RShiftU64 (LBA, 16); + + CardData->TaskFile.LBALow_Exp = (UINT8) RShiftU64 (LBA, 24); + CardData->TaskFile.LBAMid_Exp = (UINT8) RShiftU64 (LBA, 32); + CardData->TaskFile.LBAHigh_Exp = (UINT8) RShiftU64 (LBA, 40); + + Status = SendATACommand ( + CardData, + &CardData->TaskFile, + FALSE, + Buffer, + SectorCount + ); + + return Status; +} + + +/** + WRITE_DMA_EXT command + + @param[in] CardData Pointer to CARD_DATA. + @param[in] LBA The starting logical block address to read from on the device. + @param[in] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + @param[in] SectorCount Size in 512 bytes unit. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +WriteDMAExt ( + IN CARD_DATA *CardData, + IN EFI_LBA LBA, + IN UINT8 *Buffer, + IN UINT16 SectorCount + ) +{ + EFI_STATUS Status; + + ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE)); + + // + // The host only supports nIEN = 0 + // + CardData->TaskFile.Command_Status = WRITE_DMA_EXT; + + CardData->TaskFile.SectorCount = (UINT8) SectorCount; + CardData->TaskFile.SectorCount_Exp = (UINT8) (SectorCount >> 8); + + CardData->TaskFile.LBALow = (UINT8) LBA; + CardData->TaskFile.LBAMid = (UINT8) RShiftU64 (LBA, 8); + CardData->TaskFile.LBAHigh = (UINT8) RShiftU64 (LBA, 16); + + CardData->TaskFile.LBALow_Exp = (UINT8) RShiftU64 (LBA, 24); + CardData->TaskFile.LBAMid_Exp = (UINT8) RShiftU64 (LBA, 32); + CardData->TaskFile.LBAHigh_Exp = (UINT8) RShiftU64 (LBA, 40); + + Status = SendATACommand ( + CardData, + &CardData->TaskFile, + TRUE, + Buffer, + SectorCount + ); + + return Status; + +} + + +/** + Judge whether it is CE-ATA device or not. + + @param[in] CardData Pointer to CARD_DATA. + + @retval TRUE + @retval FALSE + +**/ +BOOLEAN +IsCEATADevice ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + + Status = ReadWriteMultipleRegister ( + CardData, + 0, + sizeof (TASK_FILE), + FALSE, + (UINT8 *) &CardData->TaskFile + ); + + if (EFI_ERROR (Status)) { + // + // To bring back the normal MMC card to work + // + CardData->SdHostIo->ResetSdHost (CardData->SdHostIo, Reset_DAT_CMD); + return FALSE; + } + + if (CardData->TaskFile.LBAMid == CE_ATA_SIG_CE && + CardData->TaskFile.LBAHigh == CE_ATA_SIG_AA + ) { + // + // Disable Auto CMD for CE-ATA + // + CardData->SdHostIo->EnableAutoStopCmd (CardData->SdHostIo, FALSE); + return TRUE; + } + + return FALSE; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c new file mode 100644 index 0000000..55fd085 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATABlockIo.c @@ -0,0 +1,384 @@ +/** @file + Block I/O protocol for CE-ATA device + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "SdMediaDevice.h" + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.Reset() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive. + verification operation of the device during reset. + (This parameter is ingored in this driver.) + + @retval EFI_SUCCESS Success + +**/ +EFI_STATUS +EFIAPI +CEATABlockReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + CARD_DATA *CardData; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + + CardData = CARD_DATA_FROM_THIS (This); + SdHostIo = CardData->SdHostIo; + + if (!ExtendedVerification) { + Status = SoftwareReset (CardData); + } else { + Status = SdHostIo->ResetSdHost (SdHostIo, Reset_DAT_CMD); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" )); + return Status; + } + Status = MMCSDCardInit (CardData); + } + + return Status; +} + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] MediaId The media id that the write request is for. + @param[in] LBA The starting logical block address to read from on the device. + The caller is responsible for writing to only legitimate locations. + @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple of the + intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +EFIAPI +CEATABlockReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + CARD_DATA *CardData; + UINT32 TransferSize; + UINT8 *pBuf; + UINT32 Index; + UINT64 Address; + UINT32 Remainder; + UINT64 CEATALBA; + UINT32 BoundarySize; + + Status = EFI_SUCCESS; + CardData = CARD_DATA_FROM_THIS (This); + pBuf = Buffer; + Index = 0; + Address = MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize); + BoundarySize = CardData->SdHostIo->HostCapability.BoundarySize; + + if (!Buffer) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" )); + goto Exit; + } + + if (MediaId != CardData->BlockIoMedia.MediaId) { + Status = EFI_MEDIA_CHANGED; + DEBUG ((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" )); + goto Exit; + } + + if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + DEBUG ((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" )); + goto Exit; + } + + if (BufferSize == 0) { + Status = EFI_SUCCESS; + goto Exit; + } + + if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" )); + goto Exit; + } + + do { + if (BufferSize < BoundarySize) { + TransferSize = (UINT32) BufferSize; + } else { + TransferSize = BoundarySize; + } + + Address += Index * TransferSize; + CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder); + ASSERT(Remainder == 0); + + Status = ReadDMAExt ( + CardData, + CEATALBA, + pBuf, + (UINT16) (TransferSize / DATA_UNIT_SIZE) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize)); + This->Reset (This, TRUE); + goto Exit; + } + + BufferSize -= TransferSize; + pBuf += TransferSize; + Index ++; + } while (BufferSize != 0); + +Exit: + return Status; +} + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] MediaId The media id that the write request is for. + @param[in] LBA The starting logical block address to read from on the device. + The caller is responsible for writing to only legitimate locations. + @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple of the + intrinsic block size of the device. + @param[in] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +EFIAPI +CEATABlockWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + CARD_DATA *CardData; + UINT32 TransferSize; + UINT8 *pBuf; + UINT32 Index; + UINT64 Address; + UINT32 Remainder; + UINT64 CEATALBA; + UINT32 BoundarySize; + + Status = EFI_SUCCESS; + CardData = CARD_DATA_FROM_THIS (This); + pBuf = Buffer; + Index = 0; + Address = MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize); + BoundarySize = CardData->SdHostIo->HostCapability.BoundarySize; + + if (!Buffer) { + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + if (MediaId != CardData->BlockIoMedia.MediaId) { + Status = EFI_MEDIA_CHANGED; + goto Exit; + } + + if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto Exit; + } + + if (BufferSize == 0) { + Status = EFI_SUCCESS; + goto Exit; + } + + if (CardData->BlockIoMedia.ReadOnly) { + Status = EFI_WRITE_PROTECTED; + goto Exit; + } + + if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) { + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + CardData->NeedFlush = TRUE; + + do { + if (BufferSize < BoundarySize) { + TransferSize = (UINT32) BufferSize; + } else { + TransferSize = BoundarySize; + } + + Address += Index * TransferSize; + CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder); + ASSERT (Remainder == 0); + + Status = WriteDMAExt ( + CardData, + CEATALBA, + pBuf, + (UINT16) (TransferSize / DATA_UNIT_SIZE) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize)); + This->Reset (This, TRUE); + goto Exit; + } + + BufferSize -= TransferSize; + pBuf += TransferSize; + Index ++; + } while (BufferSize != 0); + +Exit: + return Status; +} + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function. + (In this driver, this function just returns EFI_SUCCESS.) + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + + @retval EFI_SUCCESS + @retval Others + +**/ +EFI_STATUS +EFIAPI +CEATABlockFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + + CARD_DATA *CardData; + + CardData = CARD_DATA_FROM_THIS (This); + + if (CardData->NeedFlush) { + CardData->NeedFlush = FALSE; + FlushCache (CardData); + } + + return EFI_SUCCESS; +} + + +/** + CEATA card BlockIo init function. + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval Others + +**/ +EFI_STATUS +CEATABlockIoInit ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + UINT64 MaxSize; + UINT32 Remainder; + + // + // BlockIO protocol + // + CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + CardData->BlockIo.Media = &(CardData->BlockIoMedia); + CardData->BlockIo.Reset = CEATABlockReset; + CardData->BlockIo.ReadBlocks = CEATABlockReadBlocks ; + CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks; + CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks; + + CardData->BlockIoMedia.MediaId = 0; + CardData->BlockIoMedia.RemovableMedia = FALSE; + CardData->BlockIoMedia.MediaPresent = TRUE; + CardData->BlockIoMedia.LogicalPartition = FALSE; + + if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) { + CardData->BlockIoMedia.ReadOnly = TRUE; + } else { + CardData->BlockIoMedia.ReadOnly = FALSE; + } + + CardData->BlockIoMedia.WriteCaching = FALSE; + CardData->BlockIoMedia.IoAlign = 1; + + Status = IndentifyDevice (CardData); + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + //Some device does not support this feature + // + if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) { + CardData->BlockIoMedia.ReadOnly = TRUE; + } + + CardData->BlockIoMedia.BlockSize = (1 << CardData->IndentifyDeviceData.Sectorsize); + ASSERT (CardData->BlockIoMedia.BlockSize >= 12); + + + MaxSize = *(UINT64 *) (CardData->IndentifyDeviceData.MaximumLBA); + MaxSize = MultU64x32 (MaxSize, 512); + + Remainder = 0; + CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder); + ASSERT (Remainder == 0); + + CardData->BlockIoMedia.LastBlock = (EFI_LBA) (CardData->BlockNumber - 1); + +Exit: + return Status; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c new file mode 100644 index 0000000..15fdaf6 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.c @@ -0,0 +1,219 @@ +/** @file + UEFI Component Name(2) protocol implementation for SD media device driver. + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "SdMediaDevice.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSdMediaDeviceName = { + SdMediaDeviceGetDriverName, + SdMediaDeviceGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSdMediaDeviceName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SdMediaDeviceGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SdMediaDeviceGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdMediaDeviceDriverNameTable[] = { + { "eng;en", L"UEFI MMC/SD Media Device Driver" }, + { NULL, NULL } +}; + + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form 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 name 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param[in] Language 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 SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 3066 or ISO 639-2 language code format. + + @param[out] DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language 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 +SdMediaDeviceGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mSdMediaDeviceDriverNameTable, + DriverName, + (BOOLEAN) (This == &gSdMediaDeviceName) + ); +} + + +/** + 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 specified by + ControllerHandle and ChildHandle in the form 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 controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param[in] ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param[in] ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + 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 name of a + child controller. + + @param[in] Language 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 SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 3066 or ISO 639-2 language code format. + + @param[out] ControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for 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 +SdMediaDeviceGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + CARD_DATA *CardData; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gSdMediaDeviceDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + CardData = CARD_DATA_FROM_THIS (BlockIo); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + CardData->ControllerNameTable, + ControllerName, + (BOOLEAN) (This == &gSdMediaDeviceName) + ); + +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h new file mode 100644 index 0000000..3dea441 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/ComponentName.h @@ -0,0 +1,145 @@ +/** @file + This file contains the declarations for component name routines. + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 _COMPONENT_NAME_H_ +#define _COMPONENT_NAME_H_ + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form 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 name 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param[in] Language 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 SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 3066 or ISO 639-2 language code format. + + @param[out] DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language 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 +SdMediaDeviceGetDriverName ( + 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 specified by + ControllerHandle and ChildHandle in the form 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 controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param[in] ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param[in] ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + 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 name of a + child controller. + + @param[in] Language 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 SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 3066 or ISO 639-2 language code format. + + @param[out] ControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for 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 +SdMediaDeviceGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c new file mode 100644 index 0000000..6180a25 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDBlockIo.c @@ -0,0 +1,547 @@ +/** @file + Block I/O protocol for MMC/SD device. + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "SdMediaDevice.h" + +/** + Implements EFI_BLOCK_IO_PROTOCOL.Reset() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive. + verification operation of the device during reset. + (This parameter is ignored in this driver.) + + @retval EFI_SUCCESS Success + +**/ +EFI_STATUS +EFIAPI +MMCSDBlockReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + CARD_DATA *CardData; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + + CardData = CARD_DATA_FROM_THIS (This); + SdHostIo = CardData->SdHostIo; + + return SdHostIo->ResetSdHost (SdHostIo, Reset_DAT_CMD); + } + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] MediaId The media id that the write request is for. + @param[in] LBA The starting logical block address to read from on the device. + The caller is responsible for writing to only legitimate locations. + @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple of the + intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +EFIAPI +MMCSDBlockReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT32 Address; + CARD_DATA *CardData; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + UINT32 RemainingLength; + UINT32 TransferLength; + UINT8 *BufferPointer; + BOOLEAN SectorAddressing; + UINTN TotalBlock; + + DEBUG ((EFI_D_INFO, "Read(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize)); + Status = EFI_SUCCESS; + CardData = CARD_DATA_FROM_THIS (This); + SdHostIo = CardData->SdHostIo; + + if (MediaId != CardData->BlockIoMedia.MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (ModU64x32 (BufferSize, CardData->BlockIoMedia.BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + if ((CardData->CardType == SdMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) { + SectorAddressing = TRUE; + } else { + SectorAddressing = FALSE; + } + if (SectorAddressing) { + // + //Block Address + // + Address = (UINT32) DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512); + } else { + // + //Byte Address + // + Address = (UINT32) MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize); + } + TotalBlock = (UINTN) DivU64x32 (BufferSize, CardData->BlockIoMedia.BlockSize); + if (LBA + TotalBlock > CardData->BlockIoMedia.LastBlock + 1) { + return EFI_INVALID_PARAMETER; + } + + if (!Buffer) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks:Invalid parameter \r\n")); + goto Done; + } + + if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Bad buffer size \r\n")); + goto Done; + } + + if (BufferSize == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + BufferPointer = Buffer; + RemainingLength = (UINT32) BufferSize; + + while (RemainingLength > 0) { + if ((BufferSize > CardData->BlockIoMedia.BlockSize)) { + if (RemainingLength > SdHostIo->HostCapability.BoundarySize) { + TransferLength = SdHostIo->HostCapability.BoundarySize; + } else { + TransferLength = RemainingLength; + } + + if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { + if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) { + Status = SendCommand ( + CardData, + SET_BLOCKLEN, + CardData->BlockIoMedia.BlockSize, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + break; + } + } + Status = SendCommand ( + CardData, + SET_BLOCK_COUNT, + TransferLength / CardData->BlockIoMedia.BlockSize, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + break; + } + } + Status = SendCommand ( + CardData, + READ_MULTIPLE_BLOCK, + Address, + InData, + CardData->AlignedBuffer, + TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n")); + break; + } + } else { + if (RemainingLength > CardData->BlockIoMedia.BlockSize) { + TransferLength = CardData->BlockIoMedia.BlockSize; + } else { + TransferLength = RemainingLength; + } + + Status = SendCommand ( + CardData, + READ_SINGLE_BLOCK, + Address, + InData, + CardData->AlignedBuffer, + (UINT32) TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n")); + break; + } + } + CopyMem (BufferPointer, CardData->AlignedBuffer, TransferLength); + if (SectorAddressing) { + // + //Block Address + // + Address += TransferLength / 512; + } else { + // + //Byte Address + // + Address += TransferLength; + } + BufferPointer += TransferLength; + RemainingLength -= TransferLength; + } + + if (EFI_ERROR (Status)) { + if ((CardData->CardType == SdMemoryCard) || + (CardData->CardType == SdMemoryCard2)|| + (CardData->CardType == SdMemoryCard2High)) { + SendCommand ( + CardData, + STOP_TRANSMISSION, + 0, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + } else { + SendCommand ( + CardData, + STOP_TRANSMISSION, + 0, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + } + + } + +Done: + DEBUG ((EFI_D_INFO, "MMCSDBlockReadBlocks: Status = %r\n", Status)); + return Status; +} + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function. + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + @param[in] MediaId The media id that the write request is for. + @param[in] LBA The starting logical block address to read from on the device. + The caller is responsible for writing to only legitimate locations. + @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple of the + intrinsic block size of the device. + @param[in] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +EFIAPI +MMCSDBlockWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT32 Address; + CARD_DATA *CardData; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + UINT32 RemainingLength; + UINT32 TransferLength; + UINT8 *BufferPointer; + BOOLEAN SectorAddressing; + + DEBUG ((EFI_D_INFO, "Write(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize)); + Status = EFI_SUCCESS; + CardData = CARD_DATA_FROM_THIS (This); + SdHostIo = CardData->SdHostIo; + if ((CardData->CardType == SdMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) { + SectorAddressing = TRUE; + } else { + SectorAddressing = FALSE; + } + if (SectorAddressing) { + // + //Block Address + // + Address = (UINT32) DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512); + } else { + // + //Byte Address + // + Address = (UINT32) MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize); + } + + if (!Buffer) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Invalid parameter \r\n")); + goto Done; + } + + if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Bad buffer size \r\n")); + goto Done; + } + + if (BufferSize == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + if (This->Media->ReadOnly == TRUE) { + Status = EFI_WRITE_PROTECTED; + DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Write protected \r\n")); + goto Done; + } + + BufferPointer = Buffer; + RemainingLength = (UINT32) BufferSize; + + while (RemainingLength > 0) { + if ((BufferSize > CardData->BlockIoMedia.BlockSize) ) { + if (RemainingLength > SdHostIo->HostCapability.BoundarySize) { + TransferLength = SdHostIo->HostCapability.BoundarySize; + } else { + TransferLength = RemainingLength; + } + + if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { + + if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) { + Status = SendCommand ( + CardData, + SET_BLOCKLEN, + CardData->BlockIoMedia.BlockSize, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + break; + } + } + Status = SendCommand ( + CardData, + SET_BLOCK_COUNT, + TransferLength / CardData->BlockIoMedia.BlockSize, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + break; + } + } + + CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength); + + Status = SendCommand ( + CardData, + WRITE_MULTIPLE_BLOCK, + Address, + OutData, + CardData->AlignedBuffer, + (UINT32) TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n")); + break; + } + } else { + if (RemainingLength > CardData->BlockIoMedia.BlockSize) { + TransferLength = CardData->BlockIoMedia.BlockSize; + } else { + TransferLength = RemainingLength; + } + + CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength); + + Status = SendCommand ( + CardData, + WRITE_BLOCK, + Address, + OutData, + CardData->AlignedBuffer, + (UINT32) TransferLength, + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + } + + if (SectorAddressing) { + // + //Block Address + // + Address += TransferLength / 512; + } else { + // + //Byte Address + // + Address += TransferLength; + } + BufferPointer += TransferLength; + RemainingLength -= TransferLength; + + } + + if (EFI_ERROR (Status)) { + SendCommand ( + CardData, + STOP_TRANSMISSION, + 0, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + } + +Done: + return EFI_SUCCESS; +} + + +/** + Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function. + (In this driver, this function just returns EFI_SUCCESS.) + + @param[in] This The EFI_BLOCK_IO_PROTOCOL instance. + + @retval EFI_SUCCESS + @retval Others + +**/ +EFI_STATUS +EFIAPI +MMCSDBlockFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + + +/** + MMC/SD card BlockIo init function. + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval Others + +**/ +EFI_STATUS +MMCSDBlockIoInit ( + IN CARD_DATA *CardData + ) +{ + + // + // BlockIO protocol + // + CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + CardData->BlockIo.Media = &(CardData->BlockIoMedia); + CardData->BlockIo.Reset = MMCSDBlockReset; + CardData->BlockIo.ReadBlocks = MMCSDBlockReadBlocks ; + CardData->BlockIo.WriteBlocks = MMCSDBlockWriteBlocks; + CardData->BlockIo.FlushBlocks = MMCSDBlockFlushBlocks; + + CardData->BlockIoMedia.MediaId = 0; + CardData->BlockIoMedia.RemovableMedia = FALSE; + CardData->BlockIoMedia.MediaPresent = TRUE; + CardData->BlockIoMedia.LogicalPartition = FALSE; + + if (CardData->CSDRegister.PERM_WRITE_PROTECT || CardData->CSDRegister.TMP_WRITE_PROTECT) { + CardData->BlockIoMedia.ReadOnly = TRUE; + } else { + CardData->BlockIoMedia.ReadOnly = FALSE; + } + + CardData->BlockIoMedia.WriteCaching = FALSE; + CardData->BlockIoMedia.BlockSize = CardData->BlockLen; + CardData->BlockIoMedia.IoAlign = 1; + CardData->BlockIoMedia.LastBlock = (EFI_LBA) (CardData->BlockNumber - 1); + + return EFI_SUCCESS; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c new file mode 100644 index 0000000..e0304de --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/MMCSDTransfer.c @@ -0,0 +1,1661 @@ +/** @file + MMC/SD transfer specific functions + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "SdMediaDevice.h" + + +/** + Check card status, print the debug info and check the error + + @param[in] Status Status got from card status register. + + @retval EFI_SUCCESS + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +CheckCardStatus ( + IN UINT32 Status + ) +{ + CARD_STATUS *CardStatus; + CardStatus = (CARD_STATUS *) (&Status); + + if (CardStatus->ADDRESS_OUT_OF_RANGE) { + DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_OUT_OF_RANGE\n")); + } + + if (CardStatus->ADDRESS_MISALIGN) { + DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_MISALIGN\n")); + } + + if (CardStatus->BLOCK_LEN_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: BLOCK_LEN_ERROR\n")); + } + + if (CardStatus->ERASE_SEQ_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_SEQ_ERROR\n")); + } + + if (CardStatus->ERASE_PARAM) { + DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_PARAM\n")); + } + + if (CardStatus->WP_VIOLATION) { + DEBUG ((EFI_D_ERROR, "CardStatus: WP_VIOLATION\n")); + } + + if (CardStatus->CARD_IS_LOCKED) { + DEBUG ((EFI_D_ERROR, "CardStatus: CARD_IS_LOCKED\n")); + } + + if (CardStatus->LOCK_UNLOCK_FAILED) { + DEBUG ((EFI_D_ERROR, "CardStatus: LOCK_UNLOCK_FAILED\n")); + } + + if (CardStatus->COM_CRC_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: COM_CRC_ERROR\n")); + } + + if (CardStatus->ILLEGAL_COMMAND) { + DEBUG ((EFI_D_ERROR, "CardStatus: ILLEGAL_COMMAND\n")); + } + + if (CardStatus->CARD_ECC_FAILED) { + DEBUG ((EFI_D_ERROR, "CardStatus: CARD_ECC_FAILED\n")); + } + + if (CardStatus->CC_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: CC_ERROR\n")); + } + + if (CardStatus->ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: ERROR\n")); + } + + if (CardStatus->UNDERRUN) { + DEBUG ((EFI_D_ERROR, "CardStatus: UNDERRUN\n")); + } + + if (CardStatus->OVERRUN) { + DEBUG ((EFI_D_ERROR, "CardStatus: OVERRUN\n")); + } + + if (CardStatus->CID_CSD_OVERWRITE) { + DEBUG ((EFI_D_ERROR, "CardStatus: CID_CSD_OVERWRITE\n")); + } + + if (CardStatus->WP_ERASE_SKIP) { + DEBUG ((EFI_D_ERROR, "CardStatus: WP_ERASE_SKIP\n")); + } + + if (CardStatus->ERASE_RESET) { + DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_RESET\n")); + } + + if (CardStatus->SWITCH_ERROR) { + DEBUG ((EFI_D_ERROR, "CardStatus: SWITCH_ERROR\n")); + } + + if ((Status & 0xFCFFA080) != 0) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Send command by using Host IO protocol + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] CommandIndex The command index to set the command index field of command register. + @param[in] Argument Command argument to set the argument field of command register. + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out. + @param[in] Buffer Contains the data read from / write to the device. + @param[in] BufferSize The size of the buffer. + @param[in] ResponseType RESPONSE_TYPE. + @param[in] TimeOut Time out value in 1 ms unit. + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +SendCommand ( + IN CARD_DATA *CardData, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData + ) +{ + + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + + SdHostIo = CardData->SdHostIo; + if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) { + CommandIndex |= AUTO_CMD12_ENABLE; + } + Status = SdHostIo->SendCommand ( + SdHostIo, + CommandIndex, + Argument, + DataType, + Buffer, + BufferSize, + ResponseType, + TimeOut, + ResponseData + ); + + if (!EFI_ERROR (Status)) { + if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) { + ASSERT (ResponseData != NULL); + Status = CheckCardStatus (*ResponseData); + } + } else { + SdHostIo->ResetSdHost (SdHostIo, Reset_DAT_CMD); + } + + return Status; +} + + +/** + Send the card APP_CMD command with the following command indicated by CommandIndex + + @param[in] CardData Pointer to CARD_DATA. + @param[in] CommandIndex The command index to set the command index field of command register. + @param[in] Argument Command argument to set the argument field of command register. + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out. + @param[in] Buffer Contains the data read from / write to the device. + @param[in] BufferSize The size of the buffer. + @param[in] ResponseType RESPONSE_TYPE. + @param[in] TimeOut Time out value in 1 ms unit. + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +SendAppCommand ( + IN CARD_DATA *CardData, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData + ) +{ + + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + UINT8 Index; + + SdHostIo = CardData->SdHostIo; + Status = EFI_SUCCESS; + + for (Index = 0; Index < 2; Index++) { + Status = SdHostIo->SendCommand ( + SdHostIo, + APP_CMD, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + Status = CheckCardStatus (*(UINT32 *) &(CardData->CardStatus)); + if (CardData->CardStatus.SAPP_CMD != 1) { + Status = EFI_DEVICE_ERROR; + } + if (!EFI_ERROR (Status)) { + break; + } + } else { + SdHostIo->ResetSdHost (SdHostIo, Reset_Auto); + } + } + + if (EFI_ERROR (Status)) { + return Status; + } + if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) { + CommandIndex |= AUTO_CMD12_ENABLE; + } + + Status = SdHostIo->SendCommand ( + SdHostIo, + CommandIndex, + Argument, + DataType, + Buffer, + BufferSize, + ResponseType, + TimeOut, + ResponseData + ); + + if (!EFI_ERROR (Status)) { + if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) { + ASSERT (ResponseData != NULL); + Status = CheckCardStatus (*ResponseData); + } + } else { + SdHostIo->ResetSdHost (SdHostIo, Reset_Auto); + } + + return Status; +} + + +/** + Send the card FAST_IO command + + @param[in] CardData Pointer to CARD_DATA. + @param[in] RegisterAddress Register Address. + @param[in, out] RegisterData Pointer to register Data. + @param[in] Write TRUE for write, FALSE for read. + + @retval EFI_SUCCESS + @retval EFI_UNSUPPORTED + @retval EFI_INVALID_PARAMETER + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +FastIO ( + IN CARD_DATA *CardData, + IN UINT8 RegisterAddress, + IN OUT UINT8 *RegisterData, + IN BOOLEAN Write + ) +{ + EFI_STATUS Status; + UINT32 Argument; + UINT32 Data; + + Status = EFI_SUCCESS; + + if (RegisterData == NULL) { + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + Argument = (CardData->Address << 16) | (RegisterAddress << 8); + if (Write) { + Argument |= BIT15 | (*RegisterData); + } + + Status = SendCommand ( + CardData, + FAST_IO, + Argument, + NoData, + NULL, + 0, + ResponseR4, + TIMEOUT_COMMAND, + &Data + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + + if ((Data & BIT15) == 0) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + if (!Write) { + *RegisterData = (UINT8) Data; + } + +Exit: + return Status; +} + + +/** + Send the card GO_INACTIVE_STATE command. + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval others + +**/ +EFI_STATUS +PutCardInactive ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + + + Status = SendCommand ( + CardData, + GO_INACTIVE_STATE, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseNo, + TIMEOUT_COMMAND, + NULL + ); + + return Status; + +} + + +/** + Get card interested information for CSD rergister + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval EFI_UNSUPPORTED + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +CaculateCardParameter ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + UINT32 Frequency; + UINT32 Multiple; + UINT32 CSize; + CSD_SDV2 *CsdSDV2; + + Status = EFI_SUCCESS; + + switch (CardData->CSDRegister.TRAN_SPEED & 0x7) { + case 0: + Frequency = 100 * 1000; + break; + + case 1: + Frequency = 1 * 1000 * 1000; + break; + + case 2: + Frequency = 10 * 1000 * 1000; + break; + + case 3: + Frequency = 100 * 1000 * 1000; + break; + + default: + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + switch ((CardData->CSDRegister.TRAN_SPEED >> 3) & 0xF) { + case 1: + Multiple = 10; + break; + + case 2: + Multiple = 12; + break; + + case 3: + Multiple = 13; + break; + + case 4: + Multiple = 15; + break; + + case 5: + Multiple = 20; + break; + + case 6: + if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { + Multiple = 26; + } else { + Multiple = 25; + } + break; + + case 7: + Multiple = 30; + break; + + case 8: + Multiple = 35; + break; + + case 9: + Multiple = 40; + break; + + case 10: + Multiple = 45; + break; + + case 11: + if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { + Multiple = 52; + } else { + Multiple = 50; + } + break; + + case 12: + Multiple = 55; + break; + + case 13: + Multiple = 60; + break; + + case 14: + Multiple = 70; + break; + + case 15: + Multiple = 80; + break; + + default: + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + Frequency = Frequency * Multiple / 10; + CardData->MaxFrequency = Frequency; + + CardData->BlockLen = 1 << CardData->CSDRegister.READ_BL_LEN; + + if (CardData->CardType == SdMemoryCard2High) { + ASSERT (CardData->CSDRegister.CSD_STRUCTURE == 1); + CsdSDV2 = (CSD_SDV2 *) &CardData->CSDRegister; + + // + // the K here means 1024 not 1000 + // + CardData->BlockNumber = DivU64x32 (MultU64x32 (CsdSDV2->C_SIZE + 1, 512 * 1024) , CardData->BlockLen); + } else { + // + // For MMC card > 2G, the block number will be recaculate later + // + CSize = CardData->CSDRegister.C_SIZELow2 | (CardData->CSDRegister.C_SIZEHigh10 << 2); + CardData->BlockNumber = MultU64x32 (LShiftU64 (1, CardData->CSDRegister.C_SIZE_MULT + 2), CSize + 1); + } + + // + //For >= 2G card, BlockLen may be 1024, but the transfer size is still 512 bytes + // + if (CardData->BlockLen > 512) { + CardData->BlockNumber = DivU64x32 (MultU64x32 (CardData->BlockNumber, CardData->BlockLen), 512); + CardData->BlockLen = 512; + } + + DEBUG (( + EFI_D_INFO, + "CalculateCardParameter: Card Size: 0x%lx\n", MultU64x32 (CardData->BlockNumber, CardData->BlockLen) + )); + +Exit: + return Status; +} + + +/** + Test the bus width setting for MMC card.It is used only for verification purpose. + + @param[in] CardData Pointer to CARD_DATA. + @param[in] Width 1, 4, 8 bits. + + @retval EFI_SUCCESS + @retval EFI_UNSUPPORTED + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +MMCCardBusWidthTest ( + IN CARD_DATA *CardData, + IN UINT32 Width + ) +{ + EFI_STATUS Status; + UINT64 Data; + UINT64 Value; + + ASSERT(CardData != NULL); + + Value = 0; + + switch (Width) { + case 1: + Data = 0x80; + break; + + case 4: + Data = 0x5A; + break; + + case 8: + Data = 0xAA55; + break; + + default: + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + CopyMem (CardData->AlignedBuffer, &Data, Width); + Status = SendCommand ( + CardData, + BUSTEST_W, + 0, + OutData, + CardData->AlignedBuffer, + Width, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_W 0x%x\n", *(UINT32*)&(CardData->CardStatus))); + goto Exit; + } + + gBS->Stall (10 * 1000); + + Data = 0; + + Status = SendCommand ( + CardData, + BUSTEST_R, + 0, + InData, + CardData->AlignedBuffer, + Width, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_R 0x%x\n", *(UINT32 *) &(CardData->CardStatus))); + goto Exit; + } + CopyMem (&Data, CardData->AlignedBuffer, Width); + + switch (Width) { + case 1: + Value = (~(Data ^ 0x80)) & 0xC0; + break; + + case 4: + Value = (~(Data ^ 0x5A)) & 0xFF; + break; + + case 8: + Value = (~(Data ^ 0xAA55)) & 0xFFFF; + break; + } + + if (Value == 0) { + Status = EFI_SUCCESS; + } else { + Status = EFI_UNSUPPORTED; + } + +Exit: + return Status; +} + + +/** + This function can detect these card types: + 1. MMC card + 2. SD 1.1 card + 3. SD 2.0 standard card + 3. SD 2.0 high capacity card + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval others + +**/ +EFI_STATUS +GetCardType ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + UINT32 Argument; + UINT32 ResponseData; + UINT32 Count; + BOOLEAN SdCommand8Support; + + SdHostIo = CardData->SdHostIo; + + // + // Reset the card + // + Status = SendCommand ( + CardData, + GO_IDLE_STATE, + 0, + NoData, + NULL, + 0, + ResponseNo, + TIMEOUT_COMMAND, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status)); + goto Exit; + } + gBS->Stall (10 * 1000); + + // + // Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass + // MMC and SD1.1 card will fail this command + // + Argument = (VOLTAGE_27_36 << 8) | CHECK_PATTERN; + ResponseData = 0; + SdCommand8Support = FALSE; + + Status = SendCommand ( + CardData, + SEND_IF_COND, + Argument, + NoData, + NULL, + 0, + ResponseR7, + TIMEOUT_COMMAND, + &ResponseData + ); + + if (EFI_ERROR (Status)) { + if (Status != EFI_TIMEOUT) { + DEBUG ((EFI_D_ERROR, "SEND_IF_COND Fail, none time out error\n")); + goto Exit; + } + } else { + if (ResponseData != Argument) { + DEBUG ((EFI_D_ERROR, "SEND_IF_COND Fail, respond data does not match send data\n")); + Status = EFI_DEVICE_ERROR; + goto Exit; + } + SdCommand8Support = TRUE; + } + + Argument = 0; + + if (SdHostIo->HostCapability.V30Support == TRUE) { + Argument |= BIT17 | BIT18; + } else if (SdHostIo->HostCapability.V33Support == TRUE) { + Argument |= BIT20 | BIT21; + } + + if (SdCommand8Support) { + Argument |= BIT30; + } + + Count = 20; + do { + Status = SendAppCommand ( + CardData, + SD_SEND_OP_COND, + Argument, + NoData, + NULL, + 0, + ResponseR3, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->OCRRegister) + ); + + if (EFI_ERROR (Status)) { + if ((Status == EFI_TIMEOUT) && (!SdCommand8Support)) { + CardData->CardType = MMCCard; + Status = EFI_SUCCESS; + DEBUG ((EFI_D_INFO, "SD_SEND_OP_COND, MMC card was identified\n")); + } else { + DEBUG ((EFI_D_ERROR, "SD_SEND_OP_COND Fail, check whether it is neither a MMC card nor a SD card\n")); + } + goto Exit; + } + // + // Avoid waiting if sucess. Busy bit 0 means not ready + // + if (CardData->OCRRegister.Busy == 1) { + break; + } + + gBS->Stall (50 * 1000); + Count--; + if (Count == 0) { + DEBUG ((EFI_D_ERROR, "Card is always in busy state\n")); + Status = EFI_TIMEOUT; + goto Exit; + } + } while (1); + + // + // Check supported voltage + // + Argument = 0; + if (SdHostIo->HostCapability.V30Support == TRUE) { + if ((CardData->OCRRegister.V270_V360 & BIT2) == BIT2) { + Argument |= BIT17; + } else if ((CardData->OCRRegister.V270_V360 & BIT3) == BIT3) { + Argument |= BIT18; + } + } else if (SdHostIo->HostCapability.V33Support == TRUE) { + if ((CardData->OCRRegister.V270_V360 & BIT5) == BIT5) { + Argument |= BIT20; + } else if ((CardData->OCRRegister.V270_V360 & BIT6) == BIT6) { + Argument |= BIT21; + } + } + + if (Argument == 0) { + // + // No matched support voltage + // + PutCardInactive (CardData); + DEBUG ((EFI_D_ERROR, "No matched voltage for this card\n")); + Status = EFI_UNSUPPORTED; + goto Exit; + } + + CardData->CardType = SdMemoryCard; + if (SdCommand8Support == TRUE) { + CardData->CardType = SdMemoryCard2; + DEBUG ((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above standard card was identified\n")); + } + + if ((CardData->OCRRegister.AccessMode & BIT1) == BIT1) { + CardData->CardType = SdMemoryCard2High; + DEBUG ((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above high capacity card was identified\n")); + } + +Exit: + return Status; +} + + +/** + MMC card high/low voltage selection function + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_BAD_BUFFER_SIZE + +**/ +EFI_STATUS +MMCCardVoltageSelection ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + UINT8 Retry; + UINT32 TimeOut; + + Status = EFI_SUCCESS; + + // + // First try the high voltage, then if supported choose the low voltage + // + for (Retry = 0; Retry < 3; Retry++) { + // + // To bring back the normal MMC card to work + // after sending the SD command. Otherwise some + // card could not work + + Status = SendCommand ( + CardData, + GO_IDLE_STATE, + 0, + NoData, + NULL, + 0, + ResponseNo, + TIMEOUT_COMMAND, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status)); + continue; + } + // + //CE-ATA device needs long delay + // + gBS->Stall ((Retry + 1) * 50 * 1000); + + // + // Get OCR register to check voltage support, first time the OCR is 0 + // + Status = SendCommand ( + CardData, + SEND_OP_COND, + 0, + NoData, + NULL, + 0, + ResponseR3, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->OCRRegister) + ); + + if (!EFI_ERROR (Status)) { + break; + } + } + + if (Retry == 3) { + DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status)); + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + // + // TimeOut Value, 5000 * 100 * 1000 = 5 s + // + TimeOut = 5000; + + do { + Status = SendCommand ( + CardData, + SEND_OP_COND, + 0x40300000, + NoData, + NULL, + 0, + ResponseR3, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->OCRRegister) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status)); + goto Exit; + } + + gBS->Stall (1 * 1000); + TimeOut--; + if (TimeOut == 0) { + Status = EFI_TIMEOUT; + DEBUG ((EFI_D_ERROR, "Card is always in busy state\n")); + goto Exit; + } + } while (CardData->OCRRegister.Busy != 1); + + if (CardData->OCRRegister.AccessMode == 2) { + DEBUG ((EFI_D_INFO, "eMMC Card is High Capacity\n")); + CardData->CardType = MMCCardHighCap; + } + +Exit: + return Status; +} + + +/** + This function set the bus and device width for MMC card. + + @param[in] CardData Pointer to CARD_DATA. + @param[in] BusWidth 1, 4, 8 bits. + @param[in] EnableDDRMode Enable DDR Mode. + + @retval EFI_SUCCESS + @retval EFI_UNSUPPORTED + @retval EFI_INVALID_PARAMETER + +**/ +EFI_STATUS +MMCCardSetBusWidth ( + IN CARD_DATA *CardData, + IN UINT8 BusWidth, + IN BOOLEAN EnableDDRMode + ) +{ + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + SWITCH_ARGUMENT SwitchArgument; + UINT8 Value; + + SdHostIo = CardData->SdHostIo; + Value = 0; + switch (BusWidth) { + case 8: + if (EnableDDRMode) + Value = 6; + else + Value = 2; + break; + + case 4: + if (EnableDDRMode) + Value = 5; + else + Value = 1; + break; + + case 1: + if (EnableDDRMode) // Bus width 1 is not supported in ddr mode + return EFI_UNSUPPORTED; + Value = 0; + break; + + default: + ASSERT (0); + } + + ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT)); + SwitchArgument.CmdSet = 0; + SwitchArgument.Value = Value; + SwitchArgument.Index = (UINT32) ((UINTN) + (&(CardData->ExtCSDRegister.BUS_WIDTH)) - (UINTN) (&(CardData->ExtCSDRegister))); + SwitchArgument.Access = WriteByte_Mode; + Status = SendCommand ( + CardData, + SWITCH, + *(UINT32 *) &SwitchArgument, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + Status = SendCommand ( + CardData, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SWITCH %d bits Fail\n", BusWidth)); + goto Exit; + } else { + DEBUG ((EFI_D_ERROR, "MMCCardSetBusWidth:SWITCH Card Status:0x%x\n", *(UINT32 *) &(CardData->CardStatus))); + Status = SdHostIo->SetBusWidth (SdHostIo, BusWidth); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SWITCH set %d bits Fail\n", BusWidth)); + goto Exit; + } + gBS->Stall (5 * 1000); + } + } + + if (!EnableDDRMode) { // CMD19 and CMD14 are illegal commands in ddr mode + + Status = MMCCardBusWidthTest (CardData, BusWidth); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCCardBusWidthTest %d bit Fail\n", BusWidth)); + goto Exit; + } + } + + CardData->CurrentBusWidth = BusWidth; + +Exit: + return Status; +} + + +/** + MMC/SD card init function + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval others + +**/ +EFI_STATUS +MMCSDCardInit ( + IN CARD_DATA *CardData + ) +{ + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + SWITCH_ARGUMENT SwitchArgument; + UINT32 Data; + UINT32 Argument; + UINT32 nIndex; + UINT8 PowerValue; + BOOLEAN EnableDDRMode; + + ASSERT (CardData != NULL); + SdHostIo = CardData->SdHostIo; + EnableDDRMode = FALSE; + + CardData->CardType = UnknownCard; + Status = GetCardType (CardData); + if (EFI_ERROR (Status)) { + goto Exit; + } + DEBUG ((DEBUG_INFO, "CardData->CardType 0x%x\n", CardData->CardType)); + + ASSERT (CardData->CardType != UnknownCard); + + // + // MMC, SD card need host auto stop command support + // + SdHostIo->EnableAutoStopCmd (SdHostIo, TRUE); + + if (CardData->CardType == MMCCard) { + Status = MMCCardVoltageSelection (CardData); + if (EFI_ERROR (Status)) { + goto Exit; + } + } + + // + // Get CID Register + // + Status = SendCommand ( + CardData, + ALL_SEND_CID, + 0, + NoData, + NULL, + 0, + ResponseR2, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CIDRegister) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "ALL_SEND_CID Fail Status = 0x%x\n", Status)); + goto Exit; + } else { + // + // Dump out the Card ID data + // + DEBUG ((EFI_D_INFO, "Product Name: ")); + for (nIndex=0; nIndex<6; nIndex++ ) { + DEBUG ((EFI_D_INFO, "%c", CardData->CIDRegister.PNM[nIndex])); + } + DEBUG ((EFI_D_INFO, "\nApplication ID : %d\n", CardData->CIDRegister.OID)); + DEBUG ((EFI_D_INFO, "Manufacturer ID : %d\n", CardData->CIDRegister.MID)); + DEBUG ((EFI_D_INFO, "Revision ID : %d\n", CardData->CIDRegister.PRV)); + DEBUG ((EFI_D_INFO, "Serial Number : %d\n", CardData->CIDRegister.PSN)); + } + + // + // SET_RELATIVE_ADDR + // + if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { + // + // Hard code the RCA address + // + CardData->Address = 1; + + // + // Set RCA Register + // + Status = SendCommand ( + CardData, + SET_RELATIVE_ADDR, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status)); + goto Exit; + } + } else { + Data = 0; + Status = SendCommand ( + CardData, + SET_RELATIVE_ADDR, + 0, + NoData, + NULL, + 0, + ResponseR6, + TIMEOUT_COMMAND, + &Data + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status)); + goto Exit; + } + + CardData->Address = (UINT16) (Data >> 16); + *(UINT32 *) &CardData->CardStatus = Data & 0x1FFF; + CardData->CardStatus.ERROR = (Data >> 13) & 0x1; + CardData->CardStatus.ILLEGAL_COMMAND = (Data >> 14) & 0x1; + CardData->CardStatus.COM_CRC_ERROR = (Data >> 15) & 0x1; + Status = CheckCardStatus (*(UINT32 *) &CardData->CardStatus); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status)); + goto Exit; + } + } + + // + // Get CSD Register + // + Status = SendCommand ( + CardData, + SEND_CSD, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR2, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CSDRegister) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SEND_CSD Fail Status = 0x%x\n", Status)); + goto Exit; + } + + DEBUG ((EFI_D_INFO, "CardData->CSDRegister.SPEC_VERS = 0x%x\n", CardData->CSDRegister.SPEC_VERS)); + DEBUG ((EFI_D_INFO, "CardData->CSDRegister.CSD_STRUCTURE = 0x%x\n", CardData->CSDRegister.CSD_STRUCTURE)); + + Status = CaculateCardParameter (CardData); + if (EFI_ERROR (Status)) { + goto Exit; + } + + + // + // It is platform and hardware specific, need hadrware engineer input + // + if (CardData->CSDRegister.DSR_IMP == 1) { + // + // Default is 0x404 + // + Status = SendCommand ( + CardData, + SET_DSR, + (DEFAULT_DSR_VALUE << 16), + NoData, + NULL, + 0, + ResponseNo, + TIMEOUT_COMMAND, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_DSR Fail Status = 0x%x\n", Status)); + // + // Assume can operate even fail + // + } + } + // + // Change clock frequency from 400KHz to max supported when not in high speed mode + // + Status = SdHostIo->SetClockFrequency (SdHostIo, CardData->MaxFrequency); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n")); + goto Exit; + } + + // + // Put the card into tran state + // + Status = SendCommand ( + CardData, + SELECT_DESELECT_CARD, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SELECT_DESELECT_CARD Fail Status = 0x%x\n", Status)); + goto Exit; + } + gBS->Stall (5 * 1000); + // + // No need to do so + // + // + Status = SendCommand ( + CardData, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SELECT_DESELECT_CARD SEND_STATUS Fail Status = 0x%x\n", Status)); + goto Exit; + } + if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { + // + // Only V4.0 and above supports more than 1 bits and high speed + // + if (CardData->CSDRegister.SPEC_VERS >= 4) { + // + // Get ExtCSDRegister + // + Status = SendCommand ( + CardData, + SEND_EXT_CSD, + 0x0, + InData, + CardData->AlignedBuffer, + sizeof (EXT_CSD), + ResponseR1, + TIMEOUT_DATA, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SEND_EXT_CSD Fail Status = 0x%x\n", Status)); + goto Exit; + } + + CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof(EXT_CSD)); + + // + // Recaculate the block number for >2G MMC card + // + Data = (CardData->ExtCSDRegister.SEC_COUNT[0]) | + (CardData->ExtCSDRegister.SEC_COUNT[1] << 8) | + (CardData->ExtCSDRegister.SEC_COUNT[2] << 16) | + (CardData->ExtCSDRegister.SEC_COUNT[3] << 24); + + if (Data != 0) { + CardData->BlockNumber = Data; + } + DEBUG ((DEBUG_INFO, "CardData->BlockNumber %d\n", Data)); + DEBUG ((EFI_D_ERROR, "CardData->ExtCSDRegister.CARD_TYPE -> %d\n", (UINTN)CardData->ExtCSDRegister.CARD_TYPE)); + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2)|| + (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) { + + } + // + // Check current chipset capability and the plugged-in card + // whether supports HighSpeed + // + if (SdHostIo->HostCapability.HighSpeedSupport) { + + // + // Change card timing to high speed interface timing + // + ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT)); + SwitchArgument.CmdSet = 0; + SwitchArgument.Value = 1; + SwitchArgument.Index = (UINT32) ((UINTN) + (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN) (&(CardData->ExtCSDRegister))); + SwitchArgument.Access = WriteByte_Mode; + Status = SendCommand ( + CardData, + SWITCH, + *(UINT32 *) &SwitchArgument, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDCardInit:SWITCH frequency Fail Status = 0x%x\n", Status)); + } + + gBS->Stall (5 * 1000); + + if (!EFI_ERROR (Status)) { + Status = SendCommand ( + CardData, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + if (EnableDDRMode) { + DEBUG ((EFI_D_ERROR, "Enable ddr mode on host controller\n")); + SdHostIo->SetDDRMode (SdHostIo, TRUE); + } else { + DEBUG ((EFI_D_ERROR, "Enable high speed mode on host controller\n")); + SdHostIo->SetHighSpeedMode (SdHostIo, TRUE); + } + // + // Change host clock to support high speed and enable chispet to + // support speed + // + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { + Status = SdHostIo->SetClockFrequency (SdHostIo, FREQUENCY_MMC_PP_HIGH); + } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { + Status = SdHostIo->SetClockFrequency (SdHostIo, FREQUENCY_MMC_PP); + } else { + Status = EFI_UNSUPPORTED; + } + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n")); + goto Exit; + } + // + // It seems no need to stall after changing bus freqeuncy. + // It is said that the freqeuncy can be changed at any time. Just appends 8 clocks after command. + // But SetClock alreay has delay. + // + } + } + + } + + // + // Prefer wide bus width for performance + // + // + // Set to BusWidth bits mode, only version 4.0 or above support more than 1 bits + // + if (SdHostIo->HostCapability.BusWidth8 == TRUE) { + Status = MMCCardSetBusWidth (CardData, 8, EnableDDRMode); + if (EFI_ERROR (Status)) { + // + // CE-ATA may support 8 bits and 4 bits, but has no software method for detection + // + Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode); + if (EFI_ERROR (Status)) { + goto Exit; + } + } + } else if (SdHostIo->HostCapability.BusWidth4 == TRUE) { + Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode); + if (EFI_ERROR (Status)) { + goto Exit; + } + } + + PowerValue = 0; + + if (CardData->CurrentBusWidth == 8) { + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { + PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360; + PowerValue = PowerValue >> 4; + } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { + PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360; + PowerValue = PowerValue >> 4; + } + } else if (CardData->CurrentBusWidth == 4) { + if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { + PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360; + PowerValue = PowerValue & 0xF; + } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { + PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360; + PowerValue = PowerValue & 0xF; + } + } + + if (PowerValue != 0) { + // + // Update Power Class + // + ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT)); + SwitchArgument.CmdSet = 0; + SwitchArgument.Value = PowerValue; + SwitchArgument.Index = (UINT32) ((UINTN) + (&(CardData->ExtCSDRegister.POWER_CLASS)) - (UINTN) (&(CardData->ExtCSDRegister))); + SwitchArgument.Access = WriteByte_Mode; + Status = SendCommand ( + CardData, + SWITCH, + *(UINT32 *) &SwitchArgument, + NoData, + NULL, + 0, + ResponseR1b, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (!EFI_ERROR (Status)) { + Status = SendCommand ( + CardData, + SEND_STATUS, + (CardData->Address << 16), + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SWITCH Power Class Fail Status = 0x%x\n", Status)); + } + } + } + + } else { + DEBUG ((EFI_D_ERROR, "MMC Card version %d only supportes 1 bits at lower transfer speed\n",CardData->CSDRegister.SPEC_VERS)); + } + } else { + // + // Pin 1, at power up this line has a 50KOhm pull up enabled in the card. + // This pull-up should be disconnected by the user, during regular data transfer, + // with SET_CLR_CARD_DETECT (ACMD42) command + // + Status = SendAppCommand ( + CardData, + SET_CLR_CARD_DETECT, + 0, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_CLR_CARD_DETECT Fail Status = 0x%x\n", Status)); + goto Exit; + } + + // + // Set Bus Width to 4 + // + Status = SendAppCommand ( + CardData, + SET_BUS_WIDTH, + SD_BUS_WIDTH_4, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_BUS_WIDTH 4 bits Fail Status = 0x%x\n", Status)); + goto Exit; + } + + Status = SdHostIo->SetBusWidth (SdHostIo, 4); + if (EFI_ERROR (Status)) { + goto Exit; + } + CardData->CurrentBusWidth = 4; + + if ((SdHostIo->HostCapability.HighSpeedSupport == FALSE) || + ((CardData->CSDRegister.CCC & BIT10) != BIT10)) { + // + // Host must support high speed + // Card must support Switch function + // + goto Exit; + } + + // + // Mode = 0, group 1, function 1, check operation + // + Argument = 0xFFFF01; + ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS)); + + Status = SendCommand ( + CardData, + SWITCH_FUNC, + Argument, + InData, + CardData->AlignedBuffer, + sizeof (SWITCH_STATUS), + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS)); + + if ((CardData->SwitchStatus.DataStructureVersion == 0x0) || + ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) { + Argument = 0xFFFF01 | BIT31; + ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS)); + + Status = SendCommand ( + CardData, + SWITCH_FUNC, + Argument, + InData, + CardData->AlignedBuffer, + sizeof (SWITCH_STATUS), + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS)); + + if ((CardData->SwitchStatus.DataStructureVersion == 0x0) || + ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) { + gBS->Stall (1000); + + // + // Change host clock + // + Status = SdHostIo->SetClockFrequency (SdHostIo, FREQUENCY_SD_PP_HIGH); + if (EFI_ERROR (Status)) { + goto Exit; + } + + } + } + } + if (!((CardData->ExtCSDRegister.CARD_TYPE & BIT2) || + (CardData->ExtCSDRegister.CARD_TYPE & BIT3))) { + + // + // Set Block Length, to improve compatibility in case of some cards + // + Status = SendCommand ( + CardData, + SET_BLOCKLEN, + 512, + NoData, + NULL, + 0, + ResponseR1, + TIMEOUT_COMMAND, + (UINT32 *) &(CardData->CardStatus) + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SET_BLOCKLEN Fail Status = 0x%x\n", Status)); + goto Exit; + } + } + SdHostIo->SetBlockLength (SdHostIo, 512); + +Exit: + return Status; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c new file mode 100644 index 0000000..ad0eb2c --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.c @@ -0,0 +1,324 @@ +/** @file + The definition for SD media device driver model and blkio protocol routines. + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 "SdMediaDevice.h" + +EFI_DRIVER_BINDING_PROTOCOL gSdMediaDeviceDriverBinding = { + SdMediaDeviceSupported, + SdMediaDeviceStart, + SdMediaDeviceStop, + 0x20, + NULL, + NULL +}; + + +/** + Entry point for EFI drivers. + + @param[in] ImageHandle EFI_HANDLE. + @param[in] SystemTable EFI_SYSTEM_TABLE. + + @retval EFI_SUCCESS Driver is successfully loaded. + @retval Others Failed. + +**/ +EFI_STATUS +EFIAPI +InitializeSdMediaDevice ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gSdMediaDeviceDriverBinding, + ImageHandle, + &gSdMediaDeviceName, + &gSdMediaDeviceName2 + ); +} + + +/** + Test to see if this driver supports ControllerHandle. Any + ControllerHandle that has BlockIoProtocol installed will be supported. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test. + @param[in] RemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +SdMediaDeviceSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + + // + // Test whether there is PCI IO Protocol attached on the controller handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSdHostIoProtocolGuid, + (VOID **) &SdHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + + gBS->CloseProtocol ( + Controller, + &gEfiSdHostIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + +Exit: + return Status; +} + + +/** + Starting the SD Media Device Driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test. + @param[in] RemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error. + EFI_OUT_OF_RESOURCES- Failed due to resource shortage. + +**/ +EFI_STATUS +EFIAPI +SdMediaDeviceStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + CARD_DATA *CardData; + + CardData = NULL; + + // + // Open PCI I/O Protocol and save pointer to open protocol + // in private data area. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSdHostIoProtocolGuid, + (VOID **) &SdHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to open gEfiSdHostIoProtocolGuid \r\n")); + goto Exit; + } + + Status = SdHostIo->DetectCardAndInitHost (SdHostIo); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "SdMediaDeviceStart: Fail to DetectCardAndInitHost \r\n")); + goto Exit; + } + + CardData = (CARD_DATA *) AllocateZeroPool (sizeof (CARD_DATA)); + if (CardData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to AllocateZeroPool(CARD_DATA) \r\n")); + goto Exit; + } + + ASSERT (SdHostIo->HostCapability.BoundarySize >= 4 * 1024); + CardData->RawBufferPointer = (UINT8 *) ((UINTN) DMA_MEMORY_TOP); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + EFI_SIZE_TO_PAGES (2 * SdHostIo->HostCapability.BoundarySize), + (EFI_PHYSICAL_ADDRESS *) (&CardData->RawBufferPointer) + ); + + if (CardData->RawBufferPointer == NULL) { + DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to AllocateZeroPool(2*x) \r\n")); + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + CardData->AlignedBuffer = CardData->RawBufferPointer - ((UINTN) (CardData->RawBufferPointer) & (SdHostIo->HostCapability.BoundarySize - 1)) + SdHostIo->HostCapability.BoundarySize; + + CardData->Signature = CARD_DATA_SIGNATURE; + CardData->SdHostIo = SdHostIo; + + Status = MMCSDCardInit (CardData); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to MMCSDCardInit \r\n")); + goto Exit; + } + DEBUG ((EFI_D_INFO, "SdMediaDeviceStart: MMCSDCardInit SuccessFul\n")); + + if (CardData->CardType == CEATACard) { + Status = CEATABlockIoInit (CardData); + } else { + Status = MMCSDBlockIoInit (CardData); + } + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to BlockIoInit \r\n")); + goto Exit; + } + DEBUG ((EFI_D_INFO, "SdMediaDeviceStart: BlockIo is successfully installed\n")); + + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiBlockIoProtocolGuid, + EFI_NATIVE_INTERFACE, + &CardData->BlockIo + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SdMediaDeviceStart: Fail to install gEfiBlockIoProtocolGuid \r\n")); + goto Exit; + } + + // + // Install the component name protocol + // + CardData->ControllerNameTable = NULL; + + AddUnicodeString2 ( + "eng", + gSdMediaDeviceName.SupportedLanguages, + &CardData->ControllerNameTable, + L"MMC/SD Media Device", + TRUE + ); + + AddUnicodeString2 ( + "en", + gSdMediaDeviceName2.SupportedLanguages, + &CardData->ControllerNameTable, + L"MMC/Sd Media Device", + FALSE + ); + +Exit: + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "SdMediaDeviceStart: End with failure\r\n")); + if (CardData != NULL) { + if (CardData->RawBufferPointer != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * SdHostIo->HostCapability.BoundarySize)); + } + FreePool (CardData); + } + } + + return Status; +} + + +/** + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to stop driver on. + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer. + @param[in] ChildHandleBuffer List of handles for the children we need to stop. + + @retval EFI_SUCCESS + @retval others + +**/ +EFI_STATUS +EFIAPI +SdMediaDeviceStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + CARD_DATA *CardData; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + // + // First find BlockIo Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + CardData = CARD_DATA_FROM_THIS (BlockIo); + + // + // Uninstall Block I/O protocol from the device handle + // + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiBlockIoProtocolGuid, + BlockIo + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if (CardData != NULL) { + if (CardData->RawBufferPointer != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * CardData->SdHostIo->HostCapability.BoundarySize)); + } + FreeUnicodeStringTable (CardData->ControllerNameTable); + FreePool (CardData); + } + + gBS->CloseProtocol ( + Controller, + &gEfiSdHostIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h new file mode 100644 index 0000000..fe3c4fa --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDevice.h @@ -0,0 +1,466 @@ +/** @file + The definition for SD media device driver model and blkio protocol routines. + + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> + + 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 _SD_MEDIA_DEVICE_H_ +#define _SD_MEDIA_DEVICE_H_ + +#include <Uefi.h> +#include <Protocol/PciIo.h> +#include <Protocol/BlockIo.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/BaseLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <IndustryStandard/Pci22.h> +#include "ComponentName.h" +#include "SdHostIo.h" + +extern EFI_DRIVER_BINDING_PROTOCOL gSdMediaDeviceDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gSdMediaDeviceName; +extern EFI_COMPONENT_NAME2_PROTOCOL gSdMediaDeviceName2; + +// +// Define the region of memory used for DMA memory +// +#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL +#define CARD_DATA_SIGNATURE SIGNATURE_32 ('c', 'a', 'r', 'd') + +// +// Command timeout will be max 100 ms +// +#define TIMEOUT_COMMAND 100 +#define TIMEOUT_DATA 5000 + +typedef enum{ + UnknownCard = 0, + MMCCard, // MMC card + MMCCardHighCap, // MMC Card High Capacity + CEATACard, // CE-ATA device + SdMemoryCard, // SD 1.1 card + SdMemoryCard2, // SD 2.0 or above standard card + SdMemoryCard2High // SD 2.0 or above high capacity card +} CARD_TYPE; + +typedef struct { + // + // BlockIO + // + UINTN Signature; + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_BLOCK_IO_MEDIA BlockIoMedia; + + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + CARD_TYPE CardType; + + UINT8 CurrentBusWidth; + BOOLEAN DualVoltage; + BOOLEAN NeedFlush; + UINT8 Reserved[3]; + + UINT16 Address; + UINT32 BlockLen; + UINT32 MaxFrequency; + UINT64 BlockNumber; + + // + // Common used + // + CARD_STATUS CardStatus; + OCR OCRRegister; + CID CIDRegister; + CSD CSDRegister; + EXT_CSD ExtCSDRegister; + UINT8 *RawBufferPointer; + UINT8 *AlignedBuffer; + + // + // CE-ATA specific + // + TASK_FILE TaskFile; + IDENTIFY_DEVICE_DATA IndentifyDeviceData; + + // + //SD specific + // + SCR SCRRegister; + SD_STATUS_REG SdSattus; + SWITCH_STATUS SwitchStatus; +} CARD_DATA; + +#define CARD_DATA_FROM_THIS(a) \ + CR(a, CARD_DATA, BlockIo, CARD_DATA_SIGNATURE) + +/** + Test to see if this driver supports ControllerHandle. Any + ControllerHandle that has BlockIoProtocol installed will be supported. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test. + @param[in] RemainingDevicePath Not used. + + @return EFI_SUCCESS This driver supports this device. + @return EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +SdMediaDeviceSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Starting the SD Media Device Driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to test. + @param[in] RemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error. + EFI_OUT_OF_RESOURCES- Failed due to resource shortage. + +**/ +EFI_STATUS +EFIAPI +SdMediaDeviceStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param[in] This Protocol instance pointer. + @param[in] Controller Handle of device to stop driver on. + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer. + @param[in] ChildHandleBuffer List of handles for the children we need to stop. + + @return EFI_SUCCESS + @return others + +**/ +EFI_STATUS +EFIAPI +SdMediaDeviceStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + MMC/SD card init function + + @param[in] CardData Pointer to CARD_DATA. + + @return EFI_SUCCESS + @return others + +**/ +EFI_STATUS +MMCSDCardInit ( + IN CARD_DATA *CardData + ); + +/** + Send command by using Host IO protocol + + @param[in] This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. + @param[in] CommandIndex The command index to set the command index field of command register. + @param[in] Argument Command argument to set the argument field of command register. + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out. + @param[in] Buffer Contains the data read from / write to the device. + @param[in] BufferSize The size of the buffer. + @param[in] ResponseType RESPONSE_TYPE. + @param[in] TimeOut Time out value in 1 ms unit. + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +SendCommand ( + IN CARD_DATA *CardData, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData + ); + +/** + Send the card APP_CMD command with the following command indicated by CommandIndex + + @param[in] CardData Pointer to CARD_DATA. + @param[in] CommandIndex The command index to set the command index field of command register. + @param[in] Argument Command argument to set the argument field of command register. + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out. + @param[in] Buffer Contains the data read from / write to the device. + @param[in] BufferSize The size of the buffer. + @param[in] ResponseType RESPONSE_TYPE. + @param[in] TimeOut Time out value in 1 ms unit. + @param[out] ResponseData Depending on the ResponseType, such as CSD or card status. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_UNSUPPORTED + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +SendAppCommand ( + IN CARD_DATA *CardData, + IN UINT16 CommandIndex, + IN UINT32 Argument, + IN TRANSFER_TYPE DataType, + IN UINT8 *Buffer, OPTIONAL + IN UINT32 BufferSize, + IN RESPONSE_TYPE ResponseType, + IN UINT32 TimeOut, + OUT UINT32 *ResponseData + ); + +/** + Send the card FAST_IO command + + @param[in] CardData Pointer to CARD_DATA. + @param[in] RegisterAddress Register Address. + @param[in, out] RegisterData Pointer to register Data. + @param[in] Write TRUE for write, FALSE for read. + + @retval EFI_SUCCESS + @retval EFI_UNSUPPORTED + @retval EFI_INVALID_PARAMETER + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +FastIO ( + IN CARD_DATA *CardData, + IN UINT8 RegisterAddress, + IN OUT UINT8 *RegisterData, + IN BOOLEAN Write + ); + +/** + Judge whether it is CE-ATA device or not. + + @param[in] CardData Pointer to CARD_DATA. + + @retval TRUE + @retval FALSE + +**/ +BOOLEAN +IsCEATADevice ( + IN CARD_DATA *CardData + ); + +/** + Send software reset + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +SoftwareReset ( + IN CARD_DATA *CardData + ); + +/** + SendATACommand specificed in Taskfile + + @param[in] CardData Pointer to CARD_DATA. + @param[in] TaskFile Pointer to TASK_FILE. + @param[in] Write TRUE means write, FALSE means read. + @param[in] Buffer If NULL, means no data transfer, neither read nor write. + @param[in] SectorCount Buffer size in 512 bytes unit. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +SendATACommand ( + IN CARD_DATA *CardData, + IN TASK_FILE *TaskFile, + IN BOOLEAN Write, + IN UINT8 *Buffer, + IN UINT16 SectorCount + ); + +/** + IDENTIFY_DEVICE command + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +IndentifyDevice ( + IN CARD_DATA *CardData + ); + +/** + FLUSH_CACHE_EXT command + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +FlushCache ( + IN CARD_DATA *CardData + ); + +/** + STANDBY_IMMEDIATE command + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +StandByImmediate ( + IN CARD_DATA *CardData + ); + +/** + READ_DMA_EXT command + + @param[in] CardData Pointer to CARD_DATA. + @param[in] LBA The starting logical block address to read from on the device. + @param[in] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + @param[in] SectorCount Size in 512 bytes unit. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +ReadDMAExt ( + IN CARD_DATA *CardData, + IN EFI_LBA LBA, + IN UINT8 *Buffer, + IN UINT16 SectorCount + ); + +/** + WRITE_DMA_EXT command + + @param[in] CardData Pointer to CARD_DATA. + @param[in] LBA The starting logical block address to read from on the device. + @param[in] Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + @param[in] SectorCount Size in 512 bytes unit. + + @retval EFI_SUCCESS Success + @retval EFI_DEVICE_ERROR Hardware Error + @retval EFI_INVALID_PARAMETER Parameter is error + @retval EFI_NO_MEDIA No media + @retval EFI_MEDIA_CHANGED Media Change + @retval EFI_BAD_BUFFER_SIZE Buffer size is bad + +**/ +EFI_STATUS +WriteDMAExt ( + IN CARD_DATA *CardData, + IN EFI_LBA LBA, + IN UINT8 *Buffer, + IN UINT16 SectorCount + ); + +/** + CEATA card BlockIo init function. + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval Others + +**/ +EFI_STATUS +CEATABlockIoInit ( + IN CARD_DATA *CardData + ); + +/** + MMC/SD card BlockIo init function. + + @param[in] CardData Pointer to CARD_DATA. + + @retval EFI_SUCCESS + @retval Others + +**/ +EFI_STATUS +MMCSDBlockIoInit ( + IN CARD_DATA *CardData + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf new file mode 100644 index 0000000..e352b1d --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/SdMediaDeviceDxe.inf @@ -0,0 +1,64 @@ +## @file +# Component Description File For SdMediaDeviceDxe Module. +# +# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR> +# +# 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 = 0x00010005 + BASE_NAME = SdMediaDevice + FILE_GUID = E076205A-6EDC-4F68-A535-93C5D790B1DA + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeSdMediaDevice + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gSdMediaDeviceDriverBinding +# COMPONENT_NAME = gSdMediaDeviceName +# COMPONENT_NAME2 = gSdMediaDeviceName2 +# + +[Sources] + SdMediaDevice.c + SdMediaDevice.h + MMCSDTransfer.c + CEATA.c + CEATABlockIo.c + MMCSDBlockIo.c + ComponentName.c + ComponentName.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + PcdLib + +[Protocols] + gEfiPciIoProtocolGuid ## TO_START + gEfiSdHostIoProtocolGuid ## TO_START + gEfiBlockIoProtocolGuid ## BY_START + +[Pcd.common] -- 2.7.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.