summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--[-rwxr-xr-x]MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c3
-rw-r--r--MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c5
-rw-r--r--MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c22
-rw-r--r--MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h7
-rw-r--r--MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c328
-rw-r--r--MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h84
6 files changed, 366 insertions, 83 deletions
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
index 2d3fb68a4b..4ef849fd09 100755..100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
@@ -1,6 +1,7 @@
/** @file
This file provides some helper functions which are specific for EMMC device.
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -707,7 +708,7 @@ EmmcSwitchClockFreq (
//
// Convert the clock freq unit from MHz to KHz.
//
- Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot]);
+ Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
if (EFI_ERROR (Status)) {
return Status;
}
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
index 68485c8b71..83e6bf0c90 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
@@ -1,6 +1,7 @@
/** @file
This file provides some helper functions which are specific for SD card device.
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -864,7 +865,7 @@ SdCardSetBusMode (
return Status;
}
- Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot]);
+ Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1064,7 +1065,7 @@ SdCardIdentification (
goto Error;
}
- SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
+ SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
gBS->Stall (1000);
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
index a87f8deb8c..76c32a4dcd 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
@@ -4,6 +4,7 @@
It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -62,7 +63,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
{ // MaxCurrent
0,
},
- 0 // ControllerVersion
+ {
+ 0 // ControllerVersion
+ }
};
SD_DEVICE_PATH mSdDpTemplate = {
@@ -621,6 +624,14 @@ SdMmcPciHcDriverBindingStart (
for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
Private->Slot[Slot].Enable = TRUE;
+ //
+ // Get SD/MMC Pci Host Controller Version
+ //
+ Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private->ControllerVersion[Slot]);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
if (EFI_ERROR (Status)) {
continue;
@@ -649,7 +660,14 @@ SdMmcPciHcDriverBindingStart (
Private->BaseClkFreq[Slot]
));
- Support64BitDma &= Private->Capability[Slot].SysBus64;
+ //
+ // If any of the slots does not support 64b system bus
+ // do not enable 64b DMA in the PCI layer.
+ //
+ if (Private->Capability[Slot].SysBus64V3 == 0 &&
+ Private->Capability[Slot].SysBus64V4 == 0) {
+ Support64BitDma = FALSE;
+ }
Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);
if (EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
index 8c1a589078..1bb701a503 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
@@ -2,6 +2,7 @@
Provides some data structure definitions used by the SD/MMC host controller driver.
+Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015, 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
@@ -116,8 +117,7 @@ typedef struct {
SD_MMC_HC_SLOT Slot[SD_MMC_HC_MAX_SLOT];
SD_MMC_HC_SLOT_CAP Capability[SD_MMC_HC_MAX_SLOT];
UINT64 MaxCurrent[SD_MMC_HC_MAX_SLOT];
-
- UINT32 ControllerVersion;
+ UINT16 ControllerVersion[SD_MMC_HC_MAX_SLOT];
//
// Some controllers may require to override base clock frequency
@@ -150,7 +150,8 @@ typedef struct {
BOOLEAN Started;
UINT64 Timeout;
- SD_MMC_HC_ADMA_DESC_LINE *AdmaDesc;
+ SD_MMC_HC_ADMA_32_DESC_LINE *Adma32Desc;
+ SD_MMC_HC_ADMA_64_DESC_LINE *Adma64Desc;
EFI_PHYSICAL_ADDRESS AdmaDescPhy;
VOID *AdmaMap;
UINT32 AdmaPages;
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
index ddf6dcf2c4..6086720fa1 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
@@ -4,6 +4,7 @@
It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2017, 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
@@ -45,7 +46,8 @@ DumpCapabilityReg (
DEBUG ((DEBUG_INFO, " Voltage 3.3 %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Voltage 3.0 %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Voltage 1.8 %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));
- DEBUG ((DEBUG_INFO, " 64-bit Sys Bus %a\n", Capability->SysBus64 ? "TRUE" : "FALSE"));
+ DEBUG ((DEBUG_INFO, " V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE"));
+ DEBUG ((DEBUG_INFO, " V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Async Interrupt %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " SlotType "));
if (Capability->SlotType == 0x00) {
@@ -417,6 +419,36 @@ SdMmcHcWaitMmioSet (
}
/**
+ Get the controller version information from the specified slot.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[out] Version The buffer to store the version information.
+
+ @retval EFI_SUCCESS The operation executes successfully.
+ @retval Others The operation fails.
+
+**/
+EFI_STATUS
+SdMmcHcGetControllerVersion (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ OUT UINT16 *Version
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *Version &= 0xFF;
+
+ return EFI_SUCCESS;
+}
+
+/**
Software reset the specified SD/MMC host controller and enable all interrupts.
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
@@ -722,6 +754,7 @@ SdMmcHcStopClock (
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] ClockFreq The max clock frequency to be set. The unit is KHz.
@param[in] BaseClkFreq The base clock frequency of host controller in MHz.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The clock is supplied successfully.
@retval Others The clock isn't supplied successfully.
@@ -732,14 +765,14 @@ SdMmcHcClockSupply (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Slot,
IN UINT64 ClockFreq,
- IN UINT32 BaseClkFreq
+ IN UINT32 BaseClkFreq,
+ IN UINT16 ControllerVer
)
{
EFI_STATUS Status;
UINT32 SettingFreq;
UINT32 Divisor;
UINT32 Remainder;
- UINT16 ControllerVer;
UINT16 ClockCtrl;
//
@@ -775,18 +808,15 @@ SdMmcHcClockSupply (
DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
//
// Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.
//
- if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
- ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
+ if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
+ (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
ASSERT (Divisor <= 0x3FF);
ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
- } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
+ } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
+ (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
//
// Only the most significant bit can be used as divisor.
//
@@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (
}
/**
+ Configure V4 controller enhancements at initialization.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[in] Capability The capability of the slot.
+ @param[in] ControllerVer The version of host controller.
+
+ @retval EFI_SUCCESS The clock is supplied successfully.
+
+**/
+EFI_STATUS
+SdMmcHcInitV4Enhancements (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ IN SD_MMC_HC_SLOT_CAP Capability,
+ IN UINT16 ControllerVer
+ )
+{
+ EFI_STATUS Status;
+ UINT16 HostCtrl2;
+
+ //
+ // Check if controller version V4 or higher
+ //
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+ HostCtrl2 = SD_MMC_HC_V4_EN;
+ //
+ // Check if V4 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"));
+ }
+ //
+ // Check if controller version V4.10 or higher
+ //
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
+ HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
+ DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));
+ }
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
Supply SD/MMC card with lowest clock frequency at initialization.
@param[in] PciIo The PCI IO protocol instance.
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] BaseClkFreq The base clock frequency of host controller in MHz.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The clock is supplied successfully.
@retval Others The clock isn't supplied successfully.
@@ -948,7 +1029,8 @@ EFI_STATUS
SdMmcHcInitClockFreq (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Slot,
- IN UINT32 BaseClkFreq
+ IN UINT32 BaseClkFreq,
+ IN UINT16 ControllerVer
)
{
EFI_STATUS Status;
@@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
// Supply 400KHz clock frequency at initialization phase.
//
InitFreq = 400;
- Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
+ Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);
return Status;
}
@@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
PciIo = Private->PciIo;
Capability = Private->Capability[Slot];
- Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
+ Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
/**
Build ADMA descriptor table for transfer.
- Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
+ Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The ADMA descriptor table is created successfully.
@retval Others The ADMA descriptor table isn't created successfully.
@@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (
**/
EFI_STATUS
BuildAdmaDescTable (
- IN SD_MMC_HC_TRB *Trb
+ IN SD_MMC_HC_TRB *Trb,
+ IN UINT16 ControllerVer
)
{
EFI_PHYSICAL_ADDRESS Data;
@@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
UINT64 Entries;
UINT32 Index;
UINT64 Remaining;
- UINT32 Address;
+ UINT64 Address;
UINTN TableSize;
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;
Data = Trb->DataPhy;
DataLen = Trb->DataLen;
PciIo = Trb->Private->PciIo;
+
//
- // Only support 32bit ADMA Descriptor Table
+ // Detect whether 64bit addressing is supported.
//
- if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
+ 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 &&
+ ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
return EFI_INVALID_PARAMETER;
}
//
- // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
- // for 32-bit address descriptor table.
+ // Check address field alignment
//
- if ((Data & (BIT0 | BIT1)) != 0) {
- DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+ if (AddressingMode64) {
+ //
+ // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)
+ //
+ if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
+ DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data));
+ }
+ } else {
+ //
+ // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
+ //
+ if ((Data & (BIT0 | BIT1)) != 0) {
+ 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.
+ //
+ 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;
+ AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
}
- Entries = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);
- TableSize = (UINTN)MultU64x32 (Entries, sizeof (SD_MMC_HC_ADMA_DESC_LINE));
+ Entries = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);
+ TableSize = (UINTN)MultU64x32 (Entries, DescSize);
Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
Status = PciIo->AllocateBuffer (
PciIo,
AllocateAnyPages,
EfiBootServicesData,
EFI_SIZE_TO_PAGES (TableSize),
- (VOID **)&Trb->AdmaDesc,
+ (VOID **)&AdmaDesc,
0
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
- ZeroMem (Trb->AdmaDesc, TableSize);
+ ZeroMem (AdmaDesc, TableSize);
Bytes = TableSize;
Status = PciIo->Map (
PciIo,
EfiPciIoOperationBusMasterCommonBuffer,
- Trb->AdmaDesc,
+ AdmaDesc,
&Bytes,
&Trb->AdmaDescPhy,
&Trb->AdmaMap
@@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
PciIo->FreeBuffer (
PciIo,
EFI_SIZE_TO_PAGES (TableSize),
- Trb->AdmaDesc
+ AdmaDesc
);
return EFI_OUT_OF_RESOURCES;
}
- if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
+ if ((!AddressingMode64) &&
+ (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
//
// The ADMA doesn't support 64bit addressing.
//
@@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
PciIo->FreeBuffer (
PciIo,
EFI_SIZE_TO_PAGES (TableSize),
- Trb->AdmaDesc
+ AdmaDesc
);
return EFI_DEVICE_ERROR;
}
Remaining = DataLen;
- Address = (UINT32)Data;
+ Address = Data;
+ if (!AddressingMode64) {
+ Trb->Adma32Desc = AdmaDesc;
+ Trb->Adma64Desc = NULL;
+ } else {
+ Trb->Adma64Desc = AdmaDesc;
+ Trb->Adma32Desc = NULL;
+ }
for (Index = 0; Index < Entries; Index++) {
- if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
- Trb->AdmaDesc[Index].Valid = 1;
- Trb->AdmaDesc[Index].Act = 2;
- Trb->AdmaDesc[Index].Length = (UINT16)Remaining;
- Trb->AdmaDesc[Index].Address = Address;
- break;
+ if (!AddressingMode64) {
+ if (Remaining <= AdmaMaxDataPerLine) {
+ Trb->Adma32Desc[Index].Valid = 1;
+ Trb->Adma32Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
+ }
+ Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;
+ break;
+ } else {
+ Trb->Adma32Desc[Index].Valid = 1;
+ Trb->Adma32Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma32Desc[Index].UpperLength = 0;
+ }
+ Trb->Adma32Desc[Index].LowerLength = 0;
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;
+ }
} else {
- Trb->AdmaDesc[Index].Valid = 1;
- Trb->AdmaDesc[Index].Act = 2;
- Trb->AdmaDesc[Index].Length = 0;
- Trb->AdmaDesc[Index].Address = Address;
+ if (Remaining <= AdmaMaxDataPerLine) {
+ Trb->Adma64Desc[Index].Valid = 1;
+ Trb->Adma64Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma64Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
+ }
+ Trb->Adma64Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+ Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+ Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
+ break;
+ } else {
+ Trb->Adma64Desc[Index].Valid = 1;
+ Trb->Adma64Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma64Desc[Index].UpperLength = 0;
+ }
+ Trb->Adma64Desc[Index].LowerLength = 0;
+ Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+ Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
+ }
}
- Remaining -= ADMA_MAX_DATA_PER_LINE;
- Address += ADMA_MAX_DATA_PER_LINE;
+ Remaining -= AdmaMaxDataPerLine;
+ Address += AdmaMaxDataPerLine;
}
//
// Set the last descriptor line as end of descriptor table
//
- Trb->AdmaDesc[Index].End = 1;
+ AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);
return EFI_SUCCESS;
}
@@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
Trb->Mode = SdMmcNoData;
} else if (Private->Capability[Slot].Adma2 != 0) {
Trb->Mode = SdMmcAdmaMode;
- Status = BuildAdmaDescTable (Trb);
+ Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
if (EFI_ERROR (Status)) {
PciIo->Unmap (PciIo, Trb->DataMap);
goto Error;
@@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
Trb->AdmaMap
);
}
- if (Trb->AdmaDesc != NULL) {
+ if (Trb->Adma32Desc != NULL) {
+ PciIo->FreeBuffer (
+ PciIo,
+ Trb->AdmaPages,
+ Trb->Adma32Desc
+ );
+ }
+ if (Trb->Adma64Desc != NULL) {
PciIo->FreeBuffer (
PciIo,
Trb->AdmaPages,
- Trb->AdmaDesc
+ Trb->Adma64Desc
);
}
if (Trb->DataMap != NULL) {
@@ -1667,12 +1844,15 @@ SdMmcExecTrb (
UINT16 Cmd;
UINT16 IntStatus;
UINT32 Argument;
- UINT16 BlkCount;
+ UINT32 BlkCount;
UINT16 BlkSize;
UINT16 TransMode;
UINT8 HostCtrl1;
- UINT32 SdmaAddr;
+ UINT64 SdmaAddr;
UINT64 AdmaAddr;
+ BOOLEAN AddressingMode64;
+
+ AddressingMode64 = FALSE;
Packet = Trb->Packet;
PciIo = Trb->Private->PciIo;
@@ -1705,13 +1885,28 @@ SdMmcExecTrb (
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 ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
+ if ((!AddressingMode64) &&
+ ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
return EFI_INVALID_PARAMETER;
}
- SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);
+ SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
+
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
+ } else {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
+ }
+
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1741,9 +1936,13 @@ SdMmcExecTrb (
//
// Calcuate Block Count.
//
- BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
+ BlkCount = (Trb->DataLen / Trb->BlockSize);
+ }
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount);
+ } else {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount);
}
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
UINT16 IntStatus;
UINT32 Response[4];
- UINT32 SdmaAddr;
+ UINT64 SdmaAddr;
UINT8 Index;
UINT8 SwReset;
UINT32 PioLength;
@@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
//
// Update SDMA Address register.
//
- SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
- Status = SdMmcHcRwMmio (
+ SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
+
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcRwMmio (
+ Private->PciIo,
+ Trb->Slot,
+ SD_MMC_HC_ADMA_SYS_ADDR,
+ FALSE,
+ sizeof (UINT64),
+ &SdmaAddr
+ );
+ } else {
+ Status = SdMmcHcRwMmio (
Private->PciIo,
Trb->Slot,
SD_MMC_HC_SDMA_ADDR,
@@ -1972,10 +2182,12 @@ SdMmcCheckTrbResult (
sizeof (UINT32),
&SdmaAddr
);
+ }
+
if (EFI_ERROR (Status)) {
goto Done;
}
- Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
+ Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
}
if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
index dd45cbde5b..d157f2c7cd 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
@@ -2,6 +2,7 @@
Provides some data structure definitions used by the SD/MMC host controller driver.
+Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015, 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
@@ -91,18 +92,38 @@ typedef enum {
//
// The maximum data length of each descriptor line
//
-#define ADMA_MAX_DATA_PER_LINE 0x10000
+#define ADMA_MAX_DATA_PER_LINE_16B SIZE_64KB
+#define ADMA_MAX_DATA_PER_LINE_26B SIZE_64MB
+//
+// ADMA descriptor for 32b addressing.
+//
typedef struct {
UINT32 Valid:1;
UINT32 End:1;
UINT32 Int:1;
UINT32 Reserved:1;
UINT32 Act:2;
- UINT32 Reserved1:10;
- UINT32 Length:16;
+ UINT32 UpperLength:10;
+ UINT32 LowerLength:16;
UINT32 Address;
-} SD_MMC_HC_ADMA_DESC_LINE;
+} SD_MMC_HC_ADMA_32_DESC_LINE;
+
+//
+// ADMA descriptor for 64b addressing.
+//
+typedef struct {
+ UINT32 Valid:1;
+ UINT32 End:1;
+ UINT32 Int:1;
+ UINT32 Reserved:1;
+ UINT32 Act:2;
+ UINT32 UpperLength:10;
+ UINT32 LowerLength:16;
+ UINT32 LowerAddress;
+ UINT32 UpperAddress;
+ UINT32 Reserved1;
+} SD_MMC_HC_ADMA_64_DESC_LINE;
#define SD_MMC_SDMA_BOUNDARY 512 * 1024
#define SD_MMC_SDMA_ROUND_UP(x, n) (((x) + n) & ~(n - 1))
@@ -129,36 +150,43 @@ typedef struct {
UINT32 Voltage33:1; // bit 24
UINT32 Voltage30:1; // bit 25
UINT32 Voltage18:1; // bit 26
- UINT32 Reserved3:1; // bit 27
- UINT32 SysBus64:1; // bit 28
+ UINT32 SysBus64V4:1; // bit 27
+ UINT32 SysBus64V3:1; // bit 28
UINT32 AsyncInt:1; // bit 29
UINT32 SlotType:2; // bit 30:31
UINT32 Sdr50:1; // bit 32
UINT32 Sdr104:1; // bit 33
UINT32 Ddr50:1; // bit 34
- UINT32 Reserved4:1; // bit 35
+ UINT32 Reserved3:1; // bit 35
UINT32 DriverTypeA:1; // bit 36
UINT32 DriverTypeC:1; // bit 37
UINT32 DriverTypeD:1; // bit 38
UINT32 DriverType4:1; // bit 39
UINT32 TimerCount:4; // bit 40:43
- UINT32 Reserved5:1; // bit 44
+ UINT32 Reserved4:1; // bit 44
UINT32 TuningSDR50:1; // bit 45
UINT32 RetuningMod:2; // bit 46:47
UINT32 ClkMultiplier:8; // bit 48:55
- UINT32 Reserved6:7; // bit 56:62
+ UINT32 Reserved5:7; // bit 56:62
UINT32 Hs400:1; // bit 63
} SD_MMC_HC_SLOT_CAP;
//
// SD Host controller version
//
-#define SD_MMC_HC_CTRL_VER_100 0x00
-#define SD_MMC_HC_CTRL_VER_200 0x01
-#define SD_MMC_HC_CTRL_VER_300 0x02
-#define SD_MMC_HC_CTRL_VER_400 0x03
-#define SD_MMC_HC_CTRL_VER_410 0x04
-#define SD_MMC_HC_CTRL_VER_420 0x05
+#define SD_MMC_HC_CTRL_VER_100 0x00
+#define SD_MMC_HC_CTRL_VER_200 0x01
+#define SD_MMC_HC_CTRL_VER_300 0x02
+#define SD_MMC_HC_CTRL_VER_400 0x03
+#define SD_MMC_HC_CTRL_VER_410 0x04
+#define SD_MMC_HC_CTRL_VER_420 0x05
+
+//
+// SD Host controller V4 enhancements
+//
+#define SD_MMC_HC_V4_EN BIT12
+#define SD_MMC_HC_64_ADDR_EN BIT13
+#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
/**
Dump the content of SD/MMC host controller's Capability Register.
@@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
);
/**
+ Get the controller version information from the specified slot.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[out] Version The buffer to store the version information.
+
+ @retval EFI_SUCCESS The operation executes successfully.
+ @retval Others The operation fails.
+
+**/
+EFI_STATUS
+SdMmcHcGetControllerVersion (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ OUT UINT16 *Version
+ );
+
+/**
Set all interrupt status bits in Normal and Error Interrupt Status Enable
register.
@@ -424,6 +470,7 @@ SdMmcHcStopClock (
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] ClockFreq The max clock frequency to be set. The unit is KHz.
@param[in] BaseClkFreq The base clock frequency of host controller in MHz.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The clock is supplied successfully.
@retval Others The clock isn't supplied successfully.
@@ -434,7 +481,8 @@ SdMmcHcClockSupply (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Slot,
IN UINT64 ClockFreq,
- IN UINT32 BaseClkFreq
+ IN UINT32 BaseClkFreq,
+ IN UINT16 ControllerVer
);
/**
@@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
@param[in] PciIo The PCI IO protocol instance.
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] BaseClkFreq The base clock frequency of host controller in MHz.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The clock is supplied successfully.
@retval Others The clock isn't supplied successfully.
@@ -492,7 +541,8 @@ EFI_STATUS
SdMmcHcInitClockFreq (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Slot,
- IN UINT32 BaseClkFreq
+ IN UINT32 BaseClkFreq,
+ IN UINT16 ControllerVer
);
/**