Merge "feat(stm32mp15-fdts): add Linux Automation GmbH TAC" into integration
diff --git a/docs/about/features.rst b/docs/about/features.rst
index 9b7bdf9..f15144a 100644
--- a/docs/about/features.rst
+++ b/docs/about/features.rst
@@ -127,7 +127,6 @@
 Additionally the following libraries are marked experimental when included
 in a platform:
 
--  MPU translation library ``lib/xlat_mpu``
 -  RSE comms driver ``drivers/arm/rse``
 
 Still to come
@@ -151,4 +150,4 @@
 
 --------------
 
-*Copyright (c) 2019-2023, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
diff --git a/docs/components/xlat-tables-lib-v2-design.rst b/docs/components/xlat-tables-lib-v2-design.rst
index cac32f5..c7fd5a2 100644
--- a/docs/components/xlat-tables-lib-v2-design.rst
+++ b/docs/components/xlat-tables-lib-v2-design.rst
@@ -10,7 +10,7 @@
 More specifically, some use cases that this library aims to support are:
 
 #. Statically allocate translation tables and populate them (at run-time) based
-   upon a description of the memory layout. The memory layout is typically
+   on a description of the memory layout. The memory layout is typically
    provided by the platform port as a list of memory regions;
 
 #. Support for generating translation tables pertaining to a different
@@ -26,28 +26,22 @@
 #. Support for changing memory attributes of memory regions at run-time.
 
 
-About version 1, version 2 and MPU libraries
---------------------------------------------
+About version 1 and version 2
+-----------------------------
 
 This document focuses on version 2 of the library, whose sources are available
 in the ``lib/xlat_tables_v2`` directory. Version 1 of the library can still be
 found in ``lib/xlat_tables`` directory but it is less flexible and doesn't
-support dynamic mapping. ``lib/xlat_mpu``, which configures Arm's MPU
-equivalently, is also addressed here. The ``lib/xlat_mpu`` is experimental,
-meaning that its API may change. It currently strives for consistency and
-code-reuse with xlat_tables_v2.  Future versions may be more MPU-specific (e.g.,
-removing all mentions of virtual addresses). Although potential bug fixes will
-be applied to all versions of the xlat_* libs, future feature enhancements will
-focus on version 2 and might not be back-ported to version 1 and MPU versions.
-Therefore, it is recommended to use version 2, especially for new platform
-ports (unless the platform uses an MPU).
+support dynamic mapping. Although potential bug fixes will be applied to both
+versions, future features enhancements will focus on version 2 and might not be
+back-ported to version 1. Therefore, it is recommended to use version 2,
+especially for new platform ports.
 
-However, please note that version 2 and the MPU version are still in active
-development and is not considered stable yet. Hence, compatibility breaks might
-be introduced.
+However, please note that version 2 is still in active development and is not
+considered stable yet. Hence, compatibility breaks might be introduced.
 
 From this point onwards, this document will implicitly refer to version 2 of the
-library, unless stated otherwise.
+library.
 
 
 Design concepts and interfaces
@@ -108,16 +102,6 @@
 library will choose the mapping granularity for this region as it sees fit (more
 details can be found in `The memory mapping algorithm`_ section below).
 
-The MPU library also uses ``struct mmap_region`` to specify translations, but
-the MPU's translations are limited to specification of valid addresses and
-access permissions.  If the requested virtual and physical addresses mismatch
-the system will panic. Being register-based for deterministic memory-reference
-timing, the MPU hardware does not involve memory-resident translation tables.
-
-Currently, the MPU library is also limited to MPU translation at EL2 with no
-MMU translation at other ELs.  These limitations, however, are expected to be
-overcome in future library versions.
-
 Translation Context
 ~~~~~~~~~~~~~~~~~~~
 
@@ -231,8 +215,7 @@
 The ``MAP_REGION()`` and ``MAP_REGION_FLAT()`` macros do not allow specifying a
 mapping granularity, which leaves the library implementation free to choose
 it. However, in cases where a specific granularity is required, the
-``MAP_REGION2()`` macro might be used instead. Using ``MAP_REGION_FLAT()`` only
-to define regions for the MPU library is strongly recommended.
+``MAP_REGION2()`` macro might be used instead.
 
 As explained earlier in this document, when the dynamic mapping feature is
 disabled, there is no notion of dynamic regions. Conceptually, there are only
@@ -391,9 +374,6 @@
 refer to the comments in the source code of the core module for more details
 about the sorting algorithm in use.
 
-This mapping algorithm does not apply to the MPU library, since the MPU hardware
-directly maps regions by "base" and "limit" (bottom and top) addresses.
-
 TLB maintenance operations
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -410,11 +390,6 @@
 is deferred to the ``enable_mmu*()`` family of functions, just before the MMU is
 turned on.
 
-Regarding enabling and disabling memory management, for the MPU library, to
-reduce confusion, calls to enable or disable the MPU use ``mpu`` in their names
-in place of ``mmu``. For example, the ``enable_mmu_el2()`` call is changed to
-``enable_mpu_el2()``.
-
 TLB invalidation is not required when adding dynamic regions either. Dynamic
 regions are not allowed to overlap existing memory region. Therefore, if the
 dynamic mapping request is deemed legitimate, it automatically concerns memory
@@ -437,6 +412,6 @@
 
 --------------
 
-*Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.*
 
 .. |Alignment Example| image:: ../resources/diagrams/xlat_align.png
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 0ad9181..768a437 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -77,7 +77,10 @@
 |      TC2       |      Arm       |        2.12        |         TBD        |
 |                |                |                    |                    |
 +----------------+----------------+--------------------+--------------------+
+|     fvp_r      |      Arm       |        2.13        |         2.13       |
+|                |                |                    |                    |
++----------------+----------------+--------------------+--------------------+
 
 --------------
 
