diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index cb47808670..ea6fdc2367 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -91,6 +91,9 @@
[LibraryClasses.ARM, LibraryClasses.AARCH64]
ArmTrngLib|MdePkg/Library/BaseArmTrngLibNull/BaseArmTrngLibNull.inf
+ ArmSmcLib|MdePkg/Library/ArmSmcLib/ArmSmcLib.inf
+ ArmSvcLib|MdePkg/Library/ArmSvcLib/ArmSvcLib.inf
+ ArmFfaLib|MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf
[LibraryClasses.ARM]
RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
@@ -425,6 +428,7 @@
[Components.AARCH64]
SecurityPkg/Tcg/Tcg2StandaloneMmArm/Tcg2StandaloneMmArm.inf
SecurityPkg/Tcg/Tcg2AcpiFfa/Tcg2AcpiFfa.inf
+ SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigFfaPei.inf
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.inf
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceSecLibFfa.inf
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2InstanceLibFfa.inf
diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigFfaPei.inf b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigFfaPei.inf
new file mode 100644
index 0000000000..e20a1f8d2d
--- /dev/null
+++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigFfaPei.inf
@@ -0,0 +1,53 @@
+## @file
+# Set TPM device type
+#
+# This module initializes TPM device type based on CRB over FF-A interface
+#
+# Copyright (c) 2025, Arm Ltd. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = Tcg2ConfigFfaPei
+ FILE_GUID = ae8c4c50-2cd7-11f0-9e39-a7fbc471b972
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = Tcg2ConfigFfaPeimEntryPoint
+
+#
+# VALID_ARCHITECTURES = AARCH64
+#
+
+[Sources]
+ Tcg2ConfigFfaPeim.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ ArmFfaLib
+ BaseLib
+ BaseMemoryLib
+ PeiServicesLib
+ PeimEntryPoint
+ DebugLib
+ PcdLib
+ HobLib
+
+[Guids]
+ gTpm2ServiceFfaGuid ## SOMETIMES_CONSUMES
+ gEfiTpmDeviceInstanceNoneGuid ## SOMETIMES_CONSUMES
+ gEfiTpmDeviceSelectedGuid ## SOMETIMES_PRODUCES
+
+[Ppis]
+ gPeiTpmInitializationDonePpiGuid ## SOMETIMES_PRODUCES
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid
+
+[Depex]
+ gEfiPeiMasterBootModePpiGuid
diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigFfaPeim.c b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigFfaPeim.c
new file mode 100644
index 0000000000..ea01c9b815
--- /dev/null
+++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigFfaPeim.c
@@ -0,0 +1,198 @@
+/** @file
+ Set TPM device type
+
+ This module initializes the TPM device type based on a CRB over FF-A
+ interface
+
+ Copyright (C) 2025, Arm Ltd.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - https://developer.arm.com/documentation/den0138/latest/
+**/
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define TPM2_FFA_SERVICE_MAJOR_VERSION (1)
+#define TPM2_FFA_SERVICE_MINOR_VERSION (0)
+
+STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpmSelectedPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTpmDeviceSelectedGuid,
+ NULL
+};
+
+STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gPeiTpmInitializationDonePpiGuid,
+ NULL
+};
+
+/**
+ Check the Tpm Service Interface version.
+
+ See the CRB over FF-A spec 6.1.
+ all of arguments' value based on the specification.
+
+ @param [in] TpmPartId TPM service partition id.
+
+ @retval EFI_SUCCESS
+ @retval EFI_DEVICE_ERROR Failed to communicate TPM SP.
+ @retval EFI_UNSUPPORTED Unsupported version of TPM service
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+Tpm2FfaCheckInterfaceVersion (
+ IN UINT16 TpmPartId
+ )
+{
+ EFI_STATUS Status;
+ DIRECT_MSG_ARGS TpmArgs;
+ UINT16 MajorVer;
+ UINT16 MinorVer;
+
+ ZeroMem (&TpmArgs, sizeof (DIRECT_MSG_ARGS));
+ TpmArgs.Arg0 = TPM2_FFA_GET_INTERFACE_VERSION;
+
+ Status = ArmFfaLibMsgSendDirectReq2 (TpmPartId, &gTpm2ServiceFfaGuid, &TpmArgs);
+ while (Status == EFI_INTERRUPT_PENDING) {
+ // We are assuming vCPU0 of the TPM SP since it is UP.
+ Status = ArmFfaLibRun (TpmPartId, 0x00);
+ }
+
+ if (EFI_ERROR (Status) || (TpmArgs.Arg0 != TPM2_FFA_SUCCESS_OK_RESULTS_RETURNED)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get interface version... Status: %r, TpmArgs.Arg0: 0x%x\n",
+ __func__,
+ Status,
+ TpmArgs.Arg0
+ ));
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ MajorVer = (TpmArgs.Arg1 & TPM2_FFA_SERVICE_MAJOR_VER_MASK) >> TPM2_FFA_SERVICE_MAJOR_VER_SHIFT;
+ MinorVer = (TpmArgs.Arg1 & TPM2_FFA_SERVICE_MINOR_VER_MASK) >> TPM2_FFA_SERVICE_MINOR_VER_SHIFT;
+ if ((MajorVer != TPM2_FFA_SERVICE_MAJOR_VERSION) || (MinorVer < TPM2_FFA_SERVICE_MINOR_VERSION)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Wrong Tpm Ffa Interface Version...: v%d.%d\n",
+ __func__,
+ MajorVer,
+ MinorVer
+ ));
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The entry point for Tcg2 configuration driver.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+**/
+EFI_STATUS
+EFIAPI
+Tcg2ConfigFfaPeimEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT16 PartId;
+ UINT16 TpmPartId;
+ EFI_FFA_PART_INFO_DESC *TpmPartInfo;
+ VOID *TxBuffer;
+ UINT64 TxBufferSize;
+ VOID *RxBuffer;
+ UINT64 RxBufferSize;
+ UINT32 Count;
+ CONST EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ GUID *TpmInstanceGuid;
+
+ DEBUG ((DEBUG_INFO, "%a\n", __func__));
+
+ TpmInstanceGuid = &gEfiTpmDeviceInstanceNoneGuid;
+ PpiList = &mTpmInitializationDonePpiList;
+
+ Status = ArmFfaLibPartitionIdGet (&PartId);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to get partition-id. Status: %r\n", Status));
+ goto Cleanup;
+ }
+
+ Status = ArmFfaLibGetRxTxBuffers (
+ &TxBuffer,
+ &TxBufferSize,
+ &RxBuffer,
+ &RxBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to get Rx/Tx Buffer. Status: %r\n", Status));
+ goto Cleanup;
+ }
+
+ Status = ArmFfaLibPartitionInfoGet (
+ &gTpm2ServiceFfaGuid,
+ FFA_PART_INFO_FLAG_TYPE_DESC,
+ &Count,
+ (UINT32 *)&Size
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to get Tpm2 partition info. Status: %r\n", Status));
+ goto Cleanup;
+ }
+
+ if ((Count != 1) || (Size < sizeof (EFI_FFA_PART_INFO_DESC))) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((DEBUG_ERROR, "Invalid partition Info(%g). Count: %d, Size: %d\n", &gTpm2ServiceFfaGuid, Count, Size));
+ ArmFfaLibRxRelease (PartId);
+ goto Cleanup;
+ }
+
+ TpmPartInfo = (EFI_FFA_PART_INFO_DESC *)RxBuffer;
+ TpmPartId = TpmPartInfo->PartitionId;
+ ArmFfaLibRxRelease (PartId);
+
+ Status = Tpm2FfaCheckInterfaceVersion (TpmPartId);
+ if (EFI_ERROR (Status)) {
+ goto Cleanup;
+ }
+
+ /*
+ * Set the PcdTpmInstanceGuid to TPM using CRB over FF-A
+ * So that Tpm2DeviceLibRouterPei/Dxe can communicate with
+ * TPM secure partition.
+ */
+ TpmInstanceGuid = &gTpm2ServiceFfaGuid;
+ PpiList = &mTpmSelectedPpi;
+
+Cleanup:
+ Size = sizeof (GUID);
+ Status = PcdSetPtrS (
+ PcdTpmInstanceGuid,
+ &Size,
+ TpmInstanceGuid
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesInstallPpi (PpiList);
+
+ return Status;
+}