Merge pull request #1029 from islmit01/im/fix_includes

Fix order of includes
diff --git a/docs/plat/hikey.rst b/docs/plat/hikey.rst
index 027e14c..125941f 100644
--- a/docs/plat/hikey.rst
+++ b/docs/plat/hikey.rst
@@ -14,6 +14,9 @@
 -  ARM Trusted Firmware:
    `link <https://github.com/ARM-software/arm-trusted-firmware>`__
 
+-  OP-TEE
+   `link <https://github.com/OP-TEE/optee_os>`__
+
 -  edk2:
    `link <https://github.com/96boards-hikey/edk2/tree/testing/hikey960_v2.5>`__
 
@@ -24,7 +27,7 @@
    `link <https://github.com/96boards-hikey/l-loader/tree/testing/hikey960_v1.2>`__
 
 -  uefi-tools:
-   `link <https://github.com/96boards-hikey/uefi-tools/tree/testing/hikey960_v1>`__
+   `link <https://git.linaro.org/uefi/uefi-tools.git>`__
 
 -  atf-fastboot:
    `link <https://github.com/96boards-hikey/atf-fastboot/tree/master>`__
@@ -70,13 +73,11 @@
        FASTBOOT_BUILD_OPTION=$(echo ${BUILD_OPTION} | tr '[A-Z]' '[a-z]')
        cd ${EDK2_DIR}
        # Build UEFI & ARM Trust Firmware
