summaryrefslogtreecommitdiffstats
path: root/plat/hisilicon/poplar
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--plat/hisilicon/poplar/aarch64/platform_common.c79
-rw-r--r--plat/hisilicon/poplar/aarch64/poplar_helpers.S87
-rw-r--r--plat/hisilicon/poplar/bl1_plat_setup.c119
-rw-r--r--plat/hisilicon/poplar/bl2_plat_mem_params_desc.c168
-rw-r--r--plat/hisilicon/poplar/bl2_plat_setup.c219
-rw-r--r--plat/hisilicon/poplar/bl31_plat_setup.c137
-rw-r--r--plat/hisilicon/poplar/include/hi3798cv200.h105
-rw-r--r--plat/hisilicon/poplar/include/plat_macros.S10
-rw-r--r--plat/hisilicon/poplar/include/plat_private.h37
-rw-r--r--plat/hisilicon/poplar/include/platform_def.h171
-rw-r--r--plat/hisilicon/poplar/include/poplar_layout.h132
-rw-r--r--plat/hisilicon/poplar/plat_pm.c173
-rw-r--r--plat/hisilicon/poplar/plat_storage.c254
-rw-r--r--plat/hisilicon/poplar/plat_topology.c33
-rw-r--r--plat/hisilicon/poplar/platform.mk112
-rw-r--r--plat/hisilicon/poplar/poplar_gicv2.c63
-rw-r--r--plat/hisilicon/poplar/poplar_image_load.c34
17 files changed, 1933 insertions, 0 deletions
diff --git a/plat/hisilicon/poplar/aarch64/platform_common.c b/plat/hisilicon/poplar/aarch64/platform_common.c
new file mode 100644
index 0000000..fcd0a8b
--- /dev/null
+++ b/plat/hisilicon/poplar/aarch64/platform_common.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "platform_def.h"
+
+#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \
+ DDR_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \
+ DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \
+ TSP_SEC_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#ifdef SPD_opteed
+#define MAP_OPTEE_PAGEABLE MAP_REGION_FLAT( \
+ POPLAR_OPTEE_PAGEABLE_LOAD_BASE, \
+ POPLAR_OPTEE_PAGEABLE_LOAD_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+
+static const mmap_region_t poplar_mmap[] = {
+ MAP_DDR,
+ MAP_DEVICE,
+ MAP_TSP_MEM,
+#ifdef SPD_opteed
+ MAP_OPTEE_PAGEABLE,
+#endif
+ {0}
+};
+
+#define DEFINE_CONFIGURE_MMU_EL(_el) \
+ void plat_configure_mmu_el##_el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(poplar_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el##_el(0); \
+ }
+
+DEFINE_CONFIGURE_MMU_EL(3)
+DEFINE_CONFIGURE_MMU_EL(1)
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/hisilicon/poplar/aarch64/poplar_helpers.S b/plat/hisilicon/poplar/aarch64/poplar_helpers.S
new file mode 100644
index 0000000..063ee64
--- /dev/null
+++ b/plat/hisilicon/poplar/aarch64/poplar_helpers.S
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_my_core_pos
+ .globl poplar_calc_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl platform_mem_init
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses poplar_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b poplar_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int poplar_calc_core_pos(u_register_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function: CorePos = (ClusterId * 4) +
+ * CoreId
+ * -----------------------------------------------------
+ */
+func poplar_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc poplar_calc_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x4
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, POPLAR_CRASH_UART_BASE
+ mov_imm x1, POPLAR_CRASH_UART_CLK_IN_HZ
+ mov_imm x2, POPLAR_CONSOLE_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, POPLAR_CRASH_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : r0
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, POPLAR_CRASH_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------------------------------
+ * We don't need to carry out any memory initialization on ARM
+ * platforms. The Secure RAM is accessible straight away.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
diff --git a/plat/hisilicon/poplar/bl1_plat_setup.c b/plat/hisilicon/poplar/bl1_plat_setup.c
new file mode 100644
index 0000000..acc1f0e
--- /dev/null
+++ b/plat/hisilicon/poplar/bl1_plat_setup.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/arm/pl061_gpio.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
+#include <drivers/synopsys/dw_mmc.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+/* Data structure which holds the extents of the trusted RAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+static meminfo_t bl2_tzram_layout;
+static console_t console;
+
+#if !POPLAR_RECOVERY
+static struct mmc_device_info mmc_info;
+#endif
+
+/*
+ * Cannot use default weak implementation in bl1_main.c because BL1 RW data is
+ * not at the top of the secure memory.
+ */
+int bl1_plat_handle_post_image_load(unsigned int image_id)
+{
+ image_desc_t *image_desc;
+ entry_point_info_t *ep_info;
+
+ if (image_id != BL2_IMAGE_ID)
+ return 0;
+
+ /* Get the image descriptor */
+ image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+ assert(image_desc != NULL);
+
+ /* Get the entry point info */
+ ep_info = &image_desc->ep_info;
+
+ bl2_tzram_layout.total_base = BL2_BASE;
+ bl2_tzram_layout.total_size = BL32_LIMIT - BL2_BASE;
+
+ flush_dcache_range((uintptr_t)&bl2_tzram_layout, sizeof(meminfo_t));
+
+ ep_info->args.arg1 = (uintptr_t)&bl2_tzram_layout;
+
+ VERBOSE("BL1: BL2 memory layout address = %p\n",
+ (void *)&bl2_tzram_layout);
+
+ return 0;
+}
+
+void bl1_early_platform_setup(void)
+{
+ /* Initialize the console to provide early debug support */
+ console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = BL1_RW_BASE;
+ bl1_tzram_layout.total_size = BL1_RW_SIZE;
+
+ INFO("BL1: 0x%lx - 0x%lx [size = %zu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
+ BL1_RAM_LIMIT - BL1_RAM_BASE);
+}
+
+void bl1_plat_arch_setup(void)
+{
+ plat_configure_mmu_el3(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL1_RO_BASE, /* l-loader and BL1 ROM */
+ BL1_RO_LIMIT,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+void bl1_platform_setup(void)
+{
+ int i;
+#if !POPLAR_RECOVERY
+ dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE);
+#endif
+
+ generic_delay_timer_init();
+
+ pl061_gpio_init();
+ for (i = 0; i < GPIO_MAX; i++)
+ pl061_gpio_register(GPIO_BASE(i), i);
+
+#if !POPLAR_RECOVERY
+ /* SoC-specific emmc register are initialized/configured by bootrom */
+ INFO("BL1: initializing emmc\n");
+ mmc_info.mmc_dev_type = MMC_IS_EMMC;
+ dw_mmc_init(&params, &mmc_info);
+#endif
+
+ plat_io_setup();
+}
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ return BL2_IMAGE_ID;
+}
diff --git a/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c b/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c
new file mode 100644
index 0000000..9bda02e
--- /dev/null
+++ b/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload)*/
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#else /* EL3_PAYLOAD_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg1 = POPLAR_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE where it is the pager
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE where it is the paged
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+ .image_info.image_base = POPLAR_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = POPLAR_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = PLAT_POPLAR_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_POPLAR_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = DDR_BASE + DDR_SIZE -
+ PLAT_POPLAR_NS_IMAGE_OFFSET,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c
new file mode 100644
index 0000000..ee46772
--- /dev/null
+++ b/plat/hisilicon/poplar/bl2_plat_setup.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/partition/partition.h>
+#include <drivers/synopsys/dw_mmc.h>
+#include <drivers/mmc.h>
+#include <lib/mmio.h>
+#include <lib/optee_utils.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+static console_t console;
+#if !POPLAR_RECOVERY
+static struct mmc_device_info mmc_info;
+#endif
+
+/*******************************************************************************
+ * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+int plat_poplar_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ /*
+ * This platform has no SCP_BL2 yet
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t poplar_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL3-2 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifdef __aarch64__
+uint32_t poplar_get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#else
+uint32_t poplar_get_spsr_for_bl33_entry(void)
+{
+ unsigned int hyp_status, mode, spsr;
+
+ hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+ mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#endif /* __aarch64__ */
+
+int poplar_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+#ifdef __aarch64__
+ case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0) {
+ WARN("OPTEE header parse error.\n");
+ }
+
+ /*
+ * OP-TEE expect to receive DTB address in x2.
+ * This will be copied into x2 by dispatcher.
+ * Set this (arg3) if necessary
+ */
+ /* bl_mem_params->ep_info.args.arg3 = PLAT_HIKEY_DT_BASE; */
+#endif
+ bl_mem_params->ep_info.spsr = poplar_get_spsr_for_bl32_entry();
+ break;
+#endif
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = poplar_get_spsr_for_bl33_entry();
+ break;
+
+#ifdef SCP_BL2_BASE
+ case SCP_BL2_IMAGE_ID:
+ /* The subsequent handling of SCP_BL2 is platform specific */
+ err = plat_poplar_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+ if (err) {
+ WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+ }
+ break;
+#endif
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return poplar_bl2_handle_post_image_load(image_id);
+}
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct meminfo *mem_layout = (struct meminfo *)arg1;
+#if !POPLAR_RECOVERY
+ dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE);
+#endif
+
+ console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Enable arch timer */
+ generic_delay_timer_init();
+
+ bl2_tzram_layout = *mem_layout;
+
+#if !POPLAR_RECOVERY
+ /* SoC-specific emmc register are initialized/configured by bootrom */
+ INFO("BL2: initializing emmc\n");
+ mmc_info.mmc_dev_type = MMC_IS_EMMC;
+ dw_mmc_init(&params, &mmc_info);
+#endif
+
+ plat_io_setup();
+}
+
+void bl2_plat_arch_setup(void)
+{
+ plat_configure_mmu_el1(bl2_tzram_layout.total_base,
+ bl2_tzram_layout.total_size,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return PLAT_POPLAR_NS_IMAGE_OFFSET;
+#endif
+}
diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c
new file mode 100644
index 0000000..fe60ddc
--- /dev/null
+++ b/plat/hisilicon/poplar/bl31_plat_setup.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <cortex_a53.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+#define TZPC_SEC_ATTR_CTRL_VALUE (0x9DB98D45)
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static console_t console;
+
+static void hisi_tzpc_sec_init(void)
+{
+ mmio_write_32(HISI_TZPC_SEC_ATTR_CTRL, TZPC_SEC_ATTR_CTRL_VALUE);
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup common to ARM standard platforms.
+ * Here is an opportunity to copy parameters passed by the calling EL (S-EL1
+ * in BL2 & 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)
+{
+ void *from_bl2;
+
+ from_bl2 = (void *) arg0;
+
+ console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Init console for crash report */
+ plat_crash_console_init();
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_image_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0)
+ panic();
+}
+
+void bl31_platform_setup(void)
+{
+ /* Init arch timer */
+ generic_delay_timer_init();
+
+ /* Init GIC distributor and CPU interface */
+ poplar_gic_driver_init();
+ poplar_gic_init();
+
+ /* Init security properties of IP blocks */
+ hisi_tzpc_sec_init();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ /* do nothing */
+}
+
+void bl31_plat_arch_setup(void)
+{
+ plat_configure_mmu_el3(BL31_BASE,
+ (BL31_LIMIT - BL31_BASE),
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+
+ INFO("Boot BL33 from 0x%lx for %" PRIu64 " Bytes\n",
+ bl33_image_ep_info.pc, bl33_image_ep_info.args.arg2);
+}
diff --git a/plat/hisilicon/poplar/include/hi3798cv200.h b/plat/hisilicon/poplar/include/hi3798cv200.h
new file mode 100644
index 0000000..e31f4b3
--- /dev/null
+++ b/plat/hisilicon/poplar/include/hi3798cv200.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI3798CV200_H
+#define HI3798CV200_H
+
+#include <lib/utils_def.h>
+
+/* PL011 */
+#define PL011_UART0_BASE (0xF8B00000)
+#define PL011_BAUDRATE (115200)
+#define PL011_UART0_CLK_IN_HZ (75000000)
+
+/* Sys Counter */
+#define SYS_COUNTER_FREQ_IN_TICKS (24000000)
+#define SYS_COUNTER_FREQ_IN_MHZ (24)
+
+/* Timer */
+#define SEC_TIMER0_BASE (0xF8008000)
+#define TIMER00_LOAD (SEC_TIMER0_BASE + 0x000)
+#define TIMER00_VALUE (SEC_TIMER0_BASE + 0x004)
+#define TIMER00_CONTROL (SEC_TIMER0_BASE + 0x008)
+#define TIMER00_BGLOAD (SEC_TIMER0_BASE + 0x018)
+
+#define SEC_TIMER2_BASE (0xF8009000)
+#define TIMER20_LOAD (SEC_TIMER2_BASE + 0x000)
+#define TIMER20_VALUE (SEC_TIMER2_BASE + 0x004)
+#define TIMER20_CONTROL (SEC_TIMER2_BASE + 0x008)
+#define TIMER20_BGLOAD (SEC_TIMER2_BASE + 0x018)
+
+/* GPIO */
+#define GPIO_MAX (13)
+#define GPIO_BASE(x) (x != 5 ? \
+ 0xf820000 + x * 0x1000 : 0xf8004000)
+
+/* SCTL */
+#define REG_BASE_SCTL (0xF8000000)
+#define REG_SC_GEN12 (0x00B0)
+
+/* CRG */
+#define REG_BASE_CRG (0xF8A22000)
+#define REG_CPU_LP (0x48)
+#define REG_CPU_RST (0x50)
+#define REG_PERI_CRG39 (0x9C)
+#define REG_PERI_CRG40 (0xA0)
+
+/* MCI */
+#define REG_BASE_MCI (0xF9830000)
+#define MCI_CDETECT (0x50)
+#define MCI_VERID (0x6C)
+#define MCI_VERID_VALUE (0x5342250A)
+#define MCI_VERID_VALUE2 (0x5342270A)
+
+/* EMMC */
+#define REG_EMMC_PERI_CRG REG_PERI_CRG40
+#define REG_SDCARD_PERI_CRG REG_PERI_CRG39
+#define EMMC_CLK_MASK (0x7 << 8)
+#define EMMC_SRST_REQ (0x1 << 4)
+#define EMMC_CKEN (0x1 << 1)
+#define EMMC_BUS_CKEN (0x1 << 0)
+#define EMMC_CLK_100M (0 << 8)
+#define EMMC_CLK_50M (1 << 8)
+#define EMMC_CLK_25M (2 << 8)
+
+#define EMMC_DESC_SIZE U(0x00100000) /* 1MB */
+#define EMMC_INIT_PARAMS(base) \
+ { .bus_width = MMC_BUS_WIDTH_8, \
+ .clk_rate = 25 * 1000 * 1000, \
+ .desc_base = (base), \
+ .desc_size = EMMC_DESC_SIZE, \
+ .flags = MMC_FLAG_CMD23, \
+ .reg_base = REG_BASE_MCI, \
+ }
+
+/* GIC-400 */
+#define GICD_BASE (0xF1001000)
+#define GICC_BASE (0xF1002000)
+#define GICR_BASE (0xF1000000)
+
+/* FIQ platform related define */
+#define HISI_IRQ_SEC_SGI_0 8
+#define HISI_IRQ_SEC_SGI_1 9
+#define HISI_IRQ_SEC_SGI_2 10
+#define HISI_IRQ_SEC_SGI_3 11
+#define HISI_IRQ_SEC_SGI_4 12
+#define HISI_IRQ_SEC_SGI_5 13
+#define HISI_IRQ_SEC_SGI_6 14
+#define HISI_IRQ_SEC_SGI_7 15
+#define HISI_IRQ_SEC_PPI_0 29
+#define HISI_IRQ_SEC_TIMER0 60
+#define HISI_IRQ_SEC_TIMER1 50
+#define HISI_IRQ_SEC_TIMER2 52
+#define HISI_IRQ_SEC_TIMER3 88
+#define HISI_IRQ_SEC_AXI 110
+
+/* Watchdog */
+#define HISI_WDG0_BASE (0xF8A2C000)
+
+#define HISI_TZPC_BASE (0xF8A80000)
+#define HISI_TZPC_SEC_ATTR_CTRL (HISI_TZPC_BASE + 0x10)
+
+#endif /* HI3798CV200_H */
diff --git a/plat/hisilicon/poplar/include/plat_macros.S b/plat/hisilicon/poplar/include/plat_macros.S
new file mode 100644
index 0000000..82d10c1
--- /dev/null
+++ b/plat/hisilicon/poplar/include/plat_macros.S
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+.section .rodata.gic_reg_name, "aS"
+ .macro plat_crash_print_regs
+ nop
+ .endm
diff --git a/plat/hisilicon/poplar/include/plat_private.h b/plat/hisilicon/poplar/include/plat_private.h
new file mode 100644
index 0000000..a34f138
--- /dev/null
+++ b/plat/hisilicon/poplar/include/plat_private.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+#include <common/bl_common.h>
+
+#include "hi3798cv200.h"
+
+void plat_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+
+void plat_configure_mmu_el1(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+
+void plat_io_setup(void);
+
+unsigned int poplar_calc_core_pos(u_register_t mpidr);
+
+void poplar_gic_driver_init(void);
+void poplar_gic_init(void);
+void poplar_gic_cpuif_enable(void);
+void poplar_gic_pcpu_init(void);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/hisilicon/poplar/include/platform_def.h b/plat/hisilicon/poplar/include/platform_def.h
new file mode 100644
index 0000000..ce0fbbc
--- /dev/null
+++ b/plat/hisilicon/poplar/include/platform_def.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017-2019, 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 <common/interrupt_props.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include "hi3798cv200.h"
+#include "poplar_layout.h" /* BL memory region sizes, etc */
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define POPLAR_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define POPLAR_CRASH_UART_BASE PL011_UART0_BASE
+#define POPLAR_CRASH_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ
+#define POPLAR_CONSOLE_BAUDRATE PL011_BAUDRATE
+
+/* Generic platform constants */
+#define PLATFORM_STACK_SIZE (0x800)
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+#define BOOT_EMMC_NAME "l-loader.bin"
+
+#define PLATFORM_CACHE_LINE_SIZE (64)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CORE_COUNT U(4)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+
+/* IO framework user */
+#define MAX_IO_DEVICES (4)
+#define MAX_IO_HANDLES (4)
+#define MAX_IO_BLOCK_DEVICES U(2)
+
+/* Memory size options */
+#define POPLAR_DRAM_SIZE_1G 0
+#define POPLAR_DRAM_SIZE_2G 1
+
+/* Memory map related constants */
+#define DDR_BASE (0x00000000)
+
+#if (POPLAR_DRAM_SIZE_ID == POPLAR_DRAM_SIZE_2G)
+#define DDR_SIZE (0x80000000)
+#elif (POPLAR_DRAM_SIZE_ID == POPLAR_DRAM_SIZE_1G)
+#define DDR_SIZE (0x40000000)
+#else
+#error "Currently unsupported POPLAR_DRAM_SIZE_ID value"
+#endif
+
+#define DEVICE_BASE (0xF0000000)
+#define DEVICE_SIZE (0x0F000000)
+
+#define TEE_SEC_MEM_BASE (0x70000000)
+#define TEE_SEC_MEM_SIZE (0x10000000)
+
+/* Memory location options for TSP */
+#define POPLAR_SRAM_ID 0
+#define POPLAR_DRAM_ID 1
+
+/*
+ * DDR for OP-TEE (26MB from 0x02400000 -0x04000000) is divided in several
+ * regions:
+ * - Secure DDR (default is the top 16MB) used by OP-TEE
+ * - Non-secure DDR (4MB) reserved for OP-TEE's future use
+ * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature
+ * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB)
+ */
+#define DDR_SEC_SIZE 0x01000000
+#define DDR_SEC_BASE 0x03000000
+
+/*
+ * BL3-2 specific defines.
+ */
+
+/*
+ * The TSP currently executes from TZC secured area of DRAM.
+ */
+#define BL32_DRAM_BASE 0x03000000
+#define BL32_DRAM_LIMIT 0x04000000
+
+#ifdef SPD_opteed
+/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */
+#define POPLAR_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */
+#define POPLAR_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - POPLAR_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x03C0_0000 */
+#endif
+
+#if (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_DRAM_ID)
+#define TSP_SEC_MEM_BASE BL32_DRAM_BASE
+#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE)
+#define BL32_BASE BL32_DRAM_BASE
+#define BL32_LIMIT BL32_DRAM_LIMIT
+#elif (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_SRAM_ID)
+#error "SRAM storage of TSP payload is currently unsupported"
+#else
+#error "Currently unsupported POPLAR_TSP_LOCATION_ID value"
+#endif
+
+/* BL32 is mandatory in AArch32 */
+#ifdef __aarch64__
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+#endif
+
+#define POPLAR_EMMC_DATA_BASE U(0x02200000)
+#define POPLAR_EMMC_DATA_SIZE EMMC_DESC_SIZE
+#define POPLAR_EMMC_DESC_BASE (POPLAR_EMMC_DATA_BASE + POPLAR_EMMC_DATA_SIZE)
+#define POPLAR_EMMC_DESC_SIZE EMMC_DESC_SIZE
+
+#define PLAT_POPLAR_NS_IMAGE_OFFSET 0x37000000
+
+/* Page table and MMU setup constants */
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES (4)
+#define MAX_MMAP_REGIONS (16)
+
+#define CACHE_WRITEBACK_SHIFT (6)
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/* Power states */
+#define PLAT_MAX_PWR_LVL (MPIDR_AFFLVL1)
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+/* Interrupt controller */
+#define POPLAR_GICD_BASE GICD_BASE
+#define POPLAR_GICC_BASE GICC_BASE
+
+#define POPLAR_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_TIMER0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_TIMER1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_TIMER2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_TIMER3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_AXI, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define POPLAR_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/hisilicon/poplar/include/poplar_layout.h b/plat/hisilicon/poplar/include/poplar_layout.h
new file mode 100644
index 0000000..03047f9
--- /dev/null
+++ b/plat/hisilicon/poplar/include/poplar_layout.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POPLAR_LAYOUT_H
+#define POPLAR_LAYOUT_H
+
+/*
+ * Boot memory layout definitions for the HiSilicon Poplar board
+ */
+
+/*
+ * When Poplar is powered on, boot ROM verifies the initial content of
+ * boot media, loads it into low memory, and begins executing it
+ * in 32-bit mode. The image loaded is "l-loader.bin", which contains
+ * a small amount code along with an embedded ARM Trusted Firmware
+ * BL1 image. The main purpose of "l-loader" is to prepare the
+ * processor to execute the BL1 image in 64-bit mode, and to trigger
+ * that execution.
+ *
+ * Also embedded in "l-loader.bin" is a FIP image that contains
+ * other ARM Trusted Firmware images: BL2; BL31; and for BL33,
+ * U-Boot. When BL1 executes, it unpacks the BL2 image from the FIP
+ * image into a region of memory set aside to hold it. Similarly,
+ * BL2 unpacks BL31 into memory reserved for it, and unpacks U-Boot
+ * into high memory.
+ *
+ * Because the BL1 code is embedded in "l-loader", its base address
+ * in memory is derived from the base address of the "l-loader"
+ * text section, together with an offset. Memory space for BL2 is
+ * reserved immediately following BL1, and memory space is reserved
+ * for BL31 after that. ARM Trusted Firmware requires each of these
+ * memory regions to be aligned on page boundaries, so the size of
+ * each region is a multiple of a page size (ending in 000). Note
+ * that ARM Trusted Firmware requires the read-only and read-write
+ * regions of memory used for BL1 to be defined separately.
+ *
+ * ---------------------
+ * | (unused memory) |
+ * +-------------------+ - - - - -
+ * | (l-loader text) | \
+ * +-------------------+ \
+ * | BL1 (read-only) | \ \
+ * |- - - - - - - - - -| | |
+ * | BL1 (read-write) | | |
+ * +-------------------+ > BL Memory |
+ * | Reserved for BL2 | | > "l-loader.bin" image
+ * +-------------------+ | |
+ * | Reserved for BL31 | / |
+ * +-------------------+ |
+ * . . . /
+ * +-------------------+ /
+ * | FIP | /
+ * +-------------------+ - - - - -
+ * . . .
+ * | (unused memory) |
+ * . . .
+ * +-------------------+
+ * |Reserved for U-Boot|
+ * +-------------------+
+ * . . .
+ * | (unused memory) |
+ * ---------------------
+ *
+ * The size of each of these regions is defined below. The base
+ * address of the "l-loader" TEXT section and the offset of the BL1
+ * image within that serve as anchors for defining the positions of
+ * all other regions. The FIP is placed in a section of its own.
+ *
+ * A "BASE" is the memory address of the start of a region; a "LIMIT"
+ * marks its end. A "SIZE" is the size of a region (in bytes). An
+ * "OFFSET" is an offset to the start of a region relative to the
+ * base of the "l-loader" TEXT section (also a multiple of page size).
+ */
+#define LLOADER_TEXT_BASE 0x02001000 /* page aligned */
+#define BL1_OFFSET 0x0000D000 /* page multiple */
+#define FIP_BASE 0x02040000
+
+/*
+ * FIP_BASE_EMMC = 0x40000 - 0x1000
+ * = fip.bin offset - l-loader text offset
+ * in l-loader.bin
+ */
+#define FIP_BASE_EMMC 0x0003f000
+
+#define BL1_RO_SIZE 0x00008000 /* page multiple */
+#define BL1_RW_SIZE 0x00008000 /* page multiple */
+#define BL1_SIZE (BL1_RO_SIZE + BL1_RW_SIZE)
+#define BL2_SIZE 0x0000d000 /* page multiple */
+#define BL31_SIZE 0x00014000
+#if !POPLAR_RECOVERY
+/*
+ * emmc partition1 4096KB
+ * - l-loader.bin 1984KB
+ * |- l-loader + bl1.bin 256KB
+ * |- fip.bin 1728KB (0x001b0000)
+ * - u-boot persistent data 64KB
+ * - uefi persistent data 2048KB
+ */
+#define FIP_SIZE 0x001b0000 /* absolute max */
+#else
+/*
+ * same as above, but bootrom can only load an image (l-loader.bin) of
+ * 1024KB max, so after deducting the size of l-loader + bl1.bin (256KB),
+ * that leaves 768KB (0x000c0000) for fip.bin
+ */
+#define FIP_SIZE 0x000c0000 /* absolute max */
+#endif
+
+ /* BL1_OFFSET */ /* (Defined above) */
+#define BL1_BASE (LLOADER_TEXT_BASE + BL1_OFFSET)
+#define BL1_LIMIT (BL1_BASE + BL1_SIZE)
+
+#define BL1_RO_OFFSET (BL1_OFFSET)
+#define BL1_RO_BASE (LLOADER_TEXT_BASE + BL1_RO_OFFSET)
+#define BL1_RO_LIMIT (BL1_RO_BASE + BL1_RO_SIZE)
+
+#define BL1_RW_OFFSET (BL1_RO_OFFSET + BL1_RO_SIZE)
+#define BL1_RW_BASE (LLOADER_TEXT_BASE + BL1_RW_OFFSET)
+#define BL1_RW_LIMIT (BL1_RW_BASE + BL1_RW_SIZE)
+
+#define BL2_OFFSET (BL1_OFFSET + BL1_SIZE)
+#define BL2_BASE (LLOADER_TEXT_BASE + BL2_OFFSET)
+#define BL2_LIMIT (BL2_BASE + BL2_SIZE)
+
+#define BL31_OFFSET (BL2_OFFSET + BL2_SIZE)
+#define BL31_BASE (LLOADER_TEXT_BASE + BL31_OFFSET)
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+#endif /* POPLAR_LAYOUT_H */
diff --git a/plat/hisilicon/poplar/plat_pm.c b/plat/hisilicon/poplar/plat_pm.c
new file mode 100644
index 0000000..67ebca1
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_pm.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+#define REG_PERI_CPU_RVBARADDR 0xF8A80034
+#define REG_PERI_CPU_AARCH_MODE 0xF8A80030
+
+#define REG_CPU_LP_CPU_SW_BEGIN 10
+#define CPU_REG_COREPO_SRST 12
+#define CPU_REG_CORE_SRST 8
+
+static void poplar_cpu_standby(plat_local_state_t cpu_state)
+{
+ dsb();
+ wfi();
+}
+
+static int poplar_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int cpu = plat_core_pos_by_mpidr(mpidr);
+ unsigned int regval, regval_bak;
+
+ /* Select 400MHz before start slave cores */
+ regval_bak = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP));
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x206);
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x606);
+
+ /* Clear the slave cpu arm_por_srst_req reset */
+ regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST));
+ regval &= ~(1 << (cpu + CPU_REG_COREPO_SRST));
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval);
+
+ /* Clear the slave cpu reset */
+ regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST));
+ regval &= ~(1 << (cpu + CPU_REG_CORE_SRST));
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval);
+
+ /* Restore cpu frequency */
+ regval = regval_bak & (~(1 << REG_CPU_LP_CPU_SW_BEGIN));
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval);
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval_bak);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void poplar_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ assert(0);
+}
+
+static void poplar_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ assert(0);
+}
+
+static void poplar_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_MAX_OFF_STATE);
+
+ /* Enable the gic cpu interface */
+ poplar_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ poplar_gic_cpuif_enable();
+}
+
+static void poplar_pwr_domain_suspend_finish(
+ const psci_power_state_t *target_state)
+{
+ assert(0);
+}
+
+static void __dead2 poplar_system_off(void)
+{
+ ERROR("Poplar System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 poplar_system_reset(void)
+{
+ mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551);
+ mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x0), 0x00000100);
+ mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8), 0x00000003);
+
+ wfi();
+ ERROR("Poplar System Reset: operation not handled.\n");
+ panic();
+}
+
+static int32_t poplar_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
+
+ int pstate = psci_get_pstate_type(power_state);
+
+ assert(req_state);
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY)
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ else
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+static int poplar_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint >= DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
+ return PSCI_E_SUCCESS;
+
+ return PSCI_E_INVALID_ADDRESS;
+}
+
+static void poplar_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ int i;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+static const plat_psci_ops_t poplar_plat_psci_ops = {
+ .cpu_standby = poplar_cpu_standby,
+ .pwr_domain_on = poplar_pwr_domain_on,
+ .pwr_domain_off = poplar_pwr_domain_off,
+ .pwr_domain_suspend = poplar_pwr_domain_suspend,
+ .pwr_domain_on_finish = poplar_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = poplar_pwr_domain_suspend_finish,
+ .system_off = poplar_system_off,
+ .system_reset = poplar_system_reset,
+ .validate_power_state = poplar_validate_power_state,
+ .validate_ns_entrypoint = poplar_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = poplar_get_sys_suspend_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &poplar_plat_psci_ops;
+
+ mmio_write_32((uintptr_t)REG_PERI_CPU_AARCH_MODE, 0xF);
+ mmio_write_32((uintptr_t)REG_PERI_CPU_RVBARADDR, sec_entrypoint);
+ return 0;
+}
diff --git a/plat/hisilicon/poplar/plat_storage.c b/plat/hisilicon/poplar/plat_storage.c
new file mode 100644
index 0000000..a17e0f1
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_storage.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/partition.h>
+#include <lib/mmio.h>
+#include <lib/semihosting.h>
+#include <lib/utils.h>
+#include <tools_share/firmware_image_package.h>
+
+#if !POPLAR_RECOVERY
+static const io_dev_connector_t *emmc_dev_con;
+static uintptr_t emmc_dev_handle;
+static int open_emmc(const uintptr_t spec);
+
+static const io_block_spec_t emmc_fip_spec = {
+ .offset = FIP_BASE_EMMC,
+ .length = FIP_SIZE
+};
+
+static const io_block_dev_spec_t emmc_dev_spec = {
+ .buffer = {
+ .offset = POPLAR_EMMC_DATA_BASE,
+ .length = POPLAR_EMMC_DATA_SIZE,
+ },
+ .ops = {
+ .read = mmc_read_blocks,
+ .write = mmc_write_blocks,
+ },
+ .block_size = MMC_BLOCK_SIZE,
+};
+#else
+static const io_dev_connector_t *mmap_dev_con;
+static uintptr_t mmap_dev_handle;
+static int open_mmap(const uintptr_t spec);
+
+static const io_block_spec_t loader_fip_spec = {
+ .offset = FIP_BASE,
+ .length = FIP_SIZE
+};
+#endif
+
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static int open_fip(const uintptr_t spec);
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+#if !POPLAR_RECOVERY
+ [FIP_IMAGE_ID] = {
+ &emmc_dev_handle,
+ (uintptr_t)&emmc_fip_spec,
+ open_emmc
+ },
+#else
+ [FIP_IMAGE_ID] = {
+ &mmap_dev_handle,
+ (uintptr_t)&loader_fip_spec,
+ open_mmap
+ },
+#endif
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+};
+
+#if !POPLAR_RECOVERY
+static int open_emmc(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(emmc_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ INFO("Using eMMC\n");
+ io_close(local_image_handle);
+ } else {
+ ERROR("error opening emmc\n");
+ }
+ } else {
+ ERROR("error initializing emmc\n");
+ }
+
+ return result;
+}
+#else
+static int open_mmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(mmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(mmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ INFO("Using mmap\n");
+ io_close(local_image_handle);
+ } else {
+ ERROR("error opening mmap\n");
+ }
+ } else {
+ ERROR("error initializing mmap\n");
+ }
+
+ return result;
+}
+#endif
+
+static int open_fip(const uintptr_t spec)
+{
+ uintptr_t local_image_handle;
+ int result;
+
+ result = io_dev_init(fip_dev_handle, (uintptr_t) FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ INFO("Using FIP\n");
+ io_close(local_image_handle);
+ } else {
+ ERROR("error opening fip\n");
+ }
+ } else {
+ ERROR("error initializing fip\n");
+ }
+
+ return result;
+}
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ const struct plat_io_policy *policy;
+ int result;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ assert(result == 0);
+
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+
+ return result;
+}
+
+void plat_io_setup(void)
+{
+ int result;
+
+#if !POPLAR_RECOVERY
+ result = register_io_dev_block(&emmc_dev_con);
+#else
+ result = register_io_dev_memmap(&mmap_dev_con);
+#endif
+ assert(result == 0);
+
+ result = register_io_dev_fip(&fip_dev_con);
+ assert(result == 0);
+
+#if !POPLAR_RECOVERY
+ result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+#else
+ result = io_dev_open(fip_dev_con, (uintptr_t)&loader_fip_spec,
+ &fip_dev_handle);
+#endif
+ assert(result == 0);
+
+#if !POPLAR_RECOVERY
+ result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec,
+ &emmc_dev_handle);
+#else
+ result = io_dev_open(mmap_dev_con, (uintptr_t)NULL, &mmap_dev_handle);
+#endif
+ assert(result == 0);
+
+ (void) result;
+}
diff --git a/plat/hisilicon/poplar/plat_topology.c b/plat/hisilicon/poplar/plat_topology.c
new file mode 100644
index 0000000..764008e
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_topology.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <lib/psci/psci.h>
+
+#include "plat_private.h"
+
+const unsigned char hisi_power_domain_tree_desc[] = {
+ PLATFORM_CLUSTER_COUNT,
+ PLATFORM_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return hisi_power_domain_tree_desc;
+}
+
+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 poplar_calc_core_pos(mpidr);
+}
diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk
new file mode 100644
index 0000000..b5d9867
--- /dev/null
+++ b/plat/hisilicon/poplar/platform.mk
@@ -0,0 +1,112 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# On Poplar, the TSP can execute from TZC secure area in DRAM.
+POPLAR_TSP_RAM_LOCATION ?= dram
+ifeq (${POPLAR_TSP_RAM_LOCATION}, dram)
+ POPLAR_TSP_RAM_LOCATION_ID = POPLAR_DRAM_ID
+else ifeq (${POPLAR_TSP_RAM_LOCATION}, sram)
+ POPLAR_TSP_RAM_LOCATION_ID = POPLAR_SRAM_ID
+else
+ $(error "Currently unsupported POPLAR_TSP_RAM_LOCATION value")
+endif
+$(eval $(call add_define,POPLAR_TSP_RAM_LOCATION_ID))
+
+POPLAR_DRAM_SIZE ?= two_gig
+ifeq (${POPLAR_DRAM_SIZE}, two_gig)
+ POPLAR_DRAM_SIZE_ID = POPLAR_DRAM_SIZE_2G
+else ifeq (${POPLAR_DRAM_SIZE}, one_gig)
+ POPLAR_DRAM_SIZE_ID = POPLAR_DRAM_SIZE_1G
+else
+ $(error "Currently unsupported POPLAR_DRAM_SIZE value")
+endif
+$(eval $(call add_define,POPLAR_DRAM_SIZE_ID))
+
+POPLAR_RECOVERY := 0
+$(eval $(call add_define,POPLAR_RECOVERY))
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+
+NEED_BL33 := yes
+
+COLD_BOOT_SINGLE_CPU := 1
+PROGRAMMABLE_RESET_ADDRESS := 1
+CTX_INCLUDE_FPREGS := 1
+ERRATA_A53_855873 := 1
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ENABLE_SVE_FOR_NS := 0
+WORKAROUND_CVE_2017_5715 := 0
+
+PLAT_PL061_MAX_GPIOS := 104
+$(eval $(call add_define,PLAT_PL061_MAX_GPIOS))
+
+PLAT_INCLUDES := -Iplat/hisilicon/poplar/include \
+ -Iplat/hisilicon/poplar
+
+PLAT_BL_COMMON_SOURCES := \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/arm/pl011/aarch64/pl011_console.S \
+ drivers/arm/gic/v2/gicv2_main.c \
+ plat/common/plat_gicv2.c \
+ plat/hisilicon/poplar/aarch64/platform_common.c \
+ plat/hisilicon/poplar/aarch64/poplar_helpers.S \
+ plat/hisilicon/poplar/poplar_gicv2.c
+
+BL1_SOURCES += \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/mmc/mmc.c \
+ drivers/synopsys/emmc/dw_mmc.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_block.c \
+ drivers/gpio/gpio.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ plat/hisilicon/poplar/bl1_plat_setup.c \
+ plat/hisilicon/poplar/plat_storage.c
+
+BL2_SOURCES += \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/mmc/mmc.c \
+ drivers/synopsys/emmc/dw_mmc.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/gpio/gpio.c \
+ drivers/io/io_memmap.c \
+ plat/hisilicon/poplar/bl2_plat_setup.c \
+ plat/hisilicon/poplar/plat_storage.c
+
+BL2_SOURCES += \
+ plat/hisilicon/poplar/bl2_plat_mem_params_desc.c \
+ plat/hisilicon/poplar/poplar_image_load.c \
+ common/desc_image_load.c
+
+ifeq (${SPD},opteed)
+BL2_SOURCES += \
+ lib/optee/optee_utils.c
+endif
+
+BL31_SOURCES += \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/hisilicon/poplar/bl31_plat_setup.c \
+ plat/hisilicon/poplar/plat_topology.c \
+ plat/hisilicon/poplar/plat_pm.c
diff --git a/plat/hisilicon/poplar/poplar_gicv2.c b/plat/hisilicon/poplar/poplar_gicv2.c
new file mode 100644
index 0000000..59f7b76
--- /dev/null
+++ b/plat/hisilicon/poplar/poplar_gicv2.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <drivers/arm/gicv2.h>
+#include <plat/common/platform.h>
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t poplar_interrupt_props[] = {
+ POPLAR_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ POPLAR_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const gicv2_driver_data_t poplar_gic_data = {
+ .gicd_base = POPLAR_GICD_BASE,
+ .gicc_base = POPLAR_GICC_BASE,
+ .interrupt_props = poplar_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(poplar_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/******************************************************************************
+ * Helper to initialize the GICv2 only driver.
+ *****************************************************************************/
+void poplar_gic_driver_init(void)
+{
+ gicv2_driver_init(&poplar_gic_data);
+}
+
+void poplar_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * Helper to enable the GICv2 CPU interface
+ *****************************************************************************/
+void poplar_gic_cpuif_enable(void)
+{
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * Helper to initialize the per cpu distributor interface in GICv2
+ *****************************************************************************/
+void poplar_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+}
diff --git a/plat/hisilicon/poplar/poplar_image_load.c b/plat/hisilicon/poplar/poplar_image_load.c
new file mode 100644
index 0000000..0ab1ca4
--- /dev/null
+++ b/plat/hisilicon/poplar/poplar_image_load.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}