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 */