/** @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
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.\r
+ Copyright (c) 2015 - 2019, 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
\r
#include "SdMmcPciHcDxe.h"\r
\r
+EDKII_SD_MMC_OVERRIDE *mOverride;\r
+\r
//\r
// Driver Global Variables\r
//\r
{ // MaxCurrent\r
0,\r
},\r
- 0 // ControllerVersion\r
+ {\r
+ 0 // ControllerVersion\r
+ }\r
};\r
\r
SD_DEVICE_PATH mSdDpTemplate = {\r
Trb->Packet->TransactionStatus = EFI_TIMEOUT;\r
TrbEvent = Trb->Event;\r
SdMmcFreeTrb (Trb);\r
- DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));\r
+ DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));\r
gBS->SignalEvent (TrbEvent);\r
return;\r
}\r
Trb->Packet->TransactionStatus = Status;\r
TrbEvent = Trb->Event;\r
SdMmcFreeTrb (Trb);\r
- DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));\r
+ DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));\r
gBS->SignalEvent (TrbEvent);\r
}\r
return;\r
LIST_ENTRY *Link;\r
LIST_ENTRY *NextLink;\r
SD_MMC_HC_TRB *Trb;\r
+ EFI_TPL OldTpl;\r
\r
Private = (SD_MMC_HC_PRIVATE_DATA*)Context;\r
\r
if ((Private->Slot[Slot].Enable) && (Private->Slot[Slot].SlotType == RemovableSlot)) {\r
Status = SdMmcHcCardDetect (Private->PciIo, Slot, &MediaPresent);\r
if ((Status == EFI_MEDIA_CHANGED) && !MediaPresent) {\r
- DEBUG ((EFI_D_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));\r
+ DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));\r
Private->Slot[Slot].MediaPresent = FALSE;\r
Private->Slot[Slot].Initialized = FALSE;\r
//\r
// Signal all async task events at the slot with EFI_NO_MEDIA status.\r
//\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
for (Link = GetFirstNode (&Private->Queue);\r
!IsNull (&Private->Queue, Link);\r
Link = NextLink) {\r
SdMmcFreeTrb (Trb);\r
}\r
}\r
+ gBS->RestoreTPL (OldTpl);\r
//\r
// Notify the upper layer the connect state change through ReinstallProtocolInterface.\r
//\r
);\r
}\r
if ((Status == EFI_MEDIA_CHANGED) && MediaPresent) {\r
- DEBUG ((EFI_D_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));\r
+ DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));\r
//\r
// Reset the specified slot of the SD/MMC Pci Host Controller\r
//\r
- Status = SdMmcHcReset (Private->PciIo, Slot);\r
+ Status = SdMmcHcReset (Private, Slot);\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
//\r
// Reinitialize slot and restart identification process for the new attached device\r
//\r
- Status = SdMmcHcInitHost (Private->PciIo, Slot, Private->Capability[Slot]);\r
+ Status = SdMmcHcInitHost (Private, Slot);\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
CARD_TYPE_DETECT_ROUTINE *Routine;\r
UINT32 RoutineNum;\r
BOOLEAN MediaPresent;\r
+ BOOLEAN Support64BitDma;\r
\r
- DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));\r
+ DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));\r
\r
//\r
// Open PCI I/O Protocol and save pointer to open protocol\r
goto Done;\r
}\r
\r
+ //\r
+ // Attempt to locate the singleton instance of the SD/MMC override protocol,\r
+ // which implements platform specific workarounds for non-standard SDHCI\r
+ // implementations.\r
+ //\r
+ if (mOverride == NULL) {\r
+ Status = gBS->LocateProtocol (&gEdkiiSdMmcOverrideProtocolGuid, NULL,\r
+ (VOID **)&mOverride);\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_INFO, "%a: found SD/MMC override protocol\n",\r
+ __FUNCTION__));\r
+ }\r
+ }\r
+\r
+ Support64BitDma = TRUE;\r
for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {\r
Private->Slot[Slot].Enable = TRUE;\r
\r
+ //\r
+ // Get SD/MMC Pci Host Controller Version\r
+ //\r
+ Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private->ControllerVersion[Slot]);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
+\r
+ Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;\r
+\r
+ if (mOverride != NULL && mOverride->Capability != NULL) {\r
+ Status = mOverride->Capability (\r
+ Controller,\r
+ Slot,\r
+ &Private->Capability[Slot],\r
+ &Private->BaseClkFreq[Slot]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",\r
+ __FUNCTION__, Status));\r
+ continue;\r
+ }\r
+ }\r
DumpCapabilityReg (Slot, &Private->Capability[Slot]);\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Slot[%d] Base Clock Frequency: %dMHz\n",\r
+ Slot,\r
+ Private->BaseClkFreq[Slot]\r
+ ));\r
+\r
+ //\r
+ // If any of the slots does not support 64b system bus\r
+ // do not enable 64b DMA in the PCI layer.\r
+ //\r
+ if (Private->Capability[Slot].SysBus64V3 == 0 &&\r
+ Private->Capability[Slot].SysBus64V4 == 0) {\r
+ Support64BitDma = FALSE;\r
+ }\r
\r
Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);\r
if (EFI_ERROR (Status)) {\r
\r
Private->Slot[Slot].SlotType = Private->Capability[Slot].SlotType;\r
if ((Private->Slot[Slot].SlotType != RemovableSlot) && (Private->Slot[Slot].SlotType != EmbeddedSlot)) {\r
- DEBUG ((EFI_D_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));\r
+ DEBUG ((DEBUG_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));\r
continue;\r
}\r
\r
//\r
// Reset the specified slot of the SD/MMC Pci Host Controller\r
//\r
- Status = SdMmcHcReset (PciIo, Slot);\r
+ Status = SdMmcHcReset (Private, Slot);\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
//\r
// Check whether there is a SD/MMC card attached\r
//\r
- Status = SdMmcHcCardDetect (PciIo, Slot, &MediaPresent);\r
- if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {\r
- continue;\r
- } else if (!MediaPresent) {\r
- DEBUG ((EFI_D_ERROR, "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n", Slot));\r
- continue;\r
+ if (Private->Slot[Slot].SlotType == RemovableSlot) {\r
+ Status = SdMmcHcCardDetect (PciIo, Slot, &MediaPresent);\r
+ if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {\r
+ continue;\r
+ } else if (!MediaPresent) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n",\r
+ Slot\r
+ ));\r
+ continue;\r
+ }\r
}\r
\r
- Status = SdMmcHcInitHost (PciIo, Slot, Private->Capability[Slot]);\r
+ Status = SdMmcHcInitHost (Private, Slot);\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
}\r
}\r
\r
+ //\r
+ // Enable 64-bit DMA support in the PCI layer if this controller\r
+ // supports it.\r
+ //\r
+ if (Support64BitDma) {\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_WARN, "SdMmcPciHcDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status));\r
+ }\r
+ }\r
+\r
//\r
// Start the asynchronous I/O monitor\r
//\r
Status = gBS->CreateEvent (\r
EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
+ TPL_NOTIFY,\r
ProcessAsyncTaskList,\r
Private,\r
&Private->TimerEvent\r
NULL\r
);\r
\r
- DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));\r
+ DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));\r
\r
Done:\r
if (EFI_ERROR (Status)) {\r
LIST_ENTRY *NextLink;\r
SD_MMC_HC_TRB *Trb;\r
\r
- DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));\r
+ DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));\r
\r
Status = gBS->OpenProtocol (\r
Controller,\r
\r
FreePool (Private);\r
\r
- DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));\r
+ DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));\r
\r
return Status;\r
}\r
// Wait async I/O list is empty before execute sync I/O operation.\r
//\r
while (TRUE) {\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
if (IsListEmpty (&Private->Queue)) {\r
gBS->RestoreTPL (OldTpl);\r
break;\r
}\r
\r
Done:\r
- if ((Trb != NULL) && (Trb->AdmaDesc != NULL)) {\r
- FreePages (Trb->AdmaDesc, Trb->AdmaPages);\r
- }\r
-\r
- if (Trb != NULL) {\r
- FreePool (Trb);\r
- }\r
+ SdMmcFreeTrb (Trb);\r
\r
return Status;\r
}\r
//\r
// Free all async I/O requests in the queue\r
//\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
\r
for (Link = GetFirstNode (&Private->Queue);\r
!IsNull (&Private->Queue, Link);\r