Merge pull request #1410 from Anson-Huang/master

Add NXP's i.MX8QX and i.MX8QM SoC support
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
new file mode 100644
index 0000000..a7e84a3
--- /dev/null
+++ b/docs/plat/allwinner.rst
@@ -0,0 +1,29 @@
+Trusted Firmware-A for Allwinner ARMv8 SoCs
+===========================================
+
+Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Allwinner
+SoCs with ARMv8 cores. Only BL31 is used to provide proper EL3 setup and
+PSCI runtime services.
+U-Boot's SPL acts as a loader, loading both BL31 and BL33 (typically U-Boot).
+Loading is done from SD card, eMMC or SPI flash, also via an USB debug
+interface (FEL).
+BL31 lives in SRAM A2, which is documented to be accessible from secure
+world only.
+
+Current limitations:
+
+-  Missing PMIC support
+
+After building bl31.bin, the binary must be fed to the U-Boot build system
+to include it in the FIT image that the SPL loader will process.
+bl31.bin can be either copied (or sym-linked) into U-Boot's root directory,
+or the environment variable BL31 must contain the binary's path.
+See the respective `U-Boot documentation`_ for more details.
+
+To build:
+
+::
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_a64 DEBUG=1 bl31
+
+.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
diff --git a/include/drivers/console.h b/include/drivers/console.h
index a4d89fe..6e7ebbf 100644
--- a/include/drivers/console.h
+++ b/include/drivers/console.h
@@ -16,9 +16,9 @@
 #define CONSOLE_T_FLUSH			(U(4) * REGSZ)
 #define CONSOLE_T_DRVDATA		(U(5) * REGSZ)
 
-#define CONSOLE_FLAG_BOOT		BIT(0)
-#define CONSOLE_FLAG_RUNTIME		BIT(1)
-#define CONSOLE_FLAG_CRASH		BIT(2)
+#define CONSOLE_FLAG_BOOT		(U(1) << 0)
+#define CONSOLE_FLAG_RUNTIME		(U(1) << 1)
+#define CONSOLE_FLAG_CRASH		(U(1) << 2)
 /* Bits 3 to 7 reserved for additional scopes in future expansion. */
 #define CONSOLE_FLAG_SCOPE_MASK		((U(1) << 8) - 1)
 /* Bits 8 to 31 reserved for non-scope use in future expansion. */
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 2d8e4c1..030e067 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -89,7 +89,7 @@
 #if TRUSTED_BOARD_BOOT
 # define PLAT_ARM_MAX_BL2_SIZE		0x1E000
 #else
-# define PLAT_ARM_MAX_BL2_SIZE		0x10000
+# define PLAT_ARM_MAX_BL2_SIZE		0x11000
 #endif
 
 /*
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index fc3f4ec..33f2c7d 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -155,6 +155,12 @@
 void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data,
 			const arm_tzc_regions_info_t *tzc_regions);
 
+/* Console utility functions */
+void arm_console_boot_init(void);
+void arm_console_boot_end(void);
+void arm_console_runtime_init(void);
+void arm_console_runtime_end(void);
+
 /* Systimer utility function */
 void arm_configure_sys_timer(void);
 
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index 07fadd1..8e60445 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -404,6 +404,7 @@
 #if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
 	adr	x0, wa_cve_2017_5715_mmu_vbar
 	msr	vbar_el3, x0
+	/* isb will be performed before returning from this function */
 #endif
 
 #if WORKAROUND_CVE_2018_3639
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index bb9381d..38b76b9 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -137,6 +137,7 @@
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_mmu_vbar
 	msr	vbar_el3, x0
+	/* isb will be performed before returning from this function */
 1:
 #endif
 
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index d595f12..b796561 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -40,6 +40,7 @@
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_bpiall_vbar
 	msr	vbar_el3, x0
+	/* isb will be performed before returning from this function */
 1:
 #endif
 
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 20ec32c..73f566f 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -15,6 +15,7 @@
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_bpiall_vbar
 	msr	vbar_el3, x0
+	isb
 1:
 #endif
 
diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c
index 31d3365..a38f97f 100644
--- a/lib/xlat_tables_v2/xlat_tables_internal.c
+++ b/lib/xlat_tables_v2/xlat_tables_internal.c
@@ -784,8 +784,8 @@
 	       && mm_cursor->size)
 		++mm_cursor;
 