-*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
diff --git a/drivers/auth/tbbr/tbbr_cot_bl1_r64.c b/drivers/auth/tbbr/tbbr_cot_bl1_r64.c
deleted file mode 100644
index 236823a..0000000
--- a/drivers/auth/tbbr/tbbr_cot_bl1_r64.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-
-#include <mbedtls/version.h>
-
-#include <drivers/auth/auth_mod.h>
-#include <drivers/auth/tbbr_cot_common.h>
-
-#if USE_TBBR_DEFS
-#include <tools_share/tbbr_oid.h>
-#else
-#include <platform_oid.h>
-#endif
-
-#include <platform_def.h>
-
-static unsigned char trusted_world_pk_buf[PK_DER_LEN];
-static unsigned char non_trusted_world_pk_buf[PK_DER_LEN];
-static unsigned char content_pk_buf[PK_DER_LEN];
-static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
-
-static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
-static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
-static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID);
-static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID);
-static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
-static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
-/*
- * Trusted key certificate
- */
-static const auth_img_desc_t trusted_key_cert = {
-	.img_id = TRUSTED_KEY_CERT_ID,
-	.img_type = IMG_CERT,
-	.parent = NULL,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_SIG,
-			.param.sig = {
-				.pk = &subject_pk,
-				.sig = &sig,
-				.alg = &sig_alg,
-				.data = &raw_data
-			}
-		},
-		[1] = {
-			.type = AUTH_METHOD_NV_CTR,
-			.param.nv_ctr = {
-				.cert_nv_ctr = &trusted_nv_ctr,
-				.plat_nv_ctr = &trusted_nv_ctr
-			}
-		}
-	},
-	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
-		[0] = {
-			.type_desc = &trusted_world_pk,
-			.data = {
-				.ptr = (void *)trusted_world_pk_buf,
-				.len = (unsigned int)PK_DER_LEN
-			}
-		},
-		[1] = {
-			.type_desc = &non_trusted_world_pk,
-			.data = {
-				.ptr = (void *)non_trusted_world_pk_buf,
-				.len = (unsigned int)PK_DER_LEN
-			}
-		}
-	}
-};
-/*
- * Non-Trusted Firmware
- */
-static const auth_img_desc_t non_trusted_fw_key_cert = {
-	.img_id = NON_TRUSTED_FW_KEY_CERT_ID,
-	.img_type = IMG_CERT,
-	.parent = &trusted_key_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_SIG,
-			.param.sig = {
-				.pk = &non_trusted_world_pk,
-				.sig = &sig,
-				.alg = &sig_alg,
-				.data = &raw_data
-			}
-		},
-		[1] = {
-			.type = AUTH_METHOD_NV_CTR,
-			.param.nv_ctr = {
-				.cert_nv_ctr = &non_trusted_nv_ctr,
-				.plat_nv_ctr = &non_trusted_nv_ctr
-			}
-		}
-	},
-	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
-		[0] = {
-			.type_desc = &nt_fw_content_pk,
-			.data = {
-				.ptr = (void *)content_pk_buf,
-				.len = (unsigned int)PK_DER_LEN
-			}
-		}
-	}
-};
-static const auth_img_desc_t non_trusted_fw_content_cert = {
-	.img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
-	.img_type = IMG_CERT,
-	.parent = &non_trusted_fw_key_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_SIG,
-			.param.sig = {
-				.pk = &nt_fw_content_pk,
-				.sig = &sig,
-				.alg = &sig_alg,
-				.data = &raw_data
-			}
-		},
-		[1] = {
-			.type = AUTH_METHOD_NV_CTR,
-			.param.nv_ctr = {
-				.cert_nv_ctr = &non_trusted_nv_ctr,
-				.plat_nv_ctr = &non_trusted_nv_ctr
-			}
-		}
-	},
-	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
-		[0] = {
-			.type_desc = &nt_world_bl_hash,
-			.data = {
-				.ptr = (void *)nt_world_bl_hash_buf,
-				.len = (unsigned int)HASH_DER_LEN
-			}
-		},
-		[1] = {
-			.type_desc = &nt_fw_config_hash,
-			.data = {
-				.ptr = (void *)nt_fw_config_hash_buf,
-				.len = (unsigned int)HASH_DER_LEN
-			}
-		}
-	}
-};
-static const auth_img_desc_t bl33_image = {
-	.img_id = BL33_IMAGE_ID,
-	.img_type = IMG_RAW,
-	.parent = &non_trusted_fw_content_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_HASH,
-			.param.hash = {
-				.data = &raw_data,
-				.hash = &nt_world_bl_hash
-			}
-		}
-	}
-};
-
-static const auth_img_desc_t * const cot_desc[] = {
-	[TRUSTED_KEY_CERT_ID]			=	&trusted_key_cert,
-	[NON_TRUSTED_FW_KEY_CERT_ID]		=	&non_trusted_fw_key_cert,
-	[NON_TRUSTED_FW_CONTENT_CERT_ID]	=	&non_trusted_fw_content_cert,
-	[BL33_IMAGE_ID]				=	&bl33_image,
-};
-
-/* Register the CoT in the authentication module */
-REGISTER_COT(cot_desc);
diff --git a/drivers/ti/ipc/mailbox.c b/drivers/ti/ipc/mailbox.c
new file mode 100644
index 0000000..65458a5
--- /dev/null
+++ b/drivers/ti/ipc/mailbox.c
@@ -0,0 +1,145 @@
+/*
+ * Texas Instruments Mailbox Driver
+ *
+ * Copyright (C) 2024-2025 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+#include <ti_sci_transport.h>
+
+#include <platform_def.h>
+
+/*
+ * TI_MAILBOX_RX/TX_BASE and the MAILBOX_MAX_MESSAGE_SIZE values are expected
+ * to come from platform specific header file ie. platform_def.h
+ */
+
+#define TI_MAILBOX_SYSC		UL(0x10)
+#define TI_MAILBOX_MSG		UL(0x40)
+#define TI_MAILBOX_FIFO_STATUS	UL(0x80)
+#define TI_MAILBOX_MSG_STATUS		UL(0xc0)
+
+/*
+ * Function to poll for mailbox rx messages
+ * IRQ model is currently not in scope of this driver
+ */
+static int8_t ti_mailbox_poll_rx_status(void)
+{
+	uint32_t num_messages_pending = 0U;
+	uint32_t retry_count = 100U;
+
+	/*
+	 * Keep polling till we get a message for 100 times
+	 * with intervals of 10 milliseconds.
+	 */
+	while (num_messages_pending == 0U) {
+		num_messages_pending = mmio_read_32(TI_MAILBOX_RX_BASE + TI_MAILBOX_MSG_STATUS);
+		if (retry_count-- == 0U) {
+			return -ETIMEDOUT;
+		}
+		mdelay(10);
+	}
+	return 0;
+}
+
+int ti_sci_transport_clear_rx_thread(enum ti_sci_transport_chan_id id)
+{
+	/* MSG_STATUS tells us how many pending messages */
+	uint32_t try_count = mmio_read_32(TI_MAILBOX_RX_BASE + TI_MAILBOX_MSG_STATUS);
+
+	/* Run the loop till the status register is cleared */
+	while (mmio_read_32(TI_MAILBOX_RX_BASE + TI_MAILBOX_MSG_STATUS) != 0U) {
+		WARN("Clearing message from mailbox FIFO\n");
+		/* The act of reading the mailbox msg itself clears it */
+		mmio_read_32(TI_MAILBOX_RX_BASE + TI_MAILBOX_MSG);
+		/*
+		 * The try_count is kept independent of the value of the status register
+		 * because if at any point a new mailbox message arrives while this loop
+		 * is in progress, we would want to know that message arrived and not clear
+		 * it. We would rather print the error than clear the message thus indicating
+		 * that the system is probably in a bad/async state.
+		 */
+		if (!(try_count--)) {
+			ERROR("Could not clear all messages from mailbox FIFO\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+int ti_sci_transport_send(enum ti_sci_transport_chan_id id, const struct ti_sci_msg *msg)
+{
+	uint32_t num_bytes;
+	void *dst_ptr = (void *)MAILBOX_TX_START_REGION;
+
+	assert(msg != NULL);
+
+	num_bytes = msg->len;
+
+	/*
+	 * Only a simple check because even if there's 1 pending message
+	 * we will be in a bad state if we try to send another message
+	 * due to the absence of any interrupt or buffer mgmt model.
+	 */
+	if (mmio_read_32(TI_MAILBOX_TX_BASE + TI_MAILBOX_FIFO_STATUS)) {
+		ERROR("Mailbox FIFO has pending messages!\n");
+		return -EINVAL;
+	}
+
+	if (num_bytes > MAILBOX_MAX_MESSAGE_SIZE) {
+		ERROR("message length %lu > max msg size\n", msg->len);
+		return -EINVAL;
+	}
+
+	/*
+	 * Move the buffer contents into the SRAM to be accessed by TIFS
+	 */
+	memmove(dst_ptr, msg->buf, num_bytes);
+
+	mmio_write_32(TI_MAILBOX_TX_BASE + TI_MAILBOX_MSG, (uint64_t)(void *)dst_ptr);
+
+	return 0;
+}
+
+int ti_sci_transport_recv(enum ti_sci_transport_chan_id id, struct ti_sci_msg *msg)
+{
+	uint32_t num_bytes;
+	uint64_t rcv_addr;
+
+	assert(msg != NULL);
+
+	num_bytes = msg->len;
+
+	if (ti_mailbox_poll_rx_status() == -ETIMEDOUT) {
+		ERROR("Timeout waiting for receive\n");
+		return -ETIMEDOUT;
+	}
+
+	rcv_addr = mmio_read_32(TI_MAILBOX_RX_BASE + TI_MAILBOX_MSG);
+
+	if (rcv_addr != MAILBOX_RX_START_REGION) {
+		ERROR("message address %lu is not valid\n", rcv_addr);
+		return -EINVAL;
+	}
+
+	if (num_bytes > MAILBOX_MAX_MESSAGE_SIZE) {
+		ERROR("message length %lu > max msg size\n", msg->len);
+		return -EINVAL;
+	}
+
+	memmove(msg->buf, (uint8_t *)(rcv_addr), num_bytes);
+
+	return 0;
+}
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/drivers/ti/ipc/sec_proxy.c
similarity index 83%
rename from plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
rename to drivers/ti/ipc/sec_proxy.c
index fb27336..55396f6 100644
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
+++ b/drivers/ti/ipc/sec_proxy.c
@@ -2,7 +2,7 @@
  * Texas Instruments K3 Secure Proxy Driver
  *   Based on Linux and U-Boot implementation
  *
- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2018-2025 Texas Instruments Incorporated - http://www.ti.com/
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,7 +18,7 @@
 #include <lib/utils.h>
 #include <lib/utils_def.h>
 
-#include "sec_proxy.h"
+#include <ti_sci_transport.h>
 
 /* SEC PROXY RT THREAD STATUS */
 #define RT_THREAD_STATUS			(0x0)
@@ -97,32 +97,12 @@
 		.data_end_offset = 0x3C,
 	},
 	.threads = {
-#if !K3_SEC_PROXY_LITE
-		SP_THREAD(SP_NOTIFY),
-		SP_THREAD(SP_RESPONSE),
-		SP_THREAD(SP_HIGH_PRIORITY),
-		SP_THREAD(SP_LOW_PRIORITY),
-		SP_THREAD(SP_NOTIFY_RESP),
-#else
-		SP_THREAD(SP_RESPONSE),
-		SP_THREAD(SP_HIGH_PRIORITY),
-#endif /* K3_SEC_PROXY_LITE */
+		SP_THREAD(RX_SECURE_TRANSPORT_CHANNEL_ID),
+		SP_THREAD(TX_SECURE_TRANSPORT_CHANNEL_ID),
 	},
 };
 
 /**
- * struct sec_msg_hdr - Message header for secure messages and responses
- * @checksum:	CRC of message for integrity checking
- */
-union sec_msg_hdr {
-	struct {
-		uint16_t checksum;
-		uint16_t reserved;
-	} __packed;
-	uint32_t data;
-};
-
-/**
  * k3_sec_proxy_verify_thread() - Verify thread status before
  *				  sending/receiving data
  * @spt: Pointer to Secure Proxy thread description
@@ -170,13 +150,13 @@
 }
 
 /**
- * k3_sec_proxy_clear_rx_thread() - Clear Secure Proxy thread
+ * ti_sci_transport_clear_rx_thread() - Clear Secure Proxy thread
  *
  * @id: Channel Identifier
  *
  * Return: 0 if all goes well, else appropriate error message
  */
-int k3_sec_proxy_clear_rx_thread(enum k3_sec_proxy_chan_id id)
+int ti_sci_transport_clear_rx_thread(enum ti_sci_transport_chan_id id)
 {
 	struct k3_sec_proxy_thread *spt = &spm.threads[id];
 
@@ -208,16 +188,15 @@
 }
 
 /**
- * k3_sec_proxy_send() - Send data over a Secure Proxy thread
+ * ti_sci_transport_send() - Send data over a Secure Proxy thread
  * @id: Channel Identifier
- * @msg: Pointer to k3_sec_proxy_msg
+ * @msg: Pointer to ti_sci_msg
  *
  * Return: 0 if all goes well, else appropriate error message
  */
-int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_msg *msg)
+int ti_sci_transport_send(enum ti_sci_transport_chan_id id, const struct ti_sci_msg *msg)
 {
 	struct k3_sec_proxy_thread *spt = &spm.threads[id];
-	union sec_msg_hdr secure_header;
 	int num_words, trail_bytes, i, ret;
 	uintptr_t data_reg;
 
@@ -228,19 +207,13 @@
 	}
 
 	/* Check the message size */
-	if (msg->len + sizeof(secure_header) > spm.desc.max_msg_size) {
+	if (msg->len > spm.desc.max_msg_size) {
 		ERROR("Thread %s message length %lu > max msg size\n",
 		      spt->name, msg->len);
 		return -EINVAL;
 	}
 
-	/* TODO: Calculate checksum */
-	secure_header.checksum = 0;
-
-	/* Send the secure header */
 	data_reg = spm.desc.data_start_offset;
-	mmio_write_32(spt->data + data_reg, secure_header.data);
-	data_reg += sizeof(uint32_t);
 
 	/* Send whole words */
 	num_words = msg->len / sizeof(uint32_t);
@@ -281,16 +254,15 @@
 }
 
 /**
- * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread
+ * ti_sci_transport_recv() - Receive data from a Secure Proxy thread
  * @id: Channel Identifier
- * @msg: Pointer to k3_sec_proxy_msg
+ * @msg: Pointer to ti_sci_msg
  *
  * Return: 0 if all goes well, else appropriate error message
  */
-int k3_sec_proxy_recv(enum k3_sec_proxy_chan_id id, struct k3_sec_proxy_msg *msg)
+int ti_sci_transport_recv(enum ti_sci_transport_chan_id id, struct ti_sci_msg *msg)
 {
 	struct k3_sec_proxy_thread *spt = &spm.threads[id];
-	union sec_msg_hdr secure_header;
 	uintptr_t data_reg;
 	int num_words, trail_bytes, i, ret;
 
@@ -300,10 +272,7 @@
 		return ret;
 	}
 
-	/* Read secure header */
 	data_reg = spm.desc.data_start_offset;
-	secure_header.data = mmio_read_32(spt->data + data_reg);
-	data_reg += sizeof(uint32_t);
 
 	/* Read whole words */
 	num_words = msg->len / sizeof(uint32_t);
@@ -332,9 +301,6 @@
 	if (data_reg <= spm.desc.data_end_offset)
 		mmio_read_32(spt->data + spm.desc.data_end_offset);
 
-	/* TODO: Verify checksum */
-	(void)secure_header.checksum;
-
 	VERBOSE("Message successfully received from thread %s\n", spt->name);
 
 	return 0;
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/drivers/ti/ti_sci/ti_sci.c
similarity index 98%
rename from plat/ti/k3/common/drivers/ti_sci/ti_sci.c
rename to drivers/ti/ti_sci/ti_sci.c
index 5c6ba6b..f0813e5 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
+++ b/drivers/ti/ti_sci/ti_sci.c
@@ -2,7 +2,7 @@
  * Texas Instruments System Control Interface Driver
  *   Based on Linux and U-Boot implementation
  *
- * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2018-2025 Texas Instruments Incorporated - https://www.ti.com/
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,7 +16,7 @@
 #include <lib/bakery_lock.h>
 
 #include <common/debug.h>
-#include <sec_proxy.h>
+#include <ti_sci_transport.h>
 
 #include "ti_sci_protocol.h"
 #include "ti_sci.h"
@@ -34,8 +34,8 @@
  * @rx_message:	Receive message
  */
 struct ti_sci_xfer {
-	struct k3_sec_proxy_msg tx_message;
-	struct k3_sec_proxy_msg rx_message;
+	struct ti_sci_msg tx_message;
+	struct ti_sci_msg rx_message;
 };
 
 /**
@@ -69,6 +69,9 @@
 		return -ERANGE;
 
 	hdr = (struct ti_sci_msg_hdr *)tx_buf;
+
+	/* TODO: Calculate checksum */
+	hdr->sec_hdr.checksum = 0;
 	hdr->seq = ++message_sequence;
 	hdr->type = msg_type;
 	hdr->host = TI_SCI_HOST_ID;
@@ -95,8 +98,8 @@
  *
  * Return: 0 if all goes well, else appropriate error message
  */
-static int ti_sci_get_response(struct k3_sec_proxy_msg *msg,
-			       enum k3_sec_proxy_chan_id chan)
+static int ti_sci_get_response(struct ti_sci_msg *msg,
+			       enum ti_sci_transport_chan_id chan)
 {
 	struct ti_sci_msg_hdr *hdr;
 	unsigned int retry = 5;
@@ -104,7 +107,7 @@
 
 	for (; retry > 0; retry--) {
 		/* Receive the response */
-		ret = k3_sec_proxy_recv(chan, msg);
+		ret = ti_sci_transport_recv(chan, msg);
 		if (ret) {
 			ERROR("Message receive failed (%d)\n", ret);
 			return ret;
@@ -133,6 +136,9 @@
 	if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK))
 		return -ENODEV;
 
+	/* TODO: Verify checksum */
+	(void)hdr->sec_hdr.checksum;
+
 	return 0;
 }
 
@@ -145,21 +151,21 @@
  */
 static int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
 {
-	struct k3_sec_proxy_msg *tx_msg = &xfer->tx_message;
-	struct k3_sec_proxy_msg *rx_msg = &xfer->rx_message;
+	struct ti_sci_msg *tx_msg = &xfer->tx_message;
+	struct ti_sci_msg *rx_msg = &xfer->rx_message;
 	int ret;
 
 	bakery_lock_get(&ti_sci_xfer_lock);
 
 	/* Clear any spurious messages in receive queue */
-	ret = k3_sec_proxy_clear_rx_thread(SP_RESPONSE);
+	ret = ti_sci_transport_clear_rx_thread(RX_SECURE_TRANSPORT_CHANNEL_ID);
 	if (ret) {
 		ERROR("Could not clear response queue (%d)\n", ret);
 		goto unlock;
 	}
 
 	/* Send the message */
-	ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, tx_msg);
+	ret = ti_sci_transport_send(TX_SECURE_TRANSPORT_CHANNEL_ID, tx_msg);
 	if (ret) {
 		ERROR("Message sending failed (%d)\n", ret);
 		goto unlock;
@@ -167,7 +173,7 @@
 
 	/* Get the response if requested */
 	if (rx_msg->len != 0U) {
-		ret = ti_sci_get_response(rx_msg, SP_RESPONSE);
+		ret = ti_sci_get_response(rx_msg, RX_SECURE_TRANSPORT_CHANNEL_ID);
 		if (ret != 0U) {
 			ERROR("Failed to get response (%d)\n", ret);
 			goto unlock;
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/drivers/ti/ti_sci/ti_sci.h
similarity index 99%
rename from plat/ti/k3/common/drivers/ti_sci/ti_sci.h
rename to drivers/ti/ti_sci/ti_sci.h
index 06d1f8d..1f19632 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
+++ b/drivers/ti/ti_sci/ti_sci.h
@@ -2,7 +2,7 @@
  * Texas Instruments System Control Interface API
  *   Based on Linux and U-Boot implementation
  *
- * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2018-2025 Texas Instruments Incorporated - https://www.ti.com/
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/drivers/ti/ti_sci/ti_sci_protocol.h
similarity index 98%
rename from plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
rename to drivers/ti/ti_sci/ti_sci_protocol.h
index cc71eac..bdd2462 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
+++ b/drivers/ti/ti_sci/ti_sci_protocol.h
@@ -5,7 +5,7 @@
  * The system works in a message response protocol
  * See: http://processors.wiki.ti.com/index.php/TISCI for details
  *
- * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2018-2025 Texas Instruments Incorporated - https://www.ti.com/
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -54,6 +54,17 @@
 #define TISCI_MSG_WAIT_PROC_BOOT_STATUS	0xc401
 
 /**
+ * struct ti_sci_secure_msg_hdr - Header that prefixes all TISCI messages sent
+ *				  via secure transport.
+ * @checksum:	crc16 checksum for the entire message
+ * @reserved:	Reserved for future use.
+ */
+struct ti_sci_secure_msg_hdr {
+	uint16_t checksum;
+	uint16_t reserved;
+} __packed;
+
+/**
  * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
  * @type:	Type of messages: One of TI_SCI_MSG* values
  * @host:	Host of the message
@@ -61,6 +72,7 @@
  * @flags:	Flag for the message
  */
 struct ti_sci_msg_hdr {
+	struct ti_sci_secure_msg_hdr sec_hdr;
 	uint16_t type;
 	uint8_t host;
 	uint8_t seq;
diff --git a/drivers/ti/ti_sci/ti_sci_transport.h b/drivers/ti/ti_sci/ti_sci_transport.h
new file mode 100644
index 0000000..13d0fb5
--- /dev/null
+++ b/drivers/ti/ti_sci/ti_sci_transport.h
@@ -0,0 +1,74 @@
+/*
+ * Texas Instruments SCI Transport Protocol Header
+ *
+ * Copyright (C) 2018-2025 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TI_SCI_TRANSPORT_H
+#define TI_SCI_TRANSPORT_H
+
+#include <stdint.h>
+
+/**
+ * enum ti_sci_transport_chan_id - Secure Proxy thread IDs
+ *
+ * These are the available IDs used in ti_sci_transport_{send,recv}()
+ */
+enum ti_sci_transport_chan_id {
+#if !K3_SEC_PROXY_LITE
+	RX_SECURE_TRANSPORT_CHANNEL_ID = 1,
+	TX_SECURE_TRANSPORT_CHANNEL_ID,
+#else
+	RX_SECURE_TRANSPORT_CHANNEL_ID = 8,
+	/*
+	 * Note: TISCI documentation indicates "low priority", but in reality
+	 * with a single thread, there is no low or high priority.. This usage
+	 * is more appropriate for TF-A since we can reduce the churn as a
+	 * result.
+	 */
+	TX_SECURE_TRANSPORT_CHANNEL_ID,
+#endif /* K3_SEC_PROXY_LITE */
+};
+
+/**
+ * struct ti_sci_msg - Secure proxy message structure
+ * @len: Length of data in the Buffer
+ * @buf: Buffer pointer
+ *
+ * This is the structure for data used in ti_sci_transport_{send,recv}()
+ */
+struct ti_sci_msg {
+	size_t len;
+	uint8_t *buf;
+};
+
+/**
+ * ti_sci_transport_clear_rx_thread() - Clear a receive Secure Proxy thread
+ * @id: Channel Identifier
+ * @msg: Pointer to ti_sci_msg
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_transport_clear_rx_thread(enum ti_sci_transport_chan_id id);
+
+/**
+ * ti_sci_transport_send() - Send data over mailbox/ Secure Proxy thread
+ * @id: Channel Identifier
+ * @msg: Pointer to ti_sci_msg
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_transport_send(enum ti_sci_transport_chan_id id, const struct ti_sci_msg *msg);
+
+/**
+ * ti_sci_transport_recv() - Receive data from a Secure Proxy thread/ mailbox
+ * @id: Channel Identifier
+ * @msg: Pointer to ti_sci_msg
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_transport_recv(enum ti_sci_transport_chan_id id, struct ti_sci_msg *msg);
+
+#endif /* TI_SCI_TRANSPORT_H */
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index c35503a..c43beb6 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -534,6 +534,40 @@
 	cset	x0, ls
 .endm
 
+
+#if __clang_major__ < 17
+/*
+ * A problem with clang version < 17 can cause resolving nested
+ * 'cfi_startproc' to fail compilation.
+ * So add a compatibility variant for start and endfunc expansions
+ * to ignore `cfi_startproc` and `cfi_endproc`, this to be used only with
+ * check_errata/reset macros if we build TF-A with clang version < 17
+ */
+
+.macro func_compat _name, _align=2
+	.section .text.asm.\_name, "ax"
+	.type \_name, %function
+	.align \_align
+	\_name:
+#if ENABLE_BTI
+	bti	jc
+#endif
+.endm
+
+/*
+ * This macro is used to mark the end of a function.
+ */
+.macro endfunc_compat _name
+	.size \_name, . - \_name
+.endm
+
+#else
+
+#define func_compat func
+#define endfunc_compat endfunc
+
+#endif /* __clang_version__ < 17 */
+
 /*
  * Helpers to select which revisions errata apply to.
  *
@@ -555,35 +589,35 @@
  *	argument: x0 - cpu_rev_var
  */
 .macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req
-	func check_erratum_\_cpu\()_\_id
+	func_compat check_erratum_\_cpu\()_\_id
 		cpu_rev_var_ls \_rev_num
 		ret
-	endfunc check_erratum_\_cpu\()_\_id
+	endfunc_compat check_erratum_\_cpu\()_\_id
 .endm
 
 .macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req
-	func check_erratum_\_cpu\()_\_id
+	func_compat check_erratum_\_cpu\()_\_id
 		cpu_rev_var_hs \_rev_num
 		ret
-	endfunc check_erratum_\_cpu\()_\_id
+	endfunc_compat check_erratum_\_cpu\()_\_id
 .endm
 
 .macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req
-	func check_erratum_\_cpu\()_\_id
+	func_compat check_erratum_\_cpu\()_\_id
 		cpu_rev_var_range \_rev_num_lo, \_rev_num_hi
 		ret
-	endfunc check_erratum_\_cpu\()_\_id
+	endfunc_compat check_erratum_\_cpu\()_\_id
 .endm
 
 .macro check_erratum_chosen _cpu:req, _cve:req, _id:req, _chosen:req
-	func check_erratum_\_cpu\()_\_id
+	func_compat check_erratum_\_cpu\()_\_id
 		.if \_chosen
 			mov	x0, #ERRATA_APPLIES
 		.else
 			mov	x0, #ERRATA_MISSING
 		.endif
 		ret
-	endfunc check_erratum_\_cpu\()_\_id
+	endfunc_compat check_erratum_\_cpu\()_\_id
 .endm
 
 /*
@@ -591,14 +625,13 @@
  * body: clobber x0 to x4
  */
 .macro check_erratum_custom_start _cpu:req, _cve:req, _id:req
-	func check_erratum_\_cpu\()_\_id
+	func_compat check_erratum_\_cpu\()_\_id
 .endm
 
 .macro check_erratum_custom_end _cpu:req, _cve:req, _id:req
-	endfunc check_erratum_\_cpu\()_\_id
+	endfunc_compat check_erratum_\_cpu\()_\_id
 .endm
 
-
 /*******************************************************************************
  * CPU reset function wrapper
  ******************************************************************************/
@@ -611,7 +644,7 @@
  *	Name of cpu as given to declare_cpu_ops
  */
 .macro cpu_reset_prologue _cpu:req
-	func \_cpu\()_reset_func
+	func_compat \_cpu\()_reset_func
 		mov	x15, x30
 		get_rev_var x14, x0
 .endm
@@ -636,7 +669,7 @@
 .macro cpu_reset_func_end _cpu:req
 		isb
 		ret	x15
-	endfunc \_cpu\()_reset_func
+	endfunc_compat \_cpu\()_reset_func
 .endm
 
 /*
diff --git a/include/lib/xlat_mpu/xlat_mpu.h b/include/lib/xlat_mpu/xlat_mpu.h
deleted file mode 100644
index 3a470ad..0000000
--- a/include/lib/xlat_mpu/xlat_mpu.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef XLAT_MPU_H
-#define XLAT_MPU_H
-
-#ifndef __ASSEMBLER__
-
-#include <lib/cassert.h>
-
-#define XLAT_TABLES_LIB_V2	1
-
-void enable_mpu_el2(unsigned int flags);
-void enable_mpu_direct_el2(unsigned int flags);
-
-/*
- * Function to wipe clean and disable all MPU regions.  This function expects
- * that the MPU has already been turned off, and caching concerns addressed,
- * but it nevertheless also explicitly turns off the MPU.
- */
-void clear_all_mpu_regions(void);
-
-#endif /* __ASSEMBLER__ */
-#endif /* XLAT_MPU_H */
diff --git a/lib/xlat_mpu/aarch64/enable_mpu.S b/lib/xlat_mpu/aarch64/enable_mpu.S
deleted file mode 100644
index 0dda979..0000000
--- a/lib/xlat_mpu/aarch64/enable_mpu.S
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <asm_macros.S>
-#include <assert_macros.S>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-#include <platform_def.h>
-
-	.global	enable_mpu_direct_el2
-
-	/* void enable_mmu_direct_el2(unsigned int flags) */
-func enable_mpu_direct_el2
-#if ENABLE_ASSERTIONS
-	mrs	x1, sctlr_el2
-	tst	x1, #SCTLR_M_BIT
-	ASM_ASSERT(eq)
-#endif
-	mov	x7, x0
-	adrp	x0, mmu_cfg_params
-	add	x0, x0, :lo12:mmu_cfg_params
-
-	/* (MAIRs are already set up) */
-
-	/* TCR */
-	ldr	x2, [x0, #(MMU_CFG_TCR << 3)]
-	msr	tcr_el2, x2
-
-	/*
-	 * Ensure all translation table writes have drained into memory, the TLB
-	 * invalidation is complete, and translation register writes are
-	 * committed before enabling the MMU
-	 */
-	dsb	ish
-	isb
-
-	/* Set and clear required fields of SCTLR */
-	mrs	x4, sctlr_el2
-	mov_imm	x5, SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT
-	orr	x4, x4, x5
-
-	/* Additionally, amend SCTLR fields based on flags */
-	bic	x5, x4, #SCTLR_C_BIT
-	tst	x7, #DISABLE_DCACHE
-	csel	x4, x5, x4, ne
-
-	msr	sctlr_el2, x4
-	isb
-
-	ret
-endfunc enable_mpu_direct_el2
diff --git a/lib/xlat_mpu/aarch64/xlat_mpu_arch.c b/lib/xlat_mpu/aarch64/xlat_mpu_arch.c
deleted file mode 100644
index b462de0..0000000
--- a/lib/xlat_mpu/aarch64/xlat_mpu_arch.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "../xlat_mpu_private.h"
-#include <arch.h>
-#include <arch_features.h>
-#include <lib/cassert.h>
-#include <lib/utils_def.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-
-#include <fvp_r_arch_helpers.h>
-
-#warning "xlat_mpu library is currently experimental and its API may change in future."
-
-#if ENABLE_ASSERTIONS
-/*
- * Return minimum virtual address space size supported by the architecture
- */
-uintptr_t xlat_get_min_virt_addr_space_size(void)
-{
-	uintptr_t ret;
-
-	if (is_feat_ttst_present()) {
-		ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
-	} else {
-		ret = MIN_VIRT_ADDR_SPACE_SIZE;
-	}
-	return ret;
-}
-#endif /* ENABLE_ASSERTIONS*/
-
-bool is_mpu_enabled_ctx(const xlat_ctx_t *ctx)
-{
-	if (ctx->xlat_regime == EL1_EL0_REGIME) {
-		assert(xlat_arch_current_el() >= 1U);
-		return (read_sctlr_el1() & SCTLR_M_BIT) != 0U;
-	} else {
-		assert(xlat_arch_current_el() >= 2U);
-		return (read_sctlr_el2() & SCTLR_M_BIT) != 0U;
-	}
-}
-
-bool is_dcache_enabled(void)
-{
-	unsigned int el = get_current_el();
-
-	if (el == 1U) {
-		return (read_sctlr_el1() & SCTLR_C_BIT) != 0U;
-	} else {  /* must be EL2 */
-		return (read_sctlr_el2() & SCTLR_C_BIT) != 0U;
-	}
-}
-
-unsigned int xlat_arch_current_el(void)
-{
-	unsigned int el = (unsigned int)GET_EL(read_CurrentEl());
-
-	assert(el > 0U);
-
-	return el;
-}
-
diff --git a/lib/xlat_mpu/ro_xlat_mpu.mk b/lib/xlat_mpu/ro_xlat_mpu.mk
deleted file mode 100644
index d3af3bd..0000000
--- a/lib/xlat_mpu/ro_xlat_mpu.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Copyright (c) 2021, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-ifeq (${USE_DEBUGFS}, 1)
-    $(error "Debugfs requires functionality from the dynamic translation \
-             library and is incompatible with ALLOW_RO_XLAT_TABLES.")
-endif
-
-ifeq (${ARCH},aarch32)
-    $(error "The xlat_mpu library does not currently support AArch32.")
-endif
diff --git a/lib/xlat_mpu/xlat_mpu.mk b/lib/xlat_mpu/xlat_mpu.mk
deleted file mode 100644
index 31bef04..0000000
--- a/lib/xlat_mpu/xlat_mpu.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-XLAT_MPU_LIB_V1_SRCS	:=	$(addprefix lib/xlat_mpu/,		\
-				${ARCH}/enable_mpu.S			\
-				${ARCH}/xlat_mpu_arch.c			\
-				xlat_mpu_context.c			\
-				xlat_mpu_core.c				\
-				xlat_mpu_utils.c)
-
-XLAT_MPU_LIB_V1	:=	1
-$(eval $(call add_define,XLAT_MPU_LIB_V1))
-
-ifeq (${ALLOW_XLAT_MPU}, 1)
-    include lib/xlat_mpu_v2/ro_xlat_mpu.mk
-endif
diff --git a/lib/xlat_mpu/xlat_mpu_context.c b/lib/xlat_mpu/xlat_mpu_context.c
deleted file mode 100644
index 783f21d..0000000
--- a/lib/xlat_mpu/xlat_mpu_context.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <common/debug.h>
-
-#include "lib/xlat_mpu/xlat_mpu.h"
-#include <lib/xlat_tables/xlat_tables_defs.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-#include "xlat_mpu_private.h"
-
-#include <fvp_r_arch_helpers.h>
-#include <platform_def.h>
-
-#warning "xlat_mpu library is currently experimental and its API may change in future."
-
-
-/*
- * MMU configuration register values for the active translation context. Used
- * from the MMU assembly helpers.
- */
-uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
-
-/*
- * Allocate and initialise the default translation context for the BL image
- * currently executing.
- */
-REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
-			PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
-
-void mmap_add(const mmap_region_t *mm)
-{
-	mmap_add_ctx(&tf_xlat_ctx, mm);
-}
-
-void __init init_xlat_tables(void)
-{
-	assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID);
-
-	unsigned int current_el = xlat_arch_current_el();
-
-	if (current_el == 1U) {
-		tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME;
-	} else {
-		assert(current_el == 2U);
-		tf_xlat_ctx.xlat_regime = EL2_REGIME;
-	}
-	/* Note:  If EL3 is supported in future v8-R64, add EL3 assignment */
-	init_xlat_tables_ctx(&tf_xlat_ctx);
-}
-
-int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr)
-{
-	return xlat_get_mem_attributes_ctx(&tf_xlat_ctx, base_va, attr);
-}
-
-void enable_mpu_el2(unsigned int flags)
-{
-	/* EL2 is strictly MPU on v8-R64, so no need for setup_mpu_cfg() */
-	enable_mpu_direct_el2(flags);
-}
diff --git a/lib/xlat_mpu/xlat_mpu_core.c b/lib/xlat_mpu/xlat_mpu_core.c
deleted file mode 100644
index 33f381d..0000000
--- a/lib/xlat_mpu/xlat_mpu_core.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <arch_features.h>
-#include <common/debug.h>
-#include <lib/utils_def.h>
-#include <lib/xlat_tables/xlat_tables_defs.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-#include "xlat_mpu_private.h"
-
-#include <fvp_r_arch_helpers.h>
-#include <platform_def.h>
-
-#warning "xlat_mpu library is currently experimental and its API may change in future."
-
-
-/* Helper function that cleans the data cache only if it is enabled. */
-static inline __attribute__((unused))
-	void xlat_clean_dcache_range(uintptr_t addr, size_t size)
-{
-	if (is_dcache_enabled()) {
-		clean_dcache_range(addr, size);
-	}
-}
-
-
-
-/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */
-uint64_t prbar_attr_value(uint32_t attr)
-{
-	uint64_t retValue = UL(0);
-	uint64_t extract;  /* temp var holding bit extracted from attr */
-
-	/* Extract and stuff SH: */
-	extract = (uint64_t) ((attr >> MT_SHAREABILITY_SHIFT)
-				& MT_SHAREABILITY_MASK);
-	retValue |= (extract << PRBAR_SH_SHIFT);
-
-	/* Extract and stuff AP: */
-	extract = (uint64_t) ((attr >> MT_PERM_SHIFT) & MT_PERM_MASK);
-	if (extract == 0U) {
-		retValue |= (UL(2) << PRBAR_AP_SHIFT);
-	} else /* extract == 1 */ {
-		retValue |= (UL(0) << PRBAR_AP_SHIFT);
-	}
-
-	/* Extract and stuff XN: */
-	extract = (uint64_t) ((attr >> MT_EXECUTE_SHIFT) & MT_EXECUTE_MASK);
-	retValue |= (extract << PRBAR_XN_SHIFT);
-	/* However, also don't execute in peripheral space: */
-	extract = (uint64_t) ((attr >> MT_TYPE_SHIFT) & MT_TYPE_MASK);
-	if (extract == 0U) {
-		retValue |= (UL(1) << PRBAR_XN_SHIFT);
-	}
-	return retValue;
-}
-
-/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */
-uint64_t prlar_attr_value(uint32_t attr)
-{
-	uint64_t retValue = UL(0);
-	uint64_t extract;  /* temp var holding bit extracted from attr */
-
-	/* Extract and stuff AttrIndx: */
-	extract = (uint64_t) ((attr >> MT_TYPE_SHIFT)
-				& MT_TYPE_MASK);
-	switch (extract) {
-	case UL(0):
-		retValue |= (UL(1) << PRLAR_ATTR_SHIFT);
-		break;
-	case UL(2):
-		/* 0, so OR in nothing */
-		break;
-	case UL(3):
-		retValue |= (UL(2) << PRLAR_ATTR_SHIFT);
-		break;
-	default:
-		retValue |= (extract << PRLAR_ATTR_SHIFT);
-		break;
-	}
-
-	/* Stuff EN: */
-	retValue |= (UL(1) << PRLAR_EN_SHIFT);
-
-	/* Force NS to 0 (Secure);  v8-R64 only supports Secure: */
-	extract = ~(1U << PRLAR_NS_SHIFT);
-	retValue &= extract;
-
-	return retValue;
-}
-
-/*
- * Function that writes an MPU "translation" into the MPU registers. If not
- * possible (e.g., if no more MPU regions available) boot is aborted.
- */
-static void mpu_map_region(mmap_region_t *mm)
-{
-	uint64_t prenr_el2_value = 0UL;
-	uint64_t prbar_attrs = 0UL;
-	uint64_t prlar_attrs = 0UL;
-	int region_to_use = 0;
-
-	/* If all MPU regions in use, then abort boot: */
-	prenr_el2_value = read_prenr_el2();
-	assert(prenr_el2_value != 0xffffffff);
-
-	/* Find and select first-available MPU region (PRENR has an enable bit
-	 * for each MPU region, 1 for in-use or 0 for unused):
-	 */
-	for (region_to_use = 0;  region_to_use < N_MPU_REGIONS;
-	     region_to_use++) {
-		if (((prenr_el2_value >> region_to_use) & 1) == 0) {
-			break;
-		}
-	}
-	write_prselr_el2((uint64_t) (region_to_use));
-	isb();
-
-	/* Set base and limit addresses: */
-	write_prbar_el2(mm->base_pa & PRBAR_PRLAR_ADDR_MASK);
-	write_prlar_el2((mm->base_pa + mm->size - 1UL)
-			& PRBAR_PRLAR_ADDR_MASK);
-	dsbsy();
-	isb();
-
-	/* Set attributes: */
-	prbar_attrs = prbar_attr_value(mm->attr);
-	write_prbar_el2(read_prbar_el2() | prbar_attrs);
-	prlar_attrs = prlar_attr_value(mm->attr);
-	write_prlar_el2(read_prlar_el2() | prlar_attrs);
-	dsbsy();
-	isb();
-
-	/* Mark this MPU region as used: */
-	prenr_el2_value |= (1 << region_to_use);
-	write_prenr_el2(prenr_el2_value);
-	isb();
-}
-
-/*
- * Function that verifies that a region can be mapped.
- * Returns:
- *        0: Success, the mapping is allowed.
- *   EINVAL: Invalid values were used as arguments.
- *   ERANGE: The memory limits were surpassed.
- *   ENOMEM: There is not enough memory in the mmap array.
- *    EPERM: Region overlaps another one in an invalid way.
- */
-static int mmap_add_region_check(const xlat_ctx_t *ctx, const mmap_region_t *mm)
-{
-	unsigned long long base_pa = mm->base_pa;
-	uintptr_t base_va = mm->base_va;
-	size_t size = mm->size;
-
-	unsigned long long end_pa = base_pa + size - 1U;
-	uintptr_t end_va = base_va + size - 1U;
-
-	if (base_pa != base_va) {
-		return -EINVAL;  /* MPU does not perform address translation */
-	}
-	if ((base_pa % 64ULL) != 0ULL) {
-		return -EINVAL;  /* MPU requires 64-byte alignment */
-	}
-	/* Check for overflows */
-	if ((base_pa > end_pa) || (base_va > end_va)) {
-		return -ERANGE;
-	}
-	if (end_pa > ctx->pa_max_address) {
-		return -ERANGE;
-	}
-	/* Check that there is space in the ctx->mmap array */
-	if (ctx->mmap[ctx->mmap_num - 1].size != 0U) {
-		return -ENOMEM;
-	}
-	/* Check for PAs and VAs overlaps with all other regions */
-	for (const mmap_region_t *mm_cursor = ctx->mmap;
-	     mm_cursor->size != 0U; ++mm_cursor) {
-
-		uintptr_t mm_cursor_end_va =
-			mm_cursor->base_va + mm_cursor->size - 1U;
-
-		/*
-		 * Check if one of the regions is completely inside the other
-		 * one.
-		 */
-		bool fully_overlapped_va =
-			((base_va >= mm_cursor->base_va) &&
-					(end_va <= mm_cursor_end_va)) ||
-			((mm_cursor->base_va >= base_va) &&
-						(mm_cursor_end_va <= end_va));
-
-		/*
-		 * Full VA overlaps are only allowed if both regions are
-		 * identity mapped (zero offset) or have the same VA to PA
-		 * offset. Also, make sure that it's not the exact same area.
-		 * This can only be done with static regions.
-		 */
-		if (fully_overlapped_va) {
-
-#if PLAT_XLAT_TABLES_DYNAMIC
-			if (((mm->attr & MT_DYNAMIC) != 0U) ||
-			    ((mm_cursor->attr & MT_DYNAMIC) != 0U)) {
-				return -EPERM;
-			}
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-			if ((mm_cursor->base_va - mm_cursor->base_pa)
-					!= (base_va - base_pa)) {
-				return -EPERM;
-			}
-			if ((base_va == mm_cursor->base_va) &&
-					(size == mm_cursor->size)) {
-				return -EPERM;
-			}
-		} else {
-			/*
-			 * If the regions do not have fully overlapping VAs,
-			 * then they must have fully separated VAs and PAs.
-			 * Partial overlaps are not allowed
-			 */
-
-			unsigned long long mm_cursor_end_pa =
-				     mm_cursor->base_pa + mm_cursor->size - 1U;
-
-			bool separated_pa = (end_pa < mm_cursor->base_pa) ||
-				(base_pa > mm_cursor_end_pa);
-			bool separated_va = (end_va < mm_cursor->base_va) ||
-				(base_va > mm_cursor_end_va);
-
-			if (!separated_va || !separated_pa) {
-				return -EPERM;
-			}
-		}
-	}
-
-	return 0;
-}
-
-void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
-{
-	mmap_region_t *mm_cursor = ctx->mmap, *mm_destination;
-	const mmap_region_t *mm_end = ctx->mmap + ctx->mmap_num;
-	const mmap_region_t *mm_last;
-	unsigned long long end_pa = mm->base_pa + mm->size - 1U;
-	uintptr_t end_va = mm->base_va + mm->size - 1U;
-	int ret;
-
-	/* Ignore empty regions */
-	if (mm->size == 0U) {
-		return;
-	}
-
-	/* Static regions must be added before initializing the xlat tables. */
-	assert(!ctx->initialized);
-
-	ret = mmap_add_region_check(ctx, mm);
-	if (ret != 0) {
-		ERROR("mmap_add_region_check() failed. error %d\n", ret);
-		assert(false);
-		return;
-	}
-
-	/*
-	 * Find the last entry marker in the mmap
-	 */
-	mm_last = ctx->mmap;
-	while ((mm_last->size != 0U) && (mm_last < mm_end)) {
-		++mm_last;
-	}
-
-	/*
-	 * Check if we have enough space in the memory mapping table.
-	 * This shouldn't happen as we have checked in mmap_add_region_check
-	 * that there is free space.
-	 */
-	assert(mm_last->size == 0U);
-
-	/* Make room for new region by moving other regions up by one place */
-	mm_destination = mm_cursor + 1;
-	(void)memmove(mm_destination, mm_cursor,
-		(uintptr_t)mm_last - (uintptr_t)mm_cursor);
-
-	/*
-	 * Check we haven't lost the empty sentinel from the end of the array.
-	 * This shouldn't happen as we have checked in mmap_add_region_check
-	 * that there is free space.
-	 */
-	assert(mm_end->size == 0U);
-
-	*mm_cursor = *mm;
-
-	if (end_pa > ctx->max_pa) {
-		ctx->max_pa = end_pa;
-	}
-	if (end_va > ctx->max_va) {
-		ctx->max_va = end_va;
-	}
-}
-
-void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
-{
-	const mmap_region_t *mm_cursor = mm;
-
-	while (mm_cursor->granularity != 0U) {
-		mmap_add_region_ctx(ctx, mm_cursor);
-		mm_cursor++;
-	}
-}
-
-void __init init_xlat_tables_ctx(xlat_ctx_t *ctx)
-{
-	uint64_t mair = UL(0);
-
-	assert(ctx != NULL);
-	assert(!ctx->initialized);
-	assert((ctx->xlat_regime == EL2_REGIME) ||
-		(ctx->xlat_regime == EL1_EL0_REGIME));
-	/* Note:  Add EL3_REGIME if EL3 is supported in future v8-R64 cores. */
-	assert(!is_mpu_enabled_ctx(ctx));
-
-	mmap_region_t *mm = ctx->mmap;
-
-	assert(ctx->va_max_address >=
-		(xlat_get_min_virt_addr_space_size() - 1U));
-	assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U));
-	assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U));
-
-	xlat_mmap_print(mm);
-
-	/* All tables must be zeroed before mapping any region. */
-
-	for (unsigned int i = 0U; i < ctx->base_table_entries; i++)
-		ctx->base_table[i] = INVALID_DESC;
-
-	/* Also mark all MPU regions as invalid in the MPU hardware itself: */
-	write_prenr_el2(0);
-		/* Sufficient for current, max-32-region implementations. */
-	dsbsy();
-	isb();
-	while (mm->size != 0U) {
-		if (read_prenr_el2() == ALL_MPU_EL2_REGIONS_USED) {
-			ERROR("Not enough MPU regions to map region:\n"
-				" VA:0x%lx  PA:0x%llx  size:0x%zx  attr:0x%x\n",
-				mm->base_va, mm->base_pa, mm->size, mm->attr);
-			panic();
-		} else {
-#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
-			xlat_clean_dcache_range((uintptr_t)mm->base_va,
-				mm->size);
-#endif
-			mpu_map_region(mm);
-		}
-		mm++;
-	}
-
-	ctx->initialized = true;
-
-	xlat_tables_print(ctx);
-
-	/* Set attributes in the right indices of the MAIR */
-	mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
-	mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
-			ATTR_IWBWA_OWBWA_NTR_INDEX);
-	mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE,
-			ATTR_NON_CACHEABLE_INDEX);
-	write_mair_el2(mair);
-	dsbsy();
-	isb();
-}
-
-/*
- * Function to wipe clean and disable all MPU regions.  This function expects
- * that the MPU has already been turned off, and caching concerns addressed,
- * but it nevertheless also explicitly turns off the MPU.
- */
-void clear_all_mpu_regions(void)
-{
-	uint64_t sctlr_el2_value = 0UL;
-	uint64_t region_n = 0UL;
-
-	/*
-	 * MPU should already be disabled, but explicitly disable it
-	 * nevertheless:
-	 */
-	sctlr_el2_value = read_sctlr_el2() & ~(1UL);
-	write_sctlr_el2(sctlr_el2_value);
-
-	/* Disable all regions: */
-	write_prenr_el2(0UL);
-
-	/* Sequence through all regions, zeroing them out and turning off: */
-	for (region_n = 0UL;  region_n < N_MPU_REGIONS;  region_n++) {
-		write_prselr_el2(region_n);
-		isb();
-		write_prbar_el2((uint64_t) 0);
-		write_prlar_el2((uint64_t) 0);
-		dsbsy();
-		isb();
-	}
-}
diff --git a/lib/xlat_mpu/xlat_mpu_private.h b/lib/xlat_mpu/xlat_mpu_private.h
deleted file mode 100644
index 5b0697d..0000000
--- a/lib/xlat_mpu/xlat_mpu_private.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef XLAT_MPU_PRIVATE_H
-#define XLAT_MPU_PRIVATE_H
-
-#include <stdbool.h>
-
-#include <lib/xlat_tables/xlat_tables_defs.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-
-#include <platform_def.h>
-
-#if PLAT_XLAT_TABLES_DYNAMIC
-/*
- * Private shifts and masks to access fields of an mmap attribute
- */
-/* Dynamic or static */
-#define MT_DYN_SHIFT		U(31)
-
-/*
- * Memory mapping private attributes
- *
- * Private attributes not exposed in the public header.
- */
-
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
-/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */
-uint64_t prbar_attr_value(uint32_t attr);
-/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */
-uint64_t prlar_attr_value(uint32_t attr);
-/* Calculates the attr value for a given PRBAR and PRLAR entry value: */
-uint32_t region_attr(uint64_t prbar_attr, uint64_t prlar_attr);
-
-#define PRBAR_PRLAR_ADDR_MASK	UL(0xffffffffffc0)
-	/* mask for PRBAR & PRLAR MPU-region field */
-/* MPU region attribute bit fields: */
-#define PRBAR_SH_SHIFT		UL(4)
-#define PRBAR_SH_MASK		UL(0x3)
-#define PRBAR_AP_SHIFT		UL(2)
-#define PRBAR_AP_MASK		UL(0x3)
-#define PRBAR_XN_SHIFT		UL(1)
-#define PRBAR_XN_MASK		UL(0x3)
-#define PRLAR_NS_SHIFT		UL(4)
-#define PRLAR_NS_MASK		UL(0x3)
-#define PRBAR_ATTR_SHIFT	UL(0)
-#define PRBAR_ATTR_MASK		UL(0x3f)
-#define PRLAR_ATTR_SHIFT	UL(1)
-#define PRLAR_ATTR_MASK		UL(0x7)
-#define PRLAR_EN_SHIFT		UL(0)
-#define PRLAR_EN_MASK		UL(0x1)
-/* Aspects of the source attributes not defined elsewhere: */
-#define MT_PERM_MASK		UL(0x1)
-#define MT_SEC_MASK		UL(0x1)
-#define MT_EXECUTE_MASK		UL(0x3)
-#define MT_TYPE_SHIFT		UL(0)
-
-#define MPUIR_EL2		S3_4_C0_C0_4
-#define PRBAR_EL2		S3_4_C6_C8_0
-#define PRLAR_EL2		S3_4_C6_C8_1
-#define PRSELR_EL2		S3_4_C6_C2_1
-#define PRENR_EL2		S3_4_C6_C1_1
-
-/* v8-R64 MPU registers */
-DEFINE_RENAME_SYSREG_RW_FUNCS(mpuir_el2, MPUIR_EL2)
-DEFINE_RENAME_SYSREG_RW_FUNCS(prenr_el2, PRENR_EL2)
-DEFINE_RENAME_SYSREG_RW_FUNCS(prselr_el2, PRSELR_EL2)
-DEFINE_RENAME_SYSREG_RW_FUNCS(prbar_el2, PRBAR_EL2)
-DEFINE_RENAME_SYSREG_RW_FUNCS(prlar_el2, PRLAR_EL2)
-
-extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
-
-/*
- * Return the execute-never mask that will prevent instruction fetch at the
- * given translation regime.
- */
-uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime);
-
-/* Print VA, PA, size and attributes of all regions in the mmap array. */
-void xlat_mmap_print(const mmap_region_t *mmap);
-
-/*
- * Print the current state of the translation tables by reading them from
- * memory.
- */
-void xlat_tables_print(xlat_ctx_t *ctx);
-
-/*
- * Returns a block/page table descriptor for the given level and attributes.
- */
-uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr,
-		   unsigned long long addr_pa, unsigned int level);
-
-/*
- * Architecture-specific initialization code.
- */
-
-/* Returns the current Exception Level. The returned EL must be 1 or higher. */
-unsigned int xlat_arch_current_el(void);
-
-/*
- * Returns true if the MMU of the translation regime managed by the given
- * xlat_ctx_t is enabled, false otherwise.
- */
-bool is_mpu_enabled_ctx(const xlat_ctx_t *ctx);
-
-/*
- * Returns minimum virtual address space size supported by the architecture
- */
-uintptr_t xlat_get_min_virt_addr_space_size(void);
-
-#endif /* XLAT_MPU_PRIVATE_H */
diff --git a/lib/xlat_mpu/xlat_mpu_utils.c b/lib/xlat_mpu/xlat_mpu_utils.c
deleted file mode 100644
index dc5f956..0000000
--- a/lib/xlat_mpu/xlat_mpu_utils.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <common/debug.h>
-#include <lib/utils_def.h>
-#include <lib/xlat_tables/xlat_tables_defs.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-#include "xlat_mpu_private.h"
-
-#include <fvp_r_arch_helpers.h>
-#include <platform_def.h>
-
-#warning "xlat_mpu library is currently experimental and its API may change in future."
-
-
-void xlat_mmap_print(__unused const mmap_region_t *mmap)
-{
-	/* Empty */
-}
-
-#if LOG_LEVEL < LOG_LEVEL_VERBOSE
-
-void xlat_tables_print(__unused xlat_ctx_t *ctx)
-{
-	/* Empty */
-}
-
-#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */
-
-static void xlat_tables_print_internal(__unused xlat_ctx_t *ctx)
-{
-	int region_to_use = 0;
-	uintptr_t region_base;
-	size_t region_size;
-	uint64_t prenr_el2_value = 0U;
-
-	/*
-	 * Keep track of how many invalid descriptors are counted in a row.
-	 * Whenever multiple invalid descriptors are found, only the first one
-	 * is printed, and a line is added to inform about how many descriptors
-	 * have been omitted.
-	 */
-
-	/*
-	 * TODO:  Remove this WARN() and comment when these API calls are more
-	 *        completely implemented and tested!
-	 */
-	WARN("%s in this early version of xlat_mpu library may not produce reliable results!",
-	     __func__);
-
-	/*
-	 * Sequence through all regions and print those in-use (PRENR has an
-	 * enable bit for each MPU region, 1 for in-use or 0 for unused):
-	 */
-	prenr_el2_value = read_prenr_el2();
-	for (region_to_use = 0;  region_to_use < N_MPU_REGIONS;
-	     region_to_use++) {
-		if (((prenr_el2_value >> region_to_use) & 1U) == 0U) {
-			continue;
-		}
-		region_base = read_prbar_el2() & PRBAR_PRLAR_ADDR_MASK;
-		region_size = read_prlar_el2() & PRBAR_PRLAR_ADDR_MASK;
-		printf("Address:  0x%llx, size:  0x%llx ",
-			(long long) region_base,
-			(long long) region_size);
-	}
-}
-
-void xlat_tables_print(__unused xlat_ctx_t *ctx)
-{
-	xlat_tables_print_internal(ctx);
-}
-
-#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 777729e..c8439e9 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-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -156,7 +156,7 @@
  */
 #if TRUSTED_BOARD_BOOT
 #if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
-# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1F000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
+# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x20000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
 #elif TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA
 # define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
 #else
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 3dd38cd..9659e73 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -224,14 +224,9 @@
 PLAT_BL_COMMON_SOURCES 	+=	lib/xlat_tables/xlat_tables_common.c	      \
 				lib/xlat_tables/${ARCH}/xlat_tables.c
 else
-ifeq (${XLAT_MPU_LIB_V1}, 1)
-include lib/xlat_mpu/xlat_mpu.mk
-PLAT_BL_COMMON_SOURCES	+=	${XLAT_MPU_LIB_V1_SRCS}
-else
 include lib/xlat_tables_v2/xlat_tables.mk
 PLAT_BL_COMMON_SOURCES	+=      ${XLAT_TABLES_LIB_SRCS}
 endif
-endif
 
 ARM_IO_SOURCES		+=	plat/arm/common/arm_io_storage.c		\
 				plat/arm/common/fconf/arm_fconf_io.c
diff --git a/plat/ti/k3/include/k3_console.h b/plat/ti/common/include/k3_console.h
similarity index 100%
rename from plat/ti/k3/include/k3_console.h
rename to plat/ti/common/include/k3_console.h
diff --git a/plat/ti/k3/include/k3_gicv3.h b/plat/ti/common/include/k3_gicv3.h
similarity index 100%
rename from plat/ti/k3/include/k3_gicv3.h
rename to plat/ti/common/include/k3_gicv3.h
diff --git a/plat/ti/k3/include/plat_macros.S b/plat/ti/common/include/plat_macros.S
similarity index 100%
rename from plat/ti/k3/include/plat_macros.S
rename to plat/ti/common/include/plat_macros.S
diff --git a/plat/ti/common/include/plat_private.h b/plat/ti/common/include/plat_private.h
new file mode 100644
index 0000000..697cc5c
--- /dev/null
+++ b/plat/ti/common/include/plat_private.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_PRIVATE_H
+#define PLATFORM_PRIVATE_H
+
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <board_def.h>
+
+#define ADDR_DOWN(_adr) (_adr & XLAT_ADDR_MASK(2U))
+#define SIZE_UP(_adr, _sz) (round_up((_adr + _sz), XLAT_BLOCK_SIZE(2U)) - ADDR_DOWN(_adr))
+
+#define K3_MAP_REGION_FLAT(_adr, _sz, _attr) \
+	MAP_REGION_FLAT(ADDR_DOWN(_adr), SIZE_UP(_adr, _sz), _attr)
+
+extern const mmap_region_t plat_k3_mmap[];
+
+/* Any kind of SOC specific init can be done here */
+int ti_soc_init(void);
+
+#endif /* PLATFORM_PRIVATE_H */
diff --git a/plat/ti/common/include/ti_platform_defs.h b/plat/ti/common/include/ti_platform_defs.h
new file mode 100644
index 0000000..44c2f94
--- /dev/null
+++ b/plat/ti/common/include/ti_platform_defs.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TI_PLATFORM_DEF_H
+#define TI_PLATFORM_DEF_H
+
+#include <arch.h>
+#include <plat/common/common_def.h>
+
+#include <board_def.h>
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stack */
+#if IMAGE_BL31
+#define PLATFORM_STACK_SIZE		0x800
+#else
+#define PLATFORM_STACK_SIZE		0x1000
+#endif
+
+#define PLATFORM_SYSTEM_COUNT		1
+#define PLATFORM_CORE_COUNT		(K3_CLUSTER0_CORE_COUNT + \
+					K3_CLUSTER1_CORE_COUNT + \
+					K3_CLUSTER2_CORE_COUNT + \
+					K3_CLUSTER3_CORE_COUNT)
+
+#define PLATFORM_CLUSTER_COUNT		((K3_CLUSTER0_CORE_COUNT != 0) + \
+					(K3_CLUSTER1_CORE_COUNT != 0) + \
+					(K3_CLUSTER2_CORE_COUNT != 0) + \
+					(K3_CLUSTER3_CORE_COUNT != 0))
+
+#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_SYSTEM_COUNT + \
+					PLATFORM_CLUSTER_COUNT + \
+					PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL2
+#define PLAT_MAX_OFF_STATE		U(2)
+#define PLAT_MAX_RET_STATE		U(1)
+
+/*******************************************************************************
+ * Memory layout constants
+ ******************************************************************************/
+
+/*
+ * This RAM will be used for the bootloader including code, bss, and stacks.
+ * It may need to be increased if BL31 grows in size.
+ *
+ * The link addresses are determined by BL31_BASE + offset.
+ * When ENABLE_PIE is set, the TF images can be loaded anywhere, so
+ * BL31_BASE is really arbitrary.
+ *
+ * When ENABLE_PIE is unset, BL31_BASE should be chosen so that
+ * it matches to the physical address where BL31 is loaded, that is,
+ * BL31_BASE should be the base address of the RAM region.
+ *
+ * Lets make things explicit by mapping BL31_BASE to 0x0 since ENABLE_PIE is
+ * defined as default for our platform.
+ */
+#define BL31_BASE	UL(0x00000000) /* PIE remapped on fly */
+#define BL31_SIZE	UL(0x00020000) /* 128k */
+#define BL31_LIMIT	(BL31_BASE + BL31_SIZE)
+
+/*
+ * Defines the maximum number of translation tables that are allocated by the
+ * translation table library code. To minimize the amount of runtime memory
+ * used, choose the smallest value needed to map the required virtual addresses
+ * for each BL stage.
+ */
+#define MAX_XLAT_TABLES		4
+
+/*
+ * Defines the maximum number of regions that are allocated by the translation
+ * table library code. A region consists of physical base address, virtual base
+ * address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as
+ * defined in the `mmap_region_t` structure. The platform defines the regions
+ * that should be mapped. Then, the translation table library will create the
+ * corresponding tables and descriptors at runtime. To minimize the amount of
+ * runtime memory used, choose the smallest value needed to register the
+ * required regions for each BL stage.
+ */
+#if USE_COHERENT_MEM
+#define MAX_MMAP_REGIONS	11
+#else
+#define MAX_MMAP_REGIONS	10
+#endif
+
+/*
+ * Defines the total size of the address space in bytes. For example, for a 32
+ * bit address space, this value should be `(1ull << 32)`.
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 32)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+
+/* Platform default console definitions */
+#ifndef K3_USART_BASE
+#define K3_USART_BASE			(0x02800000 + 0x10000 * K3_USART)
+#endif
+
+/* USART has a default size for address space */
+#define K3_USART_SIZE 0x1000
+
+#ifndef K3_USART_CLK_SPEED
+#define K3_USART_CLK_SPEED 48000000
+#endif
+
+/* Crash console defaults */
+#define CRASH_CONSOLE_BASE K3_USART_BASE
+#define CRASH_CONSOLE_CLK K3_USART_CLK_SPEED
+#define CRASH_CONSOLE_BAUD_RATE K3_USART_BAUD
+
+/* Timer frequency */
+#ifndef SYS_COUNTER_FREQ_IN_TICKS
+#define SYS_COUNTER_FREQ_IN_TICKS 200000000
+#endif
+
+/* Interrupt numbers */
+#define ARM_IRQ_SEC_PHY_TIMER		29
+
+#define ARM_IRQ_SEC_SGI_0		8
+#define ARM_IRQ_SEC_SGI_1		9
+#define ARM_IRQ_SEC_SGI_2		10
+#define ARM_IRQ_SEC_SGI_3		11
+#define ARM_IRQ_SEC_SGI_4		12
+#define ARM_IRQ_SEC_SGI_5		13
+#define ARM_IRQ_SEC_SGI_6		14
+#define ARM_IRQ_SEC_SGI_7		15
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_LEVEL), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE)
+
+
+#define K3_GTC_BASE		0x00A90000
+/* We just need 20 byte offset, but simpler to just remap the 64K page in */
+#define K3_GTC_SIZE		0x10000
+#define K3_GTC_CNTCR_OFFSET	0x00
+#define K3_GTC_CNTCR_EN_MASK	0x01
+#define K3_GTC_CNTCR_HDBG_MASK	0x02
+#define K3_GTC_CNTFID0_OFFSET	0x20
+
+#define K3_GIC_BASE	0x01800000
+#define K3_GIC_SIZE	0x200000
+
+#define TI_SCI_HOST_ID			10
+#define TI_SCI_MAX_MESSAGE_SIZE		52
+
+#endif /* TI_PLATFORM_DEF_H */
diff --git a/plat/ti/k3/common/k3_console.c b/plat/ti/common/k3_console.c
similarity index 100%
rename from plat/ti/k3/common/k3_console.c
rename to plat/ti/common/k3_console.c
diff --git a/plat/ti/k3/common/k3_gicv3.c b/plat/ti/common/k3_gicv3.c
similarity index 100%
rename from plat/ti/k3/common/k3_gicv3.c
rename to plat/ti/common/k3_gicv3.c
diff --git a/plat/ti/k3/common/k3_helpers.S b/plat/ti/common/k3_helpers.S
similarity index 100%
rename from plat/ti/k3/common/k3_helpers.S
rename to plat/ti/common/k3_helpers.S
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/common/plat_common.mk
similarity index 77%
rename from plat/ti/k3/common/plat_common.mk
rename to plat/ti/common/plat_common.mk
index 8db732c..1f1b618 100644
--- a/plat/ti/k3/common/plat_common.mk
+++ b/plat/ti/common/plat_common.mk
@@ -51,12 +51,11 @@
 
 PLAT_INCLUDES		+=	\
 				-I${PLAT_PATH}/include			\
