MdeModulePkg: Added PPI support in UFS PEI driver.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4490

Added PPI support in UFS PEI driver to link the platform specific code
as same as UFS DXE driver.

Signed-off-by: Kanagavel S <kanagavels@ami.com>
This commit is contained in:
INDIA\kanagavels 2024-10-17 15:37:23 +05:30 committed by mergify[bot]
parent 1a3d4b33b6
commit 87e2ee60d4
6 changed files with 333 additions and 32 deletions

View File

@ -1082,13 +1082,17 @@ InitializeUfsBlockIoPeim (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
UFS_PEIM_HC_PRIVATE_DATA *Private;
EDKII_UFS_HOST_CONTROLLER_PPI *UfsHcPpi;
UINT32 Index;
UINTN MmioBase;
UINT8 Controller;
UFS_UNIT_DESC UnitDescriptor;
EFI_STATUS Status;
UFS_PEIM_HC_PRIVATE_DATA *Private;
EDKII_UFS_HOST_CONTROLLER_PPI *UfsHcPpi;
UINT32 Index;
UINTN MmioBase;
UINT8 Controller;
UFS_UNIT_DESC UnitDescriptor;
EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi = NULL;
UFS_DEV_DESC DeviceDescriptor;
UINT8 RefClkAttr;
EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE Attributes;
//
// Shadow this PEIM to run from memory
@ -1110,6 +1114,19 @@ InitializeUfsBlockIoPeim (
return EFI_DEVICE_ERROR;
}
//
// Locate ufs host controller platform PPI
//
Status = PeiServicesLocatePpi (
&gEdkiiUfsHcPlatformPpiGuid,
0,
NULL,
(VOID **)&UfsHcPlatformPpi
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "LocatePpi gEdkiiUfsHcPlatformPpiGuid Status :%r\n", Status));
}
IoMmuInit ();
Controller = 0;
@ -1145,7 +1162,7 @@ InitializeUfsBlockIoPeim (
//
// Initialize UFS Host Controller H/W.
//
Status = UfsControllerInit (Private);
Status = UfsControllerInit (UfsHcPlatformPpi, Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "UfsDevicePei: Host Controller Initialization Error, Status = %r\n", Status));
Controller++;
@ -1174,25 +1191,87 @@ InitializeUfsBlockIoPeim (
continue;
}
//
// Check if 8 common luns are active and set corresponding bit mask.
//
for (Index = 0; Index < UFS_PEIM_MAX_LUNS; Index++) {
Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8)Index, 0, &UnitDescriptor, sizeof (UFS_UNIT_DESC));
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Fail to read UFS Unit Descriptor, Index = %X, Status = %r\n", Index, Status));
continue;
}
if ((UfsHcPlatformPpi != NULL) &&
((UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq19p2Mhz) ||
(UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq26Mhz) ||
(UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq38p4Mhz)))
{
RefClkAttr = UfsAttrRefClkFreq;
Attributes = EdkiiUfsCardRefClkFreqObsolete;
if (UnitDescriptor.LunEn == 0x1) {
DEBUG ((DEBUG_INFO, "Ufs %d Lun %d is enabled\n", Controller, Index));
Private->Luns.BitMask |= (BIT0 << Index);
Status = UfsRwAttributes (Private, TRUE, RefClkAttr, 0, 0, (UINT32 *)&Attributes);
DEBUG ((DEBUG_INFO, "UfsRwAttributes #1 Status = %r \n", Status));
if (!EFI_ERROR (Status)) {
if (Attributes != UfsHcPlatformPpi->RefClkFreq) {
Attributes = UfsHcPlatformPpi->RefClkFreq;
DEBUG (
(DEBUG_INFO,
"Setting bRefClkFreq attribute(%x) to %x\n 0 -> 19.2 Mhz\n 1 -> 26 Mhz\n 2 -> 38.4 Mhz\n 3 -> Obsolete\n",
RefClkAttr,
Attributes)
);
Status = UfsRwAttributes (Private, FALSE, RefClkAttr, 0, 0, (UINT32 *)&Attributes);
DEBUG ((DEBUG_INFO, "UfsRwAttributes #2 Status = %r \n", Status));
if (EFI_ERROR (Status)) {
DEBUG (
(DEBUG_ERROR,
"Failed to Change Reference Clock Attribute to, Status = %r \n",
Status)
);
}
}
} else {
DEBUG (
(DEBUG_ERROR,
"Failed to Read Reference Clock Attribute, Status = %r \n",
Status)
);
}
}
PeiServicesInstallPpi (&Private->BlkIoPpiList);
PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
Controller++;
if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPostLinkStartup);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPostLinkStartup, Status = %r\n", Status));
Controller++;
continue;
}
//
// Check if 8 common luns are active and set corresponding bit mask.
//
for (Index = 0; Index < UFS_PEIM_MAX_LUNS; Index++) {
Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8)Index, 0, &UnitDescriptor, sizeof (UFS_UNIT_DESC));
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Fail to read UFS Unit Descriptor, Index = %X, Status = %r\n", Index, Status));
continue;
}
if (UnitDescriptor.LunEn == 0x1) {
DEBUG ((DEBUG_INFO, "Ufs %d Lun %d is enabled\n", Controller, Index));
Private->Luns.BitMask |= (BIT0 << Index);
}
}
//
// Get Ufs Device's Lun Info by reading Configuration Descriptor
//
Status = UfsRwDeviceDesc (Private, TRUE, UfsConfigDesc, 0, 0, &DeviceDescriptor, sizeof (UFS_DEV_DESC));
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Ufs Get Configuration Descriptor Error, Status = %r\n", Status));
Controller++;
continue;
}
if (DeviceDescriptor.SecurityLun == 0x1) {
DEBUG ((DEBUG_INFO, "UFS WLUN RPMB is supported\n"));
Private->Luns.BitMask |= BIT11;
}
PeiServicesInstallPpi (&Private->BlkIoPpiList);
PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
Controller++;
}
}
return EFI_SUCCESS;