-	while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va)
-	       && (mm_cursor->size < mm->size))
+	while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va) &&
+	       (mm_cursor->size != 0U) && (mm_cursor->size < mm->size))
 		++mm_cursor;
 
 	/*
diff --git a/maintainers.rst b/maintainers.rst
index 195f1f3..81c30c0 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -64,6 +64,16 @@
 -  plat/hisilicon/hikey/\*
 -  plat/hisilicon/hikey960/\*
 
+Allwinner ARMv8 platform sub-maintainer
+---------------------------------------
+
+Andre Przywara (andre.przywara@arm.com, `Andre-ARM`_)
+
+Files:
+
+-  docs/plat/allwinner.rst
+-  plat/allwinner/\*
+
 HiSilicon Poplar platform sub-maintainer
 ----------------------------------------
 
@@ -161,3 +171,4 @@
 .. _rockchip-linux: https://github.com/rockchip-linux
 .. _etienne-lms: https://github.com/etienne-lms
 .. _qoriq-open-source: https://github.com/qoriq-open-source
+.. _Andre-ARM: https://github.com/Andre-ARM
diff --git a/plat/allwinner/common/include/plat_macros.S b/plat/allwinner/common/include/plat_macros.S
new file mode 100644
index 0000000..6ee4597
--- /dev/null
+++ b/plat/allwinner/common/include/plat_macros.S
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+#include <arm_macros.S>
+#include <sunxi_mmap.h>
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant GIC and CCI registers
+	 * whenever an unhandled exception is taken in
+	 * BL31.
+	 * Clobbers: x0 - x10, x16, x17, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	mov_imm	x17, SUNXI_GICC_BASE
+	mov_imm	x16, SUNXI_GICD_BASE
+	arm_print_gic_regs
+	.endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
new file mode 100644
index 0000000..ca7db2f
--- /dev/null
+++ b/plat/allwinner/common/include/platform_def.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <common_def.h>
+#include <sunxi_mmap.h>
+#include <tbbr/tbbr_img_def.h>
+
+#define BL31_BASE			SUNXI_SRAM_A2_BASE
+#define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE)
+
+/* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */
+#define PLAT_SUNXI_NS_IMAGE_OFFSET	(SUNXI_DRAM_BASE + (160U << 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 PLAT_MAX_PWR_LVL_STATES		2
+#define PLAT_MAX_RET_STATE		1
+#define PLAT_MAX_OFF_STATE		2
+
+#define PLAT_MAX_PWR_LVL		2
+#define PLAT_NUM_PWR_DOMAINS		(1 + \
+					 PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+
+#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		4
+#define PLATFORM_STACK_SIZE		(0x1000 / PLATFORM_CORE_COUNT)
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
new file mode 100644
index 0000000..e68fbe4
--- /dev/null
+++ b/plat/allwinner/common/include/sunxi_def.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_DEF_H__
+#define __SUNXI_DEF_H__
+
+/* Clock configuration */
+#define SUNXI_OSC24M_CLK_IN_HZ		24000000
+
+/* UART configuration */
+#define SUNXI_UART0_BAUDRATE		115200
+#define SUNXI_UART0_CLK_IN_HZ		SUNXI_OSC24M_CLK_IN_HZ
+
+#endif /* __SUNXI_DEF_H__ */
diff --git a/plat/allwinner/common/plat_helpers.S b/plat/allwinner/common/plat_helpers.S
new file mode 100644
index 0000000..b00c7ae
--- /dev/null
+++ b/plat/allwinner/common/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
+	.globl	plat_my_core_pos
+	.globl	platform_mem_init
+	.globl	plat_report_exception
+
+func plat_crash_console_init
+	mov_imm x0, SUNXI_UART0_BASE
+	mov_imm x1, SUNXI_UART0_CLK_IN_HZ
+	mov_imm x2, SUNXI_UART0_BAUDRATE
+	b	console_16550_core_init
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+	mov_imm x1, SUNXI_UART0_BASE
+	b	console_16550_core_putc
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+	ret
+endfunc plat_crash_console_flush
+
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	and	x1, x0, #MPIDR_CLUSTER_MASK
+	and	x0, x0, #MPIDR_CPU_MASK
+	add	x0, x0, x1, LSR #6
+	ret
+endfunc plat_my_core_pos
+
+func platform_mem_init
+	ret
+endfunc platform_mem_init
+
+func plat_report_exception
+	ret
+endfunc plat_report_exception
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
new file mode 100644
index 0000000..d1f1aa1
--- /dev/null
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <generic_delay_timer.h>
+#include <gicv2.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <uart_16550.h>
+
+#include "sunxi_private.h"
+
+static entry_point_info_t bl33_image_ep_info;
+
+static console_16550_t console;
+
+static const gicv2_driver_data_t sunxi_gic_data = {
+	.gicd_base = SUNXI_GICD_BASE,
+	.gicc_base = SUNXI_GICC_BASE,
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	/* Initialize the debug console as soon as possible */
+	console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ,
+			       SUNXI_UART0_BAUDRATE, &console);
+
+	/* Populate entry point information for BL33 */
+	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+	/*
+	 * Tell BL31 where the non-trusted software image
+	 * is located and the entry state information
+	 */
+	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+					  DISABLE_ALL_EXCEPTIONS);
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+	/* Turn off all secondary CPUs */
+	sunxi_disable_secondary_cpus(plat_my_core_pos());
+}
+
+void bl31_plat_arch_setup(void)
+{
+	sunxi_configure_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	generic_delay_timer_init();
+
+	/* Configure the interrupt controller */
+	gicv2_driver_init(&sunxi_gic_data);
+	gicv2_distif_init();
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+
+	sunxi_security_setup();
+
+	INFO("BL31: Platform setup done\n");
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	assert(sec_state_is_valid(type) != 0);
+	assert(type == NON_SECURE);
+
+	return &bl33_image_ep_info;
+}
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
new file mode 100644
index 0000000..e36c8b0
--- /dev/null
+++ b/plat/allwinner/common/sunxi_common.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+#include <platform_def.h>
+#include <sunxi_def.h>
+#include <xlat_tables_v2.h>
+
+static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
+	MAP_REGION_FLAT(SUNXI_ROM_BASE, SUNXI_ROM_SIZE,
+			MT_MEMORY | MT_RO | MT_SECURE),
+	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),
+	{},
+};
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SUNXI_OSC24M_CLK_IN_HZ;
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	return PLAT_SUNXI_NS_IMAGE_OFFSET;
+#endif
+}
+
+void sunxi_configure_mmu_el3(int flags)
+{
+	mmap_add_region(BL31_BASE, BL31_BASE,
+			BL31_LIMIT - BL31_BASE,
+			MT_MEMORY | MT_RW | MT_SECURE);
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+			BL_CODE_END - BL_CODE_BASE,
+			MT_CODE | MT_SECURE);
+	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();
+
+	enable_mmu_el3(0);
+}
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
new file mode 100644
index 0000000..be72dee
--- /dev/null
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-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 <sunxi_mmap.h>
+#include <sunxi_cpucfg.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)
+		return;
+
+	INFO("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
+
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff);
+}
+
+static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core)
+{
+	if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0)
+		return;
+
+	INFO("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
+
+	/* Power enable sequence from original Allwinner sources */
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe);
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8);
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
+}
+
+void sunxi_cpu_off(unsigned int cluster, unsigned int core)
+{
+	INFO("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);
+}
+
+void sunxi_cpu_on(unsigned int cluster, unsigned int core)
+{
+	INFO("PSCI: Powering on cluster %d core %d\n", cluster, core);
+
+	/* Assert CPU core reset */
+	mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
+	/* Assert CPU power-on reset */
+	mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+	/* Set CPU to start in AArch64 mode */
+	mmio_setbits_32(SUNXI_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + core));
+	/* Apply power to the CPU */
+	sunxi_cpu_enable_power(cluster, core);
+	/* Release the core output clamps */
+	mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
+	/* Deassert CPU power-on reset */
+	mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+	/* Deassert CPU core reset */
+	mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
+	/* Assert DBGPWRDUP */
+	mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+}
+
+void sunxi_disable_secondary_cpus(unsigned int primary_cpu)
+{
+	for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) {
+		if (cpu == primary_cpu)
+			continue;
+		sunxi_cpu_off(cpu / PLATFORM_MAX_CPUS_PER_CLUSTER,
+			       cpu % PLATFORM_MAX_CPUS_PER_CLUSTER);
+	}
+}
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
new file mode 100644
index 0000000..fcab130
--- /dev/null
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <sunxi_mmap.h>
+#include <sunxi_cpucfg.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 && \
+	MPIDR_AFFLVL1_VAL(mpidr) < PLATFORM_CLUSTER_COUNT && \
+	MPIDR_AFFLVL0_VAL(mpidr) < PLATFORM_MAX_CPUS_PER_CLUSTER)
+
+static int sunxi_pwr_domain_on(u_register_t mpidr)
+{
+	if (mpidr_is_valid(mpidr) == 0)
+		return PSCI_E_INTERN_FAIL;
+
+	sunxi_cpu_on(MPIDR_AFFLVL1_VAL(mpidr), MPIDR_AFFLVL0_VAL(mpidr));
+
+	return PSCI_E_SUCCESS;
+}
+
+static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	gicv2_cpuif_disable();
+}
+
+static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+}
+
+static void __dead2 sunxi_system_off(void)
+{
+	/* Turn off all secondary CPUs */
+	sunxi_disable_secondary_cpus(plat_my_core_pos());
+
+	ERROR("PSCI: Full shutdown not implemented, halting\n");
+	wfi();
+	panic();
+}
+
+static void __dead2 sunxi_system_reset(void)
+{
+	/* Reset the whole system when the watchdog times out */
+	mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
+	/* Enable the watchdog with the shortest timeout (0.5 seconds) */
+	mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
+	/* Wait for twice the watchdog timeout before panicking */
+	mdelay(1000);
+
+	ERROR("PSCI: System reset failed\n");
+	wfi();
+	panic();
+}
+
+static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+	/* The non-secure entry point must be in DRAM */
+	if (ns_entrypoint >= SUNXI_DRAM_BASE &&
+	    ns_entrypoint < SUNXI_DRAM_BASE + SUNXI_DRAM_SIZE)
+		return PSCI_E_SUCCESS;
+
+	return PSCI_E_INVALID_ADDRESS;
+}
+
+static plat_psci_ops_t sunxi_psci_ops = {
+	.pwr_domain_on			= sunxi_pwr_domain_on,
+	.pwr_domain_off			= sunxi_pwr_domain_off,
+	.pwr_domain_on_finish		= sunxi_pwr_domain_on_finish,
+	.system_off			= sunxi_system_off,
+	.system_reset			= sunxi_system_reset,
+	.validate_ns_entrypoint		= sunxi_validate_ns_entrypoint,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	assert(psci_ops);
+
+	for (int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) {
+		mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
+			      sec_entrypoint & 0xffffffff);
+		mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
+			      sec_entrypoint >> 32);
+	}
+
+	*psci_ops = &sunxi_psci_ops;
+
+	return 0;
+}
diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/sunxi_private.h
new file mode 100644
index 0000000..b9f0fb4
--- /dev/null
+++ b/plat/allwinner/common/sunxi_private.h
@@ -0,0 +1,17 @@
+/*
+ * 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);
+
+void sunxi_security_setup(void);
+
+#endif /* __SUNXI_PRIVATE_H__ */
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
new file mode 100644
index 0000000..e760072
--- /dev/null
+++ b/plat/allwinner/common/sunxi_security.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <sunxi_mmap.h>
+
+#ifdef SUNXI_SPC_BASE
+#define SPC_DECPORT_STA_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4)
+#define SPC_DECPORT_SET_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0x8)
+#define SPC_DECPORT_CLR_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0xc)
+#endif
+
+#define R_PRCM_SEC_SWITCH_REG	0x1d0
+#define DMA_SEC_REG		0x20
+
+/*
+ * Setup the peripherals to be accessible by non-secure world.
+ * This will not work for the Secure Peripherals Controller (SPC) unless
+ * a fuse it burnt (seems to be an erratum), but we do it nevertheless,
+ * to allow booting on boards using secure boot.
+ */
+void sunxi_security_setup(void)
+{
+	int i;
+
+#ifdef SUNXI_SPC_BASE
+	INFO("Configuring SPC Controller\n");
+	/* SPC setup: set all devices to non-secure */
+	for (i = 0; i < 6; i++)
+		mmio_write_32(SPC_DECPORT_SET_REG(i), 0xff);
+#endif
+
+	/* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */
+	mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7);
+
+	/* set R_PRCM clocks to non-secure */
+	mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x7);
+
+	/* Set all DMA channels (16 max.) to non-secure */
+	mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
+}
diff --git a/plat/allwinner/common/sunxi_topology.c b/plat/allwinner/common/sunxi_topology.c
new file mode 100644
index 0000000..98cf63c
--- /dev/null
+++ b/plat/allwinner/common/sunxi_topology.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform.h>
+#include <platform_def.h>
+
+static unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = {
+	/* One root node for the SoC */
+	1,
+	/* One node for each cluster */
+	PLATFORM_CLUSTER_COUNT,
+	/* One set of CPUs per cluster */
+	PLATFORM_MAX_CPUS_PER_CLUSTER,
+};
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+	unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+	if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+	    MPIDR_AFFLVL2_VAL(mpidr) > 0 ||
+	    cluster >= PLATFORM_CLUSTER_COUNT ||
+	    core >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+		return -1;
+	}
+
+	return cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core;
+}
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return plat_power_domain_tree_desc;
+}
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..049c2ad
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_CPUCFG_H__
+#define __SUNXI_CPUCFG_H__
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c)	(SUNXI_CPUCFG_BASE + 0x0000 + (c) * 16)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c)	(SUNXI_CPUCFG_BASE + 0x0004 + (c) * 16)
+#define SUNXI_CPUCFG_CACHE_CFG_REG0	(SUNXI_CPUCFG_BASE + 0x0008)
+#define SUNXI_CPUCFG_CACHE_CFG_REG1	(SUNXI_CPUCFG_BASE + 0x000c)
+#define SUNXI_CPUCFG_DBG_REG0		(SUNXI_CPUCFG_BASE + 0x0020)
+#define SUNXI_CPUCFG_GLB_CTRL_REG	(SUNXI_CPUCFG_BASE + 0x0028)
+#define SUNXI_CPUCFG_CPU_STS_REG(c)	(SUNXI_CPUCFG_BASE + 0x0030 + (c) * 4)
+#define SUNXI_CPUCFG_L2_STS_REG		(SUNXI_CPUCFG_BASE + 0x003c)
+#define SUNXI_CPUCFG_RST_CTRL_REG(c)	(SUNXI_CPUCFG_BASE + 0x0080 + (c) * 4)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n)	(SUNXI_CPUCFG_BASE + 0x00a0 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n)	(SUNXI_CPUCFG_BASE + 0x00a4 + (n) * 8)
+
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n)	(SUNXI_R_PRCM_BASE + 0x0140 + \
+					 (c) * 16 + (n) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c)	(SUNXI_R_PRCM_BASE + 0x0100 + (c) * 4)
+#define SUNXI_R_CPUCFG_CPUS_RST_REG	(SUNXI_R_CPUCFG_BASE + 0x0000)
+#define SUNXI_POWERON_RST_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0030 + (c) * 4)
+#define SUNXI_R_CPUCFG_SYS_RST_REG	(SUNXI_R_CPUCFG_BASE + 0x0140)
+#define SUNXI_R_CPUCFG_SS_FLAG_REG	(SUNXI_R_CPUCFG_BASE + 0x01a0)
+#define SUNXI_R_CPUCFG_CPU_ENTRY_REG	(SUNXI_R_CPUCFG_BASE + 0x01a4)
+#define SUNXI_R_CPUCFG_SS_ENTRY_REG	(SUNXI_R_CPUCFG_BASE + 0x01a8)
+#define SUNXI_R_CPUCFG_HP_FLAG_REG	(SUNXI_R_CPUCFG_BASE + 0x01ac)
+
+#endif /* __SUNXI_CPUCFG_H__ */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
new file mode 100644
index 0000000..cb202a8
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_MMAP_H__
+#define __SUNXI_MMAP_H__
+
+/* Memory regions */
+#define SUNXI_ROM_BASE			0x00000000
+#define SUNXI_ROM_SIZE			0x00010000
+#define SUNXI_SRAM_BASE			0x00010000
+#define SUNXI_SRAM_SIZE			0x00044000
+#define SUNXI_SRAM_A1_BASE		0x00010000
+#define SUNXI_SRAM_A1_SIZE		0x00008000
+#define SUNXI_SRAM_A2_BASE		0x00044000
+#define SUNXI_SRAM_A2_SIZE		0x00010000
+#define SUNXI_SRAM_C_BASE		0x00018000
+#define SUNXI_SRAM_C_SIZE		0x0001c000
+#define SUNXI_DEV_BASE			0x01000000
+#define SUNXI_DEV_SIZE			0x01000000
+#define SUNXI_DRAM_BASE			0x40000000
+#define SUNXI_DRAM_SIZE			0x80000000
+
+/* Memory-mapped devices */
+#define SUNXI_CPU_MBIST_BASE		0x01502000
+#define SUNXI_CPUCFG_BASE		0x01700000
+#define SUNXI_SYSCON_BASE		0x01c00000
+#define SUNXI_SRAM_VER_REG		(SUNXI_SYSCON_BASE + 0x24)
+#define SUNXI_DMA_BASE			0x01c02000
+#define SUNXI_KEYMEM_BASE		0x01c0b000
+#define SUNXI_SMHC0_BASE		0x01c0f000
+#define SUNXI_SMHC1_BASE		0x01c10000
+#define SUNXI_SMHC2_BASE		0x01c11000
+#define SUNXI_SID_BASE			0x01c14000
+#define SUNXI_MSGBOX_BASE		0x01c17000
+#define SUNXI_SPINLOCK_BASE		0x01c18000
+#define SUNXI_CCU_BASE			0x01c20000
+#define SUNXI_CCU_SEC_SWITCH_REG	(SUNXI_CCU_BASE + 0x2f0)
+#define SUNXI_PIO_BASE			0x01c20800
+#define SUNXI_TIMER_BASE		0x01c20c00
+#define SUNXI_WDOG_BASE			0x01c20ca0
+#define SUNXI_SPC_BASE			0x01c23400
+#define SUNXI_THS_BASE			0x01c25000
+#define SUNXI_UART0_BASE		0x01c28000
+#define SUNXI_UART1_BASE		0x01c28400
+#define SUNXI_UART2_BASE		0x01c28800
+#define SUNXI_UART3_BASE		0x01c28c00
+#define SUNXI_I2C0_BASE			0x01c2ac00
+#define SUNXI_I2C1_BASE			0x01c2b000
+#define SUNXI_I2C2_BASE			0x01c2b400
+#define SUNXI_DRAMCOM_BASE		0x01c62000
+#define SUNXI_DRAMCTL_BASE		0x01c63000
+#define SUNXI_DRAMPHY_BASE		0x01c65000
+#define SUNXI_SPI0_BASE			0x01c68000
+#define SUNXI_SPI1_BASE			0x01c69000
+#define SUNXI_SCU_BASE			0x01c80000
+#define SUNXI_GICD_BASE			0x01c81000
+#define SUNXI_GICC_BASE			0x01c82000
+#define SUNXI_RTC_BASE			0x01f00000
+#define SUNXI_R_TIMER_BASE		0x01f00800
+#define SUNXI_R_INTC_BASE		0x01f00c00
+#define SUNXI_R_WDOG_BASE		0x01f01000
+#define SUNXI_R_PRCM_BASE		0x01f01400
+#define SUNXI_R_TWD_BASE		0x01f01800
+#define SUNXI_R_CPUCFG_BASE		0x01f01c00
+#define SUNXI_R_CIR_BASE		0x01f02000
+#define SUNXI_R_I2C_BASE		0x01f02400
+#define SUNXI_R_UART_BASE		0x01f02800
+#define SUNXI_R_PIO_BASE		0x01f02c00
+#define SUNXI_R_RSB_BASE		0x01f03400
+#define SUNXI_R_PWM_BASE		0x01f03800
+
+#endif /* __SUNXI_MMAP_H__ */
diff --git a/plat/allwinner/sun50i_a64/platform.mk b/plat/allwinner/sun50i_a64/platform.mk
new file mode 100644
index 0000000..236464f
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/platform.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
+
+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}/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
+
+# Disable the PSCI platform compatibility layer.
+ENABLE_PLAT_COMPAT		:= 	0
+
+MULTI_CONSOLE_API		:=	1
+
+# Prohibit using deprecated interfaces. We rely on this for this platform.
+ERROR_DEPRECATED		:=	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
diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S
index 760a53a..752929d 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
-	.globl	plat_crash_console_init
-	.globl	plat_crash_console_putc
-	.globl	plat_crash_console_flush
+	.weak	plat_crash_console_init
+	.weak	plat_crash_console_putc
+	.weak	plat_crash_console_flush
 	.globl	platform_mem_init
 
 