-				-I${PLAT_PATH}/common/drivers/sec_proxy	\
-				-I${PLAT_PATH}/common/drivers/ti_sci	\
+				-Idrivers/ti/ti_sci			\
 
 K3_CONSOLE_SOURCES	+=	\
 				drivers/ti/uart/aarch64/16550_console.S	\
-				${PLAT_PATH}/common/k3_console.c	\
+				plat/ti/common/k3_console.c		\
 
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
@@ -64,17 +63,14 @@
 K3_GIC_SOURCES		+=	\
 				${GICV3_SOURCES}			\
 				plat/common/plat_gicv3.c		\
-				${PLAT_PATH}/common/k3_gicv3.c		\
+				plat/ti/common/k3_gicv3.c		\
 
 K3_PSCI_SOURCES		+=	\
 				plat/common/plat_psci_common.c		\
-				${PLAT_PATH}/common/k3_psci.c		\
 
-K3_SEC_PROXY_SOURCES	+=	\
-				${PLAT_PATH}/common/drivers/sec_proxy/sec_proxy.c \
 
 K3_TI_SCI_SOURCES	+=	\
-				${PLAT_PATH}/common/drivers/ti_sci/ti_sci.c \
+				drivers/ti/ti_sci/ti_sci.c		\
 
 PLAT_BL_COMMON_SOURCES	+=	\
 				lib/cpus/aarch64/cortex_a53.S		\
