Merge "fix(gpt): use DC CIGDPAPA when MTE2 is implemented" into integration
diff --git a/Makefile b/Makefile
index f324ebc..6a1ea99 100644
--- a/Makefile
+++ b/Makefile
@@ -31,6 +31,12 @@
 
 include ${MAKE_HELPERS_DIRECTORY}defaults.mk
 
+################################################################################
+# Configure the toolchains used to build TF-A and its tools
+################################################################################
+
+include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
+
 # Assertions enabled for DEBUG builds by default
 ENABLE_ASSERTIONS		:= ${DEBUG}
 ENABLE_PMF			:= ${ENABLE_RUNTIME_INSTRUMENTATION}
@@ -94,28 +100,6 @@
 export Q ECHO
 
 ################################################################################
-# Toolchain
-################################################################################
-
-HOSTCC			:=	gcc
-export HOSTCC
-
-CC			:=	${CROSS_COMPILE}gcc
-CPP			:=	${CROSS_COMPILE}gcc -E
-AS			:=	${CROSS_COMPILE}gcc
-AR			:=	${CROSS_COMPILE}gcc-ar
-LINKER			:=	${CROSS_COMPILE}ld
-OC			:=	${CROSS_COMPILE}objcopy
-OD			:=	${CROSS_COMPILE}objdump
-DTC			:=	dtc
-
-# Use ${LD}.bfd instead if it exists (as absolute path or together with $PATH).
-ifneq ($(strip $(wildcard ${LD}.bfd) \
-	$(foreach dir,$(subst :, ,${PATH}),$(wildcard ${dir}/${LINKER}.bfd))),)
-LINKER			:=	${LINKER}.bfd
-endif
-
-################################################################################
 # Auxiliary tools (fiptool, cert_create, etc)
 ################################################################################
 
@@ -161,35 +145,22 @@
 ################################################################################
 arch-features		=	${ARM_ARCH_FEATURE}
 
-ifneq ($(findstring clang,$(notdir $(CC))),)
-	ifneq ($(findstring armclang,$(notdir $(CC))),)
+ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
+	ifeq ($($(ARCH)-cc-id),arm-clang)
 		TF_CFLAGS_aarch32	:=	-target arm-arm-none-eabi
 		TF_CFLAGS_aarch64	:=	-target aarch64-arm-none-eabi
-		LD			:=	$(LINKER)
 	else
 		TF_CFLAGS_aarch32	=	$(target32-directive)
 		TF_CFLAGS_aarch64	:=	-target aarch64-elf
-		LD			:=	$(shell $(CC) --print-prog-name ld.lld)
-
-		AR			:=	$(shell $(CC) --print-prog-name llvm-ar)
-		OD			:=	$(shell $(CC) --print-prog-name llvm-objdump)
-		OC			:=	$(shell $(CC) --print-prog-name llvm-objcopy)
 	endif
 
-	CPP		:=	$(CC) -E $(TF_CFLAGS_$(ARCH))
-	AS		:=	$(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH))
-else ifneq ($(findstring gcc,$(notdir $(CC))),)
+else ifeq ($($(ARCH)-cc-id),gnu-gcc)
 	ifeq ($(ENABLE_LTO),1)
 		# Enable LTO only for aarch64
 		ifeq (${ARCH},aarch64)
 			LTO_CFLAGS	=	-flto
-			# Use gcc as a wrapper for the ld, recommended for LTO
-			LINKER		:=	${CROSS_COMPILE}gcc
 		endif
 	endif
-	LD			=	$(LINKER)
-else
-	LD			=	$(LINKER)
 endif #(clang)
 
 # Process Debug flag
@@ -286,7 +257,7 @@
 endif #(W)
 
 # Compiler specific warnings
-ifeq ($(findstring clang,$(notdir $(CC))),)
+ifeq ($(filter %-clang,$($(ARCH)-cc-id)),)
 # not using clang
 WARNINGS	+=		-Wunused-but-set-variable -Wmaybe-uninitialized	\
 				-Wpacked-bitfield-compat -Wshift-overflow=2 \
@@ -330,18 +301,18 @@
 				-fsanitize-undefined-trap-on-error
 endif #(${SANITIZE_UB},trap)
 
-GCC_V_OUTPUT		:=	$(shell $(CC) -v 2>&1)
+GCC_V_OUTPUT		:=	$(shell $($(ARCH)-cc) -v 2>&1)
 
 TF_LDFLAGS		+=	-z noexecstack
 
 # LD = armlink
-ifneq ($(findstring armlink,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),arm-link)
 	TF_LDFLAGS		+=	--diag_error=warning --lto_level=O1
 	TF_LDFLAGS		+=	--remove --info=unused,unusedsymbols
 	TF_LDFLAGS		+=	$(TF_LDFLAGS_$(ARCH))
 
 # LD = gcc (used when GCC LTO is enabled)
-else ifneq ($(findstring gcc,$(notdir $(LD))),)
+else ifeq ($($(ARCH)-ld-id),gnu-gcc)
 	# Pass ld options with Wl or Xlinker switches
 	TF_LDFLAGS		+=	$(call ld_option,-Xlinker --no-warn-rwx-segments)
 	TF_LDFLAGS		+=	-Wl,--fatal-warnings -O1
@@ -383,7 +354,7 @@
 # therefore don't add those in that case.
 # ld.lld reports section type mismatch warnings,
 # therefore don't add --fatal-warnings to it.
-	ifeq ($(findstring ld.lld,$(notdir $(LD))),)
+	ifneq ($($(ARCH)-ld-id),llvm-lld)
 		TF_LDFLAGS	+=	$(TF_LDFLAGS_$(ARCH)) --fatal-warnings
 	endif
 
@@ -415,7 +386,7 @@
 				plat/common/${ARCH}/platform_helpers.S	\
 				${COMPILER_RT_SRCS}
 
-ifeq ($(notdir $(CC)),armclang)
+ifeq ($($(ARCH)-cc-id),arm-clang)
 	BL_COMMON_SOURCES	+=	lib/${ARCH}/armclang_printf.S
 endif
 
@@ -481,8 +452,12 @@
 			DTC_CPPFLAGS	+=	-DOPTEE_SP_FW_CONFIG
 		endif
 
+		ifeq ($(findstring trusty_sp,$(ARM_SPMC_MANIFEST_DTS)),trusty_sp)
+			DTC_CPPFLAGS	+=	-DTRUSTY_SP_FW_CONFIG
+		endif
+
 		ifeq ($(TS_SP_FW_CONFIG),1)
-		DTC_CPPFLAGS	+=	-DTS_SP_FW_CONFIG
+			DTC_CPPFLAGS	+=	-DTS_SP_FW_CONFIG
 		endif
 
 		ifneq ($(ARM_BL2_SP_LIST_DTS),)
@@ -596,14 +571,14 @@
 ifeq (${SUPPORT_STACK_MEMTAG},yes)
     ifdef mem_tag_arch_support
         # Check for armclang and clang compilers
-        ifneq ( ,$(filter $(notdir $(CC)),armclang clang))
+        ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
         # Add "memtag" architecture feature modifier if not specified
             ifeq ( ,$(findstring memtag,$(arch-features)))
                 arch-features	:=	$(arch-features)+memtag
             endif	# memtag
-            ifeq ($(notdir $(CC)),armclang)
+            ifeq ($($(ARCH)-cc-id),arm-clang)
                 TF_CFLAGS	+=	-mmemtag-stack
-            else ifeq ($(notdir $(CC)),clang)
+            else ifeq ($($(ARCH)-cc-id),llvm-clang)
                 TF_CFLAGS	+=	-fsanitize=memtag
             endif	# armclang
         endif
@@ -717,12 +692,12 @@
 PIE_FOUND		:=	$(findstring --enable-default-pie,${GCC_V_OUTPUT})
 ifneq ($(PIE_FOUND),)
 	TF_CFLAGS	+=	-fno-PIE
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
 	TF_LDFLAGS	+=	-no-pie
 endif
 endif #(PIE_FOUND)
 
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
 	PIE_LDFLAGS	+=	-Wl,-pie -Wl,--no-dynamic-linker
 else
 	PIE_LDFLAGS	+=	-pie --no-dynamic-linker
@@ -1449,7 +1424,7 @@
         $(eval $(call add_define,DYN_DISABLE_AUTH))
 endif
 
-ifneq ($(findstring armlink,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),arm-link)
         $(eval $(call add_define,USE_ARM_LINK))
 endif
 
@@ -1481,7 +1456,7 @@
 
 ifeq (${ERROR_DEPRECATED},0)
 # Check if deprecated declarations and cpp warnings should be treated as error or not.
-ifneq ($(findstring clang,$(notdir $(CC))),)
+ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
     CPPFLAGS		+= 	-Wno-error=deprecated-declarations
 else
     CPPFLAGS		+= 	-Wno-error=deprecated-declarations -Wno-error=cpp
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index 53946ab..dbb646b 100644
--- a/bl1/bl1.mk
+++ b/bl1/bl1.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -29,9 +29,9 @@
 BL1_SOURCES		+=	lib/pmf/pmf_main.c
 endif
 
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
         BL1_LDFLAGS	+=	-Wl,--sort-section=alignment
-else ifneq ($(findstring ld,$(notdir $(LD))),)
+else ifneq ($(filter llvm-lld gnu-ld,$($(ARCH)-ld-id)),)
         BL1_LDFLAGS	+=	--sort-section=alignment
 endif
 
diff --git a/bl2/bl2.mk b/bl2/bl2.mk
index b70a3fb..850d826 100644
--- a/bl2/bl2.mk
+++ b/bl2/bl2.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -15,9 +15,9 @@
 BL2_SOURCES		+=	common/aarch64/early_exceptions.S
 endif
 
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
         BL2_LDFLAGS	+=	-Wl,--sort-section=alignment
-else ifneq ($(findstring ld,$(notdir $(LD))),)
+else ifneq ($(filter llvm-lld gnu-ld,$($(ARCH)-ld-id)),)
         BL2_LDFLAGS	+=	--sort-section=alignment
 endif
 
@@ -52,4 +52,4 @@
 
 ifeq (${ENABLE_PMF},1)
 BL2_SOURCES		+=	lib/pmf/pmf_main.c
-endif
\ No newline at end of file
+endif
diff --git a/bl2u/bl2u.mk b/bl2u/bl2u.mk
index 9fe20f5..a4051ec 100644
--- a/bl2u/bl2u.mk
+++ b/bl2u/bl2u.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -14,8 +14,8 @@
 
 BL2U_DEFAULT_LINKER_SCRIPT_SOURCE := bl2u/bl2u.ld.S
 
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
         BL2U_LDFLAGS	+=	-Wl,--sort-section=alignment
-else ifneq ($(findstring ld,$(notdir $(LD))),)
+else ifneq ($(filter llvm-lld gnu-ld,$($(ARCH)-ld-id)),)
         BL2U_LDFLAGS	+=	--sort-section=alignment
 endif
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 9959a3e..cd61d01 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -167,9 +167,9 @@
 
 BL31_DEFAULT_LINKER_SCRIPT_SOURCE := bl31/bl31.ld.S
 
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
         BL31_LDFLAGS	+=	-Wl,--sort-section=alignment
-else ifneq ($(findstring ld,$(notdir $(LD))),)
+else ifneq ($(filter llvm-lld gnu-ld,$($(ARCH)-ld-id)),)
         BL31_LDFLAGS	+=	--sort-section=alignment
 endif
 
diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk
index 065468c..427e39b 100644
--- a/bl32/sp_min/sp_min.mk
+++ b/bl32/sp_min/sp_min.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -57,9 +57,9 @@
 
 BL32_DEFAULT_LINKER_SCRIPT_SOURCE := bl32/sp_min/sp_min.ld.S
 
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
         BL32_LDFLAGS	+=	-Wl,--sort-section=alignment
-else ifneq ($(findstring ld,$(notdir $(LD))),)
+else ifneq ($(filter llvm-lld gnu-ld,$($(ARCH)-ld-id)),)
         BL32_LDFLAGS	+=	--sort-section=alignment
 endif
 
diff --git a/bl32/tsp/tsp.mk b/bl32/tsp/tsp.mk
index 4c18131..6d8f74b 100644
--- a/bl32/tsp/tsp.mk
+++ b/bl32/tsp/tsp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -24,9 +24,9 @@
 
 BL32_DEFAULT_LINKER_SCRIPT_SOURCE := bl32/tsp/tsp.ld.S
 
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
         BL32_LDFLAGS	+=	-Wl,--sort-section=alignment
-else ifneq ($(findstring ld,$(notdir $(LD))),)
+else ifneq ($(filter llvm-lld gnu-ld,$($(ARCH)-ld-id)),)
         BL32_LDFLAGS	+=	--sort-section=alignment
 endif
 
diff --git a/docs/components/sdei.rst b/docs/components/sdei.rst
index 60259c8..309375f 100644
--- a/docs/components/sdei.rst
+++ b/docs/components/sdei.rst
@@ -354,7 +354,51 @@
 
 --------------
 
-*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.*
+Security Considerations
+-----------------------
+
+SDEI introduces concept of providing software based non-maskable interrupts to
+Hypervisor/OS. In doing so, it modifies the priority scheme defined by Interrupt
+controllers and relies on Non-Secure clients, Hypervisor or OS, to create/manage
+high priority events.
+
+Considering a Non-secure client is involved in SDEI state management, there exists
+some security considerations which needs to be taken care of in both client and EL3
+when using SDEI. Few of them are mentioned below.
+
+Bound events
+~~~~~~~~~~~~
+
+A bound event is an SDEI event that corresponds to a client interrupt.
+The binding of event is done using ``SDEI_INTERRUPT_BIND`` SMC call to associate
+an SDEI event with a client interrupt. There is a possibility that a rogue
+client can request an invalid interrupt to be bound. This may potentially
+cause out-of-bound memory read.
+
+Even though TF-A implementation has checks to ensure that interrupt ID passed
+by client is architecturally valid, Non-secure client should also ensure the
+validity of interrupts.
+
+Recurring events
+~~~~~~~~~~~~~~~~
+
+For a given event source, if the events are generated continuously, then NS client
+may be unusable. To mitigate against this, the Non-secure client must have
+mechanism in place to remove such interrupt source from the system.
+
+One of the examples is a memory region which continuously generates RAS errors.
+This may result in unusable Non-secure client.
+
+Dispatched events
+~~~~~~~~~~~~~~~~~
+
+For a dispatched event, it is the client's responsibility to ensure that the
+handling finishes in finite time and notify the dispatcher through
+``SDEI_EVENT_COMPLETE`` or ``SDEI_EVENT_COMPLETE_AND_RESUME``. If the client
+fails to complete the event handling, it might result in ``UNPREDICTABLE`` behavior
+in the client and potentially end up in unusable PE.
+
+*Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.*
 
 .. rubric:: Footnotes
 
diff --git a/docs/getting_started/build-internals.rst b/docs/getting_started/build-internals.rst
index 390c367..c43f4e9 100644
--- a/docs/getting_started/build-internals.rst
+++ b/docs/getting_started/build-internals.rst
@@ -19,3 +19,11 @@
   ``HANDLE_EA_EL3_FIRST_NS`` is set. Currently only NS world routes EA to EL3 but
   in future when Secure/Realm wants to use FFH then they can introduce new macros
   which will enable this option implicitly.
+
+-  ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in
+   tb_fw_config device tree. This flag is defined only when
+   ``ARM_SPMC_MANIFEST_DTS`` manifest file name contains pattern optee_sp.
+
+-  ``TRUSTY_SP_FW_CONFIG``: DTC build flag to include Trusty as SP in
+   tb_fw_config device tree. This flag is defined only when
+   ``ARM_SPMC_MANIFEST_DTS`` manifest file name contains pattern trusty_sp.
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 16522bd..37545ce 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -740,10 +740,6 @@
    1 (do save and restore). 0 is the default. An SPD may set this to 1 if it
    wants the timer registers to be saved and restored.
 
--  ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in
-   tb_fw_config device tree. This flag is defined only when
-   ``ARM_SPMC_MANIFEST_DTS`` manifest file name contains pattern optee_sp.
-
 -  ``OVERRIDE_LIBC``: This option allows platforms to override the default libc
    for the BL image. It can be either 0 (include) or 1 (remove). The default
    value is 0.
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index 700020f..55cefe1 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -14,7 +14,6 @@
 .. note::
    The FVP models used are Version 11.22 Build 14, unless otherwise stated.
 
--  ``Foundation_Platform``
 -  ``FVP_Base_AEMv8A-AEMv8A-AEMv8A-AEMv8A-CCN502`` (Version 11.17/21)
 -  ``FVP_Base_AEMv8A-GIC600AE`` (Version 11.17/21)
 -  ``FVP_Base_AEMvA``
@@ -52,7 +51,7 @@
 -  ``FVP_Morello`` (Version 0.11/33)
 -  ``FVP_RD_V1``
 -  ``FVP_TC1``
--  ``FVP_TC2`` (Version 11.20/24)
+-  ``FVP_TC2`` (Version 11.23/17)
 
 The latest version of the AArch32 build of TF-A has been tested on the
 following Arm FVPs without shifted affinities, and that do not support threaded
@@ -630,7 +629,7 @@
 
 --------------
 
-*Copyright (c) 2019-2023, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
 
 .. _FW_CONFIG for FVP: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_fw_config.dts
 .. _Arm's website: `FVP models`_
diff --git a/docs/threat_model/firmware_threat_model/threat_model.rst b/docs/threat_model/firmware_threat_model/threat_model.rst
index d93547f..63bdc8a 100644
--- a/docs/threat_model/firmware_threat_model/threat_model.rst
+++ b/docs/threat_model/firmware_threat_model/threat_model.rst
@@ -163,6 +163,15 @@
   ion beam (FIB) workstation or decapsulate the chip using chemicals) is
   considered out-of-scope.
 
+  Certain non-invasive physical attacks that do not need modifications to the
+  chip, notably those like Power Analysis Attacks, are out-of-scope. Power
+  analysis side-channel attacks represent a category of security threats that
+  capitalize on information leakage through a device's power consumption during
+  its normal operation. These attacks leverage the correlation between a
+  device's power usage and its internal data processing activities. This
+  correlation provides attackers with the means to extract sensitive
+  information, including cryptographic keys.
+
 Threat Types
 ============
 
diff --git a/drivers/arm/css/scp/css_sds.c b/drivers/arm/css/scp/css_sds.c
index e42ee10..d9965c6 100644
--- a/drivers/arm/css/scp/css_sds.c
+++ b/drivers/arm/css/scp/css_sds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,7 +20,7 @@
 	int ret;
 	unsigned int image_offset, image_flags;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SCP SDS initialization failed\n");
 		panic();
@@ -28,13 +28,15 @@
 
 	VERBOSE("Writing SCP image metadata\n");
 	image_offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE;
-	ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_ADDR_OFFSET,
+	ret = sds_struct_write(SDS_SCP_AP_REGION_ID,
+			SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_ADDR_OFFSET,
 			&image_offset, SDS_SCP_IMG_ADDR_SIZE,
 			SDS_ACCESS_MODE_NON_CACHED);
 	if (ret != SDS_OK)
 		goto sds_fail;
 
-	ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_SIZE_OFFSET,
+	ret = sds_struct_write(SDS_SCP_AP_REGION_ID,
+			SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_SIZE_OFFSET,
 			&image_size, SDS_SCP_IMG_SIZE_SIZE,
 			SDS_ACCESS_MODE_NON_CACHED);
 	if (ret != SDS_OK)
@@ -42,7 +44,8 @@
 
 	VERBOSE("Marking SCP image metadata as valid\n");
 	image_flags = SDS_SCP_IMG_VALID_FLAG_BIT;
-	ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_FLAG_OFFSET,
+	ret = sds_struct_write(SDS_SCP_AP_REGION_ID,
+			SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_FLAG_OFFSET,
 			&image_flags, SDS_SCP_IMG_FLAG_SIZE,
 			SDS_ACCESS_MODE_NON_CACHED);
 	if (ret != SDS_OK)
@@ -68,7 +71,8 @@
 
 	/* Wait for the SCP RAM Firmware to complete its initialization process */
 	while (retry > 0) {
-		ret = sds_struct_read(SDS_FEATURE_AVAIL_STRUCT_ID, 0,
+		ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+				SDS_FEATURE_AVAIL_STRUCT_ID, 0,
 				&scp_feature_availability_flags,
 				SDS_FEATURE_AVAIL_SIZE,
 				SDS_ACCESS_MODE_NON_CACHED);
diff --git a/drivers/arm/css/sds/sds.c b/drivers/arm/css/sds/sds.c
index 1fb196c..a5e6389 100644
--- a/drivers/arm/css/sds/sds.c
+++ b/drivers/arm/css/sds/sds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,40 +15,39 @@
 
 #include "sds_private.h"
 
-/*
- * Variables used to track and maintain the state of the memory region reserved
- * for usage by the SDS framework.
- */
+/* Array of SDS memory region descriptions */
+static sds_region_desc_t *sds_regions;
 
-/* Pointer to the base of the SDS memory region */
-static uintptr_t sds_mem_base;
-
-/* Size of the SDS memory region in bytes */
-static size_t sds_mem_size;
+/* Total count of SDS memory regions */
+static unsigned int sds_region_cnt;
 
 /*
  * Perform some non-exhaustive tests to determine whether any of the fields
  * within a Structure Header contain obviously invalid data.
  * Returns SDS_OK on success, SDS_ERR_FAIL on error.
  */
-static int sds_struct_is_valid(uintptr_t header)
+static int sds_struct_is_valid(unsigned int region_id, uintptr_t header)
 {
 	size_t struct_size = GET_SDS_HEADER_STRUCT_SIZE(header);
 
 	/* Zero is not a valid identifier */
-	if (GET_SDS_HEADER_ID(header) == 0)
+	if (GET_SDS_HEADER_ID(header) == 0) {
 		return SDS_ERR_FAIL;
+	}
 
 	/* Check SDS Schema version */
-	if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION)
+	if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION) {
 		return SDS_ERR_FAIL;
+	}
 
 	/* The SDS Structure sizes have to be multiple of 8 */
-	if ((struct_size == 0) || ((struct_size % 8) != 0))
+	if ((struct_size == 0) || ((struct_size % 8) != 0)) {
 		return SDS_ERR_FAIL;
+	}
 
-	if (struct_size > sds_mem_size)
+	if (struct_size > sds_regions[region_id].size) {
 		return SDS_ERR_FAIL;
+	}
 
 	return SDS_OK;
 }
@@ -57,10 +56,11 @@
  * Validate the SDS structure headers.
  * Returns SDS_OK on success, SDS_ERR_FAIL on error.
  */
-static int validate_sds_struct_headers(void)
+static int validate_sds_struct_headers(unsigned int region_id)
 {
 	unsigned int i, structure_count;
 	uintptr_t header;
+	uintptr_t sds_mem_base = sds_regions[region_id].base;
 
 	structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);
 
