diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c index b8651ff998..4dbd033d41 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.
+ Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.
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; } diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h index ed4776f548..489b6c34ec 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.
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. diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c index d19a7fed6e..360b642611 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.
+ Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.
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.