From a9682fc88738368ae66857ab599a4e6cc9b651e5 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 2 Jun 2016 14:03:12 +0800 Subject: ChvRefCodePkg: Add SDControllerDxe driver. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../SouthCluster/SDControllerDxe/ComponentName.c | 152 ++ .../SouthCluster/SDControllerDxe/MmcHostDxe.inf | 86 ++ .../SDControllerDxe/SdHostController.c | 1557 ++++++++++++++++++++ .../SouthCluster/SDControllerDxe/SdHostDriver.c | 584 ++++++++ .../SouthCluster/SDControllerDxe/SdHostDriver.h | 531 +++++++ 5 files changed, 2910 insertions(+) create mode 100644 ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/ComponentName.c create mode 100644 ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/MmcHostDxe.inf create mode 100644 ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostController.c create mode 100644 ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostDriver.c create mode 100644 ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostDriver.h diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/ComponentName.c b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/ComponentName.c new file mode 100644 index 0000000000..7074d83fd1 --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/ComponentName.c @@ -0,0 +1,152 @@ +/** @file + Component Name protocol implementation. + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SdHostDriver.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gSdHostComponentName = { + SdHostComponentNameGetDriverName, + SdHostComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mSdHostDriverNameTable[] = { + { "eng", L"UEFI SD Host Controller Driver" }, + { NULL , NULL } +}; + +/** + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param[in] 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 function completed successfully + @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 +SdHostComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString ( + Language, + gSdHostComponentName.SupportedLanguages, + mSdHostDriverNameTable, + DriverName + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param[in] Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param[in] 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 +SdHostComponentNameGetControllerName ( + 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; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSdHostIoProtocolGuid, + (VOID **) &SdHostIo, + gSdHostDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + SdHostData = SDHOST_DATA_FROM_THIS (SdHostIo); + + return LookupUnicodeString ( + Language, + gSdHostComponentName.SupportedLanguages, + SdHostData->ControllerNameTable, + ControllerName + ); +} diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/MmcHostDxe.inf b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/MmcHostDxe.inf new file mode 100644 index 0000000000..ad2c64bc12 --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/MmcHostDxe.inf @@ -0,0 +1,86 @@ +## @file +# PCH SD/MMC Controller Dxe Module +# +# Provides support for PCH SD/MMC controller. +# +# Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MmcHost + FILE_GUID = 354492A1-A743-4EEB-BEB9-F8C3E5CAF641 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SdHostDriverEntryPoint + +################################################################################ +# +# The following information is for reference only and not required by the build +# tools. +# +################################################################################ +# VALID_ARCHITECTURES = IA32 X64 IPF EBC + + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ +[Sources.common] + ComponentName.c + SdHostDriver.h + SdHostDriver.c + SdHostController.c + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ +[Packages] + MdePkg/MdePkg.dec + ChvRefCodePkg/ChvRefCodePkg.dec + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + UefiBootServicesTableLib + BaseMemoryLib + MemoryAllocationLib + UefiLib + DevicePathLib + IoLib + PcdLib + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ +[Protocols] + ## TO_START + gEfiPciIoProtocolGuid + + ## BY_START + gEfiSdHostIoProtocolGuid + diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostController.c b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostController.c new file mode 100644 index 0000000000..325756188c --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostController.c @@ -0,0 +1,1557 @@ +/** @file + SD Host I/O protocol implementation + + Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SdHostDriver.h" + +#define STALL_US(us) gBS->Stall (us) +#define STALL_MS(ms) STALL_US ((ms) * 1000) +#define SD_HOST_DEBUG(a) do { \ + if (SdHostData->EnableVerboseDebug) { \ + DEBUG (a); \ + } \ + } while (0); + +UINT32 gSdHostDebugLevel = EFI_D_ERROR; + +/** + Get Error Reason from Host + + @param[in] CommandIndex Command Index which return error + @param[in] ErrorCode Command Error Code + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT Command Timeout Error + @retval EFI_TIMEOUT Data Timeout Error + @retval EFI_CRC_ERROR Command CRC Error + @retval EFI_CRC_ERROR Data CRC Error + @retval EFI_DEVICE_ERROR Command End Bit Error + Command Index Error + Data End Bit Error + Current Limit Error + Auto CMD12 Error + ADMA Error +**/ +STATIC +EFI_STATUS +GetErrorReason ( + IN UINT16 CommandIndex, + IN UINT16 ErrorCode + ) +{ + EFI_STATUS Status; + + Status = EFI_DEVICE_ERROR; + + DEBUG ((gSdHostDebugLevel, "[%2d] -- ", CommandIndex)); + + if (ErrorCode & BIT0) { + Status = EFI_TIMEOUT; + DEBUG ((gSdHostDebugLevel, "Command Timeout Error")); + } + + if (ErrorCode & BIT1) { + Status = EFI_CRC_ERROR; + DEBUG ((gSdHostDebugLevel, "Command CRC Error")); + } + + if (ErrorCode & BIT2) { + DEBUG ((gSdHostDebugLevel, "Command End Bit Error")); + } + + if (ErrorCode & BIT3) { + DEBUG ((gSdHostDebugLevel, "Command Index Error")); + } + if (ErrorCode & BIT4) { + Status = EFI_TIMEOUT; + DEBUG ((gSdHostDebugLevel, "Data Timeout Error")); + } + + if (ErrorCode & BIT5) { + Status = EFI_CRC_ERROR; + DEBUG ((gSdHostDebugLevel, "Data CRC Error")); + } + + if (ErrorCode & BIT6) { + DEBUG ((gSdHostDebugLevel, "Data End Bit Error")); + } + + if (ErrorCode & BIT7) { + DEBUG ((gSdHostDebugLevel, "Current Limit Error")); + } + + if (ErrorCode & BIT8) { + DEBUG ((gSdHostDebugLevel, "Auto CMD12 Error")); + } + + if (ErrorCode & BIT9) { + DEBUG ((gSdHostDebugLevel, "ADMA Error")); + } + + DEBUG ((gSdHostDebugLevel, "\n")); + + return Status; +} + +/** + Read SD Host PCI Config Space Register + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Width Width of PCI IO protocol width + @param[in] Offset PCI config space register offset + @param[in] Buffer A pointer to buffer of read value + + @retval EFI_SUCCESS The data was read from or written to the PCI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not + valid for the PCI BAR specified by BarIndex. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. +**/ +STATIC +EFI_STATUS +SdHostRead ( + IN SDHOST_DATA *SdHost, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Offset, + IN OUT VOID *Buffer + ) +{ + return SdHost->PciIo->Mem.Read ( + SdHost->PciIo, + Width, + 0, + (UINT64) Offset, + 1, + Buffer + ); +} + +/** + Read SD Host PCI Config Space Register in 8 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI config space register offset + + @retval Data Register value read in 8 bits +**/ +UINT8 +SdHostRead8 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset + ) +{ + UINT8 Data; + + SdHostRead (SdHost, EfiPciIoWidthUint8, Offset, &Data); + + return Data; +} + +/** + Read SD Host PCI Config Space Register in 16 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI config space register offset + + @retval Data Register value read in 16 bits +**/ +UINT16 +SdHostRead16 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset + ) +{ + UINT16 Data; + + SdHostRead (SdHost, EfiPciIoWidthUint16, Offset, &Data); + + return Data; +} + +/** + Read SD Host PCI Config Space Register in 32 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI config space register offset + + @retval Data Register value read in 32 bits +**/ +UINT32 +SdHostRead32 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset + ) +{ + UINT32 Data; + + SdHostRead (SdHost, EfiPciIoWidthUint32, Offset, &Data); + + return Data; +} + +/** + Debug Print for SD Host Registers + + @param[in] SdHost A pointer to SDHOST_DATA structure + +**/ +VOID +DebugPrintSdHostRegisters ( + IN SDHOST_DATA *SdHost + ) +{ +#ifdef VERBOSE_REGISTER_ACCESS_DEBUG + UINTN Loop; + + if (!SdHost->EnableVerboseDebug) { + return; + } + + for (Loop = 0; Loop < 0x40; Loop++) { + DEBUG ((EFI_D_INFO, " %02x", SdHostRead8 (SdHost, Loop))); + if ((Loop % 0x10) == 0xf) { + DEBUG ((EFI_D_INFO, "\n")); + } + } +#endif +} +/** + Debug Print for SD Host Registers before write + + @param[in] SdHost A pointer to SDHOST_DATA structure + +**/ +VOID +DebugPreSdHostWrite ( + IN SDHOST_DATA *SdHost + ) +{ +#ifdef VERBOSE_REGISTER_ACCESS_DEBUG + STATIC UINTN DebugCount = 0; + + if (!SdHost->EnableVerboseDebug) { + return; + } + + DebugCount++; + + if (DebugCount < 0x100) { + DEBUG ((EFI_D_INFO, "SD HOST Registers before write:\n")); + DebugPrintSdHostRegisters (SdHost); + } +#endif +} + +/** + Debug Print for SD Host Registers post write + + @param[in] SdHost A pointer to SDHOST_DATA structure + +**/ +VOID +DebugPostSdHostWrite ( + IN SDHOST_DATA *SdHost + ) +{ +#ifdef VERBOSE_REGISTER_ACCESS_DEBUG + STATIC UINTN DebugCount = 0; + + if (!SdHost->EnableVerboseDebug) { + return; + } + + DebugCount++; + + if (DebugCount < 0x10) { + DEBUG ((EFI_D_INFO, "SD HOST Registers after write:\n")); + DebugPrintSdHostRegisters (SdHost); + } +#endif +} + +/** + Write to SD Host PCI Config Space Register + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Width Width of PCI IO protocol width + @param[in] Offset PCI config space register offset + @param[in] Buffer A pointer to buffer of read value + + @retval EFI_SUCCESS The data was read from or written to the PCI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not + valid for the PCI BAR specified by BarIndex. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. +**/ +STATIC +EFI_STATUS +SdHostWrite ( + IN SDHOST_DATA *SdHost, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Offset, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + + DebugPreSdHostWrite (SdHost); + + Status = SdHost->PciIo->Mem.Write ( + SdHost->PciIo, + Width, + 0, + (UINT64) Offset, + 1, + Buffer + ); + + DebugPostSdHostWrite (SdHost); + + return Status; +} + +/** + Write SD Host PCI Config Space Register in 8 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI config space register offset + @param[in] Data Register value write in 8 bits + +**/ +UINT8 +SdHostWrite8 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset, + IN UINT8 Data + ) +{ + SdHostWrite (SdHost, EfiPciIoWidthUint8, Offset, &Data); + + return Data; +} + +/** + Write SD Host PCI Config Space Register in 16 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI config space register offset + @param[in] Data Register value write in 16 bits + +**/ +UINT16 +SdHostWrite16 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset, + IN UINT16 Data + ) +{ + SdHostWrite (SdHost, EfiPciIoWidthUint16, Offset, &Data); + + return Data; +} + +/** + Write SD Host PCI Config Space Register in 32 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI config space register offset + @param[in] Data Register value write in 32 bits + +**/ +UINT32 +SdHostWrite32 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset, + IN UINT32 Data + ) +{ + SdHostWrite (SdHost, EfiPciIoWidthUint32, Offset, &Data); + + return Data; +} + +/** + Check Host Controller Version + + @param[in] SdHost A pointer to SDHOST_DATA structure + + @retval Data16 Controller version number +**/ +UINT32 +CheckControllerVersion ( + IN SDHOST_DATA *SdHost + ) +{ + UINT16 Data16; + Data16 = SdHostRead16 (SdHost, MMIO_CTRLRVER); + DEBUG ((EFI_D_INFO, "CheckControllerVersion: %x \n", Data16 & 0xFF)); + return (Data16 & 0xFF); +} + +/** + Power on/off the LED associated with the slot + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] Enable TRUE to set LED on, FALSE to set LED off + + @retval EFI_SUCCESS The function completed successfully +**/ +STATIC +EFI_STATUS +HostLEDEnable ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN BOOLEAN Enable + ) +{ + SDHOST_DATA *SdHostData; + UINT8 Data; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + Data = SdHostRead8 (SdHostData, MMIO_HOSTCTL); + + if (Enable) { + // + // LED On + // + Data |= BIT0; + } else { + // + // LED Off + // + Data &= ~BIT0; + } + + SdHostWrite8 (SdHostData, MMIO_HOSTCTL, Data); + + return EFI_SUCCESS; +} +/** + The main function used to send the command to the card inserted into the SD/MMC host + slot. It will assemble the arguments to set the command register and wait for the command + and transfer completed until timeout. Then it will read the response register to fill + the ResponseData. + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] CommandIndex The command index to set the command index field of command register + @param[in] Argument Command argument to set the argument field of command register + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out + @param[in] Buffer Contains the data read from / write to the device + @param[in] BufferSize The size of the buffer + @param[in] ResponseType RESPONSE_TYPE + @param[in] TimeOut Time out value in 1 ms unit + @param[in] ResponseData Depending on the ResponseType, such as CSD or card status + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. + @retval EFI_OUT_OF_RESOURCES A resource has run out. + @retval EFI_TIMEOUT The timeout time expired. + @retval EFI_DEVICE_ERROR The physical device reported an error while attempting the operation +**/ +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; + UINT32 ResponseDataCount; + UINT16 Data16; + UINT32 Data32; + UINT64 Data64; + UINT8 Index; + BOOLEAN CommandCompleted; + INT32 Timeout; + + Status = EFI_SUCCESS; + ResponseDataCount = 1; + SdHostData = SDHOST_DATA_FROM_THIS (This); + Timeout = 1000; + + if (Buffer != NULL && DataType == NoData) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((gSdHostDebugLevel, "SendCommand: Invalid parameter -> \n")); + goto Exit; + } + + if (((UINTN)Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN)NULL) { + Status = EFI_INVALID_PARAMETER; + DEBUG ((gSdHostDebugLevel, "SendCommand: Invalid parameter -> \n")); + goto Exit; + } + + DEBUG ((EFI_D_INFO, "SendCommand: CMD%d \n", CommandIndex)); + if (SdHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x00),SdHostRead32 (SdHostData, 0x04),SdHostRead32 (SdHostData, 0x08),SdHostRead32 (SdHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x10),SdHostRead32 (SdHostData, 0x14),SdHostRead32 (SdHostData, 0x18),SdHostRead32 (SdHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x20),SdHostRead32 (SdHostData, 0x24),SdHostRead32 (SdHostData, 0x28),SdHostRead32 (SdHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x30),SdHostRead32 (SdHostData, 0x34),SdHostRead32 (SdHostData, 0x38),SdHostRead32 (SdHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x40),SdHostRead32 (SdHostData, 0x44),SdHostRead32 (SdHostData, 0x48),SdHostRead32 (SdHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x50),SdHostRead32 (SdHostData, 0x54),SdHostRead32 (SdHostData, 0x58),SdHostRead32 (SdHostData, 0x5C))); + } + + // + // Check CMD INHIBIT and DATA INHIBIT before send command + // + Timeout = 10000; + do { + Data32 = SdHostRead32 (SdHostData, MMIO_PSTATE); + if (SdHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "Wait CMD INHIBIT %x\n", Data32)); + } + STALL_US (10); + } while ((Timeout-- > 0) && (Data32 & BIT0)); + + Timeout = 90; + do { + Data32 = SdHostRead32 (SdHostData, MMIO_PSTATE); + if (SdHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "Wait DATA INHIBIT %x\n", Data32)); + } + STALL_US (1100); + } while ((Timeout-- > 0) && (Data32 & BIT1)); + + // + // Clear status bits + // + SD_HOST_DEBUG ((EFI_D_INFO, "NINTSTS(0x30) <- 0x%x\n", (UINTN) 0xffff)); + SdHostWrite16 (SdHostData, MMIO_NINTSTS, 0xffff); + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS(0x30): 0x%x\n", SdHostRead16 (SdHostData, MMIO_NINTSTS))); + + SD_HOST_DEBUG ((EFI_D_INFO, "ERINTSTS <- 0x%x\n", (UINTN) 0xffff)); + SdHostWrite16 (SdHostData, MMIO_ERINTSTS, 0xffff); + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: ERINTSTS(0x32): 0x%x\n", SdHostRead16 (SdHostData, MMIO_ERINTSTS))); + + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: DMAADR(0x00) <- 0x%x\n", (UINTN) Buffer)); + SdHostWrite32 (SdHostData, MMIO_DMAADR, (UINT32)(UINTN) Buffer); + + if (Buffer != NULL) { + Data16 = SdHostRead16 (SdHostData, MMIO_BLKSZ); + Data16 &= ~(0xFFF); + if (BufferSize <= SdHostData->BlockLength) { + Data16 |= BufferSize; + } else { + Data16 |= SdHostData->BlockLength; + } + + Data16 |= 0x7000; // Set to 512KB for SDMA block size + + } else { + Data16 = 0; + } + + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: BLKSZ(0x04) <- 0x%x\n", Data16)); + SdHostWrite16 (SdHostData, MMIO_BLKSZ, Data16); + + if (Buffer != NULL) { + if (BufferSize <= SdHostData->BlockLength) { + Data16 = 1; + } else { + Data16 = (UINT16) (BufferSize / SdHostData->BlockLength); + } + } else { + Data16 = 0; + } + + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: BLKCNT(0x06) <- 0x%x\n", Data16)); + SdHostWrite16 (SdHostData, MMIO_BLKCNT, Data16); + + // + // Argument + // + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: CMDARG(0x08) <- 0x%x\n", Argument)); + SdHostWrite32 (SdHostData, MMIO_CMDARG, Argument); + + // + // Transfer Mode + // + Data16 = SdHostRead16 (SdHostData, MMIO_XFRMODE); + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: XFRMODE(0x0C) mode read 0x%x\n", Data16)); + + // + // BIT0 - DMA Enable + // BIT2 - Auto Cmd12 + // + if (DataType == InData) { + Data16 |= BIT4 | BIT0; + } else if (DataType == OutData) { + Data16 &= ~BIT4; + Data16 |= BIT0; + } else { + Data16 &= ~(BIT4 | BIT0); + } + + if (BufferSize <= SdHostData->BlockLength) { + Data16 &= ~ (BIT5 | BIT1 | BIT2); + } else { + if (SdHostData->IsAutoStopCmd && !SdHostData->IsEmmc) { + Data16 |= (BIT5 | BIT1 | BIT2); + } else { + Data16 |= (BIT5 | BIT1); + } + } + if (CommandIndex == SEND_EXT_CSD) { + Data16 |= BIT1; + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand:Enable bit 1, XFRMODE <- 0x%x\n", Data16)); + } + + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: XFRMODE(0x0C) <- 0x%x\n", Data16)); + SdHostWrite16 (SdHostData, MMIO_XFRMODE, Data16); + + // + // 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: + Data16 = (CommandIndex << 8); + ResponseDataCount = 0; + break; + + case ResponseR1: + case ResponseR5: + case ResponseR6: + case ResponseR7: + Data16 = (CommandIndex << 8) | BIT1 | BIT4| BIT3; + ResponseDataCount = 1; + break; + + case ResponseR1b: + case ResponseR5b: + Data16 = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3; + ResponseDataCount = 1; + break; + + case ResponseR2: + Data16 = (CommandIndex << 8) | BIT0 | BIT3; + ResponseDataCount = 4; + break; + + case ResponseR3: + case ResponseR4: + Data16 = (CommandIndex << 8) | BIT1; + ResponseDataCount = 1; + break; + + default: + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + if (DataType != NoData) { + Data16 |= BIT5; + } + + HostLEDEnable (This, TRUE); + + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: SDCMD(0x0E) <- 0x%x\n", Data16)); + CommandCompleted = FALSE; + SdHostWrite16 (SdHostData, MMIO_SDCMD, Data16); + + if (SdHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "After write to Command\n")); + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x00),SdHostRead32 (SdHostData, 0x04),SdHostRead32 (SdHostData, 0x08),SdHostRead32 (SdHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x10),SdHostRead32 (SdHostData, 0x14),SdHostRead32 (SdHostData, 0x18),SdHostRead32 (SdHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x20),SdHostRead32 (SdHostData, 0x24),SdHostRead32 (SdHostData, 0x28),SdHostRead32 (SdHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x30),SdHostRead32 (SdHostData, 0x34),SdHostRead32 (SdHostData, 0x38),SdHostRead32 (SdHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x40),SdHostRead32 (SdHostData, 0x44),SdHostRead32 (SdHostData, 0x48),SdHostRead32 (SdHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x50),SdHostRead32 (SdHostData, 0x54),SdHostRead32 (SdHostData, 0x58),SdHostRead32 (SdHostData, 0x5C))); + } + + TimeOut *= 1000; // ms to us conversion + do { + Data16 = SdHostRead16 (SdHostData, MMIO_ERINTSTS); + if (SdHostData->EnableVerboseDebug && (Data16 != 0)) { + DEBUG ((EFI_D_INFO, "SendCommand: ERINTSTS(0x32): 0x%x\n", Data16)); + DEBUG ((EFI_D_INFO, "SendCommand: ERINTEN(0x36): 0x%x\n", SdHostRead16 (SdHostData, MMIO_ERINTEN))); + DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS(0x30): 0x%x\n", SdHostRead16 (SdHostData, MMIO_NINTSTS))); + DEBUG ((EFI_D_INFO, "SendCommand: NINTEN(0x34): 0x%x\n", SdHostRead16 (SdHostData, MMIO_NINTEN))); + } + + if ((Data16 & 0x17FF) != 0) { + Status = GetErrorReason (CommandIndex, Data16); + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x00),SdHostRead32 (SdHostData, 0x04),SdHostRead32 (SdHostData, 0x08),SdHostRead32 (SdHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x10),SdHostRead32 (SdHostData, 0x14),SdHostRead32 (SdHostData, 0x18),SdHostRead32 (SdHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x20),SdHostRead32 (SdHostData, 0x24),SdHostRead32 (SdHostData, 0x28),SdHostRead32 (SdHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x30),SdHostRead32 (SdHostData, 0x34),SdHostRead32 (SdHostData, 0x38),SdHostRead32 (SdHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x40),SdHostRead32 (SdHostData, 0x44),SdHostRead32 (SdHostData, 0x48),SdHostRead32 (SdHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x50),SdHostRead32 (SdHostData, 0x54),SdHostRead32 (SdHostData, 0x58),SdHostRead32 (SdHostData, 0x5C))); + goto Exit; + } + + Data16 = SdHostRead16 (SdHostData, MMIO_NINTSTS) & 0x1ff; + if (SdHostData->EnableVerboseDebug && (Data16 > 1)) { + DEBUG ((EFI_D_INFO, "SendCommand: NINTSTS(0x30): 0x%x\n", Data16)); + } + + if ((Data16 & BIT0) == BIT0) { + // + // Command completed + // + CommandCompleted = TRUE; + + SdHostWrite16 (SdHostData, MMIO_NINTSTS, BIT0); + + if ((DataType == NoData) && (ResponseType != ResponseR1b)) { + break; + } + } + + if (CommandCompleted) { + // + // DMA interrupted + // + if ((Data16 & BIT3) == BIT3) { + SdHostWrite16 (SdHostData, MMIO_NINTSTS, BIT3); + Data32 = SdHostRead32 (SdHostData, MMIO_DMAADR); + + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: DMAADR(0x00) <- 0x%x\n", Data32)); + SdHostWrite32 (SdHostData, MMIO_DMAADR, Data32); + } + + // + // Transfer completed + // + if ((Data16 & BIT1) == BIT1) { + SdHostWrite16 (SdHostData, MMIO_NINTSTS, BIT1); + break; + } + } + + STALL_US (1); + + TimeOut --; + + } while (TimeOut > 0); + + if (TimeOut == 0) { + Status = EFI_TIMEOUT; + DEBUG ((gSdHostDebugLevel, "SendCommand: Time out \n")); + goto Exit; + } + + if (ResponseData != NULL) { + UINT32 *ResDataPtr = NULL; + + ResDataPtr = ResponseData; + for (Index = 0; Index < ResponseDataCount; Index++) { + *ResDataPtr = SdHostRead32 (SdHostData, MMIO_RESP + Index * 4); + ResDataPtr++; + } + SD_HOST_DEBUG ((EFI_D_INFO, "Response Data 0: RESPONSE(0x10) <- 0x%x\n", *ResponseData)); + + if (ResponseType == ResponseR2) { + // + // Adjustment for R2 response + // + Data32 = 1; + for (Index = 0; Index < ResponseDataCount; Index++) { + Data64 = LShiftU64(*ResponseData, 8); + *ResponseData = (UINT32)((Data64 & 0xFFFFFFFF) | Data32); + Data32 = (UINT32)RShiftU64 (Data64, 32); + ResponseData++; + } + } + } + + if (SdHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_INFO, "Before Exit Send Command\n")); + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x00),SdHostRead32 (SdHostData, 0x04),SdHostRead32 (SdHostData, 0x08),SdHostRead32 (SdHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x10),SdHostRead32 (SdHostData, 0x14),SdHostRead32 (SdHostData, 0x18),SdHostRead32 (SdHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x20),SdHostRead32 (SdHostData, 0x24),SdHostRead32 (SdHostData, 0x28),SdHostRead32 (SdHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x30),SdHostRead32 (SdHostData, 0x34),SdHostRead32 (SdHostData, 0x38),SdHostRead32 (SdHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x40),SdHostRead32 (SdHostData, 0x44),SdHostRead32 (SdHostData, 0x48),SdHostRead32 (SdHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x50),SdHostRead32 (SdHostData, 0x54),SdHostRead32 (SdHostData, 0x58),SdHostRead32 (SdHostData, 0x5C))); + } + +Exit: + HostLEDEnable (This, FALSE); + SD_HOST_DEBUG ((EFI_D_INFO, "SendCommand: Status -> %r\n", Status)); + + 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 Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] MaxFrequency Max frequency in HZ + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. +**/ +EFI_STATUS +EFIAPI +SetClockFrequency ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 MaxFrequency + ) +{ + UINT16 Data16; + UINT32 Frequency; + UINT32 Divider = 0; + SDHOST_DATA *SdHostData; + UINT32 TimeOutCount; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + DEBUG ((gSdHostDebugLevel, "SetClockFrequency: BaseClockInMHz = %d \n", SdHostData->BaseClockInMHz)); + + Frequency = (SdHostData->BaseClockInMHz * 1000 * 1000) / MaxFrequency; + DEBUG ((gSdHostDebugLevel, "SetClockFrequency: FrequencyInHz = %d \n", Frequency)); + + if ((SdHostData->BaseClockInMHz * 1000 * 1000 % MaxFrequency) != 0) { + Frequency += 1; + } + + Divider = 1; + while (Frequency > Divider) { + Divider = Divider * 2; + } + if (Divider >= 0x400) { + Divider = 0x200; + } + DEBUG ((gSdHostDebugLevel, "SetClockFrequency: before shift: Base Clock Divider = 0x%x \n", Divider)); + + Divider = Divider >> 1; + + DEBUG ((gSdHostDebugLevel, "SetClockFrequency: after shift: Base Clock Divider = 0x%x \n", Divider)); + + SdHostData->CurrentClockInKHz = (SdHostData->BaseClockInMHz * 1000); + if (Divider != 0) { + SdHostData->CurrentClockInKHz = SdHostData->CurrentClockInKHz / (Divider * 2); + } + + // + // Set frequency + // 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 + // 00h - Highest Frequency the target support (10MHz-63MHz) + // + // Bit [07:06] are assigned to bit 09-08 of clock divider in SDCLK Frequency Select on SD controller 3.0 + // + if (2 == CheckControllerVersion(SdHostData)) { + Data16 =(UINT16)( (Divider & 0xFF) << 8 | (((Divider & 0xFF00) >>8)<<6)); + } else { + Data16 = (UINT16) ( Divider << 8); + } + + DEBUG ((gSdHostDebugLevel, + "SetClockFrequency: base=%dMHz, clkctl=0x%04x, f=%dKHz\n", + SdHostData->BaseClockInMHz, + Data16, + SdHostData->CurrentClockInKHz + )); + DEBUG ((gSdHostDebugLevel, "SetClockFrequency: set MMIO_CLKCTL value = 0x%x \n", Data16)); + SdHostWrite16 (SdHostData, MMIO_CLKCTL, Data16); + + STALL_US (100); + Data16 |= BIT0; + SdHostWrite16 (SdHostData, MMIO_CLKCTL, Data16); + + TimeOutCount = TIME_OUT_1S; + do { + Data16 = SdHostRead16 (SdHostData, MMIO_CLKCTL); + STALL_US (100); + TimeOutCount --; + if (TimeOutCount == 0) { + DEBUG ((gSdHostDebugLevel, "SetClockFrequency: Timeout\n")); + return EFI_TIMEOUT; + } + } while ((Data16 & BIT1) != BIT1); + + STALL_MS (1); + Data16 |= BIT2; + SdHostWrite16 (SdHostData, MMIO_CLKCTL, Data16); + + return EFI_SUCCESS; +} + +/** + Set bus width of the host + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] BusWidth Bus width in 1, 4, 8 bits + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetBusWidth ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BusWidth + ) +{ + SDHOST_DATA *SdHostData; + UINT8 Data; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) { + DEBUG ((gSdHostDebugLevel, "SetBusWidth: Invalid parameter \n")); + return EFI_INVALID_PARAMETER; + } + + if ((SdHostData->SdHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) { + DEBUG ((gSdHostDebugLevel, "SetBusWidth: Invalid parameter \r\n")); + return EFI_INVALID_PARAMETER; + } + + Data = SdHostRead8 (SdHostData, MMIO_HOSTCTL); + + // + // BIT3 8-bit MMC Support (MMC8): + // If set, SCH supports 8-bit MMC. When cleared, SCH does not support this feature + // + if (BusWidth == 8) { + DEBUG ((gSdHostDebugLevel, "SetBusWidth: Bus Width is 8-bit ... \r\n")); + Data |= BIT5; + } else if (BusWidth == 4) { + DEBUG ((gSdHostDebugLevel, "SetBusWidth: Bus Width is 4-bit ... \r\n")); + Data &= ~BIT5; + Data |= BIT1; + } else { + DEBUG ((gSdHostDebugLevel, "SetBusWidth: Bus Width is 1-bit ... \r\n")); + Data &= ~BIT5; + Data &= ~BIT1; + } + + SdHostWrite8 (SdHostData, MMIO_HOSTCTL, Data); + DEBUG ((gSdHostDebugLevel, "SetBusWidth:MMIO_HOSTCTL value: 0x%x \n", SdHostRead8 (SdHostData, MMIO_HOSTCTL))); + + return EFI_SUCCESS; +} + +/** + Set voltage which could supported by the host. + Support 0(Power off the host), 1.8V, 3.0V, 3.3V + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] Voltage Units in 0.1 V + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetHostVoltage ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 Voltage + ) +{ + SDHOST_DATA *SdHostData; + UINT8 Data; + EFI_STATUS Status; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + Status = EFI_SUCCESS; + + Data = SdHostRead8 (SdHostData, MMIO_PWRCTL); + + if (Voltage == 0) { + // + // Power Off the host + // + Data &= ~BIT0; + } else if (Voltage <= 18 && This->HostCapability.V18Support) { + // + // 1.8V + // + Data |= (BIT1 | BIT3 | BIT0); + } else if (Voltage > 18 && Voltage <= 30 && This->HostCapability.V30Support) { + // + // 3.0V + // + Data |= (BIT2 | BIT3 | BIT0); + } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) { + // + // 3.3V + // + Data |= (BIT1 | BIT2 | BIT3 | BIT0); + } else { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + SdHostWrite8 (SdHostData, MMIO_PWRCTL, Data); + STALL_MS (1); + +Exit: + return Status; +} + +/** + Set Host High Speed + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] HighSpeed True for High Speed Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetHostSpeedMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 HighSpeed + ) +{ + SDHOST_DATA *SdHostData; + UINT8 Data8; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + if (SdHostData->IsEmmc) { + Data8 = SdHostRead8 (SdHostData, MMIO_HOSTCTL); + Data8 &= ~(BIT2); + if (HighSpeed) { + Data8 |= BIT2; + DEBUG ((gSdHostDebugLevel, "High Speed mode: Data8=0x%x \n", Data8)); + } else { + DEBUG ((gSdHostDebugLevel, "Normal Speed mode: Data8=0x%x \n", Data8)); + } + SdHostWrite8 (SdHostData, MMIO_HOSTCTL, Data8); + STALL_US (100); + DEBUG ((gSdHostDebugLevel, "MMIO_HOSTCTL value: 0x%x \n", SdHostRead8 (SdHostData, MMIO_HOSTCTL))); + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Set Host DDR Mode + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] DdrMode True for DDR Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetHostDdrMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 DdrMode + ) +{ + SDHOST_DATA *SdHostData; + UINT16 ModeSet; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + if (SdHostData->IsEmmc) { + ModeSet = SdHostRead16 (SdHostData, MMIO_HOST_CTL2); + ModeSet &= ~(BIT0 | BIT1 | BIT2); + if (DdrMode) { + ModeSet |= 0x0004; + ModeSet |= BIT3; // 1.8V Signaling Enable + DEBUG ((gSdHostDebugLevel, "DDR mode: Data16=0x%x \n", ModeSet)); + } else { + if (CheckControllerVersion(SdHostData) != 2) { + ModeSet = 0x0; + } + } + + SdHostWrite16 (SdHostData, MMIO_HOST_CTL2, ModeSet); + STALL_US (100); + DEBUG ((gSdHostDebugLevel, "MMIO_HOST_CTL2 value: 0x%x \n", SdHostRead16 (SdHostData, MMIO_HOST_CTL2))); + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Set Host SDR Mode + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] DdrMode True for SDR Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetHostSdrMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 SdrMode + ) +{ + SDHOST_DATA *SdHostData; + UINT16 ModeSet; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + if (SdHostData->IsEmmc) { + ModeSet = SdHostRead16 (SdHostData, MMIO_HOST_CTL2); + ModeSet &= ~(BIT0 | BIT1 | BIT2); + if (SdrMode) { + if (SdHostData->SdHostIo.HostCapability.SDR104Support) { + ModeSet |= 3; + } else if (SdHostData->SdHostIo.HostCapability.SDR50Support) { + ModeSet |= 2; + } + ModeSet |= 1; + ModeSet |= BIT3; // 1.8V Signaling Enable + DEBUG ((gSdHostDebugLevel, "SDR mode: Data16=0x%x \n", ModeSet)); + } else { + if (CheckControllerVersion(SdHostData) != 2) { + ModeSet = 0x0; + } + } + + SdHostWrite16 (SdHostData, MMIO_HOST_CTL2, ModeSet); + STALL_US (100); + DEBUG ((gSdHostDebugLevel, "MMIO_HOST_CTL2 value: 0x%x \n", SdHostRead16 (SdHostData, MMIO_HOST_CTL2))); + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Reset the host + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] ResetAll TRUE to reset all + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. +**/ +EFI_STATUS +EFIAPI +ResetSdHost ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN RESET_TYPE ResetType + ) +{ + SDHOST_DATA *SdHostData; + UINT8 Data8; + UINT32 Data; + UINT16 ErrStatus; + UINT8 Mask; + UINT32 TimeOutCount; + UINT16 SaveClkCtl; + UINT16 SavePwrCtl = 0; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + if ((SdHostData->PciDid == 0x2294)) { + SdHostData->IsEmmc = TRUE; + } else { + SdHostData->IsEmmc = FALSE; + } + + Mask = 0; + ErrStatus = 0; + + if (ResetType == Reset_Auto) { + ErrStatus = SdHostRead16 (SdHostData, MMIO_ERINTSTS); + if ((ErrStatus & 0xF) != 0) { + // + // Command Line + // + Mask |= BIT1; + } + if ((ErrStatus & 0x70) != 0) { + // + // Data Line + // + Mask |= BIT2; + } + } + + if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) { + Mask |= BIT2; + } + if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) { + Mask |= BIT1; + } + if (ResetType == Reset_All) { + Mask = BIT0; + } + if (ResetType == Reset_HW) { + SavePwrCtl = SdHostRead16 (SdHostData, MMIO_PWRCTL); + DEBUG ((gSdHostDebugLevel, "Write SavePwrCtl: %x \n", (SavePwrCtl|BIT4))); + + SdHostWrite16 (SdHostData, MMIO_PWRCTL, SavePwrCtl|BIT4); + STALL_US (100); + DEBUG ((gSdHostDebugLevel, "Write SavePwrCtl: %x \n", (SavePwrCtl&(~BIT4)))); + SdHostWrite16 (SdHostData, MMIO_PWRCTL, SavePwrCtl&(~BIT4)); + STALL_US (100); + } + + 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. + // + SaveClkCtl = SdHostRead16 (SdHostData, MMIO_CLKCTL); + + SdHostWrite16 (SdHostData, MMIO_CLKCTL, 0); + + STALL_US (5); + + // + // Reset the SD host controller + // + SdHostWrite8 (SdHostData, MMIO_SWRST, Mask); + + Data = 0; + TimeOutCount = TIME_OUT_1S; + do { + + STALL_US (100); + + TimeOutCount --; + + Data8 = SdHostRead8 (SdHostData, MMIO_SWRST); + if ((Data8 & Mask) == 0) { + break; + } + } while (TimeOutCount > 0); + + // + // We now restore the MMIO_CLKCTL register which we set to 0 above. + // + SdHostWrite16 (SdHostData, MMIO_CLKCTL, SaveClkCtl); + + if (TimeOutCount == 0) { + DEBUG ((gSdHostDebugLevel, "ResetSDHost: Time out \n")); + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Enable Auto Stop Command + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] Enable TRUE to enable Auto Stop Command + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. +**/ +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 + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] BlockLength Card supported block length + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. +**/ +EFI_STATUS +EFIAPI +SetBlockLength ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BlockLength + ) +{ + SDHOST_DATA *SdHostData; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + DEBUG ((gSdHostDebugLevel, "SetBlockLength: Block length on the host controller: %d \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 Pointer to EFI_SD_HOST_IO_PROTOCOL + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_NOT_FOUND The item was not found. +**/ +EFI_STATUS +EFIAPI +DetectCardAndInitHost ( + IN EFI_SD_HOST_IO_PROTOCOL *This + ) +{ + SDHOST_DATA *SdHostData; + UINT16 Data16; + UINT32 Data; + EFI_STATUS Status; + UINT8 Voltages[] = { 33, 30, 18 }; + UINTN Loop; + + SdHostData = SDHOST_DATA_FROM_THIS (This); + + Data = 0; + Data = SdHostRead32 (SdHostData, MMIO_PSTATE); + + if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) { + // + // Has no card inserted + // + DEBUG ((gSdHostDebugLevel, "DetectCardAndInitHost: No card\n")); + Status = EFI_NOT_FOUND; + goto Exit; + } + DEBUG ((gSdHostDebugLevel, "DetectCardAndInitHost: Card present\n")); + + // + // Enable normal status change + // + SdHostWrite16 (SdHostData, MMIO_NINTEN, BIT1 | BIT0); + + // + // Enable error status change + // + Data16 = SdHostRead16 (SdHostData, MMIO_ERINTEN); + Data16 |= 0xFFFF; //(BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8); + SdHostWrite16 (SdHostData, MMIO_ERINTEN, Data16); + + // + // Data transfer Timeout control + // + SdHostWrite8 (SdHostData, MMIO_TOCTL, 0x0E); + + // + // Stall 1 milliseconds to increase SD stability. + // + STALL_US (100); + + Status = SetClockFrequency (This, FREQUENCY_OD); + if (EFI_ERROR (Status)) { + DEBUG ((gSdHostDebugLevel, "DetectCardAndInitHost: SetClockFrequency failed\n")); + goto Exit; + } + DEBUG ((gSdHostDebugLevel, "DetectCardAndInitHost: SetClockFrequency done\n")); + + Status = EFI_NOT_FOUND; + for (Loop = 0; Loop < sizeof (Voltages); Loop++) { + DEBUG (( + EFI_D_INFO, + "DetectCardAndInitHost: SetHostVoltage %d.%dV\n", + Voltages[Loop] / 10, + Voltages[Loop] % 10 + )); + Status = SetHostVoltage (This, Voltages[Loop]); + if (EFI_ERROR (Status)) { + DEBUG ((gSdHostDebugLevel, "DetectCardAndInitHost: SetHostVoltage failed\n")); + } else { + DEBUG ((gSdHostDebugLevel, "DetectCardAndInitHost: SetHostVoltage done\n")); + break; + } + } + if (EFI_ERROR (Status)) { + DEBUG ((gSdHostDebugLevel, "DetectCardAndInitHost: Failed to SetHostVoltage\n")); + goto Exit; + } + +Exit: + return Status; +} + +/** + Setup Device for card initialization + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EFIAPI +SetupDevice ( + IN EFI_SD_HOST_IO_PROTOCOL *This + ) +{ + UINT32 tempD; + INT32 timeOut; + UINT8 temp8; + UINT16 temp16; + SDHOST_DATA *SdHostData; + + tempD = 0; + timeOut = 1000; + temp8 = 0; + temp16 = 0; + SdHostData = SDHOST_DATA_FROM_THIS (This); + + // + // Disable SDCLK + // + SdHostWrite32 (SdHostData, MMIO_CLKCTL, 0); + STALL_US(5 * 1000); + // + // Disable Bus Power + // + SdHostWrite8 (SdHostData, MMIO_PWRCTL, 0); + STALL_US(5 * 1000); + // + // Reset HC and wait for self-clear + // + SdHostWrite8 (SdHostData, MMIO_SWRST, 0x7); + STALL_US(5 * 1000); + timeOut = 1000; + do { + temp8 = SdHostRead8 (SdHostData, MMIO_SWRST); + timeOut--; + } while ((temp8 & (1 << 0)) && (timeOut > 0)); + + DEBUG ((EFI_D_ERROR, "Reset HC and wait for self-clear Done\n")); + // + // Enable all interrupt status bits (NO CARD_INTERRUPT!) + // + SdHostWrite16 (SdHostData, MMIO_NINTEN, 0x3); + // + // Clear all interrupt status bits + // + SdHostWrite16 (SdHostData, MMIO_NINTSTS, 0xFFFF); + + SdHostWrite16 (SdHostData, MMIO_ERINTEN, 0xFFFF); + + if (2 == CheckControllerVersion(SdHostData)) { + // + // SD Controller 3.0 uses bit 6, bit7 for Divider bit 8, bit 9. 200M base clock needs 0x100. + // + temp16 = (UINT16) (0x1 << 6); + } else { + // + // SD controller 2.0, 100M base clock needs 0x80 + // + temp16 = (UINT16) (0x80 << 8); + } + // + // Set to 400KHz, enable internal clock and wait for stability + // + SdHostWrite32 (SdHostData, MMIO_CLKCTL, (1 << 0) | temp16); + + STALL_US(5 * 1000); + timeOut = 1000; + do { + tempD = SdHostRead32 (SdHostData, MMIO_CLKCTL); + timeOut--; + } while ((!(tempD & (1 << 1))) && (timeOut > 0)); + STALL_US(5 * 1000); + // + // Enable SD clock + // + tempD |= (1 << 2); + SdHostWrite32 (SdHostData, MMIO_CLKCTL, tempD); + STALL_US(5 * 1000); + + temp8 = SdHostRead8 (SdHostData, MMIO_PWRCTL); + DEBUG ((EFI_D_ERROR, "==========%a, %d, offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + // + // Apply 1.8V to the bus + // + temp8 = (0x5 << (1)); + SdHostWrite8 (SdHostData, MMIO_PWRCTL, temp8); + STALL_US(5 * 1000); + temp8 = SdHostRead8 (SdHostData, MMIO_PWRCTL); + DEBUG ((EFI_D_ERROR, "==========%a, %d, set (0x5<<1):offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + // + // Clear 1.8V signaling Enabled + // + temp16 = SdHostRead16 (SdHostData, MMIO_HOST_CTL2); + temp16 &= (UINT16)~BIT3; + SdHostWrite16 (SdHostData, MMIO_HOST_CTL2, temp16); + DEBUG ((gSdHostDebugLevel, "Clear 1.8 V signaling Enable:0x%x \r\n", SdHostRead16 (SdHostData, MMIO_HOST_CTL2))); + // + // Apply power to SD + // + temp8 = SdHostRead8 (SdHostData, MMIO_PWRCTL); + DEBUG ((EFI_D_ERROR, "==========%a, %d, read offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + + temp8 |= (1 << (0)); + DEBUG ((EFI_D_ERROR, "==========%a, %d, set 1<<0:offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + + SdHostWrite8 (SdHostData, MMIO_PWRCTL, temp8); + STALL_US(5 * 1000); + temp8 = SdHostRead8 (SdHostData, MMIO_PWRCTL); + + DEBUG ((EFI_D_ERROR, "==========%a, %d, read offset=0x%x, PWRCTL = 0x%x================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8)); + + do { + temp8 = SdHostRead8 (SdHostData, MMIO_PWRCTL); + STALL_US (1); + timeOut--; + } while ((!(temp8 & (1 << 0))) && (timeOut > 0)); + DEBUG ((EFI_D_ERROR, "==========%a, %d, read offset=0x%x, PWRCTL = 0x%x, timeOut =%d================\n", __FUNCTION__, __LINE__, MMIO_PWRCTL, temp8, timeOut)); + // + // MAX out the DATA_TIMEOUT + // + SdHostWrite8 (SdHostData, MMIO_TOCTL, 0xE); + STALL_US(5 * 1000); + + if (SdHostData->EnableVerboseDebug) { + DEBUG ((EFI_D_ERROR, "==========%a, Start. RegMap================\n", __FUNCTION__)); + DEBUG ((EFI_D_INFO, "00 -10: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x00),SdHostRead32 (SdHostData, 0x04),SdHostRead32 (SdHostData, 0x08),SdHostRead32 (SdHostData, 0x0C))); + DEBUG ((EFI_D_INFO, "10 -20: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x10),SdHostRead32 (SdHostData, 0x14),SdHostRead32 (SdHostData, 0x18),SdHostRead32 (SdHostData, 0x1C))); + DEBUG ((EFI_D_INFO, "20 -30: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x20),SdHostRead32 (SdHostData, 0x24),SdHostRead32 (SdHostData, 0x28),SdHostRead32 (SdHostData, 0x2C))); + DEBUG ((EFI_D_INFO, "30 -40: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x30),SdHostRead32 (SdHostData, 0x34),SdHostRead32 (SdHostData, 0x38),SdHostRead32 (SdHostData, 0x3C))); + DEBUG ((EFI_D_INFO, "40 -50: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x40),SdHostRead32 (SdHostData, 0x44),SdHostRead32 (SdHostData, 0x48),SdHostRead32 (SdHostData, 0x4C))); + DEBUG ((EFI_D_INFO, "50 -60: %08x %08x %08x %08x \n", SdHostRead32 (SdHostData, 0x50),SdHostRead32 (SdHostData, 0x54),SdHostRead32 (SdHostData, 0x58),SdHostRead32 (SdHostData, 0x5C))); + DEBUG ((EFI_D_ERROR, "==========%a, END. RegMap================\n", __FUNCTION__)); + } + return EFI_SUCCESS; +} + diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostDriver.c b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostDriver.c new file mode 100644 index 0000000000..77fcaf0c7b --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostDriver.c @@ -0,0 +1,584 @@ +/** @file + UEFI Driver Entry and Binding support. + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SdHostDriver.h" +#include + +// +// MMCSDIOController Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gSdHostDriverBinding = { + SdHostDriverBindingSupported, + SdHostDriverBindingStart, + SdHostDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_SD_HOST_IO_PROTOCOL mSdHostIo = { + EFI_SD_HOST_IO_PROTOCOL_REVISION_01, + { + 0, // HighSpeedSupport + 0, // V18Support + 0, // V30Support + 0, // V33Support + 0, // SDR50Support + 0, // SDR104Support + 0, // DDR50Support + 0, // Reserved0 + 0, // BusWidth4 + 0, // BusWidth8 + 0, // Reserved1 + 0, // SDMASupport + 0, // ADMA2Support + 0, // DmaMode + 0, // ReTune Timer + 0, // ReTune Mode + 0, // Reserved2 + (512 * 1024) // BoundarySize 512 KB + }, + SendCommand, + SetClockFrequency, + SetBusWidth, + SetHostVoltage, + SetHostDdrMode, + SetHostSdrMode, + ResetSdHost, + EnableAutoStopCmd, + DetectCardAndInitHost, + SetBlockLength, + SetupDevice, + SetHostSpeedMode +}; + +/** + Entry point for SD Host EFI drivers. + + @param[in] ImageHandle EFI_HANDLE + @param[in] SystemTable EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function failed to complete +**/ +EFI_STATUS +EFIAPI +SdHostDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gSdHostDriverBinding, + ImageHandle, + &gSdHostComponentName, + NULL, + NULL + ); +} + +/** + Test to see if this SD Host driver supports ControllerHandle. + Any ControllerHandle that has installed will be supported. + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to test + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver supports this device + @retval EFI_UNSUPPORTED This driver does not support this device +**/ +EFI_STATUS +EFIAPI +SdHostDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_SD_HOST_IO_PROTOCOL *SdHostIo; + PCI_CLASSC PciClass; + UINT32 VidDid; + UINT32 Bar0 = 0; + UINT32 Bar1 = 0; + UINTN Seg, Bus, Dev, Func; + + // + // Verify the SD IO Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSdHostIoProtocolGuid, + (VOID **)&SdHostIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_INFO, "SdHost controller already started, Controller:0x%016Lx\r\n", (UINT64)(UINTN)Controller)); + Status = EFI_ALREADY_STARTED; + return Status; + } + + // + // Test whether there is PCI IO Protocol attached on the controller handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID**) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_VENDOR_ID_OFFSET, + 1, + &VidDid + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CLASSCODE_OFFSET, + sizeof (PCI_CLASSC) / sizeof (UINT8), + &PciClass + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0x10, + 1, + &Bar0 + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0x10, + 1, + &Bar1 + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + if ( !(VidDid == 0x22948086 || VidDid == 0x0F508086 || VidDid == 0x22968086)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) || + (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) || + ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA)) + ) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + Status = PciIo->GetLocation ( + PciIo, + &Seg, + &Bus, + &Dev, + &Func + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + DEBUG ((EFI_D_INFO, "SdHostDriverBindingSupported0: Seg %d, bus:%d,Dev:%d,Func:%d\n", Seg, Bus, Dev,Func)); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingSupported1: VidDid %08x\n", VidDid)); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingSupported1: Base Code %x\n", PciClass.BaseCode)); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingSupported1: SubClassCode %x\n", PciClass.SubClassCode)); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingSupported1: PI %x\n", PciClass.PI)); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingSupported0: MEMIO Base0 %x\n", Bar0)); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingSupported0: MEMIO Base1 %x\n", Bar1)); + +Exit: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; +} + +/** + Starting the SD Host Driver + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to start + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver start this device + @retval EFI_UNSUPPORTED This driver does not support this device + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error + @retval EFI_OUT_OF_RESOURCES This driver cannot allocate resources +**/ +EFI_STATUS +EFIAPI +SdHostDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + SDHOST_DATA *SdHostData; + UINT32 Data; + UINT16 Data16; + UINT32 VidDid; + UINT32 Bar0 = 0; + UINT32 Bar1 = 0; + UINTN Seg, Bus, Dev, Func; + + SdHostData = NULL; + Data = 0; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: Start\n")); + + // + // Open PCI I/O Protocol and save pointer to open protocol + // in private data area. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Enable the 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)); + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_VENDOR_ID_OFFSET, + 1, + &VidDid + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: VidDid = 0x%08x\n", VidDid)); + + Status = PciIo->GetLocation ( + PciIo, + &Seg, + &Bus, + &Dev, + &Func + ); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: Seg %d, bus:%d,Dev:%d,Func:%d\n", Seg, Bus, Dev,Func)); + + SdHostData->PciVid = (UINT16)(VidDid & 0xffff); + SdHostData->PciDid = (UINT16)(VidDid >> 16); + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0x10, + 1, + &Bar0 + ); + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0x14, + 1, + &Bar1 + ); + + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MEMIO Base0 %x\n", Bar0)); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MEMIO Base1 %x\n", Bar1)); + + SdHostData->SdHostIo.ResetSdHost (&SdHostData->SdHostIo, Reset_All); + SdHostData->EnableVerboseDebug = FALSE; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint16, + 0, + (UINT64)MMIO_CTRLRVER, + 1, + &Data16 + ); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MMIO_CTRLRVER = 0x%08x\n", Data16)); + + SdHostData->ControllerVersion = Data16 & 0xFF; + switch (SdHostData->ControllerVersion) { + case 0: DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: SD Host Controller Version 1.0\n")); break; + case 1: DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: SD Host Controller Version 2.0\n")); break; + case 2: DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: SD Host Controller Version 3.0\n")); break; + default: + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: Unknown SD Host Controller Version, Stopping Driver!!\n")); + goto Exit; + } + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT32)MMIO_CAP, + 1, + &Data + ); + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: Low MMIO_CAP = 0x%08x\n", Data)); + + if ((Data & BIT18) != 0) { + SdHostData->SdHostIo.HostCapability.BusWidth8 = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: BusWidth8\n")); + } + + SdHostData->SdHostIo.HostCapability.BusWidth4 = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: BusWidth4\n")); + + if ((Data & BIT19) != 0) { + SdHostData->SdHostIo.HostCapability.ADMA2Support = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: ADMA2Support\n")); + } + + if ((Data & BIT21) != 0) { + SdHostData->SdHostIo.HostCapability.HighSpeedSupport = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: HighSpeedSupport\n")); + } + + if ((Data & BIT22) != 0) { + SdHostData->SdHostIo.HostCapability.SDMASupport = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: SDMASupport\n")); + } + + if ((Data & BIT24) != 0) { + SdHostData->SdHostIo.HostCapability.V33Support = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: V33Support\n")); + } + + if ((Data & BIT25) != 0) { + SdHostData->SdHostIo.HostCapability.V30Support = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: V30Support\n")); + } + + if ((Data & BIT26) != 0) { + SdHostData->SdHostIo.HostCapability.V18Support = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: V18Support\n")); + } + + if (((Data) & (BIT30 | BIT31)) == 0) { + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: Removable Card Slot\n")); + } else if ((Data & BIT30) && (Data & (~BIT31))) { + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: Embedded Slot for One Device\n")); + } + SdHostData->BaseClockInMHz = (Data >> 8) & 0xFF; + + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + (UINT32)(MMIO_CAP + 4), + 1, + &Data + ); + + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: High MMIO_CAP = 0x%08x\n", Data)); + + if ((Data & 0x1<<(32-32)) != 0) { + SdHostData->SdHostIo.HostCapability.SDR50Support = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: SDR50Support\n")); + } + + if ((Data & 0x1<<(33-32)) != 0) { + SdHostData->SdHostIo.HostCapability.SDR104Support = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: SDR104Support\n")); + } + + if ((Data & 0x1<<(34-32)) != 0) { + SdHostData->SdHostIo.HostCapability.DDR50Support = TRUE; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: DDR50Support\n")); + } + + if (SdHostData->ControllerVersion >= 2) { + SdHostData->SdHostIo.HostCapability.ReTuneMode = (Data >> (46-32)) & 0x3; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: ReTuneMode = 0x%08x\n", SdHostData->SdHostIo.HostCapability.ReTuneMode)); + + SdHostData->SdHostIo.HostCapability.ReTuneTimer = (Data>>(40-32)) & 0xF; + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: ReTuneTimer = 0x%08x\n", SdHostData->SdHostIo.HostCapability.ReTuneTimer)); + } + + SdHostData->BlockLength = BLOCK_SIZE; + SdHostData->IsAutoStopCmd = TRUE; + + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiSdHostIoProtocolGuid, + EFI_NATIVE_INTERFACE, + &SdHostData->SdHostIo + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Component name protocol + // + Status = AddUnicodeString ( + "eng", + gSdHostComponentName.SupportedLanguages, + &SdHostData->ControllerNameTable, + L"SD Host Controller" + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + gBS->UninstallProtocolInterface ( + Controller, + &gEfiSdHostIoProtocolGuid, + &SdHostData->SdHostIo + ); + } + + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: Host Started\n")); + +Exit: + if (EFI_ERROR (Status)) { + if (SdHostData != NULL) { + FreePool (SdHostData); + } + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + return Status; +} + +/** + Stop SD Host driver on ControllerHandle. Support stopping any child handles + created by this driver. + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to stop driver on + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer + @param[in] ChildHandleBuffer List of handles for the children we need to stop + + @retval EFI_SUCCESS This driver stop this device + @retval EFI_DEVICE_ERROR This driver cannot be stop due to device Error +**/ +EFI_STATUS +EFIAPI +SdHostDriverBindingStop ( + 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 + ); + if (EFI_ERROR (Status)) { + goto _exit_SdHostDriverBindingStop; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + SdHostData = SDHOST_DATA_FROM_THIS(SdHostIo); + + // + // Uninstall Block I/O protocol from the device handle + // + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSdHostIoProtocolGuid, + &SdHostData->SdHostIo + ); + if (EFI_ERROR (Status)) { + goto _exit_SdHostDriverBindingStop; + } + FreeUnicodeStringTable (SdHostData->ControllerNameTable); + + FreePool (SdHostData); +_exit_SdHostDriverBindingStop: + DEBUG ((EFI_D_INFO, "SdHostDriverBindingStop exited with Status %r\n", Status)); + return Status; +} diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostDriver.h b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostDriver.h new file mode 100644 index 0000000000..369722db2a --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/SDControllerDxe/SdHostDriver.h @@ -0,0 +1,531 @@ +/** @file + Header file for SD Host driver. + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SD_HOST_DRIVER_H +#define _SD_HOST_DRIVER_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +// +// Driver Consumed Protocol Prototypes +// +#include +#include +// +// Driver Produced Protocol Prototypes +// +#include +#include +#include +#include + +extern EFI_COMPONENT_NAME_PROTOCOL gSdHostComponentName; +extern EFI_DRIVER_BINDING_PROTOCOL gSdHostDriverBinding; + +#define SDHOST_DATA_SIGNATURE SIGNATURE_32 ('s', 'd', 'h', 's') + +#define SDHOST_DATA_FROM_THIS(a) \ + CR(a, SDHOST_DATA, SdHostIo, SDHOST_DATA_SIGNATURE) + +#define BLOCK_SIZE 0x200 +#define TIME_OUT_1S 1000 + +#define BUFFER_CTL_REGISTER 0x84 + +#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; + UINT16 PciVid; + UINT16 PciDid; + BOOLEAN IsAutoStopCmd; + BOOLEAN IsEmmc; + BOOLEAN EnableVerboseDebug; + UINT32 BaseClockInMHz; + UINT32 CurrentClockInKHz; + UINT32 BlockLength; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + UINT32 ControllerVersion; +} SDHOST_DATA; + +/** + Entry point for SD Host EFI drivers. + + @param[in] ImageHandle EFI_HANDLE + @param[in] SystemTable EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function failed to complete +**/ +EFI_STATUS +EFIAPI +SdHostDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Test to see if this SD Host driver supports ControllerHandle. + Any ControllerHandle that has installed will be supported. + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to test + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver supports this device + @retval EFI_UNSUPPORTED This driver does not support this device +**/ +EFI_STATUS +EFIAPI +SdHostDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Starting the SD Host Driver + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to start + @param[in] RemainingDevicePath Not used + + @retval EFI_SUCCESS This driver start this device + @retval EFI_UNSUPPORTED This driver does not support this device + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error + @retval EFI_OUT_OF_RESOURCES This driver cannot allocate resources +**/ +EFI_STATUS +EFIAPI +SdHostDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop SD Host driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param[in] This Protocol instance pointer + @param[in] Controller Handle of device to stop driver on + @param[in] NumberOfChildren Number of Children in the ChildHandleBuffer + @param[in] ChildHandleBuffer List of handles for the children we need to stop + + @retval EFI_SUCCESS This driver stop this device + @retval EFI_DEVICE_ERROR This driver cannot be stop due to device Error + @retval EFI_OUT_OF_RESOURCES This driver cannot allocate resources +**/ +EFI_STATUS +EFIAPI +SdHostDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param[in] 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 function completed successfully + @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 +SdHostComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + + @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 DriverName is NULL + @retval EFI_INVALID_PARAMETER DriverName 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 +SdHostComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/** + The main function used to send the command to the card inserted into the SD/MMC host + slot. It will assemble the arguments to set the command register and wait for the command + and transfer completed until timeout. Then it will read the response register to fill + the ResponseData. + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] CommandIndex The command index to set the command index field of command register + @param[in] Argument Command argument to set the argument field of command register + @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out + @param[in] Buffer Contains the data read from / write to the device + @param[in] BufferSize The size of the buffer + @param[in] ResponseType RESPONSE_TYPE + @param[in] TimeOut Time out value in 1 ms unit + @param[in] ResponseData Depending on the ResponseType, such as CSD or card status + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. + @retval EFI_OUT_OF_RESOURCES A resource has run out. + @retval EFI_TIMEOUT The timeout time expired. + @retval EFI_DEVICE_ERROR The physical device reported an error while attempting the operation +**/ +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 Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] MaxFrequency Max frequency in HZ + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. +**/ +EFI_STATUS +EFIAPI +SetClockFrequency ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 MaxFrequencyInKHz + ); + +/** + Set bus width of the host + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] BusWidth Bus width in 1, 4, 8 bits + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetBusWidth ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BusWidth + ); + +/** + Set voltage which could supported by the host. + Support 0(Power off the host), 1.8V, 3.0V, 3.3V + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] Voltage Units in 0.1 V + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetHostVoltage ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 Voltage + ); + +/** + Set Host DDR Mode + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] DdrMode True for DDR Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetHostDdrMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 DdrMode +); + +/** + Set Host SDR Mode + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] DdrMode True for SDR Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetHostSdrMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 SdrMode +); + +/** + Set Host High Speed + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] HighSpeed True for High Speed Mode set, false for normal mode + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER A parameter was incorrect. +**/ +EFI_STATUS +EFIAPI +SetHostSpeedMode ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 HighSpeed + ); + +/** + Reset the host + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] ResetAll TRUE to reset all + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. +**/ +EFI_STATUS +EFIAPI +ResetSdHost ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN RESET_TYPE ResetType + ); + +/** + Enable Auto Stop Command + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] Enable TRUE to enable Auto Stop Command + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. +**/ +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 Pointer to EFI_SD_HOST_IO_PROTOCOL + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_NOT_FOUND The item was not found. +**/ +EFI_STATUS +EFIAPI +DetectCardAndInitHost ( + IN EFI_SD_HOST_IO_PROTOCOL *This + ); + +/** + Set the Block length + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + @param[in] BlockLength Card supported block length + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT The timeout time expired. +**/ +EFI_STATUS +EFIAPI +SetBlockLength ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BlockLength + ); + +/** + Setup Device for card initialization + + @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EFIAPI +SetupDevice ( + IN EFI_SD_HOST_IO_PROTOCOL *This + ); + +/** + Read SD Host PCI Config Space Register in 8 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI configi space register offset + + @retval Data Register value read in 8 bits +**/ +UINT8 +SdHostRead8 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset + ); + +/** + Read SD Host PCI Config Space Register in 16 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI configi space register offset + + @retval Data Register value read in 16 bits +**/ +UINT16 +SdHostRead16 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset + ); + +/** + Read SD Host PCI Config Space Register in 32 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI configi space register offset + + @retval Data Register value read in 32 bits +**/ +UINT32 +SdHostRead32 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset + ); + +/** + Write SD Host PCI Config Space Register in 8 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI configi space register offset + @param[in] Data Register value write in 8 bits + + +**/ +UINT8 +SdHostWrite8 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset, + IN UINT8 Data + ); + +/** + Write SD Host PCI Config Space Register in 16 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI configi space register offset + @param[in] Data Register value write in 16 bits + + +**/ +UINT16 +SdHostWrite16 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset, + IN UINT16 Data + ); + +/** + Write SD Host PCI Config Space Register in 32 bits + + @param[in] SdHost A pointer to SDHOST_DATA structure + @param[in] Offset PCI configi space register offset + @param[in] Data Register value write in 32 bits + + +**/ +UINT32 +SdHostWrite32 ( + IN SDHOST_DATA *SdHost, + IN UINTN Offset, + IN UINT32 Data + ); + +#endif -- cgit v1.2.3