feat(versal2): add support for AMD Versal Gen 2 platform

New SoC is a78 based with gicv3 and uart over pl011. Communication
interfaces are similar to Versal NET platform. System starts with AMD PLM
firmware which loads TF-A(bl31) to memory, which is already configured, and
jumps to it. PLM also prepare handoff structure for TF-A with information
what components were load and flags which indicate which EL level SW should
be started.

Change-Id: I5065b1b7ec4ee58e77dc4096747758480c84009c
Signed-off-by: Amit Nagal <amit.nagal@amd.com>
Signed-off-by: Akshay Belsare <akshay.belsare@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
diff --git a/plat/amd/versal2/bl31_setup.c b/plat/amd/versal2/bl31_setup.c
new file mode 100644
index 0000000..e878863
--- /dev/null
+++ b/plat/amd/versal2/bl31_setup.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/dcc.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <lib/cpus/cpu_ops.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+#include <plat_arm.h>
+#include <scmi.h>
+
+#include <def.h>
+#include <plat_fdt.h>
+#include <plat_private.h>
+#include <plat_startup.h>
+#include <pm_api_sys.h>
+#include <pm_client.h>
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_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)
+{
+	assert(sec_state_is_valid(type));
+
+	if (type == NON_SECURE) {
+		return &bl33_image_ep_info;
+	}
+
+	return &bl32_image_ep_info;
+}
+
+/*
+ * Set the build time defaults,if we can't find any config data.
+ */
+static inline void bl31_set_default_config(void)
+{
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+#if defined(SPD_opteed)
+	/* NS dtb addr passed to optee_os */
+	bl32_image_ep_info.args.arg3 = XILINX_OF_BOARD_DTB_ADDR;
+#endif
+	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+					  DISABLE_ALL_EXCEPTIONS);
+}
+
+/*
+ * Perform any BL31 specific platform actions. 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.
+ */
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	uint32_t uart_clock;
+	int32_t rc;
+
+	board_detection();
+
+	/* FIXME */
+	switch (platform_id) {
+	case SPP:
+		switch (platform_version) {
+		case SPP_PSXC_MMI_V2_0:
+			cpu_clock = 770000;
+			break;
+		case SPP_PSXC_MMI_V3_0:
+			cpu_clock = 908000;
+			break;
+		default:
+			panic();
+		}
+		break;
+	case SPP_MMD:
+		switch (platform_version) {
+		case SPP_PSXC_ISP_AIE_V2_0:
+		case SPP_PSXC_MMD_AIE_FRZ_EA:
+		case SPP_PSXC_MMD_AIE_V3_0:
+			cpu_clock = 760000;
+			break;
+		default:
+			panic();
+		}
+		break;
+	case EMU:
+	case EMU_MMD:
+		cpu_clock = 112203;
+		break;
+	case QEMU:
+		/* Random values now */
+		cpu_clock = 3333333;
+		break;
+	case SILICON:
+		cpu_clock = 100000000;
+		break;
+	default:
+		panic();
+	}
+
+	uart_clock = get_uart_clk();
+
+	if (CONSOLE_IS(pl011_0) || CONSOLE_IS(pl011_1)) {
+		static console_t _runtime_console;
+
+		/* Initialize the console to provide early debug support */
+		rc = console_pl011_register(UART_BASE, uart_clock,
+					    UART_BAUDRATE,
+					    &_runtime_console);
+		if (rc == 0) {
+			panic();
+		}
+
+		console_set_scope(&_runtime_console, CONSOLE_FLAG_BOOT |
+				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+	} else if (CONSOLE_IS(dcc)) {
+		/* Initialize the dcc console for debug.
+		 * dcc is over jtag and does not configures uart0 or uart1.
+		 */
+		rc = console_dcc_register();
+		if (rc == 0) {
+			panic();
+		}
+	} else {
+		/* Making MISRA C 2012 15.7 compliant */
+	}
+
+	NOTICE("TF-A running on %s %d.%d\n", board_name_decode(),
+	       platform_version / 10U, platform_version % 10U);
+
+	/* Initialize the platform config for future decision making */
+	config_setup();
+
+	/*
+	 * Do initial security configuration to allow DRAM/device access. On
+	 * Base only DRAM security is programmable (via TrustZone), but
+	 * other platforms might have more programmable security devices
+	 * present.
+	 */
+
+	/* Populate common information for BL32 and BL33 */
+	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+	bl31_set_default_config();
+
+	long rev_var = cpu_get_rev_var();
+
+	INFO("CPU Revision = 0x%lx\n", rev_var);
+	INFO("cpu_clock = %dHz, uart_clock = %dHz\n", cpu_clock, uart_clock);
+	NOTICE("BL31: Executing from 0x%x\n", BL31_BASE);
+	NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
+	NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
+
+}
+
+static versal_intr_info_type_el3_t type_el3_interrupt_table[MAX_INTR_EL3];
+
+int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
+{
+	static uint32_t index;
+	uint32_t i;
+
+	/* Validate 'handler' and 'id' parameters */
+	if (handler == NULL || index >= MAX_INTR_EL3) {
+		return -EINVAL;
+	}
+
+	/* Check if a handler has already been registered */
+	for (i = 0; i < index; i++) {
+		if (id == type_el3_interrupt_table[i].id) {
+			return -EALREADY;
+		}
+	}
+
+	type_el3_interrupt_table[index].id = id;
+	type_el3_interrupt_table[index].handler = handler;
+
+	index++;
+
+	return 0;
+}
+
+static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
+					  void *handle, void *cookie)
+{
+	uint32_t intr_id;
+	uint32_t i;
+	interrupt_type_handler_t handler = NULL;
+
+	intr_id = plat_ic_get_pending_interrupt_id();
+
+	for (i = 0; i < MAX_INTR_EL3; i++) {
+		if (intr_id == type_el3_interrupt_table[i].id) {
+			handler = type_el3_interrupt_table[i].handler;
+		}
+	}
+
+	if (handler != NULL) {
+		(void)handler(intr_id, flags, handle, cookie);
+	}
+
+	return 0;
+}
+
+void bl31_platform_setup(void)
+{
+	prepare_dtb();
+
+	/* Initialize the gic cpu and distributor interfaces */
+	plat_gic_driver_init();
+	plat_gic_init();
+
+	if (platform_id != EMU) {
+		init_scmi_server();
+	}
+}
+
+void bl31_plat_runtime_setup(void)
+{
+	uint64_t flags = 0;
+	int32_t rc;
+
+	set_interrupt_rm_flag(flags, NON_SECURE);
+	rc = register_interrupt_type_handler(INTR_TYPE_EL3,
+					     rdo_el3_interrupt_handler, flags);
+	if (rc != 0) {
+		panic();
+	}
+}
+
+/*
+ * Perform the very early platform specific architectural setup here.
+ */
+void bl31_plat_arch_setup(void)
+{
+	const mmap_region_t bl_regions[] = {
+#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
+		MAP_REGION_FLAT(XILINX_OF_BOARD_DTB_ADDR, XILINX_OF_BOARD_DTB_MAX_SIZE,
+				MT_MEMORY | MT_RW | MT_NS),
+#endif
+		MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+			MT_MEMORY | MT_RW | MT_SECURE),
+		MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+				MT_CODE | MT_SECURE),
+		MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE,
+				MT_RO_DATA | MT_SECURE),
+		MAP_REGION_FLAT(SMT_BUFFER_BASE, 0x1000,
+			MT_DEVICE | MT_RW | MT_NON_CACHEABLE | MT_EXECUTE_NEVER | MT_NS),
+		{0}
+	};
+
+	setup_page_tables(bl_regions, plat_get_mmap());
+	enable_mmu(0);
+}