-       ${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware hikey
+       ${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware -s ../optee_os hikey
        # Generate l-loader.bin
        cd ${BUILD_PATH}/l-loader
        ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin
-       ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin
        ln -sf ${BUILD_PATH}/atf-fastboot/build/hikey/${FASTBOOT_BUILD_OPTION}/bl1.bin fastboot.bin
-       python gen_loader.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd
        arm-linux-gnueabihf-gcc -c -o start.o start.S
        arm-linux-gnueabihf-ld -Bstatic -Tl-loader.lds -Ttext 0xf9800800 start.o -o loader
        arm-linux-gnueabihf-objcopy -O binary loader temp
@@ -86,7 +87,7 @@
 
    .. code:: shell
 
-       $PTABLE=aosp-4g SECTOR_SIZE=512 bash -x generate_ptable.sh
+       PTABLE=aosp-4g SECTOR_SIZE=512 bash -x generate_ptable.sh
 
 Setup Console
 -------------
@@ -110,6 +111,13 @@
 
        2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner
 
+-  Start ser2net
+
+   .. code:: shell
+
+       $sudo killall ser2net
+       $sudo ser2net -u
+
 -  Open the console.
 
    .. code:: shell
diff --git a/docs/plat/hikey960.rst b/docs/plat/hikey960.rst
index c28ef3a..cd1880e 100644
--- a/docs/plat/hikey960.rst
+++ b/docs/plat/hikey960.rst
@@ -14,6 +14,9 @@
 -  ARM Trusted Firmware:
    `link <https://github.com/ARM-software/arm-trusted-firmware>`__
 
+-  OP-TEE:
+   `link <https://github.com/OP-TEE/optee_os>`__
+
 -  edk2:
    `link <https://github.com/96boards-hikey/edk2/tree/testing/hikey960_v2.5>`__
 
@@ -24,7 +27,7 @@
    `link <https://github.com/96boards-hikey/l-loader/tree/testing/hikey960_v1.2>`__
 
 -  uefi-tools:
-   `link <https://github.com/96boards-hikey/uefi-tools/tree/hikey960_v1>`__
+   `link <https://git.linaro.org/uefi/uefi-tools.git>`__
 
 Build Procedure
 ---------------
@@ -56,26 +59,26 @@
    .. code:: shell
 
        BUILD_OPTION=DEBUG
-       export AARCH64_TOOLCHAIN=GCC48
+       export AARCH64_TOOLCHAIN=GCC5
        export UEFI_TOOLS_DIR=${BUILD_PATH}/uefi-tools
        export EDK2_DIR=${BUILD_PATH}/edk2
        EDK2_OUTPUT_DIR=${EDK2_DIR}/Build/HiKey960/${BUILD_OPTION}_${AARCH64_TOOLCHAIN}
        cd ${EDK2_DIR}
        # Build UEFI & ARM Trust Firmware
-       ${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware hikey960
+       ${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware -s ../optee_os hikey960
        # Generate l-loader.bin
        cd ${BUILD_PATH}/l-loader
        ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin
        ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin
        ln -sf ${EDK2_OUTPUT_DIR}/FV/BL33_AP_UEFI.fd
-       python gen_loader.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd
+       python gen_loader_hikey960.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd
 
 -  Generate partition table.
    *Make sure that you're using the sgdisk in the l-loader directory.*
 
    .. code:: shell
 
-       $PTABLE=aosp-32g SECTOR_SIZE=4096 SGDISK=./sgdisk bash -x generate_ptable.sh
+       PTABLE=aosp-32g SECTOR_SIZE=4096 SGDISK=./sgdisk bash -x generate_ptable.sh
 
 Setup Console
 -------------
@@ -99,6 +102,13 @@
 
        2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner
 
+-  Start ser2net
+
+   .. code:: shell
+
+       $sudo killall ser2net
+       $sudo ser2net -u
+
 -  Open the console.
 
    .. code:: shell
@@ -126,7 +136,7 @@
 
        $vi config
        # The content of config file
-       ./sec_user_xloader.img 0x00020000
+       ./sec_usb_xloader.img 0x00020000
        ./sec_uce_boot.img 0x6A908000
        ./l-loader.bin 0x1AC00000
 
diff --git a/docs/plat/poplar.rst b/docs/plat/poplar.rst
new file mode 100644
index 0000000..d7f1fe0
--- /dev/null
+++ b/docs/plat/poplar.rst
@@ -0,0 +1,165 @@
+Description
+===========
+
+Poplar is the first development board compliant with the 96Boards Enterprise
+Edition TV Platform specification.
+
+The board features the Hi3798C V200 with an integrated quad-core 64-bit
+ARM Cortex A53 processor and high performance Mali T720 GPU, making it capable
+of running any commercial set-top solution based on Linux or Android.
+
+It supports a premium user experience with up to H.265 HEVC decoding of 4K
+video at 60 frames per second.
+
+    SOC Hisilicon Hi3798CV200
+    CPU Quad-core ARM Cortex-A53 64 bit
+    DRAM DDR3/3L/4 SDRAM interface, maximum 32-bit data width 2 GB
+    USB Two USB 2.0 ports One USB 3.0 ports
+    CONSOLE USB-micro port for console support
+    ETHERNET 1 GBe Ethernet
+    PCIE One PCIe 2.0 interfaces
+    JTAG 8-Pin JTAG
+    EXPANSION INTERFACE Linaro 96Boards Low Speed Expansion slot
+    DIMENSION Standard 160×120 mm 96Boards Enterprice Edition form factor
+    WIFI 802.11AC 2*2 with Bluetooth
+    CONNECTORS One connector for Smart Card One connector for TSI
+
+At the start of the boot sequence, the bootROM executes the so called l-loader
+binary whose main role is to change the processor state to 64bit mode. This
+must  happen prior invoking the arm trusted  firmware:
+
+    l-loader --> arm_trusted_firmware --> u-boot
+
+How to build
+============
+
+Code Locations
+--------------
+
+-  ARM Trusted Firmware:
+   `link <https://github.com/ARM-software/arm-trusted-firmware>`__
+
+-  l-loader:
+   `link <https://github.com/Linaro/poplar-l-loader.git>`__
+
+-  u-boot:
+   `link <http://git.denx.de/u-boot.git>`__
+
+Build Procedure
+---------------
+
+-  Fetch all the above 3 repositories into local host.
+   Make all the repositories in the same ${BUILD\_PATH}.
+
+-  Prepare the AARCH64 toolchain.
+
+-  Build u-boot using poplar_defconfig
+       make CROSS_COMPILE=aarch64-linux-gnu- poplar_defconfig
+       make CROSS_COMPILE=aarch64-linux-gnu-
+
+-  Build atf providing the previously generated u-boot.bin as the BL33 image
+       make CROSS_COMPILE=aarch64-linux-gnu-  all fip SPD=none PLAT=poplar
+       BL33=u-boot.bin
+
+-  Build l-loader (generated the final fastboot.bin)
+       1. copy the atf generated files fip.bin and bl1.bin to l-loader/atf/
+       2. export ARM_TRUSTED_FIRMWARE=${ATF_SOURCE_PATH)
+       3. make
+
+Install Procedure
+-----------------
+
+- Copy l-loader/fastboot.bin to a FAT partition on a USB pen drive.
+
+- Plug the USB pen drive to any of the USB2 ports
+
+- Power the board while keeping S3 pressed (usb_boot)
+
+The system will boot into a u-boot shell which you can then use to write the
+working firmware to eMMC.
+
+Boot trace
+==========
+
+Bootrom start
+Boot Media: eMMC
+Decrypt auxiliary code ...OK
+
+lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000
+
+Entry boot auxiliary code
+
+Auxiliary code - v1.00
+DDR code - V1.1.2 20160205
+Build: Mar 24 2016 - 17:09:44
+Reg Version:  v134
+Reg Time:     2016/03/18 09:44:55
+Reg Name:     hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg
+
+Boot auxiliary code success
+Bootrom success
+
+LOADER:  Switched to aarch64 mode
+LOADER:  Entering ARM TRUSTED FIRMWARE
+LOADER:  CPU0 executes at 0x000ce000
+
+INFO:    BL1: 0xe1000 - 0xe7000 [size = 24576]
+NOTICE:  Booting Trusted Firmware
+NOTICE:  BL1: v1.3(debug):v1.3-372-g1ba9c60
+NOTICE:  BL1: Built : 17:51:33, Apr 30 2017
+INFO:    BL1: RAM 0xe1000 - 0xe7000
+INFO:    BL1: Loading BL2
+INFO:    Loading image id=1 at address 0xe9000
+INFO:    Image id=1 loaded at address 0xe9000, size = 0x5008
+NOTICE:  BL1: Booting BL2
+INFO:    Entry point address = 0xe9000
+INFO:    SPSR = 0x3c5
+NOTICE:  BL2: v1.3(debug):v1.3-372-g1ba9c60
+NOTICE:  BL2: Built : 17:51:33, Apr 30 2017
+INFO:    BL2: Loading BL31
+INFO:    Loading image id=3 at address 0x129000
+INFO:    Image id=3 loaded at address 0x129000, size = 0x8038
+INFO:    BL2: Loading BL33
+INFO:    Loading image id=5 at address 0x37000000
+INFO:    Image id=5 loaded at address 0x37000000, size = 0x58f17
+NOTICE:  BL1: Booting BL31
+INFO:    Entry point address = 0x129000
+INFO:    SPSR = 0x3cd
+INFO:    Boot bl33 from 0x37000000 for 364311 Bytes
+NOTICE:  BL31: v1.3(debug):v1.3-372-g1ba9c60
+NOTICE:  BL31: Built : 17:51:33, Apr 30 2017
+INFO:    BL31: Initializing runtime services
+INFO:    BL31: Preparing for EL3 exit to normal world
+INFO:    Entry point address = 0x37000000
+INFO:    SPSR = 0x3c9
+
+
+U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar
+
+Model: HiSilicon Poplar Development Board
+BOARD: Hisilicon HI3798cv200 Poplar
+DRAM:  1 GiB
+MMC:   Hisilicon DWMMC: 0
+In:    serial@f8b00000
+Out:   serial@f8b00000
+Err:   serial@f8b00000
+Net:   Net Initialization Skipped
+No ethernet found.
+
+Hit any key to stop autoboot:  0
+starting USB...
+USB0:   USB EHCI 1.00
+scanning bus 0 for devices... 1 USB Device(s) found
+USB1:   USB EHCI 1.00
+scanning bus 1 for devices... 4 USB Device(s) found
+       scanning usb for storage devices... 1 Storage Device(s) found
+       scanning usb for ethernet devices... 1 Ethernet Device(s) found
+
+USB device 0:
+    Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade
+            Type: Removable Hard Disk
+            Capacity: 7632.0 MB = 7.4 GB (15630336 x 512)
+... is now current device
+Scanning usb 0:1...
+=>
+
diff --git a/plat/hisilicon/hikey/aarch64/hikey_common.c b/plat/hisilicon/hikey/aarch64/hikey_common.c
index d8a68cf..20a95bf 100644
--- a/plat/hisilicon/hikey/aarch64/hikey_common.c
+++ b/plat/hisilicon/hikey/aarch64/hikey_common.c
@@ -24,6 +24,10 @@
 					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)
+
 #define MAP_ROM_PARAM	MAP_REGION_FLAT(XG2RAM0_BASE,			\
 					BL1_XG2RAM0_OFFSET,		\
 					MT_DEVICE | MT_RO | MT_SECURE)
@@ -59,6 +63,7 @@
 static const mmap_region_t hikey_mmap[] = {
 	MAP_DDR,
 	MAP_DEVICE,
+	MAP_TSP_MEM,
 	{0}
 };
 #endif
@@ -67,6 +72,15 @@
 static const mmap_region_t hikey_mmap[] = {
 	MAP_DEVICE,
 	MAP_SRAM,
+	MAP_TSP_MEM,
+	{0}
+};
+#endif
+
+#if IMAGE_BL32
+static const mmap_region_t hikey_mmap[] = {
+	MAP_DEVICE,
+	MAP_DDR,
 	{0}
 };
 #endif
diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c
index 9e9909b..13dc6c9 100644
--- a/plat/hisilicon/hikey/hikey_bl2_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl2_setup.c
@@ -144,6 +144,41 @@
 				       DISABLE_ALL_EXCEPTIONS);
 }
 