@@ -83,10 +79,7 @@
 				${K3_CONSOLE_SOURCES}			\
 
 BL31_SOURCES		+=	\
-				${PLAT_PATH}/common/k3_bl31_setup.c	\
-				${PLAT_PATH}/common/k3_helpers.S	\
-				${PLAT_PATH}/common/k3_topology.c	\
+				plat/ti/common/ti_bl31_setup.c		\
+				plat/ti/common/k3_helpers.S		\
 				${K3_GIC_SOURCES}			\
-				${K3_PSCI_SOURCES}			\
-				${K3_SEC_PROXY_SOURCES}			\
 				${K3_TI_SCI_SOURCES}			\
diff --git a/plat/ti/common/ti_bl31_setup.c b/plat/ti/common/ti_bl31_setup.c
new file mode 100644
index 0000000..8038452
--- /dev/null
+++ b/plat/ti/common/ti_bl31_setup.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <ti_sci.h>
+
+#include <k3_console.h>
+#include <k3_gicv3.h>
+#include <plat_private.h>
+#include <platform_def.h>
+
+/*
+ * Placeholder variables for maintaining information about the next image(s)
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+static uint32_t k3_get_spsr_for_bl33_entry(void)
+{
+	unsigned long el_status;
+	unsigned int mode;
+	uint32_t spsr;
+
+	/* Figure out what mode we enter the non-secure world in */
+	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+	el_status &= ID_AA64PFR0_ELX_MASK;
+
+	mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 early platform setup, such as console init and deciding on
+ * memory layout.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	/* Initialize the console to provide early debug support */
+	k3_console_setup();
+
+#ifdef BL32_BASE
+	/* Populate entry point information for BL32 */
+	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+					  DISABLE_ALL_EXCEPTIONS);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+#endif
+
+	/* Populate entry point information for BL33 */
+	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+	bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
+	bl33_image_ep_info.spsr = k3_get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#ifdef K3_HW_CONFIG_BASE
+	/*
+	 * According to the file ``Documentation/arch/arm64/booting.rst`` of the
+	 * Linux kernel tree, Linux expects the physical address of the device
+	 * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+	 * must be 0.
+	 */
+	bl33_image_ep_info.args.arg0 = (u_register_t)K3_HW_CONFIG_BASE;
+	bl33_image_ep_info.args.arg1 = 0U;
+	bl33_image_ep_info.args.arg2 = 0U;
+	bl33_image_ep_info.args.arg3 = 0U;
+#endif
+}
+
+void bl31_plat_arch_setup(void)
+{
+	const mmap_region_t bl_regions[] = {
+		MAP_REGION_FLAT(BL31_START, BL31_SIZE, MT_MEMORY | MT_RW | MT_SECURE),
+		MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+				MT_CODE | MT_RO | MT_SECURE),
+		MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE,
+				MT_RO_DATA | MT_RO | MT_SECURE),
+#if USE_COHERENT_MEM
+		MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+				MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+		{ /* sentinel */ }
+	};
+
+	setup_page_tables(bl_regions, plat_k3_mmap);
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	k3_gic_driver_init(K3_GIC_BASE);
+	k3_gic_init();
+	ti_soc_init();
+}
+
+void platform_mem_init(void)
+{
+	/* Do nothing for now... */
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	uint32_t gtc_freq;
+	uint32_t gtc_ctrl;
+
+	/* Lets try and provide basic diagnostics - cost is low */
+	gtc_ctrl = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTCR_OFFSET);
+	/* Did the bootloader fail to enable timer and OS guys are confused? */
+	if ((gtc_ctrl & K3_GTC_CNTCR_EN_MASK) == 0U) {
+		ERROR("GTC is disabled! Timekeeping broken. Fix Bootloader\n");
+	}
+	/*
+	 * If debug will not pause time, we will have issues like
+	 * drivers timing out while debugging, in cases of OS like Linux,
+	 * RCU stall errors, which can be hard to differentiate vs real issues.
+	 */
+	if ((gtc_ctrl & K3_GTC_CNTCR_HDBG_MASK) == 0U) {
+		WARN("GTC: Debug access doesn't stop time. Fix Bootloader\n");
+	}
+
+	gtc_freq = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTFID0_OFFSET);
+	/* Many older bootloaders may have missed programming FID0 register */
+	if (gtc_freq != 0U) {
+		return gtc_freq;
+	}
+
+	/*
+	 * We could have just warned about this, but this can have serious
+	 * hard to debug side effects if we are NOT sure what the actual
+	 * frequency is. Lets make sure people don't miss this.
+	 */
+	ERROR("GTC_CNTFID0 is 0! Assuming %d Hz. Fix Bootloader\n",
+	      SYS_COUNTER_FREQ_IN_TICKS);
+
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image
+ * for the security state specified. BL3-3 corresponds to the non-secure
+ * image type while BL3-2 corresponds to the secure image type. A NULL
+ * pointer is returned if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	assert(sec_state_is_valid(type));
+	next_image_info = (type == NON_SECURE) ? &bl33_image_ep_info :
+						 &bl32_image_ep_info;
+	/*
+	 * None of the images on the ARM development platforms can have 0x0
+	 * as the entrypoint
+	 */
+	if (next_image_info->pc)
+		return next_image_info;
+
+	NOTICE("Requested nonexistent image\n");
+	return NULL;
+}
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
deleted file mode 100644
index 4005102..0000000
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Texas Instruments K3 Secure Proxy Driver
- *   Based on Linux and U-Boot implementation
- *
- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef SEC_PROXY_H
-#define SEC_PROXY_H
-
-#include <stdint.h>
-
-/**
- * enum k3_sec_proxy_chan_id - Secure Proxy thread IDs
- *
- * These the available IDs used in k3_sec_proxy_{send,recv}()
- * There are two schemes we use:
- * * if K3_SEC_PROXY_LITE = 1, we just have two threads to talk
- * * if K3_SEC_PROXY_LITE = 0, we have the full fledged
- *   communication scheme available.
- */
-enum k3_sec_proxy_chan_id {
-#if !K3_SEC_PROXY_LITE
-	SP_NOTIFY = 0,
-	SP_RESPONSE,
-	SP_HIGH_PRIORITY,
-	SP_LOW_PRIORITY,
-	SP_NOTIFY_RESP,
-#else
-	SP_RESPONSE = 8,
-	/*
-	 * Note: TISCI documentation indicates "low priority", but in reality
-	 * with a single thread, there is no low or high priority.. This usage
-	 * is more appropriate for TF-A since we can reduce the churn as a
-	 * result.
-	 */
-	SP_HIGH_PRIORITY,
-#endif /* K3_SEC_PROXY_LITE */
-};
-
-/**
- * struct k3_sec_proxy_msg - Secure proxy message structure
- * @len: Length of data in the Buffer
- * @buf: Buffer pointer
- *
- * This is the structure for data used in k3_sec_proxy_{send,recv}()
- */
-struct k3_sec_proxy_msg {
-	size_t len;
-	uint8_t *buf;
-};
-
-/**
- * k3_sec_proxy_clear_rx_thread() - Clear a receive Secure Proxy thread
- * @id: Channel Identifier
- * @msg: Pointer to k3_sec_proxy_msg
- *
- * Return: 0 if all goes well, else appropriate error message
- */
-int k3_sec_proxy_clear_rx_thread(enum k3_sec_proxy_chan_id id);
-
-/**
- * k3_sec_proxy_send() - Send data over a Secure Proxy thread
- * @id: Channel Identifier
- * @msg: Pointer to k3_sec_proxy_msg
- *
- * Return: 0 if all goes well, else appropriate error message
- */
-int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_msg *msg);
-
-/**
- * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread
- * @id: Channel Identifier
- * @msg: Pointer to k3_sec_proxy_msg
- *
- * Return: 0 if all goes well, else appropriate error message
- */
-int k3_sec_proxy_recv(enum k3_sec_proxy_chan_id id, struct k3_sec_proxy_msg *msg);
-
-#endif /* SEC_PROXY_H */
diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
index 63fe020..1b93dc8 100644
--- a/plat/ti/k3/common/k3_bl31_setup.c
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -1,30 +1,16 @@
 /*
  * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/
+ * K3 SOC specific bl31_setup
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <assert.h>
-#include <string.h>
-
-#include <platform_def.h>
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <common/bl_common.h>
 #include <common/debug.h>
-#include <lib/mmio.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-
-#include <k3_console.h>
-#include <k3_gicv3.h>
 #include <ti_sci.h>
+#include <ti_sci_transport.h>
 
-#define ADDR_DOWN(_adr) (_adr & XLAT_ADDR_MASK(2U))
-#define SIZE_UP(_adr, _sz) (round_up((_adr + _sz), XLAT_BLOCK_SIZE(2U)) - ADDR_DOWN(_adr))
-
-#define K3_MAP_REGION_FLAT(_adr, _sz, _attr) \
-	MAP_REGION_FLAT(ADDR_DOWN(_adr), SIZE_UP(_adr, _sz), _attr)
+#include <plat_private.h>
 
 /* Table of regions to map using the MMU */
 const mmap_region_t plat_k3_mmap[] = {
@@ -37,98 +23,15 @@
 	{ /* sentinel */ }
 };
 
