\r
It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.\r
\r
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.\r
Copyright (c) 2015 - 2017, 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
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, " 64-bit Sys Bus %a\n", Capability->SysBus64 ? "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
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
Status = mOverride->NotifyPhase (\r
Private->ControllerHandle,\r
Slot,\r
- EdkiiSdMmcResetPre);\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
Status = mOverride->NotifyPhase (\r
Private->ControllerHandle,\r
Slot,\r
- EdkiiSdMmcResetPost);\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
@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 == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\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) >= SD_MMC_HC_CTRL_VER_300) &&\r
- ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {\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
}\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 V4 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
+ //\r
+ // Check if controller version V4.10 or higher\r
+ //\r
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {\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
Status = mOverride->NotifyPhase (\r
Private->ControllerHandle,\r
Slot,\r
- EdkiiSdMmcInitHostPre);\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
PciIo = Private->PciIo;\r
Capability = Private->Capability[Slot];\r
\r
- Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);\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
Status = mOverride->NotifyPhase (\r
Private->ControllerHandle,\r
Slot,\r
- EdkiiSdMmcInitHostPost);\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
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
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
+ BOOLEAN AddressingMode64;\r
+ BOOLEAN DataLength26;\r
+ UINT32 AdmaMaxDataPerLine;\r
+ UINT32 DescSize;\r
+ VOID *AdmaDesc;\r
+\r
+ AddressingMode64 = FALSE;\r
+ DataLength26 = FALSE;\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
+ // Detect whether 64bit addressing is supported.\r
+ //\r
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {\r
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
+ SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);\r
+ if (!EFI_ERROR (Status)) {\r
+ AddressingMode64 = TRUE;\r
+ DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);\r
+ }\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 (!AddressingMode64 &&\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 ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));\r
+ if (AddressingMode64) {\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
+ // Detect whether 26bit data length is supported.\r
+ //\r
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),\r
+ SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);\r
+ if (!EFI_ERROR (Status)) {\r
+ DataLength26 = TRUE;\r
+ AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;\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
+ 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 ((!AddressingMode64) &&\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 (!AddressingMode64) {\r
+ Trb->Adma32Desc = AdmaDesc;\r
+ Trb->Adma64Desc = NULL;\r
+ } else {\r
+ Trb->Adma64Desc = AdmaDesc;\r
+ Trb->Adma32Desc = NULL;\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 (!AddressingMode64) {\r
+ if (Remaining <= AdmaMaxDataPerLine) {\r
+ Trb->Adma32Desc[Index].Valid = 1;\r
+ Trb->Adma32Desc[Index].Act = 2;\r
+ if (DataLength26) {\r
+ Trb->Adma32Desc[Index].UpperLength = (UINT16)(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 (DataLength26) {\r
+ Trb->Adma32Desc[Index].UpperLength = 0;\r
+ }\r
+ Trb->Adma32Desc[Index].LowerLength = 0;\r
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;\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->Adma64Desc[Index].Valid = 1;\r
+ Trb->Adma64Desc[Index].Act = 2;\r
+ if (DataLength26) {\r
+ Trb->Adma64Desc[Index].UpperLength = (UINT16)(Remaining >> 16);\r
+ }\r
+ Trb->Adma64Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);\r
+ Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;\r
+ Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);\r
+ break;\r
+ } else {\r
+ Trb->Adma64Desc[Index].Valid = 1;\r
+ Trb->Adma64Desc[Index].Act = 2;\r
+ if (DataLength26) {\r
+ Trb->Adma64Desc[Index].UpperLength = 0;\r
+ }\r
+ Trb->Adma64Desc[Index].LowerLength = 0;\r
+ Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;\r
+ Trb->Adma64Desc[Index].UpperAddress = (UINT32)(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
+ AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);\r
return EFI_SUCCESS;\r
}\r
\r
Trb->Mode = SdMmcNoData;\r
} else if (Private->Capability[Slot].Adma2 != 0) {\r
Trb->Mode = SdMmcAdmaMode;\r
- Status = BuildAdmaDescTable (Trb);\r
+ Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
if (EFI_ERROR (Status)) {\r
PciIo->Unmap (PciIo, Trb->DataMap);\r
goto Error;\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->Adma32Desc\r
+ );\r
+ }\r
+ if (Trb->Adma64Desc != NULL) {\r
PciIo->FreeBuffer (\r
PciIo,\r
Trb->AdmaPages,\r
- Trb->AdmaDesc\r
+ Trb->Adma64Desc\r
);\r
}\r
if (Trb->DataMap != NULL) {\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
\r
SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);\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_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);\r
+ if (!EFI_ERROR (Status)) {\r
+ AddressingMode64 = TRUE;\r
+ }\r
+ }\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
//\r
// Calcuate Block Count.\r
//\r
- BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\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
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);\r
if (EFI_ERROR (Status)) {\r
return Status;\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
// 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