MdeModulePkg/UfsBlockIoPei: Wait fDeviceInit Be Cleared by Devices

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

[Feature Description]
- UFS device would clear fDeviceInit flag once the device initialization
  is completed.
- This change is polling to check the flag is cleared or not with
  specific timeout (UFS_INIT_COMPLETION_TIMEOUT - 600ms).
- This behavior is the same as UfsPassThruDxe module.

[Notes]
- This change included as a partial of below SHA1-ID
    - 95ad8f7f6a6c84ef46a96a8ba852afed805d1ca3
    - c5740f360636479fb91681093b1dee1cc366075c

Signed-off-by: Jason1 Lin <jason1.lin@intel.com>
This commit is contained in:
Jason1 Lin 2024-07-05 22:01:00 +08:00 committed by mergify[bot]
parent 23d3fc056d
commit 11c50d6ca1
3 changed files with 105 additions and 7 deletions

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -1016,6 +1016,58 @@ UfsEndOfPei (
return EFI_SUCCESS;
}
/**
Finishes device initialization by setting fDeviceInit flag and waiting until device responds by
clearing it.
@param[in] Private Pointer to the UFS_PEIM_HC_PRIVATE_DATA.
@retval EFI_SUCCESS The operation succeeds.
@retval Others The operation fails.
**/
EFI_STATUS
UfsFinishDeviceInitialization (
IN UFS_PEIM_HC_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
UINT8 DeviceInitStatus;
UINT32 Timeout;
DeviceInitStatus = 0xFF;
//
// The host enables the device initialization completion by setting fDeviceInit flag.
//
Status = UfsSetFlag (Private, UfsFlagDevInit);
if (EFI_ERROR (Status)) {
return Status;
}
//
// There are cards that can take upto 600ms to clear fDeviceInit flag.
//
Timeout = UFS_INIT_COMPLETION_TIMEOUT;
do {
Status = UfsReadFlag (Private, UfsFlagDevInit, &DeviceInitStatus);
if (EFI_ERROR (Status)) {
return Status;
}
MicroSecondDelay (1);
Timeout--;
} while (DeviceInitStatus != 0 && Timeout != 0);
if (Timeout == 0) {
DEBUG ((DEBUG_ERROR, "%a: DeviceInitStatus = %x EFI_TIMEOUT \n", __func__, DeviceInitStatus));
return EFI_TIMEOUT;
} else {
DEBUG ((DEBUG_INFO, "%a: Timeout left = %x EFI_SUCCESS \n", __func__, Timeout));
return EFI_SUCCESS;
}
}
/**
The user code starts with this function.
@ -1116,11 +1168,11 @@ InitializeUfsBlockIoPeim (
}
//
// The host enables the device initialization completion by setting fDeviceInit flag.
// Check the UFS device is initialized completed.
//
Status = UfsSetFlag (Private, UfsFlagDevInit);
Status = UfsFinishDeviceInitialization (Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Ufs Set fDeviceInit Flag Error, Status = %r\n", Status));
DEBUG ((DEBUG_ERROR, "Device failed to finish initialization, Status = %r\n", Status));
Controller++;
continue;
}

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -31,7 +31,8 @@
#define UFS_PEIM_HC_SIG SIGNATURE_32 ('U', 'F', 'S', 'H')
#define UFS_PEIM_MAX_LUNS 8
#define UFS_PEIM_MAX_LUNS 8
#define UFS_INIT_COMPLETION_TIMEOUT 600000
typedef struct {
UINT8 Lun[UFS_PEIM_MAX_LUNS];
@ -226,6 +227,25 @@ UfsSetFlag (
IN UINT8 FlagId
);
/**
Read specified flag from a UFS device.
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
@param[in] FlagId The ID of flag to be read.
@param[out] Value The flag's value.
@retval EFI_SUCCESS The flag was read successfully.
@retval EFI_DEVICE_ERROR A device error occurred while attempting to read the flag.
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of reading the flag.
**/
EFI_STATUS
UfsReadFlag (
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
IN UINT8 FlagId,
OUT UINT8 *Value
);
/**
Read or write specified device descriptor of a UFS device.

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -1065,6 +1065,32 @@ UfsSetFlag (
return Status;
}
/**
Read specified flag from a UFS device.
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
@param[in] FlagId The ID of flag to be read.
@param[out] Value The flag's value.
@retval EFI_SUCCESS The flag was read successfully.
@retval EFI_DEVICE_ERROR A device error occurred while attempting to read the flag.
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of reading the flag.
**/
EFI_STATUS
UfsReadFlag (
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
IN UINT8 FlagId,
OUT UINT8 *Value
)
{
EFI_STATUS Status;
Status = UfsRwFlags (Private, TRUE, FlagId, Value);
return Status;
}
/**
Sends NOP IN cmd to a UFS device for initialization process request.
For more details, please refer to UFS 2.0 spec Figure 13.3.