View File

@ -11,6 +11,7 @@
#include <PiPei.h>
#include <Ppi/UfsHostController.h>
#include <Ppi/UfsHostControllerPlatformPpi.h>
#include <Ppi/BlockIo.h>
#include <Ppi/BlockIo2.h>
#include <Ppi/IoMmu.h>
@ -156,6 +157,33 @@ typedef struct _UFS_DEVICE_MANAGEMENT_REQUEST_PACKET {
UINT8 Ocs;
} UFS_DEVICE_MANAGEMENT_REQUEST_PACKET;
/**
Read or write specified attribute of a UFS device.
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
@param[in] Read The boolean variable to show r/w direction.
@param[in] AttrId The ID of Attribute.
@param[in] Index The Index of Attribute.
@param[in] Selector The Selector of Attribute.
@param[in, out] Attributes The value of Attribute to be read or written.
@retval EFI_SUCCESS The Attribute was read/written successfully.
@retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a
type of UFS device descriptor.
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the Attribute.
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the Attribute.
**/
EFI_STATUS
UfsRwAttributes (
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
IN BOOLEAN Read,
IN UINT8 AttrId,
IN UINT8 Index,
IN UINT8 Selector,
IN OUT UINT32 *Attributes
);
/**
Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
@ -193,7 +221,8 @@ UfsExecScsiCmds (
**/
EFI_STATUS
UfsControllerInit (
IN UFS_PEIM_HC_PRIVATE_DATA *Private
IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi,
IN UFS_PEIM_HC_PRIVATE_DATA *Private
);
/**

View File

@ -52,6 +52,7 @@
gEdkiiPeiUfsHostControllerPpiGuid ## CONSUMES
gEdkiiIoMmuPpiGuid ## CONSUMES
gEfiEndOfPeiSignalPpiGuid ## CONSUMES
gEdkiiUfsHcPlatformPpiGuid ## SOMETIMES CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdUfsInitialCompletionTimeout ## CONSUMES

View File

@ -552,8 +552,8 @@ UfsCreateDMCommandDesc (
}
if (((Opcode != UtpQueryFuncOpcodeRdFlag) && (Opcode != UtpQueryFuncOpcodeSetFlag) &&
(Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag)) &&
((DataSize == 0) || (Data == NULL)))
(Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag) &&
(Opcode != UtpQueryFuncOpcodeRdAttr)) && ((DataSize == 0) || (Data == NULL)))
{
return EFI_INVALID_PARAMETER;
}
@ -759,6 +759,7 @@ UfsGetReturnDataFromQueryResponse (
)
{
UINT16 ReturnDataSize;
UINT32 ReturnData;
ReturnDataSize = 0;
@ -799,6 +800,16 @@ UfsGetReturnDataFromQueryResponse (
//
*((UINT8 *)(Packet->OutDataBuffer)) = *((UINT8 *)&(QueryResp->Tsf.Value) + 3);
break;
case UtpQueryFuncOpcodeRdAttr:
ReturnData = QueryResp->Tsf.Value;
SwapLittleEndianToBigEndian ((UINT8 *)&ReturnData, sizeof (UINT32));
CopyMem (Packet->InDataBuffer, &ReturnData, sizeof (UINT32));
break;
case UtpQueryFuncOpcodeWrAttr:
ReturnData = QueryResp->Tsf.Value;
SwapLittleEndianToBigEndian ((UINT8 *)&ReturnData, sizeof (UINT32));
CopyMem (Packet->OutDataBuffer, &ReturnData, sizeof (UINT32));
break;
default:
return EFI_INVALID_PARAMETER;
}
@ -833,7 +844,9 @@ UfsSendDmRequestRetry (
UINT8 *CmdDescBase;
UINT32 CmdDescSize;
//
// Workaround: Adding this one second for reading descriptor
MicroSecondDelay (1 * 1000 * 1000); // delay 1 seconds
// Find out which slot of transfer request list is available.
//
Status = UfsFindAvailableSlotInTrl (Private, &Slot);
@ -980,6 +993,56 @@ UfsRwDeviceDesc (
return Status;
}
/**
Read or write specified attribute of a UFS device.
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
@param[in] Read The boolean variable to show r/w direction.
@param[in] AttrId The ID of Attribute.
@param[in] Index The Index of Attribute.
@param[in] Selector The Selector of Attribute.
@param[in, out] Attributes The value of Attribute to be read or written.
@retval EFI_SUCCESS The Attribute was read/written successfully.
@retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a
type of UFS device descriptor.
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the Attribute.
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the Attribute.
**/
EFI_STATUS
UfsRwAttributes (
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
IN BOOLEAN Read,
IN UINT8 AttrId,
IN UINT8 Index,
IN UINT8 Selector,
IN OUT UINT32 *Attributes
)
{
UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
if (Read) {
Packet.DataDirection = UfsDataIn;
Packet.Opcode = UtpQueryFuncOpcodeRdAttr;
Packet.InDataBuffer = Attributes;
} else {
Packet.DataDirection = UfsDataOut;
Packet.Opcode = UtpQueryFuncOpcodeWrAttr;
Packet.OutDataBuffer = Attributes;
Packet.OutTransferLength = sizeof (UINT32);
}
Packet.DescId = AttrId;
Packet.Index = Index;
Packet.Selector = Selector;
Packet.Timeout = UFS_TIMEOUT;
return UfsSendDmRequest (Private, &Packet);
}
/**
Read or write specified flag of a UFS device.
@ -1387,6 +1450,7 @@ UfsExecUicCommands (
/**
Enable the UFS host controller for accessing.
@param[in] UfsHcPlatformPpi The pointer to the EDKII_UFS_HC_PLATFORM_PPI data structure
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
@retval EFI_SUCCESS The UFS host controller enabling was executed successfully.
@ -1395,13 +1459,22 @@ UfsExecUicCommands (
**/
EFI_STATUS
UfsEnableHostController (
IN UFS_PEIM_HC_PRIVATE_DATA *Private
IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi,
IN UFS_PEIM_HC_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
UINTN Address;
UINT32 Data;
if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPreHce);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPreHce, Status = %r\n", Status));
return Status;
}
}
//
// UFS 2.0 spec section 7.1.1 - Host Controller Initialization
//
@ -1435,6 +1508,14 @@ UfsEnableHostController (
return EFI_DEVICE_ERROR;
}
if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPostHce);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPostHce, Status = %r\n", Status));
return Status;
}
}
return EFI_SUCCESS;
}
@ -1450,7 +1531,8 @@ UfsEnableHostController (
**/
EFI_STATUS
UfsDeviceDetection (
IN UFS_PEIM_HC_PRIVATE_DATA *Private
IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi,
IN UFS_PEIM_HC_PRIVATE_DATA *Private
)
{
UINTN Retry;
@ -1458,6 +1540,14 @@ UfsDeviceDetection (
UINT32 Data;
EFI_STATUS Status;
if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPreLinkStartup);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPreLinkStartup, Status = %r\n", Status));
return Status;
}
}
//
// Start UFS device detection.
// Try up to 3 times for establishing data link with device.
@ -1625,6 +1715,7 @@ UfsInitTransferRequestList (
/**
Initialize the UFS host controller.
@param[in] UfsHcPlatformPpi The pointer to the EDKII_UFS_HC_PLATFORM_PPI data structure. // APTIOV_OVERRIDE
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
@retval EFI_SUCCESS The Ufs Host Controller is initialized successfully.
@ -1633,18 +1724,19 @@ UfsInitTransferRequestList (
**/
EFI_STATUS
UfsControllerInit (
IN UFS_PEIM_HC_PRIVATE_DATA *Private
IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi,
IN UFS_PEIM_HC_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
Status = UfsEnableHostController (Private);
Status = UfsEnableHostController (UfsHcPlatformPpi, Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "UfsDevicePei: Enable Host Controller Fails, Status = %r\n", Status));
return Status;
}
Status = UfsDeviceDetection (Private);
Status = UfsDeviceDetection (UfsHcPlatformPpi, Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "UfsDevicePei: Device Detection Fails, Status = %r\n", Status));
return Status;

