gxbb: Initial port of 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:

- Partial SCPI support.
- Basic PSCI support (CPU_ON, SYSTEM_RESET, SYSTEM_OFF).
- GICv2 driver set up.
- Basic SIP services (read efuse data, enable/disable JTAG).

This port has been tested in an ODROID-C2.

Change-Id: Ia4bc82d7aca42a69d6b118b947279f82b3f6c6da
Tested-by: Amit Singh Tomar <amittomer25@gmail.com>
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
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..6a13159
--- /dev/null
+++ b/plat/meson/gxbb/gxbb_pm.c
@@ -0,0 +1,120 @@
+/*
+ * 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 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)
+{
+	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)
+{
+	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+					PLAT_LOCAL_STATE_OFF);
+
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+}
+
+/*******************************************************************************
+ * 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,
+	.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;
+	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