-/*
- * Placeholder variables for maintaining information about the next image(s)
- */
-static entry_point_info_t bl32_image_ep_info;
-static entry_point_info_t bl33_image_ep_info;
-
-/*******************************************************************************
- * Gets SPSR for BL33 entry
- ******************************************************************************/
-static uint32_t k3_get_spsr_for_bl33_entry(void)
-{
-	unsigned long el_status;
-	unsigned int mode;
-	uint32_t spsr;
-
-	/* Figure out what mode we enter the non-secure world in */
-	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
-	el_status &= ID_AA64PFR0_ELX_MASK;
-
-	mode = (el_status) ? MODE_EL2 : MODE_EL1;
-
-	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
-	return spsr;
-}
-
-/*******************************************************************************
- * Perform any BL3-1 early platform setup, such as console init and deciding on
- * memory layout.
- ******************************************************************************/
-void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
-				u_register_t arg2, u_register_t arg3)
-{
-	/* Initialize the console to provide early debug support */
-	k3_console_setup();
-
-#ifdef BL32_BASE
-	/* Populate entry point information for BL32 */
-	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
-	bl32_image_ep_info.pc = BL32_BASE;
-	bl32_image_ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
-					  DISABLE_ALL_EXCEPTIONS);
-	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
-#endif
-
-	/* Populate entry point information for BL33 */
-	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
-	bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
-	bl33_image_ep_info.spsr = k3_get_spsr_for_bl33_entry();
-	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
-
-#ifdef K3_HW_CONFIG_BASE
-	/*
-	 * According to the file ``Documentation/arm64/booting.txt`` of the
-	 * Linux kernel tree, Linux expects the physical address of the device
-	 * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
-	 * must be 0.
-	 */
-	bl33_image_ep_info.args.arg0 = (u_register_t)K3_HW_CONFIG_BASE;
-	bl33_image_ep_info.args.arg1 = 0U;
-	bl33_image_ep_info.args.arg2 = 0U;
-	bl33_image_ep_info.args.arg3 = 0U;
-#endif
-}
-
-void bl31_plat_arch_setup(void)
-{
-	const mmap_region_t bl_regions[] = {
-		MAP_REGION_FLAT(BL31_START,           BL31_SIZE,			          MT_MEMORY  | MT_RW | MT_SECURE),
-		MAP_REGION_FLAT(BL_CODE_BASE,         BL_CODE_END         - BL_CODE_BASE,         MT_CODE    | MT_RO | MT_SECURE),
-		MAP_REGION_FLAT(BL_RO_DATA_BASE,      BL_RO_DATA_END      - BL_RO_DATA_BASE,      MT_RO_DATA | MT_RO | MT_SECURE),
-#if USE_COHERENT_MEM
-		MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, MT_DEVICE  | MT_RW | MT_SECURE),
-#endif
-		{ /* sentinel */ }
-	};
-
-	setup_page_tables(bl_regions, plat_k3_mmap);
-	enable_mmu_el3(0);
-}
-
-void bl31_platform_setup(void)
+int ti_soc_init(void)
 {
 	struct ti_sci_msg_version version;
 	int ret;
 
-	k3_gic_driver_init(K3_GIC_BASE);
-	k3_gic_init();
-
 	ret = ti_sci_get_revision(&version);
 	if (ret) {
 		ERROR("Unable to communicate with the control firmware (%d)\n", ret);
-		return;
+		return ret;
 	}
 
 	INFO("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n",
@@ -157,70 +60,5 @@
 	} else {
 		NOTICE("Upgrade Firmwares for Power off functionality\n");
 	}
-}
-
-void platform_mem_init(void)
-{
-	/* Do nothing for now... */
-}
-
-unsigned int plat_get_syscnt_freq2(void)
-{
-	uint32_t gtc_freq;
-	uint32_t gtc_ctrl;
-
-	/* Lets try and provide basic diagnostics - cost is low */
-	gtc_ctrl = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTCR_OFFSET);
-	/* Did the bootloader fail to enable timer and OS guys are confused? */
-	if ((gtc_ctrl & K3_GTC_CNTCR_EN_MASK) == 0U) {
-		ERROR("GTC is disabled! Timekeeping broken. Fix Bootloader\n");
-	}
-	/*
-	 * If debug will not pause time, we will have issues like
-	 * drivers timing out while debugging, in cases of OS like Linux,
-	 * RCU stall errors, which can be hard to differentiate vs real issues.
-	 */
-	if ((gtc_ctrl & K3_GTC_CNTCR_HDBG_MASK) == 0U) {
-		WARN("GTC: Debug access doesn't stop time. Fix Bootloader\n");
-	}
-
-	gtc_freq = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTFID0_OFFSET);
-	/* Many older bootloaders may have missed programming FID0 register */
-	if (gtc_freq != 0U) {
-		return gtc_freq;
-	}
-
-	/*
-	 * We could have just warned about this, but this can have serious
-	 * hard to debug side effects if we are NOT sure what the actual
-	 * frequency is. Lets make sure people don't miss this.
-	 */
-	ERROR("GTC_CNTFID0 is 0! Assuming %d Hz. Fix Bootloader\n",
-	      SYS_COUNTER_FREQ_IN_TICKS);
-
-	return SYS_COUNTER_FREQ_IN_TICKS;
-}
-
-/*******************************************************************************
- * Return a pointer to the 'entry_point_info' structure of the next image
- * for the security state specified. BL3-3 corresponds to the non-secure
- * image type while BL3-2 corresponds to the secure image type. A NULL
- * pointer is returned if the image does not exist.
- ******************************************************************************/
-entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
-{
-	entry_point_info_t *next_image_info;
-
-	assert(sec_state_is_valid(type));
-	next_image_info = (type == NON_SECURE) ? &bl33_image_ep_info :
-						 &bl32_image_ep_info;
-	/*
-	 * None of the images on the ARM development platforms can have 0x0
-	 * as the entrypoint
-	 */
-	if (next_image_info->pc)
-		return next_image_info;
-
-	NOTICE("Requested nonexistent image\n");
-	return NULL;
+	return 0;
 }
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
index a2cc62d..db5e31d 100644
--- a/plat/ti/k3/include/platform_def.h
+++ b/plat/ti/k3/include/platform_def.h
@@ -7,174 +7,7 @@
 #ifndef PLATFORM_DEF_H
 #define PLATFORM_DEF_H
 
