MdeModulePkg/SdMmcPciHcDxe: Add V3 64b DMA Support
Driver was supporting only 32b DMA support for V3 controllers. Add support for 64b DMA as well for completeness. For V4.0 64b support, driver was looking at incorrect capability register bit. Fix for that is present as well. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1583 Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com> Tested-by: Eugene Cohen <eugene@hp.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
|
||||
|
||||
Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
||||
Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
@@ -1010,16 +1010,28 @@ SdMmcHcInitV4Enhancements (
|
||||
if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
|
||||
HostCtrl2 = SD_MMC_HC_V4_EN;
|
||||
//
|
||||
// Check if V4 64bit support is available
|
||||
// Check if controller version V4.0
|
||||
//
|
||||
if (Capability.SysBus64V4 != 0) {
|
||||
HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
|
||||
DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
|
||||
if (ControllerVer == SD_MMC_HC_CTRL_VER_400) {
|
||||
//
|
||||
// Check if 64bit support is available
|
||||
//
|
||||
if (Capability.SysBus64V3 != 0) {
|
||||
HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
|
||||
DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
|
||||
}
|
||||
}
|
||||
//
|
||||
// Check if controller version V4.10 or higher
|
||||
//
|
||||
if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
|
||||
else if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
|
||||
//
|
||||
// Check if 64bit support is available
|
||||
//
|
||||
if (Capability.SysBus64V4 != 0) {
|
||||
HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
|
||||
DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
|
||||
}
|
||||
HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
|
||||
DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));
|
||||
}
|
||||
@@ -1393,14 +1405,10 @@ BuildAdmaDescTable (
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_STATUS Status;
|
||||
UINTN Bytes;
|
||||
BOOLEAN AddressingMode64;
|
||||
BOOLEAN DataLength26;
|
||||
UINT32 AdmaMaxDataPerLine;
|
||||
UINT32 DescSize;
|
||||
VOID *AdmaDesc;
|
||||
|
||||
AddressingMode64 = FALSE;
|
||||
DataLength26 = FALSE;
|
||||
AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
|
||||
DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
|
||||
AdmaDesc = NULL;
|
||||
@@ -1409,28 +1417,17 @@ BuildAdmaDescTable (
|
||||
DataLen = Trb->DataLen;
|
||||
PciIo = Trb->Private->PciIo;
|
||||
|
||||
//
|
||||
// Detect whether 64bit addressing is supported.
|
||||
//
|
||||
if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
|
||||
Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
|
||||
SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
AddressingMode64 = TRUE;
|
||||
DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Check for valid ranges in 32bit ADMA Descriptor Table
|
||||
//
|
||||
if (!AddressingMode64 &&
|
||||
if ((Trb->Mode == SdMmcAdma32bMode) &&
|
||||
((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
//
|
||||
// Check address field alignment
|
||||
//
|
||||
if (AddressingMode64) {
|
||||
if (Trb->Mode != SdMmcAdma32bMode) {
|
||||
//
|
||||
// Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)
|
||||
//
|
||||
@@ -1445,13 +1442,19 @@ BuildAdmaDescTable (
|
||||
DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Detect whether 26bit data length is supported.
|
||||
// Configure 64b ADMA.
|
||||
//
|
||||
Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
|
||||
SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DataLength26 = TRUE;
|
||||
if (Trb->Mode == SdMmcAdma64bV3Mode) {
|
||||
DescSize = sizeof (SD_MMC_HC_ADMA_64_V3_DESC_LINE);
|
||||
}else if (Trb->Mode == SdMmcAdma64bV4Mode) {
|
||||
DescSize = sizeof (SD_MMC_HC_ADMA_64_V4_DESC_LINE);
|
||||
}
|
||||
//
|
||||
// Configure 26b data length.
|
||||
//
|
||||
if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {
|
||||
AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
|
||||
}
|
||||
|
||||
@@ -1492,7 +1495,7 @@ BuildAdmaDescTable (
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if ((!AddressingMode64) &&
|
||||
if ((Trb->Mode == SdMmcAdma32bMode) &&
|
||||
(UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
|
||||
//
|
||||
// The ADMA doesn't support 64bit addressing.
|
||||
@@ -1511,19 +1514,20 @@ BuildAdmaDescTable (
|
||||
|
||||
Remaining = DataLen;
|
||||
Address = Data;
|
||||
if (!AddressingMode64) {
|
||||
if (Trb->Mode == SdMmcAdma32bMode) {
|
||||
Trb->Adma32Desc = AdmaDesc;
|
||||
Trb->Adma64Desc = NULL;
|
||||
} else if (Trb->Mode == SdMmcAdma64bV3Mode) {
|
||||
Trb->Adma64V3Desc = AdmaDesc;
|
||||
} else {
|
||||
Trb->Adma64Desc = AdmaDesc;
|
||||
Trb->Adma32Desc = NULL;
|
||||
Trb->Adma64V4Desc = AdmaDesc;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < Entries; Index++) {
|
||||
if (!AddressingMode64) {
|
||||
if (Trb->Mode == SdMmcAdma32bMode) {
|
||||
if (Remaining <= AdmaMaxDataPerLine) {
|
||||
Trb->Adma32Desc[Index].Valid = 1;
|
||||
Trb->Adma32Desc[Index].Act = 2;
|
||||
if (DataLength26) {
|
||||
if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {
|
||||
Trb->Adma32Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
|
||||
}
|
||||
Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
|
||||
@@ -1532,32 +1536,53 @@ BuildAdmaDescTable (
|
||||
} else {
|
||||
Trb->Adma32Desc[Index].Valid = 1;
|
||||
Trb->Adma32Desc[Index].Act = 2;
|
||||
if (DataLength26) {
|
||||
if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {
|
||||
Trb->Adma32Desc[Index].UpperLength = 0;
|
||||
}
|
||||
Trb->Adma32Desc[Index].LowerLength = 0;
|
||||
Trb->Adma32Desc[Index].Address = (UINT32)Address;
|
||||
}
|
||||
} else {
|
||||
} else if (Trb->Mode == SdMmcAdma64bV3Mode) {
|
||||
if (Remaining <= AdmaMaxDataPerLine) {
|
||||
Trb->Adma64Desc[Index].Valid = 1;
|
||||
Trb->Adma64Desc[Index].Act = 2;
|
||||
if (DataLength26) {
|
||||
Trb->Adma64Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
|
||||
Trb->Adma64V3Desc[Index].Valid = 1;
|
||||
Trb->Adma64V3Desc[Index].Act = 2;
|
||||
if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {
|
||||
Trb->Adma64V3Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
|
||||
}
|
||||
Trb->Adma64Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
|
||||
Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
|
||||
Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
|
||||
Trb->Adma64V3Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
|
||||
Trb->Adma64V3Desc[Index].LowerAddress = (UINT32)Address;
|
||||
Trb->Adma64V3Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
|
||||
break;
|
||||
} else {
|
||||
Trb->Adma64Desc[Index].Valid = 1;
|
||||
Trb->Adma64Desc[Index].Act = 2;
|
||||
if (DataLength26) {
|
||||
Trb->Adma64Desc[Index].UpperLength = 0;
|
||||
Trb->Adma64V3Desc[Index].Valid = 1;
|
||||
Trb->Adma64V3Desc[Index].Act = 2;
|
||||
if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {
|
||||
Trb->Adma64V3Desc[Index].UpperLength = 0;
|
||||
}
|
||||
Trb->Adma64Desc[Index].LowerLength = 0;
|
||||
Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
|
||||
Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
|
||||
Trb->Adma64V3Desc[Index].LowerLength = 0;
|
||||
Trb->Adma64V3Desc[Index].LowerAddress = (UINT32)Address;
|
||||
Trb->Adma64V3Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
|
||||
}
|
||||
} else {
|
||||
if (Remaining <= AdmaMaxDataPerLine) {
|
||||
Trb->Adma64V4Desc[Index].Valid = 1;
|
||||
Trb->Adma64V4Desc[Index].Act = 2;
|
||||
if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {
|
||||
Trb->Adma64V4Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
|
||||
}
|
||||
Trb->Adma64V4Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
|
||||
Trb->Adma64V4Desc[Index].LowerAddress = (UINT32)Address;
|
||||
Trb->Adma64V4Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
|
||||
break;
|
||||
} else {
|
||||
Trb->Adma64V4Desc[Index].Valid = 1;
|
||||
Trb->Adma64V4Desc[Index].Act = 2;
|
||||
if (Trb->AdmaLengthMode == SdMmcAdmaLen26b) {
|
||||
Trb->Adma64V4Desc[Index].UpperLength = 0;
|
||||
}
|
||||
Trb->Adma64V4Desc[Index].LowerLength = 0;
|
||||
Trb->Adma64V4Desc[Index].LowerAddress = (UINT32)Address;
|
||||
Trb->Adma64V4Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,7 +1593,13 @@ BuildAdmaDescTable (
|
||||
//
|
||||
// Set the last descriptor line as end of descriptor table
|
||||
//
|
||||
AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);
|
||||
if (Trb->Mode == SdMmcAdma32bMode) {
|
||||
Trb->Adma32Desc[Index].End = 1;
|
||||
} else if (Trb->Mode == SdMmcAdma64bV3Mode) {
|
||||
Trb->Adma64V3Desc[Index].End = 1;
|
||||
} else {
|
||||
Trb->Adma64V4Desc[Index].End = 1;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1665,7 +1696,20 @@ SdMmcCreateTrb (
|
||||
if (Trb->DataLen == 0) {
|
||||
Trb->Mode = SdMmcNoData;
|
||||
} else if (Private->Capability[Slot].Adma2 != 0) {
|
||||
Trb->Mode = SdMmcAdmaMode;
|
||||
Trb->Mode = SdMmcAdma32bMode;
|
||||
Trb->AdmaLengthMode = SdMmcAdmaLen16b;
|
||||
if ((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_300) &&
|
||||
(Private->Capability[Slot].SysBus64V3 == 1)) {
|
||||
Trb->Mode = SdMmcAdma64bV3Mode;
|
||||
} else if (((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_400) &&
|
||||
(Private->Capability[Slot].SysBus64V3 == 1)) ||
|
||||
((Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) &&
|
||||
(Private->Capability[Slot].SysBus64V4 == 1))) {
|
||||
Trb->Mode = SdMmcAdma64bV4Mode;
|
||||
}
|
||||
if (Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) {
|
||||
Trb->AdmaLengthMode = SdMmcAdmaLen26b;
|
||||
}
|
||||
Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
|
||||
if (EFI_ERROR (Status)) {
|
||||
PciIo->Unmap (PciIo, Trb->DataMap);
|
||||
@@ -1719,11 +1763,18 @@ SdMmcFreeTrb (
|
||||
Trb->Adma32Desc
|
||||
);
|
||||
}
|
||||
if (Trb->Adma64Desc != NULL) {
|
||||
if (Trb->Adma64V3Desc != NULL) {
|
||||
PciIo->FreeBuffer (
|
||||
PciIo,
|
||||
Trb->AdmaPages,
|
||||
Trb->Adma64Desc
|
||||
Trb->Adma64V3Desc
|
||||
);
|
||||
}
|
||||
if (Trb->Adma64V4Desc != NULL) {
|
||||
PciIo->FreeBuffer (
|
||||
PciIo,
|
||||
Trb->AdmaPages,
|
||||
Trb->Adma64V4Desc
|
||||
);
|
||||
}
|
||||
if (Trb->DataMap != NULL) {
|
||||
@@ -1891,27 +1942,35 @@ SdMmcExecTrb (
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
|
||||
Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
|
||||
SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_64_ADDR_EN);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
AddressingMode64 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Set Host Control 1 register DMA Select field
|
||||
//
|
||||
if (Trb->Mode == SdMmcAdmaMode) {
|
||||
if ((Trb->Mode == SdMmcAdma32bMode) ||
|
||||
(Trb->Mode == SdMmcAdma64bV4Mode)) {
|
||||
HostCtrl1 = BIT4;
|
||||
Status = SdMmcHcOrMmio (PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
} else if (Trb->Mode == SdMmcAdma64bV3Mode) {
|
||||
HostCtrl1 = BIT4|BIT3;
|
||||
Status = SdMmcHcOrMmio (PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
|
||||
|
||||
if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
|
||||
Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
|
||||
SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
AddressingMode64 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (Trb->Mode == SdMmcSdmaMode) {
|
||||
if ((!AddressingMode64) &&
|
||||
((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
|
||||
@@ -1929,7 +1988,9 @@ SdMmcExecTrb (
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
} else if (Trb->Mode == SdMmcAdmaMode) {
|
||||
} else if ((Trb->Mode == SdMmcAdma32bMode) ||
|
||||
(Trb->Mode == SdMmcAdma64bV3Mode) ||
|
||||
(Trb->Mode == SdMmcAdma64bV4Mode)) {
|
||||
AdmaAddr = (UINT64)(UINTN)Trb->AdmaDescPhy;
|
||||
Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (AdmaAddr), &AdmaAddr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
Reference in New Issue
Block a user