Merge pull request #1403 from glneo/for-upstream-k3

TI K3 platform support
diff --git a/docs/plat/ti-k3.rst b/docs/plat/ti-k3.rst
new file mode 100644
index 0000000..6515c64
--- /dev/null
+++ b/docs/plat/ti-k3.rst
@@ -0,0 +1,55 @@
+Trusted Firmware-A for Texas Instruments K3 SoCs
+================================================
+
+Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Texas Instruments K3 SoCs.
+
+Boot Flow
+---------
+
+R5(U-Boot) --> TF-A BL31 --> BL32(OP-TEE) --> TF-A BL31 --> BL33(U-Boot) --> Linux
+                                                       \
+                                                Optional direct to Linux boot
+                                                         \
+                                                           --> BL33(Linux)
+
+Texas Instruments K3 SoCs contain an R5 processor used as the boot master, it
+loads the needed images for A53 startup, because of this we do not need BL1 or
+BL2 TF-A stages.
+
+Build Instructions
+------------------
+
+https://github.com/ARM-software/arm-trusted-firmware.git
+
+TF-A:
+
+.. code:: shell
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=k3 SPD=opteed all
+
+OP-TEE:
+
+.. code:: shell
+
+    make ARCH=arm CROSS_COMPILE64=aarch64-linux-gnu- PLATFORM=k3 CFG_ARM64_core=y all
+
+R5 U-Boot:
+
+.. code:: shell
+
+    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- am65x_evm_r5_defconfig
+    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- SYSFW=<path to SYSFW>
+
+A53 U-Boot:
+
+.. code:: shell
+
+    make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- am65x_evm_a53_defconfig
+    make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- ATF=<path> TEE=<path>
+
+Deploy Images
+-------------
+
+.. code:: shell
+
+    cp tiboot3.bin tispl.bin u-boot.img /sdcard/boot/
diff --git a/maintainers.rst b/maintainers.rst
index 81c30c0..96ff0e0 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -132,6 +132,16 @@
 
 -  plat/rockchip/\*
 
+Texas Instruments platform sub-maintainer
+-----------------------------------------
+
+Andrew F. Davis (afd@ti.com, `glneo`_)
+
+Files:
+
+- docs/plat/ti-k3.rst
+- plat/ti/\*
+
 UniPhier platform sub-maintainer
 --------------------------------
 
@@ -167,6 +177,7 @@
 .. _masahir0y: https://github.com/masahir0y
 .. _mtk09422: https://github.com/mtk09422
 .. _TonyXie06: https://github.com/TonyXie06
+.. _glneo: https://github.com/glneo
 .. _sivadur: https://github.com/sivadur
 .. _rockchip-linux: https://github.com/rockchip-linux
 .. _etienne-lms: https://github.com/etienne-lms