@@ -50,7 +50,7 @@
 	mov_imm	x0, PLAT_ARM_CRASH_UART_BASE
 	mov_imm	x1, PLAT_ARM_CRASH_UART_CLK_IN_HZ
 	mov_imm	x2, ARM_CONSOLE_BAUDRATE
-	b	console_core_init
+	b	console_pl011_core_init
 endfunc plat_crash_console_init
 
 	/* ---------------------------------------------
@@ -62,7 +62,7 @@
 	 */
 func plat_crash_console_putc
 	mov_imm	x1, PLAT_ARM_CRASH_UART_BASE
-	b	console_core_putc
+	b	console_pl011_core_putc
 endfunc plat_crash_console_putc
 
 	/* ---------------------------------------------
@@ -75,7 +75,7 @@
 	 */
 func plat_crash_console_flush
 	mov_imm	x0, PLAT_ARM_CRASH_UART_BASE
-	b	console_core_flush
+	b	console_pl011_core_flush
 endfunc plat_crash_console_flush
 
 	/* ---------------------------------------------------------------------
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 379e87d..e5e7304 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -9,7 +9,6 @@
 #include <arm_xlat_tables.h>
 #include <bl1.h>
 #include <bl_common.h>
-#include <console.h>
 #include <plat_arm.h>
 #include <platform.h>
 #include <platform_def.h>
@@ -45,8 +44,7 @@
 #endif
 
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
 
 	/* Allow BL1 to see the whole Trusted RAM */
 	bl1_tzram_layout.total_base = ARM_BL_RAM_BASE;
diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c
index e70d115..e7247c6 100644
--- a/plat/arm/common/arm_bl2_el3_setup.c
+++ b/plat/arm/common/arm_bl2_el3_setup.c
@@ -1,9 +1,8 @@
 /*
- * 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 <console.h>
 #include <generic_delay_timer.h>
 #include <plat_arm.h>
 #include <platform.h>
@@ -21,8 +20,7 @@
 void arm_bl2_el3_early_platform_setup(void)
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
 
 	/*
 	 * Allow BL2 to see the whole Trusted RAM. This is determined
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 4ef3a9b..3aa99f8 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -8,7 +8,6 @@
 #include <arm_def.h>
 #include <assert.h>
 #include <bl_common.h>
-#include <console.h>
 #include <debug.h>
 #include <desc_image_load.h>
 #include <generic_delay_timer.h>
@@ -176,8 +175,7 @@
 void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, meminfo_t *mem_layout)
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
 
 	/* Setup the BL2 memory layout */
 	bl2_tzram_layout = *mem_layout;
diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c
index 3b8e4aa..cd691e5 100644
--- a/plat/arm/common/arm_bl2u_setup.c
+++ b/plat/arm/common/arm_bl2u_setup.c
@@ -7,7 +7,6 @@
 #include <arch_helpers.h>
 #include <arm_def.h>
 #include <bl_common.h>