-#include <arch.h>
-#include <plat/common/common_def.h>
-
-#include <board_def.h>
-
-/*******************************************************************************
- * Generic platform constants
- ******************************************************************************/
-
-/* Size of cacheable stack */
-#if IMAGE_BL31
-#define PLATFORM_STACK_SIZE		0x800
-#else
-#define PLATFORM_STACK_SIZE		0x1000
-#endif
-
-#define PLATFORM_SYSTEM_COUNT		1
-#define PLATFORM_CORE_COUNT		(K3_CLUSTER0_CORE_COUNT + \
-					K3_CLUSTER1_CORE_COUNT + \
-					K3_CLUSTER2_CORE_COUNT + \
-					K3_CLUSTER3_CORE_COUNT)
-
-#define PLATFORM_CLUSTER_COUNT		((K3_CLUSTER0_CORE_COUNT != 0) + \
-					(K3_CLUSTER1_CORE_COUNT != 0) + \
-					(K3_CLUSTER2_CORE_COUNT != 0) + \
-					(K3_CLUSTER3_CORE_COUNT != 0))
-
-#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_SYSTEM_COUNT + \
-					PLATFORM_CLUSTER_COUNT + \
-					PLATFORM_CORE_COUNT)
-#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL2
-#define PLAT_MAX_OFF_STATE		U(2)
-#define PLAT_MAX_RET_STATE		U(1)
-
-/*******************************************************************************
- * Memory layout constants
- ******************************************************************************/
-
-/*
- * This RAM will be used for the bootloader including code, bss, and stacks.
- * It may need to be increased if BL31 grows in size.
- *
- * The link addresses are determined by BL31_BASE + offset.
- * When ENABLE_PIE is set, the TF images can be loaded anywhere, so
- * BL31_BASE is really arbitrary.
- *
- * When ENABLE_PIE is unset, BL31_BASE should be chosen so that
- * it matches to the physical address where BL31 is loaded, that is,
- * BL31_BASE should be the base address of the RAM region.
- *
- * Lets make things explicit by mapping BL31_BASE to 0x0 since ENABLE_PIE is
- * defined as default for our platform.
- */
-#define BL31_BASE	UL(0x00000000) /* PIE remapped on fly */
-#define BL31_SIZE	UL(0x00020000) /* 128k */
-#define BL31_LIMIT	(BL31_BASE + BL31_SIZE)
-
-/*
- * Defines the maximum number of translation tables that are allocated by the
- * translation table library code. To minimize the amount of runtime memory
- * used, choose the smallest value needed to map the required virtual addresses
- * for each BL stage.
- */
-#define MAX_XLAT_TABLES		4
-
-/*
- * Defines the maximum number of regions that are allocated by the translation
- * table library code. A region consists of physical base address, virtual base
- * address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as
- * defined in the `mmap_region_t` structure. The platform defines the regions
- * that should be mapped. Then, the translation table library will create the
- * corresponding tables and descriptors at runtime. To minimize the amount of
- * runtime memory used, choose the smallest value needed to register the
- * required regions for each BL stage.
- */
-#if USE_COHERENT_MEM
-#define MAX_MMAP_REGIONS	11
-#else
-#define MAX_MMAP_REGIONS	10
-#endif
-
-/*
- * Defines the total size of the address space in bytes. For example, for a 32
- * bit address space, this value should be `(1ull << 32)`.
- */
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 32)
-
-/*
- * Some data must be aligned on the biggest cache line size in the platform.
- * This is known only to the platform as it might have a combination of
- * integrated and external caches.
- */
-#define CACHE_WRITEBACK_SHIFT		6
-#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
-
-/* Platform default console definitions */
-#ifndef K3_USART_BASE
-#define K3_USART_BASE			(0x02800000 + 0x10000 * K3_USART)
-#endif
-
-/* USART has a default size for address space */
-#define K3_USART_SIZE 0x1000
-
-#ifndef K3_USART_CLK_SPEED
-#define K3_USART_CLK_SPEED 48000000
-#endif
-
-/* Crash console defaults */
-#define CRASH_CONSOLE_BASE K3_USART_BASE
-#define CRASH_CONSOLE_CLK K3_USART_CLK_SPEED
-#define CRASH_CONSOLE_BAUD_RATE K3_USART_BAUD
-
-/* Timer frequency */
-#ifndef SYS_COUNTER_FREQ_IN_TICKS
-#define SYS_COUNTER_FREQ_IN_TICKS 200000000
-#endif
-
-/* Interrupt numbers */
-#define ARM_IRQ_SEC_PHY_TIMER		29
-
-#define ARM_IRQ_SEC_SGI_0		8
-#define ARM_IRQ_SEC_SGI_1		9
-#define ARM_IRQ_SEC_SGI_2		10
-#define ARM_IRQ_SEC_SGI_3		11
-#define ARM_IRQ_SEC_SGI_4		12
-#define ARM_IRQ_SEC_SGI_5		13
-#define ARM_IRQ_SEC_SGI_6		14
-#define ARM_IRQ_SEC_SGI_7		15
-
-/*
- * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
- * terminology. On a GICv2 system or mode, the lists will be merged and treated
- * as Group 0 interrupts.
- */
-#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
-	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_LEVEL), \
-	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_EDGE), \
-	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_EDGE), \
-	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_EDGE), \
-	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_EDGE), \
-	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_EDGE), \
-	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_EDGE)
-
-#define PLAT_ARM_G0_IRQ_PROPS(grp) \
-	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_EDGE), \
-	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
-			GIC_INTR_CFG_EDGE)
-
-
-#define K3_GTC_BASE		0x00A90000
-/* We just need 20 byte offset, but simpler to just remap the 64K page in */
-#define K3_GTC_SIZE		0x10000
-#define K3_GTC_CNTCR_OFFSET	0x00
-#define K3_GTC_CNTCR_EN_MASK	0x01
-#define K3_GTC_CNTCR_HDBG_MASK	0x02
-#define K3_GTC_CNTFID0_OFFSET	0x20
-
-#define K3_GIC_BASE	0x01800000
-#define K3_GIC_SIZE	0x200000
+#include <ti_platform_defs.h>
 
 #if !K3_SEC_PROXY_LITE
 #define SEC_PROXY_DATA_BASE	0x32C00000