+/*******************************************************************************
+ * Before calling this function BL32 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL32 and set SPSR and security state.
+ * On Hikey we only set the security state of the entrypoint
+ ******************************************************************************/
+#ifdef BL32_BASE
+void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
+					entry_point_info_t *bl32_ep_info)
+{
+	SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+	/*
+	 * The Secure Payload Dispatcher service is responsible for
+	 * setting the SPSR prior to entry into the BL32 image.
+	 */
+	bl32_ep_info->spsr = 0;
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL32
+ ******************************************************************************/
+void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
+{
+	/*
+	 * Populate the extents of memory available for loading BL32.
+	 */
+	bl32_meminfo->total_base = BL32_BASE;
+	bl32_meminfo->free_base = BL32_BASE;
+	bl32_meminfo->total_size =
+			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+	bl32_meminfo->free_size =
+			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+#endif /* BL32_BASE */
+
 void bl2_plat_set_bl33_ep_info(image_info_t *image,
 			       entry_point_info_t *bl33_ep_info)
 {
diff --git a/plat/hisilicon/hikey/hikey_def.h b/plat/hisilicon/hikey/hikey_def.h
index 28ff553..bbad10f 100644
--- a/plat/hisilicon/hikey/hikey_def.h
+++ b/plat/hisilicon/hikey/hikey_def.h
@@ -12,7 +12,7 @@
 
 /* Always assume DDR is 1GB size. */
 #define DDR_BASE			0x0
-#define DDR_SIZE			0x80000000
+#define DDR_SIZE			0x40000000
 
 #define DEVICE_BASE			0xF4000000
 #define DEVICE_SIZE			0x05800000
@@ -20,6 +20,25 @@
 #define XG2RAM0_BASE			0xF9800000
 #define XG2RAM0_SIZE			0x00400000
 
+/* Memory location options for TSP */
+#define HIKEY_SRAM_ID		0
+#define HIKEY_DRAM_ID		1
+
+/*
+ * DDR for OP-TEE (32MB from 0x3E00000-0x3FFFFFFF) is divided in several
+ * regions
+ *   - Secure DDR (default is the top 16MB) used by OP-TEE
+ *   - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB)
+ *   - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature
+ *   - Non-secure DDR (8MB) reserved for OP-TEE's future use
+ */
+#define DDR_SEC_SIZE			0x01000000
+#define DDR_SEC_BASE			(DDR_BASE + DDR_SIZE - DDR_SEC_SIZE)
+
+#define DDR_SDP_SIZE			0x00400000
+#define DDR_SDP_BASE			(DDR_SEC_BASE - 0x400000 /* align */ - \
+					DDR_SDP_SIZE)
+
 #define SRAM_BASE			0xFFF80000
 #define SRAM_SIZE			0x00012000
 
diff --git a/plat/hisilicon/hikey/hikey_io_storage.c b/plat/hisilicon/hikey/hikey_io_storage.c
index 4ca1846..c61ec2c 100644
--- a/plat/hisilicon/hikey/hikey_io_storage.c
+++ b/plat/hisilicon/hikey/hikey_io_storage.c
@@ -73,6 +73,10 @@
 	.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 bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -102,6 +106,11 @@
 		(uintptr_t)&bl31_uuid_spec,
 		check_fip
 	},
+	[BL32_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_uuid_spec,
+		check_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/hisilicon/hikey/include/platform_def.h b/plat/hisilicon/hikey/include/platform_def.h
index a91a9b0..af15232 100644
--- a/plat/hisilicon/hikey/include/platform_def.h
+++ b/plat/hisilicon/hikey/include/platform_def.h
@@ -11,13 +11,6 @@
 #include "../hikey_def.h"
 
 /*
- * Platform binary types for linking
- */
-#define PLATFORM_LINKER_FORMAT          "elf64-littleaarch64"
-#define PLATFORM_LINKER_ARCH            aarch64
-
-
-/*
  * Generic platform constants
  */
 
@@ -104,6 +97,33 @@
 #define BL31_BASE			BL2_LIMIT
 #define BL31_LIMIT			0xF9898000
 
+/*
+ * BL3-2 specific defines.
+ */
+
+/*
+ * The TSP currently executes from TZC secured area of DRAM or SRAM.
+ */
+#define BL32_SRAM_BASE			BL31_LIMIT
+#define BL32_SRAM_LIMIT			(BL31_LIMIT+0x80000) /* 512K */
+
+#define BL32_DRAM_BASE			DDR_SEC_BASE
+#define BL32_DRAM_LIMIT			(DDR_SEC_BASE+DDR_SEC_SIZE)
+
+#if (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_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 (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_SRAM_ID)
+#define TSP_SEC_MEM_BASE		BL32_SRAM_BASE
+#define TSP_SEC_MEM_SIZE		(BL32_SRAM_LIMIT - BL32_SRAM_BASE)
+#define BL32_BASE			BL32_SRAM_BASE
+#define BL32_LIMIT			BL32_SRAM_LIMIT
+#else
+#error "Currently unsupported HIKEY_TSP_LOCATION_ID value"
+#endif
+
 #define NS_BL1U_BASE			(BL2_BASE)
 #define NS_BL1U_SIZE			(0x00010000)
 #define NS_BL1U_LIMIT			(NS_BL1U_BASE + NS_BL1U_SIZE)
@@ -113,10 +133,14 @@
  */
 #define ADDR_SPACE_SIZE			(1ull << 32)
 
-#if IMAGE_BL1 || IMAGE_BL2 || IMAGE_BL31
+#if IMAGE_BL1 || IMAGE_BL2 || IMAGE_BL32
 #define MAX_XLAT_TABLES			3
 #endif
 
+#if IMAGE_BL31
+#define MAX_XLAT_TABLES			4
+#endif
+
 #define MAX_MMAP_REGIONS		16
 
 #define HIKEY_NS_IMAGE_OFFSET		(DDR_BASE + 0x35000000)
diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk
index 08a3047..8da3998 100644
--- a/plat/hisilicon/hikey/platform.mk
+++ b/plat/hisilicon/hikey/platform.mk
@@ -4,6 +4,17 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# On Hikey, the TSP can execute from TZC secure area in DRAM (default)
+# or SRAM.
+HIKEY_TSP_RAM_LOCATION	:=	dram
+ifeq (${HIKEY_TSP_RAM_LOCATION}, dram)
+  HIKEY_TSP_RAM_LOCATION_ID = HIKEY_DRAM_ID
+else ifeq (${HIKEY_TSP_RAM_LOCATION}, sram)
+  HIKEY_TSP_RAM_LOCATION_ID := HIKEY_SRAM_ID
+else
+  $(error "Currently unsupported HIKEY_TSP_RAM_LOCATION value")
+endif
+
 CONSOLE_BASE			:=	PL011_UART3_BASE
 CRASH_CONSOLE_BASE		:=	PL011_UART3_BASE
 PLAT_PARTITION_MAX_ENTRIES	:=	12
@@ -12,11 +23,11 @@
 PROGRAMMABLE_RESET_ADDRESS	:=	1
 
 # Process flags
+$(eval $(call add_define,HIKEY_TSP_RAM_LOCATION_ID))
 $(eval $(call add_define,CONSOLE_BASE))
 $(eval $(call add_define,CRASH_CONSOLE_BASE))
 $(eval $(call add_define,PLAT_PL061_MAX_GPIOS))
 $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
-$(eval $(call FIP_ADD_IMG,SCP_BL2,--scp-fw))
 
 ENABLE_PLAT_COMPAT	:=	0
 
diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_common.c b/plat/hisilicon/hikey960/aarch64/hikey960_common.c
index d7894b3..7068fb6 100644
--- a/plat/hisilicon/hikey960/aarch64/hikey960_common.c
+++ b/plat/hisilicon/hikey960/aarch64/hikey960_common.c
@@ -37,6 +37,10 @@
 					HIKEY960_UFS_DESC_SIZE,		\
 					MT_MEMORY | MT_RW | MT_NS)
 
+#define MAP_TSP_MEM	MAP_REGION_FLAT(TSP_SEC_MEM_BASE,		\
+					TSP_SEC_MEM_SIZE,		\
+					MT_MEMORY | MT_RW | MT_SECURE)
+
 /*
  * Table of regions for different BL stages to map using the MMU.
  * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
@@ -56,6 +60,7 @@
 static const mmap_region_t hikey960_mmap[] = {
 	MAP_DDR,
 	MAP_DEVICE,
+	MAP_TSP_MEM,
 	{0}
 };
 #endif
@@ -63,6 +68,15 @@
 #if IMAGE_BL31
 static const mmap_region_t hikey960_mmap[] = {
 	MAP_DEVICE,
+	MAP_TSP_MEM,
+	{0}
+};
+#endif
+
+#if IMAGE_BL32
+static const mmap_region_t hikey960_mmap[] = {
+	MAP_DEVICE,
+	MAP_DDR,
 	{0}
 };
 #endif
diff --git a/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
index e225793..de676a7 100644
--- a/plat/hisilicon/hikey960/hikey960_bl2_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
@@ -177,6 +177,41 @@
 				       DISABLE_ALL_EXCEPTIONS);
 }
 
+/*******************************************************************************
+ * Before calling this function BL32 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL32 and set SPSR and security state.
+ * On Hikey we only set the security state of the entrypoint
+ ******************************************************************************/
+#ifdef BL32_BASE
+void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
+					entry_point_info_t *bl32_ep_info)
+{
+	SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+	/*
+	 * The Secure Payload Dispatcher service is responsible for
+	 * setting the SPSR prior to entry into the BL32 image.
+	 */
+	bl32_ep_info->spsr = 0;
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL32
+ ******************************************************************************/
+void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
+{
+	/*
+	 * Populate the extents of memory available for loading BL32.
+	 */
+	bl32_meminfo->total_base = BL32_BASE;
+	bl32_meminfo->free_base = BL32_BASE;
+	bl32_meminfo->total_size =
+			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+	bl32_meminfo->free_size =
+			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+#endif /* BL32_BASE */
+
 void bl2_plat_set_bl33_ep_info(image_info_t *image,
 			       entry_point_info_t *bl33_ep_info)
 {
diff --git a/plat/hisilicon/hikey960/hikey960_def.h b/plat/hisilicon/hikey960/hikey960_def.h
index e713e2e..fc46d71 100644
--- a/plat/hisilicon/hikey960/hikey960_def.h
+++ b/plat/hisilicon/hikey960/hikey960_def.h
@@ -16,6 +16,25 @@
 #define DEVICE_BASE			0xE0000000
 #define DEVICE_SIZE			0x20000000
 
+/* Memory location options for TSP */
+#define HIKEY960_SRAM_ID	0
+#define HIKEY960_DRAM_ID	1
+
+/*
+ * DDR for OP-TEE (32MB from 0x3E00000-0x3FFFFFFF) is divided in several
+ * regions:
+ *   - Secure DDR (default is the top 16MB) used by OP-TEE
+ *   - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB)
+ *   - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature
+ *   - Non-secure DDR (8MB) reserved for OP-TEE's future use
+ */
+#define DDR_SEC_SIZE			0x01000000
+#define DDR_SEC_BASE			0x3F000000
+
+#define DDR_SDP_SIZE			0x00400000
+#define DDR_SDP_BASE			(DDR_SEC_BASE - 0x400000 /* align */ - \
+					DDR_SDP_SIZE)
+
 /*
  * PL011 related constants
  */
diff --git a/plat/hisilicon/hikey960/hikey960_io_storage.c b/plat/hisilicon/hikey960/hikey960_io_storage.c
index de54e88..57d97e5 100644
--- a/plat/hisilicon/hikey960/hikey960_io_storage.c
+++ b/plat/hisilicon/hikey960/hikey960_io_storage.c
@@ -69,6 +69,10 @@
 	.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 bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -94,6 +98,11 @@
 		(uintptr_t)&bl31_uuid_spec,
 		check_fip
 	},
+	[BL32_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_uuid_spec,
+		check_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h
index 369117b..8bf32c3 100644
--- a/plat/hisilicon/hikey960/include/platform_def.h
+++ b/plat/hisilicon/hikey960/include/platform_def.h
@@ -63,6 +63,27 @@
 #define BL31_BASE			(BL2_LIMIT)		/* 1AC5_8000 */
 #define BL31_LIMIT			(BL31_BASE + 0x40000)	/* 1AC9_8000 */
 
+/*
+ * BL3-2 specific defines.
+ */
+
+/*
+ * The TSP currently executes from TZC secured area of DRAM.
+ */
+#define BL32_DRAM_BASE                  DDR_SEC_BASE
+#define BL32_DRAM_LIMIT                 (DDR_SEC_BASE+DDR_SEC_SIZE)
+
+#if (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_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 (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_SRAM_ID)
+#error "SRAM storage of TSP payload is currently unsupported"
+#else
+#error "Currently unsupported HIKEY960_TSP_LOCATION_ID value"
+#endif
+
 #define NS_BL1U_BASE			(BL31_LIMIT)		/* 1AC9_8000 */
 #define NS_BL1U_SIZE			(0x00100000)
 #define NS_BL1U_LIMIT			(NS_BL1U_BASE + NS_BL1U_SIZE)
@@ -70,7 +91,7 @@
 #define HIKEY960_NS_IMAGE_OFFSET	(0x1AC18000)	/* offset in l-loader */
 #define HIKEY960_NS_TMP_OFFSET		(0x1AE00000)
 
-#define SCP_BL2_BASE			BL31_BASE
+#define SCP_BL2_BASE			BL31_BASE /* 1AC5_8000 */
 
 #define SCP_MEM_BASE			(0x89C80000)
 #define SCP_MEM_SIZE			(0x00040000)
@@ -80,7 +101,7 @@
  */
 #define ADDR_SPACE_SIZE			(1ull << 32)
 
-#if IMAGE_BL1 || IMAGE_BL2 || IMAGE_BL31
+#if IMAGE_BL1 || IMAGE_BL2 || IMAGE_BL31 || IMAGE_BL32
 #define MAX_XLAT_TABLES			3
 #endif
 
diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk
index 145eee0..edbce63 100644
--- a/plat/hisilicon/hikey960/platform.mk
+++ b/plat/hisilicon/hikey960/platform.mk
@@ -4,13 +4,23 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# On Hikey960, the TSP can execute from TZC secure area in DRAM.
+HIKEY960_TSP_RAM_LOCATION	:=	dram
+ifeq (${HIKEY960_TSP_RAM_LOCATION}, dram)
+  HIKEY960_TSP_RAM_LOCATION_ID = HIKEY960_DRAM_ID
+else ifeq (${HIKEY960_TSP_RAM_LOCATION}, sram)
+  HIKEY960_TSP_RAM_LOCATION_ID := HIKEY960_SRAM_ID
+else
+  $(error "Currently unsupported HIKEY960_TSP_RAM_LOCATION value")
+endif
+
 CRASH_CONSOLE_BASE		:=	PL011_UART6_BASE
 COLD_BOOT_SINGLE_CPU		:=	1
 PROGRAMMABLE_RESET_ADDRESS	:=	1
 
 # Process flags
+$(eval $(call add_define,HIKEY960_TSP_RAM_LOCATION_ID))
 $(eval $(call add_define,CRASH_CONSOLE_BASE))
-$(eval $(call FIP_ADD_IMG,SCP_BL2,--scp-fw))
 
 ENABLE_PLAT_COMPAT	:=	0
 
@@ -63,3 +73,8 @@
 				plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c \
 				plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c \
 				${HIKEY960_GIC_SOURCES}
+
+# Enable workarounds for selected Cortex-A53 errata.
+ERRATA_A53_836870		:=	1
+ERRATA_A53_843419		:=	1
+ERRATA_A53_855873		:=	1
diff --git a/plat/hisilicon/poplar/aarch64/platform_common.c b/plat/hisilicon/poplar/aarch64/platform_common.c
new file mode 100644
index 0000000..a7dac4f
--- /dev/null
+++ b/plat/hisilicon/poplar/aarch64/platform_common.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <platform.h>
+#include <xlat_tables.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)
+
+static const mmap_region_t poplar_mmap[] = {
+	MAP_DDR,
+	MAP_DEVICE,
+	{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/bl1_plat_setup.c b/plat/hisilicon/poplar/bl1_plat_setup.c
new file mode 100644
index 0000000..c65e29e
--- /dev/null
+++ b/plat/hisilicon/poplar/bl1_plat_setup.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <generic_delay_timer.h>
+#include <mmio.h>
+#include <pl061_gpio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <tbbr_img_def.h>
+#include "../../bl1/bl1_private.h"
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+/* Symbols from link script for conherent section */
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+#define BL1_COHERENT_RAM_BASE	(unsigned long)(&__COHERENT_RAM_START__)
+#define BL1_COHERENT_RAM_LIMIT	(unsigned long)(&__COHERENT_RAM_END__)
+
+/* Data structure which holds the extents of the trusted RAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+	return &bl1_tzram_layout;
+}
+
+void bl1_early_platform_setup(void)
+{
+	/* Initialize the console to provide early debug support */
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+	/* Allow BL1 to see the whole Trusted RAM */
+	bl1_tzram_layout.total_base = BL_MEM_BASE;
+	bl1_tzram_layout.total_size = BL_MEM_SIZE;
+
+	/* Calculate how much RAM BL1 is using and how much remains free */
+	bl1_tzram_layout.free_base = BL_MEM_BASE;
+	bl1_tzram_layout.free_size = BL_MEM_SIZE;
+
+	reserve_mem(&bl1_tzram_layout.free_base,
+		    &bl1_tzram_layout.free_size,
+		    BL1_RAM_BASE,
+		    BL1_RAM_LIMIT - BL1_RAM_BASE);
+
+	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,
+			       BL_MEM_BASE, /* l-loader and BL1 ROM */
+			       BL1_RO_LIMIT,
+			       BL1_COHERENT_RAM_BASE,
+			       BL1_COHERENT_RAM_LIMIT);
+}
+
+void bl1_platform_setup(void)
+{
+	int i;
+
+	generic_delay_timer_init();
+
+	pl061_gpio_init();
+	for (i = 0; i < GPIO_MAX; i++)
+		pl061_gpio_register(GPIO_BASE(i), i);
+
+	plat_io_setup();
+}
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+	return BL2_IMAGE_ID;
+}
diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c
new file mode 100644
index 0000000..1741475
--- /dev/null
+++ b/plat/hisilicon/poplar/bl2_plat_setup.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <generic_delay_timer.h>
+#include <mmio.h>
+#include <partition/partition.h>
+#include <platform.h>
+#include <string.h>
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+/* Memory ranges for code and read only data sections */
+#define BL2_RO_BASE	(unsigned long)(&__RO_START__)
+#define BL2_RO_LIMIT	(unsigned long)(&__RO_END__)
+
+/* Memory ranges for coherent memory section */
+#define BL2_COHERENT_RAM_BASE	(unsigned long)(&__COHERENT_RAM_START__)
+#define BL2_COHERENT_RAM_LIMIT	(unsigned long)(&__COHERENT_RAM_END__)
+
+typedef struct bl2_to_bl31_params_mem {
+	bl31_params_t		bl31_params;
+	image_info_t		bl31_image_info;
+	image_info_t		bl33_image_info;
+	entry_point_info_t	bl33_ep_info;
+	entry_point_info_t	bl31_ep_info;
+} bl2_to_bl31_params_mem_t;
+
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+static bl2_to_bl31_params_mem_t bl31_params_mem;
+
+meminfo_t *bl2_plat_sec_mem_layout(void)
+{
+	return &bl2_tzram_layout;
+}
+
+bl31_params_t *bl2_plat_get_bl31_params(void)
+{
+	bl31_params_t *bl2_to_bl31_params = NULL;
+
+	/*
+	 * Initialise the memory for all the arguments that needs to
+	 * be passed to BL3-1
+	 */
+	memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t));
+
+	/* Assign memory for TF related information */
+	bl2_to_bl31_params = &bl31_params_mem.bl31_params;
+	SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0);
+
+	/* Fill BL3-1 related information */
+	bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info,
+		       PARAM_IMAGE_BINARY, VERSION_1, 0);
+
+	/* Fill BL3-3 related information */
+	bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
+		       PARAM_EP, VERSION_1, 0);
+
+	/* BL3-3 expects to receive the primary CPU MPID (through x0) */
+	bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
+
+	bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info,
+		       PARAM_IMAGE_BINARY, VERSION_1, 0);
+
+	return bl2_to_bl31_params;
+}
+
+struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
+{
+	return &bl31_params_mem.bl31_ep_info;
+}
+
+void bl2_plat_set_bl31_ep_info(image_info_t *image,
+			       entry_point_info_t *bl31_ep_info)
+{
+	SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
+	bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+				     DISABLE_ALL_EXCEPTIONS);
+}
+
+static uint32_t hisi_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;
+}
+
+void bl2_plat_set_bl33_ep_info(image_info_t *image,
+			       entry_point_info_t *bl33_ep_info)
+{
+	SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
+	bl33_ep_info->spsr = hisi_get_spsr_for_bl33_entry();
+	bl33_ep_info->args.arg2 = image->image_size;
+}
+
+void bl2_plat_flush_bl31_params(void)
+{
+	flush_dcache_range((unsigned long)&bl31_params_mem,
+			   sizeof(bl2_to_bl31_params_mem_t));
+}
+
+void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
+{
+	bl33_meminfo->total_base = DDR_BASE;
+	bl33_meminfo->total_size = DDR_SIZE;
+	bl33_meminfo->free_base  = DDR_BASE;
+	bl33_meminfo->free_size  = DDR_SIZE;
+}
+
+void bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+	/* Enable arch timer */
+	generic_delay_timer_init();
+
+	bl2_tzram_layout = *mem_layout;
+}
+
+void bl2_plat_arch_setup(void)
+{
+	plat_configure_mmu_el1(bl2_tzram_layout.total_base,
+			       bl2_tzram_layout.total_size,
+			       BL2_RO_BASE,
+			       BL2_RO_LIMIT,
+			       BL2_COHERENT_RAM_BASE,
+			       BL2_COHERENT_RAM_LIMIT);
+}
+
+void bl2_platform_setup(void)
+{
+	plat_io_setup();
+}
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+	return PLAT_ARM_NS_IMAGE_OFFSET;
+}
diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c
new file mode 100644
index 0000000..b9a0e18
--- /dev/null
+++ b/plat/hisilicon/poplar/bl31_plat_setup.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl31.h>
+#include <bl_common.h>
+#include <console.h>
+#include <cortex_a53.h>
+#include <debug.h>
+#include <errno.h>
+#include <generic_delay_timer.h>
+#include <mmio.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <stddef.h>
+#include <string.h>
+#include "hi3798cv200.h"
+#include "plat_private.h"
+#include "platform_def.h"
+
+/* Memory ranges for code and RO data sections */
+#define BL31_RO_BASE	(unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT	(unsigned long)(&__RO_END__)
+
+/* Memory ranges for coherent memory section */
+#define BL31_COHERENT_RAM_BASE	(unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT	(unsigned long)(&__COHERENT_RAM_END__)
+
+static entry_point_info_t bl33_image_ep_info;
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	return &bl33_image_ep_info;
+}
+
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+			       void *plat_params_from_bl2)
+{
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+	/* Init console for crash report */
+	plat_crash_console_init();
+
+	bl33_image_ep_info = *from_bl2->bl33_ep_info;
+}
+
+void bl31_platform_setup(void)
+{
+	/* Init arch timer */
+	generic_delay_timer_init();
+
+	/* Init GIC distributor and CPU interface */
+	plat_arm_gic_driver_init();
+	plat_arm_gic_init();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+	/* do nothing */
+}
+
+void bl31_plat_arch_setup(void)
+{
+	plat_configure_mmu_el3(BL31_RO_BASE,
+			       (BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE),
+			       BL31_RO_BASE,
+			       BL31_RO_LIMIT,
+			       BL31_COHERENT_RAM_BASE,
+			       BL31_COHERENT_RAM_LIMIT);
+
+	INFO("Boot BL33 from 0x%lx for %lu 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..6318b9c
--- /dev/null
+++ b/plat/hisilicon/poplar/include/hi3798cv200.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __HI3798cv200_H__
+#define __HI3798cv200_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			(12)
+#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			(0xF0000)
+#define EMMC_INIT_PARAMS(base)				\
+	{	.bus_width = EMMC_BUS_WIDTH_8,		\
+		.clk_rate = 25 * 1000 * 1000,		\
+		.desc_base = (base) - EMMC_DESC_SIZE,	\
+		.desc_size = EMMC_DESC_SIZE,		\
+		.flags =  EMMC_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)
+
+#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..e2272cc
--- /dev/null
+++ b/plat/hisilicon/poplar/include/plat_private.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_PRIVATE_H__
+#define __PLAT_PRIVATE_H__
+
+#include <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_delay_timer_init(void);
+void plat_io_setup(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..1b44dd7
--- /dev/null
+++ b/plat/hisilicon/poplar/include/platform_def.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017, 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_def.h>
+#include <tbbr/tbbr_img_def.h>
+#include "hi3798cv200.h"
+#include "poplar_layout.h"		/* BL memory region sizes, etc */
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define PLAT_ARM_CRASH_UART_BASE	PL011_UART0_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ	PL011_UART0_CLK_IN_HZ
+#define ARM_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		(1)
+#define PLATFORM_CORE_COUNT		(4)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	(4)
+
+/* IO framework user */
+#define MAX_IO_DEVICES			(4)
+#define MAX_IO_HANDLES			(4)
+#define MAX_IO_BLOCK_DEVICES		(2)
+
+/* Memory map related constants */
+#define DDR_BASE			(0x00000000)
+#define DDR_SIZE			(0x40000000)
+
+#define DEVICE_BASE			(0xF0000000)
+#define DEVICE_SIZE			(0x0F000000)
+
+#define TEE_SEC_MEM_BASE		(0x70000000)
+#define TEE_SEC_MEM_SIZE		(0x10000000)
+
+#define BL_MEM_BASE			(BL1_RO_BASE)
+#define BL_MEM_LIMIT			(BL31_LIMIT)
+#define BL_MEM_SIZE			(BL_MEM_LIMIT - BL_MEM_BASE)
+
+#define PLAT_ARM_NS_IMAGE_OFFSET	0x37000000
+
+/* Page table and MMU setup constants */
+#define 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		2
+#define PLAT_MAX_RET_STATE		1
+
+/* Interrupt controller */
+#define PLAT_ARM_GICD_BASE	GICD_BASE
+#define PLAT_ARM_GICC_BASE	GICC_BASE
+
+#define PLAT_ARM_G1S_IRQS	HISI_IRQ_SEC_SGI_0,  \
+				HISI_IRQ_SEC_SGI_1,  \
+				HISI_IRQ_SEC_SGI_2,  \
+				HISI_IRQ_SEC_SGI_3,  \
+				HISI_IRQ_SEC_SGI_4,  \
+				HISI_IRQ_SEC_SGI_5,  \
+				HISI_IRQ_SEC_SGI_6,  \
+				HISI_IRQ_SEC_SGI_7,  \
+				HISI_IRQ_SEC_TIMER0, \
+				HISI_IRQ_SEC_TIMER1, \
+				HISI_IRQ_SEC_TIMER2, \
+				HISI_IRQ_SEC_TIMER3, \
+				HISI_IRQ_SEC_AXI
+
+#define PLAT_ARM_G0_IRQS
+
+#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..192bcb9
--- /dev/null
+++ b/plat/hisilicon/poplar/include/poplar_layout.h
@@ -0,0 +1,108 @@
+/*
+ * 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 loads the initial content of
+ * boot media into low memory, verifies it, 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		0x00001000	/* page aligned */
+#define BL1_OFFSET			0x0000D000	/* page multiple */
+#define FIP_BASE			0x00040000
+
+#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			0x0000c000	/* page multiple */
+#define BL31_SIZE			0x00014000
+#define FIP_SIZE			0x00068000
+
+     /* 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..3e43d4d
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_pm.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <mmio.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <psci.h>
+#include "hi3798cv200.h"
+#include "plat_private.h"
+#include "platform_def.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 */
+	plat_arm_gic_pcpu_init();
+
+	/* Program the gic per-cpu distributor or re-distributor interface */
+	plat_arm_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..623a61b
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_storage.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <firmware_image_package.h>
+#include <io_block.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <mmio.h>
+#include <partition/partition.h>
+#include <semihosting.h>
+#include <string.h>
+#include <tbbr_img_def.h>
+#include <utils.h>
+#include "platform_def.h"
+
+static const io_dev_connector_t *mmap_dev_con;
+static const io_dev_connector_t *fip_dev_con;
+
+static uintptr_t mmap_dev_handle;
+static uintptr_t fip_dev_handle;
+
+static int open_mmap(const uintptr_t spec);
+static int open_fip(const uintptr_t spec);
+
+static const io_block_spec_t loader_fip_spec = {
+	.offset		= FIP_BASE,
+	.length		= FIP_SIZE
+};
+
+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 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[] = {
+	[FIP_IMAGE_ID] = {
+		&mmap_dev_handle,
+		(uintptr_t)&loader_fip_spec,
+		open_mmap
+	},
+	[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
+	},
+	[BL33_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl33_uuid_spec,
+		open_fip
+	},
+};
+
+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) {
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+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) {
+			io_close(local_image_handle);
+		} else {
+			VERBOSE("error opening fip\n");
+		}
+	} else {
+		VERBOSE("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;
+
+	result = register_io_dev_memmap(&mmap_dev_con);
+	assert(result == 0);
+
+	result = register_io_dev_fip(&fip_dev_con);
+	assert(result == 0);
+
+	result = io_dev_open(fip_dev_con, (uintptr_t)&loader_fip_spec,
+				&fip_dev_handle);
+	assert(result == 0);
+
+	result = io_dev_open(mmap_dev_con, (uintptr_t)NULL, &mmap_dev_handle);
+	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..3dd818e
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_topology.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <plat_arm.h>
+#include <psci.h>
+#include "platform_def.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 plat_arm_calc_core_pos(mpidr);
+}
diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk
new file mode 100644
index 0000000..fc75ff3
--- /dev/null
+++ b/plat/hisilicon/poplar/platform.mk
@@ -0,0 +1,72 @@
+#
+# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+NEED_BL33			:= yes
+
+COLD_BOOT_SINGLE_CPU		:= 1
+PROGRAMMABLE_RESET_ADDRESS	:= 1
+CTX_INCLUDE_FPREGS		:= 1
+ENABLE_PLAT_COMPAT		:= 0
+ERRATA_A53_855873		:= 1
+ERRATA_A53_835769		:= 1
+ERRATA_A53_843419		:= 1
+
+ARM_GIC_ARCH			:= 2
+$(eval $(call add_define,ARM_GIC_ARCH))
+
+PLAT_PL061_MAX_GPIOS 		:= 104
+$(eval $(call add_define,PLAT_PL061_MAX_GPIOS))
+
+PLAT_INCLUDES	:=	-Iplat/hisilicon/poplar/include		\
+			-Iinclude/plat/arm/common/		\
+			-Iplat/hisilicon/poplar			\
+			-Iinclude/common/tbbr			\
+			-Iinclude/drivers/io
+
+PLAT_BL_COMMON_SOURCES	:=						\
+		lib/aarch64/xlat_tables.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/pl011_console.S			\
+		drivers/arm/gic/v2/gicv2_main.c				\
+		plat/arm/common/aarch64/arm_helpers.S			\
+		plat/arm/common/arm_gicv2.c				\
+		plat/common/plat_gicv2.c				\
+		plat/hisilicon/poplar/aarch64/platform_common.c
+
+BL1_SOURCES	+=							\
+		lib/cpus/aarch64/cortex_a53.S				\
+		drivers/arm/pl061/pl061_gpio.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/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
+
+
+BL31_SOURCES	+=							\
+		lib/cpus/aarch64/aem_generic.S				\
+		lib/cpus/aarch64/cortex_a53.S				\
+		plat/common/aarch64/plat_psci_common.c			\
+		plat/hisilicon/poplar/bl31_plat_setup.c			\
+		plat/hisilicon/poplar/plat_topology.c			\
+		plat/hisilicon/poplar/plat_pm.c
+