-#include <console.h>
 #include <generic_delay_timer.h>
 #include <plat_arm.h>
 #include <platform_def.h>
@@ -36,8 +35,8 @@
 void arm_bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
+
 	generic_delay_timer_init();
 }
 
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 46f7ae0..6346f0f 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -78,8 +78,7 @@
 #endif
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
 
 #if RESET_TO_BL31
 	/* There are no parameters from BL2 if BL31 is a reset vector */
@@ -249,12 +248,18 @@
 /*******************************************************************************
  * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM
  * standard platforms
+ * Perform BL31 platform setup
  ******************************************************************************/
 void arm_bl31_plat_runtime_setup(void)
 {
+#if MULTI_CONSOLE_API
+	console_switch_state(CONSOLE_FLAG_RUNTIME);
+#else
+	console_uninit();
+#endif
+
 	/* Initialize the runtime console */
-	console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_runtime_init();
 }
 
 void bl31_platform_setup(void)
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 4b23ac6..76a75d3 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -125,6 +125,11 @@
 # Enable new version of image loading on ARM platforms
 LOAD_IMAGE_V2			:=	1
 
+# Use the multi console API, which is only available for AArch64 for now
+ifeq (${ARCH}, aarch64)
+  MULTI_CONSOLE_API		:=	1
+endif
+
 # Use generic OID definition (tbbr_oid.h)
 USE_TBBR_DEFS			:=	1
 
