/** @file\r
This driver is used to manage SD/MMC PCI host controllers which are compliance\r
- with SD Host Controller Simplified Specification version 3.00.\r
+ with SD Host Controller Simplified Specification version 3.00 plus the 64-bit\r
+ System Addressing support in SD Host Controller Simplified Specification version\r
+ 4.20.\r
\r
It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.\r
\r
- Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\r
+ Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
//\r
// Dump Capability Data\r
//\r
- DEBUG ((EFI_D_INFO, " == Slot [%d] Capability is 0x%x ==\n", Slot, Capability));\r
- DEBUG ((EFI_D_INFO, " Timeout Clk Freq %d%a\n", Capability->TimeoutFreq, (Capability->TimeoutUnit) ? "MHz" : "KHz"));\r
- DEBUG ((EFI_D_INFO, " Base Clk Freq %dMHz\n", Capability->BaseClkFreq));\r
- DEBUG ((EFI_D_INFO, " Max Blk Len %dbytes\n", 512 * (1 << Capability->MaxBlkLen)));\r
- DEBUG ((EFI_D_INFO, " 8-bit Support %a\n", Capability->BusWidth8 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " ADMA2 Support %a\n", Capability->Adma2 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " HighSpeed Support %a\n", Capability->HighSpeed ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " SDMA Support %a\n", Capability->Sdma ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Suspend/Resume %a\n", Capability->SuspRes ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Voltage 3.3 %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Voltage 3.0 %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Voltage 1.8 %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " 64-bit Sys Bus %a\n", Capability->SysBus64 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Async Interrupt %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " SlotType "));\r
+ DEBUG ((DEBUG_INFO, " == Slot [%d] Capability is 0x%x ==\n", Slot, Capability));\r
+ DEBUG ((DEBUG_INFO, " Timeout Clk Freq %d%a\n", Capability->TimeoutFreq, (Capability->TimeoutUnit) ? "MHz" : "KHz"));\r
+ DEBUG ((DEBUG_INFO, " Base Clk Freq %dMHz\n", Capability->BaseClkFreq));\r
+ DEBUG ((DEBUG_INFO, " Max Blk Len %dbytes\n", 512 * (1 << Capability->MaxBlkLen)));\r
+ DEBUG ((DEBUG_INFO, " 8-bit Support %a\n", Capability->BusWidth8 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " ADMA2 Support %a\n", Capability->Adma2 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " HighSpeed Support %a\n", Capability->HighSpeed ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " SDMA Support %a\n", Capability->Sdma ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Suspend/Resume %a\n", Capability->SuspRes ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Voltage 3.3 %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Voltage 3.0 %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Voltage 1.8 %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Async Interrupt %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " SlotType "));\r
if (Capability->SlotType == 0x00) {\r
- DEBUG ((EFI_D_INFO, "%a\n", "Removable Slot"));\r
+ DEBUG ((DEBUG_INFO, "%a\n", "Removable Slot"));\r
} else if (Capability->SlotType == 0x01) {\r
- DEBUG ((EFI_D_INFO, "%a\n", "Embedded Slot"));\r
+ DEBUG ((DEBUG_INFO, "%a\n", "Embedded Slot"));\r
} else if (Capability->SlotType == 0x02) {\r
- DEBUG ((EFI_D_INFO, "%a\n", "Shared Bus Slot"));\r
+ DEBUG ((DEBUG_INFO, "%a\n", "Shared Bus Slot"));\r
} else {\r
- DEBUG ((EFI_D_INFO, "%a\n", "Reserved"));\r
- }\r
- DEBUG ((EFI_D_INFO, " SDR50 Support %a\n", Capability->Sdr50 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " SDR104 Support %a\n", Capability->Sdr104 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " DDR50 Support %a\n", Capability->Ddr50 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Driver Type A %a\n", Capability->DriverTypeA ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Driver Type C %a\n", Capability->DriverTypeC ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Driver Type D %a\n", Capability->DriverTypeD ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Driver Type 4 %a\n", Capability->DriverType4 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, "%a\n", "Reserved"));\r
+ }\r
+ DEBUG ((DEBUG_INFO, " SDR50 Support %a\n", Capability->Sdr50 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " SDR104 Support %a\n", Capability->Sdr104 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " DDR50 Support %a\n", Capability->Ddr50 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Driver Type A %a\n", Capability->DriverTypeA ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Driver Type C %a\n", Capability->DriverTypeC ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Driver Type D %a\n", Capability->DriverTypeD ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Driver Type 4 %a\n", Capability->DriverType4 ? "TRUE" : "FALSE"));\r
if (Capability->TimerCount == 0) {\r
- DEBUG ((EFI_D_INFO, " Retuning TimerCnt Disabled\n", 2 * (Capability->TimerCount - 1)));\r
+ DEBUG ((DEBUG_INFO, " Retuning TimerCnt Disabled\n", 2 * (Capability->TimerCount - 1)));\r
} else {\r
- DEBUG ((EFI_D_INFO, " Retuning TimerCnt %dseconds\n", 2 * (Capability->TimerCount - 1)));\r
+ DEBUG ((DEBUG_INFO, " Retuning TimerCnt %dseconds\n", 2 * (Capability->TimerCount - 1)));\r
}\r
- DEBUG ((EFI_D_INFO, " SDR50 Tuning %a\n", Capability->TuningSDR50 ? "TRUE" : "FALSE"));\r
- DEBUG ((EFI_D_INFO, " Retuning Mode Mode %d\n", Capability->RetuningMod + 1));\r
- DEBUG ((EFI_D_INFO, " Clock Multiplier M = %d\n", Capability->ClkMultiplier + 1));\r
- DEBUG ((EFI_D_INFO, " HS 400 %a\n", Capability->Hs400 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " SDR50 Tuning %a\n", Capability->TuningSDR50 ? "TRUE" : "FALSE"));\r
+ DEBUG ((DEBUG_INFO, " Retuning Mode Mode %d\n", Capability->RetuningMod + 1));\r
+ DEBUG ((DEBUG_INFO, " Clock Multiplier M = %d\n", Capability->ClkMultiplier + 1));\r
+ DEBUG ((DEBUG_INFO, " HS 400 %a\n", Capability->Hs400 ? "TRUE" : "FALSE"));\r
return;\r
}\r
\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
\r
if ((PciIo == NULL) || (Data == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if ((Count != 1) && (Count != 2) && (Count != 4) && (Count != 8)) {\r
- return EFI_INVALID_PARAMETER;\r
+ switch (Count) {\r
+ case 1:\r
+ Width = EfiPciIoWidthUint8;\r
+ break;\r
+ case 2:\r
+ Width = EfiPciIoWidthUint16;\r
+ Count = 1;\r
+ break;\r
+ case 4:\r
+ Width = EfiPciIoWidthUint32;\r
+ Count = 1;\r
+ break;\r
+ case 8:\r
+ Width = EfiPciIoWidthUint32;\r
+ Count = 2;\r
+ break;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
if (Read) {\r
Status = PciIo->Mem.Read (\r
PciIo,\r
- EfiPciIoWidthUint8,\r
+ Width,\r
BarIndex,\r
(UINT64) Offset,\r
Count,\r
} else {\r
Status = PciIo->Mem.Write (\r
PciIo,\r
- EfiPciIoWidthUint8,\r
+ Width,\r
BarIndex,\r
(UINT64) Offset,\r
Count,\r
return EFI_TIMEOUT;\r
}\r
\r
+/**\r
+ Get the controller version information from the specified slot.\r
+\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] Slot The slot number of the SD card to send the command to.\r
+ @param[out] Version The buffer to store the version information.\r
+\r
+ @retval EFI_SUCCESS The operation executes successfully.\r
+ @retval Others The operation fails.\r
+\r
+**/\r
+EFI_STATUS\r
+SdMmcHcGetControllerVersion (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT8 Slot,\r
+ OUT UINT16 *Version\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ *Version &= 0xFF;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Software reset the specified SD/MMC host controller and enable all interrupts.\r
\r
- @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
@param[in] Slot The slot number of the SD card to send the command to.\r
\r
@retval EFI_SUCCESS The software reset executes successfully.\r
**/\r
EFI_STATUS\r
SdMmcHcReset (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
IN UINT8 Slot\r
)\r
{\r
EFI_STATUS Status;\r
UINT8 SwReset;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
\r
- SwReset = 0xFF;\r
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);\r
+ //\r
+ // Notify the SD/MMC override protocol that we are about to reset\r
+ // the SD/MMC host controller.\r
+ //\r
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+ Status = mOverride->NotifyPhase (\r
+ Private->ControllerHandle,\r
+ Slot,\r
+ EdkiiSdMmcResetPre,\r
+ NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_WARN,\r
+ "%a: SD/MMC pre reset notifier callback failed - %r\n",\r
+ __FUNCTION__, Status));\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ PciIo = Private->PciIo;\r
+ SwReset = BIT0;\r
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), &SwReset);\r
\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "SdMmcHcReset: write full 1 fails: %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write SW Reset for All fails: %r\n", Status));\r
return Status;\r
}\r
\r
Slot,\r
SD_MMC_HC_SW_RST,\r
sizeof (SwReset),\r
- 0xFF,\r
+ BIT0,\r
0x00,\r
SD_MMC_HC_GENERIC_TIMEOUT\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_INFO, "SdMmcHcReset: reset done with %r\n", Status));\r
+ DEBUG ((DEBUG_INFO, "SdMmcHcReset: reset done with %r\n", Status));\r
return Status;\r
}\r
+\r
//\r
// Enable all interrupt after reset all.\r
//\r
Status = SdMmcHcEnableInterrupt (PciIo, Slot);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_INFO, "SdMmcHcReset: SdMmcHcEnableInterrupt done with %r\n",\r
+ Status));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Notify the SD/MMC override protocol that we have just reset\r
+ // the SD/MMC host controller.\r
+ //\r
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+ Status = mOverride->NotifyPhase (\r
+ Private->ControllerHandle,\r
+ Slot,\r
+ EdkiiSdMmcResetPost,\r
+ NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_WARN,\r
+ "%a: SD/MMC post reset notifier callback failed - %r\n",\r
+ __FUNCTION__, Status));\r
+ }\r
+ }\r
\r
return Status;\r
}\r
UINT16 Data;\r
UINT32 PresentState;\r
\r
+ //\r
+ // Check Present State Register to see if there is a card presented.\r
+ //\r
+ Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((PresentState & BIT16) != 0) {\r
+ *MediaPresent = TRUE;\r
+ } else {\r
+ *MediaPresent = FALSE;\r
+ }\r
+\r
//\r
// Check Normal Interrupt Status Register\r
//\r
return Status;\r
}\r
\r
- //\r
- // Check Present State Register to see if there is a card presented.\r
- //\r
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- if ((PresentState & BIT16) != 0) {\r
- *MediaPresent = TRUE;\r
- } else {\r
- *MediaPresent = FALSE;\r
- }\r
return EFI_MEDIA_CHANGED;\r
}\r
\r
@param[in] PciIo The PCI IO protocol instance.\r
@param[in] Slot The slot number of the SD card to send the command to.\r
@param[in] ClockFreq The max clock frequency to be set. The unit is KHz.\r
- @param[in] Capability The capability of the slot.\r
+ @param[in] BaseClkFreq The base clock frequency of host controller in MHz.\r
+ @param[in] ControllerVer The version of host controller.\r
\r
@retval EFI_SUCCESS The clock is supplied successfully.\r
@retval Others The clock isn't supplied successfully.\r
IN EFI_PCI_IO_PROTOCOL *PciIo,\r
IN UINT8 Slot,\r
IN UINT64 ClockFreq,\r
- IN SD_MMC_HC_SLOT_CAP Capability\r
+ IN UINT32 BaseClkFreq,\r
+ IN UINT16 ControllerVer\r
)\r
{\r
EFI_STATUS Status;\r
- UINT32 BaseClkFreq;\r
UINT32 SettingFreq;\r
UINT32 Divisor;\r
UINT32 Remainder;\r
- UINT16 ControllerVer;\r
UINT16 ClockCtrl;\r
\r
//\r
// Calculate a divisor for SD clock frequency\r
//\r
- ASSERT (Capability.BaseClkFreq != 0);\r
+ ASSERT (BaseClkFreq != 0);\r
\r
- BaseClkFreq = Capability.BaseClkFreq;\r
- if ((ClockFreq > (BaseClkFreq * 1000)) || (ClockFreq == 0)) {\r
+ if (ClockFreq == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
+ if (ClockFreq > (BaseClkFreq * 1000)) {\r
+ ClockFreq = BaseClkFreq * 1000;\r
+ }\r
+\r
//\r
// Calculate the divisor of base frequency.\r
//\r
}\r
}\r
\r
- DEBUG ((EFI_D_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));\r
+ DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));\r
\r
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
//\r
// Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.\r
//\r
- if ((ControllerVer & 0xFF) == 2) {\r
+ if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&\r
+ (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {\r
ASSERT (Divisor <= 0x3FF);\r
ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);\r
- } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {\r
+ } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||\r
+ (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {\r
//\r
// Only the most significant bit can be used as divisor.\r
//\r
ASSERT (Divisor <= 0x80);\r
ClockCtrl = (Divisor & 0xFF) << 8;\r
} else {\r
- DEBUG ((EFI_D_ERROR, "Unknown SD Host Controller Spec version [0x%x]!!!\n", ControllerVer));\r
+ DEBUG ((DEBUG_ERROR, "Unknown SD Host Controller Spec version [0x%x]!!!\n", ControllerVer));\r
return EFI_UNSUPPORTED;\r
}\r
\r
ClockCtrl |= BIT0;\r
Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, FALSE, sizeof (ClockCtrl), &ClockCtrl);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Set SDCLK Frequency Select and Internal Clock Enable fields fails\n"));\r
+ DEBUG ((DEBUG_ERROR, "Set SDCLK Frequency Select and Internal Clock Enable fields fails\n"));\r
return Status;\r
}\r
\r
}\r
\r
/**\r
- Supply SD/MMC card with lowest clock frequency at initialization.\r
+ Configure V4 controller enhancements at initialization.\r
\r
@param[in] PciIo The PCI IO protocol instance.\r
@param[in] Slot The slot number of the SD card to send the command to.\r
@param[in] Capability The capability of the slot.\r
+ @param[in] ControllerVer The version of host controller.\r
+\r
+ @retval EFI_SUCCESS The clock is supplied successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SdMmcHcInitV4Enhancements (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT8 Slot,\r
+ IN SD_MMC_HC_SLOT_CAP Capability,\r
+ IN UINT16 ControllerVer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 HostCtrl2;\r
+\r
+ //\r
+ // Check if controller version V4 or higher\r
+ //\r
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {\r
+ HostCtrl2 = SD_MMC_HC_V4_EN;\r
+ //\r
+ // Check if controller version V4.0\r
+ //\r
+ if (ControllerVer == SD_MMC_HC_CTRL_VER_400) {\r
+ //\r
+ // Check if 64bit support is available\r
+ //\r
+ if (Capability.SysBus64V3 != 0) {\r
+ HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;\r
+ DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));\r
+ }\r
+ }\r
+ //\r
+ // Check if controller version V4.10 or higher\r
+ //\r
+ else if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {\r
+ //\r
+ // Check if 64bit support is available\r
+ //\r
+ if (Capability.SysBus64V4 != 0) {\r
+ HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;\r
+ DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));\r
+ }\r
+ HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;\r
+ DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));\r
+ }\r
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Supply SD/MMC card with lowest clock frequency at initialization.\r
+\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] Slot The slot number of the SD card to send the command to.\r
+ @param[in] BaseClkFreq The base clock frequency of host controller in MHz.\r
+ @param[in] ControllerVer The version of host controller.\r
\r
@retval EFI_SUCCESS The clock is supplied successfully.\r
@retval Others The clock isn't supplied successfully.\r
SdMmcHcInitClockFreq (\r
IN EFI_PCI_IO_PROTOCOL *PciIo,\r
IN UINT8 Slot,\r
- IN SD_MMC_HC_SLOT_CAP Capability\r
+ IN UINT32 BaseClkFreq,\r
+ IN UINT16 ControllerVer\r
)\r
{\r
EFI_STATUS Status;\r
UINT32 InitFreq;\r
\r
//\r
- // Calculate a divisor for SD clock frequency\r
+ // According to SDHCI specification ver. 4.2, BaseClkFreq field value of\r
+ // the Capability Register 1 can be zero, which means a need for obtaining\r
+ // the clock frequency via another method. Fail in case it is not updated\r
+ // by SW at this point.\r
//\r
- if (Capability.BaseClkFreq == 0) {\r
+ if (BaseClkFreq == 0) {\r
//\r
// Don't support get Base Clock Frequency information via another method\r
//\r
// Supply 400KHz clock frequency at initialization phase.\r
//\r
InitFreq = 400;\r
- Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, Capability);\r
+ Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);\r
return Status;\r
}\r
\r
Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value\r
at initialization.\r
\r
- @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
@param[in] Slot The slot number of the SD card to send the command to.\r
- @param[in] Capability The capability of the slot.\r
\r
@retval EFI_SUCCESS The host controller is initialized successfully.\r
@retval Others The host controller isn't initialized successfully.\r
**/\r
EFI_STATUS\r
SdMmcHcInitHost (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT8 Slot,\r
- IN SD_MMC_HC_SLOT_CAP Capability\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 Slot\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ SD_MMC_HC_SLOT_CAP Capability;\r
\r
- Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);\r
+ //\r
+ // Notify the SD/MMC override protocol that we are about to initialize\r
+ // the SD/MMC host controller.\r
+ //\r
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+ Status = mOverride->NotifyPhase (\r
+ Private->ControllerHandle,\r
+ Slot,\r
+ EdkiiSdMmcInitHostPre,\r
+ NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_WARN,\r
+ "%a: SD/MMC pre init notifier callback failed - %r\n",\r
+ __FUNCTION__, Status));\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ PciIo = Private->PciIo;\r
+ Capability = Private->Capability[Slot];\r
+\r
+ Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
}\r
\r
Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Notify the SD/MMC override protocol that we are have just initialized\r
+ // the SD/MMC host controller.\r
+ //\r
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+ Status = mOverride->NotifyPhase (\r
+ Private->ControllerHandle,\r
+ Slot,\r
+ EdkiiSdMmcInitHostPost,\r
+ NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_WARN,\r
+ "%a: SD/MMC post init notifier callback failed - %r\n",\r
+ __FUNCTION__, Status));\r
+ }\r
+ }\r
return Status;\r
}\r
\r
+/**\r
+ Set SD Host Controler control 2 registry according to selected speed.\r
+\r
+ @param[in] ControllerHandle The handle of the controller.\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] Slot The slot number of the SD card to send the command to.\r
+ @param[in] Timing The timing to select.\r
+\r
+ @retval EFI_SUCCESS The timing is set successfully.\r
+ @retval Others The timing isn't set successfully.\r
+**/\r
+EFI_STATUS\r
+SdMmcHcUhsSignaling (\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT8 Slot,\r
+ IN SD_MMC_BUS_MODE Timing\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 HostCtrl2;\r
+\r
+ HostCtrl2 = (UINT8)~SD_MMC_HC_CTRL_UHS_MASK;\r
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ switch (Timing) {\r
+ case SdMmcUhsSdr12:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR12;\r
+ break;\r
+ case SdMmcUhsSdr25:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR25;\r
+ break;\r
+ case SdMmcUhsSdr50:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR50;\r
+ break;\r
+ case SdMmcUhsSdr104:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR104;\r
+ break;\r
+ case SdMmcUhsDdr50:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_DDR50;\r
+ break;\r
+ case SdMmcMmcLegacy:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_LEGACY;\r
+ break;\r
+ case SdMmcMmcHsSdr:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_SDR;\r
+ break;\r
+ case SdMmcMmcHsDdr:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_DDR;\r
+ break;\r
+ case SdMmcMmcHs200:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS200;\r
+ break;\r
+ case SdMmcMmcHs400:\r
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS400;\r
+ break;\r
+ default:\r
+ HostCtrl2 = 0;\r
+ break;\r
+ }\r
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+ Status = mOverride->NotifyPhase (\r
+ ControllerHandle,\r
+ Slot,\r
+ EdkiiSdMmcUhsSignaling,\r
+ &Timing\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "%a: SD/MMC uhs signaling notifier callback failed - %r\n",\r
+ __FUNCTION__,\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set driver strength in host controller.\r
+\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] SlotIndex The slot index of the card.\r
+ @param[in] DriverStrength DriverStrength to set in the controller.\r
+\r
+ @retval EFI_SUCCESS Driver strength programmed successfully.\r
+ @retval Others Failed to set driver strength.\r
+**/\r
+EFI_STATUS\r
+SdMmcSetDriverStrength (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT8 SlotIndex,\r
+ IN SD_DRIVER_STRENGTH_TYPE DriverStrength\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 HostCtrl2;\r
+\r
+ if (DriverStrength == SdDriverStrengthIgnore) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ HostCtrl2 = (UINT16)~SD_MMC_HC_CTRL_DRIVER_STRENGTH_MASK;\r
+ Status = SdMmcHcAndMmio (PciIo, SlotIndex, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ HostCtrl2 = (DriverStrength << 4) & SD_MMC_HC_CTRL_DRIVER_STRENGTH_MASK;\r
+ return SdMmcHcOrMmio (PciIo, SlotIndex, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+}\r
+\r
/**\r
Turn on/off LED.\r
\r
/**\r
Build ADMA descriptor table for transfer.\r
\r
- Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.\r
+ Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.\r
\r
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
+ @param[in] ControllerVer The version of host controller.\r
\r
@retval EFI_SUCCESS The ADMA descriptor table is created successfully.\r
@retval Others The ADMA descriptor table isn't created successfully.\r
**/\r
EFI_STATUS\r
BuildAdmaDescTable (\r
- IN SD_MMC_HC_TRB *Trb\r
+ IN SD_MMC_HC_TRB *Trb,\r
+ IN UINT16 ControllerVer\r
)\r
{\r
EFI_PHYSICAL_ADDRESS Data;\r
UINT64 Entries;\r
UINT32 Index;\r
UINT64 Remaining;\r
- UINT32 Address;\r
+ UINT64 Address;\r
UINTN TableSize;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
EFI_STATUS Status;\r
UINTN Bytes;\r
+ UINT32 AdmaMaxDataPerLine;\r
+ UINT32 DescSize;\r
+ VOID *AdmaDesc;\r
+\r
+ AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;\r
+ DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);\r
+ AdmaDesc = NULL;\r
\r
Data = Trb->DataPhy;\r
DataLen = Trb->DataLen;\r
PciIo = Trb->Private->PciIo;\r
+\r
//\r
- // Only support 32bit ADMA Descriptor Table\r
+ // Check for valid ranges in 32bit ADMA Descriptor Table\r
//\r
- if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {\r
+ if ((Trb->Mode == SdMmcAdma32bMode) &&\r
+ ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {\r
return EFI_INVALID_PARAMETER;\r
}\r
//\r
- // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)\r
- // for 32-bit address descriptor table.\r
+ // Check address field alignment\r
//\r
- if ((Data & (BIT0 | BIT1)) != 0) {\r
- DEBUG ((EFI_D_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));\r
+ if (Trb->Mode != SdMmcAdma32bMode) {\r
+ //\r
+ // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)\r
+ //\r
+ if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {\r
+ DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data));\r
+ }\r
+ } else {\r
+ //\r
+ // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)\r
+ //\r
+ if ((Data & (BIT0 | BIT1)) != 0) {\r
+ DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));\r
+ }\r
}\r
\r
- Entries = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);\r
- TableSize = (UINTN)MultU64x32 (Entries, sizeof (SD_MMC_HC_ADMA_DESC_LINE));\r
+ //\r
+ // Configure 64b ADMA.\r
+ //\r
+ if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+ DescSize = sizeof (SD_MMC_HC_ADMA_64_V3_DESC_LINE);\r
+ }else if (Trb->Mode == SdMmcAdma64bV4Mode) {\r
+ DescSize = sizeof (SD_MMC_HC_ADMA_64_V4_DESC_LINE);\r
+ }\r
+ //\r
+ // Configure 26b data length.\r
+ //\r
+ if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+ AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;\r
+ }\r
+\r
+ Entries = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);\r
+ TableSize = (UINTN)MultU64x32 (Entries, DescSize);\r
Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);\r
Status = PciIo->AllocateBuffer (\r
PciIo,\r
AllocateAnyPages,\r
EfiBootServicesData,\r
EFI_SIZE_TO_PAGES (TableSize),\r
- (VOID **)&Trb->AdmaDesc,\r
+ (VOID **)&AdmaDesc,\r
0\r
);\r
if (EFI_ERROR (Status)) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- ZeroMem (Trb->AdmaDesc, TableSize);\r
+ ZeroMem (AdmaDesc, TableSize);\r
Bytes = TableSize;\r
Status = PciIo->Map (\r
PciIo,\r
EfiPciIoOperationBusMasterCommonBuffer,\r
- Trb->AdmaDesc,\r
+ AdmaDesc,\r
&Bytes,\r
&Trb->AdmaDescPhy,\r
&Trb->AdmaMap\r
PciIo->FreeBuffer (\r
PciIo,\r
EFI_SIZE_TO_PAGES (TableSize),\r
- Trb->AdmaDesc\r
+ AdmaDesc\r
);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {\r
+ if ((Trb->Mode == SdMmcAdma32bMode) &&\r
+ (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {\r
//\r
// The ADMA doesn't support 64bit addressing.\r
//\r
PciIo->FreeBuffer (\r
PciIo,\r
EFI_SIZE_TO_PAGES (TableSize),\r
- Trb->AdmaDesc\r
+ AdmaDesc\r
);\r
return EFI_DEVICE_ERROR;\r
}\r
\r
Remaining = DataLen;\r
- Address = (UINT32)Data;\r
+ Address = Data;\r
+ if (Trb->Mode == SdMmcAdma32bMode) {\r
+ Trb->Adma32Desc = AdmaDesc;\r
+ } else if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+ Trb->Adma64V3Desc = AdmaDesc;\r
+ } else {\r
+ Trb->Adma64V4Desc = AdmaDesc;\r
+ }\r
+\r
for (Index = 0; Index < Entries; Index++) {\r
- if (Remaining <= ADMA_MAX_DATA_PER_LINE) {\r
- Trb->AdmaDesc[Index].Valid = 1;\r
- Trb->AdmaDesc[Index].Act = 2;\r
- Trb->AdmaDesc[Index].Length = (UINT16)Remaining;\r
- Trb->AdmaDesc[Index].Address = Address;\r
- break;\r
+ if (Trb->Mode == SdMmcAdma32bMode) {\r
+ if (Remaining <= AdmaMaxDataPerLine) {\r
+ Trb->Adma32Desc[Index].Valid = 1;\r
+ Trb->Adma32Desc[Index].Act = 2;\r
+ if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+ Trb->Adma32Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);\r
+ }\r
+ Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);\r
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;\r
+ break;\r
+ } else {\r
+ Trb->Adma32Desc[Index].Valid = 1;\r
+ Trb->Adma32Desc[Index].Act = 2;\r
+ if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+ Trb->Adma32Desc[Index].UpperLength = 0;\r
+ }\r
+ Trb->Adma32Desc[Index].LowerLength = 0;\r
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;\r
+ }\r
+ } else if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+ if (Remaining <= AdmaMaxDataPerLine) {\r
+ Trb->Adma64V3Desc[Index].Valid = 1;\r
+ Trb->Adma64V3Desc[Index].Act = 2;\r
+ if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+ Trb->Adma64V3Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);\r
+ }\r
+ Trb->Adma64V3Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);\r
+ Trb->Adma64V3Desc[Index].LowerAddress = (UINT32)Address;\r
+ Trb->Adma64V3Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
+ break;\r
+ } else {\r
+ Trb->Adma64V3Desc[Index].Valid = 1;\r
+ Trb->Adma64V3Desc[Index].Act = 2;\r
+ if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+ Trb->Adma64V3Desc[Index].UpperLength = 0;\r
+ }\r
+ Trb->Adma64V3Desc[Index].LowerLength = 0;\r
+ Trb->Adma64V3Desc[Index].LowerAddress = (UINT32)Address;\r
+ Trb->Adma64V3Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
+ }\r
} else {\r
- Trb->AdmaDesc[Index].Valid = 1;\r
- Trb->AdmaDesc[Index].Act = 2;\r
- Trb->AdmaDesc[Index].Length = 0;\r
- Trb->AdmaDesc[Index].Address = Address;\r
+ if (Remaining <= AdmaMaxDataPerLine) {\r
+ Trb->Adma64V4Desc[Index].Valid = 1;\r
+ Trb->Adma64V4Desc[Index].Act = 2;\r
+ if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+ Trb->Adma64V4Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);\r
+ }\r
+ Trb->Adma64V4Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);\r
+ Trb->Adma64V4Desc[Index].LowerAddress = (UINT32)Address;\r
+ Trb->Adma64V4Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
+ break;\r
+ } else {\r
+ Trb->Adma64V4Desc[Index].Valid = 1;\r
+ Trb->Adma64V4Desc[Index].Act = 2;\r
+ if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {\r
+ Trb->Adma64V4Desc[Index].UpperLength = 0;\r
+ }\r
+ Trb->Adma64V4Desc[Index].LowerLength = 0;\r
+ Trb->Adma64V4Desc[Index].LowerAddress = (UINT32)Address;\r
+ Trb->Adma64V4Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);\r
+ }\r
}\r
\r
- Remaining -= ADMA_MAX_DATA_PER_LINE;\r
- Address += ADMA_MAX_DATA_PER_LINE;\r
+ Remaining -= AdmaMaxDataPerLine;\r
+ Address += AdmaMaxDataPerLine;\r
}\r
\r
//\r
// Set the last descriptor line as end of descriptor table\r
//\r
- Trb->AdmaDesc[Index].End = 1;\r
+ if (Trb->Mode == SdMmcAdma32bMode) {\r
+ Trb->Adma32Desc[Index].End = 1;\r
+ } else if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+ Trb->Adma64V3Desc[Index].End = 1;\r
+ } else {\r
+ Trb->Adma64V4Desc[Index].End = 1;\r
+ }\r
return EFI_SUCCESS;\r
}\r
\r
goto Error;\r
}\r
\r
- if (Trb->Read) {\r
- Flag = EfiPciIoOperationBusMasterWrite;\r
- } else {\r
- Flag = EfiPciIoOperationBusMasterRead;\r
+ if ((Trb->DataLen != 0) && (Trb->DataLen < Trb->BlockSize)) {\r
+ Trb->BlockSize = (UINT16)Trb->DataLen;\r
}\r
\r
- PciIo = Private->PciIo;\r
- if (Trb->DataLen != 0) {\r
- MapLength = Trb->DataLen;\r
- Status = PciIo->Map (\r
- PciIo,\r
- Flag,\r
- Trb->Data,\r
- &MapLength,\r
- &Trb->DataPhy,\r
- &Trb->DataMap\r
- );\r
- if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- goto Error;\r
+ if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
+ (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
+ ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
+ (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
+ Trb->Mode = SdMmcPioMode;\r
+ } else {\r
+ if (Trb->Read) {\r
+ Flag = EfiPciIoOperationBusMasterWrite;\r
+ } else {\r
+ Flag = EfiPciIoOperationBusMasterRead;\r
}\r
- }\r
\r
- if ((Trb->DataLen % Trb->BlockSize) != 0) {\r
- if (Trb->DataLen < Trb->BlockSize) {\r
- Trb->BlockSize = (UINT16)Trb->DataLen;\r
+ PciIo = Private->PciIo;\r
+ if (Trb->DataLen != 0) {\r
+ MapLength = Trb->DataLen;\r
+ Status = PciIo->Map (\r
+ PciIo,\r
+ Flag,\r
+ Trb->Data,\r
+ &MapLength,\r
+ &Trb->DataPhy,\r
+ &Trb->DataMap\r
+ );\r
+ if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
+ Status = EFI_BAD_BUFFER_SIZE;\r
+ goto Error;\r
+ }\r
}\r
- }\r
\r
- if (Trb->DataLen == 0) {\r
- Trb->Mode = SdMmcNoData;\r
- } else if (Private->Capability[Slot].Adma2 != 0) {\r
- Trb->Mode = SdMmcAdmaMode;\r
- Status = BuildAdmaDescTable (Trb);\r
- if (EFI_ERROR (Status)) {\r
- PciIo->Unmap (PciIo, Trb->DataMap);\r
- goto Error;\r
+ if (Trb->DataLen == 0) {\r
+ Trb->Mode = SdMmcNoData;\r
+ } else if (Private->Capability[Slot].Adma2 != 0) {\r
+ Trb->Mode = SdMmcAdma32bMode;\r
+ Trb->AdmaLengthMode = SdMmcAdmaLen16b;\r
+ if ((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_300) &&\r
+ (Private->Capability[Slot].SysBus64V3 == 1)) {\r
+ Trb->Mode = SdMmcAdma64bV3Mode;\r
+ } else if (((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_400) &&\r
+ (Private->Capability[Slot].SysBus64V3 == 1)) ||\r
+ ((Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) &&\r
+ (Private->Capability[Slot].SysBus64V4 == 1))) {\r
+ Trb->Mode = SdMmcAdma64bV4Mode;\r
+ }\r
+ if (Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) {\r
+ Trb->AdmaLengthMode = SdMmcAdmaLen26b;\r
+ }\r
+ Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
+ if (EFI_ERROR (Status)) {\r
+ PciIo->Unmap (PciIo, Trb->DataMap);\r
+ goto Error;\r
+ }\r
+ } else if (Private->Capability[Slot].Sdma != 0) {\r
+ Trb->Mode = SdMmcSdmaMode;\r
+ } else {\r
+ Trb->Mode = SdMmcPioMode;\r
}\r
- } else if (Private->Capability[Slot].Sdma != 0) {\r
- Trb->Mode = SdMmcSdmaMode;\r
- } else {\r
- Trb->Mode = SdMmcPioMode;\r
}\r
\r
if (Event != NULL) {\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
InsertTailList (&Private->Queue, &Trb->TrbList);\r
gBS->RestoreTPL (OldTpl);\r
}\r
Trb->AdmaMap\r
);\r
}\r
- if (Trb->AdmaDesc != NULL) {\r
+ if (Trb->Adma32Desc != NULL) {\r
PciIo->FreeBuffer (\r
PciIo,\r
Trb->AdmaPages,\r
- Trb->AdmaDesc\r
+ Trb->Adma32Desc\r
+ );\r
+ }\r
+ if (Trb->Adma64V3Desc != NULL) {\r
+ PciIo->FreeBuffer (\r
+ PciIo,\r
+ Trb->AdmaPages,\r
+ Trb->Adma64V3Desc\r
+ );\r
+ }\r
+ if (Trb->Adma64V4Desc != NULL) {\r
+ PciIo->FreeBuffer (\r
+ PciIo,\r
+ Trb->AdmaPages,\r
+ Trb->Adma64V4Desc\r
);\r
}\r
if (Trb->DataMap != NULL) {\r
// the Present State register to be 0\r
//\r
PresentState = BIT0 | BIT1;\r
- //\r
- // For Send Tuning Block cmd, just wait for Command Inhibit (CMD) to be 0\r
- //\r
- if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
- (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
- ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
- (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
- PresentState = BIT0;\r
- }\r
} else {\r
//\r
// Wait Command Inhibit (CMD) in the Present State register\r
UINT16 Cmd;\r
UINT16 IntStatus;\r
UINT32 Argument;\r
- UINT16 BlkCount;\r
+ UINT32 BlkCount;\r
UINT16 BlkSize;\r
UINT16 TransMode;\r
UINT8 HostCtrl1;\r
- UINT32 SdmaAddr;\r
+ UINT64 SdmaAddr;\r
UINT64 AdmaAddr;\r
+ BOOLEAN AddressingMode64;\r
+\r
+ AddressingMode64 = FALSE;\r
\r
Packet = Trb->Packet;\r
PciIo = Trb->Private->PciIo;\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
+ SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_64_ADDR_EN);\r
+ if (!EFI_ERROR (Status)) {\r
+ AddressingMode64 = TRUE;\r
+ }\r
+ }\r
+\r
//\r
// Set Host Control 1 register DMA Select field\r
//\r
- if (Trb->Mode == SdMmcAdmaMode) {\r
+ if ((Trb->Mode == SdMmcAdma32bMode) ||\r
+ (Trb->Mode == SdMmcAdma64bV4Mode)) {\r
HostCtrl1 = BIT4;\r
Status = SdMmcHcOrMmio (PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+ } else if (Trb->Mode == SdMmcAdma64bV3Mode) {\r
+ HostCtrl1 = BIT4|BIT3;\r
+ Status = SdMmcHcOrMmio (PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
\r
SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);\r
\r
if (Trb->Mode == SdMmcSdmaMode) {\r
- if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {\r
+ if ((!AddressingMode64) &&\r
+ ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;\r
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);\r
+ SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;\r
+\r
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);\r
+ } else {\r
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- } else if (Trb->Mode == SdMmcAdmaMode) {\r
+ } else if ((Trb->Mode == SdMmcAdma32bMode) ||\r
+ (Trb->Mode == SdMmcAdma64bV3Mode) ||\r
+ (Trb->Mode == SdMmcAdma64bV4Mode)) {\r
AdmaAddr = (UINT64)(UINTN)Trb->AdmaDescPhy;\r
Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (AdmaAddr), &AdmaAddr);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);\r
+ BlkCount = 0;\r
+ if (Trb->Mode != SdMmcNoData) {\r
+ //\r
+ // Calcuate Block Count.\r
+ //\r
+ BlkCount = (Trb->DataLen / Trb->BlockSize);\r
+ }\r
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) {\r
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount);\r
+ } else {\r
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount);\r
+ }\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
if (Trb->Read) {\r
TransMode |= BIT4;\r
}\r
- if (BlkCount != 0) {\r
+ if (BlkCount > 1) {\r
TransMode |= BIT5 | BIT1;\r
}\r
//\r
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
UINT16 IntStatus;\r
UINT32 Response[4];\r
- UINT32 SdmaAddr;\r
+ UINT64 SdmaAddr;\r
UINT8 Index;\r
UINT8 SwReset;\r
+ UINT32 PioLength;\r
\r
SwReset = 0;\r
Packet = Trb->Packet;\r
//\r
// Update SDMA Address register.\r
//\r
- SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);\r
- Status = SdMmcHcRwMmio (\r
+ SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);\r
+\r
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
+ Status = SdMmcHcRwMmio (\r
+ Private->PciIo,\r
+ Trb->Slot,\r
+ SD_MMC_HC_ADMA_SYS_ADDR,\r
+ FALSE,\r
+ sizeof (UINT64),\r
+ &SdmaAddr\r
+ );\r
+ } else {\r
+ Status = SdMmcHcRwMmio (\r
Private->PciIo,\r
Trb->Slot,\r
SD_MMC_HC_SDMA_ADDR,\r
sizeof (UINT32),\r
&SdmaAddr\r
);\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
- Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;\r
+ Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;\r
}\r
\r
if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&\r
((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
(Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
//\r
- // While performing tuning procedure (Execute Tuning is set to 1),\r
- // Transfer Completeis not set to 1\r
- // Refer to SD Host Controller Simplified Specification 3.0 table 2-23 for details.\r
+ // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,\r
+ // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.\r
+ // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.\r
//\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
+ if ((IntStatus & BIT5) == BIT5) {\r
+ //\r
+ // Clear Buffer Read Ready interrupt at first.\r
+ //\r
+ IntStatus = BIT5;\r
+ SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
+ //\r
+ // Read data out from Buffer Port register\r
+ //\r
+ for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {\r
+ SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);\r
+ }\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
}\r
\r
Status = EFI_NOT_READY;\r