UFS host controller specification allows for implementation specific
UIC programming to take place just after host controller enable and before
device detection. Since there is no way for generic driver to anticipate
implementation specific programming we add a UFS info protocol
which allows the implementation specific code to pass this information
to generic driver. UFS info protocol is located by the driver at the
BindingStart call and the supported instance is retained throught entire
driver lifetime. Presence of the protocol is optional.

Contributed-under: TianoCore Contribution Agreement 1.1
Cc: Hao Wu <hao.a...@intel.com>
Signed-off-by: Albecki Mateusz <mateusz.albe...@intel.com>
---
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c  | 62 ++++++++++++++++++
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h  |  2 +
 .../Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf      |  1 +
 .../Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c        | 60 +++++++++++++++++
 .../Include/Protocol/UfsHostControllerInfo.h       | 75 ++++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.dec                      |  3 +
 6 files changed, 203 insertions(+)
 create mode 100644 MdeModulePkg/Include/Protocol/UfsHostControllerInfo.h

diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c 
b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
index ea329618dc..a41079e311 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
@@ -40,6 +40,7 @@ UFS_PASS_THRU_PRIVATE_DATA gUfsPassThruTemplate = {
     UfsRwUfsAttribute
   },
   0,                              // UfsHostController
+  NULL,                           // UfsInfo
   0,                              // UfsHcBase
   0,                              // Capabilities
   0,                              // TaskTag
@@ -776,6 +777,66 @@ UfsFinishDeviceInitialization (
   return EFI_SUCCESS;
 }
 