@@ -195,7 +28,4 @@
 #define SEC_PROXY_TIMEOUT_US		1000000
 #define SEC_PROXY_MAX_MESSAGE_SIZE	56
 
-#define TI_SCI_HOST_ID			10
-#define TI_SCI_MAX_MESSAGE_SIZE		52
-
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/ti/k3/platform.mk b/plat/ti/k3/platform.mk
index bce9ef1..347a088 100644
--- a/plat/ti/k3/platform.mk
+++ b/plat/ti/k3/platform.mk
@@ -7,7 +7,7 @@
 PLAT_PATH	:=	plat/ti/k3
 TARGET_BOARD	?=	generic
 
-include ${PLAT_PATH}/common/plat_common.mk
+include plat/ti/common/plat_common.mk
 include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk
 
 BL32_BASE ?= 0x9e800000
@@ -19,7 +19,20 @@
 K3_HW_CONFIG_BASE ?= 0x82000000
 $(eval $(call add_define,K3_HW_CONFIG_BASE))
 
-PLAT_INCLUDES += -Iplat/ti/k3/board/${TARGET_BOARD}/include
+PLAT_INCLUDES += -Iplat/ti/k3/board/${TARGET_BOARD}/include	\
+		 -Iplat/ti/common/include			\
 
 # modify BUILD_PLAT to point to board specific build directory
 BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE}
+
+K3_PSCI_SOURCES		+=	\
+				${PLAT_PATH}/common/k3_psci.c		\
+
+K3_TI_SCI_TRANSPORT	:=	\
+				drivers/ti/ipc/sec_proxy.c		\
+
+BL31_SOURCES		+=	\
+				${PLAT_PATH}/common/k3_bl31_setup.c	\
+				${PLAT_PATH}/common/k3_topology.c	\
+				${K3_TI_SCI_TRANSPORT}			\
+				${K3_PSCI_SOURCES}			\
diff --git a/plat/ti/k3low/board/am62lx/board.mk b/plat/ti/k3low/board/am62lx/board.mk
new file mode 100644
index 0000000..26e58c6
--- /dev/null
+++ b/plat/ti/k3low/board/am62lx/board.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2024-2025, Texas Instruments Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# We dont have system level coherency capability
+USE_COHERENT_MEM	:=	0
+
+BL32_BASE ?= 0x80200000
+$(eval $(call add_define,BL32_BASE))
+
+PRELOADED_BL33_BASE ?= 0x82000000
+$(eval $(call add_define,PRELOADED_BL33_BASE))
+
+K3_HW_CONFIG_BASE ?= 0x88000000
+$(eval $(call add_define,K3_HW_CONFIG_BASE))
diff --git a/plat/ti/k3low/board/am62lx/include/board_def.h b/plat/ti/k3low/board/am62lx/include/board_def.h
new file mode 100644
index 0000000..ea46423
--- /dev/null
+++ b/plat/ti/k3low/board/am62lx/include/board_def.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024-2025 Texas Instruments Incorporated - https://www.ti.com
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_DEF_H
+#define BOARD_DEF_H
+
+#include <lib/utils_def.h>
+
+/* The ports must be in order and contiguous */
+#define K3_CLUSTER0_CORE_COUNT		U(2)
+#define K3_CLUSTER1_CORE_COUNT		U(0)
+#define K3_CLUSTER2_CORE_COUNT		U(0)
+#define K3_CLUSTER3_CORE_COUNT		U(0)
+
+#define PLAT_PROC_START_ID		U(32)
+#define PLAT_PROC_DEVICE_START_ID	U(135)
+#define PLAT_CLUSTER_DEVICE_START_ID	U(134)
+#define PLAT_BOARD_DEVICE_ID		U(157)
+
+/* Pre-decided SRAM Addresses for sending and receiving messages */
+#define MAILBOX_TX_START_REGION		UL(0x70814000)
+#define MAILBOX_RX_START_REGION		UL(0x70815000)
+/*
+ * Pre-calculated MAX size of a message
+ * sec_hdr + (type/host/seq + flags) + payload
+ * 4 + 16 + 36
+ */
+#define MAILBOX_MAX_MESSAGE_SIZE	U(56)
+
+#endif /* BOARD_DEF_H */
diff --git a/plat/ti/k3low/common/am62l_bl31_setup.c b/plat/ti/k3low/common/am62l_bl31_setup.c
new file mode 100644
index 0000000..22255f4
--- /dev/null
+++ b/plat/ti/k3low/common/am62l_bl31_setup.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2025 Texas Instruments Incorporated - http://www.ti.com/
+ * K3 SOC specific bl31_setup
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <ti_sci.h>
+#include <ti_sci_transport.h>
+
+#include <plat_private.h>
+
+/* Table of regions to map using the MMU */
+const mmap_region_t plat_k3_mmap[] = {
+	{ /* sentinel */ }
+};
+
+int ti_soc_init(void)
+{
+	/* nothing to do right now */
+	return 0;
+}
diff --git a/plat/ti/k3low/common/am62l_psci.c b/plat/ti/k3low/common/am62l_psci.c
new file mode 100644
index 0000000..761d30f
--- /dev/null
+++ b/plat/ti/k3low/common/am62l_psci.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2025, Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/el3_runtime/cpu_data.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+#include <ti_sci.h>
+#include <ti_sci_protocol.h>
+
+#include <k3_gicv3.h>
+#include <platform_def.h>
+
+uintptr_t am62l_sec_entrypoint;
+uintptr_t am62l_sec_entrypoint_glob;
+void  __aligned(16) jump_to_atf_func(void *unused);
+
+static int am62l_pwr_domain_on(u_register_t mpidr)
+{
+	int32_t core, ret;
+	uint8_t proc_id;
+
+	core = plat_core_pos_by_mpidr(mpidr);
+	if (core < 0) {
+		ERROR("Could not get target core id: %d\n", core);
+		ret = PSCI_E_INTERN_FAIL;
+	}
+
+	proc_id = (uint8_t)(PLAT_PROC_START_ID + (uint32_t)core);
+
+	ret = ti_sci_proc_request(proc_id);
+	if (ret != 0) {
+		ERROR("Request for processor ID 0x%x failed: %d\n",
+				proc_id, ret);
+		ret = PSCI_E_INTERN_FAIL;
+	}
+
+	if (ret != PSCI_E_INTERN_FAIL) {
+		ret = ti_sci_proc_set_boot_cfg(proc_id, am62l_sec_entrypoint, 0, 0);
+		if (ret != 0) {
+			ERROR("Request to set core boot address failed: %d\n", ret);
+			ret = PSCI_E_INTERN_FAIL;
+		}
+	}
+
+	if (ret != PSCI_E_INTERN_FAIL) {
+		/* sanity check these are off before starting a core */
+		ret = ti_sci_proc_set_boot_ctrl(proc_id,
+				0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ |
+				PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS |
+				PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM);
+		if (ret != 0) {
+			ERROR("Request to clear boot config failed: %d\n", ret);
+			ret = PSCI_E_INTERN_FAIL;
+		}
+	}
+
+	if (ret != PSCI_E_INTERN_FAIL) {
+		/*
+		 * TODO: Add the actual PM operation call
+		 * to turn on the core here
+		 */
+		ret = PSCI_E_SUCCESS;
+	}
+
+	return ret;
+}
+
+static void am62l_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	/* At very least the local core should be powering down */
+	assert(((target_state)->pwr_domain_state[MPIDR_AFFLVL0]) == PLAT_MAX_OFF_STATE);
+
+	/* Prevent interrupts from spuriously waking up this cpu */
+	k3_gic_cpuif_disable();
+
+}
+
+static void am62l_pwr_down_domain(const psci_power_state_t *target_state)
+{
+	/* TODO: Add the actual pm operation call to turn off the core */
+}
+
+void am62l_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	k3_gic_pcpu_init();
+	k3_gic_cpuif_enable();
+}
+
+static void am62l_system_reset(void)
+{
+	mmio_write_32(WKUP_CTRL_MMR0_DEVICE_MANAGEMENT_BASE + WKUP_CTRL_MMR0_DEVICE_RESET_OFFSET,
+		      0x6);
+
+	/* Wait for reset to complete for 500ms before printing error */
+	mdelay(500);
+
+	/* Ideally we should not reach here */
+	ERROR("%s: Failed to reset device\n", __func__);
+}
+
+static plat_psci_ops_t am62l_plat_psci_ops = {
+	.pwr_domain_on = am62l_pwr_domain_on,
+	.pwr_domain_off = am62l_pwr_domain_off,
+	.pwr_domain_pwr_down = am62l_pwr_down_domain,
+	.pwr_domain_on_finish = am62l_pwr_domain_on_finish,
+	.system_reset = am62l_system_reset,
+};
+
+void  __aligned(16) jump_to_atf_func(void *unused)
+{
+	/*
+	 * MISRA Deviation observed:
+	 * Rule 11.1 (MISRA C:2012) Prohibits conversion performed between a
+	 * pointer to a function and another incompatible type.
+	 * This conversion is required for handling secure boot entry points.
+	 * The conversion is safe as the address is verified before execution.
+	 */
+	void (*bl31_loc_warm_entry)(void) = (void *)am62l_sec_entrypoint_glob;
+
+	bl31_loc_warm_entry();
+}
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	am62l_sec_entrypoint_glob = sec_entrypoint;
+	/* Note that boot vector reg in sec mmr requires 16B aligned start address */
+	am62l_sec_entrypoint = (uint64_t)(void *)&jump_to_atf_func;
+	VERBOSE("am62l_sec_entrypoint = 0x%lx\n", am62l_sec_entrypoint);
+
+	*psci_ops = &am62l_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/ti/k3low/common/am62l_topology.c b/plat/ti/k3low/common/am62l_topology.c
new file mode 100644
index 0000000..15f5118
--- /dev/null
+++ b/plat/ti/k3low/common/am62l_topology.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2025, Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/psci/psci.h>
+
+#include <platform_def.h>
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+	PLATFORM_SYSTEM_COUNT,
+	PLATFORM_CLUSTER_COUNT,
+	K3_CLUSTER0_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+	if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+	    MPIDR_AFFLVL2_VAL(mpidr) > 0) {
+		return -1;
+	}
+
+	return core;
+}
diff --git a/plat/ti/k3low/include/platform_def.h b/plat/ti/k3low/include/platform_def.h
new file mode 100644
index 0000000..37f984c
--- /dev/null
+++ b/plat/ti/k3low/include/platform_def.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2025, Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <ti_platform_defs.h>
+
+#define TI_MAILBOX_TX_BASE		UL(0x44240000) /* TFA sending IPC messages to TIFS */
+#define TI_MAILBOX_RX_BASE		UL(0x44250000) /* TIFS sending IPC messages to A53 */
+
+#define WKUP_CTRL_MMR0_DEVICE_MANAGEMENT_BASE	(0x43050000UL)
+#define WKUP_CTRL_MMR0_DEVICE_RESET_OFFSET	(0x4000UL)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/ti/k3low/platform.mk b/plat/ti/k3low/platform.mk
new file mode 100644
index 0000000..5bc47ff
--- /dev/null
+++ b/plat/ti/k3low/platform.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2025, Texas Instruments Incorporated - https://www.ti.com/
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_PATH	:=	plat/ti/k3low
+TARGET_BOARD	?=	am62lx
+
+include plat/ti/common/plat_common.mk
+include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk
+
+PLAT_INCLUDES +=	\
+			-I${PLAT_PATH}/board/${TARGET_BOARD}/include	\
+			-I${PLAT_PATH}					\
+			-Iplat/ti/common/include			\
+
+K3_PSCI_SOURCES		+=	\
+				${PLAT_PATH}/common/am62l_psci.c	\
+
+K3_TI_SCI_TRANSPORT	:=	\
+				drivers/ti/ipc/mailbox.c		\
+
+BL31_SOURCES		+=	\
+				drivers/delay_timer/delay_timer.c		\
+				${K3_PSCI_SOURCES}				\
+				${K3_TI_SCI_TRANSPORT}				\
+				${PLAT_PATH}/common/am62l_bl31_setup.c		\
+				${PLAT_PATH}/common/am62l_topology.c		\