View File

@ -0,0 +1,97 @@
/** @file
EDKII_UFS_HC_PLATFORM_PPI definition.
Copyright (c) 2024, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _EDKII_PEI_UFS_HC_PLATFORM_PPI_H_
#define _EDKII_PEI_UFS_HC_PLATFORM_PPI_H_
#define EDKII_UFS_HC_PLATFORM_PPI_VERSION 1
extern EFI_GUID gEdkiiUfsHcPlatformPpiGuid;
///
/// Forward declaration for the UFS_HOST_CONTROLLER_PPI.
///
typedef struct _EDKII_UFS_HC_PLATFORM_PPI EDKII_UFS_HC_PLATFORM_PPI;
typedef struct {
UINT32 Capabilities;
UINT32 Version;
} EDKII_UFS_HC_INFO;
/**
Allows platform PPI to override host controller information
@param[in] ControllerHandle Handle of the UFS controller.
@param[in, out] HcInfo Pointer EDKII_UFS_HC_INFO associated with host controller.
@retval EFI_SUCCESS Function completed successfully.
@retval EFI_INVALID_PARAMETER HcInfo is NULL.
@retval Others Function failed to complete.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_UFS_HC_PLATFORM_OVERRIDE_HC_INFO)(
IN EFI_HANDLE ControllerHandle,
IN OUT EDKII_UFS_HC_INFO *HcInfo
);
typedef enum {
EdkiiUfsHcPreHce,
EdkiiUfsHcPostHce,
EdkiiUfsHcPreLinkStartup,
EdkiiUfsHcPostLinkStartup
} EDKII_UFS_HC_PLATFORM_CALLBACK_PHASE;
typedef enum {
EdkiiUfsCardRefClkFreq19p2Mhz,
EdkiiUfsCardRefClkFreq26Mhz,
EdkiiUfsCardRefClkFreq38p4Mhz,
EdkiiUfsCardRefClkFreqObsolete
} EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE;
/**
Callback function for platform driver.
@param[in] UfsHcBaseddr The pointer to UfsHcBase address.
@param[in] CallbackPhase Specifies when the platform ppi is called
@retval EFI_SUCCESS Override function completed successfully.
@retval EFI_INVALID_PARAMETER CallbackPhase is invalid or CallbackData is NULL when phase expects valid data.
@retval Others Function failed to complete.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_UFS_HC_PLATFORM_PEI_CALLBACK)(
IN UINTN *UfsHcBaseAddr,
IN EDKII_UFS_HC_PLATFORM_CALLBACK_PHASE CallbackPhase
);
///
/// This PPI contains a set of services to interact with the UFS host controller.
///
struct _EDKII_UFS_HC_PLATFORM_PPI {
///
/// Version of the PPI.
///
UINT32 Version;
///
/// Allows platform driver to override host controller information.
///
EDKII_UFS_HC_PLATFORM_OVERRIDE_HC_INFO OverrideHcInfo;
///
/// Allows platform driver to implement platform specific flows
/// for host controller.
///
EDKII_UFS_HC_PLATFORM_PEI_CALLBACK Callback;
///
/// Reference Clock Frequency Ufs Card Attribute that need to be set in this Ufs Host Environment.
///
EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE RefClkFreq;
};
#endif

View File

@ -531,6 +531,9 @@
## Include/Ppi/UfsHostController.h
gEdkiiPeiUfsHostControllerPpiGuid = { 0xdc54b283, 0x1a77, 0x4cd6, { 0x83, 0xbb, 0xfd, 0xda, 0x46, 0x9a, 0x2e, 0xc6 }}
## Include/Ppi/UfsHostControllerPlatformPpi.h
gEdkiiUfsHcPlatformPpiGuid = { 0x9e2bde17, 0x7df0, 0x42ea, {0x98, 0xa3, 0xf6, 0x9a, 0xf3, 0xfb, 0x2b, 0xb9 }}
## Include/Ppi/IpmiPpi.h
gPeiIpmiPpiGuid = { 0xa9731431, 0xd968, 0x4277, { 0xb7, 0x52, 0xa3, 0xa9, 0xa6, 0xae, 0x18, 0x98 }}