Merge pull request #1605 from sivadur/integration

Add support new Xilinx Versal ACAP platform
diff --git a/docs/plat/xilinx-versal.md b/docs/plat/xilinx-versal.md
new file mode 100644
index 0000000..c84014c
--- /dev/null
+++ b/docs/plat/xilinx-versal.md
@@ -0,0 +1,33 @@
+Trusted Firmware-A for Xilinx Versal
+================================
+
+Trusted Firmware-A implements the EL3 firmware layer for Xilinx Versal.
+The platform only uses the runtime part of TF-A as Xilinx Versal already has a
+BootROM (BL1) and PMC FW (BL2).
+
+BL31 is TF-A.
+BL32 is an optional Secure Payload.
+BL33 is the non-secure world software (U-Boot, Linux etc).
+
+To build:
+```bash
+make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31
+```
+
+To build ATF for different platform (for now its just versal virtual "versal_virt")
+```bash
+make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal VERSAL_PLATFORM=versal_virt bl31
+```
+
+# Xilinx Versal platform specific build options
+*   `VERSAL_ATF_MEM_BASE`: Specifies the base address of the bl31 binary.
+*   `VERSAL_ATF_MEM_SIZE`: Specifies the size of the memory region of the bl31 binary.
+*   `VERSAL_BL32_MEM_BASE`: Specifies the base address of the bl32 binary.
+*   `VERSAL_BL32_MEM_SIZE`: Specifies the size of the memory region of the bl32 binary.
+
+*   `VERSAL_CONSOLE`: Select the console driver. Options:
+    -   `pl011`, `pl011_0`: ARM pl011 UART 0
+    -   `pl011_1`         : ARM pl011 UART 1
+
+*   `VERSAL_PLATFORM`: Select the platform. Options:
+    -   `versal_virt`	: Versal Virtual platform
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c
new file mode 100644
index 0000000..c13b1b5
--- /dev/null
+++ b/plat/xilinx/versal/aarch64/versal_common.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <generic_delay_timer.h>
+#include <mmio.h>
+#include <platform.h>
+#include <xlat_tables.h>
+#include "../versal_def.h"
+#include "../versal_private.h"
+
+/*
+ * Table of regions to map using the MMU.
+ * This doesn't include TZRAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+const mmap_region_t plat_versal_mmap[] = {
+	MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	{ 0 }
+};
+
+const mmap_region_t *plat_versal_get_mmap(void)
+{
+	return plat_versal_mmap;
+}
+
+static void versal_print_platform_name(void)
+{
+	NOTICE("ATF running on Xilinx %s\n", PLATFORM_NAME);
+}
+
+void versal_config_setup(void)
+{
+	uint32_t val;
+
+	versal_print_platform_name();
+
+	mmio_write_32(VERSAL_CRL_IOU_SWITCH_CTRL,
+		      VERSAL_IOU_SWITCH_CTRL_CLKACT_BIT |
+		      (0x20 << VERSAL_IOU_SWITCH_CTRL_DIVISOR0_SHIFT));
+
+	/* Global timer init - Program time stamp reference clk */
+	val = mmio_read_32(VERSAL_CRL_TIMESTAMP_REF_CTRL);
+	val |= VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
+	mmio_write_32(VERSAL_CRL_TIMESTAMP_REF_CTRL, val);
+
+	/* Clear reset of timestamp reg */
+	mmio_write_32(VERSAL_CRL_RST_TIMESTAMP_OFFSET, 0x0);
+
+	/* Program freq register in System counter and enable system counter. */
+	mmio_write_32(VERSAL_IOU_SCNTRS_BASE_FREQ, VERSAL_CPU_CLOCK);
+	mmio_write_32(VERSAL_IOU_SCNTRS_COUNTER_CONTROL_REG,
+		      VERSAL_IOU_SCNTRS_CONTROL_EN);
+
+	generic_delay_timer_init();
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return VERSAL_CPU_CLOCK;
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	return PLAT_VERSAL_NS_IMAGE_OFFSET;
+#endif
+}
diff --git a/plat/xilinx/versal/aarch64/versal_helpers.S b/plat/xilinx/versal/aarch64/versal_helpers.S
new file mode 100644
index 0000000..1b7f955
--- /dev/null
+++ b/plat/xilinx/versal/aarch64/versal_helpers.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <gicv3.h>
+#include <platform_def.h>
+
+	.globl	plat_secondary_cold_boot_setup
+	.globl	plat_is_my_cpu_primary
+	.globl	versal_calc_core_pos
+	.globl	platform_mem_init
+	.globl	plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 * void plat_secondary_cold_boot_setup (void);
+	 *
+	 * This function performs any platform specific actions
+	 * needed for a secondary cpu after a cold reset e.g
+	 * mark the cpu's presence, mechanism to place it in a
+	 * holding pen etc.
+	 * TODO: Should we read the PSYS register to make sure
+	 * that the request has gone through.
+	 * -----------------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+	mrs	x0, mpidr_el1
+
+	/*
+	 * There is no sane reason to come out of this wfi. This
+	 * cpu will be powered on and reset by the cpu_on pm api
+	 */
+	dsb	sy
+	bl	plat_panic_handler
+endfunc plat_secondary_cold_boot_setup
+
+func plat_is_my_cpu_primary
+	mov	x9, x30
+	bl	plat_my_core_pos
+	cmp	x0, #VERSAL_PRIMARY_CPU
+	cset	x0, eq
+	ret	x9
+endfunc plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the versal_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	versal_calc_core_pos
+endfunc plat_my_core_pos
+
+func versal_calc_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc versal_calc_core_pos
+
+	/* ---------------------------------------------------------------------
+	 * We don't need to carry out any memory initialization on VERSAL
+	 * platform. The Secure RAM is accessible straight away.
+	 * ---------------------------------------------------------------------
+	 */
+func platform_mem_init
+	ret
+endfunc platform_mem_init
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
new file mode 100644
index 0000000..9f71a1c
--- /dev/null
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <platform.h>
+#include <pl011.h>
+#include <xlat_tables.h>
+#include "versal_private.h"
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static console_pl011_t versal_runtime_console;
+
+/*
+ * 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;
+}
+
+/*
+ * 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)
+{
+
+	/* Initialize the console to provide early debug support */
+	int rc = console_pl011_register(VERSAL_UART_BASE,
+					VERSAL_UART_CLOCK,
+					VERSAL_UART_BAUDRATE,
+					&versal_runtime_console);
+	if (rc == 0)
+		panic();
+
+	console_set_scope(&versal_runtime_console.console, CONSOLE_FLAG_BOOT |
+			  CONSOLE_FLAG_RUNTIME);
+
+	/* Initialize the platform config for future decision making */
+	versal_config_setup();
+	/* There are no parameters from BL2 if BL31 is a reset vector */
+	assert(arg0 == 0U);
+	assert(arg1 == 0U);
+
+	/*
+	 * Do initial security configuration to allow DRAM/device access. On
+	 * Base VERSAL 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);
+
+	/* use build time defaults in JTAG boot mode */
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = 0;
+	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);
+
+	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);
+}
+
+void bl31_platform_setup(void)
+{
+	/* Initialize the gic cpu and distributor interfaces */
+	plat_versal_gic_driver_init();
+	plat_versal_gic_init();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+}
+
+/*
+ * Perform the very early platform specific architectural setup here.
+ */
+void bl31_plat_arch_setup(void)
+{
+	const mmap_region_t bl_regions[] = {
+		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(BL_COHERENT_RAM_BASE,
+				BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+				MT_DEVICE | MT_RW | MT_SECURE),
+		{0}
+	};
+
+	setup_page_tables(bl_regions, plat_versal_get_mmap());
+	enable_mmu_el3(0);
+}
diff --git a/plat/xilinx/versal/include/plat_macros.S b/plat/xilinx/versal/include/plat_macros.S
new file mode 100644
index 0000000..4fc1315
--- /dev/null
+++ b/plat/xilinx/versal/include/plat_macros.S
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include "../include/platform_def.h"
+#include <gic_common.h>
+#include <gicv2.h>
+#include <gicv3.h>
+
+.section .rodata.gic_reg_name, "aS"
+/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
+gicc_regs:
+	.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+
+/* Applicable only to GICv3 with SRE enabled */
+icc_regs:
+	.asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
+
+/* Registers common to both GICv2 and GICv3 */
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
+
+	/* ---------------------------------------------
+	 * The below utility macro prints out relevant GIC
+	 * registers whenever an unhandled exception is
+	 * taken in BL31 on Versal platform.
+	 * Expects: GICD base in x16, GICC base in x17
+	 * Clobbers: x0 - x10, sp
+	 * ---------------------------------------------
+	 */
+	.macro versal_print_gic_regs
+	/* Check for GICv3 system register access */
+	mrs	x7, id_aa64pfr0_el1
+	ubfx	x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+	cmp	x7, #1
+	b.ne	print_gicv2
+
+	/* Check for SRE enable */
+	mrs	x8, ICC_SRE_EL3
+	tst	x8, #ICC_SRE_SRE_BIT
+	b.eq	print_gicv2
+
+	/* Load the icc reg list to x6 */
+	adr	x6, icc_regs
+	/* Load the icc regs to gp regs used by str_in_crash_buf_print */
+	mrs	x8, ICC_HPPIR0_EL1
+	mrs	x9, ICC_HPPIR1_EL1
+	mrs	x10, ICC_CTLR_EL3
+	/* Store to the crash buf and print to console */
+	bl	str_in_crash_buf_print
+	b	print_gic_common
+
+print_gicv2:
+	/* Load the gicc reg list to x6 */
+	adr	x6, gicc_regs
+	/* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+	ldr	w8, [x17, #GICC_HPPIR]
+	ldr	w9, [x17, #GICC_AHPPIR]
+	ldr	w10, [x17, #GICC_CTLR]
+	/* Store to the crash buf and print to console */
+	bl	str_in_crash_buf_print
+
+print_gic_common:
+	/* Print the GICD_ISPENDR regs */
+	add	x7, x16, #GICD_ISPENDR
+	adr	x4, gicd_pend_reg
+	bl	asm_print_str
+gicd_ispendr_loop:
+	sub	x4, x7, x16
+	cmp	x4, #0x280
+	b.eq	exit_print_gic_regs
+	bl	asm_print_hex
+
+	adr	x4, spacer
+	bl	asm_print_str
+
+	ldr	x4, [x7], #8
+	bl	asm_print_hex
+
+	adr	x4, newline
+	bl	asm_print_str
+	b	gicd_ispendr_loop
+exit_print_gic_regs:
+	.endm
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant GIC and CCI registers
+	 * whenever an unhandled exception is taken in
+	 * BL31.
+	 * Clobbers: x0 - x10, x16, x17, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	mov_imm	x17, PLAT_VERSAL_GICD_BASE
+	mov_imm	x16, PLAT_VERSAL_GICR_BASE
+	versal_print_gic_regs
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h
new file mode 100644
index 0000000..45aaa84
--- /dev/null
+++ b/plat/xilinx/versal/include/platform_def.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 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 "../versal_def.h"
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE	0x440
+
+#define PLATFORM_CORE_COUNT		2
+#define PLAT_MAX_PWR_LVL		1
+#define PLAT_MAX_RET_STATE		1
+#define PLAT_MAX_OFF_STATE		2
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#ifndef VERSAL_ATF_MEM_BASE
+# define BL31_BASE			0xfffea000
+# define BL31_LIMIT			0xffffffff
+#else
+# define BL31_BASE			(VERSAL_ATF_MEM_BASE)
+# define BL31_LIMIT			(VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_SIZE - 1)
+# ifdef VERSAL_ATF_MEM_PROGBITS_SIZE
+#  define BL31_PROGBITS_LIMIT		(VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_PROGBITS_SIZE - 1)
+# endif
+#endif
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#ifndef VERSAL_BL32_MEM_BASE
+# define BL32_BASE			0x60000000
+# define BL32_LIMIT			0x7fffffff
+#else
+# define BL32_BASE			(VERSAL_BL32_MEM_BASE)
+# define BL32_LIMIT			(VERSAL_BL32_MEM_BASE + VERSAL_BL32_MEM_SIZE - 1)
+#endif
+
+/*******************************************************************************
+ * BL33 specific defines.
+ ******************************************************************************/
+#ifndef PRELOADED_BL33_BASE
+# define PLAT_VERSAL_NS_IMAGE_OFFSET	0x8000000
+#else
+# define PLAT_VERSAL_NS_IMAGE_OFFSET	PRELOADED_BL33_BASE
+#endif
+
+/*******************************************************************************
+ * TSP  specific defines.
+ ******************************************************************************/
+#define TSP_SEC_MEM_BASE		BL32_BASE
+#define TSP_SEC_MEM_SIZE		(BL32_LIMIT - BL32_BASE + 1)
+
+/* ID of the secure physical generic timer interrupt used by the TSP */
+#define TSP_IRQ_SEC_PHY_TIMER		ARM_IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * 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_MMAP_REGIONS		7
+#define MAX_XLAT_TABLES			5
+
+#define CACHE_WRITEBACK_SHIFT	6
+#define CACHE_WRITEBACK_GRANULE	(1 << CACHE_WRITEBACK_SHIFT)
+
+#define PLAT_VERSAL_GICD_BASE	0xF9000000
+#define PLAT_VERSAL_GICR_BASE	0xF9080000
+
+/*
+ * Define a list 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_VERSAL_G1S_IRQS	VERSAL_IRQ_SEC_PHY_TIMER
+#define PLAT_VERSAL_G0_IRQS	VERSAL_IRQ_SEC_PHY_TIMER
+
+#define PLAT_VERSAL_G1S_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(VERSAL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_LEVEL)
+
+#define PLAT_VERSAL_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
new file mode 100644
index 0000000..37d00f6
--- /dev/null
+++ b/plat/xilinx/versal/plat_psci.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <psci.h>
+#include "versal_private.h"
+
+static uintptr_t versal_sec_entry;
+
+static int versal_nopmc_pwr_domain_on(u_register_t mpidr)
+{
+	uint32_t r;
+	unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+	VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
+
+	if (cpu_id == -1)
+		return PSCI_E_INTERN_FAIL;
+
+	/*
+	 * program RVBAR
+	 */
+	mmio_write_32(FPD_APU_RVBAR_L_0 + (cpu_id << 3), versal_sec_entry);
+	mmio_write_32(FPD_APU_RVBAR_H_0 + (cpu_id << 3), versal_sec_entry >> 32);
+
+	/*
+	 * clear VINITHI
+	 */
+	r = mmio_read_32(FPD_APU_CONFIG_0);
+	r &= ~(1 << FPD_APU_CONFIG_0_VINITHI_SHIFT << cpu_id);
+	mmio_write_32(FPD_APU_CONFIG_0, r);
+
+	/*
+	 * FIXME: Add power up sequence, By default it works
+	 * now without the need of it as it was powered up by
+	 * default.
+	 */
+
+	/*
+	 * clear power down request
+	 */
+	r = mmio_read_32(FPD_APU_PWRCTL);
+	r &= ~(1 << cpu_id);
+	mmio_write_32(FPD_APU_PWRCTL, r);
+
+	/*
+	 * release core reset
+	 */
+	r = mmio_read_32(CRF_RST_APU);
+	r &= ~((CRF_RST_APU_ACPU_PWRON_RESET |
+			CRF_RST_APU_ACPU_RESET) << cpu_id);
+	mmio_write_32(CRF_RST_APU, r);
+
+	return PSCI_E_SUCCESS;
+}
+
+void versal_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	/* Enable the gic cpu interface */
+	plat_versal_gic_pcpu_init();
+
+	/* Program the gic per-cpu distributor or re-distributor interface */
+	plat_versal_gic_cpuif_enable();
+}
+
+static const struct plat_psci_ops versal_nopmc_psci_ops = {
+	.pwr_domain_on			= versal_nopmc_pwr_domain_on,
+	.pwr_domain_on_finish		= versal_pwr_domain_on_finish,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const struct plat_psci_ops **psci_ops)
+{
+	versal_sec_entry = sec_entrypoint;
+
+	*psci_ops = &versal_nopmc_psci_ops;
+
+	return 0;
+}
diff --git a/plat/xilinx/versal/plat_topology.c b/plat/xilinx/versal/plat_topology.c
new file mode 100644
index 0000000..66d4fae
--- /dev/null
+++ b/plat/xilinx/versal/plat_topology.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+static const unsigned char plat_power_domain_tree_desc[] = {1, PLATFORM_CORE_COUNT};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return plat_power_domain_tree_desc;
+}
diff --git a/plat/xilinx/versal/plat_versal.c b/plat/xilinx/versal/plat_versal.c
new file mode 100644
index 0000000..152cb36
--- /dev/null
+++ b/plat/xilinx/versal/plat_versal.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <platform.h>
+#include "versal_private.h"
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	if (mpidr & MPIDR_CLUSTER_MASK)
+		return -1;
+
+	if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT)
+		return -1;
+
+	return versal_calc_core_pos(mpidr);
+}
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
new file mode 100644
index 0000000..78e9b33
--- /dev/null
+++ b/plat/xilinx/versal/platform.mk
@@ -0,0 +1,63 @@
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+override PROGRAMMABLE_RESET_ADDRESS := 1
+PSCI_EXTENDED_STATE_ID := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+SEPARATE_CODE_AND_RODATA := 1
+override RESET_TO_BL31 := 1
+PL011_GENERIC_UART := 1
+MULTI_CONSOLE_API := 1
+
+ifdef VERSAL_ATF_MEM_BASE
+    $(eval $(call add_define,VERSAL_ATF_MEM_BASE))
+
+    ifndef VERSAL_ATF_MEM_SIZE
+        $(error "VERSAL_ATF_BASE defined without VERSAL_ATF_SIZE")
+    endif
+    $(eval $(call add_define,VERSAL_ATF_MEM_SIZE))
+
+    ifdef VERSAL_ATF_MEM_PROGBITS_SIZE
+        $(eval $(call add_define,VERSAL_ATF_MEM_PROGBITS_SIZE))
+    endif
+endif
+
+ifdef VERSAL_BL32_MEM_BASE
+    $(eval $(call add_define,VERSAL_BL32_MEM_BASE))
+
+    ifndef VERSAL_BL32_MEM_SIZE
+        $(error "VERSAL_BL32_BASE defined without VERSAL_BL32_SIZE")
+    endif
+    $(eval $(call add_define,VERSAL_BL32_MEM_SIZE))
+endif
+
+VERSAL_PLATFORM ?= versal_virt
+$(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM}))
+
+VERSAL_CONSOLE	?=	pl011
+$(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE}))
+
+PLAT_INCLUDES		:=	-Iplat/xilinx/versal/include/
+
+PLAT_BL_COMMON_SOURCES	:=	lib/xlat_tables/xlat_tables_common.c		\
+				lib/xlat_tables/aarch64/xlat_tables.c		\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				drivers/arm/gic/common/gic_common.c		\
+				drivers/arm/gic/v3/gicv3_main.c			\
+				drivers/arm/gic/v3/gicv3_helpers.c		\
+				drivers/arm/pl011/aarch64/pl011_console.S	\
+				plat/common/plat_gicv3.c			\
+				plat/xilinx/versal/aarch64/versal_helpers.S	\
+				plat/xilinx/versal/aarch64/versal_common.c
+
+BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a53.S			\
+				lib/cpus/aarch64/cortex_a72.S			\
+				plat/common/plat_psci_common.c			\
+				plat/xilinx/versal/bl31_versal_setup.c		\
+				plat/xilinx/versal/plat_psci.c			\
+				plat/xilinx/versal/plat_versal.c		\
+				plat/xilinx/versal/plat_topology.c		\
+				plat/xilinx/versal/sip_svc_setup.c		\
+				plat/xilinx/versal/versal_gicv3.c
diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c
new file mode 100644
index 0000000..4007d5c
--- /dev/null
+++ b/plat/xilinx/versal/sip_svc_setup.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */
+
+#include <debug.h>
+#include <runtime_svc.h>
+#include <uuid.h>
+
+/* SMC function IDs for SiP Service queries */
+#define VERSAL_SIP_SVC_CALL_COUNT	0x8200ff00
+#define VERSAL_SIP_SVC_UID		0x8200ff01
+#define VERSAL_SIP_SVC_VERSION		0x8200ff03
+
+/* SiP Service Calls version numbers */
+#define SIP_SVC_VERSION_MAJOR	0
+#define SIP_SVC_VERSION_MINOR	1
+
+/* These macros are used to identify PM calls from the SMC function ID */
+#define PM_FID_MASK	0xf000u
+#define PM_FID_VALUE	0u
+#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
+
+/* SiP Service UUID */
+DEFINE_SVC_UUID2(versal_sip_uuid,
+		0x2ab9e4ec, 0x93b9, 0x11e7, 0xa0, 0x19,
+		0xdf, 0xe0, 0xdb, 0xad, 0x0a, 0xe0);
+
+/**
+ * sip_svc_setup() - Setup SiP Service
+ *
+ * Invokes PM setup
+ */
+static int32_t sip_svc_setup(void)
+{
+	return 0;
+}
+
+/**
+ * sip_svc_smc_handler() - Top-level SiP Service SMC handler
+ *
+ * Handler for all SiP SMC calls. Handles standard SIP requests
+ * and calls PM SMC handler if the call is for a PM-API function.
+ */
+uintptr_t sip_svc_smc_handler(uint32_t smc_fid,
+			     u_register_t x1,
+			     u_register_t x2,
+			     u_register_t x3,
+			     u_register_t x4,
+			     void *cookie,
+			     void *handle,
+			     u_register_t flags)
+{
+	/* Let PM SMC handler deal with PM-related requests */
+	switch (smc_fid) {
+	case VERSAL_SIP_SVC_CALL_COUNT:
+		/* PM functions + default functions */
+		SMC_RET1(handle, 2);
+
+	case VERSAL_SIP_SVC_UID:
+		SMC_UUID_RET(handle, versal_sip_uuid);
+
+	case VERSAL_SIP_SVC_VERSION:
+		SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR);
+
+	default:
+		WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid);
+		SMC_RET1(handle, SMC_UNK);
+	}
+}
+
+/* Register PM Service Calls as runtime service */
+DECLARE_RT_SVC(
+		sip_svc,
+		OEN_SIP_START,
+		OEN_SIP_END,
+		SMC_TYPE_FAST,
+		sip_svc_setup,
+		sip_svc_smc_handler);
diff --git a/plat/xilinx/versal/versal_def.h b/plat/xilinx/versal/versal_def.h
new file mode 100644
index 0000000..5e42bd7
--- /dev/null
+++ b/plat/xilinx/versal/versal_def.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef VERSAL_DEF_H
+#define VERSAL_DEF_H
+
+#include <common_def.h>
+
+/* List all consoles */
+#define VERSAL_CONSOLE_ID_pl011	1
+#define VERSAL_CONSOLE_ID_pl011_0	1
+#define VERSAL_CONSOLE_ID_pl011_1	2
+#define VERSAL_CONSOLE_ID_dcc		3
+
+#define VERSAL_CONSOLE_IS(con)	(VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE)
+
+/* List all supported platforms */
+#define VERSAL_PLATFORM_ID_versal_virt	1
+
+#define VERSAL_PLATFORM_IS(con)	(VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM)
+
+/* Firmware Image Package */
+#define VERSAL_PRIMARY_CPU	0
+
+/*******************************************************************************
+ * memory map related constants
+ ******************************************************************************/
+#define DEVICE0_BASE		0xFF000000
+#define DEVICE0_SIZE		0x00E00000
+#define DEVICE1_BASE		0xF9000000
+#define DEVICE1_SIZE		0x00800000
+
+/* CRL */
+#define VERSAL_CRL				0xFF5E0000
+#define VERSAL_CRL_IOU_SWITCH_CTRL		(VERSAL_CRL + 0x114)
+#define VERSAL_CRL_TIMESTAMP_REF_CTRL		(VERSAL_CRL + 0x14C)
+#define VERSAL_CRL_RST_TIMESTAMP_OFFSET	(VERSAL_CRL + 0x348)
+
+#define VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT	(1 << 25)
+#define VERSAL_IOU_SWITCH_CTRL_CLKACT_BIT		(1 << 25)
+#define VERSAL_IOU_SWITCH_CTRL_DIVISOR0_SHIFT		8
+
+/* IOU SCNTRS */
+#define VERSAL_IOU_SCNTRS			 0xFF140000
+#define VERSAL_IOU_SCNTRS_COUNTER_CONTROL_REG	(VERSAL_IOU_SCNTRS + 0x0)
+#define VERSAL_IOU_SCNTRS_BASE_FREQ		(VERSAL_IOU_SCNTRS + 0x20)
+
+#define VERSAL_IOU_SCNTRS_CONTROL_EN	1
+
+/*******************************************************************************
+ * IRQ constants
+ ******************************************************************************/
+#define VERSAL_IRQ_SEC_PHY_TIMER		29
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define VERSAL_UART0_BASE		0xFF000000
+#define VERSAL_UART1_BASE		0xFF010000
+
+#if VERSAL_CONSOLE_IS(pl011)
+# define VERSAL_UART_BASE	VERSAL_UART0_BASE
+#elif VERSAL_CONSOLE_IS(pl011_1)
+# define VERSAL_UART_BASE	VERSAL_UART1_BASE
+#else
+# error "invalid VERSAL_CONSOLE"
+#endif
+
+#define PLAT_VERSAL_CRASH_UART_BASE		VERSAL_UART_BASE
+#define PLAT_VERSAL_CRASH_UART_CLK_IN_HZ	VERSAL_UART_CLOCK
+#define VERSAL_CONSOLE_BAUDRATE			VERSAL_UART_BAUDRATE
+
+/*******************************************************************************
+ * Platform related constants
+ ******************************************************************************/
+#if VERSAL_PLATFORM_IS(versal_virt)
+# define PLATFORM_NAME		"Versal Virt"
+# define VERSAL_UART_CLOCK	25000000
+# define VERSAL_UART_BAUDRATE	115200
+# define VERSAL_CPU_CLOCK	62500000
+#endif
+
+/* Access control register defines */
+#define ACTLR_EL3_L2ACTLR_BIT	(1 << 6)
+#define ACTLR_EL3_CPUACTLR_BIT	(1 << 0)
+
+/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/
+#define CRF_BASE		0xFD1A0000
+#define CRF_SIZE		0x00600000
+
+/* CRF registers and bitfields */
+#define CRF_RST_APU	(CRF_BASE + 0X00000300)
+
+#define CRF_RST_APU_ACPU_RESET		(1 << 0)
+#define CRF_RST_APU_ACPU_PWRON_RESET	(1 << 10)
+
+/* APU registers and bitfields */
+#define FPD_APU_BASE		0xFD5C0000
+#define FPD_APU_CONFIG_0	(FPD_APU_BASE + 0x20)
+#define FPD_APU_RVBAR_L_0	(FPD_APU_BASE + 0x40)
+#define FPD_APU_RVBAR_H_0	(FPD_APU_BASE + 0x44)
+#define FPD_APU_PWRCTL		(FPD_APU_BASE + 0x90)
+
+#define FPD_APU_CONFIG_0_VINITHI_SHIFT	8
+
+#endif /* VERSAL_DEF_H */
diff --git a/plat/xilinx/versal/versal_gicv3.c b/plat/xilinx/versal/versal_gicv3.c
new file mode 100644
index 0000000..72374b5
--- /dev/null
+++ b/plat/xilinx/versal/versal_gicv3.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <gicv3.h>
+#include <interrupt_props.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <utils.h>
+#include "versal_private.h"
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_versal_gic_driver_init
+#pragma weak plat_versal_gic_init
+#pragma weak plat_versal_gic_cpuif_enable
+#pragma weak plat_versal_gic_cpuif_disable
+#pragma weak plat_versal_gic_pcpu_init
+#pragma weak plat_versal_gic_redistif_on
+#pragma weak plat_versal_gic_redistif_off
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t versal_interrupt_props[] = {
+	PLAT_VERSAL_G1S_IRQ_PROPS(INTR_GROUP1S),
+	PLAT_VERSAL_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+/*
+ * We save and restore the GICv3 context on system suspend. Allocate the
+ * data in the designated EL3 Secure carve-out memory.
+ */
+static gicv3_redist_ctx_t rdist_ctx __section("versal_el3_tzc_dram");
+static gicv3_dist_ctx_t dist_ctx __section("versal_el3_tzc_dram");
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ *   - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ *   - No CPUs implemented in the system use affinity level 3.
+ */
+static unsigned int versal_gicv3_mpidr_hash(u_register_t mpidr)
+{
+	mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+	return versal_calc_core_pos(mpidr);
+}
+
+static const gicv3_driver_data_t versal_gic_data __unused = {
+	.gicd_base = PLAT_VERSAL_GICD_BASE,
+	.gicr_base = PLAT_VERSAL_GICR_BASE,
+	.interrupt_props = versal_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(versal_interrupt_props),
+	.rdistif_num = PLATFORM_CORE_COUNT,
+	.rdistif_base_addrs = rdistif_base_addrs,
+	.mpidr_to_core_pos = versal_gicv3_mpidr_hash
+};
+
+void __init plat_versal_gic_driver_init(void)
+{
+	/*
+	 * 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.
+	 */
+#if IMAGE_BL31
+	gicv3_driver_init(&versal_gic_data);
+#endif
+}
+
+/******************************************************************************
+ * Versal common helper to initialize the GIC. Only invoked by BL31
+ *****************************************************************************/
+void __init plat_versal_gic_init(void)
+{
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_versal_gic_cpuif_enable(void)
+{
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_versal_gic_cpuif_disable(void)
+{
+	gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helper to initialize the per-cpu redistributor interface in
+ * GICv3
+ *****************************************************************************/
+void plat_versal_gic_pcpu_init(void)
+{
+	gicv3_rdistif_init(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helpers to power GIC redistributor interface
+ *****************************************************************************/
+void plat_versal_gic_redistif_on(void)
+{
+	gicv3_rdistif_on(plat_my_core_pos());
+}
+
+void plat_versal_gic_redistif_off(void)
+{
+	gicv3_rdistif_off(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helper to save & restore the GICv3 on resume from system
+ * suspend
+ *****************************************************************************/
+void plat_versal_gic_save(void)
+{
+	/*
+	 * If an ITS is available, save its context before
+	 * the Redistributor using:
+	 * gicv3_its_save_disable(gits_base, &its_ctx[i])
+	 * Additionnaly, an implementation-defined sequence may
+	 * be required to save the whole ITS state.
+	 */
+
+	/*
+	 * Save the GIC Redistributors and ITS contexts before the
+	 * Distributor context. As we only handle SYSTEM SUSPEND API,
+	 * we only need to save the context of the CPU that is issuing
+	 * the SYSTEM SUSPEND call, i.e. the current CPU.
+	 */
+	gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+
+	/* Save the GIC Distributor context */
+	gicv3_distif_save(&dist_ctx);
+
+	/*
+	 * From here, all the components of the GIC can be safely powered down
+	 * as long as there is an alternate way to handle wakeup interrupt
+	 * sources.
+	 */
+}
+
+void plat_versal_gic_resume(void)
+{
+	/* Restore the GIC Distributor context */
+	gicv3_distif_init_restore(&dist_ctx);
+
+	/*
+	 * Restore the GIC Redistributor and ITS contexts after the
+	 * Distributor context. As we only handle SYSTEM SUSPEND API,
+	 * we only need to restore the context of the CPU that issued
+	 * the SYSTEM SUSPEND call.
+	 */
+	gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+
+	/*
+	 * If an ITS is available, restore its context after
+	 * the Redistributor using:
+	 * gicv3_its_restore(gits_base, &its_ctx[i])
+	 * An implementation-defined sequence may be required to
+	 * restore the whole ITS state. The ITS must also be
+	 * re-enabled after this sequence has been executed.
+	 */
+}
diff --git a/plat/xilinx/versal/versal_private.h b/plat/xilinx/versal/versal_private.h
new file mode 100644
index 0000000..1e30ebc
--- /dev/null
+++ b/plat/xilinx/versal/versal_private.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef VERSAL_PRIVATE_H
+#define VERSAL_PRIVATE_H
+
+#include <xlat_tables.h>
+
+void versal_config_setup(void);
+
+const mmap_region_t *plat_versal_get_mmap(void);
+
+void plat_versal_gic_driver_init(void);
+void plat_versal_gic_init(void);
+void plat_versal_gic_cpuif_enable(void);
+void plat_versal_gic_cpuif_disable(void);
+void plat_versal_gic_pcpu_init(void);
+
+unsigned int versal_calc_core_pos(u_register_t mpidr);
+
+#endif /* VERSAL_PRIVATE_H */