+/**
+  Locates UFS HC infor protocol suitable for this controller.
+
+  @param[in] DriverBinding     Pointer to driver binding protocol
+  @param[in] Private           Pointer to host controller private data
+  @param[in] ControllerHandle  Controller to which driver is bound
+**/
+VOID
+GetUfsHcInfoProtocol (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding,
+  IN UFS_PASS_THRU_PRIVATE_DATA   *Private,
+  IN EFI_HANDLE                   ControllerHandle
+  )
+{
+  EFI_STATUS            Status;
+  EFI_HANDLE            *ProtocolHandleArray;
+  UINTN                 NoHandles;
+  UINTN                 HandleIndex;
+  UFS_HC_INFO_PROTOCOL  *UfsHcInfo;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gUfsHcInfoProtocolGuid,
+                  NULL,
+                  &NoHandles,
+                  &ProtocolHandleArray
+                  );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) {
+    Status = gBS->OpenProtocol (
+                    ProtocolHandleArray[HandleIndex],
+                    &gUfsHcInfoProtocolGuid,
+                    &UfsHcInfo,
+                    DriverBinding->DriverBindingHandle,
+                    ControllerHandle,
+                    EFI_OPEN_PROTOCOL_BY_DRIVER
+                    );
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+    if (!EFI_ERROR(UfsHcInfo->Supported (UfsHcInfo, ControllerHandle))) {
+      Private->UfsHcInfo = UfsHcInfo;
+      break;
+    } else {
+      Status = gBS->CloseProtocol (
+                      ProtocolHandleArray[HandleIndex],
+                      &gUfsHcInfoProtocolGuid,
+                      DriverBinding->DriverBindingHandle,
+                      ControllerHandle
+                      );
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  FreePool (ProtocolHandleArray);
+}
+
 /**
   Starts a device controller or a bus controller.
 
@@ -871,6 +932,7 @@ UfsPassThruDriverBindingStart (
   Private->UfsHostController    = UfsHc;
   Private->UfsHcBase            = UfsHcBase;
   InitializeListHead (&Private->Queue);
+  GetUfsHcInfoProtocol (This, Private, Controller);
 
   //
   // Initialize UFS Host Controller H/W.
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h 
b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
index e591e78661..55a8ed9bdf 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
@@ -29,6 +29,7 @@
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/DevicePathLib.h>
 #include <Library/TimerLib.h>
+#include <Protocol/UfsHostControllerInfo.h>
 
 #include "UfsPassThruHci.h"
 
@@ -66,6 +67,7 @@ typedef struct _UFS_PASS_THRU_PRIVATE_DATA {
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL     ExtScsiPassThru;
   EFI_UFS_DEVICE_CONFIG_PROTOCOL      UfsDevConfig;
   EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHostController;
+  UFS_HC_INFO_PROTOCOL                *UfsHcInfo;
   UINTN                               UfsHcBase;
   UINT32                              Capabilities;
 
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf 
b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
index e550cd02b4..12b01771ff 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
@@ -59,6 +59,7 @@
   gEfiExtScsiPassThruProtocolGuid               ## BY_START
   gEfiUfsDeviceConfigProtocolGuid               ## BY_START
   gEdkiiUfsHostControllerProtocolGuid           ## TO_START
+  gUfsHcInfoProtocolGuid
 
 [UserExtensions.TianoCore."ExtraFiles"]
   UfsPassThruExtra.uni
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c 
b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
index c37161c4ae..125f2f2516 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
@@ -2068,6 +2068,61 @@ UfsInitTransferRequestList (
   return EFI_SUCCESS;
 }
 
+/**
+  Performs additional UIC programming if it has been specified by platform in 
UFS info protocol.
+
+  @param[in] Private  Pointer to host controller private data
+
+  @retval EFI_SUCCESS  Programming finished successfully or not requested
+  @retval others       Programming failed
+**/
+EFI_STATUS
+UfsProgramAdditionalUicAttributes (
+  IN UFS_PASS_THRU_PRIVATE_DATA  *Private
+  )
+{
+  EFI_STATUS     Status;
+  UIC_ATTRIBUTE  *UicAttrArray;
+  UINTN          NoAttributes;
+  UINTN          AttributeIndex;
+
+  //
+  // No info protocol means that no additional programming should be performed
+  //
+  if (Private->UfsHcInfo == NULL) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // If we failed to get the programming table we assume that platform doesn't 
want to do any additional programming
+  //
+  Status = Private->UfsHcInfo->GetUicProgrammingTable (Private->UfsHcInfo, 
&UicAttrArray, &NoAttributes);
+  if (EFI_ERROR (Status)) {
+    return EFI_SUCCESS;
+  }
+
+  for (AttributeIndex = 0; AttributeIndex < NoAttributes; AttributeIndex++) {
+    DEBUG ((DEBUG_ERROR, "Programing UIC attribute = %d, selector index = %d, 
set type = %d, value = %d\n",
+                          UicAttrArray[AttributeIndex].MibAttribute, 
UicAttrArray[AttributeIndex].GenSelectorIndex,
+                          UicAttrArray[AttributeIndex].AttrSetType, 
UicAttrArray[AttributeIndex].AttributeValue));
+    Status = UfsExecUicCommands (
+               Private,
+               UfsUicDmeSet,
+               (UicAttrArray[AttributeIndex].MibAttribute << 16) | 
(UicAttrArray[AttributeIndex].GenSelectorIndex),
+               UicAttrArray[AttributeIndex].AttrSetType << 16,
+               UicAttrArray[AttributeIndex].AttributeValue
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Failed to program UIC attribute = %d, selector 
index = %d, set type = %d, value = %d\n",
+                            UicAttrArray[AttributeIndex].MibAttribute, 
UicAttrArray[AttributeIndex].GenSelectorIndex,
+                            UicAttrArray[AttributeIndex].AttrSetType, 
UicAttrArray[AttributeIndex].AttributeValue));
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
 /**
   Initialize the UFS host controller.
 
@@ -2090,6 +2145,11 @@ UfsControllerInit (
     return Status;
   }
 
+  Status = UfsProgramAdditionalUicAttributes (Private);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Failed to perform additional UIC 
programming\n"));
+  }
+
   Status = UfsDeviceDetection (Private);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "UfsControllerInit: Device Detection Fails, Status = 
%r\n", Status));
diff --git a/MdeModulePkg/Include/Protocol/UfsHostControllerInfo.h 
b/MdeModulePkg/Include/Protocol/UfsHostControllerInfo.h
new file mode 100644
index 0000000000..c730127482
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/UfsHostControllerInfo.h
@@ -0,0 +1,75 @@
+/** @file
+
+  Universal Flash Storage Host Controller info Protocol.
+
+Copyright (c) 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 that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __UFS_HC_INFO_PROTOCOL_H__
+#define __UFS_HC_INFO_PROTOCOL_H__
+
+#define UFS_HC_INFO_PROTOCOL_VERSION  1
+
+extern EFI_GUID gUfsHcInfoProtocolGuid;
+
+typedef struct _UFS_HC_INFO_PROTOCOL UFS_HC_INFO_PROTOCOL;
+
+typedef struct {
+  UINT16  MibAttribute;
+  UINT16  GenSelectorIndex;
+  UINT8   AttrSetType;
+  UINT32  AttributeValue;
+} UIC_ATTRIBUTE;
+
+/**
+  Checks if this instance of the info protocol supports
+  given host controller.
+
+  @param[in] This              Pointer to this instance of UFS_HC_INFO_PROTOCOL
+  @param[in] ControllerHandle  Controller to check
+
+  @retval EFI_SUCCESS  This instance of info protocol supports given controller
+  @retval others       This instance of info protocol doesn't support given 
controller
+**/
+typedef
+EFI_STATUS
+(*UFS_INFO_CONTROLLER_SUPPORTED) (
+  IN UFS_HC_INFO_PROTOCOL  *This,
+  IN EFI_HANDLE            ControllerHandle
+  );
+
+/**
+  Get the UIC programming table to be used just after host controller
+  enabling and before device detection.
+
+  @param[in] This               Pointer to this instance of 
UFS_HC_INFO_PROTOCOL
+  @param[in] UicAttributeArray  Out variable for address of the table
+  @param[in] NoAttributes       Out variable for number of attributes in the 
array
+
+  @retval EFI_SUCCESS  Table successfully found and returned
+  @retval others       Table wasn't located successfully UIC programming 
shouldn't be performed.
+**/
+typedef
+EFI_STATUS
+(*UFS_INFO_GET_UIC_PROGRAMMING_TABLE) (
+  IN  UFS_HC_INFO_PROTOCOL  *This,
+  OUT UIC_ATTRIBUTE         **UicAttributeArray,
+  OUT UINTN                 *NoAttributes
+  );
+
+struct _UFS_HC_INFO_PROTOCOL {
+  UINT32                              Version;
+  UFS_INFO_CONTROLLER_SUPPORTED       Supported;
+  UFS_INFO_GET_UIC_PROGRAMMING_TABLE  GetUicProgrammingTable;
+};
+
+#endif
+
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index a2130bc439..c6be8f12a4 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -581,6 +581,9 @@
   ## Include/Protocol/UfsHostController.h
   gEdkiiUfsHostControllerProtocolGuid = { 0xebc01af5, 0x7a9, 0x489e, { 0xb7, 
0xce, 0xdc, 0x8, 0x9e, 0x45, 0x9b, 0x2f } }
 
+  ## Include/Protocol/UfsHostControllerInfo.h
+  gUfsHcInfoProtocolGuid = { 0x3d18ba13, 0xd9b1, 0x4dd4, {0xb9, 0x16, 0xd3, 
0x07, 0x96, 0x53, 0x9e, 0xd8}}
+
   ## Include/Protocol/EsrtManagement.h
   gEsrtManagementProtocolGuid         = { 0xa340c064, 0x723c, 0x4a9c, { 0xa4, 
0xdd, 0xd5, 0xb4, 0x7a, 0x26, 0xfb, 0xb0 }}
 
-- 
2.14.1.windows.1

--------------------------------------------------------------------

Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial 
Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | 
Kapital zakladowy 200.000 PLN.

Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i 
moze zawierac informacje poufne. W razie przypadkowego otrzymania tej 
wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; 
jakiekolwiek
przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole 
use of the intended recipient(s). If you are not the intended recipient, please 
contact the sender and delete all copies; any review or distribution by
others is strictly prohibited.

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to