Merge pull request #1623 from MISL-EBU-System-SW/a3700-support

Add support for Armada 3700 and COMPHY porting layer
diff --git a/Makefile b/Makefile
index 8cba50c..74d5180 100644
--- a/Makefile
+++ b/Makefile
@@ -78,12 +78,12 @@
         CHECKCODE_ARGS	+=	--no-summary --terse
 else
         Q:=
-        ECHO:=@\#
+        ECHO:=$(ECHO_QUIET)
 endif
 
 ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),)
         Q:=@
-        ECHO:=@\#
+        ECHO:=$(ECHO_QUIET)
 endif
 
 export Q ECHO
@@ -205,11 +205,6 @@
 				-Os -ffunction-sections -fdata-sections
 
 GCC_V_OUTPUT		:=	$(shell $(CC) -v 2>&1)
-PIE_FOUND		:=	$(findstring --enable-default-pie,${GCC_V_OUTPUT})
-
-ifneq ($(PIE_FOUND),)
-TF_CFLAGS		+=	-fno-PIE
-endif
 
 # Force the compiler to include the frame pointer
 ifeq (${ENABLE_BACKTRACE},1)
@@ -335,6 +330,16 @@
 include make_helpers/armv7-a-cpus.mk
 endif
 
+ifeq ($(ENABLE_PIE),1)
+    TF_CFLAGS		+=	-fpie
+    TF_LDFLAGS		+=	-pie
+else
+    PIE_FOUND		:=	$(findstring --enable-default-pie,${GCC_V_OUTPUT})
+    ifneq ($(PIE_FOUND),)
+        TF_CFLAGS		+=	-fno-PIE
+    endif
+endif
+
 # Include the CPU specific operations makefile, which provides default
 # values for all CPU errata workarounds and CPU specific optimisations.
 # This can be overridden by the platform.
@@ -565,6 +570,7 @@
 $(eval $(call assert_boolean,ENABLE_ASSERTIONS))
 $(eval $(call assert_boolean,ENABLE_BACKTRACE))
 $(eval $(call assert_boolean,ENABLE_MPAM_FOR_LOWER_ELS))
+$(eval $(call assert_boolean,ENABLE_PIE))
 $(eval $(call assert_boolean,ENABLE_PMF))
 $(eval $(call assert_boolean,ENABLE_PSCI_STAT))
 $(eval $(call assert_boolean,ENABLE_RUNTIME_INSTRUMENTATION))
@@ -615,6 +621,7 @@
 $(eval $(call add_define,ENABLE_ASSERTIONS))
 $(eval $(call add_define,ENABLE_BACKTRACE))
 $(eval $(call add_define,ENABLE_MPAM_FOR_LOWER_ELS))
+$(eval $(call add_define,ENABLE_PIE))
 $(eval $(call add_define,ENABLE_PMF))
 $(eval $(call add_define,ENABLE_PSCI_STAT))
 $(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION))
diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S
index bc8cbfd..30a5c59 100644
--- a/bl2/aarch64/bl2_entrypoint.S
+++ b/bl2/aarch64/bl2_entrypoint.S
@@ -70,13 +70,19 @@
 	 *   - the coherent memory section.
 	 * ---------------------------------------------
 	 */
-	ldr	x0, =__BSS_START__
-	ldr	x1, =__BSS_SIZE__
+	adrp	x0, __BSS_START__
+	add	x0, x0, :lo12:__BSS_START__
+	adrp	x1, __BSS_END__
+	add	x1, x1, :lo12:__BSS_END__
+	sub	x1, x1, x0
 	bl	zeromem
 
 #if USE_COHERENT_MEM
-	ldr	x0, =__COHERENT_RAM_START__
-	ldr	x1, =__COHERENT_RAM_UNALIGNED_SIZE__
+	adrp	x0, __COHERENT_RAM_START__
+	add	x0, x0, :lo12:__COHERENT_RAM_START__
+	adrp	x1, __COHERENT_RAM_END_UNALIGNED__
+	add	x1, x1, :lo12:__COHERENT_RAM_END_UNALIGNED__
+	sub	x1, x1, x0
 	bl	zeromem
 #endif
 
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 3a45e53..7c116a2 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -7,6 +7,7 @@
 #include <arch.h>
 #include <bl_common.h>
 #include <el3_common_macros.S>
+#include <platform_def.h>
 #include <pmf_asm_macros.S>
 #include <runtime_instr.h>
 #include <xlat_mmu_helpers.h>
@@ -73,6 +74,18 @@
 	mov	x22, 0
 	mov	x23, 0
 #endif /* RESET_TO_BL31 */
+
+	/* --------------------------------------------------------------------
+	 * If PIE is enabled, fixup the Global descriptor Table and dynamic
+	 * relocations
+	 * --------------------------------------------------------------------
+	 */
+#if ENABLE_PIE
+	mov_imm	x0, BL31_BASE
+	mov_imm	x1, BL31_LIMIT
+	bl	fixup_gdt_reloc
+#endif /* ENABLE_PIE */
+
 	/* ---------------------------------------------
 	 * Perform platform specific early arch. setup
 	 * ---------------------------------------------
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 81e7ba3..43d0ed4 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -26,6 +26,8 @@
     ASSERT(. == ALIGN(PAGE_SIZE),
            "BL31_BASE address is not aligned on a page boundary.")
 
+    __BL31_START__ = .;
+
 #if SEPARATE_CODE_AND_RODATA
     .text . : {
         __TEXT_START__ = .;
@@ -63,6 +65,16 @@
         KEEP(*(cpu_ops))
         __CPU_OPS_END__ = .;
 
+        /*
+         * Keep the .got section in the RO section as the it is patched
+         * prior to enabling the MMU and having the .got in RO is better for
+         * security.
+         */
+        . = ALIGN(16);
+        __GOT_START__ = .;
+        *(.got)
+        __GOT_END__ = .;
+
         /* Place pubsub sections for events */
         . = ALIGN(8);
 #include <pubsub_events.h>
@@ -153,6 +165,16 @@
         __DATA_END__ = .;
     } >RAM
 
+    . = ALIGN(16);
+    /*
+     * .rela.dyn needs to come after .data for the read-elf utility to parse
+     * this section correctly.
+     */
+    __RELA_START__ = .;
+    .rela.dyn . : {
+    } >RAM
+    __RELA_END__ = .;
+
 #ifdef BL31_PROGBITS_LIMIT
     ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.")
 #endif
@@ -265,11 +287,5 @@
     __RW_END__ = .;
     __BL31_END__ = .;
 
-    __BSS_SIZE__ = SIZEOF(.bss);
-#if USE_COHERENT_MEM
-    __COHERENT_RAM_UNALIGNED_SIZE__ =
-        __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
-#endif
-
     ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.")
 }
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 7cc7485..051b92b 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -2532,6 +2532,12 @@
    translation table entries for a given stage of translation for a particular
    translation regime.
 
+Armv8.3-A
+~~~~~~~~~
+
+-  Pointer Authentication features of Armv8.3-A are unconditionally enabled so
+   that lower ELs are allowed to use them without causing a trap to EL3.
+
 Armv7-A
 ~~~~~~~
 
diff --git a/docs/plat/meson-gxbb.rst b/docs/plat/meson-gxbb.rst
new file mode 100644
index 0000000..f909e99
--- /dev/null
+++ b/docs/plat/meson-gxbb.rst
@@ -0,0 +1,26 @@
+Trusted Firmware-A for Amlogic Meson S905 (GXBB)
+================================================
+
+The Amlogic Meson S905 is a SoC with a quad core Arm Cortex-A53 running at
+1.5Ghz. It also contains a Cortex-M3 used as SCP.
+
+This port is a minimal implementation of BL31 capable of booting mainline U-Boot
+and Linux:
+
+- SCPI support.
+- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0
+  can't be turned off, so there is a workaround to hide this from the caller.
+- GICv2 driver set up.
+- Basic SIP services (read efuse data, enable/disable JTAG).
+
+In order to build it:
+
+::
+
+    CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxbb bl31
+
+This port has been tested in a ODROID-C2. After building it, follow the
+instructions in the `U-Boot repository`_, replacing the mentioned **bl31.bin**
+by the one built from this port.
+
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/odroid-c2/README
diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst
index fbf753b..db47564 100644
--- a/docs/plat/rpi3.rst
+++ b/docs/plat/rpi3.rst
@@ -133,9 +133,12 @@
     0x40000000 +-----------------+
 
 The area between **0x10000000** and **0x11000000** has to be manually protected
-so that the kernel doesn't use it. That is done by adding ``memmap=16M$256M`` to
-the command line passed to the kernel. See the `Setup SD card`_ instructions to
-see how to do it.
+so that the kernel doesn't use it. The current port tries to modify the live DTB
+to add a memreserve region that reserves the previously mentioned area.
+
+If this is not possible, the user may manually add ``memmap=16M$256M`` to the
+command line passed to the kernel in ``cmdline.txt``. See the `Setup SD card`_
+instructions to see how to do it. This system is strongly discouraged.
 
 The last 16 MiB of DRAM can only be accessed by the VideoCore, that has
 different mappings than the Arm cores in which the I/O addresses don't overlap
@@ -384,14 +387,9 @@
    bootloader will look for a file called ``armstub8.bin`` and load it at
    address **0x0** instead of a predefined one.
 
-4. Open ``cmdline.txt`` and add ``memmap=16M$256M`` to prevent the kernel from
-   using the memory needed by TF-A. If you want to enable the serial port
-   "Mini UART", make sure that this file also contains
+4. To enable the serial port "Mini UART" in Linux, open ``cmdline.txt`` and add
    ``console=serial0,115200 console=tty1``.
 
-   Note that the 16 MiB reserved this way won't be available for Linux, the same
-   way as the memory reserved in DRAM for the GPU isn't available.
-
 5. Open ``config.txt`` and add the following lines at the end (``enable_uart=1``
    is only needed to enable debugging through the Mini UART):
 
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index 9e731a4..f8379b4 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -76,7 +76,23 @@
 .. code:: bash
 
     make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min
+    cd <u-boot_directory>
+    make stm32mp15_basic_defconfig
+    make DEVICE_TREE=stm32mp157c_ev1 all
+    ./tools/mkimage -T stm32image -a 0xC0100000 -e 0xC0100000 -d u-boot.bin u-boot.stm32
 
 The following build options are supported:
 
 - ``ENABLE_STACK_PROTECTOR``: To enable the stack protection.
+
+
+Populate SD-card
+----------------
+
+The SD-card has to be formated with GPT.
+It should contain at least those partitions:
+
+- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary
+- ssbl: to copy the u-boot.stm32 binary
+
+Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl.
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 1667cce..bef4af6 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2554,8 +2554,13 @@
 flag in its platform.mk. Not using this flag is deprecated for new platforms.
 
 BL31 implements a crash reporting mechanism which prints the various registers
-of the CPU to enable quick crash analysis and debugging. By default, the
-definitions in ``plat/common/aarch64/platform\_helpers.S`` will cause the crash
+of the CPU to enable quick crash analysis and debugging. This mechanism relies
+on the platform implementating ``plat_crash_console_init``,
+``plat_crash_console_putc`` and ``plat_crash_console_flush``.
+
+The file ``plat/common/aarch64/crash_console_helpers.S`` contains sample
+implementation of all of them. Platforms may include this file to their
+makefiles in order to benefit from them. By default, they will cause the crash
 output to be routed over the normal console infrastructure and get printed on
 consoles configured to output in crash state. ``console_set_scope()`` can be
 used to control whether a console is used for crash output.
@@ -2565,8 +2570,12 @@
 more explicitly. For these, the following functions can be overridden by
 platform code. They are executed outside of a C environment and without a stack.
 
-Function : plat\_crash\_console\_init
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If this behaviour is not desirable, the platform may implement functions that
+redirect the prints to the console driver (``console_xxx_core_init``, etc). Most
+platforms (including Arm platforms) do this and they can be used as an example.
+
+Function : plat\_crash\_console\_init [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ::
 
@@ -2577,9 +2586,10 @@
 console. It must only use the general purpose registers x0 through x7 to do the
 initialization and returns 1 on success.
 
-If you are trying to debug crashes before the console driver would normally get
-registered, you can use this to register a driver from assembly with hardcoded
-parameters. For example, you could register the 16550 driver like this:
+When using the sample implementation, if you are trying to debug crashes before
+the console driver would normally get registered, you can use this to register a
+driver from assembly with hardcoded parameters. For example, you could register
+the 16550 driver like this:
 
 ::
 
@@ -2595,11 +2605,11 @@
         b       console_16550_register  /* tail call, returns 1 on success */
     endfunc plat_crash_console_init
 
-If you're trying to debug crashes in BL1, you can call the console_xxx_core_init
-function exported by some console drivers from here.
+If you're trying to debug crashes in BL1, you can call the
+``console_xxx_core_init`` function exported by some console drivers from here.
 
-Function : plat\_crash\_console\_putc
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Function : plat\_crash\_console\_putc [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ::
 
@@ -2612,13 +2622,13 @@
 register x0.
 
 If you have registered a normal console driver in ``plat_crash_console_init``,
-you can keep the default implementation here (which calls ``console_putc()``).
+you can keep the sample implementation here (which calls ``console_putc()``).
 
-If you're trying to debug crashes in BL1, you can call the console_xxx_core_putc
-function exported by some console drivers from here.
+If you're trying to debug crashes in BL1, you can call the
+``console_xxx_core_putc`` function exported by some console drivers from here.
 
-Function : plat\_crash\_console\_flush
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Function : plat\_crash\_console\_flush [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ::
 
@@ -2631,7 +2641,7 @@
 completion; otherwise the return value is -1.
 
 If you have registered a normal console driver in ``plat_crash_console_init``,
-you can keep the default implementation here (which calls ``console_flush()``).
+you can keep the sample implementation here (which calls ``console_flush()``).
 
 If you're trying to debug crashes in BL1, you can call the console_xx_core_flush
 function exported by some console drivers from here.
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index f4ef85d..52cb45c 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -371,6 +371,10 @@
    partitioning in EL3, however. Platform initialisation code should configure
    and use partitions in EL3 as required. This option defaults to ``0``.
 
+-  ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE)
+   support within generic code in TF-A. This option is currently only supported
+   in BL31. Default is 0.
+
 -  ``ENABLE_PMF``: Boolean option to enable support for optional Performance
    Measurement Framework(PMF). Default is 0.
 
diff --git a/drivers/allwinner/sunxi_rsb.c b/drivers/allwinner/sunxi_rsb.c
new file mode 100644
index 0000000..7075c67
--- /dev/null
+++ b/drivers/allwinner/sunxi_rsb.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <sunxi_mmap.h>
+
+#define RSB_CTRL	0x00
+#define RSB_CCR		0x04
+#define RSB_INTE	0x08
+#define RSB_STAT	0x0c
+#define RSB_DADDR0	0x10
+#define RSB_DLEN	0x18
+#define RSB_DATA0	0x1c
+#define RSB_LCR		0x24
+#define RSB_PMCR	0x28
+#define RSB_CMD		0x2c
+#define RSB_SADDR	0x30
+
+#define RSBCMD_SRTA	0xE8
+#define RSBCMD_RD8	0x8B
+#define RSBCMD_RD16	0x9C
+#define RSBCMD_RD32	0xA6
+#define RSBCMD_WR8	0x4E
+#define RSBCMD_WR16	0x59
+#define RSBCMD_WR32	0x63
+
+#define MAX_TRIES	100000
+
+static int rsb_wait_bit(const char *desc, unsigned int offset, uint32_t mask)
+{
+	uint32_t reg, tries = MAX_TRIES;
+
+	do
+		reg = mmio_read_32(SUNXI_R_RSB_BASE + offset);
+	while ((reg & mask) && --tries);	/* transaction in progress */
+	if (reg & mask) {
+		ERROR("%s: timed out\n", desc);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int rsb_wait_stat(const char *desc)
+{
+	uint32_t reg;
+	int ret = rsb_wait_bit(desc, RSB_CTRL, BIT(7));
+
+	if (ret)
+		return ret;
+
+	reg = mmio_read_32(SUNXI_R_RSB_BASE + RSB_STAT);
+	if (reg == 0x01)
+		return 0;
+
+	ERROR("%s: 0x%x\n", desc, reg);
+	return -reg;
+}
+
+/* Initialize the RSB controller. */
+int rsb_init_controller(void)
+{
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x01); /* soft reset */
+
+	return rsb_wait_bit("RSB: reset controller", RSB_CTRL, BIT(0));
+}
+
+int rsb_read(uint8_t rt_addr, uint8_t reg_addr)
+{
+	int ret;
+
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16);
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr);
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */
+
+	ret = rsb_wait_stat("RSB: read command");
+	if (ret)
+		return ret;
+
+	return mmio_read_32(SUNXI_R_RSB_BASE + RSB_DATA0) & 0xff; /* result */
+}
+
+int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value)
+{
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_WR8);	/* byte write */
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16);
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr);
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_DATA0, value);
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */
+
+	return rsb_wait_stat("RSB: write command");
+}
+
+int rsb_set_device_mode(uint32_t device_mode)
+{
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_PMCR,
+		      (device_mode & 0x00ffffff) | BIT(31));
+
+	return rsb_wait_bit("RSB: set device to RSB", RSB_PMCR, BIT(31));
+}
+
+int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq)
+{
+	uint32_t reg;
+
+	if (bus_freq == 0)
+		return -EINVAL;
+
+	reg = source_freq / bus_freq;
+	if (reg < 2)
+		return -EINVAL;
+
+	reg = reg / 2 - 1;
+	reg |= (1U << 8);		/* one cycle of CD output delay */
+
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CCR, reg);
+
+	return 0;
+}
+
+/* Initialize the RSB PMIC connection. */
+int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr)
+{
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16));
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_SRTA);
+	mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);
+
+	return rsb_wait_stat("RSB: set run-time address");
+}
diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S
index 841ea44..46ff225 100644
--- a/drivers/arm/pl011/aarch32/pl011_console.S
+++ b/drivers/arm/pl011/aarch32/pl011_console.S
@@ -6,6 +6,7 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <assert_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
 #include <console_macros.S>
 #include <pl011.h>
 
@@ -116,7 +117,7 @@
 
 	mov	r0, r4
 	pop	{r4, lr}
-	finish_console_register pl011
+	finish_console_register pl011 putc=1, getc=1, flush=1
 
 register_fail:
 	pop	{r4, pc}
diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S
index d6a2d6b..3886f3b 100644
--- a/drivers/arm/pl011/aarch64/pl011_console.S
+++ b/drivers/arm/pl011/aarch64/pl011_console.S
@@ -6,6 +6,7 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <assert_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
 #include <console_macros.S>
 #include <pl011.h>
 
@@ -110,7 +111,7 @@
 
 	mov	x0, x6
 	mov	x30, x7
-	finish_console_register pl011
+	finish_console_register pl011 putc=1, getc=1, flush=1
 
 register_fail:
 	ret	x7
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
index db4f88a..763eba7 100644
--- a/drivers/arm/tzc/tzc400.c
+++ b/drivers/arm/tzc/tzc400.c
@@ -14,12 +14,12 @@
 /*
  * Macros which will be used by common core functions.
  */
-#define TZC_400_REGION_BASE_LOW_0_OFFSET	0x100
-#define TZC_400_REGION_BASE_HIGH_0_OFFSET	0x104
-#define TZC_400_REGION_TOP_LOW_0_OFFSET		0x108
-#define TZC_400_REGION_TOP_HIGH_0_OFFSET	0x10c
-#define TZC_400_REGION_ATTR_0_OFFSET		0x110
-#define TZC_400_REGION_ID_ACCESS_0_OFFSET	0x114
+#define TZC_400_REGION_BASE_LOW_0_OFFSET	U(0x100)
+#define TZC_400_REGION_BASE_HIGH_0_OFFSET	U(0x104)
+#define TZC_400_REGION_TOP_LOW_0_OFFSET		U(0x108)
+#define TZC_400_REGION_TOP_HIGH_0_OFFSET	U(0x10c)
+#define TZC_400_REGION_ATTR_0_OFFSET		U(0x110)
+#define TZC_400_REGION_ID_ACCESS_0_OFFSET	U(0x114)
 
 /*
  * Implementation defined values used to validate inputs later.
@@ -88,10 +88,10 @@
 	/* Upper half is current state. Lower half is requested state. */
 	open_status = get_gate_keeper_os(base);
 
-	if (val)
-		open_status |=  (1 << filter);
+	if (val != 0)
+		open_status |=  (1U << filter);
 	else
-		open_status &= ~(1 << filter);
+		open_status &= ~(1U << filter);
 
 	_tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) <<
 			      GATE_KEEPER_OR_SHIFT);
@@ -101,9 +101,9 @@
 		;
 }
 
-void tzc400_set_action(tzc_action_t action)
+void tzc400_set_action(unsigned int action)
 {
-	assert(tzc400.base);
+	assert(tzc400.base != 0U);
 	assert(action <= TZC_ACTION_ERR_INT);
 
 	/*
@@ -121,7 +121,7 @@
 #endif
 	unsigned int tzc400_build;
 
-	assert(base);
+	assert(base != 0U);
 	tzc400.base = base;
 
 #if DEBUG
@@ -134,12 +134,12 @@
 
 	/* Save values we will use later. */
 	tzc400_build = _tzc400_read_build_config(tzc400.base);
-	tzc400.num_filters = ((tzc400_build >> BUILD_CONFIG_NF_SHIFT) &
-			   BUILD_CONFIG_NF_MASK) + 1;
-	tzc400.addr_width  = ((tzc400_build >> BUILD_CONFIG_AW_SHIFT) &
-			   BUILD_CONFIG_AW_MASK) + 1;
-	tzc400.num_regions = ((tzc400_build >> BUILD_CONFIG_NR_SHIFT) &
-			   BUILD_CONFIG_NR_MASK) + 1;
+	tzc400.num_filters = (uint8_t)((tzc400_build >> BUILD_CONFIG_NF_SHIFT) &
+					BUILD_CONFIG_NF_MASK) + 1U;
+	tzc400.addr_width  = (uint8_t)((tzc400_build >> BUILD_CONFIG_AW_SHIFT) &
+					BUILD_CONFIG_AW_MASK) + 1U;
+	tzc400.num_regions = (uint8_t)((tzc400_build >> BUILD_CONFIG_NR_SHIFT) &
+					BUILD_CONFIG_NR_MASK) + 1U;
 }
 
 /*
@@ -148,10 +148,10 @@
  * to any other region, and is enabled on all filters; this cannot be
  * changed. This function only changes the access permissions.
  */
-void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+void tzc400_configure_region0(unsigned int sec_attr,
 			   unsigned int ns_device_access)
 {
-	assert(tzc400.base);
+	assert(tzc400.base != 0U);
 	assert(sec_attr <= TZC_REGION_S_RDWR);
 
 	_tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access);
@@ -166,17 +166,17 @@
  * for this region (see comment for that function).
  */
 void tzc400_configure_region(unsigned int filters,
-			  int region,
+			  unsigned int region,
 			  unsigned long long region_base,
 			  unsigned long long region_top,
-			  tzc_region_attributes_t sec_attr,
+			  unsigned int sec_attr,
 			  unsigned int nsaid_permissions)
 {
-	assert(tzc400.base);
+	assert(tzc400.base != 0U);
 
 	/* Do range checks on filters and regions. */
-	assert(((filters >> tzc400.num_filters) == 0) &&
-	       (region >= 0) && (region < tzc400.num_regions));
+	assert(((filters >> tzc400.num_filters) == 0U) &&
+	       (region < tzc400.num_regions));
 
 	/*
 	 * Do address range check based on TZC configuration. A 64bit address is
@@ -186,7 +186,7 @@
 		(region_base < region_top)));
 
 	/* region_base and (region_top + 1) must be 4KB aligned */
-	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+	assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
 
 	assert(sec_attr <= TZC_REGION_S_RDWR);
 
@@ -200,11 +200,11 @@
 	unsigned int state;
 	unsigned int filter;
 
-	assert(tzc400.base);
+	assert(tzc400.base != 0U);
 
-	for (filter = 0; filter < tzc400.num_filters; filter++) {
+	for (filter = 0U; filter < tzc400.num_filters; filter++) {
 		state = _tzc400_get_gate_keeper(tzc400.base, filter);
-		if (state) {
+		if (state != 0U) {
 			/*
 			 * The TZC filter is already configured. Changing the
 			 * programmer's view in an active system can cause
@@ -227,7 +227,7 @@
 {
 	unsigned int filter;
 
-	assert(tzc400.base);
+	assert(tzc400.base != 0U);
 
 	/*
 	 * We don't do the same state check as above as the Gatekeepers are
diff --git a/drivers/arm/tzc/tzc_common_private.h b/drivers/arm/tzc/tzc_common_private.h
index e1b7727..5fbea92 100644
--- a/drivers/arm/tzc/tzc_common_private.h
+++ b/drivers/arm/tzc/tzc_common_private.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __TZC_COMMON_PRIVATE_H__
-#define __TZC_COMMON_PRIVATE_H__
+#ifndef TZC_COMMON_PRIVATE_H
+#define TZC_COMMON_PRIVATE_H
 
 #include <arch.h>
 #include <arch_helpers.h>
@@ -15,7 +15,7 @@
 #define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name)		\
 	static inline void _tzc##fn_name##_write_action(		\
 					uintptr_t base,			\
-					tzc_action_t action)		\
+					unsigned int action)		\
 	{								\
 		mmio_write_32(base + TZC_##macro_name##_ACTION_OFF,	\
 			action);					\
@@ -24,7 +24,7 @@
 #define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name)	\
 	static inline void _tzc##fn_name##_write_region_base(		\
 					uintptr_t base,			\
-					int region_no,			\
+					unsigned int region_no,		\
 					unsigned long long region_base)	\
 	{								\
 		mmio_write_32(base +					\
@@ -44,7 +44,7 @@
 #define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name)		\
 	static inline void _tzc##fn_name##_write_region_top(		\
 					uintptr_t base,			\
-					int region_no,			\
+					unsigned int region_no,		\
 					unsigned long long region_top)	\
 	{								\
 		mmio_write_32(base +					\
@@ -52,19 +52,19 @@
 				(TZC_##macro_name##_REGION_SIZE,	\
 				region_no) +				\
 			TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET,	\
-			(uint32_t)region_top);			\
+			(uint32_t)region_top);				\
 		mmio_write_32(base +					\
 			TZC_REGION_OFFSET(				\
 				TZC_##macro_name##_REGION_SIZE,		\
 				region_no) +				\
 			TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET,	\
-			(uint32_t)(region_top >> 32));		\
+			(uint32_t)(region_top >> 32));			\
 	}
 
 #define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name)	\
 	static inline void _tzc##fn_name##_write_region_attributes(	\
 						uintptr_t base,		\
-						int region_no,		\
+						unsigned int region_no,	\
 						unsigned int attr)	\
 	{								\
 		mmio_write_32(base +					\
@@ -78,7 +78,7 @@
 #define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name)	\
 	static inline void _tzc##fn_name##_write_region_id_access(	\
 						uintptr_t base,		\
-						int region_no,		\
+						unsigned int region_no,	\
 						unsigned int val)	\
 	{								\
 		mmio_write_32(base +					\
@@ -94,13 +94,13 @@
  */
 #define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name)			\
 	static void _tzc##fn_name##_configure_region0(uintptr_t base,	\
-			   tzc_region_attributes_t sec_attr,		\
+			   unsigned int sec_attr,			\
 			   unsigned int ns_device_access)		\
 	{								\
-		assert(base);						\
+		assert(base != 0U);					\
 		VERBOSE("TrustZone : Configuring region 0 "		\
-			"(TZC Interface Base=%p sec_attr=0x%x,"		\
-			" ns_devs=0x%x)\n", (void *)base,		\
+			"(TZC Interface Base=0x%lx sec_attr=0x%x,"	\
+			" ns_devs=0x%x)\n", base,			\
 			sec_attr, ns_device_access);			\
 									\
 		/* Set secure attributes on region 0 */			\
@@ -126,18 +126,18 @@
 #define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name)			\
 	static void _tzc##fn_name##_configure_region(uintptr_t base,	\
 				unsigned int filters,			\
-				int region_no,				\
+				unsigned int region_no,			\
 				unsigned long long region_base,		\
 				unsigned long long region_top,		\
-				tzc_region_attributes_t sec_attr,	\
-				unsigned int nsaid_permissions)	\
+				unsigned int sec_attr,			\
+				unsigned int nsaid_permissions)		\
 	{								\
-		assert(base);						\
+		assert(base != 0U);					\
 		VERBOSE("TrustZone : Configuring region "		\
-			"(TZC Interface Base: %p, region_no = %d)"	\
-			"...\n", (void *)base, region_no);		\
+			"(TZC Interface Base: 0x%lx, region_no = %u)"	\
+			"...\n", base, region_no);			\
 		VERBOSE("TrustZone : ... base = %llx, top = %llx,"	\
-			"\n", region_base, region_top);\
+			"\n", region_base, region_top);			\
 		VERBOSE("TrustZone : ... sec_attr = 0x%x,"		\
 			" ns_devs = 0x%x)\n",				\
 			sec_attr, nsaid_permissions);			\
@@ -175,42 +175,44 @@
 
 	id = mmio_read_32(base + PID0_OFF);
 	/* Masks DESC part in PID1 */
-	id |= ((mmio_read_32(base + PID1_OFF) & 0xF) << 8);
+	id |= ((mmio_read_32(base + PID1_OFF) & 0xFU) << 8U);
 
 	return id;
 }
 
 #if ENABLE_ASSERTIONS
 #ifdef AARCH32
-static inline unsigned long long _tzc_get_max_top_addr(int addr_width)
+static inline unsigned long long _tzc_get_max_top_addr(unsigned int addr_width)
 {
 	/*
 	 * Assume at least 32 bit wide address and initialize the max.
 	 * This function doesn't use 64-bit integer arithmetic to avoid
 	 * having to implement additional compiler library functions.
 	 */
-	unsigned long long addr_mask = 0xFFFFFFFF;
+	unsigned long long addr_mask = 0xFFFFFFFFU;
 	uint32_t *addr_ptr = (uint32_t *)&addr_mask;
 
-	assert(addr_width >= 32);
+	assert(addr_width >= 32U);
 
 	/* This logic works only on little - endian platforms */
-	assert((read_sctlr() & SCTLR_EE_BIT) == 0);
+	assert((read_sctlr() & SCTLR_EE_BIT) == 0U);
 
 	/*
 	 * If required address width is greater than 32, populate the higher
 	 * 32 bits of the 64 bit field with the max address.
 	 */
-	if (addr_width > 32)
-		*(addr_ptr + 1) = ((1 << (addr_width - 32)) - 1);
+	if (addr_width > 32U)
+		*(addr_ptr + 1U) = ((1U << (addr_width - 32U)) - 1U);
 
 	return addr_mask;
 }
 #else
-#define _tzc_get_max_top_addr(addr_width)\
-	(UINT64_MAX >> (64 - (addr_width)))
+static inline unsigned long long _tzc_get_max_top_addr(unsigned int addr_width)
+{
+	return UINT64_MAX >> (64U - addr_width);
+}
 #endif /* AARCH32 */
 
 #endif /* ENABLE_ASSERTIONS */
 
-#endif /* __TZC_COMMON_PRIVATE_H__ */
+#endif /* TZC_COMMON_PRIVATE_H */
diff --git a/drivers/arm/tzc/tzc_dmc500.c b/drivers/arm/tzc/tzc_dmc500.c
index 8b618e6..3e6c783 100644
--- a/drivers/arm/tzc/tzc_dmc500.c
+++ b/drivers/arm/tzc/tzc_dmc500.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -36,7 +36,7 @@
  * Structure for configured regions attributes in DMC500.
  */
 typedef struct tzc_dmc500_regions {
-	tzc_region_attributes_t sec_attr;
+	unsigned int sec_attr;
 	int is_enabled;
 } tzc_dmc500_regions_t;
 
@@ -63,7 +63,7 @@
 
 static inline unsigned int _tzc_dmc500_read_region_attr_0(
 					uintptr_t dmc_si_base,
-					int region_no)
+					unsigned int region_no)
 {
 	return mmio_read_32(dmc_si_base +
 			TZC_REGION_OFFSET(TZC_DMC500_REGION_SIZE, region_no) +
@@ -144,8 +144,8 @@
  * and is always enabled; this cannot be changed. This function only changes
  * the access permissions.
  */
-void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
-					unsigned int nsaid_permissions)
+void tzc_dmc500_configure_region0(unsigned int sec_attr,
+				  unsigned int nsaid_permissions)
 {
 	int dmc_inst, sys_if;
 
@@ -172,17 +172,17 @@
  * Region 0 is special; it is preferable to use tzc_dmc500_configure_region0
  * for this region (see comment for that function).
  */
-void tzc_dmc500_configure_region(int region_no,
+void tzc_dmc500_configure_region(unsigned int region_no,
 			unsigned long long region_base,
 			unsigned long long region_top,
-			tzc_region_attributes_t sec_attr,
+			unsigned int sec_attr,
 			unsigned int nsaid_permissions)
 {
 	int dmc_inst, sys_if;
 
 	assert(g_driver_data);
 	/* Do range checks on regions. */
-	assert(region_no >= 0 && region_no <= MAX_REGION_VAL);
+	assert((region_no >= 0U) && (region_no <= MAX_REGION_VAL));
 
 	/*
 	 * Do address range check based on DMC-TZ configuration. A 43bit address
@@ -192,7 +192,7 @@
 		(region_base < region_top)));
 
 	/* region_base and (region_top + 1) must be 4KB aligned */
-	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+	assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
 
 	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
 		assert(DMC_INST_BASE_ADDR(dmc_inst));
@@ -209,7 +209,7 @@
 }
 
 /* Sets the action value for all the DMC instances */
-void tzc_dmc500_set_action(tzc_action_t action)
+void tzc_dmc500_set_action(unsigned int action)
 {
 	int dmc_inst;
 
diff --git a/drivers/cadence/uart/aarch64/cdns_console.S b/drivers/cadence/uart/aarch64/cdns_console.S
index 71359a6..8f46a62 100644
--- a/drivers/cadence/uart/aarch64/cdns_console.S
+++ b/drivers/cadence/uart/aarch64/cdns_console.S
@@ -7,6 +7,8 @@
 #include <asm_macros.S>
 #include <assert_macros.S>
 #include <cadence/cdns_uart.h>
+#define USE_FINISH_CONSOLE_REG_2
+#include <console_macros.S>
 
 	/*
 	 * "core" functions are low-level implementations that don't require
@@ -77,7 +79,7 @@
 
 	mov	x0, x6
 	mov	x30, v7
-	finish_console_register cdns
+	finish_console_register cdns putc=1, getc=1, flush=1
 
 register_fail:
 	ret	x7
diff --git a/drivers/console/aarch64/skeleton_console.S b/drivers/console/aarch64/skeleton_console.S
index 1b5d739..3993eef 100644
--- a/drivers/console/aarch64/skeleton_console.S
+++ b/drivers/console/aarch64/skeleton_console.S
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #include <asm_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
 #include <console_macros.S>
 
 	/*
@@ -60,8 +61,12 @@
 	 * Keep console_t pointer in x0 for later.
 	 */
 
-	/* Macro to finish up registration and return (needs valid x0 + x30). */
-	finish_console_register xxx
+	/*
+	 * Macro to finish up registration and return (needs valid x0 + x30).
+	 * If any of the argument is unspecified, then the corresponding
+	 * entry in console_t is set to 0.
+	 */
+	finish_console_register xxx putc=1, getc=1, flush=1
 
 	/* Jump here if hardware init fails or parameters are invalid. */
 register_fail:
diff --git a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
index 184853d..89be349 100644
--- a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
+++ b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
@@ -6,6 +6,7 @@
 
 #include <asm_macros.S>
 #include <cbmem_console.h>
+#define USE_FINISH_CONSOLE_REG_2
 #include <console_macros.S>
 
 /*
@@ -39,7 +40,7 @@
 	ldr	w2, [x0]
 	str	w2, [x1, #CONSOLE_T_CBMC_SIZE]
 	mov	x0, x1
-	finish_console_register cbmc
+	finish_console_register cbmc putc=1, flush=1
 endfunc console_cbmc_register
 
 	/* -----------------------------------------------
diff --git a/drivers/meson/console/aarch64/meson_console.S b/drivers/meson/console/aarch64/meson_console.S
new file mode 100644
index 0000000..eaee10e
--- /dev/null
+++ b/drivers/meson/console/aarch64/meson_console.S
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <assert_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
+#include <console_macros.S>
+#include <meson_console.h>
+
+	.globl console_meson_register
+	.globl console_meson_init
+	.globl console_meson_putc
+	.globl console_meson_getc
+	.globl console_meson_flush
+	.globl console_meson_core_putc
+	.globl console_meson_core_getc
+	.globl console_meson_core_flush
+
+	/* -----------------------------------------------
+	 * Hardware definitions
+	 * -----------------------------------------------
+	 */
+#define MESON_WFIFO_OFFSET			0x0
+#define MESON_RFIFO_OFFSET			0x4
+#define MESON_CONTROL_OFFSET			0x8
+#define MESON_STATUS_OFFSET			0xC
+#define MESON_MISC_OFFSET			0x10
+#define MESON_REG5_OFFSET			0x14
+
+#define MESON_CONTROL_CLR_ERROR_BIT		24
+#define MESON_CONTROL_RX_RESET_BIT		23
+#define MESON_CONTROL_TX_RESET_BIT		22
+#define MESON_CONTROL_RX_ENABLE_BIT		13
+#define MESON_CONTROL_TX_ENABLE_BIT		12
+
+#define MESON_STATUS_RX_EMPTY_BIT		20
+#define MESON_STATUS_TX_FULL_BIT		21
+#define MESON_STATUS_TX_EMPTY_BIT		22
+
+#define MESON_REG5_USE_XTAL_CLK_BIT		24
+#define MESON_REG5_USE_NEW_RATE_BIT		23
+#define MESON_REG5_NEW_BAUD_RATE_MASK		0x7FFFFF
+
+	/* -----------------------------------------------
+	 * int console_meson_register(uintptr_t base,
+	 *     uint32_t clk, uint32_t baud,
+	 *     console_meson_t *console);
+	 * Function to initialize and register a new MESON
+	 * console. Storage passed in for the console struct
+	 * *must* be persistent (i.e. not from the stack).
+	 * In: x0 - UART register base address
+	 *     w1 - UART clock in Hz
+	 *     w2 - Baud rate
+	 *     x3 - pointer to empty console_meson_t struct
+	 * Out: return 1 on success, 0 on error
+	 * Clobber list : x0, x1, x2, x6, x7, x14
+	 * -----------------------------------------------
+	 */
+func console_meson_register
+	mov	x7, x30
+	mov	x6, x3
+	cbz	x6, register_fail
+	str	x0, [x6, #CONSOLE_T_MESON_BASE]
+
+	bl	console_meson_init
+	cbz	x0, register_fail
+
+	mov	x0, x6
+	mov	x30, x7
+	finish_console_register meson putc=1, getc=1, flush=1
+
+register_fail:
+	ret	x7
+endfunc console_meson_register
+
+	/* -----------------------------------------------
+	 * int console_meson_init(uintptr_t base_addr,
+	 * unsigned int uart_clk, unsigned int baud_rate)
+	 * Function to initialize the console without a
+	 * C Runtime to print debug information. This
+	 * function will be accessed by console_init and
+	 * crash reporting.
+	 * In: x0 - console base address
+	 *     w1 - Uart clock in Hz
+	 *     w2 - Baud rate
+	 * Out: return 1 on success else 0 on error
+	 * Clobber list : x0-x3
+	 * -----------------------------------------------
+	 */
+func console_meson_init
+	cmp	w0, #0
+	beq	init_fail
+	mov_imm	w3, 24000000 /* TODO: This only works with a 24 MHz clock. */
+	cmp	w1, w3
+	bne	init_fail
+	cmp	w2, #0
+	beq	init_fail
+	/* Set baud rate: value = ((clock / 3) / baudrate) - 1 */
+	mov	w3, #3
+	udiv	w3, w1, w3
+	udiv	w3, w3, w2
+	sub	w3, w3, #1
+	orr	w3, w3, #((1 << MESON_REG5_USE_XTAL_CLK_BIT) | \
+			  (1 << MESON_REG5_USE_NEW_RATE_BIT))
+	str	w3, [x0, #MESON_REG5_OFFSET]
+	/* Reset UART and clear error flag */
+	ldr	w3, [x0, #MESON_CONTROL_OFFSET]
+	orr	w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \
+			  (1 << MESON_CONTROL_RX_RESET_BIT) | \
+			  (1 << MESON_CONTROL_TX_RESET_BIT))
+	str	w3, [x0, #MESON_CONTROL_OFFSET]
+	bic	w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \
+			  (1 << MESON_CONTROL_RX_RESET_BIT) | \
+			  (1 << MESON_CONTROL_TX_RESET_BIT))
+	str	w3, [x0, #MESON_CONTROL_OFFSET]
+	/* Enable transfer and receive FIFO */
+	orr	w3, w3, #((1 << MESON_CONTROL_RX_ENABLE_BIT) | \
+			  (1 << MESON_CONTROL_TX_ENABLE_BIT))
+	str	w3, [x0, #MESON_CONTROL_OFFSET]
+	/* Success */
+	mov	w0, #1
+	ret
+init_fail:
+	mov	w0, wzr
+	ret
+endfunc console_meson_init
+
+	/* --------------------------------------------------------
+	 * int console_meson_putc(int c, console_meson_t *console)
+	 * Function to output a character over the console. It
+	 * returns the character printed on success or -1 on error.
+	 * In : w0 - character to be printed
+	 *      x1 - pointer to console_t structure
+	 * Out : return -1 on error else return character.
+	 * Clobber list : x2
+	 * --------------------------------------------------------
+	 */
+func console_meson_putc
+#if ENABLE_ASSERTIONS
+	cmp	x1, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+	ldr	x1, [x1, #CONSOLE_T_MESON_BASE]
+	b	console_meson_core_putc
+endfunc console_meson_putc
+
+	/* --------------------------------------------------------
+	 * int console_meson_core_putc(int c, uintptr_t base_addr)
+	 * Function to output a character over the console. It
+	 * returns the character printed on success or -1 on error.
+	 * In : w0 - character to be printed
+	 *      x1 - console base address
+	 * Out : return -1 on error else return character.
+	 * Clobber list : x2
+	 * --------------------------------------------------------
+	 */
+func console_meson_core_putc
+#if ENABLE_ASSERTIONS
+	cmp	x1, #0
+	ASM_ASSERT(ne)
+#endif
+	/* Prepend '\r' to '\n' */
+	cmp	w0, #0xA
+	b.ne	2f
+	/* Wait until the transmit FIFO isn't full */
+1:	ldr	w2, [x1, #MESON_STATUS_OFFSET]
+	tbnz	w2, #MESON_STATUS_TX_FULL_BIT, 1b
+	/* Write '\r' if needed */
+	mov	w2, #0xD
+	str	w2, [x1, #MESON_WFIFO_OFFSET]
+	/* Wait until the transmit FIFO isn't full */
+2:	ldr	w2, [x1, #MESON_STATUS_OFFSET]
+	tbnz	w2, #MESON_STATUS_TX_FULL_BIT, 2b
+	/* Write input character */
+	str	w0, [x1, #MESON_WFIFO_OFFSET]
+	ret
+endfunc console_meson_core_putc
+
+	/* ---------------------------------------------
+	 * int console_meson_getc(console_meson_t *console)
+	 * Function to get a character from the console.
+	 * It returns the character grabbed on success
+	 * or -1 if no character is available.
+	 * In : x0 - pointer to console_t structure
+	 * Out: w0 - character if available, else -1
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func console_meson_getc
+#if ENABLE_ASSERTIONS
+	cmp	x0, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+	ldr	x0, [x0, #CONSOLE_T_MESON_BASE]
+	b	console_meson_core_getc
+endfunc console_meson_getc
+
+	/* ---------------------------------------------
+	 * int console_meson_core_getc(uintptr_t base_addr)
+	 * Function to get a character from the console.
+	 * It returns the character grabbed on success
+	 * or -1 if no character is available.
+	 * In : x0 - console base address
+	 * Out: w0 - character if available, else -1
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func console_meson_core_getc
+#if ENABLE_ASSERTIONS
+	cmp	x0, #0
+	ASM_ASSERT(ne)
+#endif
+	/* Is the receive FIFO empty? */
+	ldr	w1, [x0, #MESON_STATUS_OFFSET]
+	tbnz	w1, #MESON_STATUS_RX_EMPTY_BIT, 1f
+	/* Read one character from the RX FIFO */
+	ldr	w0, [x0, #MESON_RFIFO_OFFSET]
+	ret
+1:
+	mov	w0, #ERROR_NO_PENDING_CHAR
+	ret
+endfunc console_meson_core_getc
+
+	/* ---------------------------------------------
+	 * int console_meson_flush(console_meson_t *console)
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * In : x0 - pointer to console_t structure
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func console_meson_flush
+#if ENABLE_ASSERTIONS
+	cmp	x0, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+	ldr	x0, [x0, #CONSOLE_T_MESON_BASE]
+	b	console_meson_core_flush
+endfunc console_meson_flush
+
+	/* ---------------------------------------------
+	 * int console_meson_core_flush(uintptr_t base_addr)
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * In : x0 - console base address
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func console_meson_core_flush
+#if ENABLE_ASSERTIONS
+	cmp	x0, #0
+	ASM_ASSERT(ne)
+#endif
+	/* Wait until the transmit FIFO is empty */
+1:	ldr	w1, [x0, #MESON_STATUS_OFFSET]
+	tbz	w1, #MESON_STATUS_TX_EMPTY_BIT, 1b
+	mov	w0, #0
+	ret
+endfunc console_meson_core_flush
diff --git a/drivers/st/io/io_mmc.c b/drivers/st/io/io_mmc.c
new file mode 100644
index 0000000..1ed2620
--- /dev/null
+++ b/drivers/st/io/io_mmc.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <io_driver.h>
+#include <io_mmc.h>
+#include <io_storage.h>
+#include <mmc.h>
+#include <stm32_sdmmc2.h>
+#include <string.h>
+
+/* SDMMC device functions */
+static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info);
+static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+			  io_entity_t *entity);
+static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
+static int mmc_block_seek(io_entity_t *entity, int mode, ssize_t offset);
+static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
+			  size_t *length_read);
+static int mmc_block_close(io_entity_t *entity);
+static int mmc_dev_close(io_dev_info_t *dev_info);
+static io_type_t device_type_mmc(void);
+
+static ssize_t seek_offset;
+
+static const io_dev_connector_t mmc_dev_connector = {
+	.dev_open = mmc_dev_open
+};
+
+static const io_dev_funcs_t mmc_dev_funcs = {
+	.type = device_type_mmc,
+	.open = mmc_block_open,
+	.seek = mmc_block_seek,
+	.size = NULL,
+	.read = mmc_block_read,
+	.write = NULL,
+	.close = mmc_block_close,
+	.dev_init = mmc_dev_init,
+	.dev_close = mmc_dev_close,
+};
+
+static const io_dev_info_t mmc_dev_info = {
+	.funcs = &mmc_dev_funcs,
+	.info = 0,
+};
+
+/* Identify the device type as mmc device */
+static io_type_t device_type_mmc(void)
+{
+	return IO_TYPE_MMC;
+}
+
+/* Open a connection to the mmc device */
+static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info)
+{
+	assert(dev_info != NULL);
+	*dev_info = (io_dev_info_t *)&mmc_dev_info;
+
+	return 0;
+}
+
+static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+	return 0;
+}
+
+/* Close a connection to the mmc device */
+static int mmc_dev_close(io_dev_info_t *dev_info)
+{
+	return 0;
+}
+
+/* Open a file on the mmc device */
+static int mmc_block_open(io_dev_info_t *dev_info, const  uintptr_t spec,
+			  io_entity_t *entity)
+{
+	seek_offset = 0;
+	return 0;
+}
+
+/* Seek to a particular file offset on the mmc device */
+static int mmc_block_seek(io_entity_t *entity, int mode, ssize_t offset)
+{
+	seek_offset = offset;
+	return 0;
+}
+
+/* Read data from a file on the mmc device */
+static int mmc_block_read(io_entity_t *entity, uintptr_t buffer,
+			  size_t length, size_t *length_read)
+{
+	*length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
+				       buffer, length);
+
+	if (*length_read != length) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* Close a file on the mmc device */
+static int mmc_block_close(io_entity_t *entity)
+{
+	return 0;
+}
+
+/* Register the mmc driver with the IO abstraction */
+int register_io_dev_mmc(const io_dev_connector_t **dev_con)
+{
+	int result;
+
+	assert(dev_con != NULL);
+
+	result = io_register_device(&mmc_dev_info);
+	if (result == 0) {
+		*dev_con = &mmc_dev_connector;
+	}
+
+	return result;
+}
diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c
new file mode 100644
index 0000000..e6798e0
--- /dev/null
+++ b/drivers/st/io/io_stm32image.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <errno.h>
+#include <io_driver.h>
+#include <io_stm32image.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <string.h>
+#include <utils.h>
+
+static uintptr_t backend_dev_handle;
+static uintptr_t backend_image_spec;
+static uint32_t *stm32_img;
+static uint8_t first_lba_buffer[MAX_LBA_SIZE] __aligned(4);
+static struct stm32image_part_info *current_part;
+
+/* STM32 Image driver functions */
+static int stm32image_dev_open(const uintptr_t init_params,
+			       io_dev_info_t **dev_info);
+static int stm32image_partition_open(io_dev_info_t *dev_info,
+				     const uintptr_t spec, io_entity_t *entity);
+static int stm32image_partition_size(io_entity_t *entity, size_t *length);
+static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
+				     size_t length, size_t *length_read);
+static int stm32image_partition_close(io_entity_t *entity);
+static int stm32image_dev_init(io_dev_info_t *dev_info,
+			       const uintptr_t init_params);
+static int stm32image_dev_close(io_dev_info_t *dev_info);
+
+/* Identify the device type as a virtual driver */
+static io_type_t device_type_stm32image(void)
+{
+	return IO_TYPE_STM32IMAGE;
+}
+
+static const io_dev_connector_t stm32image_dev_connector = {
+	.dev_open = stm32image_dev_open
+};
+
+static const io_dev_funcs_t stm32image_dev_funcs = {
+	.type = device_type_stm32image,
+	.open = stm32image_partition_open,
+	.size = stm32image_partition_size,
+	.read = stm32image_partition_read,
+	.close = stm32image_partition_close,
+	.dev_init = stm32image_dev_init,
+	.dev_close = stm32image_dev_close,
+};
+
+static io_dev_info_t stm32image_dev_info = {
+	.funcs = &stm32image_dev_funcs,
+	.info = (uintptr_t)0,
+};
+
+static struct stm32image_device_info stm32image_dev;
+
+static int get_part_idx_by_binary_type(uint32_t binary_type)
+{
+	int i;
+
+	for (i = 0; i < STM32_PART_NUM; i++) {
+		if (stm32image_dev.part_info[i].binary_type == binary_type) {
+			return i;
+		}
+	}
+
+	return -EINVAL;
+}
+
+/* Open a connection to the STM32IMAGE device */
+static int stm32image_dev_open(const uintptr_t init_params,
+			       io_dev_info_t **dev_info)
+{
+	int i;
+	struct stm32image_device_info *device_info =
+		(struct stm32image_device_info *)init_params;
+
+	assert(dev_info != NULL);
+	*dev_info = (io_dev_info_t *)&stm32image_dev_info;
+
+	stm32image_dev.device_size = device_info->device_size;
+	stm32image_dev.lba_size = device_info->lba_size;
+
+	for (i = 0; i < STM32_PART_NUM; i++) {
+		memcpy(stm32image_dev.part_info[i].name,
+		       device_info->part_info[i].name, MAX_PART_NAME_SIZE);
+		stm32image_dev.part_info[i].part_offset =
+			device_info->part_info[i].part_offset;
+		stm32image_dev.part_info[i].bkp_offset =
+			device_info->part_info[i].bkp_offset;
+	}
+
+	return 0;
+}
+
+/* Do some basic package checks */
+static int stm32image_dev_init(io_dev_info_t *dev_info,
+			       const uintptr_t init_params)
+{
+	int result;
+
+	if ((backend_dev_handle != 0U) || (backend_image_spec != 0U)) {
+		ERROR("STM32 Image io supports only one session\n");
+		return -ENOMEM;
+	}
+
+	/* Obtain a reference to the image by querying the platform layer */
+	result = plat_get_image_source(STM32_IMAGE_ID, &backend_dev_handle,
+				       &backend_image_spec);
+	if (result != 0) {
+		ERROR("STM32 image error (%i)\n", result);
+		return -EINVAL;
+	}
+
+	return result;
+}
+
+/* Close a connection to the STM32 Image device */
+static int stm32image_dev_close(io_dev_info_t *dev_info)
+{
+	backend_dev_handle = 0U;
+	backend_image_spec = 0U;
+	stm32_img = NULL;
+
+	return 0;
+}
+
+/* Open a partition */
+static int stm32image_partition_open(io_dev_info_t *dev_info,
+				     const uintptr_t spec, io_entity_t *entity)
+{
+	const struct stm32image_part_info *partition_spec;
+	int idx;
+
+	assert(entity != NULL);
+
+	partition_spec = (struct stm32image_part_info *)spec;
+	assert(partition_spec != NULL);
+
+	idx = get_part_idx_by_binary_type(partition_spec->binary_type);
+	if ((idx < 0) || (idx > STM32_PART_NUM)) {
+		ERROR("Wrong partition index (%d)\n", idx);
+		return -EINVAL;
+	}
+
+	current_part = &stm32image_dev.part_info[idx];
+	stm32_img = (uint32_t *)&current_part->part_offset;
+
+	return 0;
+}
+
+/* Return the size of a partition */
+static int stm32image_partition_size(io_entity_t *entity, size_t *length)
+{
+	int result;
+	uintptr_t backend_handle;
+	size_t bytes_read;
+	boot_api_image_header_t *header =
+		(boot_api_image_header_t *)first_lba_buffer;
+
+	assert(entity != NULL);
+	assert(length != NULL);
+
+	/* Attempt to access the image */
+	result = io_open(backend_dev_handle, backend_image_spec,
+			 &backend_handle);
+
+	if (result < 0) {
+		ERROR("%s: io_open (%i)\n", __func__, result);
+		return result;
+	}
+
+	/* Reset magic header value */
+	header->magic = 0;
+
+	while (header->magic == 0U) {
+		result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img);
+		if (result != 0) {
+			ERROR("%s: io_seek (%i)\n", __func__, result);
+			break;
+		}
+
+		result = io_read(backend_handle, (uintptr_t)header,
+				 MAX_LBA_SIZE, (size_t *)&bytes_read);
+		if (result != 0) {
+			ERROR("%s: io_read (%i)\n", __func__, result);
+			break;
+		}
+
+		if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) ||
+		    (header->binary_type != current_part->binary_type) ||
+		    (header->image_length >= stm32image_dev.device_size)) {
+			WARN("%s: partition %s wrong header\n",
+			     __func__, current_part->name);
+
+			/* Header not correct, check next offset for backup */
+			*stm32_img += current_part->bkp_offset;
+			if (*stm32_img > stm32image_dev.device_size) {
+				/* No backup found, end of device reached */
+				WARN("Out of memory\n");
+				result = -ENOMEM;
+				break;
+			}
+			header->magic = 0;
+		}
+	}
+
+	io_close(backend_handle);
+
+	if (result != 0) {
+		return result;
+	}
+
+	*length = header->image_length;
+
+	INFO("STM32 Image size : %i\n", *length);
+
+	return 0;
+}
+
+static int check_header(boot_api_image_header_t *header, uintptr_t buffer)
+{
+	uint32_t i;
+	uint32_t img_checksum = 0;
+
+	/*
+	 * Check header/payload validity:
+	 *	- Header magic
+	 *	- Header version
+	 *	- Payload checksum
+	 */
+	if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+		ERROR("Header magic\n");
+		return -EINVAL;
+	}
+
+	if (header->header_version != BOOT_API_HEADER_VERSION) {
+		ERROR("Header version\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < header->image_length; i++) {
+		img_checksum += *(uint8_t *)(buffer + i);
+	}
+
+	if (header->payload_checksum != img_checksum) {
+		ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum,
+		      header->payload_checksum);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Read data from a partition */
+static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
+				     size_t length, size_t *length_read)
+{
+	int result = 0, offset, local_length = 0;
+	uint8_t *local_buffer = (uint8_t *)buffer;
+	boot_api_image_header_t *header =
+		(boot_api_image_header_t *)first_lba_buffer;
+	uintptr_t backend_handle;
+
+	assert(entity != NULL);
+	assert(buffer != 0U);
+	assert(length_read != NULL);
+
+	*length_read = 0U;
+
+	while (*length_read == 0U) {
+		if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+			/* Check for backup as image is corrupted */
+			*stm32_img += current_part->bkp_offset;
+			if (*stm32_img >= stm32image_dev.device_size) {
+				/* End of device reached */
+				result = -ENOMEM;
+				break;
+			}
+
+			local_buffer = (uint8_t *)buffer;
+
+			result = stm32image_partition_size(entity, &length);
+			if (result != 0) {
+				break;
+			}
+		}
+
+		/* Part of image already loaded with the header */
+		memcpy(local_buffer, (uint8_t *)first_lba_buffer +
+		       sizeof(boot_api_image_header_t),
+		       MAX_LBA_SIZE - sizeof(boot_api_image_header_t));
+		local_buffer += MAX_LBA_SIZE - sizeof(boot_api_image_header_t);
+		offset = MAX_LBA_SIZE;
+
+		/* New image length to be read */
+		local_length = round_up(length -
+					((MAX_LBA_SIZE) -
+					 sizeof(boot_api_image_header_t)),
+					stm32image_dev.lba_size);
+
+		if ((header->load_address != 0U) &&
+		    (header->load_address != buffer)) {
+			ERROR("Wrong load address\n");
+			panic();
+		}
+
+		result = io_open(backend_dev_handle, backend_image_spec,
+				 &backend_handle);
+
+		if (result != 0) {
+			ERROR("%s: io_open (%i)\n", __func__, result);
+			break;
+		}
+
+		result = io_seek(backend_handle, IO_SEEK_SET,
+				 *stm32_img + offset);
+
+		if (result != 0) {
+			ERROR("%s: io_seek (%i)\n", __func__, result);
+			*length_read = 0;
+			io_close(backend_handle);
+			break;
+		}
+
+		result = io_read(backend_handle, (uintptr_t)local_buffer,
+				 local_length, length_read);
+
+		/* Adding part of size already read from header */
+		*length_read += MAX_LBA_SIZE - sizeof(boot_api_image_header_t);
+
+		if (result != 0) {
+			ERROR("%s: io_read (%i)\n", __func__, result);
+			*length_read = 0;
+			io_close(backend_handle);
+			break;
+		}
+
+		result = check_header(header, buffer);
+		if (result != 0) {
+			ERROR("Header check failed\n");
+			*length_read = 0;
+			header->magic = 0;
+			io_close(backend_handle);
+			break;
+		}
+
+		io_close(backend_handle);
+	}
+
+	return result;
+}
+
+/* Close a partition */
+static int stm32image_partition_close(io_entity_t *entity)
+{
+	current_part = NULL;
+
+	return 0;
+}
+
+/* Register the stm32image driver with the IO abstraction */
+int register_io_dev_stm32image(const io_dev_connector_t **dev_con)
+{
+	int result;
+
+	assert(dev_con != NULL);
+
+	result = io_register_device(&stm32image_dev_info);
+	if (result == 0) {
+		*dev_con = &stm32image_dev_connector;
+	}
+
+	return result;
+}
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
new file mode 100644
index 0000000..633a425
--- /dev/null
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -0,0 +1,735 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <mmc.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stm32_sdmmc2.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_rcc.h>
+#include <stm32mp1_reset.h>
+#include <string.h>
+#include <utils.h>
+
+/* Registers offsets */
+#define SDMMC_POWER			0x00U
+#define SDMMC_CLKCR			0x04U
+#define SDMMC_ARGR			0x08U
+#define SDMMC_CMDR			0x0CU
+#define SDMMC_RESPCMDR			0x10U
+#define SDMMC_RESP1R			0x14U
+#define SDMMC_RESP2R			0x18U
+#define SDMMC_RESP3R			0x1CU
+#define SDMMC_RESP4R			0x20U
+#define SDMMC_DTIMER			0x24U
+#define SDMMC_DLENR			0x28U
+#define SDMMC_DCTRLR			0x2CU
+#define SDMMC_DCNTR			0x30U
+#define SDMMC_STAR			0x34U
+#define SDMMC_ICR			0x38U
+#define SDMMC_MASKR			0x3CU
+#define SDMMC_ACKTIMER			0x40U
+#define SDMMC_IDMACTRLR			0x50U
+#define SDMMC_IDMABSIZER		0x54U
+#define SDMMC_IDMABASE0R		0x58U
+#define SDMMC_IDMABASE1R		0x5CU
+#define SDMMC_FIFOR			0x80U
+
+/* SDMMC power control register */
+#define SDMMC_POWER_PWRCTRL		GENMASK(1, 0)
+#define SDMMC_POWER_DIRPOL		BIT(4)
+
+/* SDMMC clock control register */
+#define SDMMC_CLKCR_WIDBUS_4		BIT(14)
+#define SDMMC_CLKCR_WIDBUS_8		BIT(15)
+#define SDMMC_CLKCR_NEGEDGE		BIT(16)
+#define SDMMC_CLKCR_HWFC_EN		BIT(17)
+#define SDMMC_CLKCR_SELCLKRX_0		BIT(20)
+
+/* SDMMC command register */
+#define SDMMC_CMDR_CMDTRANS		BIT(6)
+#define SDMMC_CMDR_CMDSTOP		BIT(7)
+#define SDMMC_CMDR_WAITRESP		GENMASK(9, 8)
+#define SDMMC_CMDR_WAITRESP_SHORT	BIT(8)
+#define SDMMC_CMDR_WAITRESP_SHORT_NOCRC	BIT(9)
+#define SDMMC_CMDR_CPSMEN		BIT(12)
+
+/* SDMMC data control register */
+#define SDMMC_DCTRLR_DTEN		BIT(0)
+#define SDMMC_DCTRLR_DTDIR		BIT(1)
+#define SDMMC_DCTRLR_DTMODE		GENMASK(3, 2)
+#define SDMMC_DCTRLR_DBLOCKSIZE_0	BIT(4)
+#define SDMMC_DCTRLR_DBLOCKSIZE_1	BIT(5)
+#define SDMMC_DCTRLR_DBLOCKSIZE_3	BIT(7)
+#define SDMMC_DCTRLR_DBLOCKSIZE		GENMASK(7, 4)
+#define SDMMC_DCTRLR_FIFORST		BIT(13)
+
+#define SDMMC_DCTRLR_CLEAR_MASK		(SDMMC_DCTRLR_DTEN | \
+					 SDMMC_DCTRLR_DTDIR | \
+					 SDMMC_DCTRLR_DTMODE | \
+					 SDMMC_DCTRLR_DBLOCKSIZE)
+#define SDMMC_DBLOCKSIZE_8		(SDMMC_DCTRLR_DBLOCKSIZE_0 | \
+					 SDMMC_DCTRLR_DBLOCKSIZE_1)
+#define SDMMC_DBLOCKSIZE_512		(SDMMC_DCTRLR_DBLOCKSIZE_0 | \
+					 SDMMC_DCTRLR_DBLOCKSIZE_3)
+
+/* SDMMC status register */
+#define SDMMC_STAR_CCRCFAIL		BIT(0)
+#define SDMMC_STAR_DCRCFAIL		BIT(1)
+#define SDMMC_STAR_CTIMEOUT		BIT(2)
+#define SDMMC_STAR_DTIMEOUT		BIT(3)
+#define SDMMC_STAR_TXUNDERR		BIT(4)
+#define SDMMC_STAR_RXOVERR		BIT(5)
+#define SDMMC_STAR_CMDREND		BIT(6)
+#define SDMMC_STAR_CMDSENT		BIT(7)
+#define SDMMC_STAR_DATAEND		BIT(8)
+#define SDMMC_STAR_DBCKEND		BIT(10)
+#define SDMMC_STAR_DPSMACT		BIT(11)
+#define SDMMC_STAR_RXFIFOHF		BIT(15)
+#define SDMMC_STAR_RXFIFOE		BIT(19)
+#define SDMMC_STAR_IDMATE		BIT(27)
+#define SDMMC_STAR_IDMABTC		BIT(28)
+
+/* SDMMC DMA control register */
+#define SDMMC_IDMACTRLR_IDMAEN		BIT(0)
+
+#define SDMMC_STATIC_FLAGS		(SDMMC_STAR_CCRCFAIL | \
+					 SDMMC_STAR_DCRCFAIL | \
+					 SDMMC_STAR_CTIMEOUT | \
+					 SDMMC_STAR_DTIMEOUT | \
+					 SDMMC_STAR_TXUNDERR | \
+					 SDMMC_STAR_RXOVERR  | \
+					 SDMMC_STAR_CMDREND  | \
+					 SDMMC_STAR_CMDSENT  | \
+					 SDMMC_STAR_DATAEND  | \
+					 SDMMC_STAR_DBCKEND  | \
+					 SDMMC_STAR_IDMATE   | \
+					 SDMMC_STAR_IDMABTC)
+
+#define TIMEOUT_10_MS			(plat_get_syscnt_freq2() / 100U)
+#define TIMEOUT_1_S			plat_get_syscnt_freq2()
+
+#define DT_SDMMC2_COMPAT		"st,stm32-sdmmc2"
+
+static void stm32_sdmmc2_init(void);
+static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd);
+static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd);
+static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width);
+static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size);
+static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size);
+static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size);
+
+static const struct mmc_ops stm32_sdmmc2_ops = {
+	.init		= stm32_sdmmc2_init,
+	.send_cmd	= stm32_sdmmc2_send_cmd,
+	.set_ios	= stm32_sdmmc2_set_ios,
+	.prepare	= stm32_sdmmc2_prepare,
+	.read		= stm32_sdmmc2_read,
+	.write		= stm32_sdmmc2_write,
+};
+
+static struct stm32_sdmmc2_params sdmmc2_params;
+
+#pragma weak plat_sdmmc2_use_dma
+bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory)
+{
+	return false;
+}
+
+static void stm32_sdmmc2_init(void)
+{
+	uint32_t clock_div;
+	uintptr_t base = sdmmc2_params.reg_base;
+
+	clock_div = div_round_up(sdmmc2_params.clk_rate,
+				 STM32MP1_MMC_INIT_FREQ * 2);
+
+	mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div |
+		      sdmmc2_params.negedge |
+		      sdmmc2_params.pin_ckin);
+
+	mmio_write_32(base + SDMMC_POWER,
+		      SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol);
+
+	mdelay(1);
+}
+
+static int stm32_sdmmc2_stop_transfer(void)
+{
+	struct mmc_cmd cmd_stop;
+
+	zeromem(&cmd_stop, sizeof(struct mmc_cmd));
+
+	cmd_stop.cmd_idx = MMC_CMD(12);
+	cmd_stop.resp_type = MMC_RESPONSE_R1B;
+
+	return stm32_sdmmc2_send_cmd(&cmd_stop);
+}
+
+static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd)
+{
+	uint32_t flags_cmd, status;
+	uint32_t flags_data = 0;
+	int err = 0;
+	uintptr_t base = sdmmc2_params.reg_base;
+	unsigned int cmd_reg, arg_reg, start;
+
+	if (cmd == NULL) {
+		return -EINVAL;
+	}
+
+	flags_cmd = SDMMC_STAR_CTIMEOUT;
+	arg_reg = cmd->cmd_arg;
+
+	if ((mmio_read_32(base + SDMMC_CMDR) & SDMMC_CMDR_CPSMEN) != 0U) {
+		mmio_write_32(base + SDMMC_CMDR, 0);
+	}
+
+	cmd_reg = cmd->cmd_idx | SDMMC_CMDR_CPSMEN;
+
+	if (cmd->resp_type == 0U) {
+		flags_cmd |= SDMMC_STAR_CMDSENT;
+	}
+
+	if ((cmd->resp_type & MMC_RSP_48) != 0U) {
+		if ((cmd->resp_type & MMC_RSP_136) != 0U) {
+			flags_cmd |= SDMMC_STAR_CMDREND;
+			cmd_reg |= SDMMC_CMDR_WAITRESP;
+		} else if ((cmd->resp_type & MMC_RSP_CRC) != 0U) {
+			flags_cmd |= SDMMC_STAR_CMDREND | SDMMC_STAR_CCRCFAIL;
+			cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT;
+		} else {
+			flags_cmd |= SDMMC_STAR_CMDREND;
+			cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT_NOCRC;
+		}
+	}
+
+	switch (cmd->cmd_idx) {
+	case MMC_CMD(1):
+		arg_reg |= OCR_POWERUP;
+		break;
+	case MMC_CMD(8):
+		if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) {
+			cmd_reg |= SDMMC_CMDR_CMDTRANS;
+		}
+		break;
+	case MMC_CMD(12):
+		cmd_reg |= SDMMC_CMDR_CMDSTOP;
+		break;
+	case MMC_CMD(17):
+	case MMC_CMD(18):
+		cmd_reg |= SDMMC_CMDR_CMDTRANS;
+		if (sdmmc2_params.use_dma) {
+			flags_data |= SDMMC_STAR_DCRCFAIL |
+				      SDMMC_STAR_DTIMEOUT |
+				      SDMMC_STAR_DATAEND |
+				      SDMMC_STAR_RXOVERR |
+				      SDMMC_STAR_IDMATE;
+		}
+		break;
+	case MMC_ACMD(41):
+		arg_reg |= OCR_3_2_3_3 | OCR_3_3_3_4;
+		break;
+	case MMC_ACMD(51):
+		cmd_reg |= SDMMC_CMDR_CMDTRANS;
+		if (sdmmc2_params.use_dma) {
+			flags_data |= SDMMC_STAR_DCRCFAIL |
+				      SDMMC_STAR_DTIMEOUT |
+				      SDMMC_STAR_DATAEND |
+				      SDMMC_STAR_RXOVERR |
+				      SDMMC_STAR_IDMATE |
+				      SDMMC_STAR_DBCKEND;
+		}
+		break;
+	default:
+		break;
+	}
+
+	if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) {
+		mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
+	}
+
+	mmio_write_32(base + SDMMC_ARGR, arg_reg);
+
+	mmio_write_32(base + SDMMC_CMDR, cmd_reg);
+
+	start = get_timer(0);
+
+	do {
+		status = mmio_read_32(base + SDMMC_STAR);
+
+		if (get_timer(start) > TIMEOUT_10_MS) {
+			err = -ETIMEDOUT;
+			ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n",
+			      __func__, cmd->cmd_idx, status);
+			break;
+		}
+	} while ((status & flags_cmd) == 0U);
+
+	if (((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) &&
+	    (err == 0)) {
+		if ((status & SDMMC_STAR_CTIMEOUT) != 0U) {
+			err = -ETIMEDOUT;
+			/*
+			 * Those timeouts can occur, and framework will handle
+			 * the retries. CMD8 is expected to return this timeout
+			 * for eMMC
+			 */
+			if (!((cmd->cmd_idx == MMC_CMD(1)) ||
+			      (cmd->cmd_idx == MMC_CMD(13)) ||
+			      ((cmd->cmd_idx == MMC_CMD(8)) &&
+			       (cmd->resp_type == MMC_RESPONSE_R7)))) {
+				ERROR("%s: CTIMEOUT (cmd = %d,status = %x)\n",
+				      __func__, cmd->cmd_idx, status);
+			}
+		} else {
+			err = -EIO;
+			ERROR("%s: CRCFAIL (cmd = %d,status = %x)\n",
+			      __func__, cmd->cmd_idx, status);
+		}
+	}
+
+	if (((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) && (err == 0)) {
+		if ((cmd->cmd_idx == MMC_CMD(9)) &&
+		    ((cmd_reg & SDMMC_CMDR_WAITRESP) == SDMMC_CMDR_WAITRESP)) {
+			/* Need to invert response to match CSD structure */
+			cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP4R);
+			cmd->resp_data[1] = mmio_read_32(base + SDMMC_RESP3R);
+			cmd->resp_data[2] = mmio_read_32(base + SDMMC_RESP2R);
+			cmd->resp_data[3] = mmio_read_32(base + SDMMC_RESP1R);
+		} else {
+			cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP1R);
+			if ((cmd_reg & SDMMC_CMDR_WAITRESP) ==
+			    SDMMC_CMDR_WAITRESP) {
+				cmd->resp_data[1] = mmio_read_32(base +
+								 SDMMC_RESP2R);
+				cmd->resp_data[2] = mmio_read_32(base +
+								 SDMMC_RESP3R);
+				cmd->resp_data[3] = mmio_read_32(base +
+								 SDMMC_RESP4R);
+			}
+		}
+	}
+
+	if ((flags_data == 0U) || (err != 0)) {
+		if (flags_data != 0U) {
+			mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS);
+		}
+
+		mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+
+		if ((err != 0) && (flags_data != 0U)) {
+			return stm32_sdmmc2_stop_transfer();
+		}
+
+		return err;
+	}
+
+	start = get_timer(0);
+
+	do {
+		status = mmio_read_32(base + SDMMC_STAR);
+
+		if (get_timer(start) > TIMEOUT_10_MS) {
+			ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n",
+			      __func__, cmd->cmd_idx, status);
+			err = -ETIMEDOUT;
+			break;
+		}
+	} while ((status & flags_data) == 0U);
+
+	if ((status & (SDMMC_STAR_DTIMEOUT | SDMMC_STAR_DCRCFAIL |
+		       SDMMC_STAR_TXUNDERR | SDMMC_STAR_RXOVERR |
+		       SDMMC_STAR_IDMATE)) != 0U) {
+		ERROR("%s: Error flag (cmd = %d,status = %x)\n", __func__,
+		      cmd->cmd_idx, status);
+		err = -EIO;
+	}
+
+	mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+	mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS);
+
+	if (err != 0) {
+		return stm32_sdmmc2_stop_transfer();
+	}
+
+	return err;
+}
+
+static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd)
+{
+	int8_t retry;
+	int err = 0;
+
+	assert(cmd != NULL);
+
+	for (retry = 0; retry <= 3; retry++) {
+		err = stm32_sdmmc2_send_cmd_req(cmd);
+		if (err == 0) {
+			return err;
+		}
+
+		if ((cmd->cmd_idx == MMC_CMD(1)) ||
+		    (cmd->cmd_idx == MMC_CMD(13))) {
+			return 0; /* Retry managed by framework */
+		}
+
+		/* Command 8 is expected to fail for eMMC */
+		if (!(cmd->cmd_idx == MMC_CMD(8))) {
+			WARN(" CMD%d, Retry: %d, Error: %d\n",
+			     cmd->cmd_idx, retry, err);
+		}
+
+		udelay(10);
+	}
+
+	return err;
+}
+
+static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width)
+{
+	uintptr_t base = sdmmc2_params.reg_base;
+	uint32_t bus_cfg = 0;
+	uint32_t clock_div, max_freq;
+	uint32_t clk_rate = sdmmc2_params.clk_rate;
+	uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq;
+
+	switch (width) {
+	case MMC_BUS_WIDTH_1:
+		break;
+	case MMC_BUS_WIDTH_4:
+		bus_cfg |= SDMMC_CLKCR_WIDBUS_4;
+		break;
+	case MMC_BUS_WIDTH_8:
+		bus_cfg |= SDMMC_CLKCR_WIDBUS_8;
+		break;
+	default:
+		panic();
+		break;
+	}
+
+	if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) {
+		if (max_bus_freq >= 52000000U) {
+			max_freq = STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ;
+		} else {
+			max_freq = STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ;
+		}
+	} else {
+		if (max_bus_freq >= 50000000U) {
+			max_freq = STM32MP1_SD_HIGH_SPEED_MAX_FREQ;
+		} else {
+			max_freq = STM32MP1_SD_NORMAL_SPEED_MAX_FREQ;
+		}
+	}
+
+	clock_div = div_round_up(clk_rate, max_freq * 2);
+
+	mmio_write_32(base + SDMMC_CLKCR,
+		      SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg |
+		      sdmmc2_params.negedge |
+		      sdmmc2_params.pin_ckin);
+
+	return 0;
+}
+
+static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
+{
+	struct mmc_cmd cmd;
+	int ret;
+	uintptr_t base = sdmmc2_params.reg_base;
+	uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR;
+
+	if (size == 8U) {
+		data_ctrl |= SDMMC_DBLOCKSIZE_8;
+	} else {
+		data_ctrl |= SDMMC_DBLOCKSIZE_512;
+	}
+
+	sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf);
+
+	if (sdmmc2_params.use_dma) {
+		inv_dcache_range(buf, size);
+	}
+
+	/* Prepare CMD 16*/
+	mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
+
+	mmio_write_32(base + SDMMC_DLENR, 0);
+
+	mmio_clrsetbits_32(base + SDMMC_DCTRLR,
+			   SDMMC_DCTRLR_CLEAR_MASK, SDMMC_DCTRLR_DTDIR);
+
+	zeromem(&cmd, sizeof(struct mmc_cmd));
+
+	cmd.cmd_idx = MMC_CMD(16);
+	if (size > MMC_BLOCK_SIZE) {
+		cmd.cmd_arg = MMC_BLOCK_SIZE;
+	} else {
+		cmd.cmd_arg = size;
+	}
+
+	cmd.resp_type = MMC_RESPONSE_R1;
+
+	ret = stm32_sdmmc2_send_cmd(&cmd);
+	if (ret != 0) {
+		ERROR("CMD16 failed\n");
+		return ret;
+	}
+
+	/* Prepare data command */
+	mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
+
+	mmio_write_32(base + SDMMC_DLENR, size);
+
+	if (sdmmc2_params.use_dma) {
+		mmio_write_32(base + SDMMC_IDMACTRLR,
+			      SDMMC_IDMACTRLR_IDMAEN);
+		mmio_write_32(base + SDMMC_IDMABASE0R, buf);
+
+		flush_dcache_range(buf, size);
+	}
+
+	mmio_clrsetbits_32(base + SDMMC_DCTRLR,
+			   SDMMC_DCTRLR_CLEAR_MASK,
+			   data_ctrl);
+
+	return 0;
+}
+
+static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size)
+{
+	uint32_t error_flags = SDMMC_STAR_RXOVERR | SDMMC_STAR_DCRCFAIL |
+			       SDMMC_STAR_DTIMEOUT;
+	uint32_t flags = error_flags | SDMMC_STAR_DATAEND;
+	uint32_t status;
+	uint32_t *buffer;
+	uintptr_t base = sdmmc2_params.reg_base;
+	uintptr_t fifo_reg = base + SDMMC_FIFOR;
+	unsigned int start;
+	int ret;
+
+	/* Assert buf is 4 bytes aligned */
+	assert((buf & GENMASK(1, 0)) == 0U);
+
+	buffer = (uint32_t *)buf;
+
+	if (sdmmc2_params.use_dma) {
+		inv_dcache_range(buf, size);
+
+		return 0;
+	}
+
+	if (size <= MMC_BLOCK_SIZE) {
+		flags |= SDMMC_STAR_DBCKEND;
+	}
+
+	start = get_timer(0);
+
+	do {
+		status = mmio_read_32(base + SDMMC_STAR);
+
+		if ((status & error_flags) != 0U) {
+			ERROR("%s: Read error (status = %x)\n", __func__,
+			      status);
+			mmio_write_32(base + SDMMC_DCTRLR,
+				      SDMMC_DCTRLR_FIFORST);
+
+			mmio_write_32(base + SDMMC_ICR,
+				      SDMMC_STATIC_FLAGS);
+
+			ret = stm32_sdmmc2_stop_transfer();
+			if (ret != 0) {
+				return ret;
+			}
+
+			return -EIO;
+		}
+
+		if (get_timer(start) > TIMEOUT_1_S) {
+			ERROR("%s: timeout 1s (status = %x)\n",
+			      __func__, status);
+			mmio_write_32(base + SDMMC_ICR,
+				      SDMMC_STATIC_FLAGS);
+
+			ret = stm32_sdmmc2_stop_transfer();
+			if (ret != 0) {
+				return ret;
+			}
+
+			return -ETIMEDOUT;
+		}
+
+		if (size < (8U * sizeof(uint32_t))) {
+			if ((mmio_read_32(base + SDMMC_DCNTR) > 0U) &&
+			    ((status & SDMMC_STAR_RXFIFOE) == 0U)) {
+				*buffer = mmio_read_32(fifo_reg);
+				buffer++;
+			}
+		} else if ((status & SDMMC_STAR_RXFIFOHF) != 0U) {
+			uint32_t count;
+
+			/* Read data from SDMMC Rx FIFO */
+			for (count = 0; count < 8U; count++) {
+				*buffer = mmio_read_32(fifo_reg);
+				buffer++;
+			}
+		}
+	} while ((status & flags) == 0U);
+
+	mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+
+	if ((status & SDMMC_STAR_DPSMACT) != 0U) {
+		WARN("%s: DPSMACT=1, send stop\n", __func__);
+		return stm32_sdmmc2_stop_transfer();
+	}
+
+	return 0;
+}
+
+static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size)
+{
+	return 0;
+}
+
+static int stm32_sdmmc2_dt_get_config(void)
+{
+	int sdmmc_node;
+	void *fdt = NULL;
+	const fdt32_t *cuint;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if (fdt == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	sdmmc_node = fdt_node_offset_by_compatible(fdt, -1, DT_SDMMC2_COMPAT);
+
+	while (sdmmc_node != -FDT_ERR_NOTFOUND) {
+		cuint = fdt_getprop(fdt, sdmmc_node, "reg", NULL);
+		if (cuint == NULL) {
+			continue;
+		}
+
+		if (fdt32_to_cpu(*cuint) == sdmmc2_params.reg_base) {
+			break;
+		}
+
+		sdmmc_node = fdt_node_offset_by_compatible(fdt, sdmmc_node,
+							   DT_SDMMC2_COMPAT);
+	}
+
+	if (sdmmc_node == -FDT_ERR_NOTFOUND) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if (fdt_check_status(sdmmc_node) == 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if (dt_set_pinctrl_config(sdmmc_node) != 0) {
+		return -FDT_ERR_BADVALUE;
+	}
+
+	cuint = fdt_getprop(fdt, sdmmc_node, "clocks", NULL);
+	if (cuint == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	cuint++;
+	sdmmc2_params.clock_id = fdt32_to_cpu(*cuint);
+
+	cuint = fdt_getprop(fdt, sdmmc_node, "resets", NULL);
+	if (cuint == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	cuint++;
+	sdmmc2_params.reset_id = fdt32_to_cpu(*cuint);
+
+	if ((fdt_getprop(fdt, sdmmc_node, "st,pin-ckin", NULL)) != NULL) {
+		sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0;
+	}
+
+	if ((fdt_getprop(fdt, sdmmc_node, "st,dirpol", NULL)) != NULL) {
+		sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL;
+	}
+
+	if ((fdt_getprop(fdt, sdmmc_node, "st,negedge", NULL)) != NULL) {
+		sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE;
+	}
+
+	cuint = fdt_getprop(fdt, sdmmc_node, "bus-width", NULL);
+	if (cuint != NULL) {
+		switch (fdt32_to_cpu(*cuint)) {
+		case 4:
+			sdmmc2_params.bus_width = MMC_BUS_WIDTH_4;
+			break;
+
+		case 8:
+			sdmmc2_params.bus_width = MMC_BUS_WIDTH_8;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+unsigned long long stm32_sdmmc2_mmc_get_device_size(void)
+{
+	return sdmmc2_params.device_info->device_size;
+}
+
+int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params)
+{
+	int ret;
+
+	assert((params != NULL) &&
+	       ((params->reg_base & MMC_BLOCK_MASK) == 0U) &&
+	       ((params->bus_width == MMC_BUS_WIDTH_1) ||
+		(params->bus_width == MMC_BUS_WIDTH_4) ||
+		(params->bus_width == MMC_BUS_WIDTH_8)));
+
+	memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params));
+
+	if (stm32_sdmmc2_dt_get_config() != 0) {
+		ERROR("%s: DT error\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = stm32mp1_clk_enable(sdmmc2_params.clock_id);
+	if (ret != 0) {
+		ERROR("%s: clock %d failed\n", __func__,
+		      sdmmc2_params.clock_id);
+		return ret;
+	}
+
+	stm32mp1_reset_assert(sdmmc2_params.reset_id);
+	udelay(2);
+	stm32mp1_reset_deassert(sdmmc2_params.reset_id);
+	mdelay(1);
+
+	sdmmc2_params.clk_rate = stm32mp1_clk_get_rate(sdmmc2_params.clock_id);
+
+	return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate,
+			sdmmc2_params.bus_width, sdmmc2_params.flags,
+			sdmmc2_params.device_info);
+}
diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S
index 0f9a9d5..785b640 100644
--- a/drivers/ti/uart/aarch64/16550_console.S
+++ b/drivers/ti/uart/aarch64/16550_console.S
@@ -7,6 +7,7 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <assert_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
 #include <console_macros.S>
 #include <uart_16550.h>
 
@@ -112,7 +113,7 @@
 
 	mov	x0, x6
 	mov	x30, x7
-	finish_console_register 16550
+	finish_console_register 16550 putc=1, getc=1, flush=1
 
 register_fail:
 	ret	x7
diff --git a/include/common/aarch32/console_macros.S b/include/common/aarch32/console_macros.S
index 480e3c2..7c30688 100644
--- a/include/common/aarch32/console_macros.S
+++ b/include/common/aarch32/console_macros.S
@@ -17,6 +17,14 @@
  * with a tail call that will include return to the caller.
  * REQUIRES console_t pointer in x0 and a valid return address in x30.
  */
+/*
+ * The USE_FINISH_CONSOLE_REG_2 guard is introduced to allow selection between
+ * the 2 variants of the finish_console_register macro and will be removed
+ * once the deprecated variant is removed.
+ */
+#ifndef USE_FINISH_CONSOLE_REG_2
+#if !ERROR_DEPRECATED
+	/* This version of the macro is deprecated. Use the new version */
 	.macro	finish_console_register _driver
 	/*
 	 * Add these weak definitions so we will automatically write a 0 if the
@@ -39,5 +47,38 @@
 	str	r1, [r0, #CONSOLE_T_FLAGS]
 	b	console_register
 	.endm
+#endif /* ERROR_DEPRECATED */
+#else /* USE_FINISH_CONSOLE_REG_2 */
+	/* The new version of the macro not using weak references */
+	.macro	finish_console_register _driver, putc=0, getc=0, flush=0
+	/*
+	 * If any of the callback is not specified or set as 0, then the
+	 * corresponding callback entry in console_t is set to 0.
+	 */
+	.ifne \putc
+	  ldr	r1, =console_\_driver\()_putc
+	.else
+	  mov	r1, #0
+	.endif
+	str	r1, [r0, #CONSOLE_T_PUTC]
 
+	.ifne \getc
+	  ldr	r1, =console_\_driver\()_getc
+	.else
+	  mov	r1, #0
+	.endif
+	str	r1, [r0, #CONSOLE_T_GETC]
+
+	.ifne \flush
+	  ldr	r1, =console_\_driver\()_flush
+	.else
+	  mov	r1, #0
+	.endif
+	str	r1, [r0, #CONSOLE_T_FLUSH]
+
+	mov	r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH)
+	str	r1, [r0, #CONSOLE_T_FLAGS]
+	b	console_register
+	.endm
+#endif /* USE_FINISH_CONSOLE_REG_2 */
 #endif /* __CONSOLE_MACROS_S__ */
diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S
index 9621a1c..91416e4 100644
--- a/include/common/aarch64/asm_macros.S
+++ b/include/common/aarch64/asm_macros.S
@@ -105,8 +105,9 @@
 	 * Clobber: X30, X1, X2
 	 */
 	.macro get_my_mp_stack _name, _size
-	bl  plat_my_core_pos
-	ldr x2, =(\_name + \_size)
+	bl	plat_my_core_pos
+	adrp	x2, (\_name + \_size)
+	add	x2, x2, :lo12:(\_name + \_size)
 	mov x1, #\_size
 	madd x0, x0, x1, x2
 	.endm
@@ -117,7 +118,8 @@
 	 * Out: X0 = physical address of stack base
 	 */
 	.macro get_up_stack _name, _size
-	ldr x0, =(\_name + \_size)
+	adrp	x0, (\_name + \_size)
+	add	x0, x0, :lo12:(\_name + \_size)
 	.endm
 
 	/*
diff --git a/include/common/aarch64/console_macros.S b/include/common/aarch64/console_macros.S
index 0ebea2c..b285ecc 100644
--- a/include/common/aarch64/console_macros.S
+++ b/include/common/aarch64/console_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,6 +17,14 @@
  * with a tail call that will include return to the caller.
  * REQUIRES console_t pointer in x0 and a valid return address in x30.
  */
+/*
+ * The USE_FINISH_CONSOLE_REG_2 guard is introduced to allow selection between
+ * the 2 variants of the finish_console_register macro and will be removed
+ * once the deprecated variant is removed.
+ */
+#ifndef USE_FINISH_CONSOLE_REG_2
+#if !ERROR_DEPRECATED
+	/* This version of the macro is deprecated. Use the new version */
 	.macro	finish_console_register _driver
 	/*
 	 * Add these weak definitions so we will automatically write a 0 if the
@@ -39,5 +47,41 @@
 	str	x1, [x0, #CONSOLE_T_FLAGS]
 	b	console_register
 	.endm
+#endif /* ERROR_DEPRECATED */
+#else /* USE_FINISH_CONSOLE_REG_2 */
+	/* The new version of the macro not using weak references */
+	.macro	finish_console_register _driver, putc=0, getc=0, flush=0
+	/*
+	 * If any of the callback is not specified or set as 0, then the
+	 * corresponding callback entry in console_t is set to 0.
+	 */
+	.ifne \putc
+	  adrp	x1, console_\_driver\()_putc
+	  add	x1, x1, :lo12:console_\_driver\()_putc
+	  str	x1, [x0, #CONSOLE_T_PUTC]
+	.else
+	  str	xzr, [x0, #CONSOLE_T_PUTC]
+	.endif
 
+	.ifne \getc
+	  adrp	x1, console_\_driver\()_getc
+	  add	x1, x1, :lo12:console_\_driver\()_getc
+	  str	x1, [x0, #CONSOLE_T_GETC]
+	.else
+	  str	xzr, [x0, #CONSOLE_T_GETC]
+	.endif
+
+	.ifne \flush
+	  adrp	x1, console_\_driver\()_flush
+	  add	x1, x1, :lo12:console_\_driver\()_flush
+	  str	x1, [x0, #CONSOLE_T_FLUSH]
+	.else
+	  str	xzr, [x0, #CONSOLE_T_FLUSH]
+	.endif
+
+	mov	x1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH)
+	str	x1, [x0, #CONSOLE_T_FLAGS]
+	b	console_register
+	.endm
+#endif /* USE_FINISH_CONSOLE_REG_2 */
 #endif /* __CONSOLE_MACROS_S__ */
diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S
index 03b977e..4902583 100644
--- a/include/common/aarch64/el3_common_macros.S
+++ b/include/common/aarch64/el3_common_macros.S
@@ -70,9 +70,14 @@
 	 *
 	 * SCR_EL3.EA: Set to one to route External Aborts and SError Interrupts
 	 *  to EL3 when executing at any EL.
+	 *
+	 * SCR_EL3.{API,APK}: For Armv8.3 pointer authentication feature,
+	 * disable traps to EL3 when accessing key registers or using pointer
+	 * authentication instructions from lower ELs.
 	 * ---------------------------------------------------------------------
 	 */
-	mov	x0, #((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT) \
+	mov_imm	x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT | \
+				SCR_API_BIT | SCR_APK_BIT) \
 			& ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT))
 	msr	scr_el3, x0
 
@@ -278,26 +283,38 @@
 		 * an earlier boot loader stage.
 		 * -------------------------------------------------------------
 		 */
-		ldr	x0, =__RW_START__
-		ldr	x1, =__RW_END__
+		adrp	x0, __RW_START__
+		add	x0, x0, :lo12:__RW_START__
+		adrp	x1, __RW_END__
+		add	x1, x1, :lo12:__RW_END__
 		sub	x1, x1, x0
 		bl	inv_dcache_range
 #endif
+		adrp	x0, __BSS_START__
+		add	x0, x0, :lo12:__BSS_START__
 
-		ldr	x0, =__BSS_START__
-		ldr	x1, =__BSS_SIZE__
+		adrp	x1, __BSS_END__
+		add	x1, x1, :lo12:__BSS_END__
+		sub	x1, x1, x0
 		bl	zeromem
 
 #if USE_COHERENT_MEM
-		ldr	x0, =__COHERENT_RAM_START__
-		ldr	x1, =__COHERENT_RAM_UNALIGNED_SIZE__
+		adrp	x0, __COHERENT_RAM_START__
+		add	x0, x0, :lo12:__COHERENT_RAM_START__
+		adrp	x1, __COHERENT_RAM_END_UNALIGNED__
+		add	x1, x1, :lo12: __COHERENT_RAM_END_UNALIGNED__
+		sub	x1, x1, x0
 		bl	zeromem
 #endif
 
 #if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_IN_XIP_MEM)
-		ldr	x0, =__DATA_RAM_START__
-		ldr	x1, =__DATA_ROM_START__
-		ldr	x2, =__DATA_SIZE__
+		adrp	x0, __DATA_RAM_START__
+		add	x0, x0, :lo12:__DATA_RAM_START__
+		adrp	x1, __DATA_ROM_START__
+		add	x1, x1, :lo12:__DATA_ROM_START__
+		adrp	x2, __DATA_RAM_END__
+		add	x2, x2, :lo12:__DATA_RAM_END__
+		sub	x2, x2, x0
 		bl	memcpy16
 #endif
 	.endif /* _init_c_runtime */
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index af598d0..6a79dc3 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -83,6 +83,7 @@
 #elif defined(IMAGE_BL2U)
 IMPORT_SYM(unsigned long, __BL2U_END__,		BL2U_END);
 #elif defined(IMAGE_BL31)
+IMPORT_SYM(unsigned long, __BL31_START__,	BL31_START);
 IMPORT_SYM(unsigned long, __BL31_END__,		BL31_END);
 #elif defined(IMAGE_BL32)
 IMPORT_SYM(unsigned long, __BL32_END__,		BL32_END);
@@ -193,6 +194,11 @@
 void print_entry_point_info(const entry_point_info_t *ep_info);
 uintptr_t page_align(uintptr_t value, unsigned dir);
 
+struct mmap_region;
+
+void setup_page_tables(const struct mmap_region *bl_regions,
+			   const struct mmap_region *plat_regions);
+
 #endif /*__ASSEMBLY__*/
 
 #endif /* __BL_COMMON_H__ */
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index a97914d..96bfb53 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -77,7 +77,13 @@
 /* NT_FW_CONFIG */
 #define NT_FW_CONFIG_ID			U(27)
 
+/* GPT Partition */
+#define GPT_IMAGE_ID			U(28)
+
+/* Binary with STM32 header */
+#define STM32_IMAGE_ID			U(29)
+
 /* Define size of the array */
-#define MAX_NUMBER_IDS			U(28)
+#define MAX_NUMBER_IDS			U(30)
 
 #endif /* __TBBR_IMG_DEF_H__ */
diff --git a/include/drivers/allwinner/sunxi_rsb.h b/include/drivers/allwinner/sunxi_rsb.h
new file mode 100644
index 0000000..5a69d35
--- /dev/null
+++ b/include/drivers/allwinner/sunxi_rsb.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_RSB_H
+#define SUNXI_RSB_H
+
+#include <stdint.h>
+
+int rsb_init_controller(void);
+int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq);
+int rsb_set_device_mode(uint32_t device_mode);
+int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr);
+
+int rsb_read(uint8_t rt_addr, uint8_t reg_addr);
+int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value);
+
+#endif
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index 095099c..a7bb3f6 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -4,83 +4,84 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __TZC400_H__
-#define __TZC400_H__
+#ifndef TZC400_H
+#define TZC400_H
 
 #include <tzc_common.h>
+#include <utils_def.h>
 
-#define BUILD_CONFIG_OFF			0x000
-#define GATE_KEEPER_OFF				0x008
-#define SPECULATION_CTRL_OFF			0x00c
-#define INT_STATUS				0x010
-#define INT_CLEAR				0x014
+#define BUILD_CONFIG_OFF			U(0x000)
+#define GATE_KEEPER_OFF				U(0x008)
+#define SPECULATION_CTRL_OFF			U(0x00c)
+#define INT_STATUS				U(0x010)
+#define INT_CLEAR				U(0x014)
 
-#define FAIL_ADDRESS_LOW_OFF			0x020
-#define FAIL_ADDRESS_HIGH_OFF			0x024
-#define FAIL_CONTROL_OFF			0x028
-#define FAIL_ID					0x02c
+#define FAIL_ADDRESS_LOW_OFF			U(0x020)
+#define FAIL_ADDRESS_HIGH_OFF			U(0x024)
+#define FAIL_CONTROL_OFF			U(0x028)
+#define FAIL_ID					U(0x02c)
 
 /* ID registers not common across different varieties of TZC */
-#define PID5					0xFD4
-#define PID6					0xFD8
-#define PID7					0xFDC
+#define PID5					U(0xFD4)
+#define PID6					U(0xFD8)
+#define PID7					U(0xFDC)
 
 #define BUILD_CONFIG_NF_SHIFT			24
-#define BUILD_CONFIG_NF_MASK			0x3
+#define BUILD_CONFIG_NF_MASK			U(0x3)
 #define BUILD_CONFIG_AW_SHIFT			8
-#define BUILD_CONFIG_AW_MASK			0x3f
+#define BUILD_CONFIG_AW_MASK			U(0x3f)
 #define BUILD_CONFIG_NR_SHIFT			0
-#define BUILD_CONFIG_NR_MASK			0x1f
+#define BUILD_CONFIG_NR_MASK			U(0x1f)
 
 /*
  * Number of gate keepers is implementation defined. But we know the max for
  * this device is 4. Get implementation details from BUILD_CONFIG.
  */
 #define GATE_KEEPER_OS_SHIFT			16
-#define GATE_KEEPER_OS_MASK			0xf
+#define GATE_KEEPER_OS_MASK			U(0xf)
 #define GATE_KEEPER_OR_SHIFT			0
-#define GATE_KEEPER_OR_MASK			0xf
-#define GATE_KEEPER_FILTER_MASK			0x1
+#define GATE_KEEPER_OR_MASK			U(0xf)
+#define GATE_KEEPER_FILTER_MASK			U(0x1)
 
 /* Speculation is enabled by default. */
-#define SPECULATION_CTRL_WRITE_DISABLE		(1 << 1)
-#define SPECULATION_CTRL_READ_DISABLE		(1 << 0)
+#define SPECULATION_CTRL_WRITE_DISABLE		BIT_32(1)
+#define SPECULATION_CTRL_READ_DISABLE		BIT_32(0)
 
 /* Max number of filters allowed is 4. */
 #define INT_STATUS_OVERLAP_SHIFT		16
-#define INT_STATUS_OVERLAP_MASK			0xf
+#define INT_STATUS_OVERLAP_MASK			U(0xf)
 #define INT_STATUS_OVERRUN_SHIFT		8
-#define INT_STATUS_OVERRUN_MASK			0xf
+#define INT_STATUS_OVERRUN_MASK			U(0xf)
 #define INT_STATUS_STATUS_SHIFT			0
-#define INT_STATUS_STATUS_MASK			0xf
+#define INT_STATUS_STATUS_MASK			U(0xf)
 
 #define INT_CLEAR_CLEAR_SHIFT			0
-#define INT_CLEAR_CLEAR_MASK			0xf
+#define INT_CLEAR_CLEAR_MASK			U(0xf)
 
-#define FAIL_CONTROL_DIR_SHIFT			(1 << 24)
-#define FAIL_CONTROL_DIR_READ			0x0
-#define FAIL_CONTROL_DIR_WRITE			0x1
-#define FAIL_CONTROL_NS_SHIFT			(1 << 21)
-#define FAIL_CONTROL_NS_SECURE			0x0
-#define FAIL_CONTROL_NS_NONSECURE		0x1
-#define FAIL_CONTROL_PRIV_SHIFT			(1 << 20)
-#define FAIL_CONTROL_PRIV_PRIV			0x0
-#define FAIL_CONTROL_PRIV_UNPRIV		0x1
+#define FAIL_CONTROL_DIR_SHIFT			24
+#define FAIL_CONTROL_DIR_READ			U(0)
+#define FAIL_CONTROL_DIR_WRITE			U(1)
+#define FAIL_CONTROL_NS_SHIFT			21
+#define FAIL_CONTROL_NS_SECURE			U(0)
+#define FAIL_CONTROL_NS_NONSECURE		U(1)
+#define FAIL_CONTROL_PRIV_SHIFT			20
+#define FAIL_CONTROL_PRIV_PRIV			U(0)
+#define FAIL_CONTROL_PRIV_UNPRIV		U(1)
 
 /*
  * FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific.
  * Platform should provide the value on initialisation.
  */
 #define FAIL_ID_VNET_SHIFT			24
-#define FAIL_ID_VNET_MASK			0xf
+#define FAIL_ID_VNET_MASK			U(0xf)
 #define FAIL_ID_ID_SHIFT			0
 
-#define TZC_400_PERIPHERAL_ID			0x460
+#define TZC_400_PERIPHERAL_ID			U(0x460)
 
 /* Filter enable bits in a TZC */
-#define TZC_400_REGION_ATTR_F_EN_MASK		0xf
-#define TZC_400_REGION_ATTR_FILTER_BIT(x)	((1 << x)		\
-					<< TZC_REGION_ATTR_F_EN_SHIFT)
+#define TZC_400_REGION_ATTR_F_EN_MASK		U(0xf)
+#define TZC_400_REGION_ATTR_FILTER_BIT(x)				\
+				((U(1) << (x)) << TZC_REGION_ATTR_F_EN_SHIFT)
 #define TZC_400_REGION_ATTR_FILTER_BIT_ALL				\
 				(TZC_400_REGION_ATTR_F_EN_MASK <<	\
 				TZC_REGION_ATTR_F_EN_SHIFT)
@@ -89,8 +90,8 @@
  * All TZC region configuration registers are placed one after another. It
  * depicts size of block of registers for programming each region.
  */
-#define TZC_400_REGION_SIZE			0x20
-#define TZC_400_ACTION_OFF			0x4
+#define TZC_400_REGION_SIZE			U(0x20)
+#define TZC_400_ACTION_OFF			U(0x4)
 
 #ifndef __ASSEMBLY__
 
@@ -101,15 +102,15 @@
  * Function & variable prototypes
  ******************************************************************************/
 void tzc400_init(uintptr_t base);
-void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+void tzc400_configure_region0(unsigned int sec_attr,
 			   unsigned int ns_device_access);
 void tzc400_configure_region(unsigned int filters,
-			  int region,
+			  unsigned int region,
 			  unsigned long long region_base,
 			  unsigned long long region_top,
-			  tzc_region_attributes_t sec_attr,
+			  unsigned int sec_attr,
 			  unsigned int nsaid_permissions);
-void tzc400_set_action(tzc_action_t action);
+void tzc400_set_action(unsigned int action);
 void tzc400_enable_filters(void);
 void tzc400_disable_filters(void);
 
@@ -119,7 +120,7 @@
 }
 
 static inline void tzc_configure_region0(
-			tzc_region_attributes_t sec_attr,
+			unsigned int sec_attr,
 			unsigned int ns_device_access)
 {
 	tzc400_configure_region0(sec_attr, ns_device_access);
@@ -127,17 +128,17 @@
 
 static inline void tzc_configure_region(
 			  unsigned int filters,
-			  int region,
+			  unsigned int region,
 			  unsigned long long region_base,
 			  unsigned long long region_top,
-			  tzc_region_attributes_t sec_attr,
+			  unsigned int sec_attr,
 			  unsigned int ns_device_access)
 {
 	tzc400_configure_region(filters, region, region_base,
 			region_top, sec_attr, ns_device_access);
 }
 
-static inline void tzc_set_action(tzc_action_t action)
+static inline void tzc_set_action(unsigned int action)
 {
 	tzc400_set_action(action);
 }
@@ -155,4 +156,4 @@
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* __TZC400__ */
+#endif /* TZC400_H */
diff --git a/include/drivers/arm/tzc_common.h b/include/drivers/arm/tzc_common.h
index bb64b00..dac79aa 100644
--- a/include/drivers/arm/tzc_common.h
+++ b/include/drivers/arm/tzc_common.h
@@ -1,11 +1,13 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __TZC_COMMON_H__
-#define __TZC_COMMON_H__
+#ifndef TZC_COMMON_H
+#define TZC_COMMON_H
+
+#include <utils_def.h>
 
 /*
  * Offset of core registers from the start of the base of configuration
@@ -13,53 +15,15 @@
  */
 
 /* ID Registers */
-#define PID0_OFF					0xfe0
-#define PID1_OFF					0xfe4
-#define PID2_OFF					0xfe8
-#define PID3_OFF					0xfec
-#define PID4_OFF					0xfd0
-#define CID0_OFF					0xff0
-#define CID1_OFF					0xff4
-#define CID2_OFF					0xff8
-#define CID3_OFF					0xffc
-
-/* Bit positions of TZC_ACTION registers */
-#define TZC_ACTION_RV_SHIFT				0
-#define TZC_ACTION_RV_MASK				0x3
-#define TZC_ACTION_RV_LOWOK				0x0
-#define TZC_ACTION_RV_LOWERR				0x1
-#define TZC_ACTION_RV_HIGHOK				0x2
-#define TZC_ACTION_RV_HIGHERR				0x3
-
-/* Used along with 'tzc_region_attributes_t' below */
-#define TZC_REGION_ATTR_S_RD_SHIFT			30
-#define TZC_REGION_ATTR_S_WR_SHIFT			31
-#define TZC_REGION_ATTR_F_EN_SHIFT			0
-#define TZC_REGION_ATTR_SEC_SHIFT			30
-#define TZC_REGION_ATTR_S_RD_MASK			0x1
-#define TZC_REGION_ATTR_S_WR_MASK			0x1
-#define TZC_REGION_ATTR_SEC_MASK			0x3
-
-#define TZC_REGION_ACCESS_WR_EN_SHIFT			16
-#define TZC_REGION_ACCESS_RD_EN_SHIFT			0
-#define TZC_REGION_ACCESS_ID_MASK			0xf
-
-/* Macros for allowing Non-Secure access to a region based on NSAID */
-#define TZC_REGION_ACCESS_RD(nsaid)				\
-	((1 << ((nsaid) & TZC_REGION_ACCESS_ID_MASK)) <<	\
-	 TZC_REGION_ACCESS_RD_EN_SHIFT)
-#define TZC_REGION_ACCESS_WR(nsaid)				\
-	((1 << ((nsaid) & TZC_REGION_ACCESS_ID_MASK)) <<	\
-	 TZC_REGION_ACCESS_WR_EN_SHIFT)
-#define TZC_REGION_ACCESS_RDWR(nsaid)				\
-	(TZC_REGION_ACCESS_RD(nsaid) |				\
-	TZC_REGION_ACCESS_WR(nsaid))
-
-#ifndef __ASSEMBLY__
-
-/* Returns offset of registers to program for a given region no */
-#define TZC_REGION_OFFSET(region_size, region_no)	\
-				((region_size) * (region_no))
+#define PID0_OFF					U(0xfe0)
+#define PID1_OFF					U(0xfe4)
+#define PID2_OFF					U(0xfe8)
+#define PID3_OFF					U(0xfec)
+#define PID4_OFF					U(0xfd0)
+#define CID0_OFF					U(0xff0)
+#define CID1_OFF					U(0xff4)
+#define CID2_OFF					U(0xff8)
+#define CID3_OFF					U(0xffc)
 
 /*
  * What type of action is expected when an access violation occurs.
@@ -73,23 +37,61 @@
  *  TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
  *                       external data abort
  */
-typedef enum {
-	TZC_ACTION_NONE = 0,
-	TZC_ACTION_ERR = 1,
-	TZC_ACTION_INT = 2,
-	TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
-} tzc_action_t;
+#define TZC_ACTION_NONE			U(0)
+#define TZC_ACTION_ERR			U(1)
+#define TZC_ACTION_INT			U(2)
+#define TZC_ACTION_ERR_INT		(TZC_ACTION_ERR | TZC_ACTION_INT)
+
+/* Bit positions of TZC_ACTION registers */
+#define TZC_ACTION_RV_SHIFT				0
+#define TZC_ACTION_RV_MASK				U(0x3)
+#define TZC_ACTION_RV_LOWOK				U(0x0)
+#define TZC_ACTION_RV_LOWERR				U(0x1)
+#define TZC_ACTION_RV_HIGHOK				U(0x2)
+#define TZC_ACTION_RV_HIGHERR				U(0x3)
 
 /*
  * Controls secure access to a region. If not enabled secure access is not
  * allowed to region.
  */
-typedef enum {
-	TZC_REGION_S_NONE = 0,
-	TZC_REGION_S_RD = 1,
-	TZC_REGION_S_WR = 2,
-	TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
-} tzc_region_attributes_t;
+#define TZC_REGION_S_NONE		U(0)
+#define TZC_REGION_S_RD			U(1)
+#define TZC_REGION_S_WR			U(2)
+#define TZC_REGION_S_RDWR		(TZC_REGION_S_RD | TZC_REGION_S_WR)
+
+#define TZC_REGION_ATTR_S_RD_SHIFT			30
+#define TZC_REGION_ATTR_S_WR_SHIFT			31
+#define TZC_REGION_ATTR_F_EN_SHIFT			0
+#define TZC_REGION_ATTR_SEC_SHIFT			30
+#define TZC_REGION_ATTR_S_RD_MASK			U(0x1)
+#define TZC_REGION_ATTR_S_WR_MASK			U(0x1)
+#define TZC_REGION_ATTR_SEC_MASK			U(0x3)
+
+#define TZC_REGION_ACCESS_WR_EN_SHIFT			16
+#define TZC_REGION_ACCESS_RD_EN_SHIFT			0
+#define TZC_REGION_ACCESS_ID_MASK			U(0xf)
+
+/* Macros for allowing Non-Secure access to a region based on NSAID */
+#define TZC_REGION_ACCESS_RD(nsaid)				\
+	((U(1) << (nsaid & TZC_REGION_ACCESS_ID_MASK)) <<	\
+	 TZC_REGION_ACCESS_RD_EN_SHIFT)
+#define TZC_REGION_ACCESS_WR(nsaid)				\
+	((U(1) << (nsaid & TZC_REGION_ACCESS_ID_MASK)) <<	\
+	 TZC_REGION_ACCESS_WR_EN_SHIFT)
+#define TZC_REGION_ACCESS_RDWR(nsaid)				\
+	(TZC_REGION_ACCESS_RD(nsaid) |				\
+	TZC_REGION_ACCESS_WR(nsaid))
+
+/* Returns offset of registers to program for a given region no */
+#define TZC_REGION_OFFSET(region_size, region_no)	\
+				((region_size) * (region_no))
+
+#ifndef __ASSEMBLY__
+
+#if !ERROR_DEPRECATED
+typedef unsigned int tzc_action_t;
+typedef unsigned int tzc_region_attributes_t;
+#endif
 
 #endif /* __ASSEMBLY__ */
-#endif /* __TZC_COMMON_H__ */
+#endif /* TZC_COMMON_H */
diff --git a/include/drivers/arm/tzc_dmc500.h b/include/drivers/arm/tzc_dmc500.h
index ff58a27..df6e7f9 100644
--- a/include/drivers/arm/tzc_dmc500.h
+++ b/include/drivers/arm/tzc_dmc500.h
@@ -1,38 +1,39 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __TZC_DMC500_H__
-#define __TZC_DMC500_H__
+#ifndef TZC_DMC500_H
+#define TZC_DMC500_H
 
 #include <tzc_common.h>
+#include <utils_def.h>
 
-#define SI_STATUS_OFFSET				0x000
-#define SI_STATE_CTRL_OFFSET				0x030
-#define SI_FLUSH_CTRL_OFFSET				0x034
-#define SI_INT_CONTROL_OFFSET				0x048
+#define SI_STATUS_OFFSET				U(0x000)
+#define SI_STATE_CTRL_OFFSET				U(0x030)
+#define SI_FLUSH_CTRL_OFFSET				U(0x034)
+#define SI_INT_CONTROL_OFFSET				U(0x048)
 
-#define SI_INT_STATUS_OFFSET				0x004
-#define SI_TZ_FAIL_ADDRESS_LOW_OFFSET			0x008
-#define SI_TZ_FAIL_ADDRESS_HIGH_OFFSET			0x00c
-#define SI_FAIL_CONTROL_OFFSET				0x010
-#define SI_FAIL_ID_OFFSET				0x014
-#define SI_INT_CLR_OFFSET				0x04c
+#define SI_INT_STATUS_OFFSET				U(0x004)
+#define SI_TZ_FAIL_ADDRESS_LOW_OFFSET			U(0x008)
+#define SI_TZ_FAIL_ADDRESS_HIGH_OFFSET			U(0x00c)
+#define SI_FAIL_CONTROL_OFFSET				U(0x010)
+#define SI_FAIL_ID_OFFSET				U(0x014)
+#define SI_INT_CLR_OFFSET				U(0x04c)
 
 /*
  * DMC-500 has 2 system interfaces each having a similar set of regs
  * to configure each interface.
  */
-#define SI0_BASE					0x0000
-#define SI1_BASE					0x0200
+#define SI0_BASE					U(0x0000)
+#define SI1_BASE					U(0x0200)
 
 /* Bit positions of SIx_SI_STATUS */
-#define SI_EMPTY_SHIFT					0x01
-#define SI_STALL_ACK_SHIFT				0x00
-#define SI_EMPTY_MASK					0x01
-#define SI_STALL_ACK_MASK				0x01
+#define SI_EMPTY_SHIFT					1
+#define SI_STALL_ACK_SHIFT				0
+#define SI_EMPTY_MASK					U(0x01)
+#define SI_STALL_ACK_MASK				U(0x01)
 
 /* Bit positions of SIx_SI_INT_STATUS */
 #define PMU_REQ_INT_OVERFLOW_STATUS_SHIFT		18
@@ -40,11 +41,11 @@
 #define PMU_REQ_INT_STATUS_SHIFT			2
 #define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_SHIFT	1
 #define FAILED_ACCESS_INT_STATUS_SHIFT			0
-#define PMU_REQ_INT_OVERFLOW_STATUS_MASK		0x1
-#define FAILED_ACCESS_INT_OVERFLOW_STATUS_MASK		0x1
-#define PMU_REQ_INT_STATUS_MASK				0x1
-#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_MASK	0x1
-#define FAILED_ACCESS_INT_STATUS_MASK			0x1
+#define PMU_REQ_INT_OVERFLOW_STATUS_MASK		U(0x1)
+#define FAILED_ACCESS_INT_OVERFLOW_STATUS_MASK		U(0x1)
+#define PMU_REQ_INT_STATUS_MASK				U(0x1)
+#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_MASK	U(0x1)
+#define FAILED_ACCESS_INT_STATUS_MASK			U(0x1)
 
 /* Bit positions of SIx_TZ_FAIL_CONTROL */
 #define DIRECTION_SHIFT					24
@@ -52,21 +53,21 @@
 #define PRIVILEGED_SHIFT				20
 #define FAILED_ACCESS_INT_INFO_RANK_MASKED_SHIFT	3
 #define FAILED_ACCESS_INT_INFO_UNMAPPED_SHIFT		2
-#define FAILED_ACCESS_INT_TZ_FAIL_SHIFT			0x1
+#define FAILED_ACCESS_INT_TZ_FAIL_SHIFT			1
 #define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_SHIFT	0
-#define DIRECTION_MASK					0x1
-#define NON_SECURE_MASK					0x1
-#define PRIVILEGED_MASK					0x1
-#define FAILED_ACCESS_INT_INFO_RANK_MASKED_MASK		0x1
-#define FAILED_ACCESS_INT_INFO_UNMAPPED_MASK		0x1
-#define FAILED_ACCESS_INT_TZ_FAIL_MASK			1
-#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_MASK	0x1
+#define DIRECTION_MASK					U(0x1)
+#define NON_SECURE_MASK					U(0x1)
+#define PRIVILEGED_MASK					U(0x1)
+#define FAILED_ACCESS_INT_INFO_RANK_MASKED_MASK		U(0x1)
+#define FAILED_ACCESS_INT_INFO_UNMAPPED_MASK		U(0x1)
+#define FAILED_ACCESS_INT_TZ_FAIL_MASK			U(0x1)
+#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_MASK	U(0x1)
 
 /* Bit positions of SIx_FAIL_STATUS */
 #define FAIL_ID_VNET_SHIFT				24
 #define FAIL_ID_ID_SHIFT				0
-#define FAIL_ID_VNET_MASK				0xf
-#define FAIL_ID_ID_MASK					0xffffff
+#define FAIL_ID_VNET_MASK				U(0xf)
+#define FAIL_ID_ID_MASK					U(0xffffff)
 
 /* Bit positions of SIx_SI_STATE_CONTRL */
 #define SI_STALL_REQ_GO					0x0
@@ -81,44 +82,44 @@
 #define PMU_REQ_INT_EN_SHIFT				2
 #define OVERLAP_DETECT_INT_EN_SHIFT			1
 #define FAILED_ACCESS_INT_EN_SHIFT			0
-#define PMU_REQ_INT_EN_MASK				0x1
-#define OVERLAP_DETECT_INT_EN_MASK			0x1
-#define FAILED_ACCESS_INT_EN_MASK			0x1
-#define PMU_REQ_INT_EN					0x1
-#define OVERLAP_DETECT_INT_EN				0x1
-#define FAILED_ACCESS_INT_EN				0x1
+#define PMU_REQ_INT_EN_MASK				U(0x1)
+#define OVERLAP_DETECT_INT_EN_MASK			U(0x1)
+#define FAILED_ACCESS_INT_EN_MASK			U(0x1)
+#define PMU_REQ_INT_EN					U(0x1)
+#define OVERLAP_DETECT_INT_EN				U(0x1)
+#define FAILED_ACCESS_INT_EN				U(0x1)
 
 /* Bit positions of SIx_SI_INT_CLR */
 #define PMU_REQ_OFLOW_CLR_SHIFT				18
 #define FAILED_ACCESS_OFLOW_CLR_SHIFT			16
 #define PMU_REQ_INT_CLR_SHIFT				2
 #define FAILED_ACCESS_INT_CLR_SHIFT			0
-#define PMU_REQ_OFLOW_CLR_MASK				0x1
-#define FAILED_ACCESS_OFLOW_CLR_MASK			0x1
-#define PMU_REQ_INT_CLR_MASK				0x1
-#define FAILED_ACCESS_INT_CLR_MASK			0x1
-#define PMU_REQ_OFLOW_CLR				0x1
-#define FAILED_ACCESS_OFLOW_CLR				0x1
-#define PMU_REQ_INT_CLR					0x1
-#define FAILED_ACCESS_INT_CLR				0x1
+#define PMU_REQ_OFLOW_CLR_MASK				U(0x1)
+#define FAILED_ACCESS_OFLOW_CLR_MASK			U(0x1)
+#define PMU_REQ_INT_CLR_MASK				U(0x1)
+#define FAILED_ACCESS_INT_CLR_MASK			U(0x1)
+#define PMU_REQ_OFLOW_CLR				U(0x1)
+#define FAILED_ACCESS_OFLOW_CLR				U(0x1)
+#define PMU_REQ_INT_CLR					U(0x1)
+#define FAILED_ACCESS_INT_CLR				U(0x1)
 
 /* Macro to get the correct base register for a system interface */
 #define IFACE_OFFSET(sys_if)	((sys_if) ? SI1_BASE : SI0_BASE)
 
-#define MAX_SYS_IF_COUNT				2
+#define MAX_SYS_IF_COUNT				U(2)
 #define MAX_REGION_VAL					8
 
 /* DMC-500 supports striping across a max of 4 DMC instances */
 #define MAX_DMC_COUNT					4
 
 /* Consist of part_number_1 and part_number_0 */
-#define DMC500_PERIPHERAL_ID				0x0450
+#define DMC500_PERIPHERAL_ID				U(0x0450)
 
 /* Filter enable bits in a TZC */
-#define TZC_DMC500_REGION_ATTR_F_EN_MASK		0x1
+#define TZC_DMC500_REGION_ATTR_F_EN_MASK		U(0x1)
 
 /* Length of registers for configuring each region */
-#define TZC_DMC500_REGION_SIZE				0x018
+#define TZC_DMC500_REGION_SIZE				U(0x018)
 
 #ifndef __ASSEMBLY__
 
@@ -134,18 +135,17 @@
 } tzc_dmc500_driver_data_t;
 
 void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data);
-void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
+void tzc_dmc500_configure_region0(unsigned int sec_attr,
 				unsigned int nsaid_permissions);
-void tzc_dmc500_configure_region(int region_no,
+void tzc_dmc500_configure_region(unsigned int region_no,
 				unsigned long long region_base,
 				unsigned long long region_top,
-				tzc_region_attributes_t sec_attr,
+				unsigned int sec_attr,
 				unsigned int nsaid_permissions);
-void tzc_dmc500_set_action(tzc_action_t action);
+void tzc_dmc500_set_action(unsigned int action);
 void tzc_dmc500_config_complete(void);
 int tzc_dmc500_verify_complete(void);
 
 
 #endif /* __ASSEMBLY__ */
-#endif /* __TZC_DMC500_H__ */
-
+#endif /* TZC_DMC500_H */
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
index 485ed8c..02308e3 100644
--- a/include/drivers/io/io_storage.h
+++ b/include/drivers/io/io_storage.h
@@ -22,6 +22,8 @@
 	IO_TYPE_DUMMY,
 	IO_TYPE_FIRMWARE_IMAGE_PACKAGE,
 	IO_TYPE_BLOCK,
+	IO_TYPE_MMC,
+	IO_TYPE_STM32IMAGE,
 	IO_TYPE_MAX
 } io_type_t;
 
diff --git a/include/drivers/meson/meson_console.h b/include/drivers/meson/meson_console.h
new file mode 100644
index 0000000..759571d
--- /dev/null
+++ b/include/drivers/meson/meson_console.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MESON_CONSOLE_H
+#define MESON_CONSOLE_H
+
+#include <console.h>
+
+#define CONSOLE_T_MESON_BASE	CONSOLE_T_DRVDATA
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+typedef struct {
+	console_t console;
+	uintptr_t base;
+} console_meson_t;
+
+/*
+ * Initialize a new meson console instance and register it with the console
+ * framework. The |console| pointer must point to storage that will be valid
+ * for the lifetime of the console, such as a global or static local variable.
+ * Its contents will be reinitialized from scratch.
+ *
+ * NOTE: The clock is actually fixed to 24 MHz. The argument is only there in
+ * order to make this function future-proof.
+ */
+int console_meson_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+			   console_meson_t *console);
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* MESON_CONSOLE_H */
diff --git a/include/drivers/st/io_mmc.h b/include/drivers/st/io_mmc.h
new file mode 100644
index 0000000..de71e7d
--- /dev/null
+++ b/include/drivers/st/io_mmc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IO_MMC_H
+#define IO_MMC_H
+
+#include <io_driver.h>
+
+int register_io_dev_mmc(const io_dev_connector_t **dev_con);
+
+#endif /* IO_MMC_H */
diff --git a/include/drivers/st/io_stm32image.h b/include/drivers/st/io_stm32image.h
new file mode 100644
index 0000000..b668219
--- /dev/null
+++ b/include/drivers/st/io_stm32image.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IO_STM32IMAGE_H
+#define IO_STM32IMAGE_H
+
+#include <io_driver.h>
+#include <partition.h>
+
+#define MAX_LBA_SIZE		512
+#define MAX_PART_NAME_SIZE	(EFI_NAMELEN + 1)
+#define STM32_PART_NUM		(PLAT_PARTITION_MAX_ENTRIES - STM32_TF_A_COPIES)
+
+struct stm32image_part_info {
+	char name[MAX_PART_NAME_SIZE];
+	uint32_t binary_type;
+	uintptr_t part_offset;
+	uint32_t bkp_offset;
+};
+
+struct stm32image_device_info {
+	struct stm32image_part_info part_info[STM32_PART_NUM];
+	uint32_t device_size;
+	uint32_t lba_size;
+};
+
+int register_io_dev_stm32image(const io_dev_connector_t **dev_con);
+
+#endif /* IO_STM32IMAGE_H */
diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h
new file mode 100644
index 0000000..b172659
--- /dev/null
+++ b/include/drivers/st/stm32_sdmmc2.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_SDMMC2_H
+#define STM32_SDMMC2_H
+
+#include <mmc.h>
+#include <stdbool.h>
+
+struct stm32_sdmmc2_params {
+	uintptr_t		reg_base;
+	unsigned int		clk_rate;
+	unsigned int		bus_width;
+	unsigned int		flags;
+	struct mmc_device_info	*device_info;
+	unsigned int		pin_ckin;
+	unsigned int		negedge;
+	unsigned int		dirpol;
+	unsigned int		clock_id;
+	unsigned int		reset_id;
+	bool			use_dma;
+};
+
+unsigned long long stm32_sdmmc2_mmc_get_device_size(void);
+int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params);
+bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory);
+
+#endif /* STM32_SDMMC2_H */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index a6022cb..e6842e1 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -218,6 +218,8 @@
 /* SCR definitions */
 #define SCR_RES1_BITS		((U(1) << 4) | (U(1) << 5))
 #define SCR_FIEN_BIT		(U(1) << 21)
+#define SCR_API_BIT		(U(1) << 17)
+#define SCR_APK_BIT		(U(1) << 16)
 #define SCR_TWE_BIT		(U(1) << 13)
 #define SCR_TWI_BIT		(U(1) << 12)
 #define SCR_ST_BIT		(U(1) << 11)
@@ -274,6 +276,8 @@
 #define VTTBR_BADDR_SHIFT	U(0)
 
 /* HCR definitions */
+#define HCR_API_BIT		(ULL(1) << 41)
+#define HCR_APK_BIT		(ULL(1) << 40)
 #define HCR_RW_SHIFT		U(31)
 #define HCR_RW_BIT		(ULL(1) << HCR_RW_SHIFT)
 #define HCR_AMO_BIT		(ULL(1) << 5)
diff --git a/include/lib/cpus/aarch32/cpu_macros.S b/include/lib/cpus/aarch32/cpu_macros.S
index 525e18c..aa728b2 100644
--- a/include/lib/cpus/aarch32/cpu_macros.S
+++ b/include/lib/cpus/aarch32/cpu_macros.S
@@ -161,10 +161,9 @@
 	.endif
 
 	/*
-	 * Weakly-bound, optional errata status printing function for CPUs of
+	 * Mandatory errata status printing function for CPUs of
 	 * this class.
 	 */
-	.weak \_name\()_errata_report
 	.word \_name\()_errata_report
 
 #ifdef IMAGE_BL32
diff --git a/include/lib/cpus/aarch64/cortex_a75.h b/include/lib/cpus/aarch64/cortex_a75.h
index 493c7d4..f68f98f 100644
--- a/include/lib/cpus/aarch64/cortex_a75.h
+++ b/include/lib/cpus/aarch64/cortex_a75.h
@@ -4,11 +4,13 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __CORTEX_A75_H__
-#define __CORTEX_A75_H__
+#ifndef CORTEX_A75_H
+#define CORTEX_A75_H
+
+#include <utils_def.h>
 
 /* Cortex-A75 MIDR */
-#define CORTEX_A75_MIDR		0x410fd0a0
+#define CORTEX_A75_MIDR		U(0x410fd0a0)
 
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
@@ -24,7 +26,7 @@
 #define CORTEX_A75_CPUACTLR_EL1_DISABLE_LOAD_PASS_STORE	(1 << 35)
 
 /* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */
-#define CORTEX_A75_CORE_PWRDN_EN_MASK	0x1
+#define CORTEX_A75_CORE_PWRDN_EN_MASK	U(0x1)
 
 #define CORTEX_A75_ACTLR_AMEN_BIT	(U(1) << 4)
 
@@ -50,4 +52,4 @@
 void cortex_a75_amu_write_cpuamcntenclr_el0(unsigned int mask);
 #endif /* __ASSEMBLY__ */
 
-#endif /* __CORTEX_A75_H__ */
+#endif /* CORTEX_A75_H */
diff --git a/include/lib/cpus/aarch64/cortex_ares.h b/include/lib/cpus/aarch64/cortex_ares.h
index 84955b1..4f3e812 100644
--- a/include/lib/cpus/aarch64/cortex_ares.h
+++ b/include/lib/cpus/aarch64/cortex_ares.h
@@ -4,11 +4,13 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __CORTEX_ARES_H__
-#define __CORTEX_ARES_H__
+#ifndef CORTEX_ARES_H
+#define CORTEX_ARES_H
+
+#include <utils_def.h>
 
 /* Cortex-ARES MIDR for revision 0 */
-#define CORTEX_ARES_MIDR		0x410fd0c0
+#define CORTEX_ARES_MIDR		U(0x410fd0c0)
 
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
@@ -17,7 +19,7 @@
 #define CORTEX_ARES_CPUECTLR_EL1	S3_0_C15_C1_4
 
 /* Definitions of register field mask in CORTEX_ARES_CPUPWRCTLR_EL1 */
-#define CORTEX_ARES_CORE_PWRDN_EN_MASK	0x1
+#define CORTEX_ARES_CORE_PWRDN_EN_MASK	U(0x1)
 
 #define CORTEX_ARES_ACTLR_AMEN_BIT	(U(1) << 4)
 
@@ -30,4 +32,4 @@
 #define CPUPOR_EL3	S3_6_C15_C8_2
 #define CPUPMR_EL3	S3_6_C15_C8_3
 
-#endif /* __CORTEX_ARES_H__ */
+#endif /* CORTEX_ARES_H */
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index 4672cbc..14616ac 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -183,10 +183,9 @@
 	.endif
 
 	/*
-	 * Weakly-bound, optional errata status printing function for CPUs of
+	 * Mandatory errata status printing function for CPUs of
 	 * this class.
 	 */
-	.weak \_name\()_errata_report
 	.quad \_name\()_errata_report
 
 #ifdef IMAGE_BL31
diff --git a/include/lib/cpus/aarch64/cpuamu.h b/include/lib/cpus/aarch64/cpuamu.h
index 960a524..921abdb 100644
--- a/include/lib/cpus/aarch64/cpuamu.h
+++ b/include/lib/cpus/aarch64/cpuamu.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __CPUAMU_H__
-#define __CPUAMU_H__
+#ifndef CPUAMU_H
+#define CPUAMU_H
 
 /*******************************************************************************
  * CPU Activity Monitor Unit register specific definitions.
@@ -32,8 +32,8 @@
 #ifndef __ASSEMBLY__
 #include <stdint.h>
 
-uint64_t cpuamu_cnt_read(int idx);
-void cpuamu_cnt_write(int idx, uint64_t val);
+uint64_t cpuamu_cnt_read(unsigned int idx);
+void cpuamu_cnt_write(unsigned int idx, uint64_t val);
 unsigned int cpuamu_read_cpuamcntenset_el0(void);
 unsigned int cpuamu_read_cpuamcntenclr_el0(void);
 void cpuamu_write_cpuamcntenset_el0(unsigned int mask);
@@ -45,4 +45,4 @@
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* __CPUAMU_H__ */
+#endif /* CPUAMU_H */
diff --git a/include/lib/cpus/errata_report.h b/include/lib/cpus/errata_report.h
index d2138bf..c97d4c2 100644
--- a/include/lib/cpus/errata_report.h
+++ b/include/lib/cpus/errata_report.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __ERRATA_H__
-#define __ERRATA_H__
+#ifndef ERRATA_REPORT_H
+#define ERRATA_REPORT_H
 
 #ifndef __ASSEMBLY__
 
@@ -30,5 +30,4 @@
 #define ERRATA_APPLIES		1
 #define ERRATA_MISSING		2
 
-#endif /* __ERRATA_H__ */
-
+#endif /* ERRATA_REPORT_H */
diff --git a/include/lib/cpus/wa_cve_2017_5715.h b/include/lib/cpus/wa_cve_2017_5715.h
index 0a65a56..940fc65 100644
--- a/include/lib/cpus/wa_cve_2017_5715.h
+++ b/include/lib/cpus/wa_cve_2017_5715.h
@@ -4,9 +4,9 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __WA_CVE_2017_5715_H__
-#define __WA_CVE_2017_5715_H__
+#ifndef WA_CVE_2017_5715_H
+#define WA_CVE_2017_5715_H
 
 int check_wa_cve_2017_5715(void);
 
-#endif /* __WA_CVE_2017_5715_H__ */
+#endif /* WA_CVE_2017_5715_H */
diff --git a/include/lib/cpus/wa_cve_2018_3639.h b/include/lib/cpus/wa_cve_2018_3639.h
index 36546f7..e37db37 100644
--- a/include/lib/cpus/wa_cve_2018_3639.h
+++ b/include/lib/cpus/wa_cve_2018_3639.h
@@ -4,9 +4,9 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __WA_CVE_2018_3639_H__
-#define __WA_CVE_2018_3639_H__
+#ifndef WA_CVE_2018_3639_H
+#define WA_CVE_2018_3639_H
 
 void *wa_cve_2018_3639_get_disable_ptr(void);
 
-#endif /* __WA_CVE_2018_3639_H__ */
+#endif /* WA_CVE_2018_3639_H */
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 15d34eb..b695950 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __CPU_DATA_H__
-#define __CPU_DATA_H__
+#ifndef CPU_DATA_H
+#define CPU_DATA_H
 
 #include <ehf.h>
 #include <platform_def.h>	/* CACHE_WRITEBACK_GRANULE required */
@@ -161,4 +161,4 @@
 
 
 #endif /* __ASSEMBLY__ */
-#endif /* __CPU_DATA_H__ */
+#endif /* CPU_DATA_H */
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
index 46d5e15..1836fe5 100644
--- a/include/lib/extensions/amu.h
+++ b/include/lib/extensions/amu.h
@@ -4,33 +4,35 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __AMU_H__
-#define __AMU_H__
+#ifndef AMU_H
+#define AMU_H
 
 #include <cassert.h>
 #include <platform_def.h>
+#include <stdbool.h>
 #include <stdint.h>
+#include <utils_def.h>
 
 /* All group 0 counters */
-#define AMU_GROUP0_COUNTERS_MASK	0xf
+#define AMU_GROUP0_COUNTERS_MASK	U(0xf)
 
 #ifdef PLAT_AMU_GROUP1_COUNTERS_MASK
 #define AMU_GROUP1_COUNTERS_MASK	PLAT_AMU_GROUP1_COUNTERS_MASK
 #else
-#define AMU_GROUP1_COUNTERS_MASK	0
+#define AMU_GROUP1_COUNTERS_MASK	U(0)
 #endif
 
 #ifdef PLAT_AMU_GROUP1_NR_COUNTERS
 #define AMU_GROUP1_NR_COUNTERS		PLAT_AMU_GROUP1_NR_COUNTERS
 #else
-#define AMU_GROUP1_NR_COUNTERS		0
+#define AMU_GROUP1_NR_COUNTERS		U(0)
 #endif
 
 CASSERT(AMU_GROUP1_COUNTERS_MASK <= 0xffff, invalid_amu_group1_counters_mask);
 CASSERT(AMU_GROUP1_NR_COUNTERS <= 16, invalid_amu_group1_nr_counters);
 
-int amu_supported(void);
-void amu_enable(int el2_unused);
+bool amu_supported(void);
+void amu_enable(bool el2_unused);
 
 /* Group 0 configuration helpers */
 uint64_t amu_group0_cnt_read(int idx);
@@ -41,4 +43,4 @@
 void amu_group1_cnt_write(int idx, uint64_t val);
 void amu_group1_set_evtype(int idx, unsigned int val);
 
-#endif /* __AMU_H__ */
+#endif /* AMU_H */
diff --git a/include/lib/extensions/amu_private.h b/include/lib/extensions/amu_private.h
index 0c660bb..ab4e6aa 100644
--- a/include/lib/extensions/amu_private.h
+++ b/include/lib/extensions/amu_private.h
@@ -1,19 +1,19 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __AMU_PRIVATE_H__
-#define __AMU_PRIVATE_H__
+#ifndef AMU_PRIVATE_H
+#define AMU_PRIVATE_H
 
 #include <stdint.h>
 
 uint64_t amu_group0_cnt_read_internal(int idx);
-void amu_group0_cnt_write_internal(int idx, uint64_t);
+void amu_group0_cnt_write_internal(int idx, uint64_t val);
 
 uint64_t amu_group1_cnt_read_internal(int idx);
-void amu_group1_cnt_write_internal(int idx, uint64_t);
+void amu_group1_cnt_write_internal(int idx, uint64_t val);
 void amu_group1_set_evtype_internal(int idx, unsigned int val);
 
-#endif /* __AMU_PRIVATE_H__ */
+#endif /* AMU_PRIVATE_H */
diff --git a/include/lib/extensions/mpam.h b/include/lib/extensions/mpam.h
index 571b96b..ac8c00a 100644
--- a/include/lib/extensions/mpam.h
+++ b/include/lib/extensions/mpam.h
@@ -10,6 +10,6 @@
 #include <stdbool.h>
 
 bool mpam_supported(void);
-void mpam_enable(int el2_unused);
+void mpam_enable(bool el2_unused);
 
 #endif /* MPAM_H */
diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h
index b2b188e..d4b925f 100644
--- a/include/lib/extensions/spe.h
+++ b/include/lib/extensions/spe.h
@@ -4,11 +4,13 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __SPE_H__
-#define __SPE_H__
+#ifndef SPE_H
+#define SPE_H
 
-int spe_supported(void);
-void spe_enable(int el2_unused);
+#include <stdbool.h>
+
+bool spe_supported(void);
+void spe_enable(bool el2_unused);
 void spe_disable(void);
 
-#endif /* __SPE_H__ */
+#endif /* SPE_H */
diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h
index 9c7f37f..83df177 100644
--- a/include/lib/extensions/sve.h
+++ b/include/lib/extensions/sve.h
@@ -4,10 +4,12 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __SVE_H__
-#define __SVE_H__
+#ifndef SVE_H
+#define SVE_H
 
-int sve_supported(void);
-void sve_enable(int el2_unused);
+#include <stdbool.h>
 
-#endif /* __SVE_H__ */
+bool sve_supported(void);
+void sve_enable(bool el2_unused);
+
+#endif /* SVE_H */
diff --git a/include/lib/libc/string.h b/include/lib/libc/string.h
index 050f643..3c8e3b6 100644
--- a/include/lib/libc/string.h
+++ b/include/lib/libc/string.h
@@ -27,5 +27,6 @@
 void *memset(void *dst, int val, size_t count);
 size_t strlen(const char *s);
 size_t strnlen(const char *s, size_t maxlen);
+char *strrchr(const char *p, int ch);
 
 #endif /* STRING_H */
diff --git a/include/lib/libfdt/fdt.h b/include/lib/libfdt/fdt.h
index c833dc1..74961f9 100644
--- a/include/lib/libfdt/fdt.h
+++ b/include/lib/libfdt/fdt.h
@@ -1,5 +1,5 @@
-#ifndef _FDT_H
-#define _FDT_H
+#ifndef FDT_H
+#define FDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
@@ -52,16 +52,8 @@
  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*
- * Portions copyright (c) 2016-2017, ARM Limited and Contributors.
- * All rights reserved.
- */
-
 #ifndef __ASSEMBLY__
 
-#include <libfdt_env.h>
-
-
 struct fdt_header {
 	fdt32_t magic;			 /* magic word FDT_MAGIC */
 	fdt32_t totalsize;		 /* total size of DT block */
@@ -88,14 +80,14 @@
 
 struct fdt_node_header {
 	fdt32_t tag;
-	char name[];
+	char name[0];
 };
 
 struct fdt_property {
 	fdt32_t tag;
 	fdt32_t len;
 	fdt32_t nameoff;
-	char data[];
+	char data[0];
 };
 
 #endif /* !__ASSEMBLY */
@@ -116,4 +108,4 @@
 #define FDT_V16_SIZE	FDT_V3_SIZE
 #define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(fdt32_t))
 
-#endif /* _FDT_H */
+#endif /* FDT_H */
diff --git a/include/lib/libfdt/libfdt.h b/include/lib/libfdt/libfdt.h
index f662378..830b77e 100644
--- a/include/lib/libfdt/libfdt.h
+++ b/include/lib/libfdt/libfdt.h
@@ -1,5 +1,5 @@
-#ifndef _LIBFDT_H
-#define _LIBFDT_H
+#ifndef LIBFDT_H
+#define LIBFDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
@@ -51,22 +51,17 @@
  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*
- * Portions copyright (c) 2016-2017, ARM Limited and Contributors.
- * All rights reserved.
- */
-
 #include <libfdt_env.h>
 #include <fdt.h>
 
-#define FDT_FIRST_SUPPORTED_VERSION	0x10
+#define FDT_FIRST_SUPPORTED_VERSION	0x02
 #define FDT_LAST_SUPPORTED_VERSION	0x11
 
 /* Error codes: informative error codes */
 #define FDT_ERR_NOTFOUND	1
 	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
 #define FDT_ERR_EXISTS		2
-	/* FDT_ERR_EXISTS: Attemped to create a node or property which
+	/* FDT_ERR_EXISTS: Attempted to create a node or property which
 	 * already exists */
 #define FDT_ERR_NOSPACE		3
 	/* FDT_ERR_NOSPACE: Operation needed to expand the device
@@ -84,8 +79,10 @@
 	 * (e.g. missing a leading / for a function which requires an
 	 * absolute path) */
 #define FDT_ERR_BADPHANDLE	6
-	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
-	 * value.  phandle values of 0 and -1 are not permitted. */
+	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.
+	 * This can be caused either by an invalid phandle property
+	 * length, or the phandle value was either 0 or -1, which are
+	 * not permitted. */
 #define FDT_ERR_BADSTATE	7
 	/* FDT_ERR_BADSTATE: Function was passed an incomplete device
 	 * tree created by the sequential-write functions, which is
@@ -93,8 +90,9 @@
 
 /* Error codes: codes for bad device tree blobs */
 #define FDT_ERR_TRUNCATED	8
-	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
-	 * ends without an FDT_END tag. */
+	/* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
+	 * terminated (overflows, goes outside allowed bounds, or
+	 * isn't properly terminated).  */
 #define FDT_ERR_BADMAGIC	9
 	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
 	 * device tree at all - it is missing the flattened device
@@ -131,13 +129,24 @@
 	 * value. For example: a property expected to contain a string list
 	 * is not NUL-terminated within the length of its value. */
 
-#define FDT_ERR_MAX		15
+#define FDT_ERR_BADOVERLAY	16
+	/* FDT_ERR_BADOVERLAY: The device tree overlay, while
+	 * correctly structured, cannot be applied due to some
+	 * unexpected or missing value, property or node. */
+
+#define FDT_ERR_NOPHANDLES	17
+	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
+	 * phandle available anymore without causing an overflow */
+
+#define FDT_ERR_MAX		17
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
 /**********************************************************************/
 
+#ifndef SWIG /* This function is not useful in Python */
 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
+#endif
 static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
 {
 	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
@@ -145,6 +154,29 @@
 
 uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
+/*
+ * Alignment helpers:
+ *     These helpers access words from a device tree blob.  They're
+ *     built to work even with unaligned pointers on platforms (ike
+ *     ARM) that don't like unaligned loads and stores
+ */
+
+static inline uint32_t fdt32_ld(const fdt32_t *p)
+{
+	fdt32_t v;
+
+	memcpy(&v, p, sizeof(v));
+	return fdt32_to_cpu(v);
+}
+
+static inline uint64_t fdt64_ld(const fdt64_t *p)
+{
+	fdt64_t v;
+
+	memcpy(&v, p, sizeof(v));
+	return fdt64_to_cpu(v);
+}
+
 /**********************************************************************/
 /* Traversal functions                                                */
 /**********************************************************************/
@@ -204,9 +236,8 @@
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
-
 #define fdt_get_header(fdt, field) \
-	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+	(fdt32_ld(&((const struct fdt_header *)(fdt))->field))
 #define fdt_magic(fdt)			(fdt_get_header(fdt, magic))
 #define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
 #define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
@@ -218,37 +249,50 @@
 #define fdt_size_dt_strings(fdt)	(fdt_get_header(fdt, size_dt_strings))
 #define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct))
 
-#define __fdt_set_hdr(name) \
+#define fdt_set_hdr_(name) \
 	static inline void fdt_set_##name(void *fdt, uint32_t val) \
 	{ \
 		struct fdt_header *fdth = (struct fdt_header *)fdt; \
 		fdth->name = cpu_to_fdt32(val); \
 	}
-__fdt_set_hdr(magic)
-__fdt_set_hdr(totalsize)
-__fdt_set_hdr(off_dt_struct)
-__fdt_set_hdr(off_dt_strings)
-__fdt_set_hdr(off_mem_rsvmap)
-__fdt_set_hdr(version)
-__fdt_set_hdr(last_comp_version)
-__fdt_set_hdr(boot_cpuid_phys)
-__fdt_set_hdr(size_dt_strings)
-__fdt_set_hdr(size_dt_struct)
-#undef __fdt_set_hdr
+fdt_set_hdr_(magic);
+fdt_set_hdr_(totalsize);
+fdt_set_hdr_(off_dt_struct);
+fdt_set_hdr_(off_dt_strings);
+fdt_set_hdr_(off_mem_rsvmap);
+fdt_set_hdr_(version);
+fdt_set_hdr_(last_comp_version);
+fdt_set_hdr_(boot_cpuid_phys);
+fdt_set_hdr_(size_dt_strings);
+fdt_set_hdr_(size_dt_struct);
+#undef fdt_set_hdr_
 
 /**
- * fdt_check_header - sanity check a device tree or possible device tree
+ * fdt_header_size - return the size of the tree's header
+ * @fdt: pointer to a flattened device tree
+ */
+size_t fdt_header_size_(uint32_t version);
+static inline size_t fdt_header_size(const void *fdt)
+{
+	return fdt_header_size_(fdt_version(fdt));
+}
+
+/**
+ * fdt_check_header - sanity check a device tree header
+
  * @fdt: pointer to data which might be a flattened device tree
  *
  * fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
+ * appears to be a flattened device tree, and that the header contains
+ * valid information (to the extent that can be determined from the
+ * header alone).
  *
  * returns:
  *     0, if the buffer appears to contain a valid device tree
  *     -FDT_ERR_BADMAGIC,
  *     -FDT_ERR_BADVERSION,
- *     -FDT_ERR_BADSTATE, standard meanings, as above
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_TRUNCATED, standard meanings, as above
  */
 int fdt_check_header(const void *fdt);
 
@@ -277,6 +321,24 @@
 /* Read-only functions                                                */
 /**********************************************************************/
 
+int fdt_check_full(const void *fdt, size_t bufsize);
+
+/**
+ * fdt_get_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ * @lenp: optional pointer to return the string's length
+ *
+ * fdt_get_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt, and optionally also
+ * returns the string's length in *lenp.
+ *
+ * returns:
+ *     a pointer to the string, on success
+ *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
+ */
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
+
 /**
  * fdt_string - retrieve a string from the strings block of a device tree
  * @fdt: pointer to the device tree blob
@@ -287,7 +349,7 @@
  *
  * returns:
  *     a pointer to the string, on success
- *     NULL, if stroffset is out of bounds
+ *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
  */
 const char *fdt_string(const void *fdt, int stroffset);
 
@@ -348,8 +410,10 @@
  * useful for finding subnodes based on a portion of a larger string,
  * such as a full path.
  */
+#ifndef SWIG /* Not available in Python */
 int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
 			       const char *name, int namelen);
+#endif
 /**
  * fdt_subnode_offset - find a subnode of a given node
  * @fdt: pointer to the device tree blob
@@ -385,7 +449,9 @@
  * Identical to fdt_path_offset(), but only consider the first namelen
  * characters of path as the path name.
  */
+#ifndef SWIG /* Not available in Python */
 int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
+#endif
 
 /**
  * fdt_path_offset - find a tree node by its full path
@@ -516,6 +582,9 @@
  * offset.  If lenp is non-NULL, the length of the property value is
  * also returned, in the integer pointed to by lenp.
  *
+ * Note that this code only works on device tree versions >= 16. fdt_getprop()
+ * works on all versions.
+ *
  * returns:
  *	pointer to the structure representing the property
  *		if lenp is non-NULL, *lenp contains the length of the property
@@ -544,10 +613,12 @@
  * Identical to fdt_get_property(), but only examine the first namelen
  * characters of name for matching the property name.
  */
+#ifndef SWIG /* Not available in Python */
 const struct fdt_property *fdt_get_property_namelen(const void *fdt,
 						    int nodeoffset,
 						    const char *name,
 						    int namelen, int *lenp);
+#endif
 
 /**
  * fdt_get_property - find a given property in a given node
@@ -618,8 +689,10 @@
  *		-FDT_ERR_BADSTRUCTURE,
  *		-FDT_ERR_TRUNCATED, standard meanings
  */
+#ifndef SWIG /* This function is not useful in Python */
 const void *fdt_getprop_by_offset(const void *fdt, int offset,
 				  const char **namep, int *lenp);
+#endif
 
 /**
  * fdt_getprop_namelen - get property value based on substring
@@ -632,6 +705,7 @@
  * Identical to fdt_getprop(), but only examine the first namelen
  * characters of name for matching the property name.
  */
+#ifndef SWIG /* Not available in Python */
 const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
 				const char *name, int namelen, int *lenp);
 static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
@@ -641,6 +715,7 @@
 	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
 						      namelen, lenp);
 }
+#endif
 
 /**
  * fdt_getprop - retrieve the value of a given property
@@ -701,11 +776,13 @@
  * Identical to fdt_get_alias(), but only examine the first namelen
  * characters of name for matching the alias name.
  */
+#ifndef SWIG /* Not available in Python */
 const char *fdt_get_alias_namelen(const void *fdt,
 				  const char *name, int namelen);
+#endif
 
 /**
- * fdt_get_alias - retreive the path referenced by a given alias
+ * fdt_get_alias - retrieve the path referenced by a given alias
  * @fdt: pointer to the device tree blob
  * @name: name of the alias th look up
  *
@@ -1068,7 +1145,7 @@
  *
  * returns:
  *	0 <= n < FDT_MAX_NCELLS, on success
- *      2, if the node has no #address-cells property
+ *      2, if the node has no #size-cells property
  *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
  *		#size-cells property
  *	-FDT_ERR_BADMAGIC,
@@ -1100,10 +1177,12 @@
  * of the name. It is useful when you want to manipulate only one value of
  * an array and you have a string that doesn't end with \0.
  */
+#ifndef SWIG /* Not available in Python */
 int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
 					const char *name, int namelen,
 					uint32_t idx, const void *val,
 					int len);
+#endif
 
 /**
  * fdt_setprop_inplace - change a property's value, but not its size
@@ -1133,8 +1212,10 @@
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
+#ifndef SWIG /* Not available in Python */
 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 			const void *val, int len);
+#endif
 
 /**
  * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
@@ -1287,10 +1368,29 @@
 	fdt64_t tmp = cpu_to_fdt64(val);
 	return fdt_property(fdt, name, &tmp, sizeof(tmp));
 }
+
+#ifndef SWIG /* Not available in Python */
 static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
 {
 	return fdt_property_u32(fdt, name, val);
 }
+#endif
+
+/**
+ * fdt_property_placeholder - add a new property and return a ptr to its value
+ *
+ * @fdt: pointer to the device tree blob
+ * @name: name of property to add
+ * @len: length of property value in bytes
+ * @valp: returns a pointer to where where the value should be placed
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_NOSPACE, standard meanings
+ */
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
+
 #define fdt_property_string(fdt, name, str) \
 	fdt_property(fdt, name, str, strlen(str)+1)
 int fdt_end_node(void *fdt);
@@ -1410,6 +1510,37 @@
 		const void *val, int len);
 
 /**
+ * fdt_setprop_placeholder - allocate space for a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @len: length of the property value
+ * @prop_data: return pointer to property data
+ *
+ * fdt_setprop_placeholer() allocates the named property in the given node.
+ * If the property exists it is resized. In either case a pointer to the
+ * property data is returned.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
+			    int len, void **prop_data);
+
+/**
  * fdt_setprop_u32 - set a property to a 32-bit integer
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
@@ -1521,6 +1652,36 @@
 #define fdt_setprop_string(fdt, nodeoffset, name, str) \
 	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
 
+
+/**
+ * fdt_setprop_empty - set a property to an empty value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ *
+ * fdt_setprop_empty() sets the value of the named property in the
+ * given node to an empty (zero length) value, or creates a new empty
+ * property if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_setprop_empty(fdt, nodeoffset, name) \
+	fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
+
 /**
  * fdt_appendprop - append to or create a property
  * @fdt: pointer to the device tree blob
@@ -1698,8 +1859,10 @@
  * creating subnodes based on a portion of a larger string, such as a
  * full path.
  */
+#ifndef SWIG /* Not available in Python */
 int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 			    const char *name, int namelen);
+#endif
 
 /**
  * fdt_add_subnode - creates a new node
@@ -1757,10 +1920,41 @@
  */
 int fdt_del_node(void *fdt, int nodeoffset);
 
+/**
+ * fdt_overlay_apply - Applies a DT overlay on a base DT
+ * @fdt: pointer to the base device tree blob
+ * @fdto: pointer to the device tree overlay blob
+ *
+ * fdt_overlay_apply() will apply the given device tree overlay on the
+ * given base device tree.
+ *
+ * Expect the base device tree to be modified, even if the function
+ * returns an error.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there's not enough space in the base device tree
+ *	-FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
+ *		properties in the base DT
+ *	-FDT_ERR_BADPHANDLE,
+ *	-FDT_ERR_BADOVERLAY,
+ *	-FDT_ERR_NOPHANDLES,
+ *	-FDT_ERR_INTERNAL,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADOFFSET,
+ *	-FDT_ERR_BADPATH,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_overlay_apply(void *fdt, void *fdto);
+
 /**********************************************************************/
 /* Debugging / informational functions                                */
 /**********************************************************************/
 
 const char *fdt_strerror(int errval);
 
-#endif /* _LIBFDT_H */
+#endif /* LIBFDT_H */
diff --git a/include/lib/libfdt/libfdt_env.h b/include/lib/libfdt/libfdt_env.h
index 9dea97d..eb20538 100644
--- a/include/lib/libfdt/libfdt_env.h
+++ b/include/lib/libfdt/libfdt_env.h
@@ -1,5 +1,5 @@
-#ifndef _LIBFDT_ENV_H
-#define _LIBFDT_ENV_H
+#ifndef LIBFDT_ENV_H
+#define LIBFDT_ENV_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
@@ -54,19 +54,21 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #ifdef __CHECKER__
-#define __force __attribute__((force))
-#define __bitwise __attribute__((bitwise))
+#define FDT_FORCE __attribute__((force))
+#define FDT_BITWISE __attribute__((bitwise))
 #else
-#define __force
-#define __bitwise
+#define FDT_FORCE
+#define FDT_BITWISE
 #endif
 
-typedef uint16_t __bitwise fdt16_t;
-typedef uint32_t __bitwise fdt32_t;
-typedef uint64_t __bitwise fdt64_t;
+typedef uint16_t FDT_BITWISE fdt16_t;
+typedef uint32_t FDT_BITWISE fdt32_t;
+typedef uint64_t FDT_BITWISE fdt64_t;
 
 #define EXTRACT_BYTE(x, n)	((unsigned long long)((uint8_t *)&x)[n])
 #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
@@ -79,33 +81,60 @@
 
 static inline uint16_t fdt16_to_cpu(fdt16_t x)
 {
-	return (__force uint16_t)CPU_TO_FDT16(x);
+	return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
 }
 static inline fdt16_t cpu_to_fdt16(uint16_t x)
 {
-	return (__force fdt16_t)CPU_TO_FDT16(x);
+	return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);
 }
 
 static inline uint32_t fdt32_to_cpu(fdt32_t x)
 {
-	return (__force uint32_t)CPU_TO_FDT32(x);
+	return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);
 }
 static inline fdt32_t cpu_to_fdt32(uint32_t x)
 {
-	return (__force fdt32_t)CPU_TO_FDT32(x);
+	return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);
 }
 
 static inline uint64_t fdt64_to_cpu(fdt64_t x)
 {
-	return (__force uint64_t)CPU_TO_FDT64(x);
+	return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);
 }
 static inline fdt64_t cpu_to_fdt64(uint64_t x)
 {
-	return (__force fdt64_t)CPU_TO_FDT64(x);
+	return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
 }
 #undef CPU_TO_FDT64
 #undef CPU_TO_FDT32
 #undef CPU_TO_FDT16
 #undef EXTRACT_BYTE
 
-#endif /* _LIBFDT_ENV_H */
+#ifdef __APPLE__
+#include <AvailabilityMacros.h>
+
+/* strnlen() is not available on Mac OS < 10.7 */
+# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
+                                         MAC_OS_X_VERSION_10_7)
+
+#define strnlen fdt_strnlen
+
+/*
+ * fdt_strnlen: returns the length of a string or max_count - which ever is
+ * smallest.
+ * Input 1 string: the string whose size is to be determined
+ * Input 2 max_count: the maximum value returned by this function
+ * Output: length of the string or max_count (the smallest of the two)
+ */
+static inline size_t fdt_strnlen(const char *string, size_t max_count)
+{
+    const char *p = memchr(string, 0, max_count);
+    return p ? p - string : max_count;
+}
+
+#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
+          MAC_OS_X_VERSION_10_7) */
+
+#endif /* __APPLE__ */
+
+#endif /* LIBFDT_ENV_H */
diff --git a/include/lib/pmf/pmf.h b/include/lib/pmf/pmf.h
index a3812fb..18ef0a5 100644
--- a/include/lib/pmf/pmf.h
+++ b/include/lib/pmf/pmf.h
@@ -9,17 +9,18 @@
 
 #include <cassert.h>
 #include <pmf_helpers.h>
+#include <utils_def.h>
 
 /*
  * Constants used for/by PMF services.
  */
-#define PMF_ARM_TIF_IMPL_ID	0x41
+#define PMF_ARM_TIF_IMPL_ID	U(0x41)
 #define PMF_TID_SHIFT		0
-#define PMF_TID_MASK		(0xFF << PMF_TID_SHIFT)
+#define PMF_TID_MASK		(U(0xFF) << PMF_TID_SHIFT)
 #define PMF_SVC_ID_SHIFT	10
-#define PMF_SVC_ID_MASK		(0x3F << PMF_SVC_ID_SHIFT)
+#define PMF_SVC_ID_MASK		(U(0x3F) << PMF_SVC_ID_SHIFT)
 #define PMF_IMPL_ID_SHIFT	24
-#define PMF_IMPL_ID_MASK	(0xFFU << PMF_IMPL_ID_SHIFT)
+#define PMF_IMPL_ID_MASK	(U(0xFF) << PMF_IMPL_ID_SHIFT)
 
 /*
  * Flags passed to PMF_REGISTER_SERVICE
@@ -37,16 +38,16 @@
 /*
  * Defines for PMF SMC function ids.
  */
-#define PMF_SMC_GET_TIMESTAMP_32	0x82000010u
-#define PMF_SMC_GET_TIMESTAMP_64	0xC2000010u
+#define PMF_SMC_GET_TIMESTAMP_32	U(0x82000010)
+#define PMF_SMC_GET_TIMESTAMP_64	U(0xC2000010)
 #define PMF_NUM_SMC_CALLS		2
 
 /*
  * The macros below are used to identify
  * PMF calls from the SMC function ID.
  */
-#define PMF_FID_MASK	0xffe0u
-#define PMF_FID_VALUE	0u
+#define PMF_FID_MASK	U(0xffe0)
+#define PMF_FID_VALUE	U(0)
 #define is_pmf_fid(_fid)	(((_fid) & PMF_FID_MASK) == PMF_FID_VALUE)
 
 /* Following are the supported PMF service IDs */
diff --git a/include/lib/pmf/pmf_asm_macros.S b/include/lib/pmf/pmf_asm_macros.S
index d58829e..5e19e62 100644
--- a/include/lib/pmf/pmf_asm_macros.S
+++ b/include/lib/pmf/pmf_asm_macros.S
@@ -18,10 +18,12 @@
 	mov	x9, x30
 	bl	plat_my_core_pos
 	mov	x30, x9
-	ldr	x1, =__PERCPU_TIMESTAMP_SIZE__
+	adr	x2, __PMF_PERCPU_TIMESTAMP_END__
+	adr	x1, __PMF_TIMESTAMP_START__
+	sub	x1, x2, x1
 	mov	x2, #(\_tid * PMF_TS_SIZE)
 	madd	x0, x0, x1, x2
-	ldr	x1, =pmf_ts_mem_\_name
+	adr	x1, pmf_ts_mem_\_name
 	add	x0, x0, x1
 	.endm
 
diff --git a/include/lib/pmf/pmf_helpers.h b/include/lib/pmf/pmf_helpers.h
index b9757de..c535b22 100644
--- a/include/lib/pmf/pmf_helpers.h
+++ b/include/lib/pmf/pmf_helpers.h
@@ -11,7 +11,6 @@
 #include <assert.h>
 #include <bl_common.h>
 #include <platform.h>
-#include <pmf.h>
 #include <stddef.h>
 #include <stdint.h>
 
diff --git a/include/lib/utils.h b/include/lib/utils.h
index d46d846..f324a99 100644
--- a/include/lib/utils.h
+++ b/include/lib/utils.h
@@ -67,6 +67,29 @@
  *       zeroing.
  */
 void zeromem(void *mem, u_register_t length);
+
+/*
+ * Utility function to return the address of a symbol. By default, the
+ * compiler generates adr/adrp instruction pair to return the reference
+ * to the symbol and this utility is used to override this compiler
+ * generated to code to use `ldr` instruction.
+ *
+ * This helps when Position Independent Executable needs to reference a symbol
+ * which is constant and does not depend on the execute address of the binary.
+ */
+#define DEFINE_LOAD_SYM_ADDR(_name)		\
+static inline u_register_t load_addr_## _name(void)		\
+{								\
+	u_register_t v;						\
+	/* Create a void reference to silence compiler */	\
+	(void) _name;						\
+	__asm__ volatile ("ldr %0, =" #_name : "=r" (v));	\
+	return v;						\
+}
+
+/* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */
+#define LOAD_ADDR_OF(_name)	(typeof(_name) *) load_addr_## _name()
+
 #endif /* !(defined(__LINKER__) || defined(__ASSEMBLY__)) */
 
 #endif /* __UTILS_H__ */
diff --git a/include/lib/xlat_tables/xlat_tables_compat.h b/include/lib/xlat_tables/xlat_tables_compat.h
new file mode 100644
index 0000000..4650a8c
--- /dev/null
+++ b/include/lib/xlat_tables/xlat_tables_compat.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#if XLAT_TABLES_LIB_V2
+#include <xlat_tables_v2.h>
+#else
+#include <xlat_tables.h>
+#endif
diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h
index 02c3494..4a1d43c 100644
--- a/include/plat/arm/board/common/v2m_def.h
+++ b/include/plat/arm/board/common/v2m_def.h
@@ -6,8 +6,7 @@
 #ifndef V2M_DEF_H
 #define V2M_DEF_H
 
-#include <arm_xlat_tables.h>
-
+#include <xlat_tables_compat.h>
 
 /* V2M motherboard system registers & offsets */
 #define V2M_SYSREGS_BASE		UL(0x1c010000)
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index d5f5c15..0f5b57f 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -53,9 +53,9 @@
 #define ARM_DRAM_ID			2
 
 /* The first 4KB of Trusted SRAM are used as shared memory */
-#define ARM_TRUSTED_SRAM_BASE		0x04000000
+#define ARM_TRUSTED_SRAM_BASE		UL(0x04000000)
 #define ARM_SHARED_RAM_BASE		ARM_TRUSTED_SRAM_BASE
-#define ARM_SHARED_RAM_SIZE		0x00001000	/* 4 KB */
+#define ARM_SHARED_RAM_SIZE		UL(0x00001000)	/* 4 KB */
 
 /* The remaining Trusted SRAM is used to load the BL images */
 #define ARM_BL_RAM_BASE			(ARM_SHARED_RAM_BASE +	\
@@ -68,7 +68,7 @@
  *   - SCP TZC DRAM: If present, DRAM reserved for SCP use
  *   - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use
  */
-#define ARM_TZC_DRAM1_SIZE		ULL(0x01000000)
+#define ARM_TZC_DRAM1_SIZE		UL(0x01000000)
 
 #define ARM_SCP_TZC_DRAM1_BASE		(ARM_DRAM1_BASE +		\
 					 ARM_DRAM1_SIZE -		\
@@ -84,7 +84,7 @@
  * placed here.
  */
 #define ARM_EL3_TZC_DRAM1_BASE		(ARM_SCP_TZC_DRAM1_BASE - ARM_EL3_TZC_DRAM1_SIZE)
-#define ARM_EL3_TZC_DRAM1_SIZE		ULL(0x00200000) /* 2 MB */
+#define ARM_EL3_TZC_DRAM1_SIZE		UL(0x00200000) /* 2 MB */
 #define ARM_EL3_TZC_DRAM1_END		(ARM_EL3_TZC_DRAM1_BASE +	\
 					ARM_EL3_TZC_DRAM1_SIZE - 1)
 
@@ -122,7 +122,7 @@
 #define ARM_OPTEE_PAGEABLE_LOAD_BASE	(ARM_AP_TZC_DRAM1_BASE + \
 					 ARM_AP_TZC_DRAM1_SIZE - \
 					 ARM_OPTEE_PAGEABLE_LOAD_SIZE)
-#define ARM_OPTEE_PAGEABLE_LOAD_SIZE	0x400000
+#define ARM_OPTEE_PAGEABLE_LOAD_SIZE	UL(0x400000)
 #define ARM_OPTEE_PAGEABLE_LOAD_MEM	MAP_REGION_FLAT(		\
 					ARM_OPTEE_PAGEABLE_LOAD_BASE,	\
 					ARM_OPTEE_PAGEABLE_LOAD_SIZE,	\
@@ -144,12 +144,12 @@
 #define ARM_NS_DRAM1_END		(ARM_NS_DRAM1_BASE +		\
 					 ARM_NS_DRAM1_SIZE - 1)
 
-#define ARM_DRAM1_BASE			ULL(0x80000000)
-#define ARM_DRAM1_SIZE			ULL(0x80000000)
+#define ARM_DRAM1_BASE			UL(0x80000000)
+#define ARM_DRAM1_SIZE			UL(0x80000000)
 #define ARM_DRAM1_END			(ARM_DRAM1_BASE +		\
 					 ARM_DRAM1_SIZE - 1)
 
-#define ARM_DRAM2_BASE			ULL(0x880000000)
+#define ARM_DRAM2_BASE			UL(0x880000000)
 #define ARM_DRAM2_SIZE			PLAT_ARM_DRAM2_SIZE
 #define ARM_DRAM2_END			(ARM_DRAM2_BASE +		\
 					 ARM_DRAM2_SIZE - 1)
@@ -293,16 +293,16 @@
 					 ARM_BL_REGIONS)
 
 /* Memory mapped Generic timer interfaces  */
-#define ARM_SYS_CNTCTL_BASE		0x2a430000
-#define ARM_SYS_CNTREAD_BASE		0x2a800000
-#define ARM_SYS_TIMCTL_BASE		0x2a810000
-#define ARM_SYS_CNT_BASE_S		0x2a820000
-#define ARM_SYS_CNT_BASE_NS		0x2a830000
+#define ARM_SYS_CNTCTL_BASE		UL(0x2a430000)
+#define ARM_SYS_CNTREAD_BASE		UL(0x2a800000)
+#define ARM_SYS_TIMCTL_BASE		UL(0x2a810000)
+#define ARM_SYS_CNT_BASE_S		UL(0x2a820000)
+#define ARM_SYS_CNT_BASE_NS		UL(0x2a830000)
 
 #define ARM_CONSOLE_BAUDRATE		115200
 
 /* Trusted Watchdog constants */
-#define ARM_SP805_TWDG_BASE		0x2a490000
+#define ARM_SP805_TWDG_BASE		UL(0x2a490000)
 #define ARM_SP805_TWDG_CLK_HZ		32768
 /* The TBBR document specifies a watchdog timeout of 256 seconds. SP805
  * asserts reset after two consecutive countdowns (2 x 128 = 256 sec) */
@@ -344,7 +344,7 @@
  * This is known only to the platform as it might have a combination of
  * integrated and external caches.
  */
-#define CACHE_WRITEBACK_GRANULE		(1 << ARM_CACHE_WRITEBACK_SHIFT)
+#define CACHE_WRITEBACK_GRANULE		(U(1) << ARM_CACHE_WRITEBACK_SHIFT)
 
 /*
  * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
diff --git a/include/plat/arm/common/arm_sip_svc.h b/include/plat/arm/common/arm_sip_svc.h
index 68375af..3e25cbc 100644
--- a/include/plat/arm/common/arm_sip_svc.h
+++ b/include/plat/arm/common/arm_sip_svc.h
@@ -1,24 +1,26 @@
 /*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __ARM_SIP_SVC_H__
-#define __ARM_SIP_SVC_H__
+#ifndef ARM_SIP_SVC_H
+#define ARM_SIP_SVC_H
+
+#include <utils_def.h>
 
 /* SMC function IDs for SiP Service queries */
 
-#define ARM_SIP_SVC_CALL_COUNT		0x8200ff00
-#define ARM_SIP_SVC_UID			0x8200ff01
-/*					0x8200ff02 is reserved */
-#define ARM_SIP_SVC_VERSION		0x8200ff03
+#define ARM_SIP_SVC_CALL_COUNT		U(0x8200ff00)
+#define ARM_SIP_SVC_UID			U(0x8200ff01)
+/*					U(0x8200ff02) is reserved */
+#define ARM_SIP_SVC_VERSION		U(0x8200ff03)
 
 /* Function ID for requesting state switch of lower EL */
-#define ARM_SIP_SVC_EXE_STATE_SWITCH	0x82000020
+#define ARM_SIP_SVC_EXE_STATE_SWITCH	U(0x82000020)
 
 /* ARM SiP Service Calls version numbers */
-#define ARM_SIP_SVC_VERSION_MAJOR		0x0
-#define ARM_SIP_SVC_VERSION_MINOR		0x2
+#define ARM_SIP_SVC_VERSION_MAJOR		U(0x0)
+#define ARM_SIP_SVC_VERSION_MINOR		U(0x2)
 
-#endif /* __ARM_SIP_SVC_H__ */
+#endif /* ARM_SIP_SVC_H */
diff --git a/include/plat/arm/common/arm_xlat_tables.h b/include/plat/arm/common/arm_xlat_tables.h
deleted file mode 100644
index 0923ad8..0000000
--- a/include/plat/arm/common/arm_xlat_tables.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#if ARM_XLAT_TABLES_LIB_V1
-#include <xlat_tables.h>
-#else
-#include <xlat_tables_v2.h>
-#endif /* ARM_XLAT_TABLES_LIB_V1 */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 848f4ee..e7082d0 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -3,10 +3,9 @@
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
-#ifndef __PLAT_ARM_H__
-#define __PLAT_ARM_H__
+#ifndef PLAT_ARM_H
+#define PLAT_ARM_H
 
-#include <arm_xlat_tables.h>
 #include <bakery_lock.h>
 #include <cassert.h>
 #include <cpu_data.h>
@@ -14,6 +13,7 @@
 #include <spinlock.h>
 #include <tzc_common.h>
 #include <utils_def.h>
+#include <xlat_tables_compat.h>
 
 /*******************************************************************************
  * Forward declarations
@@ -25,7 +25,7 @@
 typedef struct arm_tzc_regions_info {
 	unsigned long long base;
 	unsigned long long end;
-	tzc_region_attributes_t sec_attr;
+	unsigned int sec_attr;
 	unsigned int nsaid_permissions;
 } arm_tzc_regions_info_t;
 
@@ -66,12 +66,6 @@
 		<= MAX_MMAP_REGIONS,					  \
 		assert_max_mmap_regions);
 
-/*
- * Utility functions common to ARM standard platforms
- */
-void arm_setup_page_tables(const mmap_region_t bl_regions[],
-			   const mmap_region_t plat_regions[]);
-
 void arm_setup_romlib(void);
 
 #if defined(IMAGE_BL31) || (defined(AARCH32) && defined(IMAGE_BL32))
@@ -298,4 +292,4 @@
 extern const mmap_region_t plat_arm_mmap[];
 extern const unsigned int arm_pm_idle_states[];
 
-#endif /* __PLAT_ARM_H__ */
+#endif /* PLAT_ARM_H */
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index 048c58a..3853319 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -26,6 +26,11 @@
 #define SSC_REG_BASE			0x2a420000
 #define SSC_GPRETN			(SSC_REG_BASE + 0x030)
 
+/* System ID Registers Unit */
+#define SID_REG_BASE			0x2a4a0000
+#define SID_SYSTEM_ID_OFFSET		0x40
+#define SID_SYSTEM_CFG_OFFSET		0x70
+
 /* The slave_bootsecure controls access to GPU, DMC and CS. */
 #define CSS_NIC400_SLAVE_BOOTSECURE	8
 
@@ -123,6 +128,8 @@
 #define SSC_VERSION_DESIGNER_ID_MASK		0xff
 #define SSC_VERSION_PART_NUM_MASK		0xfff
 
+#define SID_SYSTEM_ID_PART_NUM_MASK		0xfff
+
 /* SSC debug configuration registers */
 #define SSC_DBGCFG_SET		0x14
 #define SSC_DBGCFG_CLR		0x18
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S
index 1a075aa..002942e 100644
--- a/lib/aarch64/misc_helpers.S
+++ b/lib/aarch64/misc_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,7 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <assert_macros.S>
+#include <xlat_tables_defs.h>
 
 	.globl	get_afflvl_shift
 	.globl	mpidr_mask_lower_afflvls
@@ -23,6 +24,8 @@
 	.globl	disable_mmu_icache_el1
 	.globl	disable_mmu_icache_el3
 
+	.globl	fixup_gdt_reloc
+
 #if SUPPORT_VFP
 	.globl	enable_vfp
 #endif
@@ -497,3 +500,114 @@
 	ret
 endfunc enable_vfp
 #endif
+
+/* ---------------------------------------------------------------------------
+ * Helper to fixup Global Descriptor table (GDT) and dynamic relocations
+ * (.rela.dyn) at runtime.
+ *
+ * This function is meant to be used when the firmware is compiled with -fpie
+ * and linked with -pie options. We rely on the linker script exporting
+ * appropriate markers for start and end of the section. For GOT, we
+ * expect __GOT_START__ and __GOT_END__. Similarly for .rela.dyn, we expect
+ * __RELA_START__ and __RELA_END__.
+ *
+ * The function takes the limits of the memory to apply fixups to as
+ * arguments (which is usually the limits of the relocable BL image).
+ *   x0 -  the start of the fixup region
+ *   x1 -  the limit of the fixup region
+ * These addresses have to be page (4KB aligned).
+ * ---------------------------------------------------------------------------
+ */
+func fixup_gdt_reloc
+	mov	x6, x0
+	mov	x7, x1
+
+	/* Test if the limits are 4K aligned */
+#if ENABLE_ASSERTIONS
+	orr	x0, x0, x1
+	tst	x0, #(PAGE_SIZE - 1)
+	ASM_ASSERT(eq)
+#endif
+	/*
+	 * Calculate the offset based on return address in x30.
+	 * Assume that this funtion is called within a page of the start of
+	 * of fixup region.
+	 */
+	and	x2, x30, #~(PAGE_SIZE - 1)
+	sub	x0, x2, x6	/* Diff(S) = Current Address - Compiled Address */
+
+	adrp	x1, __GOT_START__
+	add	x1, x1, :lo12:__GOT_START__
+	adrp	x2, __GOT_END__
+	add	x2, x2, :lo12:__GOT_END__
+
+	/*
+	 * GOT is an array of 64_bit addresses which must be fixed up as
+	 * new_addr = old_addr + Diff(S).
+	 * The new_addr is the address currently the binary is executing from
+	 * and old_addr is the address at compile time.
+	 */
+1:
+	ldr	x3, [x1]
+	/* Skip adding offset if address is < lower limit */
+	cmp	x3, x6
+	b.lo	2f
+	/* Skip adding offset if address is >= upper limit */
+	cmp	x3, x7
+	b.ge	2f
+	add	x3, x3, x0
+	str	x3, [x1]
+2:
+	add	x1, x1, #8
+	cmp	x1, x2
+	b.lo	1b
+
+	/* Starting dynamic relocations. Use adrp/adr to get RELA_START and END */
+	adrp	x1, __RELA_START__
+	add	x1, x1, :lo12:__RELA_START__
+	adrp	x2, __RELA_END__
+	add	x2, x2, :lo12:__RELA_END__
+	/*
+	 * According to ELF-64 specification, the RELA data structure is as
+	 * follows:
+	 *	typedef struct
+	 * 	{
+	 *		Elf64_Addr r_offset;
+	 *		Elf64_Xword r_info;
+	 *		Elf64_Sxword r_addend;
+	 *	} Elf64_Rela;
+	 *
+	 * r_offset is address of reference
+	 * r_info is symbol index and type of relocation (in this case
+	 * 0x403 which corresponds to R_AARCH64_RELATIV).
+	 * r_addend is constant part of expression.
+	 *
+	 * Size of Elf64_Rela structure is 24 bytes.
+	 */
+1:
+	/* Assert that the relocation type is R_AARCH64_RELATIV */
+#if ENABLE_ASSERTIONS
+	ldr	x3, [x1, #8]
+	cmp	x3, #0x403
+	ASM_ASSERT(eq)
+#endif
+	ldr	x3, [x1]	/* r_offset */
+	add	x3, x0, x3
+	ldr	x4, [x1, #16]	/* r_addend */
+
+	/* Skip adding offset if r_addend is < lower limit */
+	cmp	x4, x6
+	b.lo	2f
+	/* Skip adding offset if r_addend entry is >= upper limit */
+	cmp	x4, x7
+	b.ge	2f
+
+	add	x4, x0, x4	/* Diff(S) + r_addend */
+	str	x4, [x3]
+
+2:	add	x1, x1, #24
+	cmp	x1, x2
+	b.lo	1b
+
+	ret
+endfunc fixup_gdt_reloc
diff --git a/lib/cpus/aarch32/aem_generic.S b/lib/cpus/aarch32/aem_generic.S
index 5f3d744..7bd586a 100644
--- a/lib/cpus/aarch32/aem_generic.S
+++ b/lib/cpus/aarch32/aem_generic.S
@@ -40,6 +40,15 @@
 	b	dcsw_op_all
 endfunc aem_generic_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for AEM. Must follow AAPCS.
+ */
+func aem_generic_errata_report
+	bx	lr
+endfunc aem_generic_errata_report
+#endif
+
 /* cpu_ops for Base AEM FVP */
 declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \
 	aem_generic_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a12.S b/lib/cpus/aarch32/cortex_a12.S
index 73c9750..5300fe0 100644
--- a/lib/cpus/aarch32/cortex_a12.S
+++ b/lib/cpus/aarch32/cortex_a12.S
@@ -69,6 +69,15 @@
 	b	cortex_a12_disable_smp
 endfunc cortex_a12_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex-A12. Must follow AAPCS.
+ */
+func cortex_a12_errata_report
+	bx	lr
+endfunc cortex_a12_errata_report
+#endif
+
 declare_cpu_ops cortex_a12, CORTEX_A12_MIDR, \
 	cortex_a12_reset_func, \
 	cortex_a12_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a32.S b/lib/cpus/aarch32/cortex_a32.S
index 2b6df27..c262276 100644
--- a/lib/cpus/aarch32/cortex_a32.S
+++ b/lib/cpus/aarch32/cortex_a32.S
@@ -117,6 +117,15 @@
 	b	cortex_a32_disable_smp
 endfunc cortex_a32_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex-A32. Must follow AAPCS.
+ */
+func cortex_a32_errata_report
+	bx	lr
+endfunc cortex_a32_errata_report
+#endif
+
 declare_cpu_ops cortex_a32, CORTEX_A32_MIDR, \
 	cortex_a32_reset_func, \
 	cortex_a32_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a5.S b/lib/cpus/aarch32/cortex_a5.S
index c07c13e..8abb66f 100644
--- a/lib/cpus/aarch32/cortex_a5.S
+++ b/lib/cpus/aarch32/cortex_a5.S
@@ -69,6 +69,15 @@
 	b	cortex_a5_disable_smp
 endfunc cortex_a5_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex-A5. Must follow AAPCS.
+ */
+func cortex_a5_errata_report
+	bx	lr
+endfunc cortex_a5_errata_report
+#endif
+
 declare_cpu_ops cortex_a5, CORTEX_A5_MIDR, \
 	cortex_a5_reset_func, \
 	cortex_a5_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a7.S b/lib/cpus/aarch32/cortex_a7.S
index 0278d1f..4d4bb77 100644
--- a/lib/cpus/aarch32/cortex_a7.S
+++ b/lib/cpus/aarch32/cortex_a7.S
@@ -69,6 +69,15 @@
 	b	cortex_a7_disable_smp
 endfunc cortex_a7_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex-A7. Must follow AAPCS.
+ */
+func cortex_a7_errata_report
+	bx	lr
+endfunc cortex_a7_errata_report
+#endif
+
 declare_cpu_ops cortex_a7, CORTEX_A7_MIDR, \
 	cortex_a7_reset_func, \
 	cortex_a7_core_pwr_dwn, \
diff --git a/lib/cpus/aarch64/aem_generic.S b/lib/cpus/aarch64/aem_generic.S
index 7592e3d..51b5ce9 100644
--- a/lib/cpus/aarch64/aem_generic.S
+++ b/lib/cpus/aarch64/aem_generic.S
@@ -46,6 +46,15 @@
 	b	dcsw_op_all
 endfunc aem_generic_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for AEM. Must follow AAPCS.
+ */
+func aem_generic_errata_report
+	ret
+endfunc aem_generic_errata_report
+#endif
+
 	/* ---------------------------------------------
 	 * This function provides cpu specific
 	 * register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a35.S b/lib/cpus/aarch64/cortex_a35.S
index b22189c..2e0d631 100644
--- a/lib/cpus/aarch64/cortex_a35.S
+++ b/lib/cpus/aarch64/cortex_a35.S
@@ -114,6 +114,16 @@
 	b	cortex_a35_disable_smp
 endfunc cortex_a35_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex A35. Must follow AAPCS.
+ */
+func cortex_a35_errata_report
+	ret
+endfunc cortex_a35_errata_report
+#endif
+
+
 	/* ---------------------------------------------
 	 * This function provides cortex_a35 specific
 	 * register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a75_pubsub.c b/lib/cpus/aarch64/cortex_a75_pubsub.c
index 16f62f4..f4ca486 100644
--- a/lib/cpus/aarch64/cortex_a75_pubsub.c
+++ b/lib/cpus/aarch64/cortex_a75_pubsub.c
@@ -12,14 +12,16 @@
 {
 	if (midr_match(CORTEX_A75_MIDR) != 0)
 		cpuamu_context_save(CORTEX_A75_AMU_NR_COUNTERS);
-	return 0;
+
+	return (void *)0;
 }
 
 static void *cortex_a75_context_restore(const void *arg)
 {
 	if (midr_match(CORTEX_A75_MIDR) != 0)
 		cpuamu_context_restore(CORTEX_A75_AMU_NR_COUNTERS);
-	return 0;
+
+	return (void *)0;
 }
 
 SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_a75_context_save);
diff --git a/lib/cpus/aarch64/cortex_ares_pubsub.c b/lib/cpus/aarch64/cortex_ares_pubsub.c
index c7d850a..9566223 100644
--- a/lib/cpus/aarch64/cortex_ares_pubsub.c
+++ b/lib/cpus/aarch64/cortex_ares_pubsub.c
@@ -12,14 +12,16 @@
 {
 	if (midr_match(CORTEX_ARES_MIDR) != 0)
 		cpuamu_context_save(CORTEX_ARES_AMU_NR_COUNTERS);
-	return 0;
+
+	return (void *)0;
 }
 
 static void *cortex_ares_context_restore(const void *arg)
 {
 	if (midr_match(CORTEX_ARES_MIDR) != 0)
 		cpuamu_context_restore(CORTEX_ARES_AMU_NR_COUNTERS);
-	return 0;
+
+	return (void *)0;
 }
 
 SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_ares_context_save);
diff --git a/lib/cpus/aarch64/cortex_deimos.S b/lib/cpus/aarch64/cortex_deimos.S
index aec62a2..cad906f 100644
--- a/lib/cpus/aarch64/cortex_deimos.S
+++ b/lib/cpus/aarch64/cortex_deimos.S
@@ -27,6 +27,16 @@
 	ret
 endfunc cortex_deimos_core_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex Deimos. Must follow AAPCS.
+ */
+func cortex_deimos_errata_report
+	ret
+endfunc cortex_deimos_errata_report
+#endif
+
+
 	/* ---------------------------------------------
 	 * This function provides Cortex-Deimos specific
 	 * register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_helios.S b/lib/cpus/aarch64/cortex_helios.S
index bcda741..4812ac4 100644
--- a/lib/cpus/aarch64/cortex_helios.S
+++ b/lib/cpus/aarch64/cortex_helios.S
@@ -19,6 +19,16 @@
 	ret
 endfunc cortex_helios_cpu_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex Helios. Must follow AAPCS.
+ */
+func cortex_helios_errata_report
+	ret
+endfunc cortex_helios_errata_report
+#endif
+
+
 .section .rodata.cortex_helios_regs, "aS"
 cortex_helios_regs:  /* The ascii list of register names to be reported */
 	.asciz	"cpuectlr_el1", ""
diff --git a/lib/cpus/aarch64/cpuamu_helpers.S b/lib/cpus/aarch64/cpuamu_helpers.S
index 8965d6d..79b7288 100644
--- a/lib/cpus/aarch64/cpuamu_helpers.S
+++ b/lib/cpus/aarch64/cpuamu_helpers.S
@@ -16,7 +16,7 @@
 	.globl	cpuamu_write_cpuamcntenclr_el0
 
 /*
- * uint64_t cpuamu_cnt_read(int idx);
+ * uint64_t cpuamu_cnt_read(unsigned int idx);
  *
  * Given `idx`, read the corresponding AMU counter
  * and return it in `x0`.
@@ -41,7 +41,7 @@
 endfunc cpuamu_cnt_read
 
 /*
- * void cpuamu_cnt_write(int idx, uint64_t val);
+ * void cpuamu_cnt_write(unsigned int idx, uint64_t val);
  *
  * Given `idx`, write `val` to the corresponding AMU counter.
  */
diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c
index c679336..42603cb 100644
--- a/lib/cpus/errata_report.c
+++ b/lib/cpus/errata_report.c
@@ -12,6 +12,7 @@
 #include <debug.h>
 #include <errata_report.h>
 #include <spinlock.h>
+#include <stdbool.h>
 #include <utils.h>
 
 #ifdef IMAGE_BL1
@@ -35,10 +36,10 @@
  */
 int errata_needs_reporting(spinlock_t *lock, uint32_t *reported)
 {
-	int report_now;
+	bool report_now;
 
 	/* If already reported, return false. */
-	if (*reported)
+	if (*reported != 0U)
 		return 0;
 
 	/*
@@ -46,7 +47,7 @@
 	 * report status to true.
 	 */
 	spin_lock(lock);
-	report_now = !(*reported);
+	report_now = (*reported == 0U);
 	if (report_now)
 		*reported = 1;
 	spin_unlock(lock);
@@ -75,8 +76,8 @@
 
 
 	assert(status < ARRAY_SIZE(errata_status_str));
-	assert(cpu);
-	assert(id);
+	assert(cpu != NULL);
+	assert(id != NULL);
 
 	msg = errata_status_str[status];
 
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 11ef6e5..80cea28 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -14,6 +14,7 @@
 #include <platform.h>
 #include <platform_def.h>
 #include <smccc_helpers.h>
+#include <stdbool.h>
 #include <string.h>
 #include <utils.h>
 
@@ -129,7 +130,7 @@
  * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise
  * it is zero.
  ******************************************************************************/
-static void enable_extensions_nonsecure(int el2_unused)
+static void enable_extensions_nonsecure(bool el2_unused)
 {
 #if IMAGE_BL32
 #if ENABLE_AMU
@@ -175,7 +176,7 @@
 {
 	uint32_t hsctlr, scr;
 	cpu_context_t *ctx = cm_get_context(security_state);
-	int el2_unused = 0;
+	bool el2_unused = false;
 
 	assert(ctx);
 
@@ -200,7 +201,7 @@
 			isb();
 		} else if (read_id_pfr1() &
 			(ID_PFR1_VIRTEXT_MASK << ID_PFR1_VIRTEXT_SHIFT)) {
-			el2_unused = 1;
+			el2_unused = true;
 
 			/*
 			 * Set the NS bit to access NS copies of certain banked
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index acc8d6d..f037e18 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -18,6 +18,7 @@
 #include <pubsub_events.h>
 #include <smccc_helpers.h>
 #include <spe.h>
+#include <stdbool.h>
 #include <string.h>
 #include <sve.h>
 #include <utils.h>
@@ -231,7 +232,7 @@
  * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise
  * it is zero.
  ******************************************************************************/
-static void enable_extensions_nonsecure(int el2_unused)
+static void enable_extensions_nonsecure(bool el2_unused)
 {
 #if IMAGE_BL31
 #if ENABLE_SPE_FOR_LOWER_ELS
@@ -289,7 +290,8 @@
 {
 	uint32_t sctlr_elx, scr_el3, mdcr_el2;
 	cpu_context_t *ctx = cm_get_context(security_state);
-	int el2_unused = 0;
+	bool el2_unused = false;
+	uint64_t hcr_el2 = 0;
 
 	assert(ctx);
 
@@ -303,19 +305,26 @@
 			sctlr_elx |= SCTLR_EL2_RES1;
 			write_sctlr_el2(sctlr_elx);
 		} else if (EL_IMPLEMENTED(2)) {
-			el2_unused = 1;
+			el2_unused = true;
 
 			/*
 			 * EL2 present but unused, need to disable safely.
 			 * SCTLR_EL2 can be ignored in this case.
 			 *
-			 * Initialise all fields in HCR_EL2, except HCR_EL2.RW,
-			 * to zero so that Non-secure operations do not trap to
-			 * EL2.
-			 *
-			 * HCR_EL2.RW: Set this field to match SCR_EL3.RW
+			 * Set EL2 register width appropriately: Set HCR_EL2
+			 * field to match SCR_EL3.RW.
 			 */
-			write_hcr_el2((scr_el3 & SCR_RW_BIT) ? HCR_RW_BIT : 0);
+			if (scr_el3 & SCR_RW_BIT)
+				hcr_el2 |= HCR_RW_BIT;
+
+			/*
+			 * For Armv8.3 pointer authentication feature, disable
+			 * traps to EL2 when accessing key registers or using
+			 * pointer authentication instructions from lower ELs.
+			 */
+			hcr_el2 |= (HCR_API_BIT | HCR_APK_BIT);
+
+			write_hcr_el2(hcr_el2);
 
 			/*
 			 * Initialise CPTR_EL2 setting all fields rather than
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
index 05c98f1..585d908 100644
--- a/lib/extensions/amu/aarch32/amu.c
+++ b/lib/extensions/amu/aarch32/amu.c
@@ -10,6 +10,7 @@
 #include <arch_helpers.h>
 #include <platform.h>
 #include <pubsub_events.h>
+#include <stdbool.h>
 
 #define AMU_GROUP0_NR_COUNTERS	4
 
@@ -20,17 +21,17 @@
 
 static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
 
-int amu_supported(void)
+bool amu_supported(void)
 {
 	uint64_t features;
 
 	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
-	return (features & ID_PFR0_AMU_MASK) == 1;
+	return (features & ID_PFR0_AMU_MASK) == 1U;
 }
 
-void amu_enable(int el2_unused)
+void amu_enable(bool el2_unused)
 {
-	if (amu_supported() == 0)
+	if (!amu_supported())
 		return;
 
 	if (el2_unused) {
@@ -54,8 +55,8 @@
 /* Read the group 0 counter identified by the given `idx`. */
 uint64_t amu_group0_cnt_read(int idx)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
 
 	return amu_group0_cnt_read_internal(idx);
 }
@@ -63,8 +64,8 @@
 /* Write the group 0 counter identified by the given `idx` with `val`. */
 void amu_group0_cnt_write(int idx, uint64_t val)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
 
 	amu_group0_cnt_write_internal(idx, val);
 	isb();
@@ -73,8 +74,8 @@
 /* Read the group 1 counter identified by the given `idx`. */
 uint64_t amu_group1_cnt_read(int idx)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
 
 	return amu_group1_cnt_read_internal(idx);
 }
@@ -82,8 +83,8 @@
 /* Write the group 1 counter identified by the given `idx` with `val`. */
 void amu_group1_cnt_write(int idx, uint64_t val)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
 
 	amu_group1_cnt_write_internal(idx, val);
 	isb();
@@ -91,8 +92,8 @@
 
 void amu_group1_set_evtype(int idx, unsigned int val)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
 
 	amu_group1_set_evtype_internal(idx, val);
 	isb();
@@ -103,7 +104,7 @@
 	struct amu_ctx *ctx;
 	int i;
 
-	if (amu_supported() == 0)
+	if (!amu_supported())
 		return (void *)-1;
 
 	ctx = &amu_ctxs[plat_my_core_pos()];
@@ -126,7 +127,7 @@
 	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
 		ctx->group1_cnts[i] = amu_group1_cnt_read(i);
 
-	return 0;
+	return (void *)0;
 }
 
 static void *amu_context_restore(const void *arg)
@@ -134,13 +135,13 @@
 	struct amu_ctx *ctx;
 	int i;
 
-	if (amu_supported() == 0)
+	if (!amu_supported())
 		return (void *)-1;
 
 	ctx = &amu_ctxs[plat_my_core_pos()];
 
 	/* Counters were disabled in `amu_context_save()` */
-	assert(read_amcntenset0() == 0 && read_amcntenset1() == 0);
+	assert((read_amcntenset0() == 0U) && (read_amcntenset1() == 0U));
 
 	/* Restore group 0 counters */
 	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
@@ -153,7 +154,7 @@
 
 	/* Enable group 1 counters */
 	write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
-	return 0;
+	return (void *)0;
 }
 
 SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index 5d556e5..1564e84 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -11,6 +11,7 @@
 #include <assert.h>
 #include <platform.h>
 #include <pubsub_events.h>
+#include <stdbool.h>
 
 #define AMU_GROUP0_NR_COUNTERS	4
 
@@ -21,23 +22,23 @@
 
 static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
 
-int amu_supported(void)
+bool amu_supported(void)
 {
 	uint64_t features;
 
 	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT;
-	return (features & ID_AA64PFR0_AMU_MASK) == 1;
+	return (features & ID_AA64PFR0_AMU_MASK) == 1U;
 }
 
 /*
  * Enable counters.  This function is meant to be invoked
  * by the context management library before exiting from EL3.
  */
-void amu_enable(int el2_unused)
+void amu_enable(bool el2_unused)
 {
 	uint64_t v;
 
-	if (amu_supported() == 0)
+	if (!amu_supported())
 		return;
 
 	if (el2_unused) {
@@ -67,8 +68,8 @@
 /* Read the group 0 counter identified by the given `idx`. */
 uint64_t amu_group0_cnt_read(int idx)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
 
 	return amu_group0_cnt_read_internal(idx);
 }
@@ -76,8 +77,8 @@
 /* Write the group 0 counter identified by the given `idx` with `val`. */
 void amu_group0_cnt_write(int idx, uint64_t val)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
 
 	amu_group0_cnt_write_internal(idx, val);
 	isb();
@@ -86,8 +87,8 @@
 /* Read the group 1 counter identified by the given `idx`. */
 uint64_t amu_group1_cnt_read(int idx)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
 
 	return amu_group1_cnt_read_internal(idx);
 }
@@ -95,8 +96,8 @@
 /* Write the group 1 counter identified by the given `idx` with `val`. */
 void amu_group1_cnt_write(int idx, uint64_t val)
 {
-	assert(amu_supported() != 0);
-	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
 
 	amu_group1_cnt_write_internal(idx, val);
 	isb();
@@ -108,8 +109,8 @@
  */
 void amu_group1_set_evtype(int idx, unsigned int val)
 {
-	assert(amu_supported() != 0);
-	assert (idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+	assert(amu_supported());
+	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
 
 	amu_group1_set_evtype_internal(idx, val);
 	isb();
@@ -120,14 +121,14 @@
 	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
 	int i;
 
-	if (amu_supported() == 0)
+	if (!amu_supported())
 		return (void *)-1;
 
 	/* Assert that group 0/1 counter configuration is what we expect */
-	assert(read_amcntenset0_el0() == AMU_GROUP0_COUNTERS_MASK &&
-	       read_amcntenset1_el0() == AMU_GROUP1_COUNTERS_MASK);
+	assert((read_amcntenset0_el0() == AMU_GROUP0_COUNTERS_MASK) &&
+	       (read_amcntenset1_el0() == AMU_GROUP1_COUNTERS_MASK));
 
-	assert((sizeof(int) * 8) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK)
+	assert(((sizeof(int) * 8) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK))
 		<= AMU_GROUP1_NR_COUNTERS);
 
 	/*
@@ -146,7 +147,7 @@
 	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
 		ctx->group1_cnts[i] = amu_group1_cnt_read(i);
 
-	return 0;
+	return (void *)0;
 }
 
 static void *amu_context_restore(const void *arg)
@@ -154,30 +155,30 @@
 	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
 	int i;
 
-	if (amu_supported() == 0)
+	if (!amu_supported())
 		return (void *)-1;
 
 	/* Counters were disabled in `amu_context_save()` */
-	assert(read_amcntenset0_el0() == 0 && read_amcntenset1_el0() == 0);
+	assert((read_amcntenset0_el0() == 0U) && (read_amcntenset1_el0() == 0U));
 
-	assert((sizeof(int) * 8) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK)
+	assert(((sizeof(int) * 8U) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK))
 		<= AMU_GROUP1_NR_COUNTERS);
 
 	/* Restore group 0 counters */
 	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
-		if (AMU_GROUP0_COUNTERS_MASK & (1U << i))
+		if ((AMU_GROUP0_COUNTERS_MASK & (1U << i)) != 0U)
 			amu_group0_cnt_write(i, ctx->group0_cnts[i]);
 
 	/* Restore group 1 counters */
 	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
-		if (AMU_GROUP1_COUNTERS_MASK & (1U << i))
+		if ((AMU_GROUP1_COUNTERS_MASK & (1U << i)) != 0U)
 			amu_group1_cnt_write(i, ctx->group1_cnts[i]);
 
 	/* Restore group 0/1 counter configuration */
 	write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
 	write_amcntenset1_el0(AMU_GROUP1_COUNTERS_MASK);
 
-	return 0;
+	return (void *)0;
 }
 
 SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
diff --git a/lib/extensions/mpam/mpam.c b/lib/extensions/mpam/mpam.c
index e628827..d57bb47 100644
--- a/lib/extensions/mpam/mpam.c
+++ b/lib/extensions/mpam/mpam.c
@@ -16,7 +16,7 @@
 	return ((features & ID_AA64PFR0_MPAM_MASK) != 0U);
 }
 
-void mpam_enable(int el2_unused)
+void mpam_enable(bool el2_unused)
 {
 	if (!mpam_supported())
 		return;
@@ -31,7 +31,7 @@
 	 * If EL2 is implemented but unused, disable trapping to EL2 when lower
 	 * ELs access their own MPAM registers.
 	 */
-	if (el2_unused != 0) {
+	if (el2_unused) {
 		write_mpam2_el2(0);
 
 		if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U)
diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c
index dc35840..e5df015 100644
--- a/lib/extensions/spe/spe.c
+++ b/lib/extensions/spe/spe.c
@@ -8,26 +8,30 @@
 #include <arch_helpers.h>
 #include <pubsub.h>
 #include <spe.h>
+#include <stdbool.h>
 
-/*
- * The assembler does not yet understand the psb csync mnemonic
- * so use the equivalent hint instruction.
- */
-#define psb_csync()	asm volatile("hint #17")
+static inline void psb_csync(void)
+{
+	/*
+	 * The assembler does not yet understand the psb csync mnemonic
+	 * so use the equivalent hint instruction.
+	 */
+	__asm__ volatile("hint #17");
+}
 
-int spe_supported(void)
+bool spe_supported(void)
 {
 	uint64_t features;
 
 	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
-	return (features & ID_AA64DFR0_PMS_MASK) == 1;
+	return (features & ID_AA64DFR0_PMS_MASK) == 1U;
 }
 
-void spe_enable(int el2_unused)
+void spe_enable(bool el2_unused)
 {
 	uint64_t v;
 
-	if (spe_supported() == 0)
+	if (!spe_supported())
 		return;
 
 	if (el2_unused) {
@@ -59,7 +63,7 @@
 {
 	uint64_t v;
 
-	if (spe_supported() == 0)
+	if (!spe_supported())
 		return;
 
 	/* Drain buffered data */
@@ -75,13 +79,14 @@
 
 static void *spe_drain_buffers_hook(const void *arg)
 {
-	if (spe_supported() == 0)
+	if (!spe_supported())
 		return (void *)-1;
 
 	/* Drain buffered data */
 	psb_csync();
 	dsbnsh();
-	return 0;
+
+	return (void *)0;
 }
 
 SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook);
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
index 6442487..e031bf6 100644
--- a/lib/extensions/sve/sve.c
+++ b/lib/extensions/sve/sve.c
@@ -7,21 +7,22 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <pubsub.h>
+#include <stdbool.h>
 #include <sve.h>
 
-int sve_supported(void)
+bool sve_supported(void)
 {
 	uint64_t features;
 
 	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
-	return (features & ID_AA64PFR0_SVE_MASK) == 1;
+	return (features & ID_AA64PFR0_SVE_MASK) == 1U;
 }
 
 static void *disable_sve_hook(const void *arg)
 {
 	uint64_t cptr;
 
-	if (sve_supported() == 0)
+	if (!sve_supported())
 		return (void *)-1;
 
 	/*
@@ -39,14 +40,14 @@
 	 * No explicit ISB required here as ERET to switch to Secure
 	 * world covers it
 	 */
-	return 0;
+	return (void *)0;
 }
 
 static void *enable_sve_hook(const void *arg)
 {
 	uint64_t cptr;
 
-	if (sve_supported() == 0)
+	if (!sve_supported())
 		return (void *)-1;
 
 	/*
@@ -60,14 +61,14 @@
 	 * No explicit ISB required here as ERET to switch to Non-secure
 	 * world covers it
 	 */
-	return 0;
+	return (void *)0;
 }
 
-void sve_enable(int el2_unused)
+void sve_enable(bool el2_unused)
 {
 	uint64_t cptr;
 
-	if (sve_supported() == 0)
+	if (!sve_supported())
 		return;
 
 #if CTX_INCLUDE_FPREGS
diff --git a/lib/libc/libc.mk b/lib/libc/libc.mk
index 554f36b..daa2ec1 100644
--- a/lib/libc/libc.mk
+++ b/lib/libc/libc.mk
@@ -21,7 +21,8 @@
 			strcmp.c			\
 			strlen.c			\
 			strncmp.c			\
-			strnlen.c)
+			strnlen.c			\
+			strrchr.c)
 
 INCLUDES	+=	-Iinclude/lib/libc		\
 			-Iinclude/lib/libc/$(ARCH)	\
diff --git a/lib/libc/strrchr.c b/lib/libc/strrchr.c
new file mode 100644
index 0000000..cd435ff
--- /dev/null
+++ b/lib/libc/strrchr.c
@@ -0,0 +1,49 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+char *
+strrchr(const char *p, int ch)
+{
+	char *save;
+	char c;
+
+	c = ch;
+	for (save = NULL;; ++p) {
+		if (*p == c)
+			save = (char *)p;
+		if (*p == '\0')
+			return (save);
+	}
+	/* NOTREACHED */
+}
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index 22286a1..ae03b11 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -55,7 +55,12 @@
 
 #include "libfdt_internal.h"
 
-int fdt_check_header(const void *fdt)
+/*
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
+ * that the given buffer contains what appears to be a flattened
+ * device tree with sane information in its header.
+ */
+int fdt_ro_probe_(const void *fdt)
 {
 	if (fdt_magic(fdt) == FDT_MAGIC) {
 		/* Complete tree */
@@ -74,6 +79,78 @@
 	return 0;
 }
 
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+	return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+			uint32_t base, uint32_t size)
+{
+	if (!check_off_(hdrsize, totalsize, base))
+		return 0; /* block start out of bounds */
+	if ((base + size) < base)
+		return 0; /* overflow */
+	if (!check_off_(hdrsize, totalsize, base + size))
+		return 0; /* block end out of bounds */
+	return 1;
+}
+
+size_t fdt_header_size_(uint32_t version)
+{
+	if (version <= 1)
+		return FDT_V1_SIZE;
+	else if (version <= 2)
+		return FDT_V2_SIZE;
+	else if (version <= 3)
+		return FDT_V3_SIZE;
+	else if (version <= 16)
+		return FDT_V16_SIZE;
+	else
+		return FDT_V17_SIZE;
+}
+
+int fdt_check_header(const void *fdt)
+{
+	size_t hdrsize;
+
+	if (fdt_magic(fdt) != FDT_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	hdrsize = fdt_header_size(fdt);
+	if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+	    || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION))
+		return -FDT_ERR_BADVERSION;
+	if (fdt_version(fdt) < fdt_last_comp_version(fdt))
+		return -FDT_ERR_BADVERSION;
+
+	if ((fdt_totalsize(fdt) < hdrsize)
+	    || (fdt_totalsize(fdt) > INT_MAX))
+		return -FDT_ERR_TRUNCATED;
+
+	/* Bounds check memrsv block */
+	if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt)))
+		return -FDT_ERR_TRUNCATED;
+
+	/* Bounds check structure block */
+	if (fdt_version(fdt) < 17) {
+		if (!check_off_(hdrsize, fdt_totalsize(fdt),
+				fdt_off_dt_struct(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	} else {
+		if (!check_block_(hdrsize, fdt_totalsize(fdt),
+				  fdt_off_dt_struct(fdt),
+				  fdt_size_dt_struct(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
+	/* Bounds check strings block */
+	if (!check_block_(hdrsize, fdt_totalsize(fdt),
+			  fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt)))
+		return -FDT_ERR_TRUNCATED;
+
+	return 0;
+}
+
 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 {
 	unsigned absoffset = offset + fdt_off_dt_struct(fdt);
@@ -88,7 +165,7 @@
 		    || ((offset + len) > fdt_size_dt_struct(fdt)))
 			return NULL;
 
-	return _fdt_offset_ptr(fdt, offset);
+	return fdt_offset_ptr_(fdt, offset);
 }
 
 uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
@@ -123,6 +200,9 @@
 		/* skip-name offset, length and value */
 		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
 			+ fdt32_to_cpu(*lenp);
+		if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
+		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
+			offset += 4;
 		break;
 
 	case FDT_END:
@@ -141,7 +221,7 @@
 	return tag;
 }
 
-int _fdt_check_node_offset(const void *fdt, int offset)
+int fdt_check_node_offset_(const void *fdt, int offset)
 {
 	if ((offset < 0) || (offset % FDT_TAGSIZE)
 	    || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
@@ -150,7 +230,7 @@
 	return offset;
 }
 
-int _fdt_check_prop_offset(const void *fdt, int offset)
+int fdt_check_prop_offset_(const void *fdt, int offset)
 {
 	if ((offset < 0) || (offset % FDT_TAGSIZE)
 	    || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
@@ -165,7 +245,7 @@
 	uint32_t tag;
 
 	if (offset >= 0)
-		if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
+		if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
 			return nextoffset;
 
 	do {
@@ -227,7 +307,7 @@
 	return offset;
 }
 
-const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
 {
 	int len = strlen(s) + 1;
 	const char *last = strtab + tabsize - len;
@@ -241,7 +321,7 @@
 
 int fdt_move(const void *fdt, void *buf, int bufsize)
 {
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (fdt_totalsize(fdt) > bufsize)
 		return -FDT_ERR_NOSPACE;
diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c
index eff4dbc..49537b5 100644
--- a/lib/libfdt/fdt_addresses.c
+++ b/lib/libfdt/fdt_addresses.c
@@ -1,6 +1,7 @@
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
+ * Copyright (C) 2018 embedded brains GmbH
  *
  * libfdt is dual licensed: you can use it either under the terms of
  * the GPL, or the BSD license, at your option.
@@ -55,42 +56,32 @@
 
 #include "libfdt_internal.h"
 
-int fdt_address_cells(const void *fdt, int nodeoffset)
+static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
 {
-	const fdt32_t *ac;
+	const fdt32_t *c;
 	int val;
 	int len;
 
-	ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
-	if (!ac)
+	c = fdt_getprop(fdt, nodeoffset, name, &len);
+	if (!c)
 		return 2;
 
-	if (len != sizeof(*ac))
+	if (len != sizeof(*c))
 		return -FDT_ERR_BADNCELLS;
 
-	val = fdt32_to_cpu(*ac);
+	val = fdt32_to_cpu(*c);
 	if ((val <= 0) || (val > FDT_MAX_NCELLS))
 		return -FDT_ERR_BADNCELLS;
 
 	return val;
 }
 
+int fdt_address_cells(const void *fdt, int nodeoffset)
+{
+	return fdt_cells(fdt, nodeoffset, "#address-cells");
+}
+
 int fdt_size_cells(const void *fdt, int nodeoffset)
 {
-	const fdt32_t *sc;
-	int val;
-	int len;
-
-	sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
-	if (!sc)
-		return 2;
-
-	if (len != sizeof(*sc))
-		return -FDT_ERR_BADNCELLS;
-
-	val = fdt32_to_cpu(*sc);
-	if ((val < 0) || (val > FDT_MAX_NCELLS))
-		return -FDT_ERR_BADNCELLS;
-
-	return val;
+	return fdt_cells(fdt, nodeoffset, "#size-cells");
 }
diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c
index f72d13b..f2ae9b7 100644
--- a/lib/libfdt/fdt_empty_tree.c
+++ b/lib/libfdt/fdt_empty_tree.c
@@ -81,4 +81,3 @@
 
 	return fdt_open_into(buf, buf, bufsize);
 }
-
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
new file mode 100644
index 0000000..5fdab6c
--- /dev/null
+++ b/lib/libfdt/fdt_overlay.c
@@ -0,0 +1,912 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2016 Free Electrons
+ * Copyright (C) 2016 NextThing Co.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+/**
+ * overlay_get_target_phandle - retrieves the target phandle of a fragment
+ * @fdto: pointer to the device tree overlay blob
+ * @fragment: node offset of the fragment in the overlay
+ *
+ * overlay_get_target_phandle() retrieves the target phandle of an
+ * overlay fragment when that fragment uses a phandle (target
+ * property) instead of a path (target-path property).
+ *
+ * returns:
+ *      the phandle pointed by the target property
+ *      0, if the phandle was not found
+ *	-1, if the phandle was malformed
+ */
+static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
+{
+	const fdt32_t *val;
+	int len;
+
+	val = fdt_getprop(fdto, fragment, "target", &len);
+	if (!val)
+		return 0;
+
+	if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
+		return (uint32_t)-1;
+
+	return fdt32_to_cpu(*val);
+}
+
+/**
+ * overlay_get_target - retrieves the offset of a fragment's target
+ * @fdt: Base device tree blob
+ * @fdto: Device tree overlay blob
+ * @fragment: node offset of the fragment in the overlay
+ * @pathp: pointer which receives the path of the target (or NULL)
+ *
+ * overlay_get_target() retrieves the target offset in the base
+ * device tree of a fragment, no matter how the actual targetting is
+ * done (through a phandle or a path)
+ *
+ * returns:
+ *      the targetted node offset in the base device tree
+ *      Negative error code on error
+ */
+static int overlay_get_target(const void *fdt, const void *fdto,
+			      int fragment, char const **pathp)
+{
+	uint32_t phandle;
+	const char *path = NULL;
+	int path_len = 0, ret;
+
+	/* Try first to do a phandle based lookup */
+	phandle = overlay_get_target_phandle(fdto, fragment);
+	if (phandle == (uint32_t)-1)
+		return -FDT_ERR_BADPHANDLE;
+
+	/* no phandle, try path */
+	if (!phandle) {
+		/* And then a path based lookup */
+		path = fdt_getprop(fdto, fragment, "target-path", &path_len);
+		if (path)
+			ret = fdt_path_offset(fdt, path);
+		else
+			ret = path_len;
+	} else
+		ret = fdt_node_offset_by_phandle(fdt, phandle);
+
+	/*
+	* If we haven't found either a target or a
+	* target-path property in a node that contains a
+	* __overlay__ subnode (we wouldn't be called
+	* otherwise), consider it a improperly written
+	* overlay
+	*/
+	if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
+		ret = -FDT_ERR_BADOVERLAY;
+
+	/* return on error */
+	if (ret < 0)
+		return ret;
+
+	/* return pointer to path (if available) */
+	if (pathp)
+		*pathp = path ? path : NULL;
+
+	return ret;
+}
+
+/**
+ * overlay_phandle_add_offset - Increases a phandle by an offset
+ * @fdt: Base device tree blob
+ * @node: Device tree overlay blob
+ * @name: Name of the property to modify (phandle or linux,phandle)
+ * @delta: offset to apply
+ *
+ * overlay_phandle_add_offset() increments a node phandle by a given
+ * offset.
+ *
+ * returns:
+ *      0 on success.
+ *      Negative error code on error
+ */
+static int overlay_phandle_add_offset(void *fdt, int node,
+				      const char *name, uint32_t delta)
+{
+	const fdt32_t *val;
+	uint32_t adj_val;
+	int len;
+
+	val = fdt_getprop(fdt, node, name, &len);
+	if (!val)
+		return len;
+
+	if (len != sizeof(*val))
+		return -FDT_ERR_BADPHANDLE;
+
+	adj_val = fdt32_to_cpu(*val);
+	if ((adj_val + delta) < adj_val)
+		return -FDT_ERR_NOPHANDLES;
+
+	adj_val += delta;
+	if (adj_val == (uint32_t)-1)
+		return -FDT_ERR_NOPHANDLES;
+
+	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
+}
+
+/**
+ * overlay_adjust_node_phandles - Offsets the phandles of a node
+ * @fdto: Device tree overlay blob
+ * @node: Offset of the node we want to adjust
+ * @delta: Offset to shift the phandles of
+ *
+ * overlay_adjust_node_phandles() adds a constant to all the phandles
+ * of a given node. This is mainly use as part of the overlay
+ * application process, when we want to update all the overlay
+ * phandles to not conflict with the overlays of the base device tree.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_adjust_node_phandles(void *fdto, int node,
+					uint32_t delta)
+{
+	int child;
+	int ret;
+
+	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
+	if (ret && ret != -FDT_ERR_NOTFOUND)
+		return ret;
+
+	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
+	if (ret && ret != -FDT_ERR_NOTFOUND)
+		return ret;
+
+	fdt_for_each_subnode(child, fdto, node) {
+		ret = overlay_adjust_node_phandles(fdto, child, delta);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
+ * @fdto: Device tree overlay blob
+ * @delta: Offset to shift the phandles of
+ *
+ * overlay_adjust_local_phandles() adds a constant to all the
+ * phandles of an overlay. This is mainly use as part of the overlay
+ * application process, when we want to update all the overlay
+ * phandles to not conflict with the overlays of the base device tree.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
+{
+	/*
+	 * Start adjusting the phandles from the overlay root
+	 */
+	return overlay_adjust_node_phandles(fdto, 0, delta);
+}
+
+/**
+ * overlay_update_local_node_references - Adjust the overlay references
+ * @fdto: Device tree overlay blob
+ * @tree_node: Node offset of the node to operate on
+ * @fixup_node: Node offset of the matching local fixups node
+ * @delta: Offset to shift the phandles of
+ *
+ * overlay_update_local_nodes_references() update the phandles
+ * pointing to a node within the device tree overlay by adding a
+ * constant delta.
+ *
+ * This is mainly used as part of a device tree application process,
+ * where you want the device tree overlays phandles to not conflict
+ * with the ones from the base device tree before merging them.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_update_local_node_references(void *fdto,
+						int tree_node,
+						int fixup_node,
+						uint32_t delta)
+{
+	int fixup_prop;
+	int fixup_child;
+	int ret;
+
+	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
+		const fdt32_t *fixup_val;
+		const char *tree_val;
+		const char *name;
+		int fixup_len;
+		int tree_len;
+		int i;
+
+		fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
+						  &name, &fixup_len);
+		if (!fixup_val)
+			return fixup_len;
+
+		if (fixup_len % sizeof(uint32_t))
+			return -FDT_ERR_BADOVERLAY;
+
+		tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
+		if (!tree_val) {
+			if (tree_len == -FDT_ERR_NOTFOUND)
+				return -FDT_ERR_BADOVERLAY;
+
+			return tree_len;
+		}
+
+		for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
+			fdt32_t adj_val;
+			uint32_t poffset;
+
+			poffset = fdt32_to_cpu(fixup_val[i]);
+
+			/*
+			 * phandles to fixup can be unaligned.
+			 *
+			 * Use a memcpy for the architectures that do
+			 * not support unaligned accesses.
+			 */
+			memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
+
+			adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
+
+			ret = fdt_setprop_inplace_namelen_partial(fdto,
+								  tree_node,
+								  name,
+								  strlen(name),
+								  poffset,
+								  &adj_val,
+								  sizeof(adj_val));
+			if (ret == -FDT_ERR_NOSPACE)
+				return -FDT_ERR_BADOVERLAY;
+
+			if (ret)
+				return ret;
+		}
+	}
+
+	fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
+		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
+							    NULL);
+		int tree_child;
+
+		tree_child = fdt_subnode_offset(fdto, tree_node,
+						fixup_child_name);
+		if (tree_child == -FDT_ERR_NOTFOUND)
+			return -FDT_ERR_BADOVERLAY;
+		if (tree_child < 0)
+			return tree_child;
+
+		ret = overlay_update_local_node_references(fdto,
+							   tree_child,
+							   fixup_child,
+							   delta);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * overlay_update_local_references - Adjust the overlay references
+ * @fdto: Device tree overlay blob
+ * @delta: Offset to shift the phandles of
+ *
+ * overlay_update_local_references() update all the phandles pointing
+ * to a node within the device tree overlay by adding a constant
+ * delta to not conflict with the base overlay.
+ *
+ * This is mainly used as part of a device tree application process,
+ * where you want the device tree overlays phandles to not conflict
+ * with the ones from the base device tree before merging them.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_update_local_references(void *fdto, uint32_t delta)
+{
+	int fixups;
+
+	fixups = fdt_path_offset(fdto, "/__local_fixups__");
+	if (fixups < 0) {
+		/* There's no local phandles to adjust, bail out */
+		if (fixups == -FDT_ERR_NOTFOUND)
+			return 0;
+
+		return fixups;
+	}
+
+	/*
+	 * Update our local references from the root of the tree
+	 */
+	return overlay_update_local_node_references(fdto, 0, fixups,
+						    delta);
+}
+
+/**
+ * overlay_fixup_one_phandle - Set an overlay phandle to the base one
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ * @symbols_off: Node offset of the symbols node in the base device tree
+ * @path: Path to a node holding a phandle in the overlay
+ * @path_len: number of path characters to consider
+ * @name: Name of the property holding the phandle reference in the overlay
+ * @name_len: number of name characters to consider
+ * @poffset: Offset within the overlay property where the phandle is stored
+ * @label: Label of the node referenced by the phandle
+ *
+ * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
+ * a node in the base device tree.
+ *
+ * This is part of the device tree overlay application process, when
+ * you want all the phandles in the overlay to point to the actual
+ * base dt nodes.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_fixup_one_phandle(void *fdt, void *fdto,
+				     int symbols_off,
+				     const char *path, uint32_t path_len,
+				     const char *name, uint32_t name_len,
+				     int poffset, const char *label)
+{
+	const char *symbol_path;
+	uint32_t phandle;
+	fdt32_t phandle_prop;
+	int symbol_off, fixup_off;
+	int prop_len;
+
+	if (symbols_off < 0)
+		return symbols_off;
+
+	symbol_path = fdt_getprop(fdt, symbols_off, label,
+				  &prop_len);
+	if (!symbol_path)
+		return prop_len;
+
+	symbol_off = fdt_path_offset(fdt, symbol_path);
+	if (symbol_off < 0)
+		return symbol_off;
+
+	phandle = fdt_get_phandle(fdt, symbol_off);
+	if (!phandle)
+		return -FDT_ERR_NOTFOUND;
+
+	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
+	if (fixup_off == -FDT_ERR_NOTFOUND)
+		return -FDT_ERR_BADOVERLAY;
+	if (fixup_off < 0)
+		return fixup_off;
+
+	phandle_prop = cpu_to_fdt32(phandle);
+	return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
+						   name, name_len, poffset,
+						   &phandle_prop,
+						   sizeof(phandle_prop));
+};
+
+/**
+ * overlay_fixup_phandle - Set an overlay phandle to the base one
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ * @symbols_off: Node offset of the symbols node in the base device tree
+ * @property: Property offset in the overlay holding the list of fixups
+ *
+ * overlay_fixup_phandle() resolves all the overlay phandles pointed
+ * to in a __fixups__ property, and updates them to match the phandles
+ * in use in the base device tree.
+ *
+ * This is part of the device tree overlay application process, when
+ * you want all the phandles in the overlay to point to the actual
+ * base dt nodes.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
+				 int property)
+{
+	const char *value;
+	const char *label;
+	int len;
+
+	value = fdt_getprop_by_offset(fdto, property,
+				      &label, &len);
+	if (!value) {
+		if (len == -FDT_ERR_NOTFOUND)
+			return -FDT_ERR_INTERNAL;
+
+		return len;
+	}
+
+	do {
+		const char *path, *name, *fixup_end;
+		const char *fixup_str = value;
+		uint32_t path_len, name_len;
+		uint32_t fixup_len;
+		char *sep, *endptr;
+		int poffset, ret;
+
+		fixup_end = memchr(value, '\0', len);
+		if (!fixup_end)
+			return -FDT_ERR_BADOVERLAY;
+		fixup_len = fixup_end - fixup_str;
+
+		len -= fixup_len + 1;
+		value += fixup_len + 1;
+
+		path = fixup_str;
+		sep = memchr(fixup_str, ':', fixup_len);
+		if (!sep || *sep != ':')
+			return -FDT_ERR_BADOVERLAY;
+
+		path_len = sep - path;
+		if (path_len == (fixup_len - 1))
+			return -FDT_ERR_BADOVERLAY;
+
+		fixup_len -= path_len + 1;
+		name = sep + 1;
+		sep = memchr(name, ':', fixup_len);
+		if (!sep || *sep != ':')
+			return -FDT_ERR_BADOVERLAY;
+
+		name_len = sep - name;
+		if (!name_len)
+			return -FDT_ERR_BADOVERLAY;
+
+		poffset = strtoul(sep + 1, &endptr, 10);
+		if ((*endptr != '\0') || (endptr <= (sep + 1)))
+			return -FDT_ERR_BADOVERLAY;
+
+		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
+						path, path_len, name, name_len,
+						poffset, label);
+		if (ret)
+			return ret;
+	} while (len > 0);
+
+	return 0;
+}
+
+/**
+ * overlay_fixup_phandles - Resolve the overlay phandles to the base
+ *                          device tree
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ *
+ * overlay_fixup_phandles() resolves all the overlay phandles pointing
+ * to nodes in the base device tree.
+ *
+ * This is one of the steps of the device tree overlay application
+ * process, when you want all the phandles in the overlay to point to
+ * the actual base dt nodes.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_fixup_phandles(void *fdt, void *fdto)
+{
+	int fixups_off, symbols_off;
+	int property;
+
+	/* We can have overlays without any fixups */
+	fixups_off = fdt_path_offset(fdto, "/__fixups__");
+	if (fixups_off == -FDT_ERR_NOTFOUND)
+		return 0; /* nothing to do */
+	if (fixups_off < 0)
+		return fixups_off;
+
+	/* And base DTs without symbols */
+	symbols_off = fdt_path_offset(fdt, "/__symbols__");
+	if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
+		return symbols_off;
+
+	fdt_for_each_property_offset(property, fdto, fixups_off) {
+		int ret;
+
+		ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * overlay_apply_node - Merges a node into the base device tree
+ * @fdt: Base Device Tree blob
+ * @target: Node offset in the base device tree to apply the fragment to
+ * @fdto: Device tree overlay blob
+ * @node: Node offset in the overlay holding the changes to merge
+ *
+ * overlay_apply_node() merges a node into a target base device tree
+ * node pointed.
+ *
+ * This is part of the final step in the device tree overlay
+ * application process, when all the phandles have been adjusted and
+ * resolved and you just have to merge overlay into the base device
+ * tree.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_apply_node(void *fdt, int target,
+			      void *fdto, int node)
+{
+	int property;
+	int subnode;
+
+	fdt_for_each_property_offset(property, fdto, node) {
+		const char *name;
+		const void *prop;
+		int prop_len;
+		int ret;
+
+		prop = fdt_getprop_by_offset(fdto, property, &name,
+					     &prop_len);
+		if (prop_len == -FDT_ERR_NOTFOUND)
+			return -FDT_ERR_INTERNAL;
+		if (prop_len < 0)
+			return prop_len;
+
+		ret = fdt_setprop(fdt, target, name, prop, prop_len);
+		if (ret)
+			return ret;
+	}
+
+	fdt_for_each_subnode(subnode, fdto, node) {
+		const char *name = fdt_get_name(fdto, subnode, NULL);
+		int nnode;
+		int ret;
+
+		nnode = fdt_add_subnode(fdt, target, name);
+		if (nnode == -FDT_ERR_EXISTS) {
+			nnode = fdt_subnode_offset(fdt, target, name);
+			if (nnode == -FDT_ERR_NOTFOUND)
+				return -FDT_ERR_INTERNAL;
+		}
+
+		if (nnode < 0)
+			return nnode;
+
+		ret = overlay_apply_node(fdt, nnode, fdto, subnode);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * overlay_merge - Merge an overlay into its base device tree
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ *
+ * overlay_merge() merges an overlay into its base device tree.
+ *
+ * This is the next to last step in the device tree overlay application
+ * process, when all the phandles have been adjusted and resolved and
+ * you just have to merge overlay into the base device tree.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_merge(void *fdt, void *fdto)
+{
+	int fragment;
+
+	fdt_for_each_subnode(fragment, fdto, 0) {
+		int overlay;
+		int target;
+		int ret;
+
+		/*
+		 * Each fragments will have an __overlay__ node. If
+		 * they don't, it's not supposed to be merged
+		 */
+		overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
+		if (overlay == -FDT_ERR_NOTFOUND)
+			continue;
+
+		if (overlay < 0)
+			return overlay;
+
+		target = overlay_get_target(fdt, fdto, fragment, NULL);
+		if (target < 0)
+			return target;
+
+		ret = overlay_apply_node(fdt, target, fdto, overlay);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int get_path_len(const void *fdt, int nodeoffset)
+{
+	int len = 0, namelen;
+	const char *name;
+
+	FDT_RO_PROBE(fdt);
+
+	for (;;) {
+		name = fdt_get_name(fdt, nodeoffset, &namelen);
+		if (!name)
+			return namelen;
+
+		/* root? we're done */
+		if (namelen == 0)
+			break;
+
+		nodeoffset = fdt_parent_offset(fdt, nodeoffset);
+		if (nodeoffset < 0)
+			return nodeoffset;
+		len += namelen + 1;
+	}
+
+	/* in case of root pretend it's "/" */
+	if (len == 0)
+		len++;
+	return len;
+}
+
+/**
+ * overlay_symbol_update - Update the symbols of base tree after a merge
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ *
+ * overlay_symbol_update() updates the symbols of the base tree with the
+ * symbols of the applied overlay
+ *
+ * This is the last step in the device tree overlay application
+ * process, allowing the reference of overlay symbols by subsequent
+ * overlay operations.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_symbol_update(void *fdt, void *fdto)
+{
+	int root_sym, ov_sym, prop, path_len, fragment, target;
+	int len, frag_name_len, ret, rel_path_len;
+	const char *s, *e;
+	const char *path;
+	const char *name;
+	const char *frag_name;
+	const char *rel_path;
+	const char *target_path;
+	char *buf;
+	void *p;
+
+	ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
+
+	/* if no overlay symbols exist no problem */
+	if (ov_sym < 0)
+		return 0;
+
+	root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
+
+	/* it no root symbols exist we should create them */
+	if (root_sym == -FDT_ERR_NOTFOUND)
+		root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
+
+	/* any error is fatal now */
+	if (root_sym < 0)
+		return root_sym;
+
+	/* iterate over each overlay symbol */
+	fdt_for_each_property_offset(prop, fdto, ov_sym) {
+		path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
+		if (!path)
+			return path_len;
+
+		/* verify it's a string property (terminated by a single \0) */
+		if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
+			return -FDT_ERR_BADVALUE;
+
+		/* keep end marker to avoid strlen() */
+		e = path + path_len;
+
+		/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
+
+		if (*path != '/')
+			return -FDT_ERR_BADVALUE;
+
+		/* get fragment name first */
+		s = strchr(path + 1, '/');
+		if (!s)
+			return -FDT_ERR_BADOVERLAY;
+
+		frag_name = path + 1;
+		frag_name_len = s - path - 1;
+
+		/* verify format; safe since "s" lies in \0 terminated prop */
+		len = sizeof("/__overlay__/") - 1;
+		if ((e - s) < len || memcmp(s, "/__overlay__/", len))
+			return -FDT_ERR_BADOVERLAY;
+
+		rel_path = s + len;
+		rel_path_len = e - rel_path;
+
+		/* find the fragment index in which the symbol lies */
+		ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
+					       frag_name_len);
+		/* not found? */
+		if (ret < 0)
+			return -FDT_ERR_BADOVERLAY;
+		fragment = ret;
+
+		/* an __overlay__ subnode must exist */
+		ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
+		if (ret < 0)
+			return -FDT_ERR_BADOVERLAY;
+
+		/* get the target of the fragment */
+		ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+		if (ret < 0)
+			return ret;
+		target = ret;
+
+		/* if we have a target path use */
+		if (!target_path) {
+			ret = get_path_len(fdt, target);
+			if (ret < 0)
+				return ret;
+			len = ret;
+		} else {
+			len = strlen(target_path);
+		}
+
+		ret = fdt_setprop_placeholder(fdt, root_sym, name,
+				len + (len > 1) + rel_path_len + 1, &p);
+		if (ret < 0)
+			return ret;
+
+		if (!target_path) {
+			/* again in case setprop_placeholder changed it */
+			ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+			if (ret < 0)
+				return ret;
+			target = ret;
+		}
+
+		buf = p;
+		if (len > 1) { /* target is not root */
+			if (!target_path) {
+				ret = fdt_get_path(fdt, target, buf, len + 1);
+				if (ret < 0)
+					return ret;
+			} else
+				memcpy(buf, target_path, len + 1);
+
+		} else
+			len--;
+
+		buf[len] = '/';
+		memcpy(buf + len + 1, rel_path, rel_path_len);
+		buf[len + 1 + rel_path_len] = '\0';
+	}
+
+	return 0;
+}
+
+int fdt_overlay_apply(void *fdt, void *fdto)
+{
+	uint32_t delta = fdt_get_max_phandle(fdt);
+	int ret;
+
+	FDT_RO_PROBE(fdt);
+	FDT_RO_PROBE(fdto);
+
+	ret = overlay_adjust_local_phandles(fdto, delta);
+	if (ret)
+		goto err;
+
+	ret = overlay_update_local_references(fdto, delta);
+	if (ret)
+		goto err;
+
+	ret = overlay_fixup_phandles(fdt, fdto);
+	if (ret)
+		goto err;
+
+	ret = overlay_merge(fdt, fdto);
+	if (ret)
+		goto err;
+
+	ret = overlay_symbol_update(fdt, fdto);
+	if (ret)
+		goto err;
+
+	/*
+	 * The overlay has been damaged, erase its magic.
+	 */
+	fdt_set_magic(fdto, ~0);
+
+	return 0;
+
+err:
+	/*
+	 * The overlay might have been damaged, erase its magic.
+	 */
+	fdt_set_magic(fdto, ~0);
+
+	/*
+	 * The base device tree might have been damaged, erase its
+	 * magic.
+	 */
+	fdt_set_magic(fdt, ~0);
+
+	return ret;
+}
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 0459098..eafc142 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -55,12 +55,13 @@
 
 #include "libfdt_internal.h"
 
-static int _fdt_nodename_eq(const void *fdt, int offset,
+static int fdt_nodename_eq_(const void *fdt, int offset,
 			    const char *s, int len)
 {
-	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+	int olen;
+	const char *p = fdt_get_name(fdt, offset, &olen);
 
-	if (! p)
+	if (!p || olen < len)
 		/* short match */
 		return 0;
 
@@ -75,17 +76,72 @@
 		return 0;
 }
 
-const char *fdt_string(const void *fdt, int stroffset)
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
 {
-	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+	uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt);
+	size_t len;
+	int err;
+	const char *s, *n;
+
+	err = fdt_ro_probe_(fdt);
+	if (err != 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	if (absoffset >= fdt_totalsize(fdt))
+		goto fail;
+	len = fdt_totalsize(fdt) - absoffset;
+
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		if (stroffset < 0)
+			goto fail;
+		if (fdt_version(fdt) >= 17) {
+			if (stroffset >= fdt_size_dt_strings(fdt))
+				goto fail;
+			if ((fdt_size_dt_strings(fdt) - stroffset) < len)
+				len = fdt_size_dt_strings(fdt) - stroffset;
+		}
+	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+		if ((stroffset >= 0)
+		    || (stroffset < -fdt_size_dt_strings(fdt)))
+			goto fail;
+		if ((-stroffset) < len)
+			len = -stroffset;
+	} else {
+		err = -FDT_ERR_INTERNAL;
+		goto fail;
+	}
+
+	s = (const char *)fdt + absoffset;
+	n = memchr(s, '\0', len);
+	if (!n) {
+		/* missing terminating NULL */
+		err = -FDT_ERR_TRUNCATED;
+		goto fail;
+	}
+
+	if (lenp)
+		*lenp = n - s;
+	return s;
+
+fail:
+	if (lenp)
+		*lenp = err;
+	return NULL;
 }
 
-static int _fdt_string_eq(const void *fdt, int stroffset,
+const char *fdt_string(const void *fdt, int stroffset)
+{
+	return fdt_get_string(fdt, stroffset, NULL);
+}
+
+static int fdt_string_eq_(const void *fdt, int stroffset,
 			  const char *s, int len)
 {
-	const char *p = fdt_string(fdt, stroffset);
+	int slen;
+	const char *p = fdt_get_string(fdt, stroffset, &slen);
 
-	return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+	return p && (slen == len) && (memcmp(p, s, len) == 0);
 }
 
 uint32_t fdt_get_max_phandle(const void *fdt)
@@ -114,24 +170,45 @@
 	return 0;
 }
 
+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
+{
+	int offset = n * sizeof(struct fdt_reserve_entry);
+	int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+
+	if (absoffset < fdt_off_mem_rsvmap(fdt))
+		return NULL;
+	if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry))
+		return NULL;
+	return fdt_mem_rsv_(fdt, n);
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
-	FDT_CHECK_HEADER(fdt);
-	*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
-	*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+	const struct fdt_reserve_entry *re;
+
+	FDT_RO_PROBE(fdt);
+	re = fdt_mem_rsv(fdt, n);
+	if (!re)
+		return -FDT_ERR_BADOFFSET;
+
+	*address = fdt64_ld(&re->address);
+	*size = fdt64_ld(&re->size);
 	return 0;
 }
 
 int fdt_num_mem_rsv(const void *fdt)
 {
-	int i = 0;
+	int i;
+	const struct fdt_reserve_entry *re;
 
-	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
-		i++;
-	return i;
+	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+		if (fdt64_ld(&re->size) == 0)
+			return i;
+	}
+	return -FDT_ERR_TRUNCATED;
 }
 
-static int _nextprop(const void *fdt, int offset)
+static int nextprop_(const void *fdt, int offset)
 {
 	uint32_t tag;
 	int nextoffset;
@@ -160,13 +237,13 @@
 {
 	int depth;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	for (depth = 0;
 	     (offset >= 0) && (depth >= 0);
 	     offset = fdt_next_node(fdt, offset, &depth))
 		if ((depth == 1)
-		    && _fdt_nodename_eq(fdt, offset, name, namelen))
+		    && fdt_nodename_eq_(fdt, offset, name, namelen))
 			return offset;
 
 	if (depth < 0)
@@ -186,7 +263,7 @@
 	const char *p = path;
 	int offset = 0;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* see if we have an alias */
 	if (*path != '/') {
@@ -232,17 +309,35 @@
 
 const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
 {
-	const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
+	const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
+	const char *nameptr;
 	int err;
 
-	if (((err = fdt_check_header(fdt)) != 0)
-	    || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+	if (((err = fdt_ro_probe_(fdt)) != 0)
+	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
 			goto fail;
 
-	if (len)
-		*len = strlen(nh->name);
+	nameptr = nh->name;
 
-	return nh->name;
+	if (fdt_version(fdt) < 0x10) {
+		/*
+		 * For old FDT versions, match the naming conventions of V16:
+		 * give only the leaf name (after all /). The actual tree
+		 * contents are loosely checked.
+		 */
+		const char *leaf;
+		leaf = strrchr(nameptr, '/');
+		if (leaf == NULL) {
+			err = -FDT_ERR_BADSTRUCTURE;
+			goto fail;
+		}
+		nameptr = leaf+1;
+	}
+
+	if (len)
+		*len = strlen(nameptr);
+
+	return nameptr;
 
  fail:
 	if (len)
@@ -254,58 +349,79 @@
 {
 	int offset;
 
-	if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+	if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
 		return offset;
 
-	return _nextprop(fdt, offset);
+	return nextprop_(fdt, offset);
 }
 
 int fdt_next_property_offset(const void *fdt, int offset)
 {
-	if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+	if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
 		return offset;
 
-	return _nextprop(fdt, offset);
+	return nextprop_(fdt, offset);
+}
+
+static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
+						              int offset,
+						              int *lenp)
+{
+	int err;
+	const struct fdt_property *prop;
+
+	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
+		if (lenp)
+			*lenp = err;
+		return NULL;
+	}
+
+	prop = fdt_offset_ptr_(fdt, offset);
+
+	if (lenp)
+		*lenp = fdt32_ld(&prop->len);
+
+	return prop;
 }
 
 const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
 						      int offset,
 						      int *lenp)
 {
-	int err;
-	const struct fdt_property *prop;
+	/* Prior to version 16, properties may need realignment
+	 * and this API does not work. fdt_getprop_*() will, however. */
 
-	if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+	if (fdt_version(fdt) < 0x10) {
 		if (lenp)
-			*lenp = err;
+			*lenp = -FDT_ERR_BADVERSION;
 		return NULL;
 	}
 
-	prop = _fdt_offset_ptr(fdt, offset);
-
-	if (lenp)
-		*lenp = fdt32_to_cpu(prop->len);
-
-	return prop;
+	return fdt_get_property_by_offset_(fdt, offset, lenp);
 }
 
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
-						    int offset,
-						    const char *name,
-						    int namelen, int *lenp)
+static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
+						            int offset,
+						            const char *name,
+						            int namelen,
+							    int *lenp,
+							    int *poffset)
 {
 	for (offset = fdt_first_property_offset(fdt, offset);
 	     (offset >= 0);
 	     (offset = fdt_next_property_offset(fdt, offset))) {
 		const struct fdt_property *prop;
 
-		if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+		if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
 			offset = -FDT_ERR_INTERNAL;
 			break;
 		}
-		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
-				   name, namelen))
+		if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
+				   name, namelen)) {
+			if (poffset)
+				*poffset = offset;
 			return prop;
+		}
 	}
 
 	if (lenp)
@@ -313,6 +429,25 @@
 	return NULL;
 }
 
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+						    int offset,
+						    const char *name,
+						    int namelen, int *lenp)
+{
+	/* Prior to version 16, properties may need realignment
+	 * and this API does not work. fdt_getprop_*() will, however. */
+	if (fdt_version(fdt) < 0x10) {
+		if (lenp)
+			*lenp = -FDT_ERR_BADVERSION;
+		return NULL;
+	}
+
+	return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
+					 NULL);
+}
+
+
 const struct fdt_property *fdt_get_property(const void *fdt,
 					    int nodeoffset,
 					    const char *name, int *lenp)
@@ -324,12 +459,18 @@
 const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
 				const char *name, int namelen, int *lenp)
 {
+	int poffset;
 	const struct fdt_property *prop;
 
-	prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
-	if (! prop)
+	prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
+					 &poffset);
+	if (!prop)
 		return NULL;
 
+	/* Handle realignment */
+	if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
+	    fdt32_ld(&prop->len) >= 8)
+		return prop->data + 4;
 	return prop->data;
 }
 
@@ -338,11 +479,26 @@
 {
 	const struct fdt_property *prop;
 
-	prop = fdt_get_property_by_offset(fdt, offset, lenp);
+	prop = fdt_get_property_by_offset_(fdt, offset, lenp);
 	if (!prop)
 		return NULL;
-	if (namep)
-		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+	if (namep) {
+		const char *name;
+		int namelen;
+		name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+				      &namelen);
+		if (!name) {
+			if (lenp)
+				*lenp = namelen;
+			return NULL;
+		}
+		*namep = name;
+	}
+
+	/* Handle realignment */
+	if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
+	    fdt32_ld(&prop->len) >= 8)
+		return prop->data + 4;
 	return prop->data;
 }
 
@@ -366,7 +522,7 @@
 			return 0;
 	}
 
-	return fdt32_to_cpu(*php);
+	return fdt32_ld(php);
 }
 
 const char *fdt_get_alias_namelen(const void *fdt,
@@ -392,7 +548,7 @@
 	int offset, depth, namelen;
 	const char *name;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (buflen < 2)
 		return -FDT_ERR_NOSPACE;
@@ -444,7 +600,7 @@
 	int offset, depth;
 	int supernodeoffset = -FDT_ERR_INTERNAL;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (supernodedepth < 0)
 		return -FDT_ERR_NOTFOUND;
@@ -503,7 +659,7 @@
 	const void *val;
 	int len;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_getprop(), then if that didn't
@@ -529,7 +685,7 @@
 	if ((phandle == 0) || (phandle == -1))
 		return -FDT_ERR_BADPHANDLE;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we
 	 * potentially scan each property of a node in
@@ -571,7 +727,7 @@
 
 	list = fdt_getprop(fdt, nodeoffset, property, &length);
 	if (!list)
-		return -length;
+		return length;
 
 	end = list + length;
 
@@ -597,7 +753,7 @@
 
 	list = fdt_getprop(fdt, nodeoffset, property, &length);
 	if (!list)
-		return -length;
+		return length;
 
 	len = strlen(string) + 1;
 	end = list + length;
@@ -682,7 +838,7 @@
 {
 	int offset, err;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_node_check_compatible(), then if
@@ -701,3 +857,66 @@
 
 	return offset; /* error from fdt_next_node() */
 }
+
+int fdt_check_full(const void *fdt, size_t bufsize)
+{
+	int err;
+	int num_memrsv;
+	int offset, nextoffset = 0;
+	uint32_t tag;
+	unsigned depth = 0;
+	const void *prop;
+	const char *propname;
+
+	if (bufsize < FDT_V1_SIZE)
+		return -FDT_ERR_TRUNCATED;
+	err = fdt_check_header(fdt);
+	if (err != 0)
+		return err;
+	if (bufsize < fdt_totalsize(fdt))
+		return -FDT_ERR_TRUNCATED;
+
+	num_memrsv = fdt_num_mem_rsv(fdt);
+	if (num_memrsv < 0)
+		return num_memrsv;
+
+	while (1) {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		if (nextoffset < 0)
+			return nextoffset;
+
+		switch (tag) {
+		case FDT_NOP:
+			break;
+
+		case FDT_END:
+			if (depth != 0)
+				return -FDT_ERR_BADSTRUCTURE;
+			return 0;
+
+		case FDT_BEGIN_NODE:
+			depth++;
+			if (depth > INT_MAX)
+				return -FDT_ERR_BADSTRUCTURE;
+			break;
+
+		case FDT_END_NODE:
+			if (depth == 0)
+				return -FDT_ERR_BADSTRUCTURE;
+			depth--;
+			break;
+
+		case FDT_PROP:
+			prop = fdt_getprop_by_offset(fdt, offset, &propname,
+						     &err);
+			if (!prop)
+				return err;
+			break;
+
+		default:
+			return -FDT_ERR_INTERNAL;
+		}
+	}
+}
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 2eed4f5..2e49855 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -55,8 +55,8 @@
 
 #include "libfdt_internal.h"
 
-static int _fdt_blocks_misordered(const void *fdt,
-			      int mem_rsv_size, int struct_size)
+static int fdt_blocks_misordered_(const void *fdt,
+				  int mem_rsv_size, int struct_size)
 {
 	return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
 		|| (fdt_off_dt_struct(fdt) <
@@ -67,13 +67,13 @@
 		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
 }
 
-static int _fdt_rw_check_header(void *fdt)
+static int fdt_rw_probe_(void *fdt)
 {
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (fdt_version(fdt) < 17)
 		return -FDT_ERR_BADVERSION;
-	if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+	if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
 				   fdt_size_dt_struct(fdt)))
 		return -FDT_ERR_BADLAYOUT;
 	if (fdt_version(fdt) > 17)
@@ -82,22 +82,22 @@
 	return 0;
 }
 
-#define FDT_RW_CHECK_HEADER(fdt) \
+#define FDT_RW_PROBE(fdt) \
 	{ \
-		int __err; \
-		if ((__err = _fdt_rw_check_header(fdt)) != 0) \
-			return __err; \
+		int err_; \
+		if ((err_ = fdt_rw_probe_(fdt)) != 0) \
+			return err_; \
 	}
 
-static inline int _fdt_data_size(void *fdt)
+static inline int fdt_data_size_(void *fdt)
 {
 	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
 }
 
-static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
+static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
 {
 	char *p = splicepoint;
-	char *end = (char *)fdt + _fdt_data_size(fdt);
+	char *end = (char *)fdt + fdt_data_size_(fdt);
 
 	if (((p + oldlen) < p) || ((p + oldlen) > end))
 		return -FDT_ERR_BADOFFSET;
@@ -109,12 +109,12 @@
 	return 0;
 }
 
-static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
 			       int oldn, int newn)
 {
 	int delta = (newn - oldn) * sizeof(*p);
 	int err;
-	err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+	err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
 	if (err)
 		return err;
 	fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
@@ -122,13 +122,13 @@
 	return 0;
 }
 
-static int _fdt_splice_struct(void *fdt, void *p,
+static int fdt_splice_struct_(void *fdt, void *p,
 			      int oldlen, int newlen)
 {
 	int delta = newlen - oldlen;
 	int err;
 
-	if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
+	if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
 		return err;
 
 	fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
@@ -136,20 +136,20 @@
 	return 0;
 }
 
-static int _fdt_splice_string(void *fdt, int newlen)
+static int fdt_splice_string_(void *fdt, int newlen)
 {
 	void *p = (char *)fdt
 		+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
 	int err;
 
-	if ((err = _fdt_splice(fdt, p, 0, newlen)))
+	if ((err = fdt_splice_(fdt, p, 0, newlen)))
 		return err;
 
 	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
 	return 0;
 }
 
-static int _fdt_find_add_string(void *fdt, const char *s)
+static int fdt_find_add_string_(void *fdt, const char *s)
 {
 	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
 	const char *p;
@@ -157,13 +157,13 @@
 	int len = strlen(s) + 1;
 	int err;
 
-	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+	p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
 	if (p)
 		/* found it */
 		return (p - strtab);
 
 	new = strtab + fdt_size_dt_strings(fdt);
-	err = _fdt_splice_string(fdt, len);
+	err = fdt_splice_string_(fdt, len);
 	if (err)
 		return err;
 
@@ -176,10 +176,10 @@
 	struct fdt_reserve_entry *re;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
-	re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
-	err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
+	re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
+	err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
 	if (err)
 		return err;
 
@@ -190,27 +190,27 @@
 
 int fdt_del_mem_rsv(void *fdt, int n)
 {
-	struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+	struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	if (n >= fdt_num_mem_rsv(fdt))
 		return -FDT_ERR_NOTFOUND;
 
-	return _fdt_splice_mem_rsv(fdt, re, 1, 0);
+	return fdt_splice_mem_rsv_(fdt, re, 1, 0);
 }
 
-static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
+static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
 				int len, struct fdt_property **prop)
 {
 	int oldlen;
 	int err;
 
 	*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
-	if (! (*prop))
+	if (!*prop)
 		return oldlen;
 
-	if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+	if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
 				      FDT_TAGALIGN(len))))
 		return err;
 
@@ -218,7 +218,7 @@
 	return 0;
 }
 
-static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
+static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
 			     int len, struct fdt_property **prop)
 {
 	int proplen;
@@ -226,17 +226,17 @@
 	int namestroff;
 	int err;
 
-	if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+	if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
 		return nextoffset;
 
-	namestroff = _fdt_find_add_string(fdt, name);
+	namestroff = fdt_find_add_string_(fdt, name);
 	if (namestroff < 0)
 		return namestroff;
 
-	*prop = _fdt_offset_ptr_w(fdt, nextoffset);
+	*prop = fdt_offset_ptr_w_(fdt, nextoffset);
 	proplen = sizeof(**prop) + FDT_TAGALIGN(len);
 
-	err = _fdt_splice_struct(fdt, *prop, 0, proplen);
+	err = fdt_splice_struct_(fdt, *prop, 0, proplen);
 	if (err)
 		return err;
 
@@ -252,7 +252,7 @@
 	int oldlen, newlen;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
 	if (!namep)
@@ -260,7 +260,7 @@
 
 	newlen = strlen(name);
 
-	err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
+	err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),
 				 FDT_TAGALIGN(newlen+1));
 	if (err)
 		return err;
@@ -269,21 +269,36 @@
 	return 0;
 }
 
-int fdt_setprop(void *fdt, int nodeoffset, const char *name,
-		const void *val, int len)
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
+			    int len, void **prop_data)
 {
 	struct fdt_property *prop;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
-	err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
+	err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
 	if (err == -FDT_ERR_NOTFOUND)
-		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+		err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
 	if (err)
 		return err;
 
-	memcpy(prop->data, val, len);
+	*prop_data = prop->data;
+	return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len)
+{
+	void *prop_data;
+	int err;
+
+	err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
+	if (err)
+		return err;
+
+	if (len)
+		memcpy(prop_data, val, len);
 	return 0;
 }
 
@@ -293,12 +308,12 @@
 	struct fdt_property *prop;
 	int err, oldlen, newlen;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
 	if (prop) {
 		newlen = len + oldlen;
-		err = _fdt_splice_struct(fdt, prop->data,
+		err = fdt_splice_struct_(fdt, prop->data,
 					 FDT_TAGALIGN(oldlen),
 					 FDT_TAGALIGN(newlen));
 		if (err)
@@ -306,7 +321,7 @@
 		prop->len = cpu_to_fdt32(newlen);
 		memcpy(prop->data + oldlen, val, len);
 	} else {
-		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+		err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
 		if (err)
 			return err;
 		memcpy(prop->data, val, len);
@@ -319,14 +334,14 @@
 	struct fdt_property *prop;
 	int len, proplen;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
-	if (! prop)
+	if (!prop)
 		return len;
 
 	proplen = sizeof(*prop) + FDT_TAGALIGN(len);
-	return _fdt_splice_struct(fdt, prop, proplen, 0);
+	return fdt_splice_struct_(fdt, prop, proplen, 0);
 }
 
 int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@@ -339,7 +354,7 @@
 	uint32_t tag;
 	fdt32_t *endtag;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
 	if (offset >= 0)
@@ -354,10 +369,10 @@
 		tag = fdt_next_tag(fdt, offset, &nextoffset);
 	} while ((tag == FDT_PROP) || (tag == FDT_NOP));
 
-	nh = _fdt_offset_ptr_w(fdt, offset);
+	nh = fdt_offset_ptr_w_(fdt, offset);
 	nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
 
-	err = _fdt_splice_struct(fdt, nh, 0, nodelen);
+	err = fdt_splice_struct_(fdt, nh, 0, nodelen);
 	if (err)
 		return err;
 
@@ -379,17 +394,17 @@
 {
 	int endoffset;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
-	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	endoffset = fdt_node_end_offset_(fdt, nodeoffset);
 	if (endoffset < 0)
 		return endoffset;
 
-	return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+	return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),
 				  endoffset - nodeoffset, 0);
 }
 
-static void _fdt_packblocks(const char *old, char *new,
+static void fdt_packblocks_(const char *old, char *new,
 			    int mem_rsv_size, int struct_size)
 {
 	int mem_rsv_off, struct_off, strings_off;
@@ -420,7 +435,7 @@
 	const char *fdtend = fdtstart + fdt_totalsize(fdt);
 	char *tmp;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 		* sizeof(struct fdt_reserve_entry);
@@ -435,7 +450,7 @@
 			return struct_size;
 	}
 
-	if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+	if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
 		/* no further work necessary */
 		err = fdt_move(fdt, buf, bufsize);
 		if (err)
@@ -463,7 +478,7 @@
 			return -FDT_ERR_NOSPACE;
 	}
 
-	_fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
+	fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
 	memmove(buf, tmp, newsize);
 
 	fdt_set_magic(buf, FDT_MAGIC);
@@ -479,12 +494,12 @@
 {
 	int mem_rsv_size;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 		* sizeof(struct fdt_reserve_entry);
-	_fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
-	fdt_set_totalsize(fdt, _fdt_data_size(fdt));
+	fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+	fdt_set_totalsize(fdt, fdt_data_size_(fdt));
 
 	return 0;
 }
diff --git a/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c
index e6c3cee..9677a18 100644
--- a/lib/libfdt/fdt_strerror.c
+++ b/lib/libfdt/fdt_strerror.c
@@ -69,6 +69,7 @@
 
 	FDT_ERRTABENT(FDT_ERR_BADOFFSET),
 	FDT_ERRTABENT(FDT_ERR_BADPATH),
+	FDT_ERRTABENT(FDT_ERR_BADPHANDLE),
 	FDT_ERRTABENT(FDT_ERR_BADSTATE),
 
 	FDT_ERRTABENT(FDT_ERR_TRUNCATED),
@@ -76,6 +77,11 @@
 	FDT_ERRTABENT(FDT_ERR_BADVERSION),
 	FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
 	FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
+	FDT_ERRTABENT(FDT_ERR_INTERNAL),
+	FDT_ERRTABENT(FDT_ERR_BADNCELLS),
+	FDT_ERRTABENT(FDT_ERR_BADVALUE),
+	FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
+	FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
 };
 #define FDT_ERRTABSIZE	(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
 
diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c
index 6a80485..9fa4a94 100644
--- a/lib/libfdt/fdt_sw.c
+++ b/lib/libfdt/fdt_sw.c
@@ -55,22 +55,78 @@
 
 #include "libfdt_internal.h"
 
-static int _fdt_sw_check_header(void *fdt)
+static int fdt_sw_probe_(void *fdt)
 {
-	if (fdt_magic(fdt) != FDT_SW_MAGIC)
+	if (fdt_magic(fdt) == FDT_MAGIC)
+		return -FDT_ERR_BADSTATE;
+	else if (fdt_magic(fdt) != FDT_SW_MAGIC)
 		return -FDT_ERR_BADMAGIC;
-	/* FIXME: should check more details about the header state */
 	return 0;
 }
 
-#define FDT_SW_CHECK_HEADER(fdt) \
+#define FDT_SW_PROBE(fdt) \
 	{ \
 		int err; \
-		if ((err = _fdt_sw_check_header(fdt)) != 0) \
+		if ((err = fdt_sw_probe_(fdt)) != 0) \
 			return err; \
 	}
 
-static void *_fdt_grab_space(void *fdt, size_t len)
+/* 'memrsv' state:	Initial state after fdt_create()
+ *
+ * Allowed functions:
+ *	fdt_add_reservmap_entry()
+ *	fdt_finish_reservemap()		[moves to 'struct' state]
+ */
+static int fdt_sw_probe_memrsv_(void *fdt)
+{
+	int err = fdt_sw_probe_(fdt);
+	if (err)
+		return err;
+
+	if (fdt_off_dt_strings(fdt) != 0)
+		return -FDT_ERR_BADSTATE;
+	return 0;
+}
+
+#define FDT_SW_PROBE_MEMRSV(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
+			return err; \
+	}
+
+/* 'struct' state:	Enter this state after fdt_finish_reservemap()
+ *
+ * Allowed functions:
+ *	fdt_begin_node()
+ *	fdt_end_node()
+ *	fdt_property*()
+ *	fdt_finish()			[moves to 'complete' state]
+ */
+static int fdt_sw_probe_struct_(void *fdt)
+{
+	int err = fdt_sw_probe_(fdt);
+	if (err)
+		return err;
+
+	if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
+		return -FDT_ERR_BADSTATE;
+	return 0;
+}
+
+#define FDT_SW_PROBE_STRUCT(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
+			return err; \
+	}
+
+/* 'complete' state:	Enter this state after fdt_finish()
+ *
+ * Allowed functions: none
+ */
+
+static void *fdt_grab_space_(void *fdt, size_t len)
 {
 	int offset = fdt_size_dt_struct(fdt);
 	int spaceleft;
@@ -82,14 +138,16 @@
 		return NULL;
 
 	fdt_set_size_dt_struct(fdt, offset + len);
-	return _fdt_offset_ptr_w(fdt, offset);
+	return fdt_offset_ptr_w_(fdt, offset);
 }
 
 int fdt_create(void *buf, int bufsize)
 {
+	const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
+					 sizeof(struct fdt_reserve_entry));
 	void *fdt = buf;
 
-	if (bufsize < sizeof(struct fdt_header))
+	if (bufsize < hdrsize)
 		return -FDT_ERR_NOSPACE;
 
 	memset(buf, 0, bufsize);
@@ -99,10 +157,9 @@
 	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
 	fdt_set_totalsize(fdt,  bufsize);
 
-	fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
-					      sizeof(struct fdt_reserve_entry)));
+	fdt_set_off_mem_rsvmap(fdt, hdrsize);
 	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
-	fdt_set_off_dt_strings(fdt, bufsize);
+	fdt_set_off_dt_strings(fdt, 0);
 
 	return 0;
 }
@@ -112,11 +169,14 @@
 	size_t headsize, tailsize;
 	char *oldtail, *newtail;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE(fdt);
 
-	headsize = fdt_off_dt_struct(fdt);
+	headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 	tailsize = fdt_size_dt_strings(fdt);
 
+	if ((headsize + tailsize) > fdt_totalsize(fdt))
+		return -FDT_ERR_INTERNAL;
+
 	if ((headsize + tailsize) > bufsize)
 		return -FDT_ERR_NOSPACE;
 
@@ -133,8 +193,9 @@
 		memmove(buf, fdt, headsize);
 	}
 
-	fdt_set_off_dt_strings(buf, bufsize);
 	fdt_set_totalsize(buf, bufsize);
+	if (fdt_off_dt_strings(buf))
+		fdt_set_off_dt_strings(buf, bufsize);
 
 	return 0;
 }
@@ -144,10 +205,7 @@
 	struct fdt_reserve_entry *re;
 	int offset;
 
-	FDT_SW_CHECK_HEADER(fdt);
-
-	if (fdt_size_dt_struct(fdt))
-		return -FDT_ERR_BADSTATE;
+	FDT_SW_PROBE_MEMRSV(fdt);
 
 	offset = fdt_off_dt_struct(fdt);
 	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@@ -164,17 +222,24 @@
 
 int fdt_finish_reservemap(void *fdt)
 {
-	return fdt_add_reservemap_entry(fdt, 0, 0);
+	int err = fdt_add_reservemap_entry(fdt, 0, 0);
+
+	if (err)
+		return err;
+
+	fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
+	return 0;
 }
 
 int fdt_begin_node(void *fdt, const char *name)
 {
 	struct fdt_node_header *nh;
-	int namelen = strlen(name) + 1;
+	int namelen;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
-	nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
+	namelen = strlen(name) + 1;
+	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
 	if (! nh)
 		return -FDT_ERR_NOSPACE;
 
@@ -187,9 +252,9 @@
 {
 	fdt32_t *en;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
-	en = _fdt_grab_space(fdt, FDT_TAGSIZE);
+	en = fdt_grab_space_(fdt, FDT_TAGSIZE);
 	if (! en)
 		return -FDT_ERR_NOSPACE;
 
@@ -197,7 +262,7 @@
 	return 0;
 }
 
-static int _fdt_find_add_string(void *fdt, const char *s)
+static int fdt_find_add_string_(void *fdt, const char *s)
 {
 	char *strtab = (char *)fdt + fdt_totalsize(fdt);
 	const char *p;
@@ -205,7 +270,7 @@
 	int len = strlen(s) + 1;
 	int struct_top, offset;
 
-	p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
 	if (p)
 		return p - strtab;
 
@@ -220,25 +285,37 @@
 	return offset;
 }
 
-int fdt_property(void *fdt, const char *name, const void *val, int len)
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
 {
 	struct fdt_property *prop;
 	int nameoff;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
-	nameoff = _fdt_find_add_string(fdt, name);
+	nameoff = fdt_find_add_string_(fdt, name);
 	if (nameoff == 0)
 		return -FDT_ERR_NOSPACE;
 
-	prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
+	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
 	if (! prop)
 		return -FDT_ERR_NOSPACE;
 
 	prop->tag = cpu_to_fdt32(FDT_PROP);
 	prop->nameoff = cpu_to_fdt32(nameoff);
 	prop->len = cpu_to_fdt32(len);
-	memcpy(prop->data, val, len);
+	*valp = prop->data;
+	return 0;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+	void *ptr;
+	int ret;
+
+	ret = fdt_property_placeholder(fdt, name, len, &ptr);
+	if (ret)
+		return ret;
+	memcpy(ptr, val, len);
 	return 0;
 }
 
@@ -250,10 +327,10 @@
 	uint32_t tag;
 	int offset, nextoffset;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
 	/* Add terminator */
-	end = _fdt_grab_space(fdt, sizeof(*end));
+	end = fdt_grab_space_(fdt, sizeof(*end));
 	if (! end)
 		return -FDT_ERR_NOSPACE;
 	*end = cpu_to_fdt32(FDT_END);
@@ -269,7 +346,7 @@
 	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
 		if (tag == FDT_PROP) {
 			struct fdt_property *prop =
-				_fdt_offset_ptr_w(fdt, offset);
+				fdt_offset_ptr_w_(fdt, offset);
 			int nameoff;
 
 			nameoff = fdt32_to_cpu(prop->nameoff);
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 6aaab39..534c1cb 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -82,7 +82,7 @@
 	int proplen;
 
 	propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
-	if (! propval)
+	if (!propval)
 		return proplen;
 
 	if (proplen != len)
@@ -93,7 +93,7 @@
 						   val, len);
 }
 
-static void _fdt_nop_region(void *start, int len)
+static void fdt_nop_region_(void *start, int len)
 {
 	fdt32_t *p;
 
@@ -107,15 +107,15 @@
 	int len;
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
-	if (! prop)
+	if (!prop)
 		return len;
 
-	_fdt_nop_region(prop, len + sizeof(*prop));
+	fdt_nop_region_(prop, len + sizeof(*prop));
 
 	return 0;
 }
 
-int _fdt_node_end_offset(void *fdt, int offset)
+int fdt_node_end_offset_(void *fdt, int offset)
 {
 	int depth = 0;
 
@@ -129,11 +129,11 @@
 {
 	int endoffset;
 
-	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	endoffset = fdt_node_end_offset_(fdt, nodeoffset);
 	if (endoffset < 0)
 		return endoffset;
 
-	_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
+	fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
 			endoffset - nodeoffset);
 	return 0;
 }
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index 02cfa6f..4109f89 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -1,5 +1,5 @@
-#ifndef _LIBFDT_INTERNAL_H
-#define _LIBFDT_INTERNAL_H
+#ifndef LIBFDT_INTERNAL_H
+#define LIBFDT_INTERNAL_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
@@ -55,29 +55,30 @@
 #define FDT_ALIGN(x, a)		(((x) + (a) - 1) & ~((a) - 1))
 #define FDT_TAGALIGN(x)		(FDT_ALIGN((x), FDT_TAGSIZE))
 
-#define FDT_CHECK_HEADER(fdt) \
+int fdt_ro_probe_(const void *fdt);
+#define FDT_RO_PROBE(fdt)			\
 	{ \
-		int __err; \
-		if ((__err = fdt_check_header(fdt)) != 0) \
-			return __err; \
+		int err_; \
+		if ((err_ = fdt_ro_probe_(fdt)) != 0)	\
+			return err_; \
 	}
 
-int _fdt_check_node_offset(const void *fdt, int offset);
-int _fdt_check_prop_offset(const void *fdt, int offset);
-const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
-int _fdt_node_end_offset(void *fdt, int nodeoffset);
+int fdt_check_node_offset_(const void *fdt, int offset);
+int fdt_check_prop_offset_(const void *fdt, int offset);
+const char *fdt_find_string_(const char *strtab, int tabsize, const char *s);
+int fdt_node_end_offset_(void *fdt, int nodeoffset);
 
-static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
 {
 	return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
 }
 
-static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
 {
-	return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
+	return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
 }
 
-static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
 {
 	const struct fdt_reserve_entry *rsv_table =
 		(const struct fdt_reserve_entry *)
@@ -85,11 +86,11 @@
 
 	return rsv_table + n;
 }
-static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
 {
-	return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
+	return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
 }
 
 #define FDT_SW_MAGIC		(~FDT_MAGIC)
 
-#endif /* _LIBFDT_INTERNAL_H */
+#endif /* LIBFDT_INTERNAL_H */
diff --git a/lib/pmf/pmf_main.c b/lib/pmf/pmf_main.c
index a020860..fe7bb74 100644
--- a/lib/pmf/pmf_main.c
+++ b/lib/pmf/pmf_main.c
@@ -25,9 +25,10 @@
 
 IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_START__,		PMF_SVC_DESCS_START);
 IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_END__,		PMF_SVC_DESCS_END);
-IMPORT_SYM(uintptr_t, __PERCPU_TIMESTAMP_SIZE__,	PMF_PERCPU_TIMESTAMP_SIZE);
-IMPORT_SYM(intptr_t,  __PMF_TIMESTAMP_START__,		PMF_TIMESTAMP_ARRAY_START);
-IMPORT_SYM(uintptr_t, __PMF_TIMESTAMP_END__,		PMF_TIMESTAMP_ARRAY_END);
+IMPORT_SYM(uintptr_t, __PMF_PERCPU_TIMESTAMP_END__,	PMF_PERCPU_TIMESTAMP_END);
+IMPORT_SYM(uintptr_t,  __PMF_TIMESTAMP_START__,		PMF_TIMESTAMP_ARRAY_START);
+
+#define PMF_PERCPU_TIMESTAMP_SIZE	(PMF_PERCPU_TIMESTAMP_END - PMF_TIMESTAMP_ARRAY_START)
 
 #define PMF_SVC_DESCS_MAX		10
 
@@ -66,15 +67,15 @@
 	pmf_svc_descs = (pmf_svc_desc_t *) PMF_SVC_DESCS_START;
 	for (ii = 0; ii < pmf_svc_descs_num; ii++) {
 
-		assert(pmf_svc_descs[ii].get_ts);
+		assert(pmf_svc_descs[ii].get_ts != NULL);
 
 		/*
 		 * Call the initialization routine for this
 		 * PMF service, if it is defined.
 		 */
-		if (pmf_svc_descs[ii].init) {
+		if (pmf_svc_descs[ii].init != NULL) {
 			rc = pmf_svc_descs[ii].init();
-			if (rc) {
+			if (rc != 0) {
 				WARN("Could not initialize PMF"
 					"service %s - skipping \n",
 					pmf_svc_descs[ii].name);
@@ -124,7 +125,7 @@
 	if (pmf_num_services == 0)
 		return NULL;
 
-	assert(pmf_svc_descs);
+	assert(pmf_svc_descs != NULL);
 
 	do {
 		mid = (low + high) / 2;
@@ -157,7 +158,7 @@
 		unsigned long long *ts_value)
 {
 	pmf_svc_desc_t *svc_desc;
-	assert(ts_value);
+	assert(ts_value != NULL);
 
 	/* Search for registered service. */
 	svc_desc = get_service(tid);
@@ -246,7 +247,7 @@
 	unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr,
 				tid, cpuid);
 
-	if (flags & PMF_CACHE_MAINT)
+	if ((flags & PMF_CACHE_MAINT) != 0U)
 		inv_dcache_range((uintptr_t)ts_addr, sizeof(unsigned long long));
 
 	return *ts_addr;
diff --git a/lib/pmf/pmf_smc.c b/lib/pmf/pmf_smc.c
index e866118..4c5b14f 100644
--- a/lib/pmf/pmf_smc.c
+++ b/lib/pmf/pmf_smc.c
@@ -37,7 +37,8 @@
 			 * x0 --> error code.
 			 * x1 - x2 --> time-stamp value.
 			 */
-			rc = pmf_get_timestamp_smc(x1, x2, x3, &ts_value);
+			rc = pmf_get_timestamp_smc((unsigned int)x1, x2,
+					(unsigned int)x3, &ts_value);
 			SMC_RET3(handle, rc, (uint32_t)ts_value,
 					(uint32_t)(ts_value >> 32));
 		}
@@ -49,7 +50,8 @@
 			 * x0 --> error code.
 			 * x1 --> time-stamp value.
 			 */
-			rc = pmf_get_timestamp_smc(x1, x2, x3, &ts_value);
+			rc = pmf_get_timestamp_smc((unsigned int)x1, x2,
+					(unsigned int)x3, &ts_value);
 			SMC_RET2(handle, rc, ts_value);
 		}
 	}
diff --git a/lib/romlib/init.s b/lib/romlib/init.s
index 5cf2aca..7d97e4d 100644
--- a/lib/romlib/init.s
+++ b/lib/romlib/init.s
@@ -5,7 +5,7 @@
  */
 
 	.globl	rom_lib_init
-	.extern	__DATA_RAM_START__, __DATA_ROM_START__, __DATA_SIZE__
+	.extern	__DATA_RAM_START__, __DATA_ROM_START__, __DATA_RAM_END__
 	.extern	memset, memcpy
 
 rom_lib_init:
@@ -16,13 +16,19 @@
 
 1:	stp	x29, x30, [sp, #-16]!
 	adrp	x0, __DATA_RAM_START__
-	ldr	x1,= __DATA_ROM_START__
-	ldr	x2, =__DATA_SIZE__
+	adrp	x1, __DATA_ROM_START__
+	add	x1, x1, :lo12:__DATA_ROM_START__
+	adrp	x2, __DATA_RAM_END__
+	add	x2, x2, :lo12:__DATA_RAM_END__
+	sub	x2, x2, x0
 	bl	memcpy
 
-	ldr	x0, =__BSS_START__
+	adrp	x0,__BSS_START__
+	add	x0, x0, :lo12:__BSS_START__
 	mov	x1, #0
-	ldr	x2, =__BSS_SIZE__
+	adrp	x2, __BSS_END__
+	add	x2, x2, :lo12:__BSS_END__
+	sub	x2, x2, x0
 	bl	memset
 	ldp	x29, x30, [sp], #16
 
diff --git a/lib/xlat_tables_v2/aarch64/enable_mmu.S b/lib/xlat_tables_v2/aarch64/enable_mmu.S
index 21717d2..504c03c 100644
--- a/lib/xlat_tables_v2/aarch64/enable_mmu.S
+++ b/lib/xlat_tables_v2/aarch64/enable_mmu.S
@@ -45,7 +45,8 @@
 		tlbi_invalidate_all \el
 
 		mov	x7, x0
-		ldr	x0, =mmu_cfg_params
+		adrp	x0, mmu_cfg_params
+		add	x0, x0, :lo12:mmu_cfg_params
 
 		/* MAIR */
 		ldr	x1, [x0, #(MMU_CFG_MAIR << 3)]
diff --git a/lib/xlat_tables_v2/xlat_tables.mk b/lib/xlat_tables_v2/xlat_tables.mk
index 9507ad7..c946315 100644
--- a/lib/xlat_tables_v2/xlat_tables.mk
+++ b/lib/xlat_tables_v2/xlat_tables.mk
@@ -10,3 +10,6 @@
 				xlat_tables_context.c			\
 				xlat_tables_core.c			\
 				xlat_tables_utils.c)
+
+XLAT_TABLES_LIB_V2	:=	1
+$(eval $(call add_define,XLAT_TABLES_LIB_V2))
diff --git a/maintainers.rst b/maintainers.rst
index 1c88726..3122ecd 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -26,6 +26,14 @@
 :F: plat/allwinner/
 :F: drivers/allwinner/
 
+Amlogic Meson S905 (GXBB) platform port
+---------------------------------------
+:M: Antonio Niño Díaz <antonio.ninodiaz@arm.com>
+:G: `antonio-nino-diaz-arm`_
+:F: docs/plat/meson-gxbb.rst
+:F: drivers/meson/
+:F: plat/meson/gxbb/
+
 Armv7-A architecture port
 -------------------------
 :M: Etienne Carriere <etienne.carriere@linaro.org>
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 435de20..4a3f541 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -64,6 +64,9 @@
 # Build option to enable MPAM for lower ELs
 ENABLE_MPAM_FOR_LOWER_ELS	:= 0
 
+# Flag to Enable Position Independant support (PIE)
+ENABLE_PIE			:= 0
+
 # Flag to enable Performance Measurement Framework
 ENABLE_PMF			:= 0
 
diff --git a/make_helpers/unix.mk b/make_helpers/unix.mk
index 17f8a7c..545ddfd 100644
--- a/make_helpers/unix.mk
+++ b/make_helpers/unix.mk
@@ -1,9 +1,8 @@
 #
-# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
-#
 
 # Trusted Firmware shell command definitions for a Unix style environment.
 
@@ -11,6 +10,7 @@
     UNIX_MK := $(lastword $(MAKEFILE_LIST))
 
     ECHO_BLANK_LINE := echo
+    ECHO_QUIET := @\#
 
     DIR_DELIM := /
     PATH_SEP := :
diff --git a/make_helpers/windows.mk b/make_helpers/windows.mk
index 69f6a01..5ab8bdc 100644
--- a/make_helpers/windows.mk
+++ b/make_helpers/windows.mk
@@ -1,9 +1,8 @@
 #
-# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
-#
 
 # OS specific parts for builds in a Windows_NT environment. The
 # environment variable OS is set to Windows_NT on all modern Windows platforms
@@ -14,6 +13,7 @@
     WINDOWS_MK := $(lastword $(MAKEFILE_LIST))
 
     ECHO_BLANK_LINE := @cmd /c echo.
+    ECHO_QUIET := @rem
     DIR_DELIM := $(strip \)
     BIN_EXT   := .exe
     PATH_SEP  := ;
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
new file mode 100644
index 0000000..2dc058f
--- /dev/null
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AW_PLAT			:=	plat/allwinner
+
+PLAT_INCLUDES		:=	-Iinclude/plat/arm/common		\
+				-Iinclude/plat/arm/common/aarch64	\
+				-I${AW_PLAT}/common/include		\
+				-I${AW_PLAT}/${PLAT}/include
+
+include lib/libfdt/libfdt.mk
+
+PLAT_BL_COMMON_SOURCES	:=	drivers/console/${ARCH}/console.S	\
+				drivers/ti/uart/${ARCH}/16550_console.S	\
+				${XLAT_TABLES_LIB_SRCS}			\
+				${AW_PLAT}/common/plat_helpers.S	\
+				${AW_PLAT}/common/sunxi_common.c
+
+BL31_SOURCES		+=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v2/gicv2_helpers.c	\
+				drivers/arm/gic/v2/gicv2_main.c		\
+				drivers/delay_timer/delay_timer.c	\
+				drivers/delay_timer/generic_delay_timer.c \
+				lib/cpus/${ARCH}/cortex_a53.S		\
+				plat/common/plat_gicv2.c		\
+				plat/common/plat_psci_common.c		\
+				${AW_PLAT}/common/sunxi_bl31_setup.c	\
+				${AW_PLAT}/common/sunxi_cpu_ops.c	\
+				${AW_PLAT}/common/sunxi_pm.c		\
+				${AW_PLAT}/${PLAT}/sunxi_power.c	\
+				${AW_PLAT}/common/sunxi_security.c	\
+				${AW_PLAT}/common/sunxi_topology.c
+
+# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
+COLD_BOOT_SINGLE_CPU		:=	1
+
+# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
+ERRATA_A53_835769		:=	1
+ERRATA_A53_843419		:=	1
+ERRATA_A53_855873		:=	1
+
+MULTI_CONSOLE_API		:=	1
+
+# The reset vector can be changed for each CPU.
+PROGRAMMABLE_RESET_ADDRESS	:=	1
+
+# Allow mapping read-only data as execute-never.
+SEPARATE_CODE_AND_RODATA	:=	1
+
+# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
+RESET_TO_BL31			:=	1
+
+# We are short on memory, so save 3.5KB by not having an extra coherent page.
+USE_COHERENT_MEM		:=	0
diff --git a/plat/allwinner/common/arisc_off.S b/plat/allwinner/common/arisc_off.S
new file mode 100644
index 0000000..ed10832
--- /dev/null
+++ b/plat/allwinner/common/arisc_off.S
@@ -0,0 +1,115 @@
+# turn_off_core.S
+#
+# Copyright (c) 2018, Andre Przywara <osp@andrep.de>
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# OpenRISC assembly to turn off an ARM core on an Allwinner SoC from
+# the arisc management controller.
+# Generate a binary representation with:
+# $ or1k-elf-as -c -o turn_off_core.o turn_off_core.S
+# $ or1k-elf-objcopy -O binary --reverse-bytes=4 turn_off_core.o \
+#   turn_off_core.bin
+# The encoded instructions go into an array defined in
+# plat/allwinner/sun50i_*/include/core_off_arisc.h, to be handed off to
+# the arisc processor.
+#
+# This routine is meant to be called directly from arisc reset (put the
+# start address in the reset vector), to be actually triggered by that
+# very ARM core to be turned off.
+# It expects the core number presented as a mask in the upper half of
+# r3, so to be patched in the lower 16 bits of the first instruction,
+# overwriting the 0 in this code here.
+# The code will do the following:
+# - Read the C_CPU_STATUS register, which contains the status of the WFI
+#   lines of each of the four A53 cores.
+# - Loop until the core in question reaches WFI.
+# - Using that mask, activate the core output clamps by setting the
+#   respective core bit in CPUX_PWROFF_GATING_REG (0x1f01500).
+#   Note that the clamp for core 0 covers more than just the core, activating
+#   it hangs the whole system. So we skip this step for core 0.
+# - Using the negated mask, assert the core's reset line by clearing the
+#   respective bit in C_RST_CTRL (0x1f01c30).
+# - Finally turn off the core's power switch by writing 0xff to the
+#   respective CPUx_PWR_SWITCH_REG (0x1f01540 ff.)
+# - Assert the arisc's own reset to end execution.
+#   This also signals other arisc users that the chip is free again.
+# So in C this would look like:
+#	while (!(readl(0x1700030) & (1U << core_nr)))
+#		;
+#	if (core_nr != 0)
+#		writel(readl(0x1f01500) | (1U << core_nr), 0x1f01500);
+#	writel(readl(0x1f01c30) & ~(1U << core_nr), 0x1f01c30);
+#	writel(0xff, 0x1f01540 + (core_nr * 4));
+# (using A64/H5 addresses)
+
+.text
+_start:
+	l.movhi	r3, 0				# FIXUP! with core mask
+	l.movhi r0, 0				# clear r0
+	l.movhi	r13, 0x170			# r13: CPU_CFG_BASE=0x01700000
+wait_wfi:
+	l.lwz	r5, 0x30(r13)			# load C_CPU_STATUS
+	l.and	r5, r5, r3			# mask requested core
+	l.sfeq	r5, r0				# is it not yet in WFI?
+	l.bf	wait_wfi			# try again
+
+	l.srli	r6, r3, 16			# move mask to lower 16 bits
+	l.sfeqi	r6, 1				# core 0 is special
+	l.bf	1f				# don't touch the bit for core 0
+	l.movhi	r13, 0x1f0			# address of R_CPUCFG (delay)
+	l.lwz	r5, 0x1500(r13)			# core output clamps
+	l.or	r5, r5, r6			# set bit to ...
+	l.sw	0x1500(r13), r5			# ... activate for our core
+
+1:	l.lwz	r5, 0x1c30(r13)			# CPU power-on reset
+	l.xori	r6, r6, -1			# negate core mask
+	l.and	r5, r5, r6			# clear bit to ...
+	l.sw	0x1c30(r13), r5			# ... assert for our core
+
+	l.ff1	r6, r3				# get core number from high mask
+	l.addi	r6, r6, -17			# convert to 0-3
+	l.slli	r6, r6, 2			# r5: core number*4 (0-12)
+	l.add	r6, r6, r13			# add to base address
+	l.ori	r5, r0, 0xff			# 0xff means all switches off
+	l.sw	0x1540(r6), r5			# core power switch registers
+
+reset:	l.sw	0x1c00(r13),r0			# pull down our own reset line
+
+	l.j	reset				# just in case ....
+	l.nop	0x0				# (delay slot)
+
+# same as above, but with the MMIO addresses matching the H6 SoC
+_start_h6:
+	l.movhi	r3, 0				# FIXUP! with core mask
+	l.movhi r0, 0				# clear r0
+	l.movhi	r13, 0x901			# r13: CPU_CFG_BASE=0x09010000
+1:
+	l.lwz	r5, 0x80(r13)			# load C_CPU_STATUS
+	l.and	r5, r5, r3			# mask requested core
+	l.sfeq	r5, r0				# is it not yet in WFI?
+	l.bf	1b				# try again
+
+	l.srli	r6, r3, 16			# move mask to lower 16 bits(ds)
+	l.sfeqi	r6, 1				# core 0 is special
+	l.bf	1f				# don't touch the bit for core 0
+	l.movhi	r13, 0x700			# address of R_CPUCFG (ds)
+	l.lwz	r5, 0x0444(r13)			# core output clamps
+	l.or	r5, r5, r6			# set bit to ...
+	l.sw	0x0444(r13), r5			# ... activate for our core
+
+1:	l.lwz	r5, 0x0440(r13)			# CPU power-on reset
+	l.xori	r6, r6, -1			# negate core mask
+	l.and	r5, r5, r6			# clear bit to ...
+	l.sw	0x0440(r13), r5			# ... assert for our core
+
+	l.ff1	r6, r3				# get core number from high mask
+	l.addi	r6, r6, -17			# convert to 0-3
+	l.slli	r6, r6, 2			# r5: core number*4 (0-12)
+	l.add	r6, r6, r13			# add to base address
+	l.ori	r5, r0, 0xff			# 0xff means all switches off
+	l.sw	0x0450(r6), r5			# core power switch registers
+
+1:	l.sw	0x0400(r13),r0			# pull down our own reset line
+
+	l.j	1b				# just in case ...
+	l.nop	0x0				# (delay slot)
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index b46d410..08eb5cf 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -18,11 +18,17 @@
 /* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */
 #define PLAT_SUNXI_NS_IMAGE_OFFSET	(SUNXI_DRAM_BASE + (160U << 20))
 
+/* How much memory to reserve as secure for BL32, if configured */
+#define SUNXI_DRAM_SEC_SIZE		(32U << 20)
+
+/* How much DRAM to map (to map BL33, for fetching the DTB from U-Boot) */
+#define SUNXI_DRAM_MAP_SIZE		(64U << 20)
+
 #define CACHE_WRITEBACK_SHIFT		6
 #define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
 
-#define MAX_MMAP_REGIONS		(4 + PLATFORM_MMAP_REGIONS)
-#define MAX_XLAT_TABLES			2
+#define MAX_MMAP_REGIONS		(3 + PLATFORM_MMAP_REGIONS)
+#define MAX_XLAT_TABLES			1
 
 #define PLAT_MAX_PWR_LVL_STATES		U(2)
 #define PLAT_MAX_RET_STATE		U(1)
@@ -34,13 +40,13 @@
 					 PLATFORM_CORE_COUNT)
 
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 28)
 
 #define PLATFORM_CLUSTER_COUNT		1
 #define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER_COUNT * \
 					 PLATFORM_MAX_CPUS_PER_CLUSTER)
 #define PLATFORM_MAX_CPUS_PER_CLUSTER	4
-#define PLATFORM_MMAP_REGIONS		3
+#define PLATFORM_MMAP_REGIONS		4
 #define PLATFORM_STACK_SIZE		(0x1000 / PLATFORM_CORE_COUNT)
 
 #ifndef SPD_none
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
index e68fbe4..da87b23 100644
--- a/plat/allwinner/common/include/sunxi_def.h
+++ b/plat/allwinner/common/include/sunxi_def.h
@@ -14,4 +14,8 @@
 #define SUNXI_UART0_BAUDRATE		115200
 #define SUNXI_UART0_CLK_IN_HZ		SUNXI_OSC24M_CLK_IN_HZ
 
+#define SUNXI_SOC_A64			0x1689
+#define SUNXI_SOC_H5			0x1718
+#define SUNXI_SOC_H6			0x1728
+
 #endif /* __SUNXI_DEF_H__ */
diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h
new file mode 100644
index 0000000..1e1b0a4
--- /dev/null
+++ b/plat/allwinner/common/include/sunxi_private.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_PRIVATE_H
+#define SUNXI_PRIVATE_H
+
+void sunxi_configure_mmu_el3(int flags);
+
+void sunxi_cpu_on(unsigned int cluster, unsigned int core);
+void sunxi_cpu_off(unsigned int cluster, unsigned int core);
+void sunxi_disable_secondary_cpus(unsigned int primary_cpu);
+void __dead2 sunxi_power_down(void);
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt);
+void sunxi_security_setup(void);
+
+uint16_t sunxi_read_soc_id(void);
+void sunxi_set_gpio_out(char port, int pin, bool level_high);
+int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb);
+void sunxi_execute_arisc_code(uint32_t *code, size_t size,
+			      int patch_offset, uint16_t param);
+
+#endif /* SUNXI_PRIVATE_H */
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index 7e11cec..8f597c3 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -10,13 +10,14 @@
 #include <debug.h>
 #include <generic_delay_timer.h>
 #include <gicv2.h>
+#include <libfdt.h>
 #include <platform.h>
 #include <platform_def.h>
 #include <sunxi_def.h>
 #include <sunxi_mmap.h>
+#include <sunxi_private.h>
 #include <uart_16550.h>
 
-#include "sunxi_private.h"
 
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
@@ -28,6 +29,47 @@
 	.gicc_base = SUNXI_GICC_BASE,
 };
 
+/*
+ * Try to find a DTB loaded in memory by previous stages.
+ *
+ * At the moment we implement a heuristic to find the DTB attached to U-Boot:
+ * U-Boot appends its DTB to the end of the image. Assuming that BL33 is
+ * U-Boot, try to find the size of the U-Boot image to learn the DTB address.
+ * The generic ARMv8 U-Boot image contains the load address and its size
+ * as u64 variables at the beginning of the image. There might be padding
+ * or other headers before that data, so scan the first 2KB after the BL33
+ * entry point to find the load address, which should be followed by the
+ * size. Adding those together gives us the address of the DTB.
+ */
+static void *sunxi_find_dtb(void)
+{
+	uint64_t *u_boot_base;
+	int i;
+
+	u_boot_base = (void *)(SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE);
+
+	for (i = 0; i < 2048 / sizeof(uint64_t); i++) {
+		uint32_t *dtb_base;
+
+		if (u_boot_base[i] != PLAT_SUNXI_NS_IMAGE_OFFSET)
+			continue;
+
+		/* Does the suspected U-Boot size look anyhow reasonable? */
+		if (u_boot_base[i + 1] >= 256 * 1024 * 1024)
+			continue;
+
+		/* end of the image: base address + size */
+		dtb_base = (void *)((char *)u_boot_base + u_boot_base[i + 1]);
+
+		if (fdt_check_header(dtb_base) != 0)
+			continue;
+
+		return dtb_base;
+	}
+
+	return NULL;
+}
+
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
@@ -66,15 +108,16 @@
 {
 	const char *soc_name;
 	uint16_t soc_id = sunxi_read_soc_id();
+	void *fdt;
 
 	switch (soc_id) {
-	case 0x1689:
+	case SUNXI_SOC_A64:
 		soc_name = "A64/H64/R18";
 		break;
-	case 0x1718:
+	case SUNXI_SOC_H5:
 		soc_name = "H5";
 		break;
-	case 0x1728:
+	case SUNXI_SOC_H6:
 		soc_name = "H6";
 		break;
 	default:
@@ -85,6 +128,18 @@
 
 	generic_delay_timer_init();
 
+	fdt = sunxi_find_dtb();
+	if (fdt) {
+		const char *model;
+		int length;
+
+		model = fdt_getprop(fdt, 0, "model", &length);
+		NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt,
+		     model ?: "unknown");
+	} else {
+		NOTICE("BL31: No DTB found.\n");
+	}
+
 	/* Configure the interrupt controller */
 	gicv2_driver_init(&sunxi_gic_data);
 	gicv2_distif_init();
@@ -93,7 +148,7 @@
 
 	sunxi_security_setup();
 
-	sunxi_pmic_setup();
+	sunxi_pmic_setup(soc_id, fdt);
 
 	INFO("BL31: Platform setup done\n");
 }
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index fc9bf20..2eb26a9 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -4,21 +4,28 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <arch_helpers.h>
+#include <debug.h>
+#include <errno.h>
 #include <mmio.h>
 #include <platform.h>
 #include <platform_def.h>
 #include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
 #include <xlat_tables_v2.h>
 
-#include "sunxi_private.h"
-
 static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
 	MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
 			MT_MEMORY | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(SUNXI_DRAM_BASE, SUNXI_DRAM_SIZE,
-			MT_MEMORY | MT_RW | MT_NS),
+	MAP_REGION(SUNXI_DRAM_BASE, SUNXI_DRAM_VIRT_BASE, SUNXI_DRAM_SEC_SIZE,
+			MT_MEMORY | MT_RW | MT_SECURE),
+	MAP_REGION(PLAT_SUNXI_NS_IMAGE_OFFSET,
+		   SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE,
+		   SUNXI_DRAM_MAP_SIZE,
+		   MT_MEMORY | MT_RO | MT_NS),
 	{},
 };
 
@@ -47,9 +54,6 @@
 	mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
 			BL_RO_DATA_END - BL_RO_DATA_BASE,
 			MT_RO_DATA | MT_SECURE);
-	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
-			BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
-			MT_DEVICE | MT_RW | MT_SECURE);
 	mmap_add(sunxi_mmap);
 	init_xlat_tables();
 
@@ -71,3 +75,136 @@
 
 	return reg >> 16;
 }
+
+/*
+ * Configure a given pin to the GPIO-OUT function and sets its level.
+ * The port is given as a capital letter, the pin is the number within
+ * this port group.
+ * So to set pin PC7 to high, use: sunxi_set_gpio_out('C', 7, true);
+ */
+void sunxi_set_gpio_out(char port, int pin, bool level_high)
+{
+	uintptr_t port_base;
+
+	if (port < 'A' || port > 'L')
+		return;
+	if (port == 'L')
+		port_base = SUNXI_R_PIO_BASE;
+	else
+		port_base = SUNXI_PIO_BASE + (port - 'A') * 0x24;
+
+	/* Set the new level first before configuring the pin. */
+	if (level_high)
+		mmio_setbits_32(port_base + 0x10, BIT(pin));
+	else
+		mmio_clrbits_32(port_base + 0x10, BIT(pin));
+
+	/* configure pin as GPIO out (4(3) bits per pin, 1: GPIO out */
+	mmio_clrsetbits_32(port_base + (pin / 8) * 4,
+			   0x7 << ((pin % 8) * 4),
+			   0x1 << ((pin % 8) * 4));
+}
+
+int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb)
+{
+	uint32_t pin_func = 0x77;
+	uint32_t device_bit;
+	unsigned int reset_offset = 0xb0;
+
+	switch (socid) {
+	case SUNXI_SOC_H5:
+		if (use_rsb)
+			return -ENODEV;
+		pin_func = 0x22;
+		device_bit = BIT(6);
+		break;
+	case SUNXI_SOC_H6:
+		if (use_rsb)
+			return -ENODEV;
+		pin_func = 0x33;
+		device_bit = BIT(16);
+		reset_offset = 0x19c;
+		break;
+	case SUNXI_SOC_A64:
+		pin_func = use_rsb ? 0x22 : 0x33;
+		device_bit = use_rsb ? BIT(3) : BIT(6);
+		break;
+	default:
+		INFO("R_I2C/RSB on Allwinner 0x%x SoC not supported\n", socid);
+		return -ENODEV;
+	}
+
+	/* un-gate R_PIO clock */
+	if (socid != SUNXI_SOC_H6)
+		mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, BIT(0));
+
+	/* switch pins PL0 and PL1 to the desired function */
+	mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x00, 0xffU, pin_func);
+
+	/* level 2 drive strength */
+	mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x14, 0x0fU, 0xaU);
+
+	/* set both pins to pull-up */
+	mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x1c, 0x0fU, 0x5U);
+
+	/* assert, then de-assert reset of I2C/RSB controller */
+	mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
+	mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
+
+	/* un-gate clock */
+	if (socid != SUNXI_SOC_H6)
+		mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit);
+	else
+		mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x19c, device_bit | BIT(0));
+
+	return 0;
+}
+
+/* This lock synchronises access to the arisc management processor. */
+DEFINE_BAKERY_LOCK(arisc_lock);
+
+/*
+ * Tell the "arisc" SCP core (an OpenRISC core) to execute some code.
+ * We don't have any service running there, so we place some OpenRISC code
+ * in SRAM, put the address of that into the reset vector and release the
+ * arisc reset line. The SCP will execute that code and pull the line up again.
+ */
+void sunxi_execute_arisc_code(uint32_t *code, size_t size,
+			      int patch_offset, uint16_t param)
+{
+	uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE - 0x4000 + 0x100;
+
+	do {
+		bakery_lock_get(&arisc_lock);
+		/* Wait until the arisc is in reset state. */
+		if (!(mmio_read_32(SUNXI_R_CPUCFG_BASE) & BIT(0)))
+			break;
+
+		bakery_lock_release(&arisc_lock);
+	} while (1);
+
+	/* Patch up the code to feed in an input parameter. */
+	if (patch_offset >= 0 && patch_offset <= (size - 4))
+		code[patch_offset] = (code[patch_offset] & ~0xffff) | param;
+	clean_dcache_range((uintptr_t)code, size);
+
+	/*
+	 * The OpenRISC unconditional branch has opcode 0, the branch offset
+	 * is in the lower 26 bits, containing the distance to the target,
+	 * in instruction granularity (32 bits).
+	 */
+	mmio_write_32(arisc_reset_vec, ((uintptr_t)code - arisc_reset_vec) / 4);
+	clean_dcache_range(arisc_reset_vec, 4);
+
+	/* De-assert the arisc reset line to let it run. */
+	mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
+
+	/*
+	 * We release the lock here, although the arisc is still busy.
+	 * But as long as it runs, the reset line is high, so other users
+	 * won't leave the loop above.
+	 * Once it has finished, the code is supposed to clear the reset line,
+	 * to signal this to other users.
+	 */
+	bakery_lock_release(&arisc_lock);
+}
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index aaee65c..3b732b5 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -4,15 +4,19 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <arch_helpers.h>
+#include <assert.h>
+#include <core_off_arisc.h>
 #include <debug.h>
+#include <delay_timer.h>
 #include <mmio.h>
+#include <platform.h>
 #include <platform_def.h>
-#include <sunxi_mmap.h>
 #include <sunxi_cpucfg.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
 #include <utils_def.h>
 
-#include "sunxi_private.h"
-
 static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core)
 {
 	if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff)
@@ -40,16 +44,37 @@
 
 void sunxi_cpu_off(unsigned int cluster, unsigned int core)
 {
+	int corenr = cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core;
+
 	VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core);
 
 	/* Deassert DBGPWRDUP */
 	mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
-	/* Activate the core output clamps */
-	mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
-	/* Assert CPU power-on reset */
-	mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
-	/* Remove power from the CPU */
-	sunxi_cpu_disable_power(cluster, core);
+
+	/* We can't turn ourself off like this, but it works for other cores. */
+	if (plat_my_core_pos() != corenr) {
+		/* Activate the core output clamps, but not for core 0. */
+		if (corenr != 0)
+			mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster),
+					BIT(core));
+		/* Assert CPU power-on reset */
+		mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+		/* Remove power from the CPU */
+		sunxi_cpu_disable_power(cluster, core);
+
+		return;
+	}
+
+	/* Simplifies assembly, all SoCs so far are single cluster anyway. */
+	assert(cluster == 0);
+
+	/*
+	 * If we are supposed to turn ourself off, tell the arisc SCP
+	 * to do that work for us. The code expects the core mask to be
+	 * patched into the first instruction.
+	 */
+	sunxi_execute_arisc_code(arisc_core_off, sizeof(arisc_core_off),
+				 0, BIT_32(core));
 }
 
 void sunxi_cpu_on(unsigned int cluster, unsigned int core)
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index e4bb582..7d13cda 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -13,15 +13,14 @@
 #include <platform.h>
 #include <platform_def.h>
 #include <psci.h>
-#include <sunxi_mmap.h>
 #include <sunxi_cpucfg.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
 
 #define SUNXI_WDOG0_CTRL_REG		(SUNXI_WDOG_BASE + 0x0010)
 #define SUNXI_WDOG0_CFG_REG		(SUNXI_WDOG_BASE + 0x0014)
 #define SUNXI_WDOG0_MODE_REG		(SUNXI_WDOG_BASE + 0x0018)
 
-#include "sunxi_private.h"
-
 #define mpidr_is_valid(mpidr) ( \
 	MPIDR_AFFLVL3_VAL(mpidr) == 0 && \
 	MPIDR_AFFLVL2_VAL(mpidr) == 0 && \
@@ -43,6 +42,16 @@
 	gicv2_cpuif_disable();
 }
 
+static void __dead2 sunxi_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+	u_register_t mpidr = read_mpidr();
+
+	sunxi_cpu_off(MPIDR_AFFLVL1_VAL(mpidr), MPIDR_AFFLVL0_VAL(mpidr));
+
+	while (1)
+		wfi();
+}
+
 static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
 	gicv2_pcpu_distif_init();
@@ -83,6 +92,7 @@
 static plat_psci_ops_t sunxi_psci_ops = {
 	.pwr_domain_on			= sunxi_pwr_domain_on,
 	.pwr_domain_off			= sunxi_pwr_domain_off,
+	.pwr_domain_pwr_down_wfi	= sunxi_pwr_down_wfi,
 	.pwr_domain_on_finish		= sunxi_pwr_domain_on_finish,
 	.system_off			= sunxi_system_off,
 	.system_reset			= sunxi_system_reset,
diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/sunxi_private.h
deleted file mode 100644
index 20fa23e..0000000
--- a/plat/allwinner/common/sunxi_private.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __SUNXI_PRIVATE_H__
-#define __SUNXI_PRIVATE_H__
-
-void sunxi_configure_mmu_el3(int flags);
-void sunxi_cpu_off(unsigned int cluster, unsigned int core);
-void sunxi_cpu_on(unsigned int cluster, unsigned int core);
-void sunxi_disable_secondary_cpus(unsigned int primary_cpu);
-
-uint16_t sunxi_read_soc_id(void);
-
-void sunxi_pmic_setup(void);
-void sunxi_security_setup(void);
-
-void __dead2 sunxi_power_down(void);
-
-#endif /* __SUNXI_PRIVATE_H__ */
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
index 80fed6a..9053728 100644
--- a/plat/allwinner/common/sunxi_security.c
+++ b/plat/allwinner/common/sunxi_security.c
@@ -7,6 +7,7 @@
 #include <debug.h>
 #include <mmio.h>
 #include <sunxi_mmap.h>
+#include <sunxi_private.h>
 
 #ifdef SUNXI_SPC_BASE
 #define SPC_DECPORT_STA_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4)
diff --git a/plat/allwinner/sun50i_a64/include/core_off_arisc.h b/plat/allwinner/sun50i_a64/include/core_off_arisc.h
new file mode 100644
index 0000000..ae436ca
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/core_off_arisc.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+static uint32_t arisc_core_off[] = {
+	0x18600000, /* l.movhi	r3, <corenr>	*/
+	0x18000000, /* l.movhi	r0, 0x0		*/
+	0x19a00170, /* l.movhi	r13, 0x170	*/
+	0x84ad0030, /* l.lwz	r5, 0x30(r13)	*/
+	0xe0a51803, /* l.and	r5, r5, r3	*/
+	0xe4050000, /* l.sfeq	r5, r0		*/
+	0x13fffffd, /* l.bf	-12		*/
+
+	0xb8c30050, /* l.srli	r6, r3, 16	*/
+	0xbc060001, /* l.sfeqi	r6, 1		*/
+	0x10000005, /* l.bf	+20		*/
+	0x19a001f0, /* l.movhi	r13, 0x1f0	*/
+	0x84ad1500, /* l.lwz	r5, 0x1500(r13)	*/
+	0xe0a53004, /* l.or	r5, r5, r6	*/
+	0xd44d2d00, /* l.sw	0x1500(r13), r5	*/
+
+	0x84ad1c30, /* l.lwz	r5, 0x1c30(r13)	*/
+	0xacc6ffff, /* l.xori	r6, r6, -1	*/
+	0xe0a53003, /* l.and	r5, r5, r6	*/
+	0xd46d2c30, /* l.sw	0x1c30(r13), r5	*/
+
+	0xe0c3000f, /* l.ff1	r6, r3		*/
+	0x9cc6ffef, /* l.addi	r6, r6, -17	*/
+	0xb8c60002, /* l.slli	r6, r6, 2	*/
+	0xe0c66800, /* l.add	r6, r6, r13	*/
+	0xa8a000ff, /* l.ori	r5, r0, 0xff	*/
+	0xd4462d40, /* l.sw	0x1540(r6), r5	*/
+
+	0xd46d0400, /* l.sw	0x1c00(r13), r0	*/
+	0x03ffffff, /* l.j	-1		*/
+	0x15000000, /* l.nop			*/
+};
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index 7d46487..28b1dd3 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -21,7 +21,7 @@
 #define SUNXI_DEV_BASE			0x01000000
 #define SUNXI_DEV_SIZE			0x01000000
 #define SUNXI_DRAM_BASE			0x40000000
-#define SUNXI_DRAM_SIZE			0x80000000
+#define SUNXI_DRAM_VIRT_BASE		0x02000000
 
 /* Memory-mapped devices */
 #define SUNXI_CPU_MBIST_BASE		0x01502000
diff --git a/plat/allwinner/sun50i_a64/platform.mk b/plat/allwinner/sun50i_a64/platform.mk
index 2216654..b46fbc2 100644
--- a/plat/allwinner/sun50i_a64/platform.mk
+++ b/plat/allwinner/sun50i_a64/platform.mk
@@ -4,51 +4,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-include lib/xlat_tables_v2/xlat_tables.mk
+# The differences between the platform are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
 
-AW_PLAT			:=	plat/allwinner
-
-PLAT_INCLUDES		:=	-Iinclude/plat/arm/common/		\
-				-Iinclude/plat/arm/common/aarch64	\
-				-I${AW_PLAT}/common/include		\
-				-I${AW_PLAT}/${PLAT}/include
-
-PLAT_BL_COMMON_SOURCES	:=	drivers/console/${ARCH}/console.S	\
-				drivers/ti/uart/${ARCH}/16550_console.S	\
-				${XLAT_TABLES_LIB_SRCS}			\
-				${AW_PLAT}/common/plat_helpers.S	\
-				${AW_PLAT}/common/sunxi_common.c
-
-BL31_SOURCES		+=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/delay_timer/delay_timer.c	\
-				drivers/delay_timer/generic_delay_timer.c \
-				lib/cpus/${ARCH}/cortex_a53.S		\
-				plat/common/plat_gicv2.c		\
-				plat/common/plat_psci_common.c		\
-				${AW_PLAT}/common/sunxi_bl31_setup.c	\
-				${AW_PLAT}/common/sunxi_cpu_ops.c	\
-				${AW_PLAT}/common/sunxi_pm.c		\
-				${AW_PLAT}/sun50i_a64/sunxi_power.c	\
-				${AW_PLAT}/common/sunxi_security.c	\
-				${AW_PLAT}/common/sunxi_topology.c
-
-# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
-COLD_BOOT_SINGLE_CPU		:=	1
-
-# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
-ERRATA_A53_835769		:=	1
-ERRATA_A53_843419		:=	1
-ERRATA_A53_855873		:=	1
-
-MULTI_CONSOLE_API		:=	1
-
-# The reset vector can be changed for each CPU.
-PROGRAMMABLE_RESET_ADDRESS	:=	1
-
-# Allow mapping read-only data as execute-never.
-SEPARATE_CODE_AND_RODATA	:=	1
-
-# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
-RESET_TO_BL31			:=	1
+PLAT_BL_COMMON_SOURCES	+=	drivers/allwinner/sunxi_rsb.c
diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c
index c1907d6..af30477 100644
--- a/plat/allwinner/sun50i_a64/sunxi_power.c
+++ b/plat/allwinner/sun50i_a64/sunxi_power.c
@@ -5,20 +5,350 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <allwinner/sunxi_rsb.h>
 #include <arch_helpers.h>
 #include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
 
-int sunxi_pmic_setup(void)
+static enum pmic_type {
+	GENERIC_H5,
+	GENERIC_A64,
+	REF_DESIGN_H5,	/* regulators controlled by GPIO pins on port L */
+	AXP803_RSB,	/* PMIC connected via RSB on most A64 boards */
+} pmic;
+
+#define AXP803_HW_ADDR	0x3a3
+#define AXP803_RT_ADDR	0x2d
+
+/*
+ * On boards without a proper PMIC we struggle to turn off the system properly.
+ * Try to turn off as much off the system as we can, to reduce power
+ * consumption. This should be entered with only one core running and SMP
+ * disabled.
+ * This function only cares about peripherals.
+ */
+void sunxi_turn_off_soc(uint16_t socid)
 {
-	/* STUB */
-	NOTICE("BL31: STUB PMIC setup code called\n");
+	int i;
 
+	/** Turn off most peripherals, most importantly DRAM users. **/
+	/* Keep DRAM controller running for now. */
+	mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, ~BIT_32(14));
+	mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, ~BIT_32(14));
+	/* Contains msgbox (bit 21) and spinlock (bit 22) */
+	mmio_write_32(SUNXI_CCU_BASE + 0x2c4, 0);
+	mmio_write_32(SUNXI_CCU_BASE + 0x64, 0);
+	mmio_write_32(SUNXI_CCU_BASE + 0x2c8, 0);
+	/* Keep PIO controller running for now. */
+	mmio_clrbits_32(SUNXI_CCU_BASE + 0x68, ~(BIT_32(5)));
+	mmio_write_32(SUNXI_CCU_BASE + 0x2d0, 0);
+	/* Contains UART0 (bit 16) */
+	mmio_write_32(SUNXI_CCU_BASE + 0x2d8, 0);
+	mmio_write_32(SUNXI_CCU_BASE + 0x6c, 0);
+	mmio_write_32(SUNXI_CCU_BASE + 0x70, 0);
+
+	/** Turn off DRAM controller. **/
+	mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, BIT_32(14));
+	mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, BIT_32(14));
+
+	/** Migrate CPU and bus clocks away from the PLLs. **/
+	/* AHB1: use OSC24M/1, APB1 = AHB1 / 2 */
+	mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x1000);
+	/* APB2: use OSC24M */
+	mmio_write_32(SUNXI_CCU_BASE + 0x58, 0x1000000);
+	/* AHB2: use AHB1 clock */
+	mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0);
+	/* CPU: use OSC24M */
+	mmio_write_32(SUNXI_CCU_BASE + 0x50, 0x10000);
+
+	/** Turn off PLLs. **/
+	for (i = 0; i < 6; i++)
+		mmio_clrbits_32(SUNXI_CCU_BASE + i * 8, BIT(31));
+	switch (socid) {
+	case SUNXI_SOC_H5:
+		mmio_clrbits_32(SUNXI_CCU_BASE + 0x44, BIT(31));
+		break;
+	case SUNXI_SOC_A64:
+		mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c, BIT(31));
+		mmio_clrbits_32(SUNXI_CCU_BASE + 0x4c, BIT(31));
+		break;
+	}
+}
+
+static int rsb_init(void)
+{
+	int ret;
+
+	ret = rsb_init_controller();
+	if (ret)
+		return ret;
+
+	/* Start with 400 KHz to issue the I2C->RSB switch command. */
+	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 400000);
+	if (ret)
+		return ret;
+
+	/*
+	 * Initiate an I2C transaction to write 0x7c into register 0x3e,
+	 * switching the PMIC to RSB mode.
+	 */
+	ret = rsb_set_device_mode(0x7c3e00);
+	if (ret)
+		return ret;
+
+	/* Now in RSB mode, switch to the recommended 3 MHz. */
+	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
+	if (ret)
+		return ret;
+
+	/* Associate the 8-bit runtime address with the 12-bit bus address. */
+	return rsb_assign_runtime_address(AXP803_HW_ADDR,
+					  AXP803_RT_ADDR);
+}
+
+static int axp_write(uint8_t reg, uint8_t val)
+{
+	return rsb_write(AXP803_RT_ADDR, reg, val);
+}
+
+static int axp_setbits(uint8_t reg, uint8_t set_mask)
+{
+	uint8_t regval;
+	int ret;
+
+	ret = rsb_read(AXP803_RT_ADDR, reg);
+	if (ret < 0)
+		return ret;
+
+	regval = ret | set_mask;
+
+	return rsb_write(AXP803_RT_ADDR, reg, regval);
+}
+
+static bool should_enable_regulator(const void *fdt, int node)
+{
+	if (fdt_getprop(fdt, node, "phandle", NULL) != NULL)
+		return true;
+	if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL)
+		return true;
+	return false;
+}
+
+/*
+ * Retrieve the voltage from a given regulator DTB node.
+ * Both the regulator-{min,max}-microvolt properties must be present and
+ * have the same value. Return that value in millivolts.
+ */
+static int fdt_get_regulator_millivolt(const void *fdt, int node)
+{
+	const fdt32_t *prop;
+	uint32_t min_volt;
+
+	prop = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
+	if (prop == NULL)
+		return -EINVAL;
+	min_volt = fdt32_to_cpu(*prop);
+
+	prop = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
+	if (prop == NULL)
+		return -EINVAL;
+
+	if (fdt32_to_cpu(*prop) != min_volt)
+		return -EINVAL;
+
+	return min_volt / 1000;
+}
+
+#define NO_SPLIT 0xff
+
+struct axp_regulator {
+	char *dt_name;
+	uint16_t min_volt;
+	uint16_t max_volt;
+	uint16_t step;
+	unsigned char split;
+	unsigned char volt_reg;
+	unsigned char switch_reg;
+	unsigned char switch_bit;
+} regulators[] = {
+	{"dcdc1", 1600, 3400, 100, NO_SPLIT, 0x20, 0xff, 9},
+	{"dcdc5",  800, 1840,  10,       32, 0x24, 0xff, 9},
+	{"dldo1",  700, 3300, 100, NO_SPLIT, 0x15, 0x12, 3},
+	{"dldo2",  700, 4200, 100,       27, 0x16, 0x12, 4},
+	{"dldo3",  700, 3300, 100, NO_SPLIT, 0x17, 0x12, 5},
+	{"fldo1",  700, 1450,  50, NO_SPLIT, 0x1c, 0x13, 2},
+	{}
+};
+
+static int setup_regulator(const void *fdt, int node,
+			   const struct axp_regulator *reg)
+{
+	int mvolt;
+	uint8_t regval;
+
+	if (!should_enable_regulator(fdt, node))
+		return -ENOENT;
+
+	mvolt = fdt_get_regulator_millivolt(fdt, node);
+	if (mvolt < reg->min_volt || mvolt > reg->max_volt)
+		return -EINVAL;
+
+	regval = (mvolt / reg->step) - (reg->min_volt / reg->step);
+	if (regval > reg->split)
+		regval = ((regval - reg->split) / 2) + reg->split;
+
+	axp_write(reg->volt_reg, regval);
+	if (reg->switch_reg < 0xff)
+		axp_setbits(reg->switch_reg, BIT(reg->switch_bit));
+
+	INFO("PMIC: AXP803: %s voltage: %d.%03dV\n", reg->dt_name,
+	     mvolt / 1000, mvolt % 1000);
+
+	return 0;
+}
+
+static void setup_axp803_rails(const void *fdt)
+{
+	int node;
+	bool dc1sw = false;
+
+	/* locate the PMIC DT node, bail out if not found */
+	node = fdt_node_offset_by_compatible(fdt, -1, "x-powers,axp803");
+	if (node == -FDT_ERR_NOTFOUND) {
+		WARN("BL31: PMIC: No AXP803 DT node, skipping initial setup.\n");
+		return;
+	}
+
+	if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL))
+		axp_setbits(0x8f, BIT(4));
+
+	/* descend into the "regulators" subnode */
+	node = fdt_first_subnode(fdt, node);
+
+	/* iterate over all regulators to find used ones */
+	for (node = fdt_first_subnode(fdt, node);
+	     node != -FDT_ERR_NOTFOUND;
+	     node = fdt_next_subnode(fdt, node)) {
+		struct axp_regulator *reg;
+		const char *name;
+		int length;
+
+		/* We only care if it's always on or referenced. */
+		if (!should_enable_regulator(fdt, node))
+			continue;
+
+		name = fdt_get_name(fdt, node, &length);
+		for (reg = regulators; reg->dt_name; reg++) {
+			if (!strncmp(name, reg->dt_name, length)) {
+				setup_regulator(fdt, node, reg);
+				break;
+			}
+		}
+
+		if (!strncmp(name, "dc1sw", length)) {
+			/* Delay DC1SW enablement to avoid overheating. */
+			dc1sw = true;
+			continue;
+		}
+	}
+	/*
+	 * If DLDO2 is enabled after DC1SW, the PMIC overheats and shuts
+	 * down. So always enable DC1SW as the very last regulator.
+	 */
+	if (dc1sw) {
+		INFO("PMIC: AXP803: Enabling DC1SW\n");
+		axp_setbits(0x12, BIT(7));
+	}
+}
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+	int ret;
+
+	switch (socid) {
+	case SUNXI_SOC_H5:
+		pmic = REF_DESIGN_H5;
+		NOTICE("BL31: PMIC: Defaulting to PortL GPIO according to H5 reference design.\n");
+		break;
+	case SUNXI_SOC_A64:
+		pmic = GENERIC_A64;
+		ret = sunxi_init_platform_r_twi(socid, true);
+		if (ret)
+			return ret;
+
+		ret = rsb_init();
+		if (ret)
+			return ret;
+
+		pmic = AXP803_RSB;
+		NOTICE("BL31: PMIC: Detected AXP803 on RSB.\n");
+
+		if (fdt)
+			setup_axp803_rails(fdt);
+
+		break;
+	default:
+		NOTICE("BL31: PMIC: No support for Allwinner %x SoC.\n", socid);
+		return -ENODEV;
+	}
 	return 0;
 }
 
 void __dead2 sunxi_power_down(void)
 {
-	ERROR("PSCI: Full shutdown not implemented, halting\n");
+	switch (pmic) {
+	case GENERIC_H5:
+		/* Turn off as many peripherals and clocks as we can. */
+		sunxi_turn_off_soc(SUNXI_SOC_H5);
+		/* Turn off the pin controller now. */
+		mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
+		break;
+	case GENERIC_A64:
+		/* Turn off as many peripherals and clocks as we can. */
+		sunxi_turn_off_soc(SUNXI_SOC_A64);
+		/* Turn off the pin controller now. */
+		mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
+		break;
+	case REF_DESIGN_H5:
+		sunxi_turn_off_soc(SUNXI_SOC_H5);
+
+		/*
+		 * Switch PL pins to power off the board:
+		 * - PL5 (VCC_IO) -> high
+		 * - PL8 (PWR-STB = CPU power supply) -> low
+		 * - PL9 (PWR-DRAM) ->low
+		 * - PL10 (power LED) -> low
+		 * Note: Clearing PL8 will reset the board, so keep it up.
+		 */
+		sunxi_set_gpio_out('L', 5, 1);
+		sunxi_set_gpio_out('L', 9, 0);
+		sunxi_set_gpio_out('L', 10, 0);
+
+		/* Turn off pin controller now. */
+		mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
+
+		break;
+	case AXP803_RSB:
+		/* (Re-)init RSB in case the rich OS has disabled it. */
+		sunxi_init_platform_r_twi(SUNXI_SOC_A64, true);
+		rsb_init();
+
+		/* Set "power disable control" bit */
+		axp_setbits(0x32, BIT(7));
+		break;
+	default:
+		break;
+	}
+
+	udelay(1000);
+	ERROR("PSCI: Cannot turn off system, halting.\n");
 	wfi();
 	panic();
 }
diff --git a/plat/allwinner/sun50i_h6/include/core_off_arisc.h b/plat/allwinner/sun50i_h6/include/core_off_arisc.h
new file mode 100644
index 0000000..63a5d8d
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/core_off_arisc.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+static uint32_t arisc_core_off[] = {
+	0x18600000, /* l.movhi	r3, <corenr>	*/
+	0x18000000, /* l.movhi	r0, 0x0		*/
+	0x19a00901, /* l.movhi	r13, 0x901	*/
+	0x84ad0080, /* l.lwz	r5, 0x80(r13)	*/
+	0xe0a51803, /* l.and	r5, r5, r3	*/
+	0xe4050000, /* l.sfeq	r5, r0		*/
+	0x13fffffd, /* l.bf	-12		*/
+	0xb8c30050, /* l.srli	r6, r3, 16	*/
+
+	0xbc060001, /* l.sfeqi	r6, 1		*/
+	0x10000005, /* l.bf	+20		*/
+	0x19a00700, /* l.movhi	r13, 0x700	*/
+	0x84ad0444, /* l.lwz	r5, 0x0444(r13)	*/
+	0xe0a53004, /* l.or	r5, r5, r6	*/
+	0xd40d2c44, /* l.sw	0x0444(r13), r5	*/
+
+	0x84ad0440, /* l.lwz	r5, 0x0440(r13)	*/
+	0xacc6ffff, /* l.xori	r6, r6, -1	*/
+	0xe0a53003, /* l.and	r5, r5, r6	*/
+	0xd40d2c40, /* l.sw	0x0440(r13), r5	*/
+
+	0xe0c3000f, /* l.ff1	r6, r3		*/
+	0x9cc6ffef, /* l.addi	r6, r6, -17	*/
+	0xb8c60002, /* l.slli	r6, r6, 2	*/
+	0xe0c66800, /* l.add	r6, r6, r13	*/
+	0xa8a000ff, /* l.ori	r5, r0, 0xff	*/
+	0xd4062c50, /* l.sw	0x0450(r6), r5	*/
+
+	0xd40d0400, /* l.sw	0x0400(r13), r0	*/
+	0x03ffffff, /* l.j	-1		*/
+	0x15000000, /* l.nop			*/
+};
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index f2d5aed..ff1eb61 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -11,7 +11,7 @@
 #define SUNXI_ROM_BASE			0x00000000
 #define SUNXI_ROM_SIZE			0x00010000
 #define SUNXI_SRAM_BASE			0x00020000
-#define SUNXI_SRAM_SIZE			0x00098000
+#define SUNXI_SRAM_SIZE			0x000f8000
 #define SUNXI_SRAM_A1_BASE		0x00020000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
 #define SUNXI_SRAM_A2_BASE		0x00104000
@@ -21,7 +21,7 @@
 #define SUNXI_DEV_BASE			0x01000000
 #define SUNXI_DEV_SIZE			0x09000000
 #define SUNXI_DRAM_BASE			0x40000000
-#define SUNXI_DRAM_SIZE			0xc0000000
+#define SUNXI_DRAM_VIRT_BASE		0x0a000000
 
 /* Memory-mapped devices */
 #define SUNXI_SYSCON_BASE		0x03000000
diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk
index 4fb8986..5c21ead 100644
--- a/plat/allwinner/sun50i_h6/platform.mk
+++ b/plat/allwinner/sun50i_h6/platform.mk
@@ -4,53 +4,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-include lib/xlat_tables_v2/xlat_tables.mk
+# The differences between the platform are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
 
-AW_PLAT			:=	plat/allwinner
-AW_DRIVERS		:=	drivers/allwinner
-
-PLAT_INCLUDES		:=	-Iinclude/plat/arm/common		\
-				-Iinclude/plat/arm/common/aarch64	\
-				-I${AW_PLAT}/common/include		\
-				-I${AW_PLAT}/${PLAT}/include
-
-PLAT_BL_COMMON_SOURCES	:=	drivers/console/${ARCH}/console.S	\
-				drivers/mentor/i2c/mi2cv.c		\
-				drivers/ti/uart/${ARCH}/16550_console.S	\
-				${XLAT_TABLES_LIB_SRCS}			\
-				${AW_PLAT}/common/plat_helpers.S	\
-				${AW_PLAT}/common/sunxi_common.c
-
-BL31_SOURCES		+=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/delay_timer/delay_timer.c	\
-				drivers/delay_timer/generic_delay_timer.c \
-				lib/cpus/${ARCH}/cortex_a53.S		\
-				plat/common/plat_gicv2.c		\
-				plat/common/plat_psci_common.c		\
-				${AW_PLAT}/common/sunxi_bl31_setup.c	\
-				${AW_PLAT}/common/sunxi_cpu_ops.c	\
-				${AW_PLAT}/common/sunxi_pm.c		\
-				${AW_PLAT}/sun50i_h6/sunxi_power.c	\
-				${AW_PLAT}/common/sunxi_security.c	\
-				${AW_PLAT}/common/sunxi_topology.c
-
-# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
-COLD_BOOT_SINGLE_CPU		:=	1
-
-# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
-ERRATA_A53_835769		:=	1
-ERRATA_A53_843419		:=	1
-ERRATA_A53_855873		:=	1
-
-MULTI_CONSOLE_API		:=	1
-
-# The reset vector can be changed for each CPU.
-PROGRAMMABLE_RESET_ADDRESS	:=	1
-
-# Allow mapping read-only data as execute-never.
-SEPARATE_CODE_AND_RODATA	:=	1
-
-# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
-RESET_TO_BL31			:=	1
+PLAT_BL_COMMON_SOURCES	+=	drivers/mentor/i2c/mi2cv.c
diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c
index 12438b3..7bdac8a 100644
--- a/plat/allwinner/sun50i_h6/sunxi_power.c
+++ b/plat/allwinner/sun50i_h6/sunxi_power.c
@@ -12,7 +12,9 @@
 #include <mmio.h>
 #include <mentor/mi2cv.h>
 #include <string.h>
+#include <sunxi_def.h>
 #include <sunxi_mmap.h>
+#include <sunxi_private.h>
 
 #define AXP805_ADDR	0x36
 #define AXP805_ID	0x03
@@ -24,36 +26,6 @@
 
 enum pmic_type pmic;
 
-static int sunxi_init_r_i2c(void)
-{
-	uint32_t reg;
-
-	/* switch pins PL0 and PL1 to I2C */
-	reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x00);
-	mmio_write_32(SUNXI_R_PIO_BASE + 0x00, (reg & ~0xff) | 0x33);
-
-	/* level 2 drive strength */
-	reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x14);
-	mmio_write_32(SUNXI_R_PIO_BASE + 0x14, (reg & ~0x0f) | 0xa);
-
-	/* set both ports to pull-up */
-	reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x1c);
-	mmio_write_32(SUNXI_R_PIO_BASE + 0x1c, (reg & ~0x0f) | 0x5);
-
-	/* assert & de-assert reset of R_I2C */
-	reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c);
-	mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg & ~BIT(16));
-	mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | BIT(16));
-
-	/* un-gate R_I2C clock */
-	mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | BIT(16) | BIT(0));
-
-	/* call mi2cv driver */
-	i2c_init((void *)SUNXI_R_I2C_BASE);
-
-	return 0;
-}
-
 int axp_i2c_read(uint8_t chip, uint8_t reg, uint8_t *val)
 {
 	int ret;
@@ -96,11 +68,13 @@
 	return 0;
 }
 
-int sunxi_pmic_setup(void)
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
 {
 	int ret;
 
-	sunxi_init_r_i2c();
+	sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
+	/* initialise mi2cv driver */
+	i2c_init((void *)SUNXI_R_I2C_BASE);
 
 	NOTICE("PMIC: Probing AXP805\n");
 	pmic = AXP805;
@@ -120,7 +94,10 @@
 
 	switch (pmic) {
 	case AXP805:
-		sunxi_init_r_i2c();
+		/* Re-initialise after rich OS might have used it. */
+		sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
+		/* initialise mi2cv driver */
+		i2c_init((void *)SUNXI_R_I2C_BASE);
 		axp_i2c_read(AXP805_ADDR, 0x32, &val);
 		axp_i2c_write(AXP805_ADDR, 0x32, val | 0x80);
 		break;
diff --git a/plat/arm/board/fvp/aarch64/fvp_helpers.S b/plat/arm/board/fvp/aarch64/fvp_helpers.S
index 88fcdb1..abc3ceb 100644
--- a/plat/arm/board/fvp/aarch64/fvp_helpers.S
+++ b/plat/arm/board/fvp/aarch64/fvp_helpers.S
@@ -19,7 +19,7 @@
 	.globl	plat_arm_calc_core_pos
 
 	.macro	fvp_choose_gicmmap  param1, param2, x_tmp, w_tmp, res
-	ldr	\x_tmp, =V2M_SYSREGS_BASE + V2M_SYS_ID
+	mov_imm	\x_tmp, V2M_SYSREGS_BASE + V2M_SYS_ID
 	ldr	\w_tmp, [\x_tmp]
 	ubfx	\w_tmp, \w_tmp, #V2M_SYS_ID_BLD_SHIFT, #V2M_SYS_ID_BLD_LENGTH
 	cmp	\w_tmp, #BLD_GIC_VE_MMAP
@@ -48,7 +48,7 @@
 	 * ---------------------------------------------
 	 */
 	mrs	x0, mpidr_el1
-	ldr	x1, =PWRC_BASE
+	mov_imm	x1, PWRC_BASE
 	str	w0, [x1, #PPOFFR_OFF]
 
 	/* ---------------------------------------------
@@ -72,8 +72,8 @@
 	b	secondary_cold_boot_wait
 
 gicv2_bypass_disable:
-	ldr	x0, =VE_GICC_BASE
-	ldr	x1, =BASE_GICC_BASE
+	mov_imm	x0, VE_GICC_BASE
+	mov_imm	x1, BASE_GICC_BASE
 	fvp_choose_gicmmap	x0, x1, x2, w2, x1
 	mov	w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1)
 	orr	w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0)
@@ -128,7 +128,7 @@
 	 * ---------------------------------------------------------------------
 	 */
 	mrs	x2, mpidr_el1
-	ldr	x1, =PWRC_BASE
+	mov_imm	x1, PWRC_BASE
 	str	w2, [x1, #PSYSR_OFF]
 	ldr	w2, [x1, #PSYSR_OFF]
 	ubfx	w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
@@ -171,7 +171,7 @@
 	 */
 func plat_is_my_cpu_primary
 	mrs	x0, mpidr_el1
-	ldr	x1, =MPIDR_AFFINITY_MASK
+	mov_imm	x1, MPIDR_AFFINITY_MASK
 	and	x0, x0, x1
 	cmp	x0, #FVP_PRIMARY_CPU
 	cset	w0, eq
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index aa4f839..f5198f6 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -7,7 +7,6 @@
 #include <arm_config.h>
 #include <arm_def.h>
 #include <arm_spm_def.h>
-#include <arm_xlat_tables.h>
 #include <assert.h>
 #include <cci.h>
 #include <ccn.h>
@@ -18,6 +17,8 @@
 #include <platform.h>
 #include <secure_partition.h>
 #include <v2m_def.h>
+#include <xlat_tables_compat.h>
+
 #include "../fvp_def.h"
 #include "fvp_private.h"
 
@@ -52,8 +53,8 @@
 
 /*
  * Table of memory regions for various BL stages to map using the MMU.
- * This doesn't include Trusted SRAM as arm_setup_page_tables() already
- * takes care of mapping it.
+ * This doesn't include Trusted SRAM as setup_page_tables() already takes care
+ * of mapping it.
  *
  * The flash needs to be mapped as writable in order to erase the FIP's Table of
  * Contents in case of unrecoverable error (see plat_error_handler()).
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 332df4d..3d858c2 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -202,7 +202,9 @@
 DYNAMIC_WORKAROUND_CVE_2018_3639	:=	1
 
 # Enable reclaiming of BL31 initialisation code for secondary cores stacks for FVP
+ifneq (${RESET_TO_BL31},1)
 RECLAIM_INIT_CODE	:=	1
+endif
 
 ifeq (${ENABLE_AMU},1)
 BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a75_pubsub.c	\
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 0e5c6d9..d4a77f0 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -142,7 +142,7 @@
 # define PLAT_ARM_MAX_BL2_SIZE		0x1C000
 #endif
 #else
-# define PLAT_ARM_MAX_BL2_SIZE		0xE000
+# define PLAT_ARM_MAX_BL2_SIZE		0xF000
 #endif
 
 /*
diff --git a/plat/arm/board/juno/juno_common.c b/plat/arm/board/juno/juno_common.c
index 40b1a27..2e6b011 100644
--- a/plat/arm/board/juno/juno_common.c
+++ b/plat/arm/board/juno/juno_common.c
@@ -8,8 +8,8 @@
 
 /*
  * Table of memory regions for different BL stages to map using the MMU.
- * This doesn't include Trusted SRAM as arm_setup_page_tables() already
- * takes care of mapping it.
+ * This doesn't include Trusted SRAM as setup_page_tables() already takes care
+ * of mapping it.
  */
 #ifdef IMAGE_BL1
 const mmap_region_t plat_arm_mmap[] = {
diff --git a/plat/arm/board/juno/juno_topology.c b/plat/arm/board/juno/juno_topology.c
index 72bb92e..6d8fc05 100644
--- a/plat/arm/board/juno/juno_topology.c
+++ b/plat/arm/board/juno/juno_topology.c
@@ -9,6 +9,21 @@
 #include <plat_arm.h>
 #include <platform.h>
 #include "juno_def.h"
+#include "../../css/drivers/scmi/scmi.h"
+#include "../../css/drivers/mhu/css_mhu_doorbell.h"
+
+static scmi_channel_plat_info_t juno_scmi_plat_info = {
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhu_ring_doorbell,
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info()
+{
+	return &juno_scmi_plat_info;
+}
 
 /*
  * On Juno, the system power level is the highest power level.
diff --git a/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S
new file mode 100644
index 0000000..6eb01aa
--- /dev/null
+++ b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cortex_ares.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+
+	.globl	plat_arm_calc_core_pos
+	.globl	plat_reset_handler
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+	 *
+	 * Helper function to calculate the core position.
+	 * (ClusterId * N1SDP_MAX_CPUS_PER_CLUSTER * N1SDP_MAX_PE_PER_CPU) +
+	 * (CPUId * N1SDP_MAX_PE_PER_CPU) +
+	 * ThreadId
+	 *
+	 * which can be simplified as:
+	 *
+	 * ((ClusterId * N1SDP_MAX_CPUS_PER_CLUSTER + CPUId) *
+	 * N1SDP_MAX_PE_PER_CPU) + ThreadId
+	 * ------------------------------------------------------
+	 */
+
+func plat_arm_calc_core_pos
+	mov	x3, x0
+
+	/*
+	 * The MT bit in MPIDR is always set for n1sdp and the
+	 * affinity level 0 corresponds to thread affinity level.
+	 */
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	x4, #N1SDP_MAX_CPUS_PER_CLUSTER
+	madd	x1, x2, x4, x1
+	mov	x5, #N1SDP_MAX_PE_PER_CPU
+	madd	x0, x1, x5, x0
+	ret
+endfunc plat_arm_calc_core_pos
+
+	/* -----------------------------------------------------
+	 * void plat_reset_handler(void);
+	 *
+	 * Determine the CPU MIDR and disable power down bit for
+	 * that CPU.
+	 * -----------------------------------------------------
+	 */
+
+func plat_reset_handler
+	jump_if_cpu_midr CORTEX_ARES_MIDR, ARES
+	ret
+
+	/* -----------------------------------------------------
+	 * Disable CPU power down bit in power control register
+	 * -----------------------------------------------------
+	 */
+ARES:
+	mrs	x0, CORTEX_ARES_CPUPWRCTLR_EL1
+	bic	x0, x0, #CORTEX_ARES_CORE_PWRDN_EN_MASK
+	msr	CORTEX_ARES_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc plat_reset_handler
diff --git a/plat/arm/board/n1sdp/include/plat_macros.S b/plat/arm/board/n1sdp/include/plat_macros.S
new file mode 100644
index 0000000..fe9a66c
--- /dev/null
+++ b/plat/arm/board/n1sdp/include/plat_macros.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+#include <css_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+	.macro plat_crash_print_regs
+	.endm
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
new file mode 100644
index 0000000..d26f559
--- /dev/null
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arm_def.h>
+#include <board_css_def.h>
+#include <css_def.h>
+
+#if CSS_USE_SCMI_SDS_DRIVER
+#define N1SDP_SCMI_PAYLOAD_BASE			0x45400000
+#else
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE	0x45400000
+#endif
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE		0x00080000	/* 512 KB */
+#define PLAT_ARM_MAX_BL31_SIZE			0X20000
+
+
+/*******************************************************************************
+ * N1SDP topology related constants
+ ******************************************************************************/
+#define N1SDP_MAX_CPUS_PER_CLUSTER		2
+#define PLAT_ARM_CLUSTER_COUNT			2
+#define N1SDP_MAX_PE_PER_CPU			1
+
+#define PLATFORM_CORE_COUNT			(PLAT_ARM_CLUSTER_COUNT *	\
+						N1SDP_MAX_CPUS_PER_CLUSTER *	\
+						N1SDP_MAX_PE_PER_CPU)
+
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#define PLAT_ARM_MMAP_ENTRIES			3
+#define MAX_XLAT_TABLES				4
+
+#define PLATFORM_STACK_SIZE			0x400
+
+#define PLAT_ARM_NSTIMER_FRAME_ID		0
+#define PLAT_CSS_MHU_BASE			0x45000000
+#define PLAT_MAX_PWR_LVL			1
+
+#define PLAT_ARM_G1S_IRQS			ARM_G1S_IRQS,			\
+						CSS_IRQ_MHU
+#define PLAT_ARM_G0_IRQS			ARM_G0_IRQS
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp)		CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp)		ARM_G0_IRQ_PROPS(grp)
+
+
+#define N1SDP_DEVICE_BASE			(0x20000000)
+#define N1SDP_DEVICE_SIZE			(0x20000000)
+#define N1SDP_MAP_DEVICE			MAP_REGION_FLAT(	\
+						N1SDP_DEVICE_BASE,	\
+						N1SDP_DEVICE_SIZE,	\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE			0x30000000
+#define PLAT_ARM_GICC_BASE			0x2C000000
+#define PLAT_ARM_GICR_BASE			0x300C0000
+
+/* Platform ID address */
+#define SSC_VERSION				(SSC_REG_BASE + SSC_VERSION_OFFSET)
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
new file mode 100644
index 0000000..65aad9c
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "../../css/drivers/scmi/scmi.h"
+#include "../../css/drivers/mhu/css_mhu_doorbell.h"
+#include <platform_def.h>
+
+static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
+		.scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhu_ring_doorbell,
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info()
+{
+	return &n1sdp_scmi_plat_info;
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_interconnect.c b/plat/arm/board/n1sdp/n1sdp_interconnect.c
new file mode 100644
index 0000000..908f41c
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_interconnect.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/*
+ * For N1SDP which support FCM (with automatic interconnect enter/exit),
+ * we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers.
+ */
+
+/******************************************************************************
+ * Helper function to initialize ARM interconnect driver.
+ *****************************************************************************/
+void plat_arm_interconnect_init(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_plat.c b/plat/arm/board/n1sdp/n1sdp_plat.c
new file mode 100644
index 0000000..8c057c5
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_plat.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arm_def.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/*
+ * Table of regions to map using the MMU.
+ * Replace or extend the below regions as required
+ */
+
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	N1SDP_MAP_DEVICE,
+	SOC_CSS_MAP_DEVICE,
+	{0}
+};
+
diff --git a/plat/arm/board/n1sdp/n1sdp_security.c b/plat/arm/board/n1sdp/n1sdp_security.c
new file mode 100644
index 0000000..d2a187b
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_security.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * TZC programming is currently not done.
+ */
+void plat_arm_security_setup(void)
+{
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_topology.c b/plat/arm/board/n1sdp/n1sdp_topology.c
new file mode 100644
index 0000000..c3b4550
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_topology.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_arm.h>
+
+/* Topology */
+typedef struct n1sdp_topology {
+	const unsigned char *power_tree;
+	unsigned int plat_cluster_core_count;
+} n1sdp_topology_t;
+
+/*
+ * The power domain tree descriptor. The cluster power domains are
+ * arranged so that when the PSCI generic code creates the power domain tree,
+ * the indices of the CPU power domain nodes it allocates match the linear
+ * indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char n1sdp_pd_tree_desc[] = {
+	PLAT_ARM_CLUSTER_COUNT,
+	N1SDP_MAX_CPUS_PER_CLUSTER,
+	N1SDP_MAX_CPUS_PER_CLUSTER
+};
+
+/* Topology configuration for n1sdp */
+const n1sdp_topology_t n1sdp_topology = {
+	.power_tree = n1sdp_pd_tree_desc,
+	.plat_cluster_core_count = N1SDP_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return n1sdp_topology.power_tree;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+	return n1sdp_topology.plat_cluster_core_count;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
+	0, 1, 2, 3};
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
new file mode 100644
index 0000000..c9acb49
--- /dev/null
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+
+N1SDP_BASE		:=	plat/arm/board/n1sdp
+
+INTERCONNECT_SOURCES	:=	${N1SDP_BASE}/n1sdp_interconnect.c
+
+PLAT_INCLUDES		:=	-I${N1SDP_BASE}/include
+
+
+N1SDP_CPU_SOURCES	:=	lib/cpus/aarch64/cortex_ares.S
+
+
+N1SDP_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v3/gicv3_main.c		\
+				drivers/arm/gic/v3/gicv3_helpers.c	\
+				plat/common/plat_gicv3.c		\
+				plat/arm/common/arm_gicv3.c		\
+				drivers/arm/gic/v3/gic600.c
+
+PLAT_BL_COMMON_SOURCES	:=	${N1SDP_BASE}/n1sdp_plat.c	        \
+				${N1SDP_BASE}/aarch64/n1sdp_helper.S
+
+
+BL31_SOURCES		:=	${N1SDP_CPU_SOURCES}			\
+				${INTERCONNECT_SOURCES}			\
+				${N1SDP_GIC_SOURCES}			\
+				${N1SDP_BASE}/n1sdp_bl31_setup.c	        \
+				${N1SDP_BASE}/n1sdp_topology.c	        \
+				${N1SDP_BASE}/n1sdp_security.c
+
+
+# TF-A not required to load the SCP Images
+override CSS_LOAD_SCP_IMAGES	  	:=	0
+
+# BL1/BL2 Image not a part of the capsule Image for n1sdp
+override NEED_BL1		  	:=	no
+override NEED_BL2		  	:=	no
+override NEED_BL2U		  	:=	no
+
+#TFA for n1sdp starts from BL31
+override RESET_TO_BL31            	:=	1
+
+# 32 bit mode not supported
+override CTX_INCLUDE_AARCH32_REGS 	:=	0
+
+override ARM_PLAT_MT              	:=	1
+
+# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the
+# SCP during power management operations and for SCP RAM Firmware transfer.
+CSS_USE_SCMI_SDS_DRIVER		  	:=	1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY			:=	1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM			:=	0
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/soc/common/soc_css.mk
+include plat/arm/board/common/board_common.mk
+
diff --git a/plat/arm/board/sgi575/fdts/sgi575.dts b/plat/arm/board/sgi575/fdts/sgi575.dts
new file mode 100644
index 0000000..1e1ea14
--- /dev/null
+++ b/plat/arm/board/sgi575/fdts/sgi575.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+	/* compatible string */
+	compatible = "arm,sgi575";
+
+	/*
+	 * Place holder for system-id node with default values. The
+	 * value of platform-id and config-id will be set to the
+	 * correct values during the BL2 stage of boot.
+	 */
+	system-id {
+		platform-id = <0x0>;
+		config-id = <0x0>;
+	};
+};
diff --git a/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
similarity index 100%
rename from plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts
rename to plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
new file mode 100644
index 0000000..1870fc7
--- /dev/null
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <sgi_base_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT		2
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER	4
+#define CSS_SGI_MAX_PE_PER_CPU		1
+
+#define PLAT_CSS_MHU_BASE		0x45000000
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index 078f393..8df8b12 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -6,9 +6,31 @@
 
 include plat/arm/css/sgi/sgi-common.mk
 
+SGI575_BASE		=	plat/arm/board/sgi575
+
+PLAT_INCLUDES		+=	-I${SGI575_BASE}/include/
+
+SGI_CPU_SOURCES		:=	lib/cpus/aarch64/cortex_a75.S
+
+BL1_SOURCES		+=	${SGI_CPU_SOURCES}
+
 BL2_SOURCES		+=	lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
-BL31_SOURCES		+=	drivers/cfi/v2m/v2m_flash.c		\
+BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				drivers/cfi/v2m/v2m_flash.c		\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
+
+FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}.dts
+HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config))
diff --git a/plat/arm/board/sgiclarka/fdts/sgiclarka.dts b/plat/arm/board/sgiclarka/fdts/sgiclarka.dts
new file mode 100644
index 0000000..43bd856
--- /dev/null
+++ b/plat/arm/board/sgiclarka/fdts/sgiclarka.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+	/* compatible string */
+	compatible = "arm,sgi-clark";
+
+	/*
+	 * Place holder for system-id node with default values. The
+	 * value of platform-id and config-id will be set to the
+	 * correct values during the BL2 stage of boot.
+	 */
+	system-id {
+		platform-id = <0x0>;
+		config-id = <0x0>;
+	};
+};
diff --git a/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts
similarity index 100%
copy from plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts
copy to plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts
diff --git a/plat/arm/board/sgiclarka/include/platform_def.h b/plat/arm/board/sgiclarka/include/platform_def.h
new file mode 100644
index 0000000..abc48d8
--- /dev/null
+++ b/plat/arm/board/sgiclarka/include/platform_def.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <sgi_base_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT		2
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER	4
+#define CSS_SGI_MAX_PE_PER_CPU		1
+
+#define PLAT_CSS_MHU_BASE		0x45400000
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgiclarka/platform.mk b/plat/arm/board/sgiclarka/platform.mk
new file mode 100644
index 0000000..fc2f766
--- /dev/null
+++ b/plat/arm/board/sgiclarka/platform.mk
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include plat/arm/css/sgi/sgi-common.mk
+
+SGICLARKA_BASE		=	plat/arm/board/sgiclarka
+
+PLAT_INCLUDES		+=	-I${SGICLARKA_BASE}/include/
+
+SGI_CPU_SOURCES		:=	lib/cpus/aarch64/cortex_ares.S
+
+BL1_SOURCES		+=	${SGI_CPU_SOURCES}
+
+BL2_SOURCES		+=	lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				drivers/cfi/v2m/v2m_flash.c		\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${SGICLARKA_BASE}/fdts/${PLAT}_tb_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
+
+FDT_SOURCES		+=	${SGICLARKA_BASE}/fdts/${PLAT}.dts
+HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config))
+
+override CTX_INCLUDE_AARCH32_REGS	:= 0
diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S
index 752929d..0672058 100644
--- a/plat/arm/common/aarch64/arm_helpers.S
+++ b/plat/arm/common/aarch64/arm_helpers.S
@@ -8,9 +8,9 @@
 
 	.weak	plat_arm_calc_core_pos
 	.weak	plat_my_core_pos
-	.weak	plat_crash_console_init
-	.weak	plat_crash_console_putc
-	.weak	plat_crash_console_flush
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
 	.globl	platform_mem_init
 
 
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 717e96f..f760e18 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -6,7 +6,6 @@
 
 #include <arch.h>
 #include <arm_def.h>
-#include <arm_xlat_tables.h>
 #include <assert.h>
 #include <bl1.h>
 #include <bl_common.h>
@@ -15,6 +14,8 @@
 #include <platform_def.h>
 #include <sp805.h>
 #include <utils.h>
+#include <xlat_tables_compat.h>
+
 #include "../../../bl1/bl1_private.h"
 
 /* Weak definitions may be overridden in specific ARM standard platform */
@@ -122,7 +123,7 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 #ifdef AARCH32
 	enable_mmu_svc_mon(0);
 #else
diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c
index c67ab49..4f5e6a9 100644
--- a/plat/arm/common/arm_bl2_el3_setup.c
+++ b/plat/arm/common/arm_bl2_el3_setup.c
@@ -79,7 +79,7 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 
 #ifdef AARCH32
 	enable_mmu_svc_mon(0);
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index d31f6dc..628a50d 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -125,7 +125,7 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 
 #ifdef AARCH32
 	enable_mmu_svc_mon(0);
diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c
index b518f0f..3848aa0 100644
--- a/plat/arm/common/arm_bl2u_setup.c
+++ b/plat/arm/common/arm_bl2u_setup.c
@@ -80,7 +80,7 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 
 #ifdef AARCH32
 	enable_mmu_svc_mon(0);
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index e218c2f..1b05f46 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -16,7 +16,7 @@
 #include <platform.h>
 #include <ras.h>
 #include <utils.h>
-#include <arm_xlat_tables.h>
+#include <xlat_tables_compat.h>
 
 /*
  * Placeholder variables for copying the arguments that have been passed to
@@ -25,11 +25,13 @@
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
+#if !RESET_TO_BL31
 /*
  * Check that BL31_BASE is above ARM_TB_FW_CONFIG_LIMIT. The reserved page
  * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
  */
 CASSERT(BL31_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl31_base_overflows);
+#endif
 
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak bl31_early_platform_setup2
@@ -38,8 +40,8 @@
 #pragma weak bl31_plat_get_next_image_ep_info
 
 #define MAP_BL31_TOTAL		MAP_REGION_FLAT(			\
-					BL31_BASE,			\
-					BL31_END - BL31_BASE,		\
+					BL31_START,			\
+					BL31_END - BL31_START,		\
 					MT_MEMORY | MT_RW | MT_SECURE)
 #if RECLAIM_INIT_CODE
 IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE);
@@ -302,7 +304,7 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 
 	enable_mmu_el3(0);
 
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index a21d189..6b14785 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -5,7 +5,6 @@
  */
 #include <arch.h>
 #include <arch_helpers.h>
-#include <arm_xlat_tables.h>
 #include <assert.h>
 #include <debug.h>
 #include <mmio.h>
@@ -14,6 +13,7 @@
 #include <platform_def.h>
 #include <romlib.h>
 #include <secure_partition.h>
+#include <xlat_tables_compat.h>
 
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak plat_get_ns_image_entrypoint
@@ -32,42 +32,6 @@
 #endif
 }
 
-/*
- * Set up the page tables for the generic and platform-specific memory regions.
- * The size of the Trusted SRAM seen by the BL image must be specified as well
- * as an array specifying the generic memory regions which can be;
- * - Code section;
- * - Read-only data section;
- * - Init code section, if applicable
- * - Coherent memory region, if applicable.
- */
-
-void __init arm_setup_page_tables(const mmap_region_t bl_regions[],
-			   const mmap_region_t plat_regions[])
-{
-#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
-	const mmap_region_t *regions = bl_regions;
-
-	while (regions->size != 0U) {
-		VERBOSE("Region: 0x%lx - 0x%lx has attributes 0x%x\n",
-				regions->base_va,
-				(regions->base_va + regions->size),
-				regions->attr);
-		regions++;
-	}
-#endif
-	/*
-	 * Map the Trusted SRAM with appropriate memory attributes.
-	 * Subsequent mappings will adjust the attributes for specific regions.
-	 */
-	mmap_add(bl_regions);
-	/* Now (re-)map the platform-specific memory regions */
-	mmap_add(plat_regions);
-
-	/* Create the page tables to reflect the above mappings */
-	init_xlat_tables();
-}
-
 uintptr_t plat_get_ns_image_entrypoint(void)
 {
 #ifdef PRELOADED_BL33_BASE
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 3fb1eff..23777fb 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -130,6 +130,11 @@
 $(eval $(call assert_boolean,ARM_CRYPTOCELL_INTEG))
 $(eval $(call add_define,ARM_CRYPTOCELL_INTEG))
 
+# Enable PIE support for RESET_TO_BL31 case
+ifeq (${RESET_TO_BL31},1)
+    ENABLE_PIE			:=	1
+endif
+
 # CryptoCell integration relies on coherent buffers for passing data from
 # the AP CPU to the CryptoCell
 ifeq (${ARM_CRYPTOCELL_INTEG},1)
diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c
index e9e8a74..a43bff3 100644
--- a/plat/arm/common/arm_gicv3.c
+++ b/plat/arm/common/arm_gicv3.c
@@ -10,6 +10,7 @@
 #include <plat_arm.h>
 #include <platform.h>
 #include <platform_def.h>
+#include <utils.h>
 
 /******************************************************************************
  * The following functions are defined as weak to allow a platform to override
@@ -33,10 +34,16 @@
 
 /*
  * We save and restore the GICv3 context on system suspend. Allocate the
- * data in the designated EL3 Secure carve-out memory
+ * data in the designated EL3 Secure carve-out memory. The `volatile`
+ * is used to prevent the compiler from removing the gicv3 contexts even
+ * though the DEFINE_LOAD_SYM_ADDR creates a dummy reference to it.
  */
-static gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram");
-static gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram");
+static volatile gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram");
+static volatile gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram");
+
+/* Define accessor function to get reference to the GICv3 context */
+DEFINE_LOAD_SYM_ADDR(rdist_ctx)
+DEFINE_LOAD_SYM_ADDR(dist_ctx)
 
 /*
  * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
@@ -134,6 +141,10 @@
  *****************************************************************************/
 void plat_arm_gic_save(void)
 {
+	gicv3_redist_ctx_t * const rdist_context =
+			(gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx);
+	gicv3_dist_ctx_t * const dist_context =
+			(gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx);
 
 	/*
 	 * If an ITS is available, save its context before
@@ -149,10 +160,10 @@
 	 * we only need to save the context of the CPU that is issuing
 	 * the SYSTEM SUSPEND call, i.e. the current CPU.
 	 */
-	gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+	gicv3_rdistif_save(plat_my_core_pos(), rdist_context);
 
 	/* Save the GIC Distributor context */
-	gicv3_distif_save(&dist_ctx);
+	gicv3_distif_save(dist_context);
 
 	/*
 	 * From here, all the components of the GIC can be safely powered down
@@ -163,8 +174,13 @@
 
 void plat_arm_gic_resume(void)
 {
+	const gicv3_redist_ctx_t *rdist_context =
+			(gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx);
+	const gicv3_dist_ctx_t *dist_context =
+			(gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx);
+
 	/* Restore the GIC Distributor context */
-	gicv3_distif_init_restore(&dist_ctx);
+	gicv3_distif_init_restore(dist_context);
 
 	/*
 	 * Restore the GIC Redistributor and ITS contexts after the
@@ -172,7 +188,7 @@
 	 * we only need to restore the context of the CPU that issued
 	 * the SYSTEM SUSPEND call.
 	 */
-	gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+	gicv3_rdistif_init_restore(plat_my_core_pos(), rdist_context);
 
 	/*
 	 * If an ITS is available, restore its context after
diff --git a/plat/arm/common/arm_sip_svc.c b/plat/arm/common/arm_sip_svc.c
index e450c6f..e482a89 100644
--- a/plat/arm/common/arm_sip_svc.c
+++ b/plat/arm/common/arm_sip_svc.c
@@ -58,7 +58,7 @@
 
 		/* Validate supplied entry point */
 		pc = (u_register_t) ((x1 << 32) | (uint32_t) x2);
-		if (arm_validate_ns_entrypoint(pc))
+		if (arm_validate_ns_entrypoint(pc) != 0)
 			SMC_RET1(handle, STATE_SW_E_PARAM);
 
 		/*
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index a32736c..2ae084c 100644
--- a/plat/arm/common/arm_tzc400.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -24,7 +24,7 @@
 void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions)
 {
 #ifndef EL3_PAYLOAD_BASE
-	int region_index = 1;
+	unsigned int region_index = 1U;
 	const arm_tzc_regions_info_t *p;
 	const arm_tzc_regions_info_t init_tzc_regions[] = {
 		ARM_TZC_REGIONS_DEF,
@@ -55,7 +55,7 @@
 		region_index++;
 	}
 
-	INFO("Total %d regions set.\n", region_index);
+	INFO("Total %u regions set.\n", region_index);
 
 #else /* if defined(EL3_PAYLOAD_BASE) */
 
diff --git a/plat/arm/common/arm_tzc_dmc500.c b/plat/arm/common/arm_tzc_dmc500.c
index 8cb81e7..6bd771b 100644
--- a/plat/arm/common/arm_tzc_dmc500.c
+++ b/plat/arm/common/arm_tzc_dmc500.c
@@ -20,7 +20,7 @@
 			const arm_tzc_regions_info_t *tzc_regions)
 {
 #ifndef EL3_PAYLOAD_BASE
-	int region_index = 1;
+	unsigned int region_index = 1U;
 	const arm_tzc_regions_info_t *p;
 	const arm_tzc_regions_info_t init_tzc_regions[] = {
 		ARM_TZC_REGIONS_DEF,
@@ -50,7 +50,7 @@
 		region_index++;
 	}
 
-	INFO("Total %d regions set.\n", region_index);
+	INFO("Total %u regions set.\n", region_index);
 
 #else
 	/* Allow secure access only to DRAM for EL3 payloads */
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index b8234c1..e151073 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -208,7 +208,7 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 
 	enable_mmu_svc_mon(0);
 }
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
index 2d42d8e..3cf8825 100644
--- a/plat/arm/common/tsp/arm_tsp_setup.c
+++ b/plat/arm/common/tsp/arm_tsp_setup.c
@@ -85,6 +85,6 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 	enable_mmu_el1(0);
 }
diff --git a/plat/arm/css/common/aarch64/css_helpers.S b/plat/arm/css/common/aarch64/css_helpers.S
index 59d9206..5096d8d 100644
--- a/plat/arm/css/common/aarch64/css_helpers.S
+++ b/plat/arm/css/common/aarch64/css_helpers.S
@@ -108,7 +108,7 @@
 func plat_is_my_cpu_primary
 	mov	x9, x30
 	bl	plat_my_core_pos
-	ldr	x1, =SCP_BOOT_CFG_ADDR
+	mov_imm	x1, SCP_BOOT_CFG_ADDR
 	ldr	x1, [x1]
 	ubfx	x1, x1, #PLAT_CSS_PRIMARY_CPU_SHIFT, \
 			#PLAT_CSS_PRIMARY_CPU_BIT_WIDTH
diff --git a/plat/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h
index 71a8c2d..7f89229 100644
--- a/plat/arm/css/drivers/scmi/scmi.h
+++ b/plat/arm/css/drivers/scmi/scmi.h
@@ -159,4 +159,7 @@
 int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr);
 int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr);
 
+/* API to get the platform specific SCMI channel information. */
+scmi_channel_plat_info_t *plat_css_get_scmi_info();
+
 #endif	/* __CSS_SCMI_H__ */
diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c
index 9297e9f..956f583 100644
--- a/plat/arm/css/drivers/scp/css_pm_scmi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scmi.c
@@ -13,7 +13,6 @@
 #include <platform.h>
 #include <string.h>
 #include "../scmi/scmi.h"
-#include "../mhu/css_mhu_doorbell.h"
 #include "css_scp.h"
 
 /*
@@ -298,14 +297,6 @@
 	css_scp_system_off(SCMI_SYS_PWR_COLD_RESET);
 }
 
-static scmi_channel_plat_info_t plat_css_scmi_plat_info = {
-		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
-		.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
-		.db_preserve_mask = 0xfffffffe,
-		.db_modify_mask = 0x1,
-		.ring_doorbell = &mhu_ring_doorbell,
-};
-
 static int scmi_ap_core_init(scmi_channel_t *ch)
 {
 #if PROGRAMMABLE_RESET_ADDRESS
@@ -330,7 +321,7 @@
 
 void __init plat_arm_pwrc_setup(void)
 {
-	channel.info = &plat_css_scmi_plat_info;
+	channel.info = plat_css_get_scmi_info();
 	channel.lock = ARM_SCMI_LOCK_GET_INSTANCE;
 	scmi_handle = scmi_init(&channel);
 	if (scmi_handle == NULL) {
diff --git a/plat/arm/css/sgi/aarch64/sgi_helper.S b/plat/arm/css/sgi/aarch64/sgi_helper.S
index 27bae43..d79f1aa 100644
--- a/plat/arm/css/sgi/aarch64/sgi_helper.S
+++ b/plat/arm/css/sgi/aarch64/sgi_helper.S
@@ -8,6 +8,7 @@
 #include <asm_macros.S>
 #include <platform_def.h>
 #include <cortex_a75.h>
+#include <cortex_ares.h>
 #include <cpu_macros.S>
 
 	.globl	plat_arm_calc_core_pos
@@ -58,6 +59,7 @@
 	 */
 func plat_reset_handler
 	jump_if_cpu_midr CORTEX_A75_MIDR, A75
+	jump_if_cpu_midr CORTEX_ARES_MIDR, ARES
 	ret
 
 	/* -----------------------------------------------------
@@ -70,4 +72,11 @@
 	msr	CORTEX_A75_CPUPWRCTLR_EL1, x0
 	isb
 	ret
+
+ARES:
+	mrs	x0, CORTEX_ARES_CPUPWRCTLR_EL1
+	bic	x0, x0, #CORTEX_ARES_CORE_PWRDN_EN_MASK
+	msr	CORTEX_ARES_CPUPWRCTLR_EL1, x0
+	isb
+	ret
 endfunc plat_reset_handler
diff --git a/plat/arm/css/sgi/fdts/sgi575.dts b/plat/arm/css/sgi/fdts/sgi575.dts
deleted file mode 100644
index be9920c..0000000
--- a/plat/arm/css/sgi/fdts/sgi575.dts
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-/ {
-	/* compatible string */
-	compatible = "arm,sgi575";
-};
diff --git a/plat/arm/css/sgi/include/platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
similarity index 96%
rename from plat/arm/css/sgi/include/platform_def.h
rename to plat/arm/css/sgi/include/sgi_base_platform_def.h
index 6297490..90eb336 100644
--- a/plat/arm/css/sgi/include/platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef PLATFORM_DEF_H
-#define PLATFORM_DEF_H
+#ifndef SGI_BASE_PLATFORM_DEF_H
+#define SGI_BASE_PLATFORM_DEF_H
 
 #include <arm_def.h>
 #include <arm_spm_def.h>
@@ -17,11 +17,6 @@
 #include <v2m_def.h>
 #include <xlat_tables_defs.h>
 
-#define CSS_SGI_MAX_CPUS_PER_CLUSTER	4
-
-/* CPU topology */
-#define PLAT_ARM_CLUSTER_COUNT		2
-#define CSS_SGI_MAX_PE_PER_CPU		1
 #define PLATFORM_CORE_COUNT		(PLAT_ARM_CLUSTER_COUNT *	\
 					CSS_SGI_MAX_CPUS_PER_CLUSTER * \
 					CSS_SGI_MAX_PE_PER_CPU)
@@ -118,8 +113,6 @@
 
 #define PLAT_ARM_NSTIMER_FRAME_ID	0
 
-#define PLAT_CSS_MHU_BASE		0x45000000
-
 #define PLAT_ARM_TRUSTED_ROM_BASE	0x0
 #define PLAT_ARM_TRUSTED_ROM_SIZE	0x00080000	/* 512KB */
 
@@ -216,4 +209,4 @@
 					 V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
 
 
-#endif /* PLATFORM_DEF_H */
+#endif /* SGI_BASE_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgi/include/sgi_plat_config.h b/plat/arm/css/sgi/include/sgi_plat_config.h
deleted file mode 100644
index 9b29d74..0000000
--- a/plat/arm/css/sgi/include/sgi_plat_config.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __SGI_PLAT_CONFIG_H__
-#define __SGI_PLAT_CONFIG_H__
-
-#include <ccn.h>
-#include <gicv3.h>
-
-/* The type of interconnect */
-typedef enum {
-	ARM_CCI = 0,
-	ARM_CCN,
-	ARM_CMN
-} css_inteconn_type_t;
-
-typedef ccn_desc_t inteconn_desc_t;
-
-/* Interconnect configurations */
-typedef struct css_inteconn_config {
-	css_inteconn_type_t ip_type;
-	const inteconn_desc_t *plat_inteconn_desc;
-} css_inteconn_config_t;
-
-/* Topology configurations */
-typedef struct css_topology {
-	const unsigned char *power_tree;
-	unsigned int plat_cluster_core_count;
-} css_topology_t;
-
-typedef struct css_plat_config {
-	const gicv3_driver_data_t *gic_data;
-	const css_inteconn_config_t *inteconn;
-	const css_topology_t *topology;
-} css_plat_config_t;
-
-void plat_config_init(void);
-css_plat_config_t *get_plat_config(void);
-
-#endif /* __SGI_PLAT_CONFIG_H__ */
diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h
index 5698d0a..dea580b 100644
--- a/plat/arm/css/sgi/include/sgi_variant.h
+++ b/plat/arm/css/sgi/include/sgi_variant.h
@@ -4,10 +4,21 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __SGI_VARIANT_H__
-#define __SGI_VARIANT_H__
+#ifndef SGI_VARIANT_H
+#define SGI_VARIANT_H
 
 /* SSC_VERSION values for SGI575 */
 #define SGI575_SSC_VER_PART_NUM		0x0783
 
-#endif /* __SGI_VARIANT_H__ */
+/* SID Version values for SGI-Clark */
+#define SGI_CLARK_SID_VER_PART_NUM		0x0786
+
+/* Structure containing SGI platform variant information */
+typedef struct sgi_platform_info {
+	unsigned int platform_id;	/* Part Number of the platform */
+	unsigned int config_id;		/* Config Id of the platform */
+} sgi_platform_info_t;
+
+extern sgi_platform_info_t sgi_plat_info;
+
+#endif /* SGI_VARIANT_H */
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 24f03dd..d6e5448 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -22,8 +22,6 @@
 
 PLAT_INCLUDES		+=	-I${CSS_ENT_BASE}/include
 
-ENT_CPU_SOURCES		:=	lib/cpus/aarch64/cortex_a75.S
-
 ENT_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
@@ -35,38 +33,20 @@
 PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c	\
 				${CSS_ENT_BASE}/aarch64/sgi_helper.S
 
-BL1_SOURCES		+=	${INTERCONNECT_SOURCES}			\
-				${ENT_CPU_SOURCES}			\
-				${CSS_ENT_BASE}/sgi_bl1_setup.c	\
-				${CSS_ENT_BASE}/sgi_plat_config.c
+BL1_SOURCES		+=	${INTERCONNECT_SOURCES}
 
 BL2_SOURCES		+=	${CSS_ENT_BASE}/sgi_security.c		\
 				${CSS_ENT_BASE}/sgi_image_load.c
 
-BL31_SOURCES		+=	${ENT_CPU_SOURCES}			\
-				${INTERCONNECT_SOURCES}			\
+BL31_SOURCES		+=	${INTERCONNECT_SOURCES}			\
 				${ENT_GIC_SOURCES}			\
 				${CSS_ENT_BASE}/sgi_bl31_setup.c	\
-				${CSS_ENT_BASE}/sgi_topology.c	\
-				${CSS_ENT_BASE}/sgi_plat_config.c
+				${CSS_ENT_BASE}/sgi_topology.c
 
 ifeq (${RAS_EXTENSION},1)
 BL31_SOURCES		+=	${CSS_ENT_BASE}/sgi_ras.c
 endif
 
-# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${CSS_ENT_BASE}/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
-
-# Add the TB_FW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
-
-FDT_SOURCES		+=	${CSS_ENT_BASE}/fdts/${PLAT}.dts
-HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
-
-# Add the HW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config))
-
 ifneq (${RESET_TO_BL31},0)
   $(error "Using BL31 as the reset vector is not supported on ${PLATFORM} platform. \
   Please set RESET_TO_BL31 to 0.")
diff --git a/plat/arm/css/sgi/sgi_bl1_setup.c b/plat/arm/css/sgi/sgi_bl1_setup.c
deleted file mode 100644
index d3d98d9..0000000
--- a/plat/arm/css/sgi/sgi_bl1_setup.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <bl_common.h>
-#include <debug.h>
-#include <plat_arm.h>
-#include <sgi_plat_config.h>
-#include <soc_css.h>
-
-void bl1_early_platform_setup(void)
-{
-	/* Initialize the platform configuration structure */
-	plat_config_init();
-
-	arm_bl1_early_platform_setup();
-}
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index 09f493e..ce85026 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -4,17 +4,91 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
 #include <bl_common.h>
 #include <debug.h>
+#include <libfdt.h>
 #include <plat_arm.h>
-#include <sgi_plat_config.h>
 #include <sgi_ras.h>
+#include <sgi_variant.h>
+#include "../../css/drivers/scmi/scmi.h"
+#include "../../css/drivers/mhu/css_mhu_doorbell.h"
+
+sgi_platform_info_t sgi_plat_info;
+
+static scmi_channel_plat_info_t sgi575_scmi_plat_info = {
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhu_ring_doorbell,
+};
+
+static scmi_channel_plat_info_t sgi_clark_scmi_plat_info = {
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhuv2_ring_doorbell,
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info()
+{
+	if (sgi_plat_info.platform_id == SGI_CLARK_SID_VER_PART_NUM)
+		return &sgi_clark_scmi_plat_info;
+	else if (sgi_plat_info.platform_id == SGI575_SSC_VER_PART_NUM)
+		return &sgi575_scmi_plat_info;
+	else
+		panic();
+};
+
+/*******************************************************************************
+ * This function sets the sgi_platform_id and sgi_config_id
+ ******************************************************************************/
+int sgi_identify_platform(unsigned long hw_config)
+{
+	void *fdt;
+	int nodeoffset;
+	const unsigned int *property;
+
+	fdt = (void *)hw_config;
+
+	/* Check the validity of the fdt */
+	assert(fdt_check_header(fdt) == 0);
+
+	nodeoffset = fdt_subnode_offset(fdt, 0, "system-id");
+	if (nodeoffset < 0) {
+		ERROR("Failed to get system-id node offset\n");
+		return -1;
+	}
+
+	property = fdt_getprop(fdt, nodeoffset, "platform-id", NULL);
+	if (property == NULL) {
+		ERROR("Failed to get platform-id property\n");
+		return -1;
+	}
+
+	sgi_plat_info.platform_id = fdt32_to_cpu(*property);
+
+	property = fdt_getprop(fdt, nodeoffset, "config-id", NULL);
+	if (property == NULL) {
+		ERROR("Failed to get config-id property\n");
+		return -1;
+	}
+
+	sgi_plat_info.config_id = fdt32_to_cpu(*property);
+
+	return 0;
+}
 
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	/* Initialize the platform configuration structure */
-	plat_config_init();
+	int ret;
+
+	ret = sgi_identify_platform(arg2);
+	if (ret == -1)
+		panic();
 
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 }
diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c
index 09403f8..d97583e 100644
--- a/plat/arm/css/sgi/sgi_image_load.c
+++ b/plat/arm/css/sgi/sgi_image_load.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <arch_helpers.h>
 #include <debug.h>
 #include <desc_image_load.h>
 #include <libfdt.h>
@@ -13,6 +14,7 @@
  * This function inserts Platform information via device tree nodes as,
  * system-id {
  *    platform-id = <0>;
+ *    config-id = <0>;
  * }
  ******************************************************************************/
 static int plat_sgi_append_config_node(void)
@@ -20,7 +22,7 @@
 	bl_mem_params_node_t *mem_params;
 	void *fdt;
 	int nodeoffset, err;
-	unsigned int platid = 0;
+	unsigned int platid = 0, platcfg = 0;
 	char *platform_name;
 
 	mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
@@ -45,31 +47,38 @@
 	}
 
 	if (strcmp(platform_name, "arm,sgi575") == 0) {
-		platid = mmio_read_32(SSC_VERSION);
+		platid = mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK;
+		platcfg = (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT)
+				& SSC_VERSION_CONFIG_MASK;
+	} else if (strcmp(platform_name, "arm,sgi-clark") == 0) {
+		platid = mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+				& SID_SYSTEM_ID_PART_NUM_MASK;
+		platcfg = mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
 	} else {
 		WARN("Invalid platform\n");
 		return -1;
 	}
 
-	/* Increase DTB blob by 512 byte */
-	err = fdt_open_into(fdt, fdt, mem_params->image_info.image_size + 512);
-	if (err < 0) {
-		ERROR("Failed to open HW_CONFIG DTB\n");
-		return -1;
-	}
-
-	/* Create "/system-id" node */
-	nodeoffset = fdt_add_subnode(fdt, 0, "system-id");
+	nodeoffset = fdt_subnode_offset(fdt, 0, "system-id");
 	if (nodeoffset < 0) {
-		ERROR("Failed to add node system-id\n");
+		ERROR("Failed to get system-id node offset\n");
 		return -1;
 	}
 
 	err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid);
 	if (err < 0) {
-		ERROR("Failed to add node platform-id\n");
+		ERROR("Failed to set platform-id\n");
 		return -1;
 	}
+
+	err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg);
+	if (err < 0) {
+		ERROR("Failed to set config-id\n");
+		return -1;
+	}
+
+	flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
+
 	return 0;
 }
 
diff --git a/plat/arm/css/sgi/sgi_interconnect.c b/plat/arm/css/sgi/sgi_interconnect.c
index 325b5b1..074f8a2 100644
--- a/plat/arm/css/sgi/sgi_interconnect.c
+++ b/plat/arm/css/sgi/sgi_interconnect.c
@@ -6,7 +6,6 @@
 
 #include <arch_helpers.h>
 #include <debug.h>
-#include <sgi_plat_config.h>
 
 /*
  * For SGI575 which support FCM (with automatic interconnect enter/exit),
diff --git a/plat/arm/css/sgi/sgi_plat_config.c b/plat/arm/css/sgi/sgi_plat_config.c
deleted file mode 100644
index 29b99a3..0000000
--- a/plat/arm/css/sgi/sgi_plat_config.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <debug.h>
-#include <plat_arm.h>
-#include <platform_def.h>
-#include <sgi_variant.h>
-#include <sgi_plat_config.h>
-#include <string.h>
-
-static css_plat_config_t *css_plat_info;
-
-/* GIC */
-/* The GICv3 driver only needs to be initialized in EL3 */
-uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
-
-/* Interconnect configuration for SGI575 */
-const css_inteconn_config_t sgi575_inteconn = {
-	.ip_type = ARM_CMN,
-	.plat_inteconn_desc = NULL
-};
-
-/* Configuration structure for SGI575 */
-css_plat_config_t sgi575_config = {
-	.inteconn = &sgi575_inteconn,
-};
-
-/*******************************************************************************
- * This function initializes the platform sturcture.
- ******************************************************************************/
-void plat_config_init(void)
-{
-	/* Get the platform configurations */
-	switch (GET_SGI_PART_NUM) {
-	case SGI575_SSC_VER_PART_NUM:
-		css_plat_info = &sgi575_config;
-		break;
-	default:
-		ERROR("Not a valid sgi variant!\n");
-		panic();
-	}
-}
-
-/*******************************************************************************
- * This function returns the platform structure pointer.
- ******************************************************************************/
-css_plat_config_t *get_plat_config(void)
-{
-	assert(css_plat_info != NULL);
-	return css_plat_info;
-}
diff --git a/plat/arm/css/sgi/sgi_topology.c b/plat/arm/css/sgi/sgi_topology.c
index 3f6357b..3b7a57a 100644
--- a/plat/arm/css/sgi/sgi_topology.c
+++ b/plat/arm/css/sgi/sgi_topology.c
@@ -5,7 +5,6 @@
  */
 
 #include <plat_arm.h>
-#include <sgi_plat_config.h>
 
 /* Topology */
 /*
@@ -20,18 +19,12 @@
 	CSS_SGI_MAX_CPUS_PER_CLUSTER
 };
 
-/* Topology configuration for sgi platform */
-const css_topology_t sgi_topology = {
-	.power_tree = sgi_pd_tree_desc,
-	.plat_cluster_core_count = CSS_SGI_MAX_CPUS_PER_CLUSTER
-};
-
 /*******************************************************************************
  * This function returns the topology tree information.
  ******************************************************************************/
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	return sgi_topology.power_tree;
+	return sgi_pd_tree_desc;
 }
 
 /*******************************************************************************
@@ -40,7 +33,7 @@
  ******************************************************************************/
 unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
 {
-	return sgi_topology.plat_cluster_core_count;
+	return CSS_SGI_MAX_CPUS_PER_CLUSTER;
 }
 
 /*******************************************************************************
diff --git a/plat/arm/css/sgm/sgm_bl31_setup.c b/plat/arm/css/sgm/sgm_bl31_setup.c
index a55176a..29c32e7 100644
--- a/plat/arm/css/sgm/sgm_bl31_setup.c
+++ b/plat/arm/css/sgm/sgm_bl31_setup.c
@@ -8,6 +8,21 @@
 #include <debug.h>
 #include <plat_arm.h>
 #include <sgm_plat_config.h>
+#include "../../css/drivers/scmi/scmi.h"
+#include "../../css/drivers/mhu/css_mhu_doorbell.h"
+
+static scmi_channel_plat_info_t sgm775_scmi_plat_info = {
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhu_ring_doorbell,
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info()
+{
+	return &sgm775_scmi_plat_info;
+}
 
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
diff --git a/plat/common/aarch32/crash_console_helpers.S b/plat/common/aarch32/crash_console_helpers.S
new file mode 100644
index 0000000..fc37c08
--- /dev/null
+++ b/plat/common/aarch32/crash_console_helpers.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * If a platform wishes to use the functions in this file it has to be added to
+ * the Makefile of the platform. It is not included in the common Makefile.
+ */
+
+#include <asm_macros.S>
+#include <console.h>
+
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
+
+#if MULTI_CONSOLE_API
+
+	/* -----------------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Use normal console by default. Switch it to crash
+	 * mode so serial consoles become active again.
+	 * NOTE: This default implementation will only work for
+	 * crashes that occur after a normal console (marked
+	 * valid for the crash state) has been registered with
+	 * the console framework. To debug crashes that occur
+	 * earlier, the platform has to override these functions
+	 * with an implementation that initializes a console
+	 * driver with hardcoded parameters. See
+	 * docs/porting-guide.rst for more information.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_init
+#if defined(IMAGE_BL1)
+	/*
+	 * BL1 code can possibly crash so early that the data segment is not yet
+	 * accessible. Don't risk undefined behavior by trying to run the normal
+	 * console framework. Platforms that want to debug BL1 will need to
+	 * override this with custom functions that can run from registers only.
+	 */
+	mov	r0, #0
+	bx	lr
+#else	/* IMAGE_BL1 */
+	mov	r3, lr
+	mov	r0, #CONSOLE_FLAG_CRASH
+	bl	console_switch_state
+	mov	r0, #1
+	bx	r3
+#endif
+endfunc plat_crash_console_init
+
+	/* -----------------------------------------------------
+	 * void plat_crash_console_putc(int character)
+	 * Output through the normal console by default.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_putc
+	b	console_putc
+endfunc plat_crash_console_putc
+
+	/* -----------------------------------------------------
+	 * void plat_crash_console_flush(void)
+	 * Flush normal console by default.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_flush
+	b	console_flush
+endfunc plat_crash_console_flush
+
+#else	/* MULTI_CONSOLE_API */
+
+	/* -----------------------------------------------------
+	 * In the old API these are all no-op stubs that need to
+	 * be overridden by the platform to be useful.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_init
+	mov	r0, #0
+	bx	lr
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+	bx	lr
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+	bx	lr
+endfunc plat_crash_console_flush
+
+#endif
diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S
index d618539..e1e2a6f 100644
--- a/plat/common/aarch32/platform_helpers.S
+++ b/plat/common/aarch32/platform_helpers.S
@@ -8,9 +8,11 @@
 #include <asm_macros.S>
 
 	.weak	plat_report_exception
+#if !ERROR_DEPRECATED
 	.weak	plat_crash_console_init
 	.weak	plat_crash_console_putc
 	.weak	plat_crash_console_flush
+#endif
 	.weak	plat_reset_handler
 	.weak	plat_disable_acp
 	.weak	bl1_plat_prepare_exit
@@ -26,6 +28,7 @@
 	bx	lr
 endfunc plat_report_exception
 
+#if !ERROR_DEPRECATED
 	/* -----------------------------------------------------
 	 * Placeholder function which should be redefined by
 	 * each platform.
@@ -54,6 +57,7 @@
 	mov	r0, #0
 	bx	lr
 endfunc plat_crash_console_flush
+#endif
 
 	/* -----------------------------------------------------
 	 * Placeholder function which should be redefined by
diff --git a/plat/common/aarch64/crash_console_helpers.S b/plat/common/aarch64/crash_console_helpers.S
new file mode 100644
index 0000000..5af8db2
--- /dev/null
+++ b/plat/common/aarch64/crash_console_helpers.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * If a platform wishes to use the functions in this file it has to be added to
+ * the Makefile of the platform. It is not included in the common Makefile.
+ */
+
+#include <asm_macros.S>
+#include <console.h>
+
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
+
+#if MULTI_CONSOLE_API
+
+	/* -----------------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Use normal console by default. Switch it to crash
+	 * mode so serial consoles become active again.
+	 * NOTE: This default implementation will only work for
+	 * crashes that occur after a normal console (marked
+	 * valid for the crash state) has been registered with
+	 * the console framework. To debug crashes that occur
+	 * earlier, the platform has to override these functions
+	 * with an implementation that initializes a console
+	 * driver with hardcoded parameters. See
+	 * docs/porting-guide.rst for more information.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_init
+#if defined(IMAGE_BL1)
+	/*
+	 * BL1 code can possibly crash so early that the data segment is not yet
+	 * accessible. Don't risk undefined behavior by trying to run the normal
+	 * console framework. Platforms that want to debug BL1 will need to
+	 * override this with custom functions that can run from registers only.
+	 */
+	mov	x0, #0
+	ret
+#else	/* IMAGE_BL1 */
+	mov	x3, x30
+	mov	x0, #CONSOLE_FLAG_CRASH
+	bl	console_switch_state
+	mov	x0, #1
+	ret	x3
+#endif
+endfunc plat_crash_console_init
+
+	/* -----------------------------------------------------
+	 * void plat_crash_console_putc(int character)
+	 * Output through the normal console by default.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_putc
+	b	console_putc
+endfunc plat_crash_console_putc
+
+	/* -----------------------------------------------------
+	 * void plat_crash_console_flush(void)
+	 * Flush normal console by default.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_flush
+	b	console_flush
+endfunc plat_crash_console_flush
+
+#else	/* MULTI_CONSOLE_API */
+
+	/* -----------------------------------------------------
+	 * In the old API these are all no-op stubs that need to
+	 * be overridden by the platform to be useful.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_init
+	mov	x0, #0
+	ret
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+	ret
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+	ret
+endfunc plat_crash_console_flush
+
+#endif
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
index 7214588..d3ffcaf 100644
--- a/plat/common/aarch64/platform_helpers.S
+++ b/plat/common/aarch64/platform_helpers.S
@@ -10,9 +10,11 @@
 #include <platform_def.h>
 
 	.weak	plat_report_exception
+#if !ERROR_DEPRECATED
 	.weak	plat_crash_console_init
 	.weak	plat_crash_console_putc
 	.weak	plat_crash_console_flush
+#endif
 	.weak	plat_reset_handler
 	.weak	plat_disable_acp
 	.weak	bl1_plat_prepare_exit
@@ -37,6 +39,7 @@
 	ret
 endfunc plat_report_exception
 
+#if !ERROR_DEPRECATED
 #if MULTI_CONSOLE_API
 	/* -----------------------------------------------------
 	 * int plat_crash_console_init(void)
@@ -109,6 +112,7 @@
 	ret
 endfunc plat_crash_console_flush
 #endif
+#endif /* ERROR_DEPRECATED */
 
 	/* -----------------------------------------------------
 	 * Placeholder function which should be redefined by
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index 264d518..4cf1cc5 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -13,6 +13,7 @@
 #include <mbedtls_config.h>
 #endif
 #include <platform.h>
+#include <xlat_tables_compat.h>
 
 /*
  * The following platform functions are weakly defined. The Platforms
@@ -72,3 +73,40 @@
 	return 0;
 }
 #endif /* TRUSTED_BOARD_BOOT */
+
+/*
+ * Set up the page tables for the generic and platform-specific memory regions.
+ * The size of the Trusted SRAM seen by the BL image must be specified as well
+ * as an array specifying the generic memory regions which can be;
+ * - Code section;
+ * - Read-only data section;
+ * - Init code section, if applicable
+ * - Coherent memory region, if applicable.
+ */
+
+void __init setup_page_tables(const mmap_region_t *bl_regions,
+			      const mmap_region_t *plat_regions)
+{
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+	const mmap_region_t *regions = bl_regions;
+
+	while (regions->size != 0U) {
+		VERBOSE("Region: 0x%lx - 0x%lx has attributes 0x%x\n",
+				regions->base_va,
+				regions->base_va + regions->size,
+				regions->attr);
+		regions++;
+	}
+#endif
+	/*
+	 * Map the Trusted SRAM with appropriate memory attributes.
+	 * Subsequent mappings will adjust the attributes for specific regions.
+	 */
+	mmap_add(bl_regions);
+
+	/* Now (re-)map the platform-specific memory regions */
+	mmap_add(plat_regions);
+
+	/* Create the page tables to reflect the above mappings */
+	init_xlat_tables();
+}
diff --git a/plat/hisilicon/hikey/aarch64/hikey_helpers.S b/plat/hisilicon/hikey/aarch64/hikey_helpers.S
index 32ff8b4..9dfdae4 100644
--- a/plat/hisilicon/hikey/aarch64/hikey_helpers.S
+++ b/plat/hisilicon/hikey/aarch64/hikey_helpers.S
@@ -12,6 +12,7 @@
 	.globl	platform_mem_init
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
 	.globl	plat_report_exception
 	.globl	plat_reset_handler
 
@@ -61,6 +62,19 @@
 endfunc plat_crash_console_putc
 
 	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm	x0, CRASH_CONSOLE_BASE
+	b	console_core_flush
+endfunc plat_crash_console_flush
+
+	/* ---------------------------------------------
 	 * void plat_report_exception(unsigned int type)
 	 * Function to report an unhandled exception
 	 * with platform-specific means.
diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S
index d18399f..550c560 100644
--- a/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S
+++ b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 	.globl	platform_mem_init
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
 	.globl	plat_report_exception
 	.globl	plat_reset_handler
 	.globl	clr_ex
@@ -65,6 +66,19 @@
 endfunc plat_crash_console_putc
 
 	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm	x0, CRASH_CONSOLE_BASE
+	b	console_core_flush
+endfunc plat_crash_console_flush
+
+	/* ---------------------------------------------
 	 * void plat_report_exception(unsigned int type)
 	 * Function to report an unhandled exception
 	 * with platform-specific means.
diff --git a/plat/hisilicon/poplar/aarch64/poplar_helpers.S b/plat/hisilicon/poplar/aarch64/poplar_helpers.S
new file mode 100644
index 0000000..928dbef
--- /dev/null
+++ b/plat/hisilicon/poplar/aarch64/poplar_helpers.S
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, 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
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * 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/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c
index 83803a6..20a613d 100644
--- a/plat/hisilicon/poplar/bl31_plat_setup.c
+++ b/plat/hisilicon/poplar/bl31_plat_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,13 +15,12 @@
 #include <errno.h>
 #include <generic_delay_timer.h>
 #include <mmio.h>
-#include <plat_arm.h>
 #include <platform.h>
+#include <platform_def.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__)
@@ -113,8 +112,8 @@
 	generic_delay_timer_init();
 
 	/* Init GIC distributor and CPU interface */
-	plat_arm_gic_driver_init();
-	plat_arm_gic_init();
+	poplar_gic_driver_init();
+	poplar_gic_init();
 
 	/* Init security properties of IP blocks */
 	hisi_tzpc_sec_init();
diff --git a/plat/hisilicon/poplar/include/plat_private.h b/plat/hisilicon/poplar/include/plat_private.h
index 845b1bd..63b7d76 100644
--- a/plat/hisilicon/poplar/include/plat_private.h
+++ b/plat/hisilicon/poplar/include/plat_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,4 +26,11 @@
 
 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
index 99fd996..6287a76 100644
--- a/plat/hisilicon/poplar/include/platform_def.h
+++ b/plat/hisilicon/poplar/include/platform_def.h
@@ -22,9 +22,9 @@
 #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
+#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)
@@ -134,10 +134,10 @@
 #define PLAT_MAX_RET_STATE		U(1)
 
 /* Interrupt controller */
-#define PLAT_ARM_GICD_BASE	GICD_BASE
-#define PLAT_ARM_GICC_BASE	GICC_BASE
+#define POPLAR_GICD_BASE	GICD_BASE
+#define POPLAR_GICC_BASE	GICC_BASE
 
-#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+#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, \
@@ -165,6 +165,6 @@
 	INTR_PROP_DESC(HISI_IRQ_SEC_AXI, GIC_HIGHEST_SEC_PRIORITY, grp, \
 			GIC_INTR_CFG_LEVEL)
 
-#define PLAT_ARM_G0_IRQ_PROPS(grp)
+#define POPLAR_G0_IRQ_PROPS(grp)
 
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/hisilicon/poplar/plat_pm.c b/plat/hisilicon/poplar/plat_pm.c
index e59cac9..dcbcec4 100644
--- a/plat/hisilicon/poplar/plat_pm.c
+++ b/plat/hisilicon/poplar/plat_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,12 +12,11 @@
 #include <context_mgmt.h>
 #include <debug.h>
 #include <mmio.h>
-#include <plat_arm.h>
 #include <platform.h>
+#include <platform_def.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
@@ -76,10 +75,10 @@
 					PLAT_MAX_OFF_STATE);
 
 	/* Enable the gic cpu interface */
-	plat_arm_gic_pcpu_init();
+	poplar_gic_pcpu_init();
 
 	/* Program the gic per-cpu distributor or re-distributor interface */
-	plat_arm_gic_cpuif_enable();
+	poplar_gic_cpuif_enable();
 }
 
 static void poplar_pwr_domain_suspend_finish(
diff --git a/plat/hisilicon/poplar/plat_topology.c b/plat/hisilicon/poplar/plat_topology.c
index 3dd818e..bb53c6b 100644
--- a/plat/hisilicon/poplar/plat_topology.c
+++ b/plat/hisilicon/poplar/plat_topology.c
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, 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"
+#include "plat_private.h"
 
 const unsigned char hisi_power_domain_tree_desc[] = {
 	PLATFORM_CLUSTER_COUNT,
@@ -27,5 +27,5 @@
 	if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT)
 		return -1;
 
-	return plat_arm_calc_core_pos(mpidr);
+	return poplar_calc_core_pos(mpidr);
 }
diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk
index 9d2b617..de262ad 100644
--- a/plat/hisilicon/poplar/platform.mk
+++ b/plat/hisilicon/poplar/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -53,7 +53,6 @@
 $(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/synopsys		\
@@ -68,10 +67,10 @@
 		drivers/delay_timer/delay_timer.c			\
 		drivers/arm/pl011/aarch64/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
+		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				\
diff --git a/plat/hisilicon/poplar/poplar_gicv2.c b/plat/hisilicon/poplar/poplar_gicv2.c
new file mode 100644
index 0000000..1c1be47
--- /dev/null
+++ b/plat/hisilicon/poplar/poplar_gicv2.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <gicv2.h>
+#include <platform.h>
+#include <platform_def.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/imx/common/imx8_helpers.S b/plat/imx/common/imx8_helpers.S
index b89d346..19293bf 100644
--- a/plat/imx/common/imx8_helpers.S
+++ b/plat/imx/common/imx8_helpers.S
@@ -16,6 +16,7 @@
 	.globl	plat_secondary_cold_boot_setup
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
 	.globl	platform_mem_init
 	.globl  imx_mailbox_init
 
@@ -106,6 +107,7 @@
 endfunc plat_secondary_cold_boot_setup
 
 func plat_crash_console_init
+	mov	x0, #1
 	ret
 endfunc plat_crash_console_init
 
@@ -113,6 +115,11 @@
 	ret
 endfunc plat_crash_console_putc
 
+func plat_crash_console_flush
+	mov	x0, #0
+	ret
+endfunc plat_crash_console_flush
+
 func platform_mem_init
 	ret
 endfunc platform_mem_init
diff --git a/plat/imx/common/lpuart_console.S b/plat/imx/common/lpuart_console.S
index ad71b89..668fd62 100644
--- a/plat/imx/common/lpuart_console.S
+++ b/plat/imx/common/lpuart_console.S
@@ -6,6 +6,7 @@
 
 #include <arch.h>
 #include <asm_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
 #include <console_macros.S>
 #include <assert_macros.S>
 #include "imx8_lpuart.h"
@@ -26,7 +27,7 @@
 
 	mov	x0, x6
 	mov	x30, x7
-	finish_console_register lpuart
+	finish_console_register lpuart putc=1, getc=1
 
 register_fail:
 	ret	x7
diff --git a/plat/imx/imx7/warp7/aarch32/warp7_helpers.S b/plat/imx/imx7/warp7/aarch32/warp7_helpers.S
index b1921cc..3695b32 100644
--- a/plat/imx/imx7/warp7/aarch32/warp7_helpers.S
+++ b/plat/imx/imx7/warp7/aarch32/warp7_helpers.S
@@ -14,6 +14,7 @@
 	.globl	plat_get_my_entrypoint
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
 	.globl	plat_panic_handler
 
 	/* ---------------------------------------------
@@ -45,6 +46,12 @@
 	b	imx_crash_uart_putc
 endfunc plat_crash_console_putc
 
+func plat_crash_console_flush
+	/* Placeholder */
+	mov	r0, #0
+	bx	lr
+endfunc plat_crash_console_flush
+
 func plat_panic_handler
 	mov	r3, #HAB_ROM_VECTOR_TABLE_FAILSAFE
 	ldr	r3, [r3, #0]
diff --git a/plat/imx/imx7/warp7/platform.mk b/plat/imx/imx7/warp7/platform.mk
index deb4c41..a771865 100644
--- a/plat/imx/imx7/warp7/platform.mk
+++ b/plat/imx/imx7/warp7/platform.mk
@@ -22,7 +22,6 @@
 # Platform
 PLAT_INCLUDES		:=	-Idrivers/imx/uart			\
 				-Iinclude/common/tbbr			\
-				-Iinclude/plat/arm/common/		\
 				-Iplat/imx/common/include/		\
 				-Iplat/imx/imx7/warp7/include		\
 				-Idrivers/imx/timer			\
diff --git a/plat/layerscape/board/ls1043/platform.mk b/plat/layerscape/board/ls1043/platform.mk
index c554ac3..678205c 100644
--- a/plat/layerscape/board/ls1043/platform.mk
+++ b/plat/layerscape/board/ls1043/platform.mk
@@ -22,7 +22,6 @@
 					plat/layerscape/board/ls1043/ls1043_security.c
 
 PLAT_INCLUDES			:=	-Iplat/layerscape/board/ls1043/include   \
-					-Iinclude/plat/arm/common	\
 					-Iplat/layerscape/common/include	\
 					-Iinclude/drivers/arm   \
 					-Iinclude/lib		\
diff --git a/plat/layerscape/common/aarch64/ls_console.S b/plat/layerscape/common/aarch64/ls_console.S
index 5c87465..ec4390a 100644
--- a/plat/layerscape/common/aarch64/ls_console.S
+++ b/plat/layerscape/common/aarch64/ls_console.S
@@ -6,6 +6,7 @@
 
 #include <arch.h>
 #include <asm_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
 #include <console_macros.S>
 #include <assert_macros.S>
 #include "ls_16550.h"
@@ -106,7 +107,7 @@
 
 	mov	x0, x6
 	mov	x30, x7
-	finish_console_register ls_16550
+	finish_console_register ls_16550 putc=1, getc=1, flush=1
 
 register_fail:
 	ret	x7
diff --git a/plat/marvell/common/aarch64/marvell_helpers.S b/plat/marvell/common/aarch64/marvell_helpers.S
index a3dc917..128c3ab 100644
--- a/plat/marvell/common/aarch64/marvell_helpers.S
+++ b/plat/marvell/common/aarch64/marvell_helpers.S
@@ -18,6 +18,7 @@
 	.weak	plat_my_core_pos
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
 	.globl	platform_mem_init
 	.globl	disable_mmu_dcache
 	.globl	invalidate_tlb_all
@@ -79,6 +80,19 @@
 	b	console_core_putc
 endfunc plat_crash_console_putc
 
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm	x0, PLAT_MARVELL_CRASH_UART_BASE
+	b	console_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.
diff --git a/plat/meson/gxbb/aarch64/gxbb_helpers.S b/plat/meson/gxbb/aarch64/gxbb_helpers.S
new file mode 100644
index 0000000..760d6c4
--- /dev/null
+++ b/plat/meson/gxbb/aarch64/gxbb_helpers.S
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <platform_def.h>
+
+	.globl	plat_crash_console_flush
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	platform_mem_init
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_my_core_pos
+	.globl	plat_reset_handler
+	.globl	plat_gxbb_calc_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_my_core_pos(void);
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_gxbb_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_gxbb_calc_core_pos(u_register_t mpidr);
+	 * -----------------------------------------------------
+	 */
+func plat_gxbb_calc_core_pos
+	and	x0, x0, #MPIDR_CPU_MASK
+	ret
+endfunc plat_gxbb_calc_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_is_my_cpu_primary(void);
+	 * -----------------------------------------------------
+	 */
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	cmp	x0, #GXBB_PRIMARY_CPU
+	cset	w0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* ---------------------------------------------
+	 * void platform_mem_init(void);
+	 * ---------------------------------------------
+	 */
+func platform_mem_init
+	ret
+endfunc platform_mem_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, GXBB_UART0_AO_BASE
+	mov_imm	x1, GXBB_UART0_AO_CLK_IN_HZ
+	mov_imm	x2, GXBB_UART_BAUDRATE
+	b	console_meson_init
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(int c)
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	mov_imm	x1, GXBB_UART0_AO_BASE
+	b	console_meson_core_putc
+endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm	x0, GXBB_UART0_AO_BASE
+	b	console_meson_core_flush
+endfunc plat_crash_console_flush
+
+	/* ---------------------------------------------
+	 * void plat_reset_handler(void);
+	 * ---------------------------------------------
+	 */
+func plat_reset_handler
+	ret
+endfunc plat_reset_handler
diff --git a/plat/meson/gxbb/gxbb_bl31_setup.c b/plat/meson/gxbb/gxbb_bl31_setup.c
new file mode 100644
index 0000000..3e176f9
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_bl31_setup.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <gicv2.h>
+#include <interrupt_props.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <xlat_mmu_helpers.h>
+
+#include "gxbb_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	assert(type == NON_SECURE);
+
+	next_image_info = &bl33_image_ep_info;
+
+	/* None of the images can have 0x0 as the entrypoint. */
+	if (next_image_info->pc != 0U) {
+		return next_image_info;
+	} else {
+		return NULL;
+	}
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+struct gxbb_bl31_param {
+	param_header_t h;
+	image_info_t *bl31_image_info;
+	entry_point_info_t *bl32_ep_info;
+	image_info_t *bl32_image_info;
+	entry_point_info_t *bl33_ep_info;
+	image_info_t *bl33_image_info;
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	struct gxbb_bl31_param *from_bl2;
+
+	/* Initialize the console to provide early debug support */
+	gxbb_console_init();
+
+	/*
+	 * In debug builds, we pass a special value in 'arg1' to verify platform
+	 * parameters from BL2 to BL31. In release builds it's not used.
+	 */
+	assert(arg1 == GXBB_BL31_PLAT_PARAM_VAL);
+
+	/* Check that params passed from BL2 are not NULL. */
+	from_bl2 = (struct gxbb_bl31_param *) arg0;
+
+	/* Check params passed from BL2 are not NULL. */
+	assert(from_bl2 != NULL);
+	assert(from_bl2->h.type == PARAM_BL31);
+	assert(from_bl2->h.version >= VERSION_1);
+
+	/*
+	 * Copy BL33 entry point information. It is stored in Secure RAM, in
+	 * BL2's address space.
+	 */
+	bl33_image_ep_info = *from_bl2->bl33_ep_info;
+
+	if (bl33_image_ep_info.pc == 0U) {
+		ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
+		panic();
+	}
+}
+
+void bl31_plat_arch_setup(void)
+{
+	gxbb_setup_page_tables();
+
+	enable_mmu_el3(0);
+}
+
+/*******************************************************************************
+ * GICv2 driver setup information
+ ******************************************************************************/
+static const interrupt_prop_t gxbb_interrupt_props[] = {
+	INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+};
+
+static const gicv2_driver_data_t gxbb_gic_data = {
+	.gicd_base = GXBB_GICD_BASE,
+	.gicc_base = GXBB_GICC_BASE,
+	.interrupt_props = gxbb_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(gxbb_interrupt_props),
+};
+
+void bl31_platform_setup(void)
+{
+	mhu_secure_init();
+
+	gicv2_driver_init(&gxbb_gic_data);
+	gicv2_distif_init();
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+
+	gxbb_thermal_unknown();
+}
diff --git a/plat/meson/gxbb/gxbb_common.c b/plat/meson/gxbb/gxbb_common.c
new file mode 100644
index 0000000..349d02f
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_common.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <ep_info.h>
+#include <interrupt_mgmt.h>
+#include <meson_console.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <xlat_tables_v2.h>
+
+/*******************************************************************************
+ * Platform memory map regions
+ ******************************************************************************/
+#define MAP_NSDRAM0	MAP_REGION_FLAT(GXBB_NSDRAM0_BASE,		\
+					GXBB_NSDRAM0_SIZE,		\
+					MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_NSDRAM1	MAP_REGION_FLAT(GXBB_NSDRAM1_BASE,		\
+					GXBB_NSDRAM1_SIZE,		\
+					MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_SEC_DEVICE0	MAP_REGION_FLAT(GXBB_SEC_DEVICE0_BASE,		\
+					GXBB_SEC_DEVICE0_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE1	MAP_REGION_FLAT(GXBB_SEC_DEVICE1_BASE,		\
+					GXBB_SEC_DEVICE1_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TZRAM	MAP_REGION_FLAT(GXBB_TZRAM_BASE,		\
+					GXBB_TZRAM_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE2	MAP_REGION_FLAT(GXBB_SEC_DEVICE2_BASE,		\
+					GXBB_SEC_DEVICE2_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE3	MAP_REGION_FLAT(GXBB_SEC_DEVICE3_BASE,		\
+					GXBB_SEC_DEVICE3_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+static const mmap_region_t gxbb_mmap[] = {
+	MAP_NSDRAM0,
+	MAP_NSDRAM1,
+	MAP_SEC_DEVICE0,
+	MAP_SEC_DEVICE1,
+	MAP_TZRAM,
+	MAP_SEC_DEVICE2,
+	MAP_SEC_DEVICE3,
+	{0}
+};
+
+/*******************************************************************************
+ * Per-image regions
+ ******************************************************************************/
+#define MAP_BL31	MAP_REGION_FLAT(BL31_BASE,			\
+				BL31_END - BL31_BASE,			\
+				MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_BL_CODE	MAP_REGION_FLAT(BL_CODE_BASE,			\
+				BL_CODE_END - BL_CODE_BASE,		\
+				MT_CODE | MT_SECURE)
+
+#define MAP_BL_RO_DATA	MAP_REGION_FLAT(BL_RO_DATA_BASE,		\
+				BL_RO_DATA_END - BL_RO_DATA_BASE,	\
+				MT_RO_DATA | MT_SECURE)
+
+#define MAP_BL_COHERENT	MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,		\
+				BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+				MT_DEVICE | MT_RW | MT_SECURE)
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void gxbb_setup_page_tables(void)
+{
+#if IMAGE_BL31
+	const mmap_region_t gxbb_bl_mmap[] = {
+		MAP_BL31,
+		MAP_BL_CODE,
+		MAP_BL_RO_DATA,
+#if USE_COHERENT_MEM
+		MAP_BL_COHERENT,
+#endif
+		{0}
+	};
+#endif
+
+	mmap_add(gxbb_bl_mmap);
+
+	mmap_add(gxbb_mmap);
+
+	init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Function that sets up the console
+ ******************************************************************************/
+static console_meson_t gxbb_console;
+
+void gxbb_console_init(void)
+{
+	int rc = console_meson_register(GXBB_UART0_AO_BASE,
+					GXBB_UART0_AO_CLK_IN_HZ,
+					GXBB_UART_BAUDRATE,
+					&gxbb_console);
+	if (rc == 0) {
+		/*
+		 * The crash console doesn't use the multi console API, it uses
+		 * the core console functions directly. It is safe to call panic
+		 * and let it print debug information.
+		 */
+		panic();
+	}
+
+	console_set_scope(&gxbb_console.console,
+			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+}
+
+/*******************************************************************************
+ * Function that returns the system counter frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+	uint32_t val;
+
+	val = mmio_read_32(GXBB_SYS_CPU_CFG7);
+	val &= 0xFDFFFFFF;
+	mmio_write_32(GXBB_SYS_CPU_CFG7, val);
+
+	val = mmio_read_32(GXBB_AO_TIMESTAMP_CNTL);
+	val &= 0xFFFFFE00;
+	mmio_write_32(GXBB_AO_TIMESTAMP_CNTL, val);
+
+	return GXBB_OSC24M_CLK_IN_HZ;
+}
diff --git a/plat/meson/gxbb/gxbb_def.h b/plat/meson/gxbb/gxbb_def.h
new file mode 100644
index 0000000..0c73ac0
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_def.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GXBB_DEF_H
+#define GXBB_DEF_H
+
+#include <utils_def.h>
+
+/*******************************************************************************
+ * System oscillator
+ ******************************************************************************/
+#define GXBB_OSC24M_CLK_IN_HZ			ULL(24000000) /* 24 MHz */
+
+/*******************************************************************************
+ * Memory regions
+ ******************************************************************************/
+#define GXBB_NSDRAM0_BASE			UL(0x01000000)
+#define GXBB_NSDRAM0_SIZE			UL(0x0F000000)
+
+#define GXBB_NSDRAM1_BASE			UL(0x10000000)
+#define GXBB_NSDRAM1_SIZE			UL(0x00100000)
+
+#define BL31_BASE				UL(0x10100000)
+#define BL31_SIZE				UL(0x000C0000)
+#define BL31_LIMIT				(BL31_BASE + BL31_SIZE)
+
+/* Shared memory used for SMC services */
+#define GXBB_SHARE_MEM_INPUT_BASE		UL(0x100FE000)
+#define GXBB_SHARE_MEM_OUTPUT_BASE		UL(0x100FF000)
+
+#define GXBB_SEC_DEVICE0_BASE			UL(0xC0000000)
+#define GXBB_SEC_DEVICE0_SIZE			UL(0x09000000)
+
+#define GXBB_SEC_DEVICE1_BASE			UL(0xD0040000)
+#define GXBB_SEC_DEVICE1_SIZE			UL(0x00008000)
+
+#define GXBB_TZRAM_BASE				UL(0xD9000000)
+#define GXBB_TZRAM_SIZE				UL(0x00014000)
+/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */
+
+/* Mailboxes */
+#define GXBB_MHU_SECURE_SCP_TO_AP_PAYLOAD	UL(0xD9013800)
+#define GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD	UL(0xD9013A00)
+#define GXBB_PSCI_MAILBOX_BASE			UL(0xD9013F00)
+
+#define GXBB_TZROM_BASE				UL(0xD9040000)
+#define GXBB_TZROM_SIZE				UL(0x00010000)
+
+#define GXBB_SEC_DEVICE2_BASE			UL(0xDA000000)
+#define GXBB_SEC_DEVICE2_SIZE			UL(0x00200000)
+
+#define GXBB_SEC_DEVICE3_BASE			UL(0xDA800000)
+#define GXBB_SEC_DEVICE3_SIZE			UL(0x00200000)
+
+/*******************************************************************************
+ * GIC-400 and interrupt handling related constants
+ ******************************************************************************/
+#define GXBB_GICD_BASE				UL(0xC4301000)
+#define GXBB_GICC_BASE				UL(0xC4302000)
+
+#define IRQ_SEC_PHY_TIMER			29
+
+#define IRQ_SEC_SGI_0				8
+#define IRQ_SEC_SGI_1				9
+#define IRQ_SEC_SGI_2				10
+#define IRQ_SEC_SGI_3				11
+#define IRQ_SEC_SGI_4				12
+#define IRQ_SEC_SGI_5				13
+#define IRQ_SEC_SGI_6				14
+#define IRQ_SEC_SGI_7				15
+
+/*******************************************************************************
+ * UART definitions
+ ******************************************************************************/
+#define GXBB_UART0_AO_BASE			UL(0xC81004C0)
+#define GXBB_UART0_AO_CLK_IN_HZ			GXBB_OSC24M_CLK_IN_HZ
+#define GXBB_UART_BAUDRATE			U(115200)
+
+/*******************************************************************************
+ * Memory-mapped I/O Registers
+ ******************************************************************************/
+#define GXBB_AO_TIMESTAMP_CNTL			UL(0xC81000B4)
+
+#define GXBB_SYS_CPU_CFG7			UL(0xC8834664)
+
+#define GXBB_AO_RTI_STATUS_REG3			UL(0xDA10001C)
+
+#define GXBB_HIU_MAILBOX_SET_0			UL(0xDA83C404)
+#define GXBB_HIU_MAILBOX_STAT_0			UL(0xDA83C408)
+#define GXBB_HIU_MAILBOX_CLR_0			UL(0xDA83C40C)
+#define GXBB_HIU_MAILBOX_SET_3			UL(0xDA83C428)
+#define GXBB_HIU_MAILBOX_STAT_3			UL(0xDA83C42C)
+#define GXBB_HIU_MAILBOX_CLR_3			UL(0xDA83C430)
+
+/*******************************************************************************
+ * System Monitor Call IDs and arguments
+ ******************************************************************************/
+#define GXBB_SM_GET_SHARE_MEM_INPUT_BASE	U(0x82000020)
+#define GXBB_SM_GET_SHARE_MEM_OUTPUT_BASE	U(0x82000021)
+
+#define GXBB_SM_EFUSE_READ			U(0x82000030)
+#define GXBB_SM_EFUSE_USER_MAX			U(0x82000033)
+
+#define GXBB_SM_JTAG_ON				U(0x82000040)
+#define GXBB_SM_JTAG_OFF			U(0x82000041)
+
+#define GXBB_JTAG_STATE_ON			U(0)
+#define GXBB_JTAG_STATE_OFF			U(1)
+
+#define GXBB_JTAG_M3_AO				U(0)
+#define GXBB_JTAG_M3_EE				U(1)
+#define GXBB_JTAG_A53_AO			U(2)
+#define GXBB_JTAG_A53_EE			U(3)
+
+#endif /* GXBB_DEF_H */
diff --git a/plat/meson/gxbb/gxbb_efuse.c b/plat/meson/gxbb/gxbb_efuse.c
new file mode 100644
index 0000000..edea542
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_efuse.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include "gxbb_private.h"
+
+#define EFUSE_BASE	0x140
+#define EFUSE_SIZE	0xC0
+
+uint64_t gxbb_efuse_read(void *dst, uint32_t offset, uint32_t size)
+{
+	if ((uint64_t)(offset + size) > (uint64_t)EFUSE_SIZE)
+		return 0;
+
+	return scpi_efuse_read(dst, offset + EFUSE_BASE, size);
+}
+
+uint64_t gxbb_efuse_user_max(void)
+{
+	return EFUSE_SIZE;
+}
diff --git a/plat/meson/gxbb/gxbb_mhu.c b/plat/meson/gxbb/gxbb_mhu.c
new file mode 100644
index 0000000..78b895c
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_mhu.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bakery_lock.h>
+#include <mmio.h>
+#include <platform_def.h>
+
+static DEFINE_BAKERY_LOCK(mhu_lock);
+
+void mhu_secure_message_start(void)
+{
+	bakery_lock_get(&mhu_lock);
+
+	while (mmio_read_32(GXBB_HIU_MAILBOX_STAT_3) != 0)
+		;
+}
+
+void mhu_secure_message_send(uint32_t msg)
+{
+	mmio_write_32(GXBB_HIU_MAILBOX_SET_3, msg);
+
+	while (mmio_read_32(GXBB_HIU_MAILBOX_STAT_3) != 0)
+		;
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+	uint32_t val;
+
+	do {
+		val = mmio_read_32(GXBB_HIU_MAILBOX_STAT_0);
+	} while (val == 0);
+
+	return val;
+}
+
+void mhu_secure_message_end(void)
+{
+	mmio_write_32(GXBB_HIU_MAILBOX_CLR_0, 0xFFFFFFFF);
+
+	bakery_lock_release(&mhu_lock);
+}
+
+void mhu_secure_init(void)
+{
+	bakery_lock_init(&mhu_lock);
+
+	mmio_write_32(GXBB_HIU_MAILBOX_CLR_3, 0xFFFFFFFF);
+}
diff --git a/plat/meson/gxbb/gxbb_pm.c b/plat/meson/gxbb/gxbb_pm.c
new file mode 100644
index 0000000..930b5e1
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_pm.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+
+#include "gxbb_private.h"
+
+#define SCPI_POWER_ON		0
+#define SCPI_POWER_RETENTION	1
+#define SCPI_POWER_OFF		3
+
+#define SCPI_SYSTEM_SHUTDOWN	0
+#define SCPI_SYSTEM_REBOOT	1
+
+static uintptr_t gxbb_sec_entrypoint;
+static volatile uint32_t gxbb_cpu0_go;
+
+static void gxbb_program_mailbox(u_register_t mpidr, uint64_t value)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
+	uintptr_t cpu_mailbox_addr = GXBB_PSCI_MAILBOX_BASE + (core << 4);
+
+	mmio_write_64(cpu_mailbox_addr, value);
+	flush_dcache_range(cpu_mailbox_addr, sizeof(uint64_t));
+}
+
+static void __dead2 gxbb_system_reset(void)
+{
+	INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+	uint32_t status = mmio_read_32(GXBB_AO_RTI_STATUS_REG3);
+
+	NOTICE("BL31: Reboot reason: 0x%x\n", status);
+
+	status &= 0xFFFF0FF0;
+
+	console_flush();
+
+	mmio_write_32(GXBB_AO_RTI_STATUS_REG3, status);
+
+	int ret = scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+
+	if (ret != 0) {
+		ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %u\n", ret);
+		panic();
+	}
+
+	wfi();
+
+	ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+	panic();
+}
+
+static void __dead2 gxbb_system_off(void)
+{
+	INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+	unsigned int ret = scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+
+	if (ret != 0) {
+		ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %u\n", ret);
+		panic();
+	}
+
+	gxbb_program_mailbox(read_mpidr_el1(), 0);
+
+	wfi();
+
+	ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
+	panic();
+}
+
+static int32_t gxbb_pwr_domain_on(u_register_t mpidr)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
+
+	/* CPU0 can't be turned OFF, emulate it with a WFE loop */
+	if (core == GXBB_PRIMARY_CPU) {
+		VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
+
+		gxbb_cpu0_go = 1;
+		flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go));
+		dsb();
+		isb();
+
+		sev();
+
+		return PSCI_E_SUCCESS;
+	}
+
+	gxbb_program_mailbox(mpidr, gxbb_sec_entrypoint);
+	scpi_set_css_power_state(mpidr,
+				 SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
+	dmbsy();
+	sev();
+
+	return PSCI_E_SUCCESS;
+}
+
+static void gxbb_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(read_mpidr_el1());
+
+	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+					PLAT_LOCAL_STATE_OFF);
+
+	if (core == GXBB_PRIMARY_CPU) {
+		gxbb_cpu0_go = 0;
+		flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go));
+		dsb();
+		isb();
+	}
+
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+}
+
+static void gxbb_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	u_register_t mpidr = read_mpidr_el1();
+	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
+	uintptr_t addr = GXBB_PSCI_MAILBOX_BASE + 8 + (core << 4);
+
+	mmio_write_32(addr, 0xFFFFFFFF);
+	flush_dcache_range(addr, sizeof(uint32_t));
+
+	gicv2_cpuif_disable();
+
+	/* CPU0 can't be turned OFF, emulate it with a WFE loop */
+	if (core == GXBB_PRIMARY_CPU)
+		return;
+
+	scpi_set_css_power_state(mpidr,
+				 SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON);
+}
+
+static void __dead2 gxbb_pwr_domain_pwr_down_wfi(const psci_power_state_t
+						 *target_state)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(read_mpidr_el1());
+
+	/* CPU0 can't be turned OFF, emulate it with a WFE loop */
+	if (core == GXBB_PRIMARY_CPU) {
+		VERBOSE("BL31: CPU0 entering wait loop...\n");
+
+		while (gxbb_cpu0_go == 0)
+			wfe();
+
+		VERBOSE("BL31: CPU0 resumed.\n");
+
+		write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT);
+	}
+
+	dsbsy();
+
+	for (;;)
+		wfi();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t gxbb_ops = {
+	.pwr_domain_on			= gxbb_pwr_domain_on,
+	.pwr_domain_on_finish		= gxbb_pwr_domain_on_finish,
+	.pwr_domain_off			= gxbb_pwr_domain_off,
+	.pwr_domain_pwr_down_wfi	= gxbb_pwr_domain_pwr_down_wfi,
+	.system_off			= gxbb_system_off,
+	.system_reset			= gxbb_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	gxbb_sec_entrypoint = sec_entrypoint;
+	*psci_ops = &gxbb_ops;
+	gxbb_cpu0_go = 0;
+	return 0;
+}
diff --git a/plat/meson/gxbb/gxbb_private.h b/plat/meson/gxbb/gxbb_private.h
new file mode 100644
index 0000000..910a42c
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GXBB_PRIVATE_H
+#define GXBB_PRIVATE_H
+
+#include <stdint.h>
+
+/* Utility functions */
+unsigned int plat_gxbb_calc_core_pos(u_register_t mpidr);
+void gxbb_console_init(void);
+void gxbb_setup_page_tables(void);
+
+/* MHU functions */
+void mhu_secure_message_start(void);
+void mhu_secure_message_send(uint32_t msg);
+uint32_t mhu_secure_message_wait(void);
+void mhu_secure_message_end(void);
+void mhu_secure_init(void);
+
+/* SCPI functions */
+void scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
+			      uint32_t cluster_state, uint32_t css_state);
+uint32_t scpi_sys_power_state(uint64_t system_state);
+void scpi_jtag_set_state(uint32_t state, uint8_t select);
+uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size);
+void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
+			  uint32_t arg2, uint32_t arg3);
+
+/* Peripherals */
+void gxbb_thermal_unknown(void);
+uint64_t gxbb_efuse_read(void *dst, uint32_t offset, uint32_t size);
+uint64_t gxbb_efuse_user_max(void);
+
+#endif /* GXBB_PRIVATE_H */
diff --git a/plat/meson/gxbb/gxbb_scpi.c b/plat/meson/gxbb/gxbb_scpi.c
new file mode 100644
index 0000000..2390bca
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_scpi.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+
+#include "gxbb_private.h"
+
+#define SIZE_SHIFT	20
+#define SIZE_MASK	0x1FF
+
+/*
+ * Note: The Amlogic SCP firmware uses the legacy SCPI protocol.
+ */
+#define SCPI_CMD_SET_CSS_POWER_STATE	0x04
+#define SCPI_CMD_SET_SYS_POWER_STATE	0x08
+
+#define SCPI_CMD_JTAG_SET_STATE		0xC0
+#define SCPI_CMD_EFUSE_READ		0xC2
+
+static inline uint32_t scpi_cmd(uint32_t command, uint32_t size)
+{
+	return command | (size << SIZE_SHIFT);
+}
+
+void scpi_secure_message_send(uint32_t command, uint32_t size)
+{
+	mhu_secure_message_send(scpi_cmd(command, size));
+}
+
+uint32_t scpi_secure_message_receive(void **message_out, size_t *size_out)
+{
+	uint32_t response = mhu_secure_message_wait();
+
+	size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
+
+	response &= ~(SIZE_MASK << SIZE_SHIFT);
+
+	if (size_out != NULL)
+		*size_out = size;
+
+	if (message_out != NULL)
+		*message_out = (void *)GXBB_MHU_SECURE_SCP_TO_AP_PAYLOAD;
+
+	return response;
+}
+
+void scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
+			      uint32_t cluster_state, uint32_t css_state)
+{
+	uint32_t state = (mpidr & 0x0F) | /* CPU ID */
+			 ((mpidr & 0xF00) >> 4) | /* Cluster ID */
+			 (cpu_state << 8) |
+			 (cluster_state << 12) |
+			 (css_state << 16);
+
+	mhu_secure_message_start();
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, state);
+	mhu_secure_message_send(scpi_cmd(SCPI_CMD_SET_CSS_POWER_STATE, 4));
+	mhu_secure_message_wait();
+	mhu_secure_message_end();
+}
+
+uint32_t scpi_sys_power_state(uint64_t system_state)
+{
+	uint32_t *response;
+	size_t size;
+
+	mhu_secure_message_start();
+	mmio_write_8(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, system_state);
+	mhu_secure_message_send(scpi_cmd(SCPI_CMD_SET_SYS_POWER_STATE, 1));
+	scpi_secure_message_receive((void *)&response, &size);
+	mhu_secure_message_end();
+
+	return *response;
+}
+
+void scpi_jtag_set_state(uint32_t state, uint8_t select)
+{
+	assert(state <= GXBB_JTAG_STATE_OFF);
+
+	if (select > GXBB_JTAG_A53_EE) {
+		WARN("BL31: Invalid JTAG select (0x%x).\n", select);
+		return;
+	}
+
+	mhu_secure_message_start();
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD,
+		      (state << 8) | (uint32_t)select);
+	mhu_secure_message_send(scpi_cmd(SCPI_CMD_JTAG_SET_STATE, 4));
+	mhu_secure_message_wait();
+	mhu_secure_message_end();
+}
+
+uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size)
+{
+	uint32_t *response;
+	size_t resp_size;
+
+	if (size > 0x1FC)
+		return 0;
+
+	mhu_secure_message_start();
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, base);
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 4, size);
+	mhu_secure_message_send(scpi_cmd(SCPI_CMD_EFUSE_READ, 8));
+	scpi_secure_message_receive((void *)&response, &resp_size);
+	mhu_secure_message_end();
+
+	/*
+	 * response[0] is the size of the response message.
+	 * response[1 ... N] are the contents.
+	 */
+	if (*response != 0)
+		memcpy(dst, response + 1, *response);
+
+	return *response;
+}
+
+void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
+			  uint32_t arg2, uint32_t arg3)
+{
+	mhu_secure_message_start();
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x0, arg0);
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x4, arg1);
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x8, arg2);
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0xC, arg3);
+	mhu_secure_message_send(scpi_cmd(0xC3, 16));
+	mhu_secure_message_wait();
+	mhu_secure_message_end();
+}
diff --git a/plat/meson/gxbb/gxbb_sip_svc.c b/plat/meson/gxbb/gxbb_sip_svc.c
new file mode 100644
index 0000000..82ed449
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_sip_svc.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <runtime_svc.h>
+#include <stdint.h>
+
+#include "gxbb_private.h"
+
+/*******************************************************************************
+ * This function is responsible for handling all SiP calls
+ ******************************************************************************/
+static uintptr_t gxbb_sip_handler(uint32_t smc_fid,
+				  u_register_t x1, u_register_t x2,
+				  u_register_t x3, u_register_t x4,
+				  void *cookie, void *handle,
+				  u_register_t flags)
+{
+	switch (smc_fid) {
+
+	case GXBB_SM_GET_SHARE_MEM_INPUT_BASE:
+		SMC_RET1(handle, GXBB_SHARE_MEM_INPUT_BASE);
+
+	case GXBB_SM_GET_SHARE_MEM_OUTPUT_BASE:
+		SMC_RET1(handle, GXBB_SHARE_MEM_OUTPUT_BASE);
+
+	case GXBB_SM_EFUSE_READ:
+	{
+		void *dst = (void *)GXBB_SHARE_MEM_OUTPUT_BASE;
+		uint64_t ret = gxbb_efuse_read(dst, (uint32_t)x1, x2);
+
+		SMC_RET1(handle, ret);
+	}
+	case GXBB_SM_EFUSE_USER_MAX:
+		SMC_RET1(handle,  gxbb_efuse_user_max());
+
+	case GXBB_SM_JTAG_ON:
+		scpi_jtag_set_state(GXBB_JTAG_STATE_ON, x1);
+		SMC_RET1(handle, 0);
+
+	case GXBB_SM_JTAG_OFF:
+		scpi_jtag_set_state(GXBB_JTAG_STATE_OFF, x1);
+		SMC_RET1(handle, 0);
+
+	default:
+		ERROR("BL31: Unhandled SIP SMC: 0x%08x\n", smc_fid);
+		break;
+	}
+
+	SMC_RET1(handle, SMC_UNK);
+}
+
+DECLARE_RT_SVC(
+	gxbb_sip_handler,
+
+	OEN_SIP_START,
+	OEN_SIP_END,
+	SMC_TYPE_FAST,
+	NULL,
+	gxbb_sip_handler
+);
diff --git a/plat/meson/gxbb/gxbb_thermal.c b/plat/meson/gxbb/gxbb_thermal.c
new file mode 100644
index 0000000..b6048ee
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_thermal.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include "gxbb_private.h"
+
+static int32_t modules_initialized = -1;
+
+/*******************************************************************************
+ * Unknown commands related to something thermal-related
+ ******************************************************************************/
+void gxbb_thermal_unknown(void)
+{
+	uint16_t ret;
+
+	if (modules_initialized == -1) {
+		scpi_efuse_read(&ret, 0, 2);
+		modules_initialized = ret;
+	}
+
+	scpi_unknown_thermal(10, 2,  /* thermal */
+			     13, 1); /* thermalver */
+}
diff --git a/plat/meson/gxbb/gxbb_topology.c b/plat/meson/gxbb/gxbb_topology.c
new file mode 100644
index 0000000..49bb2dc
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_topology.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+#include "gxbb_private.h"
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+	/* Number of root nodes */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first node */
+	PLATFORM_CLUSTER0_CORE_COUNT
+};
+
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+		return -1;
+
+	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+		return -1;
+
+	if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
+		return -1;
+
+	return plat_gxbb_calc_core_pos(mpidr);
+}
diff --git a/plat/meson/gxbb/include/plat_macros.S b/plat/meson/gxbb/include/plat_macros.S
new file mode 100644
index 0000000..948b5f9
--- /dev/null
+++ b/plat/meson/gxbb/include/plat_macros.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <gicv2.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+
+gicc_regs:
+	.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant GIC and CCI registers
+	 * whenever an unhandled exception is taken in
+	 * BL31.
+	 * Clobbers: x0 - x10, x16, x17, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+
+	/* GICC registers */
+
+	mov_imm	x17, GXBB_GICC_BASE
+
+	adr	x6, gicc_regs
+	ldr	w8, [x17, #GICC_HPPIR]
+	ldr	w9, [x17, #GICC_AHPPIR]
+	ldr	w10, [x17, #GICC_CTLR]
+	bl	str_in_crash_buf_print
+
+	/* GICD registers */
+
+	mov_imm	x16, GXBB_GICD_BASE
+
+	add	x7, x16, #GICD_ISPENDR
+	adr	x4, gicd_pend_reg
+	bl	asm_print_str
+
+gicd_ispendr_loop:
+	sub	x4, x7, x16
+	cmp	x4, #0x280
+	b.eq	exit_print_gic_regs
+	bl	asm_print_hex
+
+	adr	x4, spacer
+	bl	asm_print_str
+
+	ldr	x4, [x7], #8
+	bl	asm_print_hex
+
+	adr	x4, newline
+	bl	asm_print_str
+	b	gicd_ispendr_loop
+exit_print_gic_regs:
+
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/meson/gxbb/include/platform_def.h b/plat/meson/gxbb/include/platform_def.h
new file mode 100644
index 0000000..a85637f
--- /dev/null
+++ b/plat/meson/gxbb/include/platform_def.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <utils_def.h>
+
+#include "../gxbb_def.h"
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define GXBB_BL31_PLAT_PARAM_VAL	ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE		UL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	U(4)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT		PLATFORM_CLUSTER0_CORE_COUNT
+
+#define GXBB_PRIMARY_CPU		U(0)
+
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_OFF_STATE		U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN		U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET		U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains. */
+#define PLAT_LOCAL_STATE_OFF		U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH		U(4)
+#define PLAT_LOCAL_PSTATE_MASK		((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT		U(6)
+#define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
+
+/* Memory-related defines */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS		12
+#define MAX_XLAT_TABLES			5
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/meson/gxbb/platform.mk b/plat/meson/gxbb/platform.mk
new file mode 100644
index 0000000..e6f5ae4
--- /dev/null
+++ b/plat/meson/gxbb/platform.mk
@@ -0,0 +1,78 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES		:=	-Iinclude/drivers/meson/		\
+				-Iplat/meson/gxbb/include
+
+GXBB_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v2/gicv2_main.c		\
+				drivers/arm/gic/v2/gicv2_helpers.c	\
+				plat/common/plat_gicv2.c
+
+PLAT_BL_COMMON_SOURCES	:=	drivers/console/aarch64/multi_console.S	\
+				drivers/meson/console/aarch64/meson_console.S \
+				plat/meson/gxbb/gxbb_common.c		\
+				plat/meson/gxbb/gxbb_topology.c		\
+				${XLAT_TABLES_LIB_SRCS}
+
+BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a53.S		\
+				plat/common/plat_psci_common.c		\
+				plat/meson/gxbb/aarch64/gxbb_helpers.S	\
+				plat/meson/gxbb/gxbb_bl31_setup.c	\
+				plat/meson/gxbb/gxbb_efuse.c		\
+				plat/meson/gxbb/gxbb_mhu.c		\
+				plat/meson/gxbb/gxbb_pm.c		\
+				plat/meson/gxbb/gxbb_scpi.c		\
+				plat/meson/gxbb/gxbb_sip_svc.c		\
+				plat/meson/gxbb/gxbb_thermal.c		\
+				${GXBB_GIC_SOURCES}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+    TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+    TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
+else
+    TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_826319		:= 1
+ERRATA_A53_835769		:= 1
+ERRATA_A53_836870		:= 1
+ERRATA_A53_843419		:= 1
+ERRATA_A53_855873		:= 1
+
+WORKAROUND_CVE_2017_5715	:= 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA	:= 1
+
+# Use Coherent memory
+USE_COHERENT_MEM		:= 1
+
+# Use multi console API
+MULTI_CONSOLE_API		:= 1
+
+# Verify build config
+# -------------------
+
+ifneq (${MULTI_CONSOLE_API}, 1)
+  $(error Error: gxbb needs MULTI_CONSOLE_API=1)
+endif
+
+ifneq (${RESET_TO_BL31}, 0)
+  $(error Error: gxbb needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+  $(error Error: AArch32 not supported on gxbb)
+endif
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index 3c490d0..0476ba8 100644
--- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -36,6 +36,7 @@
 	.globl	platform_mem_init
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
 	.globl	tegra_secure_entrypoint
 	.globl	plat_reset_handler
 
@@ -240,6 +241,20 @@
 	b	console_core_putc
 endfunc plat_crash_console_putc
 
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	adr	x0, tegra_console_base
+	ldr	x0, [x0]
+	b	console_core_flush
+endfunc plat_crash_console_flush
+
 	/* ---------------------------------------------------
 	 * Function to handle a platform reset and store
 	 * input parameters passed by BL2.
diff --git a/plat/qemu/include/platform_def.h b/plat/qemu/include/platform_def.h
index 55252c3..c2289bc 100644
--- a/plat/qemu/include/platform_def.h
+++ b/plat/qemu/include/platform_def.h
@@ -223,7 +223,7 @@
  * DT related constants
  */
 #define PLAT_QEMU_DT_BASE		NS_DRAM0_BASE
-#define PLAT_QEMU_DT_MAX_SIZE		0x10000
+#define PLAT_QEMU_DT_MAX_SIZE		0x100000
 
 /*
  * System counter
diff --git a/plat/qemu/platform.mk b/plat/qemu/platform.mk
index 9167c9f..982886a 100644
--- a/plat/qemu/platform.mk
+++ b/plat/qemu/platform.mk
@@ -38,24 +38,12 @@
 PLAT_INCLUDES		+=	-Iinclude/plat/arm/common/${ARCH}
 endif
 
-# Use translation tables library v2 by default
-ARM_XLAT_TABLES_LIB_V1		:=	0
-$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
-$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
-
-
 PLAT_BL_COMMON_SOURCES	:=	plat/qemu/qemu_common.c			  \
 				plat/qemu/qemu_console.c		  \
 				drivers/arm/pl011/${ARCH}/pl011_console.S \
 
-ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
-PLAT_BL_COMMON_SOURCES	+=	lib/xlat_tables/xlat_tables_common.c		\
-				lib/xlat_tables/${ARCH}/xlat_tables.c
-else
 include lib/xlat_tables_v2/xlat_tables.mk
-
 PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
-endif
 
 ifneq (${TRUSTED_BOARD_BOOT},0)
 
diff --git a/plat/qemu/qemu_common.c b/plat/qemu/qemu_common.c
index 376ff2f..43a3f70 100644
--- a/plat/qemu/qemu_common.c
+++ b/plat/qemu/qemu_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,7 +7,8 @@
 #include <arch_helpers.h>
 #include <bl_common.h>
 #include <platform_def.h>
-#include <arm_xlat_tables.h>
+#include <xlat_tables_v2.h>
+
 #include "qemu_private.h"
 
 #define MAP_DEVICE0	MAP_REGION_FLAT(DEVICE0_BASE,			\
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
index 560ccca..785f640 100644
--- a/plat/rockchip/rk3328/platform.mk
+++ b/plat/rockchip/rk3328/platform.mk
@@ -29,6 +29,7 @@
 
 PLAT_BL_COMMON_SOURCES	:=	lib/xlat_tables/aarch64/xlat_tables.c		\
 				lib/xlat_tables/xlat_tables_common.c		\
+				plat/common/aarch64/crash_console_helpers.S	\
 				plat/common/plat_psci_common.c
 
 BL31_SOURCES		+=	${RK_GIC_SOURCES}				\
diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk
index 050a2c4..a3e593e 100644
--- a/plat/rockchip/rk3368/platform.mk
+++ b/plat/rockchip/rk3368/platform.mk
@@ -26,6 +26,7 @@
 
 PLAT_BL_COMMON_SOURCES	:=	lib/xlat_tables/xlat_tables_common.c		\
 				lib/xlat_tables/aarch64/xlat_tables.c		\
+				plat/common/aarch64/crash_console_helpers.S	\
 				plat/common/plat_psci_common.c
 
 BL31_SOURCES		+=	${RK_GIC_SOURCES}				\
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 9120419..eccf1cc 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -32,6 +32,7 @@
 
 PLAT_BL_COMMON_SOURCES	:=	lib/xlat_tables/xlat_tables_common.c	\
 				lib/xlat_tables/aarch64/xlat_tables.c	\
+				plat/common/aarch64/crash_console_helpers.S \
 				plat/common/plat_psci_common.c
 
 BL31_SOURCES	+=	${RK_GIC_SOURCES}				\
diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk
index a7b0991..36c1ee2 100644
--- a/plat/rpi3/platform.mk
+++ b/plat/rpi3/platform.mk
@@ -4,12 +4,16 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+include lib/libfdt/libfdt.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
 PLAT_INCLUDES		:=	-Iinclude/common/tbbr			\
 				-Iplat/rpi3/include
 
 PLAT_BL_COMMON_SOURCES	:=	drivers/console/aarch64/console.S	\
 				drivers/ti/uart/aarch64/16550_console.S	\
-				plat/rpi3/rpi3_common.c
+				plat/rpi3/rpi3_common.c			\
+				${XLAT_TABLES_LIB_SRCS}
 
 BL1_SOURCES		+=	drivers/io/io_fip.c			\
 				drivers/io/io_memmap.c			\
@@ -37,12 +41,8 @@
 				plat/rpi3/aarch64/plat_helpers.S	\
 				plat/rpi3/rpi3_bl31_setup.c		\
 				plat/rpi3/rpi3_pm.c			\
-				plat/rpi3/rpi3_topology.c
-
-# Translation tables library
-include lib/xlat_tables_v2/xlat_tables.mk
-
-PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
+				plat/rpi3/rpi3_topology.c		\
+				${LIBFDT_SRCS}
 
 # Tune compiler for Cortex-A53
 ifeq ($(notdir $(CC)),armclang)
diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c
index 0ae783e..483d150 100644
--- a/plat/rpi3/rpi3_bl31_setup.c
+++ b/plat/rpi3/rpi3_bl31_setup.c
@@ -6,6 +6,7 @@
 
 #include <assert.h>
 #include <bl_common.h>
+#include <libfdt.h>
 #include <platform.h>
 #include <platform_def.h>
 #include <xlat_mmu_helpers.h>
@@ -137,12 +138,74 @@
 	enable_mmu_el3(0);
 }
 
+/*
+ * Add information to the device tree (if any) about the reserved DRAM used by
+ * the Trusted Firmware.
+ */
+static void rpi3_dtb_add_mem_rsv(void)
+{
+	int i, regions, rc;
+	uint64_t addr, size;
+	void *dtb = (void *)RPI3_PRELOADED_DTB_BASE;
+
+	INFO("rpi3: Checking DTB...\n");
+
+	/* Return if no device tree is detected */
+	if (fdt_check_header(dtb) != 0)
+		return;
+
+	regions = fdt_num_mem_rsv(dtb);
+
+	VERBOSE("rpi3: Found %d mem reserve region(s)\n", regions);
+
+	/* We expect to find one reserved region that we can modify */
+	if (regions < 1)
+		return;
+
+	/*
+	 * Look for the region that corresponds to the default boot firmware. It
+	 * starts at address 0, and it is not needed when the default firmware
+	 * is replaced by this port of the Trusted Firmware.
+	 */
+	for (i = 0; i < regions; i++) {
+		if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0)
+			continue;
+
+		if (addr != 0x0)
+			continue;
+
+		VERBOSE("rpi3: Firmware mem reserve region found\n");
+
+		rc = fdt_del_mem_rsv(dtb, i);
+		if (rc != 0) {
+			INFO("rpi3: Can't remove mem reserve region (%d)\n", rc);
+		}
+
+		break;
+	}
+
+	if (i == regions) {
+		VERBOSE("rpi3: Firmware mem reserve region not found\n");
+	}
+
+	/*
+	 * Reserve all SRAM. As said in the documentation, this isn't actually
+	 * secure memory, so it is needed to tell BL33 that this is a reserved
+	 * memory region. It doesn't guarantee it won't use it, though.
+	 */
+	rc = fdt_add_mem_rsv(dtb, SEC_SRAM_BASE, SEC_SRAM_SIZE);
+	if (rc != 0) {
+		WARN("rpi3: Can't add mem reserve region (%d)\n", rc);
+	}
+
+	INFO("rpi3: Reserved 0x%llx - 0x%llx in DTB\n", SEC_SRAM_BASE,
+	     SEC_SRAM_BASE + SEC_SRAM_SIZE);
+}
+
 void bl31_platform_setup(void)
 {
-	/*
-	 * Do initial security configuration to allow DRAM/device access
-	 * (if earlier BL has not already done so).
-	 */
-
-	return;
+#ifdef RPI3_PRELOADED_DTB_BASE
+	/* Only modify a DTB if we know where to look for it */
+	rpi3_dtb_add_mem_rsv();
+#endif
 }
diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c
index 98cf534..18ff1c8 100644
--- a/plat/rpi3/rpi3_common.c
+++ b/plat/rpi3/rpi3_common.c
@@ -23,7 +23,12 @@
 
 #define MAP_SHARED_RAM	MAP_REGION_FLAT(SHARED_RAM_BASE,		\
 					SHARED_RAM_SIZE,		\
-					MT_DEVICE  | MT_RW | MT_SECURE)
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#ifdef RPI3_PRELOADED_DTB_BASE
+#define MAP_NS_DTB	MAP_REGION_FLAT(RPI3_PRELOADED_DTB_BASE, 0x10000, \
+					MT_MEMORY | MT_RW | MT_NS)
+#endif
 
 #define MAP_NS_DRAM0	MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE,	\
 					MT_MEMORY | MT_RW | MT_NS)
@@ -74,6 +79,9 @@
 static const mmap_region_t plat_rpi3_mmap[] = {
 	MAP_SHARED_RAM,
 	MAP_DEVICE0,
+#ifdef RPI3_PRELOADED_DTB_BASE
+	MAP_NS_DTB,
+#endif
 #ifdef BL32_BASE
 	MAP_BL32_MEM,
 #endif
diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c
index 7346c0c..9a02312 100644
--- a/plat/st/stm32mp1/bl2_io_storage.c
+++ b/plat/st/stm32mp1/bl2_io_storage.c
@@ -8,12 +8,18 @@
 #include <assert.h>
 #include <boot_api.h>
 #include <debug.h>
+#include <io_block.h>
 #include <io_driver.h>
 #include <io_dummy.h>
+#include <io_mmc.h>
+#include <io_stm32image.h>
 #include <io_storage.h>
+#include <mmc.h>
 #include <mmio.h>
+#include <partition.h>
 #include <platform.h>
 #include <platform_def.h>
+#include <stm32_sdmmc2.h>
 #include <stm32mp1_private.h>
 #include <stm32mp1_rcc.h>
 #include <string.h>
@@ -24,6 +30,50 @@
 static uintptr_t dummy_dev_handle;
 static uintptr_t dummy_dev_spec;
 
+static uintptr_t image_dev_handle;
+
+static io_block_spec_t gpt_block_spec = {
+	.offset = 0,
+	.length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */
+};
+
+uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
+
+static const io_block_dev_spec_t mmc_block_dev_spec = {
+	/* It's used as temp buffer in block driver */
+	.buffer = {
+		.offset = (size_t)&block_buffer,
+		.length = MMC_BLOCK_SIZE,
+	},
+	.ops = {
+		.read = mmc_read_blocks,
+		.write = NULL,
+	},
+	.block_size = MMC_BLOCK_SIZE,
+};
+
+static uintptr_t storage_dev_handle;
+static const io_dev_connector_t *mmc_dev_con;
+
+#define IMG_IDX_BL33		0
+
+static const struct stm32image_part_info bl33_partition_spec = {
+	.name = BL33_IMAGE_NAME,
+	.binary_type = BL33_BINARY_TYPE,
+};
+
+static struct stm32image_device_info stm32image_dev_info_spec = {
+	.lba_size = MMC_BLOCK_SIZE,
+	.part_info[IMG_IDX_BL33] = {
+		.name = BL33_IMAGE_NAME,
+		.binary_type = BL33_BINARY_TYPE,
+	},
+};
+
+static io_block_spec_t stm32image_block_spec;
+
+static const io_dev_connector_t *stm32image_dev_con;
+
 static const io_block_spec_t bl32_block_spec = {
 	.offset = BL32_BASE,
 	.length = STM32MP1_BL32_SIZE
@@ -35,6 +85,8 @@
 };
 
 static int open_dummy(const uintptr_t spec);
+static int open_image(const uintptr_t spec);
+static int open_storage(const uintptr_t spec);
 
 struct plat_io_policy {
 	uintptr_t *dev_handle;
@@ -53,6 +105,21 @@
 		.image_spec = (uintptr_t)&bl32_block_spec,
 		.check = open_dummy
 	},
+	[BL33_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&bl33_partition_spec,
+		.check = open_image
+	},
+	[GPT_IMAGE_ID] = {
+		.dev_handle = &storage_dev_handle,
+		.image_spec = (uintptr_t)&gpt_block_spec,
+		.check = open_storage
+	},
+	[STM32_IMAGE_ID] = {
+		.dev_handle = &storage_dev_handle,
+		.image_spec = (uintptr_t)&stm32image_block_spec,
+		.check = open_storage
+	}
 };
 
 static int open_dummy(const uintptr_t spec)
@@ -60,6 +127,16 @@
 	return io_dev_init(dummy_dev_handle, 0);
 }
 
+static int open_image(const uintptr_t spec)
+{
+	return io_dev_init(image_dev_handle, 0);
+}
+
+static int open_storage(const uintptr_t spec)
+{
+	return io_dev_init(storage_dev_handle, 0);
+}
+
 static void print_boot_device(boot_api_context_t *boot_context)
 {
 	switch (boot_context->boot_interface_selected) {
@@ -149,6 +226,9 @@
 void stm32mp1_io_setup(void)
 {
 	int io_result __unused;
+	struct stm32_sdmmc2_params params;
+	struct mmc_device_info device_info;
+	uintptr_t mmc_default_instance;
 	boot_api_context_t *boot_context =
 		(boot_api_context_t *)stm32mp1_get_boot_ctx_address();
 
@@ -168,6 +248,93 @@
 	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
 				&dummy_dev_handle);
 	assert(io_result == 0);
+
+	switch (boot_context->boot_interface_selected) {
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		dmb();
+
+		memset(&params, 0, sizeof(struct stm32_sdmmc2_params));
+
+		if (boot_context->boot_interface_selected ==
+		    BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) {
+			device_info.mmc_dev_type = MMC_IS_EMMC;
+			mmc_default_instance = STM32MP1_SDMMC2_BASE;
+		} else {
+			device_info.mmc_dev_type = MMC_IS_SD;
+			mmc_default_instance = STM32MP1_SDMMC1_BASE;
+		}
+
+		switch (boot_context->boot_interface_instance) {
+		case 1:
+			params.reg_base = STM32MP1_SDMMC1_BASE;
+			break;
+		case 2:
+			params.reg_base = STM32MP1_SDMMC2_BASE;
+			break;
+		case 3:
+			params.reg_base = STM32MP1_SDMMC3_BASE;
+			break;
+		default:
+			WARN("SDMMC instance not found, using default\n");
+			params.reg_base = mmc_default_instance;
+			break;
+		}
+
+		params.device_info = &device_info;
+		stm32_sdmmc2_mmc_init(&params);
+
+		/* Open MMC as a block device to read GPT table */
+		io_result = register_io_dev_block(&mmc_dev_con);
+		if (io_result != 0) {
+			panic();
+		}
+
+		io_result = io_dev_open(mmc_dev_con,
+					(uintptr_t)&mmc_block_dev_spec,
+					&storage_dev_handle);
+		assert(io_result == 0);
+
+		partition_init(GPT_IMAGE_ID);
+
+		io_result = io_dev_close(storage_dev_handle);
+		assert(io_result == 0);
+
+		stm32image_dev_info_spec.device_size =
+			stm32_sdmmc2_mmc_get_device_size();
+		stm32image_dev_info_spec.part_info[IMG_IDX_BL33].part_offset =
+			get_partition_entry(BL33_IMAGE_NAME)->start;
+		stm32image_dev_info_spec.part_info[IMG_IDX_BL33].bkp_offset =
+			get_partition_entry(BL33_IMAGE_NAME)->length;
+
+		stm32image_block_spec.offset = 0;
+		stm32image_block_spec.length =
+			get_partition_entry(BL33_IMAGE_NAME)->length;
+
+		/*
+		 * Re-open MMC with io_mmc, for better perfs compared to
+		 * io_block.
+		 */
+		io_result = register_io_dev_mmc(&mmc_dev_con);
+		assert(io_result == 0);
+
+		io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
+		assert(io_result == 0);
+
+		io_result = register_io_dev_stm32image(&stm32image_dev_con);
+		assert(io_result == 0);
+
+		io_result = io_dev_open(stm32image_dev_con,
+					(uintptr_t)&stm32image_dev_info_spec,
+					&image_dev_handle);
+		assert(io_result == 0);
+		break;
+
+	default:
+		ERROR("Boot interface %d not supported\n",
+		      boot_context->boot_interface_selected);
+		break;
+	}
 }
 
 /*
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index 71c3593..e019cff 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #define __BOOT_API_H
 
 #include <stdint.h>
+#include <stdio.h>
 
 /*
  * Possible value of boot context field 'boot_interface_sel'
@@ -229,7 +230,9 @@
 	 */
 	uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
 	/* Pad up to 256 byte total size */
-	uint8_t pad[84];
+	uint8_t pad[83];
+	/* Add binary type information */
+	uint8_t binary_type;
 } __packed boot_api_image_header_t;
 
 #endif /* __BOOT_API_H */
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 47e1ffc..2ba6cc6 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -26,6 +26,7 @@
 
 /* SSBL = second stage boot loader */
 #define BL33_IMAGE_NAME			"ssbl"
+#define BL33_BINARY_TYPE		U(0x0)
 
 #define STM32MP1_PRIMARY_CPU		U(0x0)
 
@@ -39,6 +40,7 @@
 
 #define MAX_IO_DEVICES			4
 #define MAX_IO_HANDLES			4
+#define MAX_IO_BLOCK_DEVICES		1
 
 /*******************************************************************************
  * BL2 specific defines.
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 30b2932..678a852 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -14,8 +14,15 @@
 # Not needed for Cortex-A7
 WORKAROUND_CVE_2017_5715:=	0
 
+# Number of TF-A copies in the device
+STM32_TF_A_COPIES		:=	2
+$(eval $(call add_define,STM32_TF_A_COPIES))
+PLAT_PARTITION_MAX_ENTRIES	:=	$(shell echo $$(($(STM32_TF_A_COPIES) + 1)))
+$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
+
 PLAT_INCLUDES		:=	-Iplat/st/stm32mp1/include/
 PLAT_INCLUDES		+=	-Iinclude/common/tbbr
+PLAT_INCLUDES		+=	-Iinclude/drivers/partition
 PLAT_INCLUDES		+=	-Iinclude/drivers/st
 
 # Device tree
@@ -56,11 +63,19 @@
 				plat/st/stm32mp1/stm32mp1_helper.S			\
 				plat/st/stm32mp1/stm32mp1_security.c
 
-BL2_SOURCES		+=	drivers/io/io_dummy.c					\
+BL2_SOURCES		+=	drivers/io/io_block.c					\
+				drivers/io/io_dummy.c					\
 				drivers/io/io_storage.c					\
+				drivers/st/io/io_stm32image.c				\
 				plat/st/stm32mp1/bl2_io_storage.c			\
 				plat/st/stm32mp1/bl2_plat_setup.c
 
+BL2_SOURCES		+=	drivers/mmc/mmc.c					\
+				drivers/partition/gpt.c					\
+				drivers/partition/partition.c				\
+				drivers/st/io/io_mmc.c					\
+				drivers/st/mmc/stm32_sdmmc2.c
+
 BL2_SOURCES		+=	drivers/st/ddr/stm32mp1_ddr.c				\
 				drivers/st/ddr/stm32mp1_ram.c
 
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index bb3fecf..2224498 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -155,10 +155,9 @@
 #define STM32MP1_SDMMC2_BASE		U(0x58007000)
 #define STM32MP1_SDMMC3_BASE		U(0x48004000)
 
-#define STM32MP1_SD_INIT_FREQ			400000		/*400 KHz*/
+#define STM32MP1_MMC_INIT_FREQ			400000		/*400 KHz*/
 #define STM32MP1_SD_NORMAL_SPEED_MAX_FREQ	25000000	/*25 MHz*/
 #define STM32MP1_SD_HIGH_SPEED_MAX_FREQ		50000000	/*50 MHz*/
-#define STM32MP1_EMMC_INIT_FREQ			STM32MP1_SD_INIT_FREQ
 #define STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ	26000000	/*26 MHz*/
 #define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ	52000000	/*52 MHz*/
 
diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
index f84b9d4..e438dc3 100644
--- a/plat/ti/k3/common/k3_bl31_setup.c
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -108,7 +108,7 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 	enable_mmu_el3(0);
 }
 
diff --git a/plat/ti/k3/common/k3_helpers.S b/plat/ti/k3/common/k3_helpers.S
index c95e9c3..3dfdda4 100644
--- a/plat/ti/k3/common/k3_helpers.S
+++ b/plat/ti/k3/common/k3_helpers.S
@@ -100,13 +100,13 @@
 	 * Clobber list : x0 - x4
 	 * ---------------------------------------------
 	 */
+	.globl plat_crash_console_init
 func plat_crash_console_init
 	mov_imm	x0, CRASH_CONSOLE_BASE
 	mov_imm	x1, CRASH_CONSOLE_CLK
 	mov_imm	x2, CRASH_CONSOLE_BAUD_RATE
 	mov w3, #0x0
-	b	console_core_init
-
+	b	console_16550_core_init
 endfunc plat_crash_console_init
 
 	/* ---------------------------------------------
@@ -116,7 +116,22 @@
 	 * Clobber list : x1, x2
 	 * ---------------------------------------------
 	 */
+	.globl plat_crash_console_putc
 func plat_crash_console_putc
 	mov_imm	x1, CRASH_CONSOLE_BASE
-	b	console_core_putc
+	b	console_16550_core_putc
 endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+	.globl plat_crash_console_flush
+func plat_crash_console_flush
+	mov_imm	x0, CRASH_CONSOLE_BASE
+	b	console_16550_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
index ad960f4..969d8fa 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,12 @@
 
 	.globl	plat_secondary_cold_boot_setup
 	.globl	plat_is_my_cpu_primary
+	.globl	zynqmp_calc_core_pos
+	.globl	plat_my_core_pos
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
+	.globl	platform_mem_init
 
 	/* -----------------------------------------------------
 	 * void plat_secondary_cold_boot_setup (void);
@@ -47,3 +53,76 @@
 	cset	x0, eq
 	ret	x9
 endfunc plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the zynqmp_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	zynqmp_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 *  unsigned int zynqmp_calc_core_pos(u_register_t mpidr)
+	 *  Helper function to calculate the core position.
+	 *  With this function: CorePos = (ClusterId * 4) +
+	 *  				  CoreId
+	 * -----------------------------------------------------
+	 */
+func zynqmp_calc_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc zynqmp_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, ZYNQMP_CRASH_UART_BASE
+	mov_imm	x1, ZYNQMP_CRASH_UART_CLK_IN_HZ
+	mov_imm	x2, ZYNQMP_UART_BAUDRATE
+	b	console_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, ZYNQMP_CRASH_UART_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : r0
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm	x0, ZYNQMP_CRASH_UART_BASE
+	b	console_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/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index a14388f..0163450 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -193,6 +193,6 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 	enable_mmu_el3(0);
 }
diff --git a/plat/xilinx/zynqmp/plat_zynqmp.c b/plat/xilinx/zynqmp/plat_zynqmp.c
index cbfa935..2441630 100644
--- a/plat/xilinx/zynqmp/plat_zynqmp.c
+++ b/plat/xilinx/zynqmp/plat_zynqmp.c
@@ -1,10 +1,11 @@
 /*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <plat_arm.h>
+#include <platform.h>
+#include "zynqmp_private.h"
 
 int plat_core_pos_by_mpidr(u_register_t mpidr)
 {
@@ -14,5 +15,5 @@
 	if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT)
 		return -1;
 
-	return plat_arm_calc_core_pos(mpidr);
+	return zynqmp_calc_core_pos(mpidr);
 }
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 53d93c3..35c8983 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -16,10 +16,6 @@
 
 WORKAROUND_CVE_2017_5715	:=	0
 
-ARM_XLAT_TABLES_LIB_V1		:=	1
-$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
-$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
-
 ifdef ZYNQMP_ATF_MEM_BASE
     $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE))
 
@@ -64,7 +60,6 @@
 				drivers/arm/gic/v2/gicv2_helpers.c		\
 				drivers/cadence/uart/aarch64/cdns_console.S	\
 				drivers/console/aarch64/console.S		\
-				plat/arm/common/aarch64/arm_helpers.S		\
 				plat/arm/common/arm_cci.c			\
 				plat/arm/common/arm_common.c			\
 				plat/arm/common/arm_gicv2.c			\
diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
index 52d4bf8..a27f34b 100644
--- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
+++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -57,6 +57,6 @@
 		{0}
 	};
 
-	arm_setup_page_tables(bl_regions, plat_arm_get_mmap());
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
 	enable_mmu_el1(0);
 }
diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h
index 50a7331..9d19b1b 100644
--- a/plat/xilinx/zynqmp/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/zynqmp_def.h
@@ -145,13 +145,11 @@
 # error "invalid ZYNQMP_CONSOLE"
 #endif
 
-#define PLAT_ARM_CRASH_UART_BASE	ZYNQMP_UART_BASE
+#define ZYNQMP_CRASH_UART_BASE		ZYNQMP_UART_BASE
 /* impossible to call C routine how it is done now - hardcode any value */
-#define	PLAT_ARM_CRASH_UART_CLK_IN_HZ	100000000 /* FIXME */
-
+#define ZYNQMP_CRASH_UART_CLK_IN_HZ	100000000 /* FIXME */
 /* Must be non zero */
-#define ZYNQMP_UART_BAUDRATE	115200
-#define ARM_CONSOLE_BAUDRATE	ZYNQMP_UART_BAUDRATE
+#define ZYNQMP_UART_BAUDRATE		115200
 
 /* Silicon version detection */
 #define ZYNQMP_SILICON_VER_MASK		0xF000
diff --git a/plat/xilinx/zynqmp/zynqmp_private.h b/plat/xilinx/zynqmp/zynqmp_private.h
index 08a5410..d5024c3 100644
--- a/plat/xilinx/zynqmp/zynqmp_private.h
+++ b/plat/xilinx/zynqmp/zynqmp_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,9 +9,12 @@
 
 #include <bl_common.h>
 #include <interrupt_mgmt.h>
+#include <stdint.h>
 
 void zynqmp_config_setup(void);
 
+unsigned int zynqmp_calc_core_pos(u_register_t mpidr);
+
 /* ZynqMP specific functions */
 unsigned int zynqmp_get_uart_clk(void);
 unsigned int zynqmp_get_bootmode(void);
diff --git a/readme.rst b/readme.rst
index f2a7a00..e7fbfb4 100644
--- a/readme.rst
+++ b/readme.rst
@@ -193,6 +193,7 @@
 This release also contains the following platform support:
 
 -  Allwinner sun50i_64 and sun50i_h6
+-  Amlogic Meson S905 (GXBB)
 -  ARM SGI-575 and SGM-775
 -  HiKey, HiKey960 and Poplar boards
 -  Marvell Armada 8K
diff --git a/services/std_svc/sdei/sdei_private.h b/services/std_svc/sdei/sdei_private.h
index f5197c6..8212667 100644
--- a/services/std_svc/sdei/sdei_private.h
+++ b/services/std_svc/sdei/sdei_private.h
@@ -8,6 +8,7 @@
 #define SDEI_PRIVATE_H
 
 #include <arch_helpers.h>
+#include <context.h>
 #include <context_mgmt.h>
 #include <debug.h>
 #include <errno.h>
diff --git a/tools/stm32image/stm32image.c b/tools/stm32image/stm32image.c
index 2607928..41024e2 100644
--- a/tools/stm32image/stm32image.c
+++ b/tools/stm32image/stm32image.c
@@ -22,7 +22,7 @@
 #define VER_MINOR		1
 #define VER_VARIANT		0
 #define HEADER_VERSION_V1	0x1
-#define TF_BINARY_TYPE		0x0
+#define TF_BINARY_TYPE		0x10
 
 /* Default option : bit0 => no signature */
 #define HEADER_DEFAULT_OPTION	(__cpu_to_le32(0x00000001))