diff options
author | Guo Mang <mang.guo@intel.com> | 2016-12-23 12:55:57 +0800 |
---|---|---|
committer | Guo Mang <mang.guo@intel.com> | 2016-12-26 19:15:07 +0800 |
commit | 3538dcf484c99fadbc3448078247b498291fd5b1 (patch) | |
tree | 16a85903b43f3c38c08618bd0d50d07af13c663d /Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD | |
parent | 1f6e7e4d497661bebaa19884106997ee35201d14 (diff) | |
download | edk2-platforms-3538dcf484c99fadbc3448078247b498291fd5b1.tar.xz |
BroxtonSiPkg: Add Sdio
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD')
14 files changed, 7002 insertions, 0 deletions
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 0000000000..0bc98618c4 --- /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 0000000000..89d8a270d8 --- /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 0000000000..ff01c85e14 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdControllerDxe/SdController.c @@ -0,0 +1,1803 @@ +/** @file
+ The 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.
+
+**/
+
+#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
+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 0000000000..a70256594f --- /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 0000000000..499c9b75df --- /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 0000000000..cb7a1bb457 --- /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 0000000000..55fd085de3 --- /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 0000000000..15fdaf6d42 --- /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 0000000000..3dea441ca9 --- /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 0000000000..6180a252c1 --- /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 0000000000..e0304deeed --- /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 0000000000..ad0eb2c2e1 --- /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 0000000000..fe3c4fa3d2 --- /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 0000000000..e352b1dc37 --- /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]
|