diff --git a/plat/ti/k3/board/generic/board.mk b/plat/ti/k3/board/generic/board.mk
new file mode 100644
index 0000000..a342214
--- /dev/null
+++ b/plat/ti/k3/board/generic/board.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_BASE ?= 0x9e800000
+$(eval $(call add_define,BL32_BASE))
+
+PRELOADED_BL33_BASE ?= 0x80080000
+$(eval $(call add_define,PRELOADED_BL33_BASE))
+
+K3_HW_CONFIG_BASE ?= 0x82000000
+$(eval $(call add_define,K3_HW_CONFIG_BASE))
+
+PLAT_INCLUDES		+=	\
+				-Iplat/ti/k3/board/generic/include	\
diff --git a/plat/ti/k3/board/generic/include/board_def.h b/plat/ti/k3/board/generic/include/board_def.h
new file mode 100644
index 0000000..4c59c75
--- /dev/null
+++ b/plat/ti/k3/board/generic/include/board_def.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __BOARD_DEF_H__
+#define __BOARD_DEF_H__
+
+/* The ports must be in order and contiguous */
+#define K3_CLUSTER0_CORE_COUNT		2
+#define K3_CLUSTER0_MSMC_PORT		0
+
+#define K3_CLUSTER1_CORE_COUNT		2
+#define K3_CLUSTER1_MSMC_PORT		1
+
+#define K3_CLUSTER2_CORE_COUNT		2
+#define K3_CLUSTER2_MSMC_PORT		2
+
+#define K3_CLUSTER3_CORE_COUNT		2
+#define K3_CLUSTER3_MSMC_PORT		3
+
+/*
+ * This RAM will be used for the bootloader including code, bss, and stacks.
+ * It may need to be increased if BL31 grows in size.
+ */
+#define SEC_SRAM_BASE			0x70000000 /* Base of MSMC SRAM */
+#define SEC_SRAM_SIZE			0x00020000 /* 128k */
+
+#define PLAT_MAX_OFF_STATE		2
+#define PLAT_MAX_RET_STATE		1
+
+#endif /* __BOARD_DEF_H__ */
diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
new file mode 100644
index 0000000..ca7d214
--- /dev/null
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <k3_console.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+#include <k3_gicv3.h>
+#include <string.h>
+
+/* Table of regions to map using the MMU */
+const mmap_region_t plat_arm_mmap[] = {
+	MAP_REGION_FLAT(SHARED_RAM_BASE, SHARED_RAM_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_USART_BASE_ADDRESS, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_GICD_BASE, K3_GICD_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_GICR_BASE, K3_GICR_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	{ /* 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_setup(bl31_params_t *from_bl2,
+			       void *plat_params_from_bl2)
+{
+	/* There are no parameters from BL2 if BL31 is a reset vector */
+	assert(from_bl2 == NULL);
+	assert(plat_params_from_bl2 == NULL);
+
+	bl31_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_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	bl31_early_platform_setup((void *)arg0, (void *)arg1);
+}
+
+void bl31_plat_arch_setup(void)
+{
+	arm_setup_page_tables(BL31_BASE,
+			      BL31_END - BL31_BASE,
+			      BL_CODE_BASE,
+			      BL_CODE_END,
+			      BL_RO_DATA_BASE,
+			      BL_RO_DATA_END);
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	k3_gic_driver_init(K3_GICD_BASE, K3_GICR_BASE);
+	k3_gic_init();
+}
+
+void platform_mem_init(void)
+{
+	/* Do nothing for now... */
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+/*
+ * Empty function to prevent the console from being uninitialized after BL33 is
+ * started and allow us to see messages from BL31.
+ */
+void bl31_plat_runtime_setup(void)
+{
+}
+
+/*******************************************************************************
+ * 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/k3_console.c b/plat/ti/k3/common/k3_console.c
new file mode 100644
index 0000000..ff3ca61
--- /dev/null
+++ b/plat/ti/k3/common/k3_console.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <console.h>
+#include <k3_console.h>
+#include <platform_def.h>
+#include <uart_16550.h>
+
+void bl31_console_setup(void)
+{
+	static console_16550_t console;
+
+	/* Initialize the console to provide early debug support */
+	console_16550_register(K3_USART_BASE_ADDRESS, K3_USART_CLK_SPEED,
+			       K3_USART_BAUD, &console);
+}
diff --git a/plat/ti/k3/common/k3_gicv3.c b/plat/ti/k3/common/k3_gicv3.c
new file mode 100644
index 0000000..3253130
--- /dev/null
+++ b/plat/ti/k3/common/k3_gicv3.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <gicv3.h>
+#include <interrupt_props.h>
+#include <k3_gicv3.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <utils.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t k3_interrupt_props[] = {
+	PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
+	PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+static unsigned int k3_mpidr_to_core_pos(unsigned long mpidr)
+{
+	return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+gicv3_driver_data_t k3_gic_data = {
+	.rdistif_num = PLATFORM_CORE_COUNT,
+	.rdistif_base_addrs = rdistif_base_addrs,
+	.interrupt_props = k3_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(k3_interrupt_props),
+	.mpidr_to_core_pos = k3_mpidr_to_core_pos,
+};
+
+void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base)
+{
+	/*
+	 * The GICv3 driver is initialized in EL3 and does not need
+	 * to be initialized again in SEL1. This is because the S-EL1
+	 * can use GIC system registers to manage interrupts and does
+	 * not need GIC interface base addresses to be configured.
+	 */
+	k3_gic_data.gicd_base = gicd_base;
+	k3_gic_data.gicr_base = gicr_base;
+	gicv3_driver_init(&k3_gic_data);
+}
+
+void k3_gic_init(void)
+{
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void k3_gic_cpuif_enable(void)
+{
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void k3_gic_cpuif_disable(void)
+{
+	gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void k3_gic_pcpu_init(void)
+{
+	gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/ti/k3/common/k3_helpers.S b/plat/ti/k3/common/k3_helpers.S
new file mode 100644
index 0000000..c95e9c3
--- /dev/null
+++ b/plat/ti/k3/common/k3_helpers.S
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+#define K3_BOOT_REASON_COLD_RESET 0x1
+
+	/* ------------------------------------------------------------------
+	 *  uintptr_t plat_get_my_entrypoint(void)
+	 * ------------------------------------------------------------------
+	 *
+	 * This function is called with the called with the MMU and caches
+	 * disabled (SCTLR_EL3.M = 0 and SCTLR_EL3.C = 0). The function is
+	 * responsible for distinguishing between a warm and cold reset for the
+	 * current CPU using platform-specific means. If it's a warm reset,
+	 * then it returns the warm reset entrypoint point provided to
+	 * plat_setup_psci_ops() during BL31 initialization. If it's a cold
+	 * reset then this function must return zero.
+	 *
+	 * This function does not follow the Procedure Call Standard used by
+	 * the Application Binary Interface for the ARM 64-bit architecture.
+	 * The caller should not assume that callee saved registers are
+	 * preserved across a call to this function.
+	 */
+	.globl	plat_get_my_entrypoint
+func plat_get_my_entrypoint
+	ldr x0, k3_boot_reason_data_store
+	cmp  x0, #K3_BOOT_REASON_COLD_RESET
+
+	/* We ONLY support cold boot at this point */
+	bne plat_unsupported_boot
+	mov	x0, #0
+	ret
+
+	/*
+	 * We self manage our boot reason.
+	 * At load time, we have just a default reason - which is cold reset
+	 */
+k3_boot_reason_data_store:
+	.word	K3_BOOT_REASON_COLD_RESET
+
+plat_unsupported_boot:
+	b plat_unsupported_boot
+
+endfunc plat_get_my_entrypoint
+
+	/* ------------------------------------------------------------------
+	 * unsigned int plat_my_core_pos(void)
+	 * ------------------------------------------------------------------
+	 *
+	 * This function returns the index of the calling CPU which is used as a
+	 * CPU-specific linear index into blocks of memory (for example while
+	 * allocating per-CPU stacks). This function will be invoked very early
+	 * in the initialization sequence which mandates that this function
+	 * should be implemented in assembly and should not rely on the
+	 * avalability of a C runtime environment. This function can clobber x0
+	 * - x8 and must preserve x9 - x29.
+	 *
+	 * This function plays a crucial role in the power domain topology
+	 * framework in PSCI and details of this can be found in Power Domain
+	 * Topology Design.
+	 */
+	.globl plat_my_core_pos
+func plat_my_core_pos
+	mrs	x0, MPIDR_EL1
+
+	and	x1, x0, #MPIDR_CLUSTER_MASK
+	lsr	x1, x1, #MPIDR_AFF1_SHIFT
+	and	x0, x0, #MPIDR_CPU_MASK
+
+#if K3_CLUSTER1_MSMC_PORT != UNUSED
+	cmp	x1, #K3_CLUSTER0_MSMC_PORT
+	b.eq out
+	add	x0, x0, #K3_CLUSTER0_CORE_COUNT
+#if K3_CLUSTER2_MSMC_PORT != UNUSED
+	cmp	x1, #K3_CLUSTER1_MSMC_PORT
+	b.eq out
+	add	x0, x0, #K3_CLUSTER1_CORE_COUNT
+#if K3_CLUSTER3_MSMC_PORT != UNUSED
+	cmp	x1, #K3_CLUSTER2_MSMC_PORT
+	b.eq out
+	add	x0, x0, #K3_CLUSTER2_CORE_COUNT
+#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
+#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
+#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
+
+out:
+	ret
+endfunc plat_my_core_pos
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0 - x4
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, CRASH_CONSOLE_BASE
+	mov_imm	x1, CRASH_CONSOLE_CLK
+	mov_imm	x2, CRASH_CONSOLE_BAUD_RATE
+	mov w3, #0x0
+	b	console_core_init
+
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(void)
+	 * Function to print a character on the crash
+	 * console without a C Runtime.
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	mov_imm	x1, CRASH_CONSOLE_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c
new file mode 100644
index 0000000..91602c8
--- /dev/null
+++ b/plat/ti/k3/common/k3_psci.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <k3_gicv3.h>
+#include <psci.h>
+#include <stdbool.h>
+
+#define STUB() ERROR("stub %s called\n", __func__)
+
+uintptr_t k3_sec_entrypoint;
+
+static void k3_cpu_standby(plat_local_state_t cpu_state)
+{
+	/*
+	 * Enter standby state
+	 * dsb is good practice before using wfi to enter low power states
+	 */
+	dsb();
+	wfi();
+}
+
+static int k3_pwr_domain_on(u_register_t mpidr)
+{
+	sev();
+
+	/* TODO: Indicate to System firmware about powering up */
+
+	return PSCI_E_SUCCESS;
+}
+
+void k3_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	/* Prevent interrupts from spuriously waking up this cpu */
+	k3_gic_cpuif_disable();
+
+	/* TODO: Indicate to System firmware about powering down */
+}
+
+void k3_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	/* TODO: Indicate to System firmware about completion */
+
+	k3_gic_pcpu_init();
+	k3_gic_cpuif_enable();
+}
+
+static void __dead2 k3_system_reset(void)
+{
+	/* TODO: Indicate to System firmware about system reset */
+	STUB();
+
+	while (true)
+		wfi();
+}
+
+static int k3_validate_power_state(unsigned int power_state,
+				   psci_power_state_t *req_state)
+{
+	/* TODO: perform the proper validation */
+
+	return PSCI_E_SUCCESS;
+}
+
+static int k3_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+	/* TODO: perform the proper validation */
+
+	return PSCI_E_SUCCESS;
+}
+
+static const plat_psci_ops_t k3_plat_psci_ops = {
+	.cpu_standby = k3_cpu_standby,
+	.pwr_domain_on = k3_pwr_domain_on,
+	.pwr_domain_off = k3_pwr_domain_off,
+	.pwr_domain_on_finish = k3_pwr_domain_on_finish,
+	.system_reset = k3_system_reset,
+	.validate_power_state = k3_validate_power_state,
+	.validate_ns_entrypoint = k3_validate_ns_entrypoint
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	k3_sec_entrypoint = sec_entrypoint;
+
+	*psci_ops = &k3_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/ti/k3/common/k3_topology.c b/plat/ti/k3/common/k3_topology.c
new file mode 100644
index 0000000..a77c8f3
--- /dev/null
+++ b/plat/ti/k3/common/k3_topology.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+#include <psci.h>
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+	PLATFORM_CLUSTER_COUNT,
+	K3_CLUSTER0_CORE_COUNT,
+#if K3_CLUSTER1_MSMC_PORT != UNUSED
+	K3_CLUSTER1_CORE_COUNT,
+#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
+#if K3_CLUSTER2_MSMC_PORT != UNUSED
+	K3_CLUSTER2_CORE_COUNT,
+#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
+#if K3_CLUSTER3_MSMC_PORT != UNUSED
+	K3_CLUSTER3_CORE_COUNT,
+#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
+};
+
+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 cpu_id;
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+
+	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+		return -1;
+
+	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	switch (MPIDR_AFFLVL1_VAL(mpidr)) {
+	case K3_CLUSTER0_MSMC_PORT:
+		if (cpu_id < K3_CLUSTER0_CORE_COUNT)
+			return cpu_id;
+		return -1;
+#if K3_CLUSTER1_MSMC_PORT != UNUSED
+	case K3_CLUSTER1_MSMC_PORT:
+		if (cpu_id < K3_CLUSTER1_CORE_COUNT)
+			return K3_CLUSTER0_CORE_COUNT + cpu_id;
+		return -1;
+#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
+#if K3_CLUSTER2_MSMC_PORT != UNUSED
+	case K3_CLUSTER2_MSMC_PORT:
+		if (cpu_id < K3_CLUSTER2_CORE_COUNT)
+			return K3_CLUSTER0_CORE_COUNT +
+			       K3_CLUSTER1_CORE_COUNT + cpu_id;
+		return -1;
+#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
+#if K3_CLUSTER3_MSMC_PORT != UNUSED
+	case K3_CLUSTER3_MSMC_PORT:
+		if (cpu_id < K3_CLUSTER3_CORE_COUNT)
+			return K3_CLUSTER0_CORE_COUNT +
+			       K3_CLUSTER1_CORE_COUNT +
+			       K3_CLUSTER2_CORE_COUNT + cpu_id;
+		return -1;
+#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
+	default:
+		return -1;
+	}
+}
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
new file mode 100644
index 0000000..bf2a73f
--- /dev/null
+++ b/plat/ti/k3/common/plat_common.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# We don't use BL1 or BL2, so BL31 is the first image to execute
+RESET_TO_BL31		:=	1
+# Only one core starts up at first
+COLD_BOOT_SINGLE_CPU	:=	1
+# We can choose where a core starts executing
+PROGRAMMABLE_RESET_ADDRESS:=	1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY	:=	1
+USE_COHERENT_MEM	:=	0
+
+ERROR_DEPRECATED	:=	1
+ENABLE_PLAT_COMPAT	:=	0
+
+# A53 erratum for SoC. (enable them all)
+ERRATA_A53_826319	:=	1
+ERRATA_A53_835769	:=	1
+ERRATA_A53_836870	:=	1
+ERRATA_A53_843419	:=	1
+ERRATA_A53_855873	:=	1
+
+MULTI_CONSOLE_API	:=	1
+TI_16550_MDR_QUIRK	:=	1
+$(eval $(call add_define,TI_16550_MDR_QUIRK))
+
+# Libraries
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES		+=	\
+				-I${PLAT_PATH}/include			\
+				-Iinclude/plat/arm/common/		\
+				-Iinclude/plat/arm/common/aarch64/	\
+
+K3_CONSOLE_SOURCES	+=	\
+				drivers/console/aarch64/console.S	\
+				drivers/ti/uart/aarch64/16550_console.S	\
+				${PLAT_PATH}/common/k3_console.c	\
+
+K3_GIC_SOURCES		+=	\
+				drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v3/gicv3_main.c		\
+				drivers/arm/gic/v3/gicv3_helpers.c	\
+				plat/common/plat_gicv3.c		\
+				${PLAT_PATH}/common/k3_gicv3.c		\
+
+K3_PSCI_SOURCES		+=	\
+				plat/common/plat_psci_common.c		\
+				${PLAT_PATH}/common/k3_psci.c		\
+
+PLAT_BL_COMMON_SOURCES	+=	\
+				plat/arm/common/arm_common.c		\
+				lib/cpus/aarch64/cortex_a53.S		\
+				${XLAT_TABLES_LIB_SRCS}			\
+				${K3_CONSOLE_SOURCES}			\
+
+BL31_SOURCES		+=	\
+				${PLAT_PATH}/common/k3_bl31_setup.c	\
+				${PLAT_PATH}/common/k3_helpers.S	\
+				${PLAT_PATH}/common/k3_topology.c	\
+				${K3_GIC_SOURCES}			\
+				${K3_PSCI_SOURCES}			\
diff --git a/plat/ti/k3/include/k3_console.h b/plat/ti/k3/include/k3_console.h
new file mode 100644
index 0000000..5b01a31
--- /dev/null
+++ b/plat/ti/k3/include/k3_console.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __K3_CONSOLE_H__
+#define __K3_CONSOLE_H__
+
+void bl31_console_setup(void);
+
+#endif /* __K3_CONSOLE_H__ */
diff --git a/plat/ti/k3/include/k3_gicv3.h b/plat/ti/k3/include/k3_gicv3.h
new file mode 100644
index 0000000..bbf5bf9
--- /dev/null
+++ b/plat/ti/k3/include/k3_gicv3.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __K3_GICV3_H__
+#define __K3_GICV3_H__
+
+void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base);
+void k3_gic_init(void);
+void k3_gic_cpuif_enable(void);
+void k3_gic_cpuif_disable(void);
+void k3_gic_pcpu_init(void);
+
+#endif /* __K3_GICV3_H__ */
diff --git a/plat/ti/k3/include/plat_macros.S b/plat/ti/k3/include/plat_macros.S
new file mode 100644
index 0000000..96d1cd2
--- /dev/null
+++ b/plat/ti/k3/include/plat_macros.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant platform registers
+	 * whenever an unhandled exception is taken in
+	 * BL31.
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	/* STUB */
+	.endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
new file mode 100644
index 0000000..8856af2
--- /dev/null
+++ b/plat/ti/k3/include/platform_def.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <board_def.h>
+#include <common_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_MSMC_PORT != UNUSED) + \
+					(K3_CLUSTER1_MSMC_PORT != UNUSED) + \
+					(K3_CLUSTER2_MSMC_PORT != UNUSED) + \
+					(K3_CLUSTER3_MSMC_PORT != UNUSED))
+
+#define UNUSED				-1
+
+#if !defined(K3_CLUSTER1_CORE_COUNT) || !defined(K3_CLUSTER1_MSMC_PORT)
+#define K3_CLUSTER1_CORE_COUNT		0
+#define K3_CLUSTER1_MSMC_PORT		UNUSED
+#endif
+
+#if !defined(K3_CLUSTER2_CORE_COUNT) || !defined(K3_CLUSTER2_MSMC_PORT)
+#define K3_CLUSTER2_CORE_COUNT		0
+#define K3_CLUSTER2_MSMC_PORT		UNUSED
+#endif
+
+#if !defined(K3_CLUSTER3_CORE_COUNT) || !defined(K3_CLUSTER3_MSMC_PORT)
+#define K3_CLUSTER3_CORE_COUNT		0
+#define K3_CLUSTER3_MSMC_PORT		UNUSED
+#endif
+
+#if K3_CLUSTER0_MSMC_PORT == UNUSED
+#error "ARM cluster 0 must be used"
+#endif
+
+#if ((K3_CLUSTER1_MSMC_PORT == UNUSED) && (K3_CLUSTER1_CORE_COUNT != 0)) || \
+    ((K3_CLUSTER2_MSMC_PORT == UNUSED) && (K3_CLUSTER2_CORE_COUNT != 0)) || \
+    ((K3_CLUSTER3_MSMC_PORT == UNUSED) && (K3_CLUSTER3_CORE_COUNT != 0))
+#error "Unused ports must have 0 ARM cores"
+#endif
+
+#define PLATFORM_CLUSTER_OFFSET		K3_CLUSTER0_MSMC_PORT
+
+#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_CLUSTER_COUNT + \
+					PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL1
+
+/*******************************************************************************
+ * Memory layout constants
+ ******************************************************************************/
+
+/*
+ * ARM-TF lives in SRAM, partition it here
+ */
+
+#define SHARED_RAM_BASE			BL31_LIMIT
+#define SHARED_RAM_SIZE			0x00001000
+
+/*
+ * BL3-1 specific defines.
+ *
+ * Put BL3-1 at the base of the Trusted SRAM, before SHARED_RAM.
+ */
+#define BL31_BASE			SEC_SRAM_BASE
+#define BL31_SIZE			(SEC_SRAM_SIZE - SHARED_RAM_SIZE)
+#define BL31_LIMIT			(BL31_BASE + BL31_SIZE)
+#define BL31_PROGBITS_LIMIT		BL31_LIMIT
+
+/*
+ * 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		8
+
+/*
+ * 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.
+ */
+#define MAX_MMAP_REGIONS	8
+
+/*
+ * 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_ADDRESS
+#define K3_USART_BASE_ADDRESS 0x02800000
+#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
+
+#ifndef K3_USART_BAUD
+#define K3_USART_BAUD 115200
+#endif
+
+/* Crash console defaults */
+#define CRASH_CONSOLE_BASE K3_USART_BASE_ADDRESS
+#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_GICD_BASE  0x01800000
+#define K3_GICD_SIZE  0x10000
+#define K3_GICR_BASE  0x01880000
+#define K3_GICR_SIZE  0x100000
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/ti/k3/platform.mk b/plat/ti/k3/platform.mk
new file mode 100644
index 0000000..65d5cc2
--- /dev/null
+++ b/plat/ti/k3/platform.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_PATH	:=	plat/ti/k3
+TARGET_BOARD	?=	generic
+
+include ${PLAT_PATH}/common/plat_common.mk
+include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk
+
+# modify BUILD_PLAT to point to board specific build directory
+BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE}
diff --git a/readme.rst b/readme.rst
index 94b1e63..3738c97 100644
--- a/readme.rst
+++ b/readme.rst
@@ -183,6 +183,7 @@
 -  Raspberry Pi 3 board
 -  RockChip RK3328, RK3368 and RK3399 SoCs
 -  Socionext UniPhier SoC family
+-  Texas Instruments K3 SoCs
 -  Xilinx Zynq UltraScale + MPSoC
 
 Still to come