feat(mt8186): initialize platform for MediaTek MT8186

- Add basic platform setup.
- Add MT8186 documentation at docs/plat/.
- Add generic CPU helper functions.
- Add basic register address.

TEST=build pass
BUG=b:202871018

Change-Id: Id3e2f46a8c3ab2f3e29137e508d4c671e8f4aad5
diff --git a/.cz.json b/.cz.json
index 5447f17..5ed24f4 100644
--- a/.cz.json
+++ b/.cz.json
@@ -194,6 +194,10 @@
                         {
                             "title": "MT8195",
                             "scopes": ["mt8195", "plat/mediatek/me8195", "plat/mediatek/mt8195", "plat/mdeiatek/mt8195"]
+                        },
+                        {
+                            "title": "MT8186",
+                            "scopes": ["mt8186", "plat/mediatek/mt8186"]
                         }
                     ]
                 },
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 5848005..eadd946 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -20,6 +20,7 @@
    intel-stratix10
    marvell/index
    mt8183
+   mt8186
    mt8192
    mt8195
    nvidia-tegra
diff --git a/docs/plat/mt8186.rst b/docs/plat/mt8186.rst
new file mode 100644
index 0000000..16b833a
--- /dev/null
+++ b/docs/plat/mt8186.rst
@@ -0,0 +1,21 @@
+MediaTek 8186
+=============
+
+MediaTek 8186 (MT8186) is a 64-bit ARM SoC introduced by MediaTek in 2021.
+The chip incorporates eight cores - six Cortex-A55 little cores and two Cortex-A76.
+Cortex-A76 can operate at up to 2.05 GHz.
+Cortex-A55 can operate at up to 2.0 GHz.
+
+Boot Sequence
+-------------
+
+::
+
+    Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel
+
+How to Build
+------------
+
+.. code:: shell
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8186 DEBUG=1 COREBOOT=1
diff --git a/plat/mediatek/mt8186/aarch64/plat_helpers.S b/plat/mediatek/mt8186/aarch64/plat_helpers.S
new file mode 100644
index 0000000..35b293f
--- /dev/null
+++ b/plat/mediatek/mt8186/aarch64/plat_helpers.S
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+	.globl plat_is_my_cpu_primary
+	.globl plat_my_core_pos
+	.globl plat_mediatek_calc_core_pos
+
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	cmp	x0, #PLAT_PRIMARY_CPU
+	cset	x0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the plat_mediatek_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+	 *
+	 * With this function: CorePos = CoreID (AFF1)
+	 * we do it with x0 = (x0 >> 8) & 0xff
+	 * -----------------------------------------------------
+	 */
+func plat_mediatek_calc_core_pos
+	mov	x1, #MPIDR_AFFLVL_MASK
+	and	x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+	ret
+endfunc plat_mediatek_calc_core_pos
diff --git a/plat/mediatek/mt8186/aarch64/platform_common.c b/plat/mediatek/mt8186/aarch64/platform_common.c
new file mode 100644
index 0000000..745e547
--- /dev/null
+++ b/plat/mediatek/mt8186/aarch64/platform_common.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <platform_def.h>
+
+/* Table of regions to map using the MMU.  */
+const mmap_region_t plat_mmap[] = {
+	/* for TF text, RO, RW */
+	MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	{ 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+			    uintptr_t total_size,
+			    uintptr_t ro_start,
+			    uintptr_t ro_limit)
+{
+	mmap_add_region(total_base, total_base, total_size,
+			MT_RW_DATA | MT_SECURE);
+	mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+			MT_CODE | MT_SECURE);
+	mmap_add(plat_mmap);
+	init_xlat_tables();
+	enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/mediatek/mt8186/bl31_plat_setup.c b/plat/mediatek/mt8186/bl31_plat_setup.c
new file mode 100644
index 0000000..3fd1c71
--- /dev/null
+++ b/plat/mediatek/mt8186/bl31_plat_setup.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* System Includes */
+#include <assert.h>
+
+/* Project Includes */
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+
+/* Platform Includes */
+#include <plat_params.h>
+#include <plat_private.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 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;
+
+	next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+	assert(next_image_info->h.type == PARAM_EP);
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	} else {
+		return NULL;
+	}
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+
+	params_early_setup(arg1);
+
+#if COREBOOT
+	if (coreboot_serial.type) {
+		console_16550_register(coreboot_serial.baseaddr,
+				       coreboot_serial.input_hertz,
+				       coreboot_serial.baud,
+				       &console);
+	}
+#else
+	console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+	INFO("MT8186 bl31_setup\n");
+
+	bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+	plat_configure_mmu_el3(BL31_START,
+			       BL31_END - BL31_START,
+			       BL_CODE_BASE,
+			       BL_CODE_END);
+}
diff --git a/plat/mediatek/mt8186/include/plat_helpers.h b/plat/mediatek/mt8186/include/plat_helpers.h
new file mode 100644
index 0000000..ebc9fa0
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_HELPERS_H__
+#define __PLAT_HELPERS_H__
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* __PLAT_HELPERS_H__ */
diff --git a/plat/mediatek/mt8186/include/plat_macros.S b/plat/mediatek/mt8186/include/plat_macros.S
new file mode 100644
index 0000000..39727ea
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_macros.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+	.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n"	\
+		" Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+	.asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+	/* ---------------------------------------------
+	 * The below macro prints out relevant GIC
+	 * registers whenever an unhandled exception
+	 * is taken in BL31.
+	 * Clobbers: x0 - x10, x26, x27, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	/* TODO: leave implementation to GIC owner */
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8186/include/plat_private.h b/plat/mediatek/mt8186/include/plat_private.h
new file mode 100644
index 0000000..7ef2b85
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+			    uintptr_t total_size,
+			    uintptr_t ro_start,
+			    uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8186/include/platform_def.h b/plat/mediatek/mt8186/include/platform_def.h
new file mode 100644
index 0000000..bf1bbef
--- /dev/null
+++ b/plat/mediatek/mt8186/include/platform_def.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#define PLAT_PRIMARY_CPU	0x0
+
+#define MT_GIC_BASE		(0x0C000000)
+#define MCUCFG_BASE		(0x0C530000)
+#define IO_PHYS			(0x10000000)
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE	IO_PHYS
+#define MTK_DEV_RNG0_SIZE	0x400000
+#define MTK_DEV_RNG1_BASE	(IO_PHYS + 0x1000000)
+#define MTK_DEV_RNG1_SIZE	0xa110000
+#define MTK_DEV_RNG2_BASE	MT_GIC_BASE
+#define MTK_DEV_RNG2_SIZE	0x600000
+
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE			(IO_PHYS + 0x01002000)
+
+#define UART_BAUDRATE			115200
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS	13000000
+#define SYS_COUNTER_FREQ_IN_MHZ		13
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE		0x800
+
+#define FIRMWARE_WELCOME_STR		"Booting Trusted Firmware\n"
+
+#define PLAT_MAX_PWR_LVL		U(3)
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_OFF_STATE		U(9)
+
+#define PLATFORM_SYSTEM_COUNT		U(1)
+#define PLATFORM_MCUSYS_COUNT		U(1)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	U(8)
+#define PLATFORM_CLUSTER1_CORE_COUNT	U(0)
+
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	U(8)
+
+#define SOC_CHIP_ID			U(0x8186)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE			0x54600000
+#define TZRAM_SIZE			0x00030000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE			(TZRAM_BASE + 0x1000)
+#define BL31_LIMIT			(TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#define MAX_XLAT_TABLES			16
+#define MAX_MMAP_REGIONS		16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * 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. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8186/plat_pm.c b/plat/mediatek/mt8186/plat_pm.c
new file mode 100644
index 0000000..61d2cc9
--- /dev/null
+++ b/plat/mediatek/mt8186/plat_pm.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/psci/psci.h>
+
+static const plat_psci_ops_t plat_psci_ops = {
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	*psci_ops = &plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/mediatek/mt8186/plat_topology.c b/plat/mediatek/mt8186/plat_topology.c
new file mode 100644
index 0000000..bc95c64
--- /dev/null
+++ b/plat/mediatek/mt8186/plat_topology.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+#include <plat_helpers.h>
+#include <platform_def.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+	/* Number of root nodes */
+	PLATFORM_SYSTEM_COUNT,
+	/* Number of children for the root node */
+	PLATFORM_MCUSYS_COUNT,
+	/* Number of children for the mcusys node */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first cluster node */
+	PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+
+	if ((read_mpidr() & MPIDR_MT_MASK) != 0) {
+		/* ARMv8.2 arch */
+		if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0) {
+			return -1;
+		}
+		return plat_mediatek_calc_core_pos(mpidr);
+	}
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+
+	if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) {
+		return -1;
+	}
+
+	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+		return -1;
+	}
+
+	/*
+	 * Validate cpu_id by checking whether it represents a CPU in
+	 * one of the two clusters present on the platform.
+	 */
+	if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+		return -1;
+	}
+
+	return (cpu_id + (cluster_id * 8));
+}
diff --git a/plat/mediatek/mt8186/platform.mk b/plat/mediatek/mt8186/platform.mk
new file mode 100644
index 0000000..2d20213
--- /dev/null
+++ b/plat/mediatek/mt8186/platform.mk
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2021, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT     := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/                            \
+                 -I${MTK_PLAT_SOC}/include/
+
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES}                              \
+                          ${XLAT_TABLES_LIB_SRCS}                       \
+                          plat/common/aarch64/crash_console_helpers.S   \
+                          plat/common/plat_psci_common.c
+
+
+BL31_SOURCES += common/desc_image_load.c                              \
+                drivers/ti/uart/aarch64/16550_console.S               \
+                lib/bl_aux_params/bl_aux_params.c                     \
+                lib/cpus/aarch64/cortex_a55.S                         \
+                lib/cpus/aarch64/cortex_a76.S                         \
+                plat/common/plat_gicv3.c                              \
+                ${MTK_PLAT}/common/mtk_plat_common.c                  \
+                ${MTK_PLAT}/common/params_setup.c                     \
+                ${MTK_PLAT_SOC}/aarch64/platform_common.c             \
+                ${MTK_PLAT_SOC}/aarch64/plat_helpers.S                \
+                ${MTK_PLAT_SOC}/bl31_plat_setup.c                     \
+                ${MTK_PLAT_SOC}/plat_pm.c                             \
+                ${MTK_PLAT_SOC}/plat_topology.c
+
+# Configs for A76 and A55
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+CTX_INCLUDE_AARCH32_REGS := 0
+ERRATA_A55_1530923 := 1
+ERRATA_A55_1221012 := 1
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MACH_MT8186 := 1
+$(eval $(call add_define,MACH_MT8186))
+
+include lib/coreboot/coreboot.mk