@@ -141,7 +146,8 @@
 endif
 
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/${ARCH}/arm_helpers.S		\
-				plat/arm/common/arm_common.c
+				plat/arm/common/arm_common.c			\
+				plat/arm/common/arm_console.c
 
 ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
 PLAT_BL_COMMON_SOURCES	+=	lib/xlat_tables/xlat_tables_common.c		\
diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c
new file mode 100644
index 0000000..6c8587f
--- /dev/null
+++ b/plat/arm/common/arm_console.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <pl011.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Functions that set up the console
+ ******************************************************************************/
+#if MULTI_CONSOLE_API
+static console_pl011_t arm_boot_console;
+static console_pl011_t arm_runtime_console;
+#endif
+
+/* Initialize the console to provide early debug support */
+void arm_console_boot_init(void)
+{
+#if MULTI_CONSOLE_API
+	int rc = console_pl011_register(PLAT_ARM_BOOT_UART_BASE,
+					PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+					ARM_CONSOLE_BAUDRATE,
+					&arm_boot_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(&arm_boot_console.console, CONSOLE_FLAG_BOOT);
+#else
+	(void)console_init(PLAT_ARM_BOOT_UART_BASE,
+			   PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+			   ARM_CONSOLE_BAUDRATE);
+#endif /* MULTI_CONSOLE_API */
+}
+
+void arm_console_boot_end(void)
+{
+	(void)console_flush();
+
+#if MULTI_CONSOLE_API
+	(void)console_unregister(&arm_boot_console.console);
+#else
+	console_uninit();
+#endif /* MULTI_CONSOLE_API */
+}
+
+/* Initialize the runtime console */
+void arm_console_runtime_init(void)
+{
+#if MULTI_CONSOLE_API
+	int rc = console_pl011_register(PLAT_ARM_BL31_RUN_UART_BASE,
+					PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
+					ARM_CONSOLE_BAUDRATE,
+					&arm_runtime_console);
+	if (rc == 0)
+		panic();
+
+	console_set_scope(&arm_runtime_console.console, CONSOLE_FLAG_RUNTIME);
+#else
+	(void)console_init(PLAT_ARM_BL31_RUN_UART_BASE,
+			   PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
+			   ARM_CONSOLE_BAUDRATE);
+#endif /* MULTI_CONSOLE_API */
+}
+
+void arm_console_runtime_end(void)
+{
+	(void)console_flush();
+
+#if MULTI_CONSOLE_API
+	(void)console_unregister(&arm_runtime_console.console);
+#else
+	console_uninit();
+#endif /* MULTI_CONSOLE_API */
+}
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index 32a515b..118bd26 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -61,8 +61,8 @@
 
 	err = arm_dyn_tb_fw_cfg_init((void *)config_base, &tb_fw_node);
 	if (err < 0) {
-		WARN("Invalid TB_FW_CONFIG loaded\n");
-		return;
+		ERROR("Invalid TB_FW_CONFIG loaded\n");
+		panic();
 	}
 
 	err = arm_dyn_get_disable_auth((void *)config_base, tb_fw_node, &disable_auth);
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 44ac5b5..4632099 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -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
  */
@@ -8,7 +8,6 @@
 #include <arm_def.h>
 #include <arm_gic.h>
 #include <assert.h>
-#include <console.h>
 #include <errno.h>
 #include <plat_arm.h>
 #include <platform.h>
@@ -160,6 +159,12 @@
 	plat_arm_gic_save();
 
 	/*
+	 * Unregister console now so that it is not registered for a second
+	 * time during resume.
+	 */
+	arm_console_runtime_end();
+
+	/*
 	 * All the other peripheral which are configured by ARM TF are
 	 * re-initialized on resume from system suspend. Hence we
 	 * don't save their state here.
@@ -174,8 +179,8 @@
  *****************************************************************************/
 void arm_system_pwr_domain_resume(void)
 {
-	console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
-						ARM_CONSOLE_BAUDRATE);
+	/* Initialize the console */
+	arm_console_runtime_init();
 
 	/* Assert system power domain is available on the platform */
 	assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
index abeaea0..16125ad 100644
--- a/plat/arm/common/tsp/arm_tsp_setup.c
+++ b/plat/arm/common/tsp/arm_tsp_setup.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,6 +7,8 @@
 #include <arm_def.h>
 #include <bl_common.h>
 #include <console.h>
+#include <debug.h>
+#include <pl011.h>
 #include <plat_arm.h>
 #include <platform_def.h>
 #include <platform_tsp.h>
@@ -22,14 +24,30 @@
 /*******************************************************************************
  * Initialize the UART
  ******************************************************************************/
+#if MULTI_CONSOLE_API
+static console_pl011_t arm_tsp_runtime_console;
+#endif
+
 void arm_tsp_early_platform_setup(void)
 {
+#if MULTI_CONSOLE_API
 	/*
 	 * Initialize a different console than already in use to display
 	 * messages from TSP
 	 */
+	int rc = console_pl011_register(PLAT_ARM_TSP_UART_BASE,
+					PLAT_ARM_TSP_UART_CLK_IN_HZ,
+					ARM_CONSOLE_BAUDRATE,
+					&arm_tsp_runtime_console);
+	if (rc == 0)
+		panic();
+
+	console_set_scope(&arm_tsp_runtime_console.console,
+			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+#else
 	console_init(PLAT_ARM_TSP_UART_BASE, PLAT_ARM_TSP_UART_CLK_IN_HZ,
 			ARM_CONSOLE_BAUDRATE);
+#endif /* MULTI_CONSOLE_API */
 }
 
 void tsp_early_platform_setup(void)
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
index 4b1f233..c5bbe74 100644
--- a/plat/common/plat_bl1_common.c
+++ b/plat/common/plat_bl1_common.c
@@ -107,7 +107,8 @@
 #if LOAD_IMAGE_V2
 	bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->total_base;
 #else
-	bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->free_base;
+	bl2_tzram_layout = (meminfo_t *) round_up(bl1_tzram_layout->free_base,
+						  sizeof(uint64_t));
 #endif /* LOAD_IMAGE_V2 */
 
 #if !ERROR_DEPRECATED