Drivers/DwUfsHcDxe: open PciIo protocol
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
diff --git a/Drivers/Block/DwUfsHcDxe/ComponentName.c b/Drivers/Block/DwUfsHcDxe/ComponentName.c
index 89c3f14..03c690c 100644
--- a/Drivers/Block/DwUfsHcDxe/ComponentName.c
+++ b/Drivers/Block/DwUfsHcDxe/ComponentName.c
@@ -191,6 +191,8 @@
OUT CHAR16 **ControllerName
)
{
+ EFI_STATUS Status;
+
if (Language == NULL || ControllerName == NULL) {
return EFI_INVALID_PARAMETER;
}
@@ -202,6 +204,18 @@
return EFI_UNSUPPORTED;
}
+ //
+ // Make sure this driver is currently managing Controller Handle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gUfsHcDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
diff --git a/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.c b/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.c
index 901f508..669f9b0 100644
--- a/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.c
+++ b/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.c
@@ -17,6 +17,10 @@
#include "DwUfsHcDxe.h"
+#include <IndustryStandard/Pci.h>
+
+#include <Protocol/PciIo.h>
+
//
// Ufs Host Controller Driver Binding Protocol Instance
//
@@ -551,9 +555,13 @@
)
{
EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ BOOLEAN UfsHcFound;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath = NULL;
+ EFI_PCI_IO_PROTOCOL *PciIo = NULL;
+ PCI_TYPE00 PciData;
ParentDevicePath = NULL;
+ UfsHcFound = FALSE;
//
// UfsHcDxe is a device driver, and should ingore the
@@ -583,6 +591,64 @@
Controller
);
+ //
+ // Now test the EfiPciIoProtocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Now further check the PCI header: Base class (offset 0x0B) and
+ // Sub Class (offset 0x0A). This controller should be an UFS controller
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciData),
+ &PciData
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Since we already got the PciData, we can close protocol to avoid to carry it on for multiple exit points.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Examine UFS Host Controller PCI Configuration table fields
+ //
+ if (PciData.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE) {
+ if (PciData.Hdr.ClassCode[1] == 0x09 ) { //UFS Controller Subclass
+ UfsHcFound = TRUE;
+ }
+ }
+
+ if (!UfsHcFound) {
+ return EFI_UNSUPPORTED;
+ }
+
return Status;
}
@@ -630,16 +696,106 @@
)
{
EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ UINT64 Supports;
+ UINT8 BarIndex;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
UINT32 BaseAddress;
+ PciIo = NULL;
+ Private = NULL;
+ Supports = 0;
+ BarDesc = NULL;
BaseAddress = PcdGet32 (PcdDwUfsHcDxeBaseAddress);
+
+ //
+ // Now test and open the EfiPciIoProtocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ //
+ // Status == 0 - A normal execution flow, SUCCESS and the program proceeds.
+ // Status == ALREADY_STARTED - A non-zero Status code returned. It indicates
+ // that the protocol has been opened and should be treated as a
+ // normal condition and the program proceeds. The Protocol will not
+ // opened 'again' by this call.
+ // Status != ALREADY_STARTED - Error status, terminate program execution
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // EFI_ALREADY_STARTED is also an error
+ //
+ return Status;
+ }
+
+ //BaseAddress = PcdGet32 (PcdDwUfsHcDxeBaseAddress);
Private = AllocateCopyPool (sizeof (UFS_HOST_CONTROLLER_PRIVATE_DATA), &gUfsHcTemplate);
if (Private == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
+
Private->RegBase = (UINTN)BaseAddress;
+ Private->PciIo = PciIo;
+
+ for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
+ Status = PciIo->GetBarAttributes (
+ PciIo,
+ BarIndex,
+ NULL,
+ (VOID**) &BarDesc
+ );
+ if (Status == EFI_UNSUPPORTED) {
+ continue;
+ } else if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ Private->BarIndex = BarIndex;
+ FreePool (BarDesc);
+ break;
+ }
+
+ FreePool (BarDesc);
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &Private->PciAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+ } else {
+ goto Done;
+ }
///
/// Install UFS_HOST_CONTROLLER protocol
@@ -653,6 +809,24 @@
Done:
if (EFI_ERROR (Status)) {
+ if ((Private != NULL) && (Private->PciAttributes != 0)) {
+ //
+ // Restore original PCI attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSet,
+ Private->PciAttributes,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
if (Private != NULL) {
FreePool (Private);
}
@@ -724,6 +898,27 @@
&(Private->UfsHc)
);
if (!EFI_ERROR (Status)) {
+ //
+ // Restore original PCI attributes
+ //
+ Status = Private->PciIo->Attributes (
+ Private->PciIo,
+ EfiPciIoAttributeOperationSet,
+ Private->PciAttributes,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Close protocols opened by UFS host controller driver
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
FreePool (Private);
}
diff --git a/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.h b/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.h
index 1448e08..a5d90ea 100644
--- a/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.h
+++ b/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.h
@@ -23,6 +23,7 @@
#include <Protocol/DevicePath.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/LoadedImage.h>
+#include <Protocol/PciIo.h>
#include <Protocol/UfsHostController.h>
#include <Library/ArmLib.h>
@@ -122,6 +123,10 @@
EFI_HANDLE Handle;
EDKII_UFS_HOST_CONTROLLER_PROTOCOL UfsHc;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 BarIndex;
+ UINT64 PciAttributes;
+
UINTN RegBase;
};
diff --git a/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.inf b/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.inf
index b36b0a4..10c2d26 100644
--- a/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.inf
+++ b/Drivers/Block/DwUfsHcDxe/DwUfsHcDxe.inf
@@ -52,8 +52,9 @@
UefiLib
[Protocols]
- gEfiDevicePathProtocolGuid ## TO_START
gEdkiiUfsHostControllerProtocolGuid ## BY_START
+ gEfiDevicePathProtocolGuid ## TO_START
+ gEfiPciIoProtocolGuid
[Pcd]
gDwUfsHcDxeTokenSpaceGuid.PcdDwUfsHcDxeBaseAddress