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