@@ -71,7 +71,7 @@
 
 	/* Iterate over structure headers and validate each one */
 	for (i = 0; i < structure_count; i++) {
-		if (sds_struct_is_valid(header) != SDS_OK) {
+		if (sds_struct_is_valid(region_id, header) != SDS_OK) {
 			WARN("SDS: Invalid structure header detected\n");
 			return SDS_ERR_FAIL;
 		}
@@ -84,10 +84,12 @@
  * Get the structure header pointer corresponding to the structure ID.
  * Returns SDS_OK on success, SDS_ERR_STRUCT_NOT_FOUND on error.
  */
-static int get_struct_header(uint32_t structure_id, struct_header_t **header)
+static int get_struct_header(unsigned int region_id, uint32_t structure_id,
+			struct_header_t **header)
 {
 	unsigned int i, structure_count;
 	uintptr_t current_header;
+	uintptr_t sds_mem_base = sds_regions[region_id].base;
 
 	assert(header);
 
@@ -116,12 +118,14 @@
  * Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND
  * if not found.
  */
-int sds_struct_exists(unsigned int structure_id)
+int sds_struct_exists(unsigned int region_id, unsigned int structure_id)
 {
 	struct_header_t *header = NULL;
 	int ret;
 
-	ret = get_struct_header(structure_id, &header);
+	assert(region_id < sds_region_cnt);
+
+	ret = get_struct_header(region_id, structure_id, &header);
 	if (ret == SDS_OK) {
 		assert(header);
 	}
@@ -136,18 +140,21 @@
  * The `data` is the pointer to store the read data of size specified by `size`.
  * Returns SDS_OK on success or corresponding error codes on failure.
  */
-int sds_struct_read(uint32_t structure_id, unsigned int fld_off,
-		void *data, size_t size, sds_access_mode_t mode)
+int sds_struct_read(unsigned int region_id, uint32_t structure_id,
+		unsigned int fld_off, void *data, size_t size,
+		sds_access_mode_t mode)
 {
 	int status;
 	uintptr_t field_base;
 	struct_header_t *header = NULL;
 
+	assert(region_id < sds_region_cnt);
+
 	if (!data)
 		return SDS_ERR_INVALID_PARAMS;
 
 	/* Check if a structure with this ID exists */
-	status = get_struct_header(structure_id, &header);
+	status = get_struct_header(region_id, structure_id, &header);
 	if (status != SDS_OK)
 		return status;
 
@@ -182,18 +189,21 @@
  * The `data` is the pointer to data of size specified by `size`.
  * Returns SDS_OK on success or corresponding error codes on failure.
  */
-int sds_struct_write(uint32_t structure_id, unsigned int fld_off,
-		void *data, size_t size, sds_access_mode_t mode)
+int sds_struct_write(unsigned int region_id, uint32_t structure_id,
+		unsigned int fld_off, void *data, size_t size,
+		sds_access_mode_t mode)
 {
 	int status;
 	uintptr_t field_base;
 	struct_header_t *header = NULL;
 
+	assert(region_id < sds_region_cnt);
+
 	if (!data)
 		return SDS_ERR_INVALID_PARAMS;
 
 	/* Check if a structure with this ID exists */
-	status = get_struct_header(structure_id, &header);
+	status = get_struct_header(region_id, structure_id, &header);
 	if (status != SDS_OK)
 		return status;
 
@@ -226,12 +236,18 @@
 
 /*
  * Initialize the SDS driver. Also verifies the SDS version and sanity of
- * the SDS structure headers.
+ * the SDS structure headers in the given SDS region.
  * Returns SDS_OK on success, SDS_ERR_FAIL on error.
  */
-int sds_init(void)
+int sds_init(unsigned int region_id)
 {
-	sds_mem_base = (uintptr_t)PLAT_ARM_SDS_MEM_BASE;
+	if (sds_regions == NULL) {
+		sds_regions = plat_sds_get_regions(&sds_region_cnt);
+	}
+
+	assert(region_id < sds_region_cnt);
+
+	uintptr_t sds_mem_base = sds_regions[region_id].base;
 
 	if (!IS_SDS_REGION_VALID(sds_mem_base)) {
 		WARN("SDS: No valid SDS Memory Region found\n");
@@ -244,15 +260,16 @@
 		return SDS_ERR_FAIL;
 	}
 
-	sds_mem_size = GET_SDS_REGION_SIZE(sds_mem_base);
-	if (sds_mem_size > PLAT_ARM_SDS_MEM_SIZE_MAX) {
+	sds_regions[region_id].size = GET_SDS_REGION_SIZE(sds_mem_base);
+	if (sds_regions[region_id].size > PLAT_ARM_SDS_MEM_SIZE_MAX) {
 		WARN("SDS: SDS Memory Region exceeds size limit\n");
 		return SDS_ERR_FAIL;
 	}
 
-	INFO("SDS: Detected SDS Memory Region (%zu bytes)\n", sds_mem_size);
+	INFO("SDS: Detected SDS Memory Region (%zu bytes)\n",
+		sds_regions[region_id].size);
 
-	if (validate_sds_struct_headers() != SDS_OK)
+	if (validate_sds_struct_headers(region_id) != SDS_OK)
 		return SDS_ERR_FAIL;
 
 	return SDS_OK;
diff --git a/drivers/arm/rss/rss_comms.c b/drivers/arm/rss/rss_comms.c
index a905b88..332105f 100644
--- a/drivers/arm/rss/rss_comms.c
+++ b/drivers/arm/rss/rss_comms.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -84,8 +84,8 @@
 	psa_status_t return_val;
 	size_t idx;
 
-	if (type > INT16_MAX || type < INT16_MIN || in_len > PSA_MAX_IOVEC
-	    || out_len > PSA_MAX_IOVEC) {
+	if (type > PSA_CALL_TYPE_MAX || type < PSA_CALL_TYPE_MIN ||
+	    in_len > PSA_MAX_IOVEC   || out_len > PSA_MAX_IOVEC) {
 		return PSA_ERROR_INVALID_ARGUMENT;
 	}
 
diff --git a/drivers/arm/rss/rss_comms_protocol_common.h b/drivers/arm/rss/rss_comms_protocol_common.h
new file mode 100644
index 0000000..177d636
--- /dev/null
+++ b/drivers/arm/rss/rss_comms_protocol_common.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Packing scheme of the control parameter
+ *
+ *  31           30-28   27    26-24  23-20   19     18-16   15-0
+ * +------------+-----+------+-------+-----+-------+-------+------+
+ * |            |     |      | invec |     |       | outvec| type |
+ * | Res        | Res | Res  | number| Res | Res   | number|      |
+ * +------------+-----+------+-------+-----+-------+-------+------+
+ *
+ * Res: Reserved.
+ */
+
+#ifndef RSS_COMMS_PROTOCOL_COMMON
+#define RSS_COMMS_PROTOCOL_COMMON
+
+#define TYPE_OFFSET	(0U)
+#define TYPE_MASK	(0xFFFFUL << TYPE_OFFSET)
+#define IN_LEN_OFFSET	(24U)
+#define IN_LEN_MASK	(0x7UL << IN_LEN_OFFSET)
+#define OUT_LEN_OFFSET	(16U)
+#define OUT_LEN_MASK	(0x7UL << OUT_LEN_OFFSET)
+
+#define PARAM_PACK(type, in_len, out_len)			   \
+	(((((uint32_t)(type)) << TYPE_OFFSET) & TYPE_MASK)	 | \
+	 ((((uint32_t)(in_len)) << IN_LEN_OFFSET) & IN_LEN_MASK) | \
+	 ((((uint32_t)(out_len)) << OUT_LEN_OFFSET) & OUT_LEN_MASK))
+
+#endif /* RSS_COMMS_PROTOCOL_COMMON */
diff --git a/drivers/arm/rss/rss_comms_protocol_embed.c b/drivers/arm/rss/rss_comms_protocol_embed.c
index c453258..05628cc 100644
--- a/drivers/arm/rss/rss_comms_protocol_embed.c
+++ b/drivers/arm/rss/rss_comms_protocol_embed.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -9,20 +9,9 @@
 #include <string.h>
 
 #include <common/debug.h>
+#include "rss_comms_protocol_common.h"
 #include "rss_comms_protocol_embed.h"
 
-#define TYPE_OFFSET	(16U)
-#define TYPE_MASK	(0xFFFFUL << TYPE_OFFSET)
-#define IN_LEN_OFFSET	(8U)
-#define IN_LEN_MASK	(0xFFUL << IN_LEN_OFFSET)
-#define OUT_LEN_OFFSET	(0U)
-#define OUT_LEN_MASK	(0xFFUL << OUT_LEN_OFFSET)
-
-#define PARAM_PACK(type, in_len, out_len)			  \
-	(((((uint32_t)type) << TYPE_OFFSET) & TYPE_MASK)	| \
-	 ((((uint32_t)in_len) << IN_LEN_OFFSET) & IN_LEN_MASK)	| \
-	 ((((uint32_t)out_len) << OUT_LEN_OFFSET) & OUT_LEN_MASK))
-
 psa_status_t rss_protocol_embed_serialize_msg(psa_handle_t handle,
 					      int16_t type,
 					      const psa_invec *in_vec,
diff --git a/drivers/arm/rss/rss_comms_protocol_pointer_access.c b/drivers/arm/rss/rss_comms_protocol_pointer_access.c
index 5007b9d..3a10a98 100644
--- a/drivers/arm/rss/rss_comms_protocol_pointer_access.c
+++ b/drivers/arm/rss/rss_comms_protocol_pointer_access.c
@@ -1,25 +1,14 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
  */
 #include <assert.h>
 
+#include "rss_comms_protocol_common.h"
 #include "rss_comms_protocol_pointer_access.h"
 
-#define TYPE_OFFSET	(16U)
-#define TYPE_MASK	(0xFFFFUL << TYPE_OFFSET)
-#define IN_LEN_OFFSET	(8U)
-#define IN_LEN_MASK	(0xFFUL << IN_LEN_OFFSET)
-#define OUT_LEN_OFFSET	(0U)
-#define OUT_LEN_MASK	(0xFFUL << OUT_LEN_OFFSET)
-
-#define PARAM_PACK(type, in_len, out_len)			  \
-	(((((uint32_t)type) << TYPE_OFFSET) & TYPE_MASK)	| \
-	 ((((uint32_t)in_len) << IN_LEN_OFFSET) & IN_LEN_MASK)	| \
-	 ((((uint32_t)out_len) << OUT_LEN_OFFSET) & OUT_LEN_MASK))
-
 psa_status_t rss_protocol_pointer_access_serialize_msg(psa_handle_t handle,
 						       int16_t type,
 						       const psa_invec *in_vec,
diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c
index c60820d..555fe7f 100644
--- a/drivers/partition/partition.c
+++ b/drivers/partition/partition.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -94,9 +94,8 @@
  * If partition numbers could be found, check & update it.
  */
 static int load_gpt_header(uintptr_t image_handle, size_t header_offset,
-			   unsigned long long *part_lba)
+			   gpt_header_t *header)
 {
-	gpt_header_t header;
 	size_t bytes_read;
 	int result;
 	uint32_t header_crc, calc_crc;
@@ -107,7 +106,7 @@
 			header_offset);
 		return result;
 	}
-	result = io_read(image_handle, (uintptr_t)&header,
+	result = io_read(image_handle, (uintptr_t)header,
 			 sizeof(gpt_header_t), &bytes_read);
 	if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) {
 		VERBOSE("GPT header read error(%i) or read mismatch occurred,"
@@ -115,8 +114,8 @@
 			sizeof(gpt_header_t), bytes_read);
 		return result;
 	}
-	if (memcmp(header.signature, GPT_SIGNATURE,
-			   sizeof(header.signature)) != 0) {
+	if (memcmp(header->signature, GPT_SIGNATURE,
+			   sizeof(header->signature)) != 0) {
 		VERBOSE("GPT header signature failure\n");
 		return -EINVAL;
 	}
@@ -126,25 +125,24 @@
 	 * computed by setting this field to 0, and computing the
 	 * 32-bit CRC for HeaderSize bytes.
 	 */
-	header_crc = header.header_crc;
-	header.header_crc = 0U;
+	header_crc = header->header_crc;
+	header->header_crc = 0U;
 
-	calc_crc = tf_crc32(0U, (uint8_t *)&header, sizeof(gpt_header_t));
+	calc_crc = tf_crc32(0U, (uint8_t *)header, sizeof(gpt_header_t));
 	if (header_crc != calc_crc) {
 		ERROR("Invalid GPT Header CRC: Expected 0x%x but got 0x%x.\n",
 		      header_crc, calc_crc);
 		return -EINVAL;
 	}
 
-	header.header_crc = header_crc;
+	header->header_crc = header_crc;
 
 	/* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */
-	list.entry_count = header.list_num;
+	list.entry_count = header->list_num;
 	if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) {
 		list.entry_count = PLAT_PARTITION_MAX_ENTRIES;
 	}
 
-	*part_lba = header.part_lba;
 	return 0;
 }
 
@@ -231,12 +229,13 @@
  * Retrieve each entry in the partition table, parse the data from each
  * entry and store them in the list of partition table entries.
  */
-static int load_partition_gpt(uintptr_t image_handle,
-			      unsigned long long part_lba)
+static int load_partition_gpt(uintptr_t image_handle, gpt_header_t header)
 {
-	const signed long long gpt_entry_offset = LBA(part_lba);
+	const signed long long gpt_entry_offset = LBA(header.part_lba);
 	gpt_entry_t entry;
-	int result, i;
+	int result;
+	unsigned int i;
+	uint32_t calc_crc = 0U;
 
 	result = io_seek(image_handle, IO_SEEK_SET, gpt_entry_offset);
 	if (result != 0) {
@@ -245,23 +244,36 @@
 		return result;
 	}
 
-	for (i = 0; i < list.entry_count; i++) {
+	for (i = 0; i < (unsigned int)list.entry_count; i++) {
 		result = load_gpt_entry(image_handle, &entry);
 		if (result != 0) {
-			VERBOSE("Failed to load gpt entry data(%i) error is (%i)\n",
+			VERBOSE("Failed to load gpt entry data(%u) error is (%i)\n",
 				i, result);
 			return result;
 		}
 
 		result = parse_gpt_entry(&entry, &list.list[i]);
 		if (result != 0) {
+			result = io_seek(image_handle, IO_SEEK_SET,
+					(gpt_entry_offset + (i * sizeof(gpt_entry_t))));
+			if (result != 0) {
+				VERBOSE("Failed to seek (%i)\n", result);
+				return result;
+			}
 			break;
 		}
+
+		/*
+		 * Calculate CRC of Partition entry array to compare with CRC
+		 * value in header
+		 */
+		calc_crc = tf_crc32(calc_crc, (uint8_t *)&entry, sizeof(gpt_entry_t));
 	}
 	if (i == 0) {
 		VERBOSE("No Valid GPT Entries found\n");
 		return -EINVAL;
 	}
+
 	/*
 	 * Only records the valid partition number that is loaded from
 	 * partition table.
@@ -269,6 +281,29 @@
 	list.entry_count = i;
 	dump_entries(list.entry_count);
 
+	/*
+	 * If there are less valid entries than the possible number of entries
+	 * from the header, continue to load the partition entry table to
+	 * calculate the full CRC in order to check against the partition CRC
+	 * from the header for validation.
+	 */
+	for (; i < header.list_num; i++) {
+		result = load_gpt_entry(image_handle, &entry);
+		if (result != 0) {
+			VERBOSE("Failed to load gpt entry data(%u) error is (%i)\n",
+				i, result);
+			return result;
+		}
+
+		calc_crc = tf_crc32(calc_crc, (uint8_t *)&entry, sizeof(gpt_entry_t));
+	}
+
+	if (header.part_crc != calc_crc) {
+		ERROR("Invalid GPT Partition Array Entry CRC: Expected 0x%x"
+				" but got 0x%x.\n", header.part_crc, calc_crc);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -279,7 +314,7 @@
 static int load_backup_gpt(unsigned int image_id, unsigned int sector_nums)
 {
 	int result;
-	unsigned long long part_lba = 0;
+	gpt_header_t header;
 	size_t gpt_header_offset;
 	uintptr_t dev_handle, image_spec, image_handle;
 	io_block_spec_t *block_spec;
@@ -316,8 +351,8 @@
 	INFO("Trying to retrieve back-up GPT header\n");
 	/* Last block is backup-GPT header, after the end of GPT entries */
 	gpt_header_offset = LBA(part_num_entries);
-	result = load_gpt_header(image_handle, gpt_header_offset, &part_lba);
-	if ((result != 0) || (part_lba == 0)) {
+	result = load_gpt_header(image_handle, gpt_header_offset, &header);
+	if ((result != 0) || (header.part_lba == 0)) {
 		ERROR("Failed to retrieve Backup GPT header,"
 		      "Partition maybe corrupted\n");
 		goto out;
@@ -327,7 +362,8 @@
 	 * Note we mapped last 33 blocks(LBA-33), first block here starts with
 	 * entries while last block was header.
 	 */
-	result = load_partition_gpt(image_handle, 0);
+	header.part_lba = 0;
+	result = load_partition_gpt(image_handle, header);
 
 out:
 	io_close(image_handle);
@@ -342,19 +378,19 @@
 static int load_primary_gpt(uintptr_t image_handle, unsigned int first_lba)
 {
 	int result;
-	unsigned long long part_lba;
 	size_t gpt_header_offset;
+	gpt_header_t header;
 
 	/* Try to load Primary GPT header from LBA1 */
 	gpt_header_offset = LBA(first_lba);
-	result = load_gpt_header(image_handle, gpt_header_offset, &part_lba);
-	if ((result != 0) || (part_lba == 0)) {
+	result = load_gpt_header(image_handle, gpt_header_offset, &header);
+	if ((result != 0) || (header.part_lba == 0)) {
 		VERBOSE("Failed to retrieve Primary GPT header,"
 			"trying to retrieve back-up GPT header\n");
 		return result;
 	}
 
-	return load_partition_gpt(image_handle, part_lba);
+	return load_partition_gpt(image_handle, header);
 }
 
 /*
diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c
index bf6c3ee..32cecff 100644
--- a/drivers/st/i2c/stm32_i2c.c
+++ b/drivers/st/i2c/stm32_i2c.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2024, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,17 +8,17 @@
 #include <stdbool.h>
 #include <stdlib.h>
 
-#include <libfdt.h>
-
-#include <platform_def.h>
-
 #include <common/debug.h>
+#include <common/fdt_wrappers.h>
 #include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32_i2c.h>
 #include <lib/mmio.h>
 #include <lib/utils.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
 
 /* STM32 I2C registers offsets */
 #define I2C_CR1			0x00U
@@ -97,40 +97,29 @@
 int stm32_i2c_get_setup_from_fdt(void *fdt, int node,
 				 struct stm32_i2c_init_s *init)
 {
-	const fdt32_t *cuint;
+	uint32_t read_val;
 
-	cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL);
-	if (cuint == NULL) {
-		init->rise_time = STM32_I2C_RISE_TIME_DEFAULT;
-	} else {
-		init->rise_time = fdt32_to_cpu(*cuint);
-	}
+	init->rise_time = fdt_read_uint32_default(fdt, node,
+						  "i2c-scl-rising-time-ns",
+						  STM32_I2C_RISE_TIME_DEFAULT);
 
-	cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL);
-	if (cuint == NULL) {
-		init->fall_time = STM32_I2C_FALL_TIME_DEFAULT;
-	} else {
-		init->fall_time = fdt32_to_cpu(*cuint);
-	}
+	init->fall_time = fdt_read_uint32_default(fdt, node,
+						  "i2c-scl-falling-time-ns",
+						  STM32_I2C_FALL_TIME_DEFAULT);
 
-	cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
-	if (cuint == NULL) {
-		init->speed_mode = STM32_I2C_SPEED_DEFAULT;
-	} else {
-		switch (fdt32_to_cpu(*cuint)) {
-		case STANDARD_RATE:
-			init->speed_mode = I2C_SPEED_STANDARD;
-			break;
-		case FAST_RATE:
-			init->speed_mode = I2C_SPEED_FAST;
-			break;
-		case FAST_PLUS_RATE:
-			init->speed_mode = I2C_SPEED_FAST_PLUS;
-			break;
-		default:
-			init->speed_mode = STM32_I2C_SPEED_DEFAULT;
-			break;
-		}
+	read_val = fdt_read_uint32_default(fdt, node, "clock-frequency",
+					   STANDARD_RATE);
+	switch (read_val) {
+	case FAST_PLUS_RATE:
+		init->speed_mode = I2C_SPEED_FAST_PLUS;
+		break;
+	case FAST_RATE:
+		init->speed_mode = I2C_SPEED_FAST;
+		break;
+	case STANDARD_RATE:
+	default:
+		init->speed_mode = I2C_SPEED_STANDARD;
+		break;
 	}
 
 	return dt_set_pinctrl_config(node);
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 19f894f..33ceb26 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -966,8 +966,7 @@
 {
 	uint8_t desc_buf[DESC_DEVICE_MAX_SIZE];
 
-	ufs_query(QUERY_READ_DESC, DESC_TYPE_DEVICE, 0, 0,
-				(uintptr_t)desc_buf, DESC_DEVICE_MAX_SIZE);
+	ufs_read_desc(DESC_TYPE_DEVICE, 0, (uintptr_t)desc_buf, DESC_DEVICE_MAX_SIZE);
 
 	/*
 	 * getting vendor (manufacturerID) and Bank Index in big endian
diff --git a/fdts/tc.dts b/fdts/tc.dts
index 4f27589..63f6c3d 100644
--- a/fdts/tc.dts
+++ b/fdts/tc.dts
@@ -1,11 +1,19 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 /dts-v1/;
 
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "platform_def.h"
+#include "tc_vers.dtsi"
+#if TARGET_FLAVOUR_FVP
+#include "tc_fvp.dtsi"
+#endif /* TARGET_FLAVOUR_FVP */
+
 / {
 	compatible = "arm,tc";
 	interrupt-parent = <&gic>;
@@ -13,11 +21,23 @@
 	#size-cells = <2>;
 
 	aliases {
-		serial0 = &soc_uart0;
+		serial0 = &os_uart;
 	};
 
 	chosen {
-		stdout-path = "serial0:115200n8";
+		stdout-path = STDOUT_PATH;
+		/*
+		 * Add some dummy entropy for Linux so it
+		 * doesn't delay the boot waiting for it.
+		 */
+		rng-seed = <0x01 0x02 0x04 0x05 0x06 0x07 0x08 \
+			    0x01 0x02 0x04 0x05 0x06 0x07 0x08 \
+			    0x01 0x02 0x04 0x05 0x06 0x07 0x08 \
+			    0x01 0x02 0x04 0x05 0x06 0x07 0x08 \
+			    0x01 0x02 0x04 0x05 0x06 0x07 0x08 \
+			    0x01 0x02 0x04 0x05 0x06 0x07 0x08 \
+			    0x01 0x02 0x04 0x05 0x06 0x07 0x08 \
+			    0x01 0x02 0x04 0x05 0x06 0x07 0x08 >;
 	};
 
 	cpus {
@@ -50,6 +70,26 @@
 				core7 {
 					cpu = <&CPU7>;
 				};
+#if TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2
+				core8 {
+					cpu = <&CPU8>;
+				};
+				core9 {
+					cpu = <&CPU9>;
+				};
+				core10 {
+					cpu = <&CPU10>;
+				};
+				core11 {
+					cpu = <&CPU11>;
+				};
+				core12 {
+					cpu = <&CPU12>;
+				};
+				core13 {
+					cpu = <&CPU13>;
+				};
+#endif /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2 */
 			};
 		};
 
@@ -58,7 +98,7 @@
 		 * These values may be inaccurate.
 		 */
 		idle-states {
-			entry-method = "arm,psci";
+			entry-method = "psci";
 
 			CPU_SLEEP_0: cpu-sleep-0 {
 				compatible = "arm,idle-state";
@@ -85,19 +125,16 @@
 
 				mpmm_gear0: counter@0 {
 					reg = <0>;
-
 					enable-at-el3;
 				};
 
 				mpmm_gear1: counter@1 {
 					reg = <1>;
-
 					enable-at-el3;
 				};
 
 				mpmm_gear2: counter@2 {
 					reg = <2>;
-
 					enable-at-el3;
 				};
 			};
@@ -110,7 +147,7 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			capacity-dmips-mhz = <406>;
+			capacity-dmips-mhz = <LIT_CAPACITY>;
 			amu = <&amu>;
 			supports-mpmm;
 		};
@@ -122,7 +159,7 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			capacity-dmips-mhz = <406>;
+			capacity-dmips-mhz = <LIT_CAPACITY>;
 			amu = <&amu>;
 			supports-mpmm;
 		};
@@ -132,9 +169,14 @@
 			compatible = "arm,armv8";
 			reg = <0x200>;
 			enable-method = "psci";
-			clocks = <&scmi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			capacity-dmips-mhz = <406>;
+#if TARGET_PLATFORM <= 2
+			clocks = <&scmi_dvfs 0>;
+			capacity-dmips-mhz = <LIT_CAPACITY>;
+#elif TARGET_PLATFORM == 3
+			clocks = <&scmi_dvfs 1>;
+			capacity-dmips-mhz = <MID_CAPACITY>;
+#endif /* TARGET_PLATFORM == 3 */
 			amu = <&amu>;
 			supports-mpmm;
 		};
@@ -144,9 +186,14 @@
 			compatible = "arm,armv8";
 			reg = <0x300>;
 			enable-method = "psci";
-			clocks = <&scmi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			capacity-dmips-mhz = <406>;
+#if TARGET_PLATFORM <= 2
+			clocks = <&scmi_dvfs 0>;
+			capacity-dmips-mhz = <LIT_CAPACITY>;
+#elif TARGET_PLATFORM == 3
+			clocks = <&scmi_dvfs 1>;
+			capacity-dmips-mhz = <MID_CAPACITY>;
+#endif /* TARGET_PLATFORM == 3 */
 			amu = <&amu>;
 			supports-mpmm;
 		};
@@ -158,7 +205,7 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			capacity-dmips-mhz = <912>;
+			capacity-dmips-mhz = <MID_CAPACITY>;
 			amu = <&amu>;
 			supports-mpmm;
 		};
@@ -170,7 +217,7 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			capacity-dmips-mhz = <912>;
+			capacity-dmips-mhz = <MID_CAPACITY>;
 			amu = <&amu>;
 			supports-mpmm;
 		};
@@ -180,9 +227,14 @@
 			compatible = "arm,armv8";
 			reg = <0x600>;
 			enable-method = "psci";
-			clocks = <&scmi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			capacity-dmips-mhz = <912>;
+#if TARGET_PLATFORM <= 2
+			clocks = <&scmi_dvfs 1>;
+			capacity-dmips-mhz = <MID_CAPACITY>;
+#elif TARGET_PLATFORM == 3
+			clocks = <&scmi_dvfs 2>;
+			capacity-dmips-mhz = <BIG_CAPACITY>;
+#endif /* TARGET_PLATFORM == 3 */
 			amu = <&amu>;
 			supports-mpmm;
 		};
@@ -192,13 +244,85 @@
 			compatible = "arm,armv8";
 			reg = <0x700>;
 			enable-method = "psci";
-			clocks = <&scmi_dvfs 2>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			capacity-dmips-mhz = <1024>;
+#if TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2
+			clocks = <&scmi_dvfs 1>;
+			capacity-dmips-mhz = <MID_CAPACITY>;
+#else
+			clocks = <&scmi_dvfs 2>;
+			capacity-dmips-mhz = <BIG_CAPACITY>;
+#endif /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2 */
 			amu = <&amu>;
 			supports-mpmm;
 		};
 
+#if TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2
+		CPU8:cpu@800 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x800>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 1>;
+			capacity-dmips-mhz = <MID_CAPACITY>;
+			amu = <&amu>;
+			supports-mpmm;
+		};
+
+		CPU9:cpu@900 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x900>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 2>;
+			capacity-dmips-mhz = <BIG2_CAPACITY>;
+			amu = <&amu>;
+			supports-mpmm;
+		};
+
+		CPU10:cpu@A00 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0xA00>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 2>;
+			capacity-dmips-mhz = <BIG2_CAPACITY>;
+			amu = <&amu>;
+			supports-mpmm;
+		};
+
+		CPU11:cpu@B00 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0xB00>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 2>;
+			capacity-dmips-mhz = <BIG2_CAPACITY>;
+			amu = <&amu>;
+			supports-mpmm;
+		};
+
+		CPU12:cpu@C00 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0xC00>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 3>;
+			capacity-dmips-mhz = <BIG_CAPACITY>;
+			amu = <&amu>;
+			supports-mpmm;
+		};
+
+		CPU13:cpu@D00 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0xD00>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 3>;
+			capacity-dmips-mhz = <BIG_CAPACITY>;
+			amu = <&amu>;
+			supports-mpmm;
+		};
+#endif /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2 */
 	};
 
 	reserved-memory {
@@ -213,24 +337,48 @@
 			linux,cma-default;
 		};
 
-		optee@0xf8e00000 {
+		optee {
 			compatible = "restricted-dma-pool";
-			reg = <0x00000000 0xf8e00000 0 0x00200000>;
+			reg = <0x0 TC_NS_OPTEE_BASE 0x0 TC_NS_OPTEE_SIZE>;
+		};
+
+		fwu_mm {
+			reg = <0x0 TC_NS_FWU_BASE 0x0 TC_NS_FWU_SIZE>;
+			no-map;
 		};
 	};
 
+	memory {
+		device_type = "memory";
+		reg = <0x0 TC_NS_DRAM1_BASE 0x0 TC_NS_DRAM1_SIZE>,
+		      <HI(PLAT_ARM_DRAM2_BASE) LO(PLAT_ARM_DRAM2_BASE)
+		       HI(TC_NS_DRAM2_SIZE) LO(TC_NS_DRAM2_SIZE)>;
+	};
+
 	psci {
 		compatible = "arm,psci-1.0", "arm,psci-0.2";
 		method = "smc";
 	};
 
+	cpu-pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&CPU0>,  <&CPU1>,  <&CPU2>,  <&CPU3>,
+				     <&CPU4>,  <&CPU5>,  <&CPU6>,  <&CPU7>
+#if TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2
+				    ,<&CPU8>,  <&CPU9>,  <&CPU10>, <&CPU11>,
+				     <&CPU12>, <&CPU13>
+#endif /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2 */
+		;
+	};
+
 	sram: sram@6000000 {
 		compatible = "mmio-sram";
-		reg = <0x0 0x06000000 0x0 0x8000>;
+		reg = <0x0 PLAT_ARM_NSRAM_BASE 0x0 PLAT_ARM_NSRAM_SIZE>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
-		ranges = <0 0x0 0x06000000 0x8000>;
+		ranges = <0 0x0 PLAT_ARM_NSRAM_BASE PLAT_ARM_NSRAM_SIZE>;
 
 		cpu_scp_scmi_mem: scp-shmem@0 {
 			compatible = "arm,scmi-shmem";
@@ -238,22 +386,22 @@
 		};
 	};
 
-	mbox_db_rx: mhu@45010000 {
+	mbox_db_rx: mhu@MHU_RX_ADDR() {
 		compatible = "arm,mhuv2-rx","arm,primecell";
-		reg = <0x0 0x45010000 0x0 0x1000>;
-		clocks = <&soc_refclk100mhz>;
+		reg = <0x0 MHU_RX_ADDR(0x) 0x0 0x1000>;
+		clocks = <&soc_refclk>;
 		clock-names = "apb_pclk";
 		#mbox-cells = <2>;
-		interrupts = <0 317 4>;
+		interrupts = <GIC_SPI INT_MBOX_RX IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "mhu_rx";
 		mhu-protocol = "doorbell";
 		arm,mhuv2-protocols = <0 1>;
 	};
 
-	mbox_db_tx: mhu@45000000 {
+	mbox_db_tx: mhu@MHU_TX_ADDR() {
 		compatible = "arm,mhuv2-tx","arm,primecell";
-		reg = <0x0 0x45000000 0x0 0x1000>;
-		clocks = <&soc_refclk100mhz>;
+		reg = <0x0 MHU_TX_ADDR(0x) 0x0 0x1000>;
+		clocks = <&soc_refclk>;
 		clock-names = "apb_pclk";
 		#mbox-cells = <2>;
 		interrupt-names = "mhu_tx";
@@ -261,12 +409,6 @@
 		arm,mhuv2-protocols = <0 1>;
 	};
 
-	cmn-pmu {
-		compatible = "arm,ci-700";
-		reg = <0x0 0x50000000 0x0 0x10000000>;
-		interrupts = <0x0 460 0x4>;
-	};
-
 	scmi {
 		compatible = "arm,scmi";
 		mbox-names = "tx", "rx";
@@ -275,6 +417,13 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+#if TC_SCMI_PD_CTRL_EN
+		scmi_devpd: protocol@11 {
+			reg = <0x11>;
+			#power-domain-cells = <1>;
+		};
+#endif /* TC_SCMI_PD_CTRL_EN */
+
 		scmi_dvfs: protocol@13 {
 			reg = <0x13>;
 			#clock-cells = <1>;
@@ -286,30 +435,30 @@
 		};
 	};
 
-	gic: interrupt-controller@2c010000 {
-		compatible = "arm,gic-600", "arm,gic-v3";
+	gic: interrupt-controller@GIC_CTRL_ADDR {
+		compatible = "arm,gic-v3";
 		#address-cells = <2>;
 		#interrupt-cells = <3>;
 		#size-cells = <2>;
 		ranges;
 		interrupt-controller;
 		reg = <0x0 0x30000000 0 0x10000>, /* GICD */
-		      <0x0 0x30080000 0 0x200000>; /* GICR */
-		interrupts = <0x1 0x9 0x4>;
+		      <0x0 0x30080000 0 GIC_GICR_OFFSET>; /* GICR */
+		interrupts = <GIC_PPI 0x9 IRQ_TYPE_LEVEL_LOW>;
 	};
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <0x1 13 0x8>,
-			     <0x1 14 0x8>,
-			     <0x1 11 0x8>,
-			     <0x1 10 0x8>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
 	};
 
-	soc_refclk100mhz: refclk100mhz {
+	soc_refclk: refclk {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
-		clock-frequency = <100000000>;
+		clock-frequency = <1000000000>;
 		clock-output-names = "apb_pclk";
 	};
 
@@ -320,34 +469,25 @@
 		clock-output-names = "iofpga_clk";
 	};
 
-	soc_uartclk:  uartclk {
+	soc_uartclk: uartclk {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
-		clock-frequency = <50000000>;
+		clock-frequency = <UARTCLK_FREQ>;
 		clock-output-names = "uartclk";
 	};
 
-	soc_uart0: uart@7ff80000 {
+	/* soc_uart0 on FPGA, ap_ns_uart on FVP */
+	os_uart: serial@2a400000 {
 		compatible = "arm,pl011", "arm,primecell";
-		reg = <0x0 0x7ff80000 0x0 0x1000>;
-		interrupts = <0x0 116 0x4>;
-		clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
+		reg = <0x0 0x2A400000 0x0 UART_OFFSET>;
+		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&soc_uartclk>, <&soc_refclk>;
 		clock-names = "uartclk", "apb_pclk";
 		status = "okay";
 	};
 
-	rtc0: rtc@1C170000 {
-		compatible = "arm,pl031", "arm,primecell";
-		reg = <0x0 0x1C170000 0x0 0x1000>;
-		interrupts = <0x0 100 0x4>;
-		clocks = <&soc_refclk100mhz>;
-		clock-names = "apb_pclk";
-		wakeup-source;
-	};
-
 	vencoder {
 		compatible = "drm,virtual-encoder";
-
 		port {
 			vencoder_in: endpoint {
 				remote-endpoint = <&dp_pl0_out0>;
@@ -355,63 +495,22 @@
 		};
 
 		display-timings {
-			panel-timing {
-				clock-frequency = <25175000>;
-				hactive = <640>;
-				vactive = <480>;
-				hfront-porch = <16>;
-				hback-porch = <48>;
-				hsync-len = <96>;
-				vfront-porch = <10>;
-				vback-porch = <33>;
-				vsync-len = <2>;
+			timing-panel {
+				VENCODER_TIMING;
 			};
 		};
 
 	};
 
-	hdlcd: hdlcd@7ff60000 {
-		compatible = "arm,hdlcd";
-		reg = <0x0 0x7ff60000 0x0 0x1000>;
-		interrupts = <0x0 117 0x4>;
-		clocks = <&fake_hdlcd_clk>;
-		clock-names = "pxlclk";
-		status = "disabled";
-
-		port {
-			hdlcd_out: endpoint {
-				remote-endpoint = <&vencoder_in>;
-			};
-		};
-	};
-
-	fake_hdlcd_clk: fake-hdlcd-clk {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <25175000>;
-		clock-output-names = "pxlclk";
-	};
-
 	ethernet@18000000 {
-		compatible = "smsc,lan91c111";
+		compatible = ETH_COMPATIBLE;
 		reg = <0x0 0x18000000 0x0 0x10000>;
-		interrupts = <0 109 4>;
-	};
-
-	kmi@1c060000 {
-		compatible = "arm,pl050", "arm,primecell";
-		reg = <0x0 0x001c060000 0x0 0x1000>;
-		interrupts = <0 197 4>;
-		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
-		clock-names = "KMIREFCLK", "apb_pclk";
-	};
+		interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
 
-	kmi@1c070000 {
-		compatible = "arm,pl050", "arm,primecell";
-		reg = <0x0 0x001c070000 0x0 0x1000>;
-		interrupts = <0 103 4>;
-		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
-		clock-names = "KMIREFCLK", "apb_pclk";
+		/* FPGA only but will work on FVP. Keep for simplicity */
+		phy-mode = "mii";
+		reg-io-width = <2>;
+		smsc,irq-push-pull;
 	};
 
 	bp_clock24mhz: clock24mhz {
@@ -421,11 +520,6 @@
 		clock-output-names = "bp:clock24mhz";
 	};
 
-	virtio_block@1c130000 {
-		compatible = "virtio,mmio";
-		reg = <0x0 0x1c130000 0x0 0x200>;
-		interrupts = <0 204 4>;
-	};
 
 	sysreg: sysreg@1c010000 {
 		compatible = "arm,vexpress-sysreg";
@@ -445,12 +539,12 @@
 	mmci@1c050000 {
 		compatible = "arm,pl180", "arm,primecell";
 		reg = <0x0 0x001c050000 0x0 0x1000>;
-		interrupts = <0 107 0x4>,
-			     <0 108 0x4>;
-		cd-gpios = <&sysreg 0 0>;
+		interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+		MMC_REMOVABLE;
 		wp-gpios = <&sysreg 1 0>;
-		bus-width = <8>;
-		max-frequency = <12000000>;
+		bus-width = <4>;
+		max-frequency = <25000000>;
 		vmmc-supply = <&fixed_3v3>;
 		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
 		clock-names = "mclk", "apb_pclk";
@@ -471,18 +565,23 @@
 	gpu: gpu@2d000000 {
 		compatible = "arm,mali-midgard";
 		reg = <0x0 0x2d000000 0x0 0x200000>;
-		interrupts = <0 66 4>, <0 67 4>, <0 65 4>;
+		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "JOB", "MMU", "GPU";
-		clocks = <&gpu_clk>, <&gpu_core_clk>;
-		clock-names = "clk_mali", "shadercores";
+		clocks = <&gpu_core_clk>;
+		clock-names = "shadercores";
+#if TC_SCMI_PD_CTRL_EN
+		power-domains = <&scmi_devpd GPU_SCMI_PD_IDX>;
+		scmi-perf-domain = <3>;
+#endif /* TC_SCMI_PD_CTRL_EN */
+
+#if TC_IOMMU_EN
 		iommus = <&smmu_700 0x200>;
-		operating-points = <
-			/* KHz uV */
-			50000 820000
-		>;
+#endif /* TC_IOMMU_EN */
 	};
 
-	power_model@simple {
+	power_model_simple {
 		/*
 		 * Numbers used are irrelevant to Titan,
 		 * it helps suppressing the kernel warnings.
@@ -494,27 +593,37 @@
 		thermal-zone = "";
 	};
 
-	smmu_700: smmu_700@3f000000 {
+#if TC_IOMMU_EN
+	smmu_700: iommu@3f000000 {
 		#iommu-cells = <1>;
 		compatible = "arm,smmu-v3";
 		reg = <0x0 0x3f000000 0x0 0x5000000>;
+		interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
+			     <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
+			     <GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "eventq", "cmdq-sync", "gerror";
 		dma-coherent;
 	};
+#endif /* TC_IOMMU_EN */
 
-	dp0: display@2cc00000 {
+	dp0: display@DPU_ADDR() {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "arm,mali-d71";
-		reg = <0 0x2cc00000 0 0x20000>;
-		interrupts = <0 69 4>;
+		reg = <HI(DPU_ADDR(0x)) LO(DPU_ADDR(0x)) 0 0x20000>;
+		interrupts = <GIC_SPI DPU_IRQ IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "DPU";
-		clocks = <&scmi_clk 0>;
-		clock-names = "aclk";
+		DPU_CLK_ATTR1;
+#if TC_IOMMU_EN
 		iommus = <&smmu_700 0x100>;
+#endif /* TC_IOMMU_EN */
+#if  TC_SCMI_PD_CTRL_EN && (TARGET_PLATFORM != 3)
+		power-domains = <&scmi_devpd DPU_SCMI_PD_IDX>;
+#endif /*  TC_SCMI_PD_CTRL_EN && (TARGET_PLATFORM != 3) */
+
 		pl0: pipeline@0 {
 			reg = <0>;
-			clocks = <&scmi_clk 1>;
-			clock-names = "pxclk";
+			DPU_CLK_ATTR2;
 			pl_id = <0>;
 			ports {
 				#address-cells = <1>;
@@ -530,8 +639,7 @@
 
 		pl1: pipeline@1 {
 			reg = <1>;
-			clocks = <&scmi_clk 2>;
-			clock-names = "pxclk";
+			DPU_CLK_ATTR3;
 			pl_id = <1>;
 			ports {
 				#address-cells = <1>;
@@ -549,7 +657,7 @@
 	 */
 	msc0 {
 		compatible = "arm,mpam-msc";
-		reg = <0x1 0x00010000 0x0 0x2000>;
+		reg = <MPAM_ADDR 0x0 0x2000>;
 	};
 
 	ete0 {
@@ -592,8 +700,72 @@
 		cpu = <&CPU7>;
 	};
 
+#if TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2
+	ete8 {
+		compatible = "arm,embedded-trace-extension";
+		cpu = <&CPU8>;
+	};
+
+	ete9 {
+		compatible = "arm,embedded-trace-extension";
+		cpu = <&CPU9>;
+	};
+
+	ete10 {
+		compatible = "arm,embedded-trace-extension";
+		cpu = <&CPU10>;
+	};
+
+	ete11 {
+		compatible = "arm,embedded-trace-extension";
+		cpu = <&CPU11>;
+	};
+
+	ete12 {
+		compatible = "arm,embedded-trace-extension";
+		cpu = <&CPU12>;
+	};
+
-	trbe0 {
+	ete13 {
+		compatible = "arm,embedded-trace-extension";
+		cpu = <&CPU13>;
+	};
+#endif /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM <= 2 */
+
+	trbe {
 		compatible = "arm,trace-buffer-extension";
-		interrupts = <1 2 4>;
+		interrupts = <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	trusty {
+		#size-cells = <0x02>;
+		#address-cells = <0x02>;
+		ranges = <0x00>;
+		compatible = "android,trusty-v1";
+
+		virtio {
+			compatible = "android,trusty-virtio-v1";
+		};
+
+		test {
+			compatible = "android,trusty-test-v1";
+		};
+
+		log {
+			compatible = "android,trusty-log-v1";
+		};
+
+		irq {
+			ipi-range = <0x08 0x0f 0x08>;
+			interrupt-ranges = <0x00 0x0f 0x00 0x10 0x1f 0x01 0x20 0x3f 0x02>;
+			interrupt-templates = <0x01 0x00 0x8001 0x01 0x01 0x04 0x8001 0x01 0x00 0x04>;
+			compatible = "android,trusty-irq-v1";
+		};
+	};
+
+	/* used in U-boot, Linux doesn't care */
+	arm_ffa {
+		compatible = "arm,ffa";
+		method = "smc";
 	};
 };
diff --git a/fdts/tc_fvp.dtsi b/fdts/tc_fvp.dtsi
new file mode 100644
index 0000000..42f3818
--- /dev/null
+++ b/fdts/tc_fvp.dtsi
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/ {
+	rtc@1c170000 {
+		compatible = "arm,pl031", "arm,primecell";
+		reg = <0x0 0x1C170000 0x0 0x1000>;
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&soc_refclk>;
+		clock-names = "apb_pclk";
+	};
+
+	kmi@1c060000 {
+		compatible = "arm,pl050", "arm,primecell";
+		reg = <0x0 0x001c060000 0x0 0x1000>;
+		interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
+		clock-names = "KMIREFCLK", "apb_pclk";
+	};
+
+	kmi@1c070000 {
+		compatible = "arm,pl050", "arm,primecell";
+		reg = <0x0 0x001c070000 0x0 0x1000>;
+		interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
+		clock-names = "KMIREFCLK", "apb_pclk";
+	};
+
+	virtio_block@1c130000 {
+		compatible = "virtio,mmio";
+		reg = <0x0 0x1c130000 0x0 0x200>;
+		/* spec lists this wrong */
+		interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
diff --git a/fdts/tc_vers.dtsi b/fdts/tc_vers.dtsi
new file mode 100644
index 0000000..43fafd5
--- /dev/null
+++ b/fdts/tc_vers.dtsi
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/* If SCMI power domain control is enabled */
+#if TC_SCMI_PD_CTRL_EN
+#define GPU_SCMI_PD_IDX		(PLAT_MAX_CPUS_PER_CLUSTER + 1)
+#define DPU_SCMI_PD_IDX		(PLAT_MAX_CPUS_PER_CLUSTER + 2)
+#endif /* TC_SCMI_PD_CTRL_EN */
+
+/* All perf is normalized against the big core */
+#define BIG_CAPACITY		1024
+
+#if TARGET_PLATFORM <= 2
+#if TARGET_FLAVOUR_FVP
+#define LIT_CAPACITY		406
+#define MID_CAPACITY		912
+#else /* TARGET_FLAVOUR_FPGA */
+#define LIT_CAPACITY		280
+#define MID_CAPACITY		775
+/* this is an area optimized configuration of the big core */
+#define BIG2_CAPACITY		930
+#endif /* TARGET_FLAVOUR_FPGA */
+
+#define INT_MBOX_RX		317
+#define MHU_TX_ADDR(pref)	pref##45000000 /* hex */
+#define MHU_RX_ADDR(pref)	pref##45010000 /* hex */
+#define MPAM_ADDR		0x1 0x00010000 /* 0x1_0001_0000 */
+#define UARTCLK_FREQ		5000000
+#elif TARGET_PLATFORM == 3
+
+#define LIT_CAPACITY		239
+#define MID_CAPACITY		686
+
+#define INT_MBOX_RX		300
+#define MHU_TX_ADDR(pref)	pref##46040000 /* hex */
+#define MHU_RX_ADDR(pref)	pref##46140000 /* hex */
+#define MPAM_ADDR		0x0 0x5f010000 /* 0x5f01_0000 */
+#define UARTCLK_FREQ		3750000
+#endif /* TARGET_PLATFORM == 3 */
+
+#if TARGET_FLAVOUR_FVP
+#define STDOUT_PATH		"serial0:115200n8"
+#define GIC_CTRL_ADDR		2c010000
+#define GIC_GICR_OFFSET		0x200000
+#define UART_OFFSET		0x1000
+#define VENCODER_TIMING_CLK 25175000
+#define VENCODER_TIMING								\
+	clock-frequency = <VENCODER_TIMING_CLK>;				\
+	hactive = <640>;							\
+	vactive = <480>;							\
+	hfront-porch = <16>;							\
+	hback-porch = <48>;							\
+	hsync-len = <96>;							\
+	vfront-porch = <10>;							\
+	vback-porch = <33>;							\
+	vsync-len = <2>
+#define ETH_COMPATIBLE		"smsc,lan91c111"
+#define MMC_REMOVABLE		cd-gpios = <&sysreg 0 0>
+#if TARGET_PLATFORM <= 2
+#define DPU_ADDR(pref)		pref##2cc00000
+#define DPU_IRQ			69
+#else /* TARGET_PLATFORM >= 3 */
+#define DPU_ADDR(pref)		pref##4000000000
+#define DPU_IRQ			579
+#endif /* TARGET_PLATFORM >= 3 */
+
+#else /* TARGET_FLAVOUR_FPGA */
+
+#define STDOUT_PATH		"serial0:38400n8"
+#define GIC_CTRL_ADDR		30000000
+#define GIC_GICR_OFFSET		0x1000000
+#define UART_OFFSET		0x10000
+/* 1440x3200@120 framebuffer */
+#define VENCODER_TIMING_CLK 836000000
+#define VENCODER_TIMING								\
+	clock-frequency = <VENCODER_TIMING_CLK>;				\
+	hactive = <1440>;							\
+	vactive = <3200>;							\
+	hfront-porch = <136>;							\
+	hback-porch = <296>;							\
+	hsync-len = <160>;							\
+	vfront-porch = <3>;							\
+	vback-porch = <217>;							\
+	vsync-len = <10>
+#define ETH_COMPATIBLE		"smsc,lan9115"
+#define MMC_REMOVABLE		non-removable
+#define DPU_ADDR(pref)		pref##2cc00000
+#define DPU_IRQ			69
+#endif /* TARGET_FLAVOUR_FPGA */
+
+/* Use SCMI controlled clocks */
+#if TC_DPU_USE_SCMI_CLK
+#define DPU_CLK_ATTR1								\
+	clocks = <&scmi_clk 0>;							\
+	clock-names = "aclk"
+
+#define DPU_CLK_ATTR2								\
+	clocks = <&scmi_clk 1>;							\
+	clock-names = "pxclk"
+
+#define DPU_CLK_ATTR3								\
+	clocks = <&scmi_clk 2>;							\
+	clock-names = "pxclk"							\
+/* Use fixed clocks */
+#else /* !TC_DPU_USE_SCMI_CLK */
+#define DPU_CLK_ATTR1								\
+	clocks = <&dpu_aclk>;							\
+	clock-names = "aclk"
+
+#define DPU_CLK_ATTR2								\
+	clocks = <&dpu_pixel_clk>, <&dpu_aclk>;					\
+	clock-names = "pxclk", "aclk"
+
+#define DPU_CLK_ATTR3 DPU_CLK_ATTR2
+#endif /* !TC_DPU_USE_SCMI_CLK */
+
+/ {
+#if TARGET_PLATFORM <= 2
+	cmn-pmu {
+		compatible = "arm,ci-700";
+		reg = <0x0 0x50000000 0x0 0x10000000>;
+		interrupts = <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>;
+	};
+#endif /* TARGET_PLATFORM <= 2 */
+
+#if !TC_DPU_USE_SCMI_CLK
+	dpu_aclk: dpu_aclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <VENCODER_TIMING_CLK>;
+		clock-output-names = "fpga:dpu_aclk";
+	};
+
+	dpu_pixel_clk: dpu-pixel-clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <VENCODER_TIMING_CLK>;
+		clock-output-names = "pxclk";
+	};
+#endif /* !TC_DPU_USE_SCMI_CLK */
+};
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 65180c0..c205f2c 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -465,6 +465,9 @@
 DEFINE_SYSREG_RW_FUNCS(cntp_cval_el0)
 DEFINE_SYSREG_READ_FUNC(cntpct_el0)
 DEFINE_SYSREG_RW_FUNCS(cnthctl_el2)
+DEFINE_SYSREG_RW_FUNCS(cntv_ctl_el0)
+DEFINE_SYSREG_RW_FUNCS(cntv_cval_el0)
+DEFINE_SYSREG_RW_FUNCS(cntkctl_el1)
 
 DEFINE_SYSREG_RW_FUNCS(vtcr_el2)
 
@@ -481,6 +484,9 @@
 #define clr_cntp_ctl_enable(x)  ((x) &= ~(U(1) << CNTP_CTL_ENABLE_SHIFT))
 #define clr_cntp_ctl_imask(x)   ((x) &= ~(U(1) << CNTP_CTL_IMASK_SHIFT))
 
+DEFINE_SYSREG_RW_FUNCS(tpidr_el0)
+DEFINE_SYSREG_RW_FUNCS(tpidr_el1)
+DEFINE_SYSREG_RW_FUNCS(tpidr_el2)
 DEFINE_SYSREG_RW_FUNCS(tpidr_el3)
 
 DEFINE_SYSREG_RW_FUNCS(cntvoff_el2)
@@ -490,7 +496,7 @@
 
 DEFINE_SYSREG_RW_FUNCS(hacr_el2)
 DEFINE_SYSREG_RW_FUNCS(hpfar_el2)
-DEFINE_SYSREG_RW_FUNCS(tpidr_el2)
+
 DEFINE_SYSREG_RW_FUNCS(dbgvcr32_el2)
 DEFINE_RENAME_SYSREG_RW_FUNCS(ich_hcr_el2, ICH_HCR_EL2)
 DEFINE_RENAME_SYSREG_RW_FUNCS(ich_vmcr_el2, ICH_VMCR_EL2)
@@ -502,6 +508,16 @@
 DEFINE_SYSREG_RW_FUNCS(hstr_el2)
 DEFINE_SYSREG_RW_FUNCS(pmcr_el0)
 
+DEFINE_SYSREG_RW_FUNCS(csselr_el1)
+DEFINE_SYSREG_RW_FUNCS(tpidrro_el0)
+DEFINE_SYSREG_RW_FUNCS(contextidr_el1)
+DEFINE_SYSREG_RW_FUNCS(spsr_abt)
+DEFINE_SYSREG_RW_FUNCS(spsr_und)
+DEFINE_SYSREG_RW_FUNCS(spsr_irq)
+DEFINE_SYSREG_RW_FUNCS(spsr_fiq)
+DEFINE_SYSREG_RW_FUNCS(dacr32_el2)
+DEFINE_SYSREG_RW_FUNCS(ifsr32_el2)
+
 /* GICv3 System Registers */
 
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
diff --git a/include/drivers/arm/css/sds.h b/include/drivers/arm/css/sds.h
index db4cbaa..ab95775 100644
--- a/include/drivers/arm/css/sds.h
+++ b/include/drivers/arm/css/sds.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -79,12 +79,33 @@
 	SDS_ACCESS_MODE_CACHED,
 } sds_access_mode_t;
 
-int sds_init(void);
-int sds_struct_exists(unsigned int structure_id);
-int sds_struct_read(uint32_t structure_id, unsigned int fld_off, void *data,
-		size_t size, sds_access_mode_t mode);
-int sds_struct_write(uint32_t structure_id, unsigned int fld_off, void *data,
-		size_t size, sds_access_mode_t mode);
+/*
+ * The following structure describes a SDS memory region. Its items are used
+ * to track and maintain the state of the memory region reserved for usage
+ * by the SDS framework.
+ *
+ * The base address of the SDS memory region is platform specific. The
+ * SDS description structure must already contain the address when it is
+ * returned by the plat_sds_get_regions() platform API during SDS region
+ * initialization.
+ * The size of the SDS memory region is dynamically discovered during the
+ * initialization of the region and written into the 'size' item of the
+ * SDS description structure.
+ */
+typedef struct {
+	uintptr_t base;	/* Pointer to the base of the SDS memory region */
+	size_t size;	/* Size of the SDS memory region in bytes */
+} sds_region_desc_t;
+
+/* API to get the platform specific SDS region description(s) */
+sds_region_desc_t *plat_sds_get_regions(unsigned int *region_count);
+
+int sds_init(unsigned int region_id);
+int sds_struct_exists(unsigned int region_id, unsigned int structure_id);
+int sds_struct_read(unsigned int region_id, uint32_t structure_id,
+	unsigned int fld_off, void *data, size_t size, sds_access_mode_t mode);
+int sds_struct_write(unsigned int region_id, uint32_t structure_id,
+	unsigned int fld_off, void *data, size_t size, sds_access_mode_t mode);
 #endif /*__ASSEMBLER__ */
 
 #endif /* SDS_H */
diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h
index 170d4cf..ccb574b 100644
--- a/include/drivers/st/stm32_i2c.h
+++ b/include/drivers/st/stm32_i2c.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2024, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -294,7 +294,6 @@
 /* STM32 specific defines */
 #define STM32_I2C_RISE_TIME_DEFAULT		25	/* ns */
 #define STM32_I2C_FALL_TIME_DEFAULT		10	/* ns */
-#define STM32_I2C_SPEED_DEFAULT			I2C_SPEED_STANDARD
 #define STM32_I2C_ANALOG_FILTER_DELAY_MIN	50	/* ns */
 #define STM32_I2C_ANALOG_FILTER_DELAY_MAX	260	/* ns */
 #define STM32_I2C_DIGITAL_FILTER_MAX		16
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 910026e..d5bd890 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -574,9 +574,6 @@
 /*******************************************************************************
  * Function prototypes
  ******************************************************************************/
-void el1_sysregs_context_save(el1_sysregs_t *regs);
-void el1_sysregs_context_restore(el1_sysregs_t *regs);
-
 #if CTX_INCLUDE_FPREGS
 void fpregs_context_save(fp_regs_t *regs);
 void fpregs_context_restore(fp_regs_t *regs);
diff --git a/include/lib/psa/psa/client.h b/include/lib/psa/psa/client.h
index 56fe028..46fac4a 100644
--- a/include/lib/psa/psa/client.h
+++ b/include/lib/psa/psa/client.h
@@ -1,6 +1,5 @@
-
 /*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -17,41 +16,57 @@
 #ifndef IOVEC_LEN
 #define IOVEC_LEN(arr) ((uint32_t)(sizeof(arr)/sizeof(arr[0])))
 #endif
+
 /*********************** PSA Client Macros and Types *************************/
+
 /**
  * The version of the PSA Framework API that is being used to build the calling
  * firmware. Only part of features of FF-M v1.1 have been implemented. FF-M v1.1
  * is compatible with v1.0.
  */
 #define PSA_FRAMEWORK_VERSION	(0x0101u)
+
 /**
  * Return value from psa_version() if the requested RoT Service is not present
  * in the system.
  */
 #define PSA_VERSION_NONE	(0u)
+
 /**
  * The zero-value null handle can be assigned to variables used in clients and
  * RoT Services, indicating that there is no current connection or message.
  */
 #define PSA_NULL_HANDLE		((psa_handle_t)0)
+
 /**
  * Tests whether a handle value returned by psa_connect() is valid.
  */
 #define PSA_HANDLE_IS_VALID(handle)	((psa_handle_t)(handle) > 0)
+
 /**
  * Converts the handle value returned from a failed call psa_connect() into
  * an error code.
  */
 #define PSA_HANDLE_TO_ERROR(handle)	((psa_status_t)(handle))
+
 /**
  * Maximum number of input and output vectors for a request to psa_call().
  */
 #define PSA_MAX_IOVEC		(4u)
+
+/**
+ * The minimum and maximum value that can be passed
+ * as the type parameter in a call to psa_call().
+ */
+#define PSA_CALL_TYPE_MIN	(0)
+#define PSA_CALL_TYPE_MAX	(INT16_MAX)
+
 /**
  * An IPC message type that indicates a generic client request.
  */
 #define PSA_IPC_CALL		(0)
 typedef int32_t psa_handle_t;
+
 /**
  * A read-only input memory region provided to an RoT Service.
  */
@@ -59,6 +74,7 @@
 	const void *base;	/*!< the start address of the memory buffer */
 	size_t len;		/*!< the size in bytes                      */
 } psa_invec;
+
 /**
  * A writable output memory region provided to an RoT Service.
  */
diff --git a/include/lib/psa/rss_crypto_defs.h b/include/lib/psa/rss_crypto_defs.h
index b8c7426..301dc05 100644
--- a/include/lib/psa/rss_crypto_defs.h
+++ b/include/lib/psa/rss_crypto_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -38,21 +38,42 @@
 };
 
 /*
- * Structure used to pack non-pointer types in a call
+ * Structure used to pack non-pointer types in a call to PSA Crypto APIs
  */
 struct rss_crypto_pack_iovec {
-	psa_key_id_t key_id;	/* Key id */
-	psa_algorithm_t alg;	/* Algorithm */
-	uint32_t op_handle;	/* Frontend context handle associated
-				   to a multipart operation */
-	uint32_t capacity;	/* Key derivation capacity */
-	uint32_t ad_length;	/* Additional Data length for multipart AEAD */
-	uint32_t plaintext_length;	/* Plaintext length for multipart AEAD */
-	struct rss_crypto_aead_pack_input aead_in;	/* Packs AEAD-related inputs */
-	uint16_t function_id;	/* Used to identify the function in the API dispatcher
-				   to the service backend. See rss_crypto_func_sid for
-				   detail */
-	uint16_t step;		/* Key derivation step */
+	psa_key_id_t key_id;		/* !< Key id */
+	psa_algorithm_t alg;		/* !< Algorithm */
+	uint32_t op_handle;		/*
+					 * !< Frontend context handle
+					 * associated to a multipart operation
+					 */
+	uint32_t ad_length;		/*
+					 * !< Additional Data length for
+					 *    multipart AEAD
+					 */
+	uint32_t plaintext_length;	/*
+					 * !< Plaintext length for multipart
+					 *    AEAD
+					 */
+
+	struct rss_crypto_aead_pack_input aead_in; /*
+						    * !< Packs AEAD-related
+						    *    inputs
+						    */
+
+	uint16_t function_id;	/*
+				 * !< Used to identify the function in the
+				 *    API dispatcher to the service backend
+				 *    See rss_crypto_func_sid for detail
+				 */
+	uint16_t step;		/* !< Key derivation step */
+	union {
+		size_t capacity;	/* !< Key derivation capacity */
+		uint64_t value;		/*
+					 * !< Key derivation integer for
+					 *    update
+					 */
+	};
 };
 
 #endif /* RSS_CRYPTO_DEFS_H */
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index a170a09..8a03c7d 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -53,6 +53,9 @@
 #define GENMASK				GENMASK_32
 #endif
 
+#define HI(addr)			(addr >> 32)
+#define LO(addr)			(addr & 0xffffffff)
+
 /*
  * This variant of div_round_up can be used in macro definition but should not
  * be used in C code as the `div` parameter is evaluated twice.
diff --git a/include/plat/arm/common/fconf_arm_sp_getter.h b/include/plat/arm/common/fconf_arm_sp_getter.h
index 96ed963..d8a332e 100644
--- a/include/plat/arm/common/fconf_arm_sp_getter.h
+++ b/include/plat/arm/common/fconf_arm_sp_getter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,12 +9,17 @@
 
 #include <common/tbbr/tbbr_img_def.h>
 #include <lib/fconf/fconf.h>
+#include <platform_def.h>
 #include <tools_share/uuid.h>
 
 /* arm_sp getter */
 #define arm__sp_getter(prop)	arm_sp.prop
 
+#ifdef PLAT_ARM_SP_MAX_SIZE
+#define ARM_SP_MAX_SIZE		PLAT_ARM_SP_MAX_SIZE
+#else
 #define ARM_SP_MAX_SIZE		U(0xb0000)
+#endif /* PLAT_ARM_SP_MAX_SIZE */
 #define ARM_SP_OWNER_NAME_LEN	U(8)
 
 struct arm_sp_t {
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index f87f857..0aea548 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -75,6 +75,7 @@
  * The SCMI Channel is placed right after the SDS region
  */
 #define CSS_SCMI_PAYLOAD_BASE		(PLAT_ARM_SDS_MEM_BASE + PLAT_ARM_SDS_MEM_SIZE_MAX)
+#define CSS_SCMI_PAYLOAD_SIZE_MAX	0x100 /* 2x128 bytes for bidirectional communication */
 #define CSS_SCMI_MHU_DB_REG_OFF		MHU_CPU_INTR_S_SET_OFFSET
 
 /* Trusted mailbox base address common to all CSS */
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 176308e..76aebf9 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -10,8 +10,6 @@
 #include <context.h>
 #include <el3_common_macros.S>
 
-	.global	el1_sysregs_context_save
-	.global	el1_sysregs_context_restore
 #if CTX_INCLUDE_FPREGS
 	.global	fpregs_context_save
 	.global	fpregs_context_restore
@@ -21,220 +19,6 @@
 	.global save_and_update_ptw_el1_sys_regs
 	.global	el3_exit
 
-
-/* ------------------------------------------------------------------
- * The following function strictly follows the AArch64 PCS to use
- * x9-x17 (temporary caller-saved registers) to save EL1 system
- * register context. It assumes that 'x0' is pointing to a
- * 'el1_sys_regs' structure where the register context will be saved.
- * ------------------------------------------------------------------
- */
-func el1_sysregs_context_save
-
-	mrs	x9, spsr_el1
-	mrs	x10, elr_el1
-	stp	x9, x10, [x0, #CTX_SPSR_EL1]
-
-#if !ERRATA_SPECULATIVE_AT
-	mrs	x15, sctlr_el1
-	mrs	x16, tcr_el1
-	stp	x15, x16, [x0, #CTX_SCTLR_EL1]
-#endif /* ERRATA_SPECULATIVE_AT */
-
-	mrs	x17, cpacr_el1
-	mrs	x9, csselr_el1
-	stp	x17, x9, [x0, #CTX_CPACR_EL1]
-
-	mrs	x10, sp_el1
-	mrs	x11, esr_el1
-	stp	x10, x11, [x0, #CTX_SP_EL1]
-
-	mrs	x12, ttbr0_el1
-	mrs	x13, ttbr1_el1
-	stp	x12, x13, [x0, #CTX_TTBR0_EL1]
-
-	mrs	x14, mair_el1
-	mrs	x15, amair_el1
-	stp	x14, x15, [x0, #CTX_MAIR_EL1]
-
-	mrs	x16, actlr_el1
-	mrs	x17, tpidr_el1
-	stp	x16, x17, [x0, #CTX_ACTLR_EL1]
-
-	mrs	x9, tpidr_el0
-	mrs	x10, tpidrro_el0
-	stp	x9, x10, [x0, #CTX_TPIDR_EL0]
-
-	mrs	x13, par_el1
-	mrs	x14, far_el1
-	stp	x13, x14, [x0, #CTX_PAR_EL1]
-
-	mrs	x15, afsr0_el1
-	mrs	x16, afsr1_el1
-	stp	x15, x16, [x0, #CTX_AFSR0_EL1]
-
-	mrs	x17, contextidr_el1
-	mrs	x9, vbar_el1
-	stp	x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
-
-	/* Save AArch32 system registers if the build has instructed so */
-#if CTX_INCLUDE_AARCH32_REGS
-	mrs	x11, spsr_abt
-	mrs	x12, spsr_und
-	stp	x11, x12, [x0, #CTX_SPSR_ABT]
-
-	mrs	x13, spsr_irq
-	mrs	x14, spsr_fiq
-	stp	x13, x14, [x0, #CTX_SPSR_IRQ]
-
-	mrs	x15, dacr32_el2
-	mrs	x16, ifsr32_el2
-	stp	x15, x16, [x0, #CTX_DACR32_EL2]
-#endif /* CTX_INCLUDE_AARCH32_REGS */
-
-	/* Save NS timer registers if the build has instructed so */
-#if NS_TIMER_SWITCH
-	mrs	x10, cntp_ctl_el0
-	mrs	x11, cntp_cval_el0
-	stp	x10, x11, [x0, #CTX_CNTP_CTL_EL0]
-
-	mrs	x12, cntv_ctl_el0
-	mrs	x13, cntv_cval_el0
-	stp	x12, x13, [x0, #CTX_CNTV_CTL_EL0]
-
-	mrs	x14, cntkctl_el1
-	str	x14, [x0, #CTX_CNTKCTL_EL1]
-#endif /* NS_TIMER_SWITCH */
-
-	/* Save MTE system registers if the build has instructed so */
-#if ENABLE_FEAT_MTE
-#if ENABLE_FEAT_MTE == 2
-	mrs x8, id_aa64pfr1_el1
-	and x8, x8, #(ID_AA64PFR1_EL1_MTE_MASK << ID_AA64PFR1_EL1_MTE_SHIFT)
-	cbz x8, no_mte_save
-#endif
-	mrs	x15, TFSRE0_EL1
-	mrs	x16, TFSR_EL1
-	stp	x15, x16, [x0, #CTX_TFSRE0_EL1]
-
-	mrs	x9, RGSR_EL1
-	mrs	x10, GCR_EL1
-	stp	x9, x10, [x0, #CTX_RGSR_EL1]
-
-no_mte_save:
-#endif /* ENABLE_FEAT_MTE */
-
-	ret
-endfunc el1_sysregs_context_save
-
-/* ------------------------------------------------------------------
- * The following function strictly follows the AArch64 PCS to use
- * x9-x17 (temporary caller-saved registers) to restore EL1 system
- * register context.  It assumes that 'x0' is pointing to a
- * 'el1_sys_regs' structure from where the register context will be
- * restored
- * ------------------------------------------------------------------
- */
-func el1_sysregs_context_restore
-
-	ldp	x9, x10, [x0, #CTX_SPSR_EL1]
-	msr	spsr_el1, x9
-	msr	elr_el1, x10
-
-#if !ERRATA_SPECULATIVE_AT
-	ldp	x15, x16, [x0, #CTX_SCTLR_EL1]
-	msr	sctlr_el1, x15
-	msr	tcr_el1, x16
-#endif /* ERRATA_SPECULATIVE_AT */
-
-	ldp	x17, x9, [x0, #CTX_CPACR_EL1]
-	msr	cpacr_el1, x17
-	msr	csselr_el1, x9
-
-	ldp	x10, x11, [x0, #CTX_SP_EL1]
-	msr	sp_el1, x10
-	msr	esr_el1, x11
-
-	ldp	x12, x13, [x0, #CTX_TTBR0_EL1]
-	msr	ttbr0_el1, x12
-	msr	ttbr1_el1, x13
-
-	ldp	x14, x15, [x0, #CTX_MAIR_EL1]
-	msr	mair_el1, x14
-	msr	amair_el1, x15
-
-	ldp 	x16, x17, [x0, #CTX_ACTLR_EL1]
-	msr	actlr_el1, x16
-	msr	tpidr_el1, x17
-
-	ldp	x9, x10, [x0, #CTX_TPIDR_EL0]
-	msr	tpidr_el0, x9
-	msr	tpidrro_el0, x10
-
-	ldp	x13, x14, [x0, #CTX_PAR_EL1]
-	msr	par_el1, x13
-	msr	far_el1, x14
-
-	ldp	x15, x16, [x0, #CTX_AFSR0_EL1]
-	msr	afsr0_el1, x15
-	msr	afsr1_el1, x16
-
-	ldp	x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
-	msr	contextidr_el1, x17
-	msr	vbar_el1, x9
-
-	/* Restore AArch32 system registers if the build has instructed so */
-#if CTX_INCLUDE_AARCH32_REGS
-	ldp	x11, x12, [x0, #CTX_SPSR_ABT]
-	msr	spsr_abt, x11
-	msr	spsr_und, x12
-
-	ldp	x13, x14, [x0, #CTX_SPSR_IRQ]
-	msr	spsr_irq, x13
-	msr	spsr_fiq, x14
-
-	ldp	x15, x16, [x0, #CTX_DACR32_EL2]
-	msr	dacr32_el2, x15
-	msr	ifsr32_el2, x16
-#endif /* CTX_INCLUDE_AARCH32_REGS */
-
-	/* Restore NS timer registers if the build has instructed so */
-#if NS_TIMER_SWITCH
-	ldp	x10, x11, [x0, #CTX_CNTP_CTL_EL0]
-	msr	cntp_ctl_el0, x10
-	msr	cntp_cval_el0, x11
-
-	ldp	x12, x13, [x0, #CTX_CNTV_CTL_EL0]
-	msr	cntv_ctl_el0, x12
-	msr	cntv_cval_el0, x13
-
-	ldr	x14, [x0, #CTX_CNTKCTL_EL1]
-	msr	cntkctl_el1, x14
-#endif /* NS_TIMER_SWITCH */
-
-	/* Restore MTE system registers if the build has instructed so */
-#if ENABLE_FEAT_MTE
-#if ENABLE_FEAT_MTE == 2
-	mrs x8, id_aa64pfr1_el1
-	and x8, x8, #(ID_AA64PFR1_EL1_MTE_MASK << ID_AA64PFR1_EL1_MTE_SHIFT)
-	cbz x8, no_mte_restore
-#endif
-
-	ldp	x11, x12, [x0, #CTX_TFSRE0_EL1]
-	msr	TFSRE0_EL1, x11
-	msr	TFSR_EL1, x12
-
-	ldp	x13, x14, [x0, #CTX_RGSR_EL1]
-	msr	RGSR_EL1, x13
-	msr	GCR_EL1, x14
-
-no_mte_restore:
-#endif /* ENABLE_FEAT_MTE */
-
-	/* No explict ISB required here as ERET covers it */
-	ret
-endfunc el1_sysregs_context_restore
-
 /* ------------------------------------------------------------------
  * The following function follows the aapcs_64 strictly to use
  * x9-x17 (temporary caller-saved registers according to AArch64 PCS)
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index c3b7e78..922b2cf 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -1134,13 +1134,58 @@
 }
 #endif /* CTX_INCLUDE_MPAM_REGS */
 
-/* -----------------------------------------------------
+/* ---------------------------------------------------------------------------
  * The following registers are not added:
- * AMEVCNTVOFF0<n>_EL2
- * AMEVCNTVOFF1<n>_EL2
  * ICH_AP0R<n>_EL2
  * ICH_AP1R<n>_EL2
  * ICH_LR<n>_EL2
+ *
+ * NOTE: For a system with S-EL2 present but not enabled, accessing
+ * ICC_SRE_EL2 is undefined from EL3. To workaround this change the
+ * SCR_EL3.NS = 1 before accessing this register.
+ * ---------------------------------------------------------------------------
+ */
+static void el2_sysregs_context_save_gic(el2_sysregs_t *ctx)
+{
+#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
+	write_ctx_reg(ctx, CTX_ICC_SRE_EL2, read_icc_sre_el2());
+#else
+	u_register_t scr_el3 = read_scr_el3();
+	write_scr_el3(scr_el3 | SCR_NS_BIT);
+	isb();
+
+	write_ctx_reg(ctx, CTX_ICC_SRE_EL2, read_icc_sre_el2());
+
+	write_scr_el3(scr_el3);
+	isb();
+
+#endif
+	write_ctx_reg(ctx, CTX_ICH_HCR_EL2, read_ich_hcr_el2());
+	write_ctx_reg(ctx, CTX_ICH_VMCR_EL2, read_ich_vmcr_el2());
+}
+
+static void el2_sysregs_context_restore_gic(el2_sysregs_t *ctx)
+{
+#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
+	write_icc_sre_el2(read_ctx_reg(ctx, CTX_ICC_SRE_EL2));
+#else
+	u_register_t scr_el3 = read_scr_el3();
+	write_scr_el3(scr_el3 | SCR_NS_BIT);
+	isb();
+
+	write_icc_sre_el2(read_ctx_reg(ctx, CTX_ICC_SRE_EL2));
+
+	write_scr_el3(scr_el3);
+	isb();
+#endif
+	write_ich_hcr_el2(read_ctx_reg(ctx, CTX_ICH_HCR_EL2));
+	write_ich_vmcr_el2(read_ctx_reg(ctx, CTX_ICH_VMCR_EL2));
+}
+
+/* -----------------------------------------------------
+ * The following registers are not added:
+ * AMEVCNTVOFF0<n>_EL2
+ * AMEVCNTVOFF1<n>_EL2
  * -----------------------------------------------------
  */
 static void el2_sysregs_context_save_common(el2_sysregs_t *ctx)
@@ -1162,22 +1207,6 @@
 	write_ctx_reg(ctx, CTX_HCR_EL2, read_hcr_el2());
 	write_ctx_reg(ctx, CTX_HPFAR_EL2, read_hpfar_el2());
 	write_ctx_reg(ctx, CTX_HSTR_EL2, read_hstr_el2());
-
-	/*
-	 * Set the NS bit to be able to access the ICC_SRE_EL2 register
-	 * TODO: remove with root context
-	 */
-	u_register_t scr_el3 = read_scr_el3();
-
-	write_scr_el3(scr_el3 | SCR_NS_BIT);
-	isb();
-	write_ctx_reg(ctx, CTX_ICC_SRE_EL2, read_icc_sre_el2());
-
-	write_scr_el3(scr_el3);
-	isb();
-
-	write_ctx_reg(ctx, CTX_ICH_HCR_EL2, read_ich_hcr_el2());
-	write_ctx_reg(ctx, CTX_ICH_VMCR_EL2, read_ich_vmcr_el2());
 	write_ctx_reg(ctx, CTX_MAIR_EL2, read_mair_el2());
 	write_ctx_reg(ctx, CTX_MDCR_EL2, read_mdcr_el2());
 	write_ctx_reg(ctx, CTX_SCTLR_EL2, read_sctlr_el2());
@@ -1212,22 +1241,6 @@
 	write_hcr_el2(read_ctx_reg(ctx, CTX_HCR_EL2));
 	write_hpfar_el2(read_ctx_reg(ctx, CTX_HPFAR_EL2));
 	write_hstr_el2(read_ctx_reg(ctx, CTX_HSTR_EL2));
-
-	/*
-	 * Set the NS bit to be able to access the ICC_SRE_EL2 register
-	 * TODO: remove with root context
-	 */
-	u_register_t scr_el3 = read_scr_el3();
-
-	write_scr_el3(scr_el3 | SCR_NS_BIT);
-	isb();
-	write_icc_sre_el2(read_ctx_reg(ctx, CTX_ICC_SRE_EL2));
-
-	write_scr_el3(scr_el3);
-	isb();
-
-	write_ich_hcr_el2(read_ctx_reg(ctx, CTX_ICH_HCR_EL2));
-	write_ich_vmcr_el2(read_ctx_reg(ctx, CTX_ICH_VMCR_EL2));
 	write_mair_el2(read_ctx_reg(ctx, CTX_MAIR_EL2));
 	write_mdcr_el2(read_ctx_reg(ctx, CTX_MDCR_EL2));
 	write_sctlr_el2(read_ctx_reg(ctx, CTX_SCTLR_EL2));
@@ -1257,6 +1270,7 @@
 	el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
 
 	el2_sysregs_context_save_common(el2_sysregs_ctx);
+	el2_sysregs_context_save_gic(el2_sysregs_ctx);
 
 	if (is_feat_mte2_supported()) {
 		write_ctx_reg(el2_sysregs_ctx, CTX_TFSR_EL2, read_tfsr_el2());
@@ -1336,6 +1350,7 @@
 	el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
 
 	el2_sysregs_context_restore_common(el2_sysregs_ctx);
+	el2_sysregs_context_restore_gic(el2_sysregs_ctx);
 
 	if (is_feat_mte2_supported()) {
 		write_tfsr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TFSR_EL2));
@@ -1429,6 +1444,116 @@
 #endif /* CTX_INCLUDE_EL2_REGS */
 }
 
+static void el1_sysregs_context_save(el1_sysregs_t *ctx)
+{
+	write_ctx_reg(ctx, CTX_SPSR_EL1, read_spsr_el1());
+	write_ctx_reg(ctx, CTX_ELR_EL1, read_elr_el1());
+
+#if !ERRATA_SPECULATIVE_AT
+	write_ctx_reg(ctx, CTX_SCTLR_EL1, read_sctlr_el1());
+	write_ctx_reg(ctx, CTX_TCR_EL1, read_tcr_el1());
+#endif /* (!ERRATA_SPECULATIVE_AT) */
+
+	write_ctx_reg(ctx, CTX_CPACR_EL1, read_cpacr_el1());
+	write_ctx_reg(ctx, CTX_CSSELR_EL1, read_csselr_el1());
+	write_ctx_reg(ctx, CTX_SP_EL1, read_sp_el1());
+	write_ctx_reg(ctx, CTX_ESR_EL1, read_esr_el1());
+	write_ctx_reg(ctx, CTX_TTBR0_EL1, read_ttbr0_el1());
+	write_ctx_reg(ctx, CTX_TTBR1_EL1, read_ttbr1_el1());
+	write_ctx_reg(ctx, CTX_MAIR_EL1, read_mair_el1());
+	write_ctx_reg(ctx, CTX_AMAIR_EL1, read_amair_el1());
+	write_ctx_reg(ctx, CTX_ACTLR_EL1, read_actlr_el1());
+	write_ctx_reg(ctx, CTX_TPIDR_EL1, read_tpidr_el1());
+	write_ctx_reg(ctx, CTX_TPIDR_EL0, read_tpidr_el0());
+	write_ctx_reg(ctx, CTX_TPIDRRO_EL0, read_tpidrro_el0());
+	write_ctx_reg(ctx, CTX_PAR_EL1, read_par_el1());
+	write_ctx_reg(ctx, CTX_FAR_EL1, read_far_el1());
+	write_ctx_reg(ctx, CTX_AFSR0_EL1, read_afsr0_el1());
+	write_ctx_reg(ctx, CTX_AFSR1_EL1, read_afsr1_el1());
+	write_ctx_reg(ctx, CTX_CONTEXTIDR_EL1, read_contextidr_el1());
+	write_ctx_reg(ctx, CTX_VBAR_EL1, read_vbar_el1());
+
+#if CTX_INCLUDE_AARCH32_REGS
+	write_ctx_reg(ctx, CTX_SPSR_ABT, read_spsr_abt());
+	write_ctx_reg(ctx, CTX_SPSR_UND, read_spsr_und());
+	write_ctx_reg(ctx, CTX_SPSR_IRQ, read_spsr_irq());
+	write_ctx_reg(ctx, CTX_SPSR_FIQ, read_spsr_fiq());
+	write_ctx_reg(ctx, CTX_DACR32_EL2, read_dacr32_el2());
+	write_ctx_reg(ctx, CTX_IFSR32_EL2, read_ifsr32_el2());
+#endif /* CTX_INCLUDE_AARCH32_REGS */
+
+#if NS_TIMER_SWITCH
+	write_ctx_reg(ctx, CTX_CNTP_CTL_EL0, read_cntp_ctl_el0());
+	write_ctx_reg(ctx, CTX_CNTP_CVAL_EL0, read_cntp_cval_el0());
+	write_ctx_reg(ctx, CTX_CNTV_CTL_EL0, read_cntv_ctl_el0());
+	write_ctx_reg(ctx, CTX_CNTV_CVAL_EL0, read_cntv_cval_el0());
+	write_ctx_reg(ctx, CTX_CNTKCTL_EL1, read_cntkctl_el1());
+#endif /* NS_TIMER_SWITCH */
+
+#if ENABLE_FEAT_MTE
+	write_ctx_reg(ctx, CTX_TFSRE0_EL1, read_tfsre0_el1());
+	write_ctx_reg(ctx, CTX_TFSR_EL1, read_tfsr_el1());
+	write_ctx_reg(ctx, CTX_RGSR_EL1, read_rgsr_el1());
+	write_ctx_reg(ctx, CTX_GCR_EL1, read_gcr_el1());
+#endif /* ENABLE_FEAT_MTE */
+
+}
+
+static void el1_sysregs_context_restore(el1_sysregs_t *ctx)
+{
+	write_spsr_el1(read_ctx_reg(ctx, CTX_SPSR_EL1));
+	write_elr_el1(read_ctx_reg(ctx, CTX_ELR_EL1));
+
+#if !ERRATA_SPECULATIVE_AT
+	write_sctlr_el1(read_ctx_reg(ctx, CTX_SCTLR_EL1));
+	write_tcr_el1(read_ctx_reg(ctx, CTX_TCR_EL1));
+#endif /* (!ERRATA_SPECULATIVE_AT) */
+
+	write_cpacr_el1(read_ctx_reg(ctx, CTX_CPACR_EL1));
+	write_csselr_el1(read_ctx_reg(ctx, CTX_CSSELR_EL1));
+	write_sp_el1(read_ctx_reg(ctx, CTX_SP_EL1));
+	write_esr_el1(read_ctx_reg(ctx, CTX_ESR_EL1));
+	write_ttbr0_el1(read_ctx_reg(ctx, CTX_TTBR0_EL1));
+	write_ttbr1_el1(read_ctx_reg(ctx, CTX_TTBR1_EL1));
+	write_mair_el1(read_ctx_reg(ctx, CTX_MAIR_EL1));
+	write_amair_el1(read_ctx_reg(ctx, CTX_AMAIR_EL1));
+	write_actlr_el1(read_ctx_reg(ctx, CTX_ACTLR_EL1));
+	write_tpidr_el1(read_ctx_reg(ctx, CTX_TPIDR_EL1));
+	write_tpidr_el0(read_ctx_reg(ctx, CTX_TPIDR_EL0));
+	write_tpidrro_el0(read_ctx_reg(ctx, CTX_TPIDRRO_EL0));
+	write_par_el1(read_ctx_reg(ctx, CTX_PAR_EL1));
+	write_far_el1(read_ctx_reg(ctx, CTX_FAR_EL1));
+	write_afsr0_el1(read_ctx_reg(ctx, CTX_AFSR0_EL1));
+	write_afsr1_el1(read_ctx_reg(ctx, CTX_AFSR1_EL1));
+	write_contextidr_el1(read_ctx_reg(ctx, CTX_CONTEXTIDR_EL1));
+	write_vbar_el1(read_ctx_reg(ctx, CTX_VBAR_EL1));
+
+#if CTX_INCLUDE_AARCH32_REGS
+	write_spsr_abt(read_ctx_reg(ctx, CTX_SPSR_ABT));
+	write_spsr_und(read_ctx_reg(ctx, CTX_SPSR_UND));
+	write_spsr_irq(read_ctx_reg(ctx, CTX_SPSR_IRQ));
+	write_spsr_fiq(read_ctx_reg(ctx, CTX_SPSR_FIQ));
+	write_dacr32_el2(read_ctx_reg(ctx, CTX_DACR32_EL2));
+	write_ifsr32_el2(read_ctx_reg(ctx, CTX_IFSR32_EL2));
+#endif /* CTX_INCLUDE_AARCH32_REGS */
+
+#if NS_TIMER_SWITCH
+	write_cntp_ctl_el0(read_ctx_reg(ctx, CTX_CNTP_CTL_EL0));
+	write_cntp_cval_el0(read_ctx_reg(ctx, CTX_CNTP_CVAL_EL0));
+	write_cntv_ctl_el0(read_ctx_reg(ctx, CTX_CNTV_CTL_EL0));
+	write_cntv_cval_el0(read_ctx_reg(ctx, CTX_CNTV_CVAL_EL0));
+	write_cntkctl_el1(read_ctx_reg(ctx, CTX_CNTKCTL_EL1));
+#endif /* NS_TIMER_SWITCH */
+
+#if ENABLE_FEAT_MTE
+	write_tfsre0_el1(read_ctx_reg(ctx, CTX_TFSRE0_EL1));
+	write_tfsr_el1(read_ctx_reg(ctx, CTX_TFSR_EL1));
+	write_rgsr_el1(read_ctx_reg(ctx, CTX_RGSR_EL1));
+	write_gcr_el1(read_ctx_reg(ctx, CTX_GCR_EL1));
+#endif /* ENABLE_FEAT_MTE */
+
+}
+
 /*******************************************************************************
  * The next four functions are used by runtime services to save and restore
  * EL1 context on the 'cpu_context' structure for the specified security
diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile
index 3b62aaa..f11e577 100644
--- a/lib/romlib/Makefile
+++ b/lib/romlib/Makefile
@@ -4,11 +4,10 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-AS          = $(CROSS_COMPILE)gcc
-AR          = $(CROSS_COMPILE)gcc-ar
-LD          = $(CROSS_COMPILE)ld
-OC          = $(CROSS_COMPILE)objcopy
-CPP         = $(CROSS_COMPILE)gcc -E
+toolchains := aarch64
+
+include ../../make_helpers/toolchain.mk
+
 ROMLIB_GEN  = ./romlib_generator.py
 BUILD_DIR   = $(BUILD_PLAT)/romlib
 LIB_DIR     = $(BUILD_PLAT)/lib
@@ -48,23 +47,23 @@
 
 %.o: %.s
 	@echo "  AS      $@"
-	$(Q)$(AS) -c $(ASFLAGS) -o $@ $<
+	$(Q)$(aarch64-as) -c $(ASFLAGS) -o $@ $<
 
 $(BUILD_DIR)/%.o: %.s
 	@echo "  AS      $@"
-	$(Q)$(AS) -c $(ASFLAGS) -o $@ $<
+	$(Q)$(aarch64-as) -c $(ASFLAGS) -o $@ $<
 
 $(BUILD_DIR)/romlib.ld: romlib.ld.S
 	@echo "  PP      $@"
-	$(Q)$(CPP) $(PPFLAGS) -o $@ romlib.ld.S
+	$(Q)$(aarch64-cpp) -E $(PPFLAGS) -o $@ romlib.ld.S
 
 $(BUILD_DIR)/romlib.elf: $(OBJS) $(BUILD_DIR)/romlib.ld
 	@echo "  LD      $@"
-	$(Q)$(LD) -T $(BUILD_DIR)/romlib.ld -L$(LIB_DIR) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+	$(Q)$(aarch64-ld) -T $(BUILD_DIR)/romlib.ld -L$(LIB_DIR) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
 
 $(BUILD_DIR)/romlib.bin: $(BUILD_DIR)/romlib.elf
 	@echo "  BIN     $@"
-	$(Q)$(OC) -O binary $(BUILD_DIR)/romlib.elf $@
+	$(Q)$(aarch64-oc) -O binary $(BUILD_DIR)/romlib.elf $@
 
 $(WRAPPER_DIR)/jmpvar.s: $(BUILD_DIR)/romlib.elf
 	@echo "  VAR     $@"
@@ -72,7 +71,7 @@
 
 $(LIB_DIR)/libwrappers.a: $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS)
 	@echo "  AR      $@"
-	$(Q)$(AR) -rc $@ $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS)
+	$(Q)$(aarch64-ar) -rc $@ $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS)
 
 $(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i
 	@echo "  PRE     $@"
diff --git a/make_helpers/build_env.mk b/make_helpers/build_env.mk
index 83093bd..a545cd0 100644
--- a/make_helpers/build_env.mk
+++ b/make_helpers/build_env.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -47,7 +47,7 @@
             endif
         endif
     endif
-    include ${MAKE_HELPERS_DIRECTORY}${ENV_FILE_TO_INCLUDE}
+    include $(dir $(lastword $(MAKEFILE_LIST)))${ENV_FILE_TO_INCLUDE}
     ENV_FILE_TO_INCLUDE :=
 
     ifndef SHELL_COPY
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 6edc2d6..a99d516 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -113,12 +113,12 @@
 
 # Convenience function to check for a given linker option. An call to
 # $(call ld_option, --no-XYZ) will return --no-XYZ if supported by the linker
-ld_option = $(shell $(LD) $(1) -Wl,--version >/dev/null 2>&1 || $(LD) $(1) -v >/dev/null 2>&1 && echo $(1))
+ld_option = $(shell $($(ARCH)-ld) $(1) -Wl,--version >/dev/null 2>&1 || $($(ARCH)-ld) $(1) -v >/dev/null 2>&1 && echo $(1))
 
 # Convenience function to check for a given compiler option. A call to
 # $(call cc_option, --no-XYZ) will return --no-XYZ if supported by the compiler
 define cc_option
-	$(shell if $(CC) $(1) -c -x c /dev/null -o /dev/null >/dev/null 2>&1; then echo $(1); fi )
+	$(shell if $($(ARCH)-cc) $(1) -c -x c /dev/null -o /dev/null >/dev/null 2>&1; then echo $(1); fi )
 endef
 
 # CREATE_SEQ is a recursive function to create sequence of numbers from 1 to
@@ -312,7 +312,7 @@
 
 $(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs
 	$$(ECHO) "  CC      $$<"
-	$$(Q)$$(CC) $$($(LIB)_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(MAKE_DEP) -c $$< -o $$@
+	$$(Q)$($(ARCH)-cc) $$($(LIB)_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(MAKE_DEP) -c $$< -o $$@
 
 -include $(DEP)
 
@@ -328,7 +328,7 @@
 
 $(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs
 	$$(ECHO) "  AS      $$<"
-	$$(Q)$$(AS) $$(ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
+	$$(Q)$($(ARCH)-as) -x assembler-with-cpp $$(TF_CFLAGS_$(ARCH)) $$(ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
 
 -include $(DEP)
 
@@ -351,7 +351,7 @@
 
 $(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
 	$$(ECHO) "  CC      $$<"
-	$$(Q)$$(CC) $$(LTO_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(BL_CPPFLAGS) $(BL_CFLAGS) $(MAKE_DEP) -c $$< -o $$@
+	$$(Q)$($(ARCH)-cc) $$(LTO_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(BL_CPPFLAGS) $(BL_CFLAGS) $(MAKE_DEP) -c $$< -o $$@
 
 -include $(DEP)
 
@@ -374,7 +374,7 @@
 
 $(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
 	$$(ECHO) "  AS      $$<"
-	$$(Q)$$(AS) $$(ASFLAGS) $(BL_CPPFLAGS) $(BL_ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
+	$$(Q)$($(ARCH)-as) -x assembler-with-cpp $$(TF_CFLAGS_$(ARCH)) $$(ASFLAGS) $(BL_CPPFLAGS) $(BL_ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
 
 -include $(DEP)
 
@@ -395,7 +395,7 @@
 
 $(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
 	$$(ECHO) "  PP      $$<"
-	$$(Q)$$(CPP) $$(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH)) -P -x assembler-with-cpp -D__LINKER__ $(MAKE_DEP) -o $$@ $$<
+	$$(Q)$($(ARCH)-cpp) -E $$(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH)) -P -x assembler-with-cpp -D__LINKER__ $(MAKE_DEP) -o $$@ $$<
 
 -include $(DEP)
 
@@ -477,7 +477,7 @@
 .PHONY : lib${1}_dirs
 lib${1}_dirs: | ${BUILD_DIR} ${LIB_DIR}  ${ROMLIB_DIR} ${LIBWRAPPER_DIR}
 libraries: ${LIB_DIR}/lib$(1).a
-ifneq ($(findstring armlink,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),arm-link)
 LDPATHS = --userlibpath=${LIB_DIR}
 LDLIBS += --library=$(1)
 else
@@ -493,7 +493,7 @@
 
 ${LIB_DIR}/lib$(1).a: $(OBJS)
 	$$(ECHO) "  AR      $$@"
-	$$(Q)$$(AR) cr $$@ $$?
+	$$(Q)$($(ARCH)-ar) cr $$@ $$?
 endef
 
 # Generate the path to one or more preprocessed linker scripts given the paths
@@ -573,22 +573,22 @@
 	@echo 'const char build_message[] = "Built : "$(BUILD_MESSAGE_TIMESTAMP); \
 	       const char version_string[] = "${VERSION_STRING}"; \
 	       const char version[] = "${VERSION}";' | \
-		$$(CC) $$(TF_CFLAGS) $$(CFLAGS) -xc -c - -o $(BUILD_DIR)/build_message.o
+		$($(ARCH)-cc) $$(TF_CFLAGS) $$(CFLAGS) -xc -c - -o $(BUILD_DIR)/build_message.o
 endif
-ifneq ($(findstring armlink,$(notdir $(LD))),)
-	$$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=${1}_entrypoint \
+ifeq ($($(ARCH)-ld-id),arm-link)
+	$$(Q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=${1}_entrypoint \
 		--predefine="-D__LINKER__=$(__LINKER__)" \
 		--predefine="-DTF_CFLAGS=$(TF_CFLAGS)" \
 		--map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/${1}.scat \
 		$(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) \
 		$(BUILD_DIR)/build_message.o $(OBJS)
-else ifneq ($(findstring gcc,$(notdir $(LD))),)
-	$$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) -Wl,-Map=$(MAPFILE) \
+else ifeq ($($(ARCH)-ld-id),gnu-gcc)
+	$$(Q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) -Wl,-Map=$(MAPFILE) \
 		$(addprefix -Wl$(comma)--script$(comma),$(LINKER_SCRIPTS)) -Wl,--script,$(DEFAULT_LINKER_SCRIPT) \
 		$(BUILD_DIR)/build_message.o \
 		$(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS)
 else
-	$$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) -Map=$(MAPFILE) \
+	$$(Q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) -Map=$(MAPFILE) \
 		$(addprefix -T ,$(LINKER_SCRIPTS)) --script $(DEFAULT_LINKER_SCRIPT) \
 		$(BUILD_DIR)/build_message.o \
 		$(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS)
@@ -601,11 +601,11 @@
 
 $(DUMP): $(ELF)
 	$${ECHO} "  OD      $$@"
-	$${Q}$${OD} -dx $$< > $$@
+	$${Q}$($(ARCH)-od) -dx $$< > $$@
 
 $(BIN): $(ELF)
 	$${ECHO} "  BIN     $$@"
-	$$(Q)$$(OC) -O binary $$< $$@
+	$$(Q)$($(ARCH)-oc) -O binary $$< $$@
 	@${ECHO_BLANK_LINE}
 	@echo "Built $$@ successfully"
 	@${ECHO_BLANK_LINE}
@@ -668,9 +668,9 @@
 $(DOBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs
 	$${ECHO} "  CPP     $$<"
 	$(eval DTBS       := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2))))
-	$$(Q)$$(CPP) $$(DTC_CPPFLAGS) -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DPRE) $$<
+	$$(Q)$($(ARCH)-cpp) -E $$(TF_CFLAGS_$(ARCH)) $$(DTC_CPPFLAGS) -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DPRE) $$<
 	$${ECHO} "  DTC     $$<"
-	$$(Q)$$(DTC) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $(DPRE)
+	$$(Q)$($(ARCH)-dtc) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $(DPRE)
 
 -include $(DTBDEP)
 -include $(DTSDEP)
diff --git a/make_helpers/march.mk b/make_helpers/march.mk
index 1b73969..25bb936 100644
--- a/make_helpers/march.mk
+++ b/make_helpers/march.mk
@@ -21,7 +21,7 @@
 # armv8.6-a armv8.7-a armv8.8-a armv8-r armv9-a
 # [...]
 #
-GCC_MARCH_OUTPUT := $(shell $(CC) -march=foo -Q --help=target -v 2>&1)
+GCC_MARCH_OUTPUT := $(shell $($(ARCH)-cc) -march=foo -Q --help=target -v 2>&1)
 
 # This function is used to find the best march value supported by the given compiler.
 # We try to use `GCC_MARCH_OUTPUT` which has verbose message with supported march values we filter that
@@ -54,7 +54,7 @@
     provided-march = armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a
 endif
 
-ifeq ($(findstring clang,$(notdir $(CC))),)
+ifeq ($(filter %-clang,$($(ARCH)-cc-id)),)
 
 # We expect from Platform to provide a correct Major/Minor value but expecting something
 # from compiler with unsupported march means we shouldn't fail without trying anything,
diff --git a/make_helpers/toolchain.mk b/make_helpers/toolchain.mk
new file mode 100644
index 0000000..7255509
--- /dev/null
+++ b/make_helpers/toolchain.mk
@@ -0,0 +1,343 @@
+#
+# Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#
+# TF-A uses three toolchains:
+#
+#   - The host toolchain (`host`) for building native tools
+#   - The AArch32 toolchain (`aarch32`) for building Arm AArch32 images
+#   - The AArch64 toolchain (`aarch64`) for building Arm AArch64 images
+#
+# In the main Makefile only one of the two Arm toolchains is enabled in any
+# given build, but individual tools and libraries may need access to both.
+#
+
+toolchains ?= host $(ARCH)
+
+ifneq ($(filter host,$(toolchains)),)
+        host-cc := $(HOSTCC)
+        host-cpp := $(HOSTCPP)
+
+        host-as := $(HOSTAS)
+
+        host-ld := $(HOSTLD)
+        host-oc := $(HOSTOC)
+        host-od := $(HOSTOD)
+        host-ar := $(HOSTAR)
+
+        host-dtc := $(HOSTDTC)
+endif
+
+ifneq ($(filter aarch32,$(toolchains)),)
+        aarch32-cc := $(if $(filter-out default,$(origin CC)),$(CC))
+        aarch32-cpp := $(if $(filter-out default,$(origin CPP)),$(CPP))
+
+        aarch32-as := $(if $(filter-out default,$(origin AS)),$(AS))
+
+        aarch32-ld := $(if $(filter-out default,$(origin LD)),$(LD))
+        aarch32-oc := $(if $(filter-out default,$(origin OC)),$(OC))
+        aarch32-od := $(if $(filter-out default,$(origin OD)),$(OD))
+        aarch32-ar := $(if $(filter-out default,$(origin AR)),$(AR))
+
+        aarch32-dtc := $(if $(filter-out default,$(origin DTC)),$(DTC))
+endif
+
+ifneq ($(filter aarch64,$(toolchains)),)
+        aarch64-cc := $(if $(filter-out default,$(origin CC)),$(CC))
+        aarch64-cpp := $(if $(filter-out default,$(origin CPP)),$(CPP))
+
+        aarch64-as := $(if $(filter-out default,$(origin AS)),$(AS))
+
+        aarch64-ld := $(if $(filter-out default,$(origin LD)),$(LD))
+        aarch64-oc := $(if $(filter-out default,$(origin OC)),$(OC))
+        aarch64-od := $(if $(filter-out default,$(origin OD)),$(OD))
+        aarch64-ar := $(if $(filter-out default,$(origin AR)),$(AR))
+
+        aarch64-dtc := $(if $(filter-out default,$(origin DTC)),$(DTC))
+endif
+
+include $(dir $(lastword $(MAKEFILE_LIST)))build_env.mk
+include $(addprefix $(dir $(lastword $(MAKEFILE_LIST)))toolchains/, \
+        $(addsuffix .mk,$(toolchains)))
+
+#
+# Configure tool classes that we recognize.
+#
+# In the context of this build system, a tool class identifies a specific role
+# or type of tool in the toolchain.
+#
+
+# C-related tools
+tool-classes := cc # C compilers
+tool-classes += cpp # C preprocessors
+
+# Assembly-related tools
+tool-classes += as # Assemblers
+
+# Linking and object-handling tools
+tool-classes += ld # Linkers
+tool-classes += oc # Object copiers
+tool-classes += od # Object dumpers
+tool-classes += ar # Archivers
+
+# Other tools
+tool-classes += dtc # Device tree compilers
+
+#
+# Configure tools that we recognize.
+#
+# Here we declare the list of specific toolchain tools that we know how to
+# interact with. We don't organize these into tool classes yet - that happens
+# further down.
+#
+
+# Arm Compiler for Embedded
+tools := arm-clang # armclang
+tools += arm-link # armlink
+tools += arm-ar # armar
+tools += arm-fromelf # fromelf
+
+# LLVM Project
+tools += llvm-clang # clang
+tools += llvm-lld # lld
+tools += llvm-objcopy # llvm-objcopy
+tools += llvm-objdump # llvm-objdump
+tools += llvm-ar # llvm-ar
+
+# GNU Compiler Collection & GNU Binary Utilities
+tools += gnu-gcc # gcc
+tools += gnu-ld # ld
+tools += gnu-objcopy # objcopy
+tools += gnu-objdump # objdump
+tools += gnu-ar # gcc-ar
+
+# Other tools
+tools += dtc # Device Tree Compiler
+
+#
+# Assign tools to tool classes.
+#
+# Multifunctional tools, i.e. tools which can perform multiple roles in a
+# toolchain, may be specified in multiple tool class lists. For example, a C
+# compiler which can also perform the role of a linker may be placed in both
+# `tools-cc` and `tools-ld`.
+#
+
+# C-related tools
+tools-cc := arm-clang llvm-clang gnu-gcc # C compilers
+tools-cpp := arm-clang llvm-clang gnu-gcc # C preprocessors
+
+# Assembly-related tools
+tools-as := arm-clang llvm-clang gnu-gcc # Assemblers
+
+# Linking and object-handling tools
+tools-ld := arm-clang arm-link llvm-clang llvm-lld gnu-gcc gnu-ld # Linkers
+tools-oc := arm-fromelf llvm-objcopy gnu-objcopy # Object copiers
+tools-od := arm-fromelf llvm-objdump gnu-objdump # Object dumpers
+tools-ar := arm-ar llvm-ar gnu-ar # Archivers
+
+# Other tools
+tools-dtc := dtc # Device tree compilers
+
+define check-tool-class-tools
+        $(eval tool-class := $(1))
+
+        ifndef tools-$(tool-class)
+                $$(error no tools registered to handle tool class `$(tool-class)`)
+        endif
+endef
+
+$(foreach tool-class,$(tool-classes), \
+        $(eval $(call check-tool-class-tools,$(tool-class))))
+
+#
+# Default tools for each toolchain.
+#
+# Toolchains can specify a default path to any given tool with a tool class.
+# These values are used in the absence of user-specified values, and are
+# configured by the makefile for each toolchain using variables of the form:
+#
+#   - $(toolchain)-$(tool-class)-default
+#
+# For example, the default C compiler for the AArch32 and AArch64 toolchains
+# could be configured with:
+#
+#   - aarch32-cc-default
+#   - aarch64-cc-default
+#
+
+define check-toolchain-tool-class-default
+        $(eval toolchain := $(1))
+        $(eval tool-class := $(2))
+
+        ifndef $(toolchain)-$(tool-class)-default
+                $$(error no default value specified for tool class `$(tool-class)` of toolchain `$(toolchain)`)
+        endif
+endef
+
+define check-toolchain-tool-class-defaults
+        $(eval toolchain := $(1))
+
+        $(foreach tool-class,$(tool-classes), \
+                $(eval $(call check-toolchain-tool-class-default,$(toolchain),$(tool-class))))
+endef
+
+$(foreach toolchain,$(toolchains), \
+        $(eval $(call check-toolchain-tool-class-defaults,$(toolchain))))
+
+#
+# Helper functions to identify toolchain tools.
+#
+# The functions defined in this section return a tool identifier when given a
+# path to a binary. We generally check a help or version string to more reliably
+# identify tools than by looking at the path alone (e.g. `gcc` on macOS is
+# actually Apple Clang).
+#
+# Each tool-guessing function (`guess-tool-$(tool)`) takes a single argument
+# giving the path to the tool to guess, and returns a non-empty value if the
+# tool corresponds to the tool identifier `$(tool)`:
+#
+#     $(call guess-tool-llvm-clang,aarch64-none-elf-gcc) # <empty>
+#     $(call guess-tool-gnu-gcc,aarch64-none-elf-gcc) # <non-empty>
+#
+# The `guess-tool` function tries to find the corresponding tool identifier
+# for a tool given its path. It takes two arguments:
+#
+#   - $(1): a list of candidate tool identifiers to check
+#   - $(2): the path to the tool to identify
+#
+# If any of the guess functions corresponding to candidate tool identifiers
+# return a non-empty value then the tool identifier of the first function to do
+# so is returned:
+#
+#     $(call guess-tool,gnu-gcc llvm-clang,armclang) # <empty>
+#     $(call guess-tool,gnu-gcc llvm-clang,clang-14) # llvm-clang
+#     $(call guess-tool,gnu-gcc llvm-clang,aarch64-none-elf-gcc-12) # gnu-gcc
+#
+# Tools are checked in the order that they appear in `tools-$(tool-class)`, and
+# the first match is returned.
+#
+
+# Arm Compiler for Embedded
+guess-tool-arm-clang = $(shell $(1) --version 2>&1 | grep -o "Tool: armclang")
+guess-tool-arm-link = $(shell $(1) --help 2>&1 | grep -o "Tool: armlink")
+guess-tool-arm-fromelf = $(shell $(1) --help 2>&1 | grep -o "Tool: fromelf")
+guess-tool-arm-ar = $(shell $(1) --version 2>&1 | grep -o "Tool: armar")
+
+# LLVM Project
+guess-tool-llvm-clang = $(shell $(1) -v 2>&1 | grep -o "clang version")
+guess-tool-llvm-lld = $(shell $(1) --help 2>&1 | grep -o "OVERVIEW: lld")
+guess-tool-llvm-objcopy = $(shell $(1) --help 2>&1 | grep -o "llvm-objcopy tool")
+guess-tool-llvm-objdump = $(shell $(1) --help 2>&1 | grep -o "llvm object file dumper")
+guess-tool-llvm-ar = $(shell $(1) --help 2>&1 | grep -o "LLVM Archiver")
+
+# GNU Compiler Collection & GNU Binary Utilities
+guess-tool-gnu-gcc = $(shell $(1) -v 2>&1 | grep -o "gcc version")
+guess-tool-gnu-ld = $(shell $(1) -v 2>&1 | grep -o "GNU ld")
+guess-tool-gnu-objcopy = $(shell $(1) --version 2>&1 | grep -o "GNU objcopy")
+guess-tool-gnu-objdump = $(shell $(1) --version 2>&1 | grep -o "GNU objdump")
+guess-tool-gnu-ar = $(shell $(1) --version 2>&1 | grep -o "GNU ar")
+
+# Other tools
+guess-tool-dtc = $(shell $(1) --version 2>&1 | grep -o "Version: DTC")
+
+guess-tool = $(firstword $(foreach candidate,$(1), \
+        $(if $(call guess-tool-$(candidate),$(2)),$(candidate))))
+
+#
+# Locate and identify tools belonging to each toolchain.
+#
+# Each tool class in each toolchain receives a variable of the form
+# `$(toolchain)-$(tool)` giving the associated path to the program. For example:
+#
+#   - `aarch64-ld` gives the linker for the AArch64 toolchain,
+#   - `aarch32-oc` gives the object copier for the AArch32 toolchain, and
+#   - `host-cc` gives the C compiler for the host toolchain.
+#
+# For each of these variables, if no program path is explicitly provided by the
+# parent Makefile then the C compiler is queried (if supported) for its
+# location. This is done via the `guess-$(tool)-$(tool-class)` set of functions.
+# For example:
+#
+#   - `guess-arm-clang-ld` guesses the linker via Arm Clang,
+#   - `guess-llvm-clang-as` guesses the assembler via LLVM Clang, and
+#   - `guess-gnu-gcc-od` guesses the object dumper via GNU GCC.
+#
+# If the C compiler cannot provide the location (or the tool class is the C
+# compiler), then it is assigned the value of the `$(toolchain)-$(tool)-default`
+# variable.
+#
+
+guess-arm-clang-cpp = $(1) # Use the C compiler
+guess-arm-clang-as = $(1) # Use the C compiler
+guess-arm-clang-ld = # Fall back to `$(toolchain)-ld-default`
+guess-arm-clang-oc = # Fall back to `$(toolchain)-oc-default`
+guess-arm-clang-od = # Fall back to `$(toolchain)-od-default`
+guess-arm-clang-ar = # Fall back to `$(toolchain)-ar-default`
+
+guess-llvm-clang-cpp = $(1) # Use the C compiler
+guess-llvm-clang-as = $(1) # Use the C compiler
+guess-llvm-clang-ld = $(shell $(1) --print-prog-name ld.lld 2>$(nul))
+guess-llvm-clang-oc = $(shell $(1) --print-prog-name llvm-objcopy 2>$(nul))
+guess-llvm-clang-od = $(shell $(1) --print-prog-name llvm-objdump 2>$(nul))
+guess-llvm-clang-ar = $(shell $(1) --print-prog-name llvm-ar 2>$(nul))
+
+guess-gnu-gcc-cpp = $(1) # Use the C compiler
+guess-gnu-gcc-as = $(1) # Use the C compiler
+guess-gnu-gcc-ld = $(if $(filter 1,$(ENABLE_LTO)),$(1),$(shell $(1) --print-prog-name ld.bfd 2>$(nul)))
+guess-gnu-gcc-oc = $(shell $(1) --print-prog-name objcopy 2>$(nul))
+guess-gnu-gcc-od = $(shell $(1) --print-prog-name objdump 2>$(nul))
+guess-gnu-gcc-ar = $(patsubst %$(notdir $(1)),%$(subst gcc,gcc-ar,$(notdir $(1))),$(1))
+
+define locate-toolchain-tool-cc
+        $(eval toolchain := $(1))
+
+        $(toolchain)-cc := $$(strip \
+                $$(or $$($(toolchain)-cc),$$($(toolchain)-cc-default)))
+        $(toolchain)-cc-id := $$(strip \
+                $$(call guess-tool,$$(tools-cc),$$($(toolchain)-cc)))
+endef
+
+define locate-toolchain-tool
+        $(eval toolchain := $(1))
+        $(eval tool-class := $(2))
+
+        ifndef $(toolchain)-$(tool-class)
+                $(toolchain)-$(tool-class) := $$(strip \
+                        $$(call guess-$$($(toolchain)-cc-id)-$(tool-class),$$($(toolchain)-cc)))
+
+                ifeq ($$($(toolchain)-$(tool-class)),)
+                        $(toolchain)-$(tool-class) := $$(strip \
+                                $$($(toolchain)-$(tool-class)-default))
+                endif
+        endif
+
+        $(toolchain)-$(tool-class)-id := $$(strip \
+                $$(call guess-tool,$$(tools-$(tool-class)),$$($$(toolchain)-$(tool-class))))
+endef
+
+define canonicalize-toolchain-tool-path
+        $(eval toolchain := $(1))
+        $(eval tool-class := $(2))
+
+        $(toolchain)-$(tool-class) := $$(strip $$(or \
+                $$(call which,$$($(toolchain)-$(tool-class))), \
+                $$($(toolchain)-$(tool-class))))
+endef
+
+define locate-toolchain
+        $(eval toolchain := $(1))
+
+        $$(eval $$(call locate-toolchain-tool-cc,$(toolchain)))
+        $$(eval $$(call canonicalize-toolchain-tool-path,$(toolchain),cc))
+
+        $$(foreach tool-class,$$(filter-out cc,$$(tool-classes)), \
+                $$(eval $$(call locate-toolchain-tool,$(toolchain),$$(tool-class))) \
+                $$(eval $$(call canonicalize-toolchain-tool-path,$(toolchain),$$(tool-class))))
+endef
+
+$(foreach toolchain,$(toolchains), \
+        $(eval $(call locate-toolchain,$(toolchain))))
diff --git a/make_helpers/toolchains/aarch32.mk b/make_helpers/toolchains/aarch32.mk
new file mode 100644
index 0000000..226bc75
--- /dev/null
+++ b/make_helpers/toolchains/aarch32.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+aarch32-cc-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc
+aarch32-cpp-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc
+aarch32-as-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc
+aarch32-ld-default := $(or $(CROSS_COMPILE),arm-none-eabi-)ld.bfd
+aarch32-oc-default := $(or $(CROSS_COMPILE),arm-none-eabi-)objcopy
+aarch32-od-default := $(or $(CROSS_COMPILE),arm-none-eabi-)objdump
+aarch32-ar-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc-ar
+aarch32-dtc-default := dtc
diff --git a/make_helpers/toolchains/aarch64.mk b/make_helpers/toolchains/aarch64.mk
new file mode 100644
index 0000000..15c5757
--- /dev/null
+++ b/make_helpers/toolchains/aarch64.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+aarch64-cc-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc
+aarch64-cpp-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc
+aarch64-as-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc
+aarch64-ld-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)ld.bfd
+aarch64-oc-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)objcopy
+aarch64-od-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)objdump
+aarch64-ar-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc-ar
+aarch64-dtc-default := dtc
diff --git a/make_helpers/toolchains/host.mk b/make_helpers/toolchains/host.mk
new file mode 100644
index 0000000..fe3fc1c
--- /dev/null
+++ b/make_helpers/toolchains/host.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+host-cc-default := gcc
+host-cpp-default := gcc
+host-as-default := gcc
+host-ld-default := gcc
+host-oc-default := objcopy
+host-od-default := objdump
+host-ar-default := gcc-ar
+host-dtc-default := dtc
diff --git a/make_helpers/toolchains/rk3399-m0.mk b/make_helpers/toolchains/rk3399-m0.mk
new file mode 100644
index 0000000..c61b6e8
--- /dev/null
+++ b/make_helpers/toolchains/rk3399-m0.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+rk3399-m0-cc-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc
+rk3399-m0-cpp-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc
+rk3399-m0-as-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc
+rk3399-m0-ld-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)ld.bfd
+rk3399-m0-oc-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)objcopy
+rk3399-m0-od-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)objdump
+rk3399-m0-ar-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc-ar
+rk3399-m0-dtc-default := dtc
diff --git a/make_helpers/unix.mk b/make_helpers/unix.mk
index 545ddfd..d285799 100644
--- a/make_helpers/unix.mk
+++ b/make_helpers/unix.mk
@@ -57,4 +57,7 @@
 	-${Q}rm -rf  "${1}"
     endef
 
+    nul := /dev/null
+
+    which = $(shell which $(1) 2>$(nul))
 endif
diff --git a/make_helpers/windows.mk b/make_helpers/windows.mk
index ac0f940..7ed8e84 100644
--- a/make_helpers/windows.mk
+++ b/make_helpers/windows.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -68,6 +68,9 @@
 	-@if exist "$(tmp_dir)"  rd /Q /S "$(tmp_dir)"
     endef
 
+    nul := nul
+
+    which = $(shell where $(1) 2>$(nul))
 endif
 
 # Because git is not available from CMD.EXE, we need to avoid
@@ -85,8 +88,7 @@
 define MAKE_BUILD_STRINGS
 	$$(file >$1.in,$$(TF_CFLAGS) $$(CFLAGS))
 	@echo $$(BUILT_TIME_DATE_STRING) $$(VERSION_STRING_MESSAGE) $$(VERSION_MESSAGE) | \
-		$$(CC) @$1.in -x c -c - -o $1
+		$($(ARCH)-cc) @$1.in -x c -c - -o $1
 endef
 
 MSVC_NMAKE := nmake.exe
-
diff --git a/plat/amlogic/axg/platform.mk b/plat/amlogic/axg/platform.mk
index 3560b0c..64b35d6 100644
--- a/plat/amlogic/axg/platform.mk
+++ b/plat/amlogic/axg/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -41,9 +41,9 @@
 				${GIC_SOURCES}
 
 # Tune compiler for Cortex-A53
-ifeq ($(notdir $(CC)),armclang)
+ifeq ($($(ARCH)-cc-id),arm-clang)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
-else ifneq ($(findstring clang,$(notdir $(CC))),)
+else ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
 else
     TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
@@ -92,4 +92,3 @@
 
 ${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
 	${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
-
diff --git a/plat/amlogic/g12a/platform.mk b/plat/amlogic/g12a/platform.mk
index b0c91b0..799e106 100644
--- a/plat/amlogic/g12a/platform.mk
+++ b/plat/amlogic/g12a/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -41,9 +41,9 @@
 				${GIC_SOURCES}
 
 # Tune compiler for Cortex-A53
-ifeq ($(notdir $(CC)),armclang)
+ifeq ($($(ARCH)-cc-id),arm-clang)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
-else ifneq ($(findstring clang,$(notdir $(CC))),)
+else ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
 else
     TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
@@ -88,4 +88,3 @@
 
 ${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
 	${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
-
diff --git a/plat/amlogic/gxbb/platform.mk b/plat/amlogic/gxbb/platform.mk
index 62384d2..fbebd3e 100644
--- a/plat/amlogic/gxbb/platform.mk
+++ b/plat/amlogic/gxbb/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -37,9 +37,9 @@
 				${GIC_SOURCES}
 
 # Tune compiler for Cortex-A53
-ifeq ($(notdir $(CC)),armclang)
+ifeq ($($(ARCH)-cc-id),arm-clang)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
-else ifneq ($(findstring clang,$(notdir $(CC))),)
+else ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
 else
     TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
diff --git a/plat/amlogic/gxl/platform.mk b/plat/amlogic/gxl/platform.mk
index 641d177..0a88482 100644
--- a/plat/amlogic/gxl/platform.mk
+++ b/plat/amlogic/gxl/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -41,9 +41,9 @@
 				${GIC_SOURCES}
 
 # Tune compiler for Cortex-A53
-ifeq ($(notdir $(CC)),armclang)
+ifeq ($($(ARCH)-cc-id),arm-clang)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
-else ifneq ($(findstring clang,$(notdir $(CC))),)
+else ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
 else
     TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
@@ -88,4 +88,3 @@
 
 ${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
 	${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
-
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index f44b37d..c9c248f 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -129,6 +129,6 @@
 
 bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/kernel_trampoline.o ${BUILD_PLAT}/build_axf.ld
 	$(ECHO) "  LD      $@"
-	$(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -s -n -o ${BUILD_PLAT}/bl31.axf
+	$(Q)$($(ARCH)-ld) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -s -n -o ${BUILD_PLAT}/bl31.axf
 
 all: bl31.axf
diff --git a/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
index fe521a9..457d181 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
@@ -34,9 +34,14 @@
 		.image_info.image_base = BL31_BASE,
 		.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
 
+#ifdef CORSTONE1000_WITH_BL32
 		.next_handoff_image_id = BL32_IMAGE_ID,
+#else
+		.next_handoff_image_id = BL33_IMAGE_ID,
+#endif
 	},
 
+#ifdef CORSTONE1000_WITH_BL32
 	/* Fill BL32 related information */
 	{
 		.image_id = BL32_IMAGE_ID,
@@ -65,7 +70,7 @@
 		VERSION_2, image_info_t, 0),
 		.next_handoff_image_id = INVALID_IMAGE_ID,
 	},
-
+#endif
 	/* Fill BL33 related information */
 	{
 		.image_id = BL33_IMAGE_ID,
diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk
index dcd0df8..fd08803 100644
--- a/plat/arm/board/corstone1000/platform.mk
+++ b/plat/arm/board/corstone1000/platform.mk
@@ -28,9 +28,14 @@
 
 override NEED_BL2U	:=	no
 override NEED_BL31	:=	yes
-NEED_BL32		:=	yes
+NEED_BL32		?=	yes
 override NEED_BL33	:=	yes
 
+# Add CORSTONE1000_WITH_BL32 as a preprocessor define (-D option)
+ifeq (${NEED_BL32},yes)
+$(eval $(call add_define,CORSTONE1000_WITH_BL32))
+endif
+
 # Include GICv2 driver files
 include drivers/arm/gic/v2/gicv2.mk
 
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 193052d..4b69d66 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -234,7 +234,13 @@
 /* When ARM_BL31_IN_DRAM is set, BL2 can use almost all of Trusted SRAM. */
 # define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1F000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #else
-# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+/**
+ * Default to just under half of SRAM to ensure there's enough room for really
+ * large BL31 build configurations when using the default SRAM size (256 Kb).
+ */
+#define PLAT_ARM_MAX_BL2_SIZE                                               \
+	(((PLAT_ARM_TRUSTED_SRAM_SIZE / 3) & ~PAGE_SIZE_MASK) - PAGE_SIZE - \
+	 FVP_BL2_ROMLIB_OPTIMIZATION)
 #endif
 
 #if RESET_TO_BL31
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 5c9a7a3..b276f7b 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -246,12 +246,14 @@
 /* MHU related constants */
 #define PLAT_CSS_MHU_BASE		UL(0x2b1f0000)
 
+#if CSS_USE_SCMI_SDS_DRIVER
+/* Index of SDS region used in the communication between AP and SCP */
+#define SDS_SCP_AP_REGION_ID			U(0)
+#else
 /*
  * Base address of the first memory region used for communication between AP
  * and SCP. Used by the BOM and SCPI protocols.
- */
-#if !CSS_USE_SCMI_SDS_DRIVER
-/*
+ *
  * Note that this is located at the same address as SCP_BOOT_CFG_ADDR, which
  * means the SCP/AP configuration data gets overwritten when the AP initiates
  * communication with the SCP. The configuration data is expected to be a
@@ -261,7 +263,7 @@
 #define PLAT_CSS_SCP_COM_SHARED_MEM_BASE	(ARM_TRUSTED_SRAM_BASE + UL(0x80))
 #define PLAT_CSS_PRIMARY_CPU_SHIFT		8
 #define PLAT_CSS_PRIMARY_CPU_BIT_WIDTH		4
-#endif
+#endif /* CSS_USE_SCMI_SDS_DRIVER */
 
 /*
  * SCP_BL2 uses up whatever remaining space is available as it is loaded before
diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c
index a9d5cc3..2bc948d 100644
--- a/plat/arm/board/juno/juno_bl1_setup.c
+++ b/plat/arm/board/juno/juno_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,13 +32,14 @@
 	int ret;
 	uint32_t scp_reset_synd_flags;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SCP SDS initialization failed\n");
 		panic();
 	}
 
-	ret = sds_struct_read(SDS_RESET_SYNDROME_STRUCT_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+					SDS_RESET_SYNDROME_STRUCT_ID,
 					SDS_RESET_SYNDROME_OFFSET,
 					&scp_reset_synd_flags,
 					SDS_RESET_SYNDROME_SIZE,
diff --git a/plat/arm/board/juno/juno_common.c b/plat/arm/board/juno/juno_common.c
index 02614da..2cd01e4 100644
--- a/plat/arm/board/juno/juno_common.c
+++ b/plat/arm/board/juno/juno_common.c
@@ -1,14 +1,16 @@
 /*
- * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <drivers/arm/css/sds.h>
 #include <lib/smccc.h>
-#include <platform_def.h>
+#include <lib/utils_def.h>
 #include <services/arm_arch_svc.h>
 
 #include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
 
 /*
  * Table of memory regions for different BL stages to map using the MMU.
@@ -138,3 +140,16 @@
 	return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) &
 			  V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK);
 }
+
+#if CSS_USE_SCMI_SDS_DRIVER
+static sds_region_desc_t juno_sds_regions[] = {
+	{ .base = PLAT_ARM_SDS_MEM_BASE },
+};
+
+sds_region_desc_t *plat_sds_get_regions(unsigned int *region_count)
+{
+	*region_count = ARRAY_SIZE(juno_sds_regions);
+
+	return juno_sds_regions;
+}
+#endif /* CSS_USE_SCMI_SDS_DRIVER */
diff --git a/plat/arm/board/morello/include/platform_def.h b/plat/arm/board/morello/include/platform_def.h
index 993aa46..3cf723e 100644
--- a/plat/arm/board/morello/include/platform_def.h
+++ b/plat/arm/board/morello/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -59,6 +59,10 @@
 
 #if CSS_USE_SCMI_SDS_DRIVER
 #define MORELLO_SCMI_PAYLOAD_BASE		ULL(0x45400000)
+/*
+ * Index of SDS region used in the communication with SCP
+ */
+#define SDS_SCP_AP_REGION_ID			U(0)
 #else
 #define PLAT_CSS_SCP_COM_SHARED_MEM_BASE	ULL(0x45400000)
 #endif
diff --git a/plat/arm/board/morello/morello_bl2_setup.c b/plat/arm/board/morello/morello_bl2_setup.c
index 39020e2..38e2e6a 100644
--- a/plat/arm/board/morello/morello_bl2_setup.c
+++ b/plat/arm/board/morello/morello_bl2_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -155,13 +155,14 @@
 	int ret;
 	struct morello_plat_info plat_info;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SDS initialization failed. ret:%d\n", ret);
 		panic();
 	}
 
-	ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+				MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
 				MORELLO_SDS_PLATFORM_INFO_OFFSET,
 				&plat_info,
 				MORELLO_SDS_PLATFORM_INFO_SIZE,
diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c
index 8469cd1..6373825 100644
--- a/plat/arm/board/morello/morello_bl31_setup.c
+++ b/plat/arm/board/morello/morello_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -43,13 +43,14 @@
 #ifdef TARGET_PLATFORM_SOC
 	int ret;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SDS initialization failed. ret:%d\n", ret);
 		panic();
 	}
 
-	ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+				MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
 				MORELLO_SDS_PLATFORM_INFO_OFFSET,
 				&plat_info,
 				MORELLO_SDS_PLATFORM_INFO_SIZE,
diff --git a/plat/arm/board/morello/morello_image_load.c b/plat/arm/board/morello/morello_image_load.c
index 4ea2bb3..cfe8bee 100644
--- a/plat/arm/board/morello/morello_image_load.c
+++ b/plat/arm/board/morello/morello_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,7 @@
 #include "morello_def.h"
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
+#include <platform_def.h>
 
 /* In client mode, a part of the DDR memory is reserved for Tag bits.
  * Calculate the usable memory size after subtracting the Tag memory.
@@ -167,13 +168,14 @@
 	struct morello_plat_info plat_info;
 	struct morello_firmware_version fw_version;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SDS initialization failed. ret:%d\n", ret);
 		panic();
 	}
 
-	ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+				MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
 				MORELLO_SDS_PLATFORM_INFO_OFFSET,
 				&plat_info,
 				MORELLO_SDS_PLATFORM_INFO_SIZE,
@@ -183,7 +185,8 @@
 		panic();
 	}
 
-	ret = sds_struct_read(MORELLO_SDS_FIRMWARE_VERSION_STRUCT_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+				MORELLO_SDS_FIRMWARE_VERSION_STRUCT_ID,
 				MORELLO_SDS_FIRMWARE_VERSION_OFFSET,
 				&fw_version,
 				MORELLO_SDS_FIRMWARE_VERSION_SIZE,
diff --git a/plat/arm/board/morello/morello_plat.c b/plat/arm/board/morello/morello_plat.c
index 2ca3d08..61fed64 100644
--- a/plat/arm/board/morello/morello_plat.c
+++ b/plat/arm/board/morello/morello_plat.c
@@ -1,12 +1,14 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <assert.h>
 
+#include <drivers/arm/css/sds.h>
 #include <drivers/arm/sbsa.h>
+#include <lib/utils_def.h>
 #include <plat/arm/common/plat_arm.h>
 
 #include "morello_def.h"
@@ -68,3 +70,16 @@
 {
 	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
 }
+
+#if CSS_USE_SCMI_SDS_DRIVER
+static sds_region_desc_t morello_sds_regions[] = {
+	{ .base = PLAT_ARM_SDS_MEM_BASE },
+};
+
+sds_region_desc_t *plat_sds_get_regions(unsigned int *region_count)
+{
+	*region_count = ARRAY_SIZE(morello_sds_regions);
+
+	return morello_sds_regions;
+}
+#endif /* CSS_USE_SCMI_SDS_DRIVER */
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
index 74d0c91..82f1e7f 100644
--- a/plat/arm/board/n1sdp/include/platform_def.h
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -77,6 +77,10 @@
 
 #if CSS_USE_SCMI_SDS_DRIVER
 #define N1SDP_SCMI_PAYLOAD_BASE			0x45400000
+/*
+ * Index of SDS region used in the communication with SCP
+ */
+#define SDS_SCP_AP_REGION_ID			U(0)
 #else
 #define PLAT_CSS_SCP_COM_SHARED_MEM_BASE	0x45400000
 #endif
diff --git a/plat/arm/board/n1sdp/n1sdp_bl2_setup.c b/plat/arm/board/n1sdp/n1sdp_bl2_setup.c
index 5f8af9f..5a5b9a5 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl2_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl2_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 
 #include "n1sdp_def.h"
 #include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
 
 struct n1sdp_plat_info {
 	bool multichip_mode;
@@ -60,13 +61,14 @@
 	int ret;
 	struct n1sdp_plat_info plat_info;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SDS initialization failed\n");
 		panic();
 	}
 
-	ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+				N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
 				N1SDP_SDS_PLATFORM_INFO_OFFSET,
 				&plat_info,
 				N1SDP_SDS_PLATFORM_INFO_SIZE,
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index 430aab6..27ea7f7 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -127,13 +127,14 @@
 	int ret;
 	struct n1sdp_plat_info plat_info;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SDS initialization failed\n");
 		panic();
 	}
 
-	ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+				N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
 				N1SDP_SDS_PLATFORM_INFO_OFFSET,
 				&plat_info,
 				N1SDP_SDS_PLATFORM_INFO_SIZE,
diff --git a/plat/arm/board/n1sdp/n1sdp_image_load.c b/plat/arm/board/n1sdp/n1sdp_image_load.c
index 6c3528c..6ae2b26 100644
--- a/plat/arm/board/n1sdp/n1sdp_image_load.c
+++ b/plat/arm/board/n1sdp/n1sdp_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,7 @@
 
 #include "n1sdp_def.h"
 #include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
 
 /*
  * Platform information structure stored in SDS.
@@ -108,13 +109,14 @@
 	int ret;
 	struct n1sdp_plat_info plat_info;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SDS initialization failed. ret:%d\n", ret);
 		panic();
 	}
 
-	ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+				N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
 				N1SDP_SDS_PLATFORM_INFO_OFFSET,
 				&plat_info,
 				N1SDP_SDS_PLATFORM_INFO_SIZE,
diff --git a/plat/arm/board/n1sdp/n1sdp_plat.c b/plat/arm/board/n1sdp/n1sdp_plat.c
index 747ff06..42efdee 100644
--- a/plat/arm/board/n1sdp/n1sdp_plat.c
+++ b/plat/arm/board/n1sdp/n1sdp_plat.c
@@ -1,12 +1,14 @@
 /*
- * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <assert.h>
 
+#include <drivers/arm/css/sds.h>
 #include <drivers/arm/sbsa.h>
+#include <lib/utils_def.h>
 #include <plat/arm/common/plat_arm.h>
 
 #include "n1sdp_def.h"
@@ -71,3 +73,16 @@
 {
 	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
 }
+
+#if CSS_USE_SCMI_SDS_DRIVER
+static sds_region_desc_t n1sdp_sds_regions[] = {
+	{ .base = PLAT_ARM_SDS_MEM_BASE },
+};
+
+sds_region_desc_t *plat_sds_get_regions(unsigned int *region_count)
+{
+	*region_count = ARRAY_SIZE(n1sdp_sds_regions);
+
+	return n1sdp_sds_regions;
+}
+#endif /* CSS_USE_SCMI_SDS_DRIVER */
diff --git a/plat/arm/board/tc/fdts/tc_spmc_common_sp_manifest.dtsi b/plat/arm/board/tc/fdts/tc_spmc_common_sp_manifest.dtsi
new file mode 100644
index 0000000..06c2937
--- /dev/null
+++ b/plat/arm/board/tc/fdts/tc_spmc_common_sp_manifest.dtsi
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Secure world memory map. For a full view of the DRAM map, see platform_def.h
+ *
+ *  0xf900_c000  ------------------
+ *               |       ...      |
+ *  0xf901_c000  ------------------
+ *               |     (63MB)     |  Trusty (=/=> OP-TEE)
+ *  0xfcf1_c000  ------------------
+ *               |       ...      |
+ *  0xfd00_0000  ------------------
+ *               |     (512K)     |  Hafnium
+ *  0xfd08_0000  ------------------
+ *               |       ...      |  Hafnium stack
+ *  0xfd28_0000  ------------------
+ *               |     (11MB)     |  OP-TEE (=/=> Trusty)
+ *  0xfdd8_0000  ------------------
+ *               |       ...      |
+ *  0xfde0_0000  ------------------
+ *               |     (2MB)      |  Firmware Upgrade
+ *  0xfec0_0000  ------------------
+ *               |     (2MB)      |  Crypto
+ *  0xfee0_0000	 ------------------
+ *               |     (2MB)      |  Internal Truested Storage
+ *  0xff00_0000  ------------------
+ */
+&hafnium {
+	vm1 {
+		is_ffa_partition;
+		vcpu_count = <8>;
+		/* partition information filled in separately */
+	};
+#ifdef TS_SP_FW_CONFIG
+	vm2 {
+		is_ffa_partition;
+		debug_name = "internal-trusted-storage";
+		load_address = <0xfee00000>;
+		vcpu_count = <1>;
+		mem_size = <0x200000>; /* 2MB TZC DRAM */
+	};
+	vm3 {
+		is_ffa_partition;
+		debug_name = "crypto";
+		load_address = <0xfec00000>;
+		vcpu_count = <1>;
+		mem_size = <0x200000>; /* 2MB TZC DRAM */
+	};
+	vm4 {
+		is_ffa_partition;
+		debug_name = "firmware-update";
+		load_address = <0xfde00000>;
+		vcpu_count = <1>;
+		mem_size = <0xe00000>; /* 14MB TZC DRAM */
+	};
+#endif
+};
diff --git a/plat/arm/board/tc/fdts/tc_spmc_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_manifest.dtsi
similarity index 66%
rename from plat/arm/board/tc/fdts/tc_spmc_manifest.dts
rename to plat/arm/board/tc/fdts/tc_spmc_manifest.dtsi
index 8ef6330..3bc0cbb 100644
--- a/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_manifest.dtsi
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
-/dts-v1/;
+#include <platform_def.h>
 
 / {
 	compatible = "arm,ffa-core-manifest-1.0";
@@ -20,36 +20,9 @@
 		binary_size = <0x80000>;
 	};
 
-	hypervisor {
+	hafnium:hypervisor {
 		compatible = "hafnium,hafnium";
-		vm1 {
-			is_ffa_partition;
-			debug_name = "cactus-primary";
-			load_address = <0xfe000000>;
-			vcpu_count = <8>;
-			mem_size = <1048576>;
-		};
-		vm2 {
-			is_ffa_partition;
-			debug_name = "cactus-secondary";
-			load_address = <0xfe100000>;
-			vcpu_count = <8>;
-			mem_size = <1048576>;
-		};
-		vm3 {
-			is_ffa_partition;
-			debug_name = "cactus-tertiary";
-			load_address = <0xfe200000>;
-			vcpu_count = <1>;
-			mem_size = <1048576>;
-		};
-		vm4 {
-			is_ffa_partition;
-			debug_name = "ivy";
-			load_address = <0xfe600000>;
-			vcpu_count = <1>;
-			mem_size = <1048576>;
-		};
+		/* filled in in top level .dts */
 	};
 
 	cpus {
@@ -117,16 +90,21 @@
 		};
 	};
 
+	/* the full secure world range */
 	memory@0 {
 		device_type = "memory";
-		reg = <0x0 0xfd000000 0x0 0x2000000>,
-		      <0x0 0x7000000 0x0 0x1000000>,
+		reg = <0x0 TC_TZC_DRAM1_BASE 0x0 TC_TZC_DRAM1_SIZE>,
 		      <0x0 0xff000000 0x0 0x1000000>;
 	};
 
 	memory@1 {
 		device_type = "ns-memory";
-		reg = <0x00008800 0x80000000 0x0 0x7f000000>,
-		      <0x0 0x88000000 0x1 0x00000000>;
+		reg =
+#ifdef TS_SP_FW_CONFIG
+		      <0x0 0x08000000 0x0 0x4000000>,
+#endif /* TS_SP_FW_CONFIG */
+		      <0x0 TC_NS_DRAM1_BASE 0x0 TC_NS_DRAM1_SIZE>,
+		      <HI(PLAT_ARM_DRAM2_BASE) LO(PLAT_ARM_DRAM2_BASE)
+		       HI(TC_NS_DRAM2_SIZE) LO(TC_NS_DRAM2_SIZE)>;
 	};
 };
diff --git a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
index 73314ee..840b80f 100644
--- a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
@@ -1,129 +1,17 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 /dts-v1/;
 
-/ {
-	compatible = "arm,ffa-core-manifest-1.0";
-	#address-cells = <2>;
-	#size-cells = <2>;
-
-	attribute {
-		spmc_id = <0x8000>;
-		maj_ver = <0x1>;
-		min_ver = <0x2>;
-		exec_state = <0x0>;
-		load_address = <0x0 0xfd000000>;
-		entrypoint = <0x0 0xfd000000>;
-		binary_size = <0x80000>;
-	};
-
-	hypervisor {
-		compatible = "hafnium,hafnium";
-		vm1 {
-			is_ffa_partition;
-			debug_name = "op-tee";
-			load_address = <0xfd280000>;
-			vcpu_count = <8>;
-#ifdef TS_SP_FW_CONFIG
-			mem_size = <26738688>; /* 25MB TZC DRAM */
-#else
-			mem_size = <30928896>; /* 29MB TZC DRAM */
-#endif
-		};
-#ifdef TS_SP_FW_CONFIG
-		vm2 {
-			is_ffa_partition;
-			debug_name = "internal-trusted-storage";
-			load_address = <0xfee00000>;
-			vcpu_count = <1>;
-			mem_size = <2097152>; /* 2MB TZC DRAM */
-		};
-		vm3 {
-			is_ffa_partition;
-			debug_name = "crypto";
-			load_address = <0xfec00000>;
-			vcpu_count = <1>;
-			mem_size = <2097152>; /* 2MB TZC DRAM */
-		};
-#endif
-	};
-
-	cpus {
-		#address-cells = <0x2>;
-		#size-cells = <0x0>;
-
-		CPU0:cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
-		};
-
-		/*
-		 * SPMC (Hafnium) requires secondary cpu nodes are declared in
-		 * descending order
-		 */
-		CPU7:cpu@700 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x700>;
-			enable-method = "psci";
-		};
-
-		CPU6:cpu@600 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x600>;
-			enable-method = "psci";
-		};
-
-		CPU5:cpu@500 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x500>;
-			enable-method = "psci";
-		};
-
-		CPU4:cpu@400 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x400>;
-			enable-method = "psci";
-		};
-
-		CPU3:cpu@300 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x300>;
-			enable-method = "psci";
-		};
-
-		CPU2:cpu@200 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x200>;
-			enable-method = "psci";
-		};
-
-		CPU1:cpu@100 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x100>;
-			enable-method = "psci";
-		};
-	};
-
-	memory@0 {
-		device_type = "memory";
-		reg = <0x0 0xfd000000 0x0 0x2000000>;
-	};
+#include <tc_spmc_manifest.dtsi>
+#include <tc_spmc_common_sp_manifest.dtsi>
 
-	memory@1 {
-		device_type = "ns-memory";
-		reg = <0x0 0x80000000 0x0 0x79000000>,
-		      <0x80 0x80000000 0x1 0x80000000>;
+&hafnium {
+	vm1 {
+		debug_name = "op-tee";
+		load_address = <0xfd280000>;
+		mem_size = <0xb00000>; /* 11MB TZC DRAM */
 	};
 };
diff --git a/plat/arm/board/tc/fdts/tc_spmc_test_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_test_manifest.dts
new file mode 100644
index 0000000..2e35f82
--- /dev/null
+++ b/plat/arm/board/tc/fdts/tc_spmc_test_manifest.dts
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#include <tc_spmc_manifest.dtsi>
+
+/ {
+	hypervisor {
+		vm1 {
+			is_ffa_partition;
+			debug_name = "cactus-primary";
+			load_address = <0xfe000000>;
+			vcpu_count = <8>;
+			mem_size = <1048576>;
+		};
+		vm2 {
+			is_ffa_partition;
+			debug_name = "cactus-secondary";
+			load_address = <0xfe100000>;
+			vcpu_count = <8>;
+			mem_size = <1048576>;
+		};
+		vm3 {
+			is_ffa_partition;
+			debug_name = "cactus-tertiary";
+			load_address = <0xfe200000>;
+			vcpu_count = <1>;
+			mem_size = <1048576>;
+		};
+		vm4 {
+			is_ffa_partition;
+			debug_name = "ivy";
+			load_address = <0xfe600000>;
+			vcpu_count = <1>;
+			mem_size = <1048576>;
+		};
+	};
+};
diff --git a/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts
new file mode 100644
index 0000000..8233eda
--- /dev/null
+++ b/plat/arm/board/tc/fdts/tc_spmc_trusty_sp_manifest.dts
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#include <tc_spmc_manifest.dtsi>
+#include <tc_spmc_common_sp_manifest.dtsi>
+
+&hafnium {
+	vm1 {
+		debug_name = "trusty";
+		load_address = <0xf901c000>;
+		mem_size = <0x3f00000>; /* 64MB TZC DRAM - 1MB align */
+	};
+};
diff --git a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
index 4c6ccef..c58f17b 100644
--- a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
+++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -41,12 +41,21 @@
 		       uuid = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0";
 		       load-address = <0xfec00000>;
 		};
+		firmware-update {
+		       uuid = "6823a838-1b06-470e-9774-0cce8bfb53fd";
+		       load-address = <0xfde00000>;
+		};
 #endif
 #if OPTEE_SP_FW_CONFIG
 		op-tee {
 		       uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b";
 		       load-address = <0xfd280000>;
 		};
+#elif TRUSTY_SP_FW_CONFIG
+		trusty {
+		       uuid = "40ee25f0-a2bc-304c-8c4c-a173c57d8af1";
+		       load-address = <0xf901c000>;
+		};
 #else
 		cactus-primary {
 			uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb";
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 59fff6e..130111e 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,8 +17,6 @@
 #include <plat/arm/soc/common/soc_css_def.h>
 #include <plat/common/common_def.h>
 
-#define PLATFORM_CORE_COUNT		8
-
 #define PLAT_ARM_TRUSTED_SRAM_SIZE	0x00080000	/* 512 KB */
 
 /*
@@ -30,6 +28,12 @@
  *   - Region to load secure partitions
  *
  *
+ *  0xf8a0_0000  ------------------   TC_NS_FWU_BASE
+ *               |    FWU shmem   |
+ *               |      (4MB)     |
+ *  0xf8e0_0000  ------------------   TC_NS_OPTEE_BASE
+ *               |  OP-TEE shmem  |
+ *               |      (2MB)     |
  *  0xF900_0000  ------------------   TC_TZC_DRAM1_BASE
  *               |                |
  *               |      SPMC      |
@@ -46,7 +50,7 @@
  */
 #define TC_TZC_DRAM1_BASE		(ARM_AP_TZC_DRAM1_BASE -	\
 					 TC_TZC_DRAM1_SIZE)
-#define TC_TZC_DRAM1_SIZE		96 * SZ_1M	/* 96 MB */
+#define TC_TZC_DRAM1_SIZE		(96 * SZ_1M)	/* 96 MB */
 #define TC_TZC_DRAM1_END		(TC_TZC_DRAM1_BASE +		\
 					 TC_TZC_DRAM1_SIZE - 1)
 
@@ -54,8 +58,12 @@
 #define TC_NS_DRAM1_SIZE		(ARM_DRAM1_SIZE -		\
 					 ARM_TZC_DRAM1_SIZE -		\
 					 TC_TZC_DRAM1_SIZE)
-#define TC_NS_DRAM1_END		(TC_NS_DRAM1_BASE +		\
-					 TC_NS_DRAM1_SIZE - 1)
+#define TC_NS_DRAM1_END			(TC_NS_DRAM1_BASE + TC_NS_DRAM1_SIZE - 1)
+
+#define TC_NS_OPTEE_SIZE		(2 * SZ_1M)
+#define TC_NS_OPTEE_BASE		(TC_NS_DRAM1_BASE + TC_NS_DRAM1_SIZE - TC_NS_OPTEE_SIZE)
+#define TC_NS_FWU_SIZE			(4 * SZ_1M)
+#define TC_NS_FWU_BASE			(TC_NS_OPTEE_BASE - TC_NS_FWU_SIZE)
 
 /*
  * Mappings for TC DRAM1 (non-secure) and TC TZC DRAM1 (secure)
@@ -137,7 +145,7 @@
  * little space for growth. Current size is considering that TRUSTED_BOARD_BOOT
  * and MEASURED_BOOT is enabled.
  */
-# define PLAT_ARM_MAX_BL2_SIZE		0x26000
+# define PLAT_ARM_MAX_BL2_SIZE		0x29000
 
 
 /*
@@ -186,6 +194,13 @@
 #define TC_DEVICE_BASE			0x21000000
 #define TC_DEVICE_SIZE			0x5f000000
 
+#if defined(TARGET_FLAVOUR_FPGA)
+#undef V2M_FLASH0_BASE
+#undef V2M_FLASH0_SIZE
+#define V2M_FLASH0_BASE			UL(0x0C000000)
+#define V2M_FLASH0_SIZE			UL(0x02000000)
+#endif
+
 // TC_MAP_DEVICE covers different peripherals
 // available to the platform
 #define TC_MAP_DEVICE	MAP_REGION_FLAT(		\
@@ -206,12 +221,24 @@
 #define PLAT_ARM_TRUSTED_ROM_SIZE	(0x00080000 - PLAT_ARM_TRUSTED_ROM_BASE)
 
 #define PLAT_ARM_NSRAM_BASE		0x06000000
+#if TARGET_FLAVOUR_FVP
 #define PLAT_ARM_NSRAM_SIZE		0x00080000	/* 512KB */
+#else /* TARGET_FLAVOUR_FPGA */
+#define PLAT_ARM_NSRAM_SIZE		0x00008000	/* 64KB */
+#endif /* TARGET_FLAVOUR_FPGA */
 
+#if TARGET_PLATFORM <= 2
 #define PLAT_ARM_DRAM2_BASE		ULL(0x8080000000)
+#elif TARGET_PLATFORM == 3
+#define PLAT_ARM_DRAM2_BASE		ULL(0x880000000)
+#endif /* TARGET_PLATFORM == 3 */
 #define PLAT_ARM_DRAM2_SIZE		ULL(0x180000000)
 #define PLAT_ARM_DRAM2_END		(PLAT_ARM_DRAM2_BASE + PLAT_ARM_DRAM2_SIZE - 1ULL)
 
+#define TC_NS_MTE_SIZE			(256 * SZ_1M)
+/* the SCP puts the carveout at the end of DRAM2 */
+#define TC_NS_DRAM2_SIZE		(PLAT_ARM_DRAM2_SIZE - TC_NS_MTE_SIZE)
+
 #define PLAT_ARM_G1S_IRQ_PROPS(grp)	CSS_G1S_INT_PROPS(grp)
 #define PLAT_ARM_G0_IRQ_PROPS(grp)	ARM_G0_IRQ_PROPS(grp),	\
 					INTR_PROP_DESC(SBSA_SECURE_WDOG_INTID,	\
@@ -221,6 +248,8 @@
 #define PLAT_ARM_SP_IMAGE_STACK_BASE	(PLAT_SP_IMAGE_NS_BUF_BASE +	\
 					 PLAT_SP_IMAGE_NS_BUF_SIZE)
 
+#define PLAT_ARM_SP_MAX_SIZE		U(0x2000000)
+
 /*******************************************************************************
  * Memprotect definitions
  ******************************************************************************/
@@ -240,12 +269,33 @@
 
 #define PLAT_ARM_SCMI_CHANNEL_COUNT	1
 
+/* Index of SDS region used in the communication with SCP */
+#define SDS_SCP_AP_REGION_ID		U(0)
+/* Index of SDS region used in the communication with RSS */
+#define SDS_RSS_AP_REGION_ID		U(1)
+/*
+ * Memory region for RSS's shared data storage (SDS)
+ * It is placed right after the SCMI payload area.
+ */
+#define PLAT_ARM_RSS_AP_SDS_MEM_BASE	(CSS_SCMI_PAYLOAD_BASE + \
+					 CSS_SCMI_PAYLOAD_SIZE_MAX)
+
 #define PLAT_ARM_CLUSTER_COUNT		U(1)
+#if TARGET_FLAVOUR_FPGA && TARGET_PLATFORM == 2
+#define PLAT_MAX_CPUS_PER_CLUSTER	U(14)
+#else /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM == 2 */
 #define PLAT_MAX_CPUS_PER_CLUSTER	U(8)
+#endif /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM == 2 */
 #define PLAT_MAX_PE_PER_CPU		U(1)
 
+#define PLATFORM_CORE_COUNT		(PLAT_MAX_CPUS_PER_CLUSTER * PLAT_ARM_CLUSTER_COUNT)
+
 /* Message Handling Unit (MHU) base addresses */
-#define PLAT_CSS_MHU_BASE		UL(0x45400000)
+#if TARGET_PLATFORM <= 2
+	#define PLAT_CSS_MHU_BASE		UL(0x45400000)
+#elif TARGET_PLATFORM == 3
+	#define PLAT_CSS_MHU_BASE		UL(0x46000000)
+#endif /* TARGET_PLATFORM == 3 */
 #define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /* TC2: AP<->RSS MHUs */
@@ -322,4 +372,43 @@
 #define PLAT_ARM_FIP_OFFSET_IN_GPT		0x6000
 #endif /* ARM_GPT_SUPPORT */
 
+/* UART related constants */
+
+#define TC_UART0			0x2a400000
+#define TC_UART1			0x2a410000
+
+/*
+ * TODO: if any more undefs are needed, it's better to consider dropping the
+ * board_css_def.h include above
+ */
+#undef PLAT_ARM_BOOT_UART_BASE
+#undef PLAT_ARM_RUN_UART_BASE
+#undef PLAT_ARM_SP_MIN_RUN_UART_BASE
+#define PLAT_ARM_SP_MIN_RUN_UART_BASE	PLAT_ARM_RUN_UART_BASE
+
+#undef PLAT_ARM_CRASH_UART_BASE
+#undef PLAT_ARM_BOOT_UART_CLK_IN_HZ
+#undef PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#if TARGET_FLAVOUR_FVP
+#define PLAT_ARM_BOOT_UART_BASE		TC_UART1
+#define TC_UARTCLK			7372800
+#else /* TARGET_FLAVOUR_FPGA */
+#define PLAT_ARM_BOOT_UART_BASE		TC_UART0
+#if TARGET_PLATFORM <= 2
+#define TC_UARTCLK			5000000
+#elif TARGET_PLATFORM >= 3
+#define TC_UARTCLK			3750000
+#endif /* TARGET_PLATFORM >= 3 */
+#undef  ARM_CONSOLE_BAUDRATE
+#define ARM_CONSOLE_BAUDRATE		38400
+#endif /* TARGET_FLAVOUR_FPGA */
+
+#define PLAT_ARM_RUN_UART_BASE		TC_UART0
+#define PLAT_ARM_SP_MIN_RUN_UART_BASE	PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_BASE	PLAT_ARM_RUN_UART_BASE
+
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ	TC_UARTCLK
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ	TC_UARTCLK
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/tc/plat_tc_mbedtls_config.h b/plat/arm/board/tc/plat_tc_mbedtls_config.h
index 773629c..de7b1aa 100644
--- a/plat/arm/board/tc/plat_tc_mbedtls_config.h
+++ b/plat/arm/board/tc/plat_tc_mbedtls_config.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023, Arm Ltd. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Ltd. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,11 +19,12 @@
 #undef TF_MBEDTLS_HEAP_SIZE
 #define TF_MBEDTLS_HEAP_SIZE	PLATFORM_TEST_MIN_MBEDTLS_HEAP_SIZE
 #endif
-#endif
+#endif /* TF_MBEDTLS_HEAP_SIZE */
 
 #define MBEDTLS_PSA_CRYPTO_C
 #define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
 #define MBEDTLS_ECP_C
 #define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_NO_INTERNAL_RNG
 
 #endif /* PLAT_TC_MBEDTLS_CONFIG_H */
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 6874cfa..5be1234 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -1,24 +1,38 @@
-# Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 include common/fdt_wrappers.mk
 
-ifeq ($(TARGET_PLATFORM), 0)
-	$(error Platform ${PLAT}$(TARGET_PLATFORM) is deprecated.)
-endif
+TARGET_FLAVOUR			:=	fvp
+# DPU with SCMI may not necessarily work, so allow its independence
+TC_DPU_USE_SCMI_CLK		:=	1
+# SCMI power domain control enable
+TC_SCMI_PD_CTRL_EN		:=	1
+# IOMMU: Enable the use of system or individual MMUs
+TC_IOMMU_EN			:=	1
 
-ifeq ($(TARGET_PLATFORM), 1)
+ifneq ($(shell expr $(TARGET_PLATFORM) \<= 1), 0)
         $(warning Platform ${PLAT}$(TARGET_PLATFORM) is deprecated. \
           Some of the features might not work as expected)
 endif
 
+ifeq ($(shell expr $(TARGET_PLATFORM) \<= 3), 0)
+        $(error TARGET_PLATFORM must be less than or equal to 3)
+endif
+
-ifeq ($(shell expr $(TARGET_PLATFORM) \<= 2), 0)
-        $(error TARGET_PLATFORM must be less than or equal to 2)
+ifeq ($(filter ${TARGET_FLAVOUR}, fvp fpga),)
+        $(error TARGET_FLAVOUR must be fvp or fpga)
 endif
 
-$(eval $(call add_define,TARGET_PLATFORM))
+$(eval $(call add_defines, \
+	TARGET_PLATFORM \
+	TARGET_FLAVOUR_$(call uppercase,${TARGET_FLAVOUR}) \
+	TC_DPU_USE_SCMI_CLK \
+	TC_SCMI_PD_CTRL_EN \
+	TC_IOMMU_EN \
+))
 
 CSS_LOAD_SCP_IMAGES	:=	1
 
@@ -70,7 +84,8 @@
 
 TC_BASE	=	plat/arm/board/tc
 
-PLAT_INCLUDES		+=	-I${TC_BASE}/include/
+PLAT_INCLUDES		+=	-I${TC_BASE}/include/ \
+				-I${TC_BASE}/fdts/
 
 # CPU libraries for TARGET_PLATFORM=1
 ifeq (${TARGET_PLATFORM}, 1)
@@ -86,6 +101,13 @@
 			lib/cpus/aarch64/cortex_x4.S
 endif
 
+# CPU libraries for TARGET_PLATFORM=3
+ifeq (${TARGET_PLATFORM}, 3)
+TC_CPU_SOURCES	+=	lib/cpus/aarch64/cortex_a520.S \
+			lib/cpus/aarch64/cortex_chaberton.S \
+			lib/cpus/aarch64/cortex_blackhawk.S
+endif
+
 INTERCONNECT_SOURCES	:=	${TC_BASE}/tc_interconnect.c
 
 PLAT_BL_COMMON_SOURCES	+=	${TC_BASE}/tc_plat.c	\
@@ -133,7 +155,7 @@
 
 ifeq (${SPD},spmd)
 ifeq ($(ARM_SPMC_MANIFEST_DTS),)
-ARM_SPMC_MANIFEST_DTS	:=	${TC_BASE}/fdts/${PLAT}_spmc_manifest.dts
+ARM_SPMC_MANIFEST_DTS	:=	${TC_BASE}/fdts/${PLAT}_spmc_test_manifest.dts
 endif
 
 FDT_SOURCES		+=	${ARM_SPMC_MANIFEST_DTS}
@@ -159,11 +181,11 @@
 override ENABLE_SPE_FOR_NS	:= 0
 
 override ENABLE_FEAT_AMU := 1
-override ENABLE_AMU_AUXILIARY_COUNTERS := 1
-override ENABLE_AMU_FCONF := 1
+ENABLE_AMU_AUXILIARY_COUNTERS := 1
+ENABLE_AMU_FCONF := 1
 
-override ENABLE_MPMM := 1
-override ENABLE_MPMM_FCONF := 1
+ENABLE_MPMM := 1
+ENABLE_MPMM_FCONF := 1
 
 # Include Measured Boot makefile before any Crypto library makefile.
 # Crypto library makefile may need default definitions of Measured Boot build
diff --git a/plat/arm/board/tc/platform_test.mk b/plat/arm/board/tc/platform_test.mk
index 2fd5ea0..4e81b2c 100644
--- a/plat/arm/board/tc/platform_test.mk
+++ b/plat/arm/board/tc/platform_test.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2022-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -13,7 +13,6 @@
 
     # Code under testing.
     BL31_SOURCES	+=	lib/psa/rss_platform.c \
-				drivers/arm/rss/rss_comms.c \
 				${RSS_COMMS_SOURCES}
 
     PLAT_INCLUDES	+=	-Iinclude/lib/psa
@@ -27,13 +26,13 @@
 
     # Code under testing.
     BL31_SOURCES	+=	lib/psa/rss_platform.c \
-				drivers/arm/rss/rss_comms.c \
 				${RSS_COMMS_SOURCES}
 
     PLAT_INCLUDES	+=	-Iinclude/lib/psa
 
     $(eval $(call add_define,PLATFORM_TEST_ROTPK))
 else ifeq (${PLATFORM_TEST},tfm-testsuite)
+    include drivers/arm/rss/rss_comms.mk
 
     # The variables need to be set to compile the platform test:
     ifeq (${TF_M_TESTS_PATH},)
@@ -56,7 +55,7 @@
 
     MBEDTLS_CONFIG_FILE		=	"<plat_tc_mbedtls_config.h>"
 
-    LIBMBEDTLS_SRCS		+= 	$(addprefix ${MBEDTLS_DIR}/library/,	\
+    LIBMBEDTLS_SRCS		+=	$(addprefix ${MBEDTLS_DIR}/library/,	\
 					entropy.c				\
 					entropy_poll.c				\
 					hmac_drbg.c				\
@@ -69,30 +68,31 @@
 					psa_crypto_slot_management.c		\
 					)
 
-    BL31_SOURCES	+=	${RSS_COMMS_SOURCES} 				\
-				plat/arm/common/arm_dyn_cfg.c 			\
-				${TC_BASE}/rss_ap_tests.c 			\
-				${TC_BASE}/rss_ap_testsuites.c 			\
+    BL31_SOURCES	+=	${RSS_COMMS_SOURCES}				\
+				plat/arm/common/arm_dyn_cfg.c			\
+				${TC_BASE}/rss_ap_tests.c			\
+				${TC_BASE}/rss_ap_testsuites.c			\
 				${TC_BASE}/rss_ap_test_stubs.c			\
-				$(TF_M_TESTS_PATH)/test/framework/test_framework.c \
+				$(TF_M_TESTS_PATH)/tests_reg/test/framework/test_framework.c \
 				$(MEASURED_BOOT_TESTS_PATH)/measured_boot_common.c \
 				$(MEASURED_BOOT_TESTS_PATH)/measured_boot_tests_common.c \
 				$(DELEGATED_ATTEST_TESTS_PATH)/delegated_attest_test.c \
-				drivers/auth/mbedtls/mbedtls_common.c 		\
-				lib/psa/measured_boot.c 			\
+				drivers/auth/mbedtls/mbedtls_common.c		\
+				lib/psa/measured_boot.c				\
 				lib/psa/delegated_attestation.c
 
     PLAT_INCLUDES	+=	-I$(TF_M_EXTRAS_PATH)/partitions/measured_boot/interface/include \
 				-I$(TF_M_EXTRAS_PATH)/partitions/delegated_attestation/interface/include \
-				-I$(TF_M_TESTS_PATH)/test/framework 		\
-				-I$(TF_M_TESTS_PATH)/log 			\
-				-I$(TF_M_TESTS_PATH)/test/secure_fw/suites/extra \
-				-I$(MEASURED_BOOT_TESTS_PATH)/non_secure 	\
-				-I$(DELEGATED_ATTEST_TESTS_PATH) 		\
-				-I$(DELEGATED_ATTEST_TESTS_PATH)/non_secure \
-				-Iplat/arm/board/tc 				\
-				-Iinclude/drivers/auth/mbedtls 			\
-				-Iinclude/drivers/arm
+				-I$(TF_M_TESTS_PATH)/tests_reg/test/framework	\
+				-I$(TF_M_TESTS_PATH)/tests_reg/test/secure_fw/suites/extra \
+				-I$(TF_M_TESTS_PATH)/lib/log			\
+				-I$(MEASURED_BOOT_TESTS_PATH)/non_secure	\
+				-I$(DELEGATED_ATTEST_TESTS_PATH)		\
+				-I$(DELEGATED_ATTEST_TESTS_PATH)/non_secure	\
+				-Iplat/arm/board/tc				\
+				-Iinclude/drivers/auth/mbedtls			\
+				-Iinclude/drivers/arm				\
+				-Iinclude/lib/psa
 
     # Some of the PSA functions are declared in multiple header files, that
     # triggers this warning.
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index aac7ece..d884366 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -75,6 +75,25 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
+	/*
+	 * Pass the hw_config to BL33 in R0. You'll notice that
+	 * arm_bl31_early_platform_setup does something similar but only behind
+	 * ARM_LINUX_KERNEL_AS_BL33 and we want to pass the DTB even to a
+	 * bootloader. Lucky for us, it copies the ep_info BL2 gave us to BL33
+	 * unconditionally in the generic case so hijack that.
+	 * TODO: this goes away with firmware handoff when it will be proper
+	 */
+
+	bl_params_node_t *bl_params = ((bl_params_t *)arg0)->head;
+
+	while (bl_params != NULL) {
+		if (bl_params->image_id == BL33_IMAGE_ID) {
+			bl_params->ep_info->args.arg0 = arg2;
+			break;
+		}
+		bl_params = bl_params->next_params_info;
+	}
+
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 
 	/* Fill the properties struct with the info from the config dtb */
diff --git a/plat/arm/board/tc/tc_plat.c b/plat/arm/board/tc/tc_plat.c
index 766bfb5..e5d05c4 100644
--- a/plat/arm/board/tc/tc_plat.c
+++ b/plat/arm/board/tc/tc_plat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,8 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <drivers/arm/ccn.h>
+#include <drivers/arm/css/sds.h>
+#include <lib/utils_def.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <drivers/arm/sbsa.h>
@@ -28,6 +30,7 @@
 #if IMAGE_BL1
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
+	TC_MAP_NS_DRAM1,
 	TC_FLASH0_RO,
 	TC_MAP_DEVICE,
 	{0}
@@ -159,3 +162,15 @@
 {
 	sbsa_wdog_refresh(SBSA_SECURE_WDOG_REFRESH_BASE);
 }
+
+static sds_region_desc_t tc_sds_regions[] = {
+	{ .base = PLAT_ARM_SDS_MEM_BASE },
+	{ .base = PLAT_ARM_RSS_AP_SDS_MEM_BASE },
+};
+
+sds_region_desc_t *plat_sds_get_regions(unsigned int *region_count)
+{
+	*region_count = ARRAY_SIZE(tc_sds_regions);
+
+	return tc_sds_regions;
+}
diff --git a/plat/arm/board/tc/tc_topology.c b/plat/arm/board/tc/tc_topology.c
index 9e18da6..cc0dcc2 100644
--- a/plat/arm/board/tc/tc_topology.c
+++ b/plat/arm/board/tc/tc_topology.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <plat/arm/common/plat_arm.h>
 #include <plat/arm/css/common/css_pm.h>
+#include <platform_def.h>
 
 /******************************************************************************
  * The power domain tree descriptor.
@@ -36,6 +37,14 @@
 	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
 	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
 	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+#if PLATFORM_CORE_COUNT == 14
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)),
+#endif /* PLATFORM_CORE_COUNT == 14 */
 };
 
 /*******************************************************************************
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index dab5f8b..2126a86 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -298,6 +298,8 @@
 
 #endif
 
+/* Index of SDS region used in the communication with SCP */
+#define SDS_SCP_AP_REGION_ID			U(0)
 /* SDS ID for unusable CPU MPID list structure */
 #define SDS_ISOLATED_CPU_LIST_ID		U(128)
 
diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c
index ac4bfd2..0a9bba9 100644
--- a/plat/arm/css/sgi/sgi_image_load.c
+++ b/plat/arm/css/sgi/sgi_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -30,13 +30,14 @@
 {
 	int ret;
 
-	ret = sds_init();
+	ret = sds_init(SDS_SCP_AP_REGION_ID);
 	if (ret != SDS_OK) {
 		ERROR("SDS initialization failed, error: %d\n", ret);
 		panic();
 	}
 
-	ret = sds_struct_read(SDS_ISOLATED_CPU_LIST_ID, 0, &list->num_entries,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+			SDS_ISOLATED_CPU_LIST_ID, 0, &list->num_entries,
 			sizeof(list->num_entries), SDS_ACCESS_MODE_CACHED);
 	if (ret != SDS_OK) {
 		INFO("SDS CPU num elements read failed, error: %d\n", ret);
@@ -54,7 +55,8 @@
 		return;
 	}
 
-	ret = sds_struct_read(SDS_ISOLATED_CPU_LIST_ID,
+	ret = sds_struct_read(SDS_SCP_AP_REGION_ID,
+			SDS_ISOLATED_CPU_LIST_ID,
 			sizeof(list->num_entries),
 			&list->mpid_list,
 			sizeof(list->mpid_list[0]) * list->num_entries,
@@ -152,4 +154,3 @@
 
 	return arm_get_next_bl_params();
 }
-
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index 01b426e..fe64d34 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,8 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <drivers/arm/ccn.h>
+#include <drivers/arm/css/sds.h>
+#include <lib/utils_def.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <drivers/arm/sbsa.h>
@@ -174,3 +176,14 @@
 {
 	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
 }
+
+static sds_region_desc_t sgi_sds_regions[] = {
+	{ .base = PLAT_ARM_SDS_MEM_BASE },
+};
+
+sds_region_desc_t *plat_sds_get_regions(unsigned int *region_count)
+{
+	*region_count = ARRAY_SIZE(sgi_sds_regions);
+
+	return sgi_sds_regions;
+}
diff --git a/plat/arm/css/sgi/sgi_plat_v2.c b/plat/arm/css/sgi/sgi_plat_v2.c
index 624fed3..d241f70 100644
--- a/plat/arm/css/sgi/sgi_plat_v2.c
+++ b/plat/arm/css/sgi/sgi_plat_v2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,9 +8,11 @@
 
 #include <platform_def.h>
 
+#include <lib/utils_def.h>
+#include <drivers/arm/css/sds.h>
+#include <drivers/arm/sbsa.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
-#include <drivers/arm/sbsa.h>
 
 #if SPM_MM
 #include <services/spm_mm_partition.h>
@@ -176,3 +178,14 @@
 {
 	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
 }
+
+static sds_region_desc_t sgi_sds_regions[] = {
+	{ .base = PLAT_ARM_SDS_MEM_BASE },
+};
+
+sds_region_desc_t *plat_sds_get_regions(unsigned int *region_count)
+{
+	*region_count = ARRAY_SIZE(sgi_sds_regions);
+
+	return sgi_sds_regions;
+}
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
index 956b508..a95eb36 100644
--- a/plat/imx/imx8m/imx8mp/gpc.c
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -374,12 +374,20 @@
 	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
 	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
 
-	/* enable all the power domain by default */
+	/* enable all clocks by default */
 	for (i = 0; i < 101; i++) {
 		mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
 	}
 
-	for (i = 0; i < 20; i++) {
-		imx_gpc_pm_domain_enable(i, true);
-	}
+	/* Depending on SKU, we may be lacking e.g. a VPU and shouldn't
+	 * access that domain here, because that would lockup the SoC.
+	 * Other i.MX8M variants don't initialize any power domains, but
+	 * for 8MP we have been enabling the USB power domains since the
+	 * beginning and stopping to do this now may render systems
+	 * unrecoverable. So we'll keep initializing just the USB power
+	 * domains instead of all of them like before.
+	 */
+	imx_gpc_pm_domain_enable(HSIOMIX, true);
+	imx_gpc_pm_domain_enable(USB1_PHY, true);
+	imx_gpc_pm_domain_enable(USB2_PHY, true);
 }
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index 2365564..6ca90a0 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
 # Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
@@ -82,7 +82,7 @@
 INCLUDES	+=	-Iinclude/lib/libc		\
 			-Iinclude/lib/libc/$(ARCH)	\
 
-ifneq ($(findstring armlink,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),arm-link)
 # o suppress warnings for section mismatches, undefined symbols
 # o use only those libraries that are specified in the input file
 #   list to resolve references
diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
index 36d9f5b..16187ef 100644
--- a/plat/qemu/common/common.mk
+++ b/plat/qemu/common/common.mk
@@ -109,7 +109,9 @@
 
 # 8.5
 ENABLE_FEAT_RNG		:=	2
-ENABLE_FEAT_SB		:=	2
+# TF-A currently does not do dynamic detection of FEAT_SB.
+# Compiler puts SB instruction when it is enabled.
+ENABLE_FEAT_SB		:=	0
 
 # 8.6
 ENABLE_FEAT_FGT		:=	2
diff --git a/plat/renesas/rcar/platform.mk b/plat/renesas/rcar/platform.mk
index c95590d..5718478 100644
--- a/plat/renesas/rcar/platform.mk
+++ b/plat/renesas/rcar/platform.mk
@@ -371,7 +371,6 @@
 .PHONY: rcar_srecord
 rcar_srecord: $(BL2_ELF_SRC) $(BL31_ELF_SRC)
 	@echo "generating srec: ${SREC_PATH}/bl2.srec"
-	$(Q)$(OC) -O srec --srec-forceS3 ${BL2_ELF_SRC}  ${SREC_PATH}/bl2.srec
+	$(Q)$($(ARCH)-oc) -O srec --srec-forceS3 ${BL2_ELF_SRC}  ${SREC_PATH}/bl2.srec
 	@echo "generating srec: ${SREC_PATH}/bl31.srec"
-	$(Q)$(OC) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec
-
+	$(Q)$($(ARCH)-oc) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec
diff --git a/plat/renesas/rzg/platform.mk b/plat/renesas/rzg/platform.mk
index f37d7d0..89ca227 100644
--- a/plat/renesas/rzg/platform.mk
+++ b/plat/renesas/rzg/platform.mk
@@ -269,6 +269,6 @@
 .PHONY: rzg_srecord
 rzg_srecord: $(BL2_ELF_SRC) $(BL31_ELF_SRC)
 	@echo "generating srec: ${SREC_PATH}/bl2.srec"
-	$(Q)$(OC) -O srec --srec-forceS3 ${BL2_ELF_SRC}  ${SREC_PATH}/bl2.srec
+	$(Q)$($(ARCH)-oc) -O srec --srec-forceS3 ${BL2_ELF_SRC}  ${SREC_PATH}/bl2.srec
 	@echo "generating srec: ${SREC_PATH}/bl31.srec"
-	$(Q)$(OC) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec
+	$(Q)$($(ARCH)-oc) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec
diff --git a/plat/rockchip/rk3399/drivers/m0/Makefile b/plat/rockchip/rk3399/drivers/m0/Makefile
index 71548ba..2abcc18 100644
--- a/plat/rockchip/rk3399/drivers/m0/Makefile
+++ b/plat/rockchip/rk3399/drivers/m0/Makefile
@@ -4,6 +4,10 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+toolchains := rk3399-m0
+
+include ../../../../../make_helpers/toolchain.mk
+
 # Cross Compile
 M0_CROSS_COMPILE ?= arm-none-eabi-
 
@@ -38,13 +42,6 @@
 ASFLAGS			:= -Wa,--gdwarf-2
 LDFLAGS			:= -Wl,--gc-sections -Wl,--build-id=none
 
-# Cross tool
-CC			:= ${M0_CROSS_COMPILE}gcc
-CPP			:= ${M0_CROSS_COMPILE}gcc -E
-AR			:= ${M0_CROSS_COMPILE}gcc-ar
-OC			:= ${M0_CROSS_COMPILE}objcopy
-OD			:= ${M0_CROSS_COMPILE}objdump
-
 # NOTE: The line continuation '\' is required in the next define otherwise we
 # end up with a line-feed characer at the end of the last c filename.
 # Also bare this issue in mind if extending the list of supported filetypes.
@@ -75,7 +72,7 @@
 
 $(OBJ) : $(2)
 	@echo "  CC      $$<"
-	$$(Q)$$(CC) $$(COMMON_FLAGS) $$(CFLAGS) $$(INCLUDES) -MMD -MT $$@ -c $$< -o $$@
+	$$(Q)$(rk3399-m0-cc) $$(COMMON_FLAGS) $$(CFLAGS) $$(INCLUDES) -MMD -MT $$@ -c $$< -o $$@
 endef
 
 define MAKE_S
@@ -83,7 +80,7 @@
 
 $(OBJ) : $(2)
 	@echo "  AS      $$<"
-	$$(Q)$$(CC) -x assembler-with-cpp $$(COMMON_FLAGS) $$(ASFLAGS) -c $$< -o $$@
+	$$(Q)$(rk3399-m0-cc) -x assembler-with-cpp $$(COMMON_FLAGS) $$(ASFLAGS) -c $$< -o $$@
 endef
 
 define MAKE_OBJS
@@ -104,20 +101,20 @@
 .DEFAULT_GOAL := all
 
 $(LINKERFILE): $(LINKERFILE_SRC)
-	$(CC) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $<
+	$(rk3399-m0-cc) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $<
 -include $(LINKERFILE).d
 
 $(ELF) : $(OBJS) $(OBJS_COMMON) $(LINKERFILE)
 	@echo "  LD      $@"
-	$(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON)
+	$(Q)$(rk3399-m0-cc) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON)
 
 %.bin : %.elf
 	@echo "  BIN     $@"
-	$(Q)$(OC) -O binary $< $@
+	$(Q)$(rk3399-m0-oc) -O binary $< $@
 
 $(ELF_PMU) : $(OBJS_COMMON) $(OBJS_PMU) $(LINKERFILE)
 	@echo "  LD      $@"
-	$(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON)
+	$(Q)$(rk3399-m0-cc) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON)
 
 $(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_COMMON),$(1)))
 $(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES),$(1)))
diff --git a/plat/rpi/rpi3/platform.mk b/plat/rpi/rpi3/platform.mk
index 06393e4..26a3268 100644
--- a/plat/rpi/rpi3/platform.mk
+++ b/plat/rpi/rpi3/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -52,9 +52,9 @@
 				${LIBFDT_SRCS}
 
 # Tune compiler for Cortex-A53
-ifeq ($(notdir $(CC)),armclang)
+ifeq ($($(ARCH)-cc-id),arm-clang)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
-else ifneq ($(findstring clang,$(notdir $(CC))),)
+else ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
 else
     TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk
index 528eb1d..42a5416 100644
--- a/plat/rpi/rpi4/platform.mk
+++ b/plat/rpi/rpi4/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -39,9 +39,9 @@
 COLD_BOOT_SINGLE_CPU	:=	0
 
 # Tune compiler for Cortex-A72
-ifeq ($(notdir $(CC)),armclang)
+ifeq ($($(ARCH)-cc-id),arm-clang)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a72
-else ifneq ($(findstring clang,$(notdir $(CC))),)
+else ifneq ($(filter %-clang,$($(ARCH)-cc-id)),)
     TF_CFLAGS_aarch64	+=	-mcpu=cortex-a72
 else
     TF_CFLAGS_aarch64	+=	-mtune=cortex-a72
@@ -113,4 +113,3 @@
 ifeq ($(SMC_PCI_SUPPORT), 1)
 BL31_SOURCES            +=      plat/rpi/rpi4/rpi4_pci_svc.c
 endif
-
diff --git a/plat/st/common/common.mk b/plat/st/common/common.mk
index 7f93961..f49112d 100644
--- a/plat/st/common/common.mk
+++ b/plat/st/common/common.mk
@@ -43,7 +43,7 @@
 STM32MP_UART_PROGRAMMER		?=	0
 STM32MP_USB_PROGRAMMER		?=	0
 
-$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}'))
+$(eval DTC_V = $(shell $($(ARCH)-dtc) -v | awk '{print $$NF}'))
 $(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g" | grep -o "[0-9]*")))
 DTC_CPPFLAGS			+=	${INCLUDES}
 DTC_FLAGS			+=	-Wno-unit_address_vs_reg
diff --git a/plat/st/common/common_rules.mk b/plat/st/common/common_rules.mk
index f39caab..212a67d 100644
--- a/plat/st/common/common_rules.mk
+++ b/plat/st/common/common_rules.mk
@@ -49,7 +49,7 @@
 
 ${BUILD_PLAT}/$(PLAT)-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb $(STM32_BINARY_MAPPING) bl2
 	@echo "  AS      $${PLAT}.S"
-	${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
+	${Q}$($(ARCH)-as) -x assembler-with-cpp $(TF_CFLAGS_$(ARCH)) ${ASFLAGS} ${TF_CFLAGS} \
 		-DDTB_BIN_PATH=\"$<\" \
 		-c $(word 2,$^) -o $@
 
@@ -57,14 +57,14 @@
 
 tf-a-%.elf: $(PLAT)-%.o ${STM32_TF_LINKERFILE}
 	@echo "  LDS     $<"
-ifneq ($(findstring gcc,$(notdir $(LD))),)
-	${Q}${LD} -o $@ $(subst --,-Wl$(comma)--,${STM32_TF_ELF_LDFLAGS}) -nostartfiles -Wl,-Map=$(@:.elf=.map) -Wl,-dT ${STM32_TF_LINKERFILE} $<
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
+	${Q}$($(ARCH)-ld) -o $@ $(subst --,-Wl$(comma)--,${STM32_TF_ELF_LDFLAGS}) -nostartfiles -Wl,-Map=$(@:.elf=.map) -Wl,-dT ${STM32_TF_LINKERFILE} $<
 else
-	${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=$(@:.elf=.map) --script ${STM32_TF_LINKERFILE} $<
+	${Q}$($(ARCH)-ld) -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=$(@:.elf=.map) --script ${STM32_TF_LINKERFILE} $<
 endif
 
 tf-a-%.bin: tf-a-%.elf
-	${Q}${OC} -O binary $< $@
+	${Q}$($(ARCH)-oc) -O binary $< $@
 	@echo
 	@echo "Built $@ successfully"
 	@echo
diff --git a/plat/st/stm32mp1/cert_create_tbbr.mk b/plat/st/stm32mp1/cert_create_tbbr.mk
index 5b1a3ed..e747e39 100644
--- a/plat/st/stm32mp1/cert_create_tbbr.mk
+++ b/plat/st/stm32mp1/cert_create_tbbr.mk
@@ -11,9 +11,8 @@
 PLAT_INCLUDE	+= -I${PLAT_DIR}include
 
 src/stm32mp1_tbb_cert.o: ${PLAT_DIR}stm32mp1_tbb_cert.c
-	${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
+	${Q}$(host-cc) -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
 
 PLAT_OBJECTS	= src/stm32mp1_tbb_cert.o
 
 OBJECTS		+= $(PLAT_OBJECTS)
-
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 4ea074f..fb096bc 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -70,7 +70,6 @@
 	cm_set_context(&(rmm_ctx->cpu_ctx), REALM);
 
 	/* Restore the realm context assigned above */
-	cm_el1_sysregs_context_restore(REALM);
 	cm_el2_sysregs_context_restore(REALM);
 	cm_set_next_eret_context(REALM);
 
@@ -78,12 +77,10 @@
 	rc = rmmd_rmm_enter(&rmm_ctx->c_rt_ctx);
 
 	/*
-	 * Save realm context. EL1 and EL2 Non-secure
-	 * contexts will be restored before exiting to
-	 * Non-secure world, therefore there is no need
-	 * to clear EL1 and EL2 context registers.
+	 * Save realm context. EL2 Non-secure context will be restored
+	 * before exiting Non-secure world, therefore there is no need
+	 * to clear EL2 context registers.
 	 */
-	cm_el1_sysregs_context_save(REALM);
 	cm_el2_sysregs_context_save(REALM);
 
 	return rc;
@@ -279,11 +276,9 @@
 	cpu_context_t *ctx = cm_get_context(dst_sec_state);
 
 	/* Save incoming security state */
-	cm_el1_sysregs_context_save(src_sec_state);
 	cm_el2_sysregs_context_save(src_sec_state);
 
 	/* Restore outgoing security state */
-	cm_el1_sysregs_context_restore(dst_sec_state);
 	cm_el2_sysregs_context_restore(dst_sec_state);
 	cm_set_next_eret_context(dst_sec_state);
 
diff --git a/services/std_svc/rmmd/trp/trp.mk b/services/std_svc/rmmd/trp/trp.mk
index b7bd317..bb96343 100644
--- a/services/std_svc/rmmd/trp/trp.mk
+++ b/services/std_svc/rmmd/trp/trp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021-2023 Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -10,9 +10,9 @@
 
 RMM_DEFAULT_LINKER_SCRIPT_SOURCE := services/std_svc/rmmd/trp/linker.ld.S
 
-ifneq ($(findstring gcc,$(notdir $(LD))),)
+ifeq ($($(ARCH)-ld-id),gnu-gcc)
         RMM_LDFLAGS	+=	-Wl,--sort-section=alignment
-else ifneq ($(findstring ld,$(notdir $(LD))),)
+else ifneq ($(filter llvm-lld gnu-ld,$($(ARCH)-ld-id)),)
         RMM_LDFLAGS	+=	--sort-section=alignment
 endif
 
diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c
index 247e2c8..c6ec30c 100644
--- a/services/std_svc/spm/el3_spmc/spmc_main.c
+++ b/services/std_svc/spm/el3_spmc/spmc_main.c
@@ -1489,7 +1489,8 @@
 				     void *handle,
 				     uint64_t flags)
 {
-	char *chars;
+	/* Maximum number of characters is 48: 6 registers of 8 bytes each. */
+	char chars[48] = {0};
 	size_t chars_max;
 	size_t chars_count = x1;
 
@@ -1500,27 +1501,23 @@
 
 	assert(smc_fid == FFA_CONSOLE_LOG_SMC32 || smc_fid == FFA_CONSOLE_LOG_SMC64);
 	if (smc_fid == FFA_CONSOLE_LOG_SMC32) {
-		uint32_t registers[] = {
-			(uint32_t)x2,
-			(uint32_t)x3,
-			(uint32_t)x4,
-			(uint32_t)SMC_GET_GP(handle, CTX_GPREG_X5),
-			(uint32_t)SMC_GET_GP(handle, CTX_GPREG_X6),
-			(uint32_t)SMC_GET_GP(handle, CTX_GPREG_X7),
-		};
-		chars_max = ARRAY_SIZE(registers) * sizeof(uint32_t);
-		chars = (char *)registers;
+		uint32_t *registers = (uint32_t *)chars;
+		registers[0] = (uint32_t)x2;
+		registers[1] = (uint32_t)x3;
+		registers[2] = (uint32_t)x4;
+		registers[3] = (uint32_t)SMC_GET_GP(handle, CTX_GPREG_X5);
+		registers[4] = (uint32_t)SMC_GET_GP(handle, CTX_GPREG_X6);
+		registers[5] = (uint32_t)SMC_GET_GP(handle, CTX_GPREG_X7);
+		chars_max = 6 * sizeof(uint32_t);
 	} else {
-		uint64_t registers[] = {
-			x2,
-			x3,
-			x4,
-			SMC_GET_GP(handle, CTX_GPREG_X5),
-			SMC_GET_GP(handle, CTX_GPREG_X6),
-			SMC_GET_GP(handle, CTX_GPREG_X7),
-		};
-		chars_max = ARRAY_SIZE(registers) * sizeof(uint64_t);
-		chars = (char *)registers;
+		uint64_t *registers = (uint64_t *)chars;
+		registers[0] = x2;
+		registers[1] = x3;
+		registers[2] = x4;
+		registers[3] = SMC_GET_GP(handle, CTX_GPREG_X5);
+		registers[4] = SMC_GET_GP(handle, CTX_GPREG_X6);
+		registers[5] = SMC_GET_GP(handle, CTX_GPREG_X7);
+		chars_max = 6 * sizeof(uint64_t);
 	}
 
 	if ((chars_count == 0) || (chars_count > chars_max)) {
diff --git a/tools/amlogic/Makefile b/tools/amlogic/Makefile
index 1a1d1f8..5ff26e5 100644
--- a/tools/amlogic/Makefile
+++ b/tools/amlogic/Makefile
@@ -4,9 +4,13 @@
 # SPDX-License-Identifier:     BSD-3-Clause
 # https://spdx.org/licenses
 #
+
+toolchains := host
+
 MAKE_HELPERS_DIRECTORY := ../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
 
 PROJECT := doimage${BIN_EXT}
 OBJECTS := doimage.o
@@ -26,22 +30,20 @@
   Q :=
 endif
 
-HOSTCC := gcc
-
 .PHONY: all clean distclean
 
 all: ${PROJECT}
 
 ${PROJECT}: ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
-	${Q}${HOSTCC} ${OBJECTS} -o $@
+	${Q}$(host-cc) ${OBJECTS} -o $@
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
 
 %.o: %.c Makefile
 	@echo "  HOSTCC  $<"
-	${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@
+	${Q}$(host-cc) -c ${HOSTCCFLAGS} $< -o $@
 
 clean:
 	$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index b911d19..21523f6 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -11,10 +11,13 @@
 BINARY		:= $(notdir ${CRTTOOL})
 COT		:= tbbr
 
+toolchains := host
+
 MAKE_HELPERS_DIRECTORY := ../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
 include ${MAKE_HELPERS_DIRECTORY}defaults.mk
+include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
 
 ifneq (${PLAT},none)
 TF_PLATFORM_ROOT	:=	../../plat/
@@ -81,8 +84,6 @@
 LIB_DIR := -L ${OPENSSL_DIR}/lib -L ${OPENSSL_DIR}
 LIB := -lssl -lcrypto
 
-HOSTCC ?= gcc
-
 .PHONY: all clean realclean --openssl
 
 all: --openssl ${BINARY}
@@ -91,12 +92,12 @@
 	@echo "  HOSTLD  $@"
 	@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \
                 const char platform_msg[] = "${PLAT_MSG}";' | \
-                ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o
-	${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
+                $(host-cc) -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o
+	${Q}$(host-cc) src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
 
 %.o: %.c
 	@echo "  HOSTCC  $<"
-	${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
+	${Q}$(host-cc) -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
 
 --openssl:
 ifeq ($(DEBUG),1)
@@ -108,4 +109,3 @@
 
 realclean: clean
 	$(call SHELL_DELETE,${BINARY})
-
diff --git a/tools/encrypt_fw/Makefile b/tools/encrypt_fw/Makefile
index 924e5fe..83f2f57 100644
--- a/tools/encrypt_fw/Makefile
+++ b/tools/encrypt_fw/Makefile
@@ -11,11 +11,13 @@
 BINARY		:= $(notdir ${ENCTOOL})
 OPENSSL_DIR	:= /usr
 
+toolchains := host
 
 MAKE_HELPERS_DIRECTORY := ../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
 include ${MAKE_HELPERS_DIRECTORY}defaults.mk
+include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
 
 OBJECTS := src/encrypt.o \
            src/cmd_opt.o \
@@ -61,8 +63,6 @@
 LIB_DIR := -L ${OPENSSL_DIR}/lib -L ${OPENSSL_DIR}
 LIB := -lssl -lcrypto
 
-HOSTCC ?= gcc
-
 .PHONY: all clean realclean --openssl
 
 all: --openssl ${BINARY}
@@ -70,12 +70,12 @@
 ${BINARY}: ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
 	@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__;' | \
-                ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o
-	${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
+                $(host-cc) -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o
+	${Q}$(host-cc) src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
 
 %.o: %.c
 	@echo "  HOSTCC  $<"
-	${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
+	${Q}$(host-cc) -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
 
 --openssl:
 ifeq ($(DEBUG),1)
diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile
index fda7c77..865ff4c 100644
--- a/tools/fiptool/Makefile
+++ b/tools/fiptool/Makefile
@@ -1,13 +1,16 @@
 #
-# Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+toolchains := host
+
 MAKE_HELPERS_DIRECTORY := ../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
 include ${MAKE_HELPERS_DIRECTORY}defaults.mk
+include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
 
 FIPTOOL ?= fiptool${BIN_EXT}
 PROJECT := $(notdir ${FIPTOOL})
@@ -58,8 +61,6 @@
   Q :=
 endif
 
-HOSTCC ?= gcc
-
 ifneq (${PLAT},)
 TF_PLATFORM_ROOT	:=	../../plat/
 include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
@@ -81,14 +82,14 @@
 
 ${PROJECT}: ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
-	${Q}${HOSTCC} ${OBJECTS} -o $@ $(LDOPTS)
+	${Q}$(host-cc) ${OBJECTS} -o $@ $(LDOPTS)
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
 
 %.o: %.c Makefile
 	@echo "  HOSTCC  $<"
-	${Q}${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} -MD -MP $< -o $@
+	${Q}$(host-cc) -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} -MD -MP $< -o $@
 
 -include $(DEPS)
 
diff --git a/tools/fiptool/plat_fiptool/st/stm32mp1/plat_fiptool.mk b/tools/fiptool/plat_fiptool/st/stm32mp1/plat_fiptool.mk
index 1ba47c1..0d69dbd 100644
--- a/tools/fiptool/plat_fiptool/st/stm32mp1/plat_fiptool.mk
+++ b/tools/fiptool/plat_fiptool/st/stm32mp1/plat_fiptool.mk
@@ -17,7 +17,7 @@
 HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
 
 ${PLAT_DEF_UUID_FILE_NAME}.o: plat_fiptool/st/stm32mp1/${PLAT_DEF_UUID_FILE_NAME}.c
-	${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
+	$(host-cc) -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
 
 PLAT_OBJECTS += ${PLAT_DEF_UUID_FILE_NAME}.o
 endif
diff --git a/tools/marvell/doimage/Makefile b/tools/marvell/doimage/Makefile
index 9f0d89d..6e59aa2 100644
--- a/tools/marvell/doimage/Makefile
+++ b/tools/marvell/doimage/Makefile
@@ -4,6 +4,10 @@
 # SPDX-License-Identifier:     BSD-3-Clause
 # https://spdx.org/licenses
 
+toolchains := host
+
+include ../../../make_helpers/toolchain.mk
+
 PROJECT = doimage
 OBJECTS = doimage.o
 
@@ -25,7 +29,6 @@
 # could get pulled in from firmware tree.
 INCLUDE_PATHS = -I.
 
-HOSTCC ?= gcc
 RM := rm -rf
 
 .PHONY: all clean
@@ -34,14 +37,14 @@
 
 ${PROJECT}: ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
-	${Q}${HOSTCC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@
+	${Q}$(host-cc) ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@
 	@echo
 	@echo "Built $@ successfully"
 	@echo
 
 %.o: %.c Makefile
 	@echo "  HOSTCC  $<"
-	${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
+	${Q}$(host-cc) -c ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
 
 clean:
 	${Q}${RM} ${PROJECT}
diff --git a/tools/nxp/create_pbl/Makefile b/tools/nxp/create_pbl/Makefile
index f971a74..b6b3b04 100644
--- a/tools/nxp/create_pbl/Makefile
+++ b/tools/nxp/create_pbl/Makefile
@@ -4,9 +4,12 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+toolchains := host
+
 MAKE_HELPERS_DIRECTORY := ../../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
 
 PROJECT_1 := create_pbl${BIN_EXT}
 OBJECTS_1 := create_pbl.o
@@ -31,30 +34,27 @@
 
 INCLUDE_PATHS :=
 
-HOSTCC ?= gcc
-CC = gcc
-
 .PHONY: all clean distclean
 
 all: create_pbl byte_swap
 
 ${PROJECT_1}: ${OBJECTS_1} Makefile
 	@echo "  LD      $@"
-	${Q}${HOSTCC} ${OBJECTS_1} -o $@ ${LDLIBS}
+	${Q}$(host-cc) ${OBJECTS_1} -o $@ ${LDLIBS}
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
 
 ${PROJECT_2}: ${OBJECTS_2} Makefile
 	@echo "  LD      $@"
-	${Q}${HOSTCC} ${OBJECTS_2} -o $@ ${LDLIBS}
+	${Q}$(host-cc) ${OBJECTS_2} -o $@ ${LDLIBS}
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
 
 %.o: %.c %.h Makefile
 	@echo "  CC      $<"
-	${Q}${HOSTCC} -c ${CPPFLAGS} ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
+	${Q}$(host-cc) -c ${CPPFLAGS} ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
 
 clean:
 	$(call SHELL_DELETE_ALL, ${PROJECT_1} ${OBJECTS_1})
diff --git a/tools/renesas/rcar_layout_create/makefile b/tools/renesas/rcar_layout_create/makefile
index 01b3d62..baa6e7e 100644
--- a/tools/renesas/rcar_layout_create/makefile
+++ b/tools/renesas/rcar_layout_create/makefile
@@ -4,6 +4,10 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+toolchains := aarch64
+
+include ../../../make_helpers/toolchain.mk
+
 ###################################################
 # makefile
 ###################################################
@@ -67,16 +71,9 @@
 ###################################################
 
 #c compiler
-CC = $(CROSS_COMPILE)gcc
 CFLAGS += ${DEFINES}
 CFLAGS += -I../../include/lib/stdlib
 
-#Linker
-LD = $(CROSS_COMPILE)ld
-
-#objcopy
-objcopy = $(CROSS_COMPILE)objcopy
-
 #clean
 CL = rm -f
 
@@ -92,29 +89,29 @@
 # Linker
 ###################################################
 $(OUTPUT_FILE_SA0) : $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0)
-	$(LD) $(OBJ_FILE_SA0)		 	\
+	$(aarch64-ld) $(OBJ_FILE_SA0)		 	\
 	-T $(MEMORY_DEF_SA0)			\
 	-o $(OUTPUT_FILE_SA0)			\
 	-Map $(FILE_NAME_SA0).map 		\
 
-	$(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
-	$(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
+	$(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
+	$(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
 
 $(OUTPUT_FILE_SA6) : $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6)
-	$(LD) $(OBJ_FILE_SA6)		 	\
+	$(aarch64-ld) $(OBJ_FILE_SA6)		 	\
 	-T $(MEMORY_DEF_SA6)			\
 	-o $(OUTPUT_FILE_SA6)			\
 	-Map $(FILE_NAME_SA6).map 		\
 
-	$(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
-	$(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
+	$(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
+	$(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
 
 ###################################################
 # Compile
 ###################################################
 
 %.o: %.c
-	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+	$(aarch64-cc) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
 
 .PHONY: clean
 clean:
diff --git a/tools/renesas/rzg_layout_create/makefile b/tools/renesas/rzg_layout_create/makefile
index 92a0557..4cab5fb 100644
--- a/tools/renesas/rzg_layout_create/makefile
+++ b/tools/renesas/rzg_layout_create/makefile
@@ -4,6 +4,10 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+toolchains := aarch64
+
+include ../../../make_helpers/toolchain.mk
+
 ###################################################
 # makefile
 ###################################################
@@ -62,18 +66,11 @@
 ###################################################
 
 #c compiler
-CC = $(CROSS_COMPILE)gcc
 CFLAGS += ${DEFINES}
 CFLAGS += -nostdinc \
 	  -I../../../include/lib/libc \
 	  -I../../../include/lib/libc/aarch64
 
-#Linker
-LD = $(CROSS_COMPILE)ld
-
-#objcopy
-objcopy = $(CROSS_COMPILE)objcopy
-
 #clean
 CL = rm -f
 
@@ -89,29 +86,29 @@
 # Linker
 ###################################################
 $(OUTPUT_FILE_SA0) : $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0)
-	$(LD) $(OBJ_FILE_SA0)		 	\
+	$(aarch64-ld) $(OBJ_FILE_SA0)		 	\
 	-T $(MEMORY_DEF_SA0)			\
 	-o $(OUTPUT_FILE_SA0)			\
 	-Map $(FILE_NAME_SA0).map 		\
 
-	$(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
-	$(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
+	$(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
+	$(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
 
 $(OUTPUT_FILE_SA6) : $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6)
-	$(LD) $(OBJ_FILE_SA6)		 	\
+	$(aarch64-ld) $(OBJ_FILE_SA6)		 	\
 	-T $(MEMORY_DEF_SA6)			\
 	-o $(OUTPUT_FILE_SA6)			\
 	-Map $(FILE_NAME_SA6).map 		\
 
-	$(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
-	$(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
+	$(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
+	$(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3  $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
 
 ###################################################
 # Compile
 ###################################################
 
 %.o: %.c
-	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+	$(aarch64-cc) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
 
 .PHONY: clean
 clean:
diff --git a/tools/sptool/Makefile b/tools/sptool/Makefile
index 1fa85fb..a913ce5 100644
--- a/tools/sptool/Makefile
+++ b/tools/sptool/Makefile
@@ -1,12 +1,15 @@
 #
-# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+toolchains := host
+
 MAKE_HELPERS_DIRECTORY := ../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
 
 SPTOOL  ?= sptool${BIN_EXT}
 PROJECT := $(notdir ${SPTOOL})
@@ -29,22 +32,20 @@
 
 INCLUDE_PATHS := -I../../include/tools_share
 
-HOSTCC ?= gcc
-
 .PHONY: all clean distclean
 
 all: ${PROJECT}
 
 ${PROJECT}: ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
-	${Q}${HOSTCC} ${OBJECTS} -o $@ ${LDLIBS}
+	${Q}$(host-cc) ${OBJECTS} -o $@ ${LDLIBS}
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
 
 %.o: %.c Makefile
 	@echo "  HOSTCC  $<"
-	${Q}${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
+	${Q}$(host-cc) -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
 
 clean:
 	$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
diff --git a/tools/stm32image/Makefile b/tools/stm32image/Makefile
index 9c9b7b5..c75e941 100644
--- a/tools/stm32image/Makefile
+++ b/tools/stm32image/Makefile
@@ -1,12 +1,15 @@
 #
-# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+toolchains := host
+
 MAKE_HELPERS_DIRECTORY := ../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
 
 PROJECT := stm32image${BIN_EXT}
 OBJECTS := stm32image.o
@@ -26,22 +29,20 @@
   Q :=
 endif
 
-HOSTCC := gcc
-
 .PHONY: all clean distclean
 
 all: ${PROJECT}
 
 ${PROJECT}: ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
-	${Q}${HOSTCC} ${OBJECTS} -o $@
+	${Q}$(host-cc) ${OBJECTS} -o $@
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
 
 %.o: %.c Makefile
 	@echo "  HOSTCC  $<"
-	${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@
+	${Q}$(host-cc) -c ${HOSTCCFLAGS} $< -o $@
 
 clean:
 	$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})