summaryrefslogtreecommitdiff
path: root/plat/amlogic
diff options
context:
space:
mode:
authorCarlo Caione <ccaione@baylibre.com>2019-08-23 18:28:36 +0100
committerCarlo Caione <ccaione@baylibre.com>2019-09-05 10:39:25 +0100
commit4a079c752beef8c2e8072b55a267d4b597b1e05b (patch)
treef238d3473ebb0cef430977477dbea7ca72d0197b /plat/amlogic
parent3441952f61a62948ccf84c2e3eada9b340c3560d (diff)
meson: Rename platform directory to amlogic
Meson is the internal code name for the SoC family. The correct name for the platform should be Amlogic. Change the name of the platform directory. Signed-off-by: Carlo Caione <ccaione@baylibre.com> Change-Id: Icc140e1ea137f12117acbf64c7dcb1a8b66b345d
Diffstat (limited to 'plat/amlogic')
-rw-r--r--plat/amlogic/gxbb/aarch64/gxbb_helpers.S97
-rw-r--r--plat/amlogic/gxbb/gxbb_bl31_setup.c146
-rw-r--r--plat/amlogic/gxbb/gxbb_common.c145
-rw-r--r--plat/amlogic/gxbb/gxbb_def.h118
-rw-r--r--plat/amlogic/gxbb/gxbb_efuse.c25
-rw-r--r--plat/amlogic/gxbb/gxbb_mhu.c53
-rw-r--r--plat/amlogic/gxbb/gxbb_pm.c193
-rw-r--r--plat/amlogic/gxbb/gxbb_private.h38
-rw-r--r--plat/amlogic/gxbb/gxbb_scpi.c139
-rw-r--r--plat/amlogic/gxbb/gxbb_sip_svc.c68
-rw-r--r--plat/amlogic/gxbb/gxbb_thermal.c27
-rw-r--r--plat/amlogic/gxbb/gxbb_topology.c55
-rw-r--r--plat/amlogic/gxbb/include/plat_macros.S71
-rw-r--r--plat/amlogic/gxbb/include/platform_def.h66
-rw-r--r--plat/amlogic/gxbb/platform.mk69
-rw-r--r--plat/amlogic/gxl/aarch64/gxl_helpers.S97
-rw-r--r--plat/amlogic/gxl/gxl_bl31_setup.c162
-rw-r--r--plat/amlogic/gxl/gxl_common.c143
-rw-r--r--plat/amlogic/gxl/gxl_def.h128
-rw-r--r--plat/amlogic/gxl/gxl_efuse.c25
-rw-r--r--plat/amlogic/gxl/gxl_mhu.c52
-rw-r--r--plat/amlogic/gxl/gxl_pm.c214
-rw-r--r--plat/amlogic/gxl/gxl_private.h40
-rw-r--r--plat/amlogic/gxl/gxl_scpi.c211
-rw-r--r--plat/amlogic/gxl/gxl_sip_svc.c66
-rw-r--r--plat/amlogic/gxl/gxl_thermal.c27
-rw-r--r--plat/amlogic/gxl/gxl_topology.c53
-rw-r--r--plat/amlogic/gxl/include/plat_macros.S71
-rw-r--r--plat/amlogic/gxl/include/platform_def.h66
-rw-r--r--plat/amlogic/gxl/platform.mk87
30 files changed, 2752 insertions, 0 deletions
diff --git a/plat/amlogic/gxbb/aarch64/gxbb_helpers.S b/plat/amlogic/gxbb/aarch64/gxbb_helpers.S
new file mode 100644
index 00000000..760d6c46
--- /dev/null
+++ b/plat/amlogic/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/amlogic/gxbb/gxbb_bl31_setup.c b/plat/amlogic/gxbb/gxbb_bl31_setup.c
new file mode 100644
index 00000000..b867a584
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_bl31_setup.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.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/amlogic/gxbb/gxbb_common.c b/plat/amlogic/gxbb/gxbb_common.c
new file mode 100644
index 00000000..eb688f77
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_common.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/ep_info.h>
+#include <drivers/amlogic/meson_console.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/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/amlogic/gxbb/gxbb_def.h b/plat/amlogic/gxbb/gxbb_def.h
new file mode 100644
index 00000000..3e27097c
--- /dev/null
+++ b/plat/amlogic/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 <lib/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/amlogic/gxbb/gxbb_efuse.c b/plat/amlogic/gxbb/gxbb_efuse.c
new file mode 100644
index 00000000..edea5426
--- /dev/null
+++ b/plat/amlogic/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/amlogic/gxbb/gxbb_mhu.c b/plat/amlogic/gxbb/gxbb_mhu.c
new file mode 100644
index 00000000..903ef411
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_mhu.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <lib/bakery_lock.h>
+#include <lib/mmio.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/amlogic/gxbb/gxbb_pm.c b/plat/amlogic/gxbb/gxbb_pm.c
new file mode 100644
index 00000000..59b9436f
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_pm.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.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/amlogic/gxbb/gxbb_private.h b/plat/amlogic/gxbb/gxbb_private.h
new file mode 100644
index 00000000..910a42c1
--- /dev/null
+++ b/plat/amlogic/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/amlogic/gxbb/gxbb_scpi.c b/plat/amlogic/gxbb/gxbb_scpi.c
new file mode 100644
index 00000000..83eeda29
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_scpi.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <lib/mmio.h>
+#include <plat/common/platform.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/amlogic/gxbb/gxbb_sip_svc.c b/plat/amlogic/gxbb/gxbb_sip_svc.c
new file mode 100644
index 00000000..63c7dba1
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_sip_svc.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.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/amlogic/gxbb/gxbb_thermal.c b/plat/amlogic/gxbb/gxbb_thermal.c
new file mode 100644
index 00000000..b6048eee
--- /dev/null
+++ b/plat/amlogic/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/amlogic/gxbb/gxbb_topology.c b/plat/amlogic/gxbb/gxbb_topology.c
new file mode 100644
index 00000000..eec2d34d
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_topology.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <arch.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/amlogic/gxbb/include/plat_macros.S b/plat/amlogic/gxbb/include/plat_macros.S
new file mode 100644
index 00000000..c721c21b
--- /dev/null
+++ b/plat/amlogic/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 <drivers/arm/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/amlogic/gxbb/include/platform_def.h b/plat/amlogic/gxbb/include/platform_def.h
new file mode 100644
index 00000000..da4aedde
--- /dev/null
+++ b/plat/amlogic/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 <lib/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/amlogic/gxbb/platform.mk b/plat/amlogic/gxbb/platform.mk
new file mode 100644
index 00000000..06aaaba3
--- /dev/null
+++ b/plat/amlogic/gxbb/platform.mk
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -Iplat/amlogic/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/amlogic/console/aarch64/meson_console.S \
+ plat/amlogic/gxbb/gxbb_common.c \
+ plat/amlogic/gxbb/gxbb_topology.c \
+ ${XLAT_TABLES_LIB_SRCS}
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/amlogic/gxbb/aarch64/gxbb_helpers.S \
+ plat/amlogic/gxbb/gxbb_bl31_setup.c \
+ plat/amlogic/gxbb/gxbb_efuse.c \
+ plat/amlogic/gxbb/gxbb_mhu.c \
+ plat/amlogic/gxbb/gxbb_pm.c \
+ plat/amlogic/gxbb/gxbb_scpi.c \
+ plat/amlogic/gxbb/gxbb_sip_svc.c \
+ plat/amlogic/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
+
+# Verify build config
+# -------------------
+
+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/amlogic/gxl/aarch64/gxl_helpers.S b/plat/amlogic/gxl/aarch64/gxl_helpers.S
new file mode 100644
index 00000000..760d6c46
--- /dev/null
+++ b/plat/amlogic/gxl/aarch64/gxl_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/amlogic/gxl/gxl_bl31_setup.c b/plat/amlogic/gxl/gxl_bl31_setup.c
new file mode 100644
index 00000000..b1da7942
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_bl31_setup.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <drivers/arm/gicv2.h>
+#include <common/interrupt_props.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+
+#include "gxl_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;
+static image_info_t bl30_image_info;
+static image_info_t bl301_image_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 gxl_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;
+ image_info_t *scp_image_info[];
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct gxl_bl31_param *from_bl2;
+
+ /* Initialize the console to provide early debug support */
+ gxbb_console_init();
+
+ /* Check that params passed from BL2 are not NULL. */
+ from_bl2 = (struct gxl_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();
+ }
+
+ bl30_image_info = *from_bl2->scp_image_info[0];
+ bl301_image_info = *from_bl2->scp_image_info[1];
+}
+
+void bl31_plat_arch_setup(void)
+{
+ gxbb_setup_page_tables();
+
+ enable_mmu_el3(0);
+}
+
+static inline bool gxl_scp_ready(void)
+{
+ return GXBB_AO_RTI_SCP_IS_READY(mmio_read_32(GXBB_AO_RTI_SCP_STAT));
+}
+
+static inline void gxl_scp_boot(void)
+{
+ scpi_upload_scp_fw(bl30_image_info.image_base,
+ bl30_image_info.image_size, 0);
+ scpi_upload_scp_fw(bl301_image_info.image_base,
+ bl301_image_info.image_size, 1);
+ while (!gxl_scp_ready())
+ ;
+}
+
+/*******************************************************************************
+ * 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();
+
+ gxl_scp_boot();
+
+ gxbb_thermal_unknown();
+}
diff --git a/plat/amlogic/gxl/gxl_common.c b/plat/amlogic/gxl/gxl_common.c
new file mode 100644
index 00000000..e3bd6048
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_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 <common/bl_common.h>
+#include <common/debug.h>
+#include <common/ep_info.h>
+#include <bl31/interrupt_mgmt.h>
+#include <meson_console.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <lib/xlat_tables/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/amlogic/gxl/gxl_def.h b/plat/amlogic/gxl/gxl_def.h
new file mode 100644
index 00000000..089fa8db
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_def.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GXBB_DEF_H
+#define GXBB_DEF_H
+
+#include <lib/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(0x05100000)
+#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(0x050FE000)
+#define GXBB_SHARE_MEM_OUTPUT_BASE UL(0x050FF000)
+
+#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)
+
+// * [ 1K] 0xD901_3800 - 0xD901_3BFF Secure Mailbox (3)
+// * [ 1K] 0xD901_3400 - 0xD901_37FF High Mailbox (2) *
+// * [ 1K] 0xD901_3000 - 0xD901_33FF High Mailbox (1) *
+
+#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_AO_RTI_SCP_STAT UL(0xDA10023C)
+#define GXBB_AO_RTI_SCP_READY_OFF U(0x14)
+#define GXBB_A0_RTI_SCP_READY_MASK U(3)
+#define GXBB_AO_RTI_SCP_IS_READY(v) \
+ ((((v) >> GXBB_AO_RTI_SCP_READY_OFF) & \
+ GXBB_A0_RTI_SCP_READY_MASK) == GXBB_A0_RTI_SCP_READY_MASK)
+
+#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/amlogic/gxl/gxl_efuse.c b/plat/amlogic/gxl/gxl_efuse.c
new file mode 100644
index 00000000..b17d1b8e
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_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 "gxl_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/amlogic/gxl/gxl_mhu.c b/plat/amlogic/gxl/gxl_mhu.c
new file mode 100644
index 00000000..4c1d5b60
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_mhu.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/bakery_lock.h>
+#include <lib/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/amlogic/gxl/gxl_pm.c b/plat/amlogic/gxl/gxl_pm.c
new file mode 100644
index 00000000..4a5d26e9
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_pm.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <drivers/console.h>
+#include <common/debug.h>
+#include <errno.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <lib/psci/psci.h>
+
+#include "gxl_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 gxl_pm_set_reset_addr(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);
+}
+
+static void gxl_pm_reset(u_register_t mpidr)
+{
+ unsigned int core = plat_gxbb_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = GXBB_PSCI_MAILBOX_BASE + (core << 4) + 8;
+
+ mmio_write_32(cpu_mailbox_addr, 0);
+}
+
+static void __dead2 gxbb_system_reset(void)
+{
+ INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+ u_register_t mpidr = read_mpidr_el1();
+ uint32_t status = mmio_read_32(GXBB_AO_RTI_STATUS_REG3);
+ int ret;
+
+ NOTICE("BL31: Reboot reason: 0x%x\n", status);
+
+ status &= 0xFFFF0FF0;
+
+ console_flush();
+
+ mmio_write_32(GXBB_AO_RTI_STATUS_REG3, status);
+
+ ret = scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
+ panic();
+ }
+
+ gxl_pm_reset(mpidr);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+ panic();
+}
+
+static void __dead2 gxbb_system_off(void)
+{
+ INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+ u_register_t mpidr = read_mpidr_el1();
+ int ret;
+
+ ret = scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
+ panic();
+ }
+
+ gxl_pm_set_reset_addr(mpidr, 0);
+ gxl_pm_reset(mpidr);
+
+ 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;
+ }
+
+ gxl_pm_set_reset_addr(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);
+
+ 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)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ 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: CPU0 entering wait loop...\n");
+
+ while (gxbb_cpu0_go == 0)
+ wfe();
+
+ VERBOSE("BL31: CPU0 resumed.\n");
+
+ /*
+ * Because setting CPU0's warm reset entrypoint through PSCI
+ * mailbox and/or mmio mapped RVBAR (0xda834650) does not seem
+ * to work, jump to it manually.
+ * In order to avoid an assert, mmu has to be disabled.
+ */
+ disable_mmu_el3();
+ ((void(*)(void))gxbb_sec_entrypoint)();
+ }
+
+ dsbsy();
+ gxl_pm_set_reset_addr(mpidr, 0);
+ gxl_pm_reset(mpidr);
+
+ 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/amlogic/gxl/gxl_private.h b/plat/amlogic/gxl/gxl_private.h
new file mode 100644
index 00000000..913cbf65
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_private.h
@@ -0,0 +1,40 @@
+/*
+ * 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>
+#include <stddef.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);
+void scpi_upload_scp_fw(uintptr_t addr, size_t size, int send);
+
+/* 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/amlogic/gxl/gxl_scpi.c b/plat/amlogic/gxl/gxl_scpi.c
new file mode 100644
index 00000000..13d65243
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_scpi.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <crypto/sha_dma.h>
+
+#include "gxl_private.h"
+
+#define SIZE_SHIFT 20
+#define SIZE_MASK 0x1FF
+#define SIZE_FWBLK 0x200UL
+
+/*
+ * 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
+
+#define SCPI_CMD_COPY_FW 0xd4
+#define SCPI_CMD_SET_FW_ADDR 0xd3
+#define SCPI_CMD_FW_SIZE 0xd2
+
+static inline uint32_t scpi_cmd(uint32_t command, uint32_t size)
+{
+ return command | (size << SIZE_SHIFT);
+}
+
+static 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();
+}
+
+static inline void scpi_copy_scp_data(uint8_t *data, size_t len)
+{
+ void *dst = (void *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+ size_t sz;
+
+ mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
+ scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
+ mhu_secure_message_wait();
+
+ for (sz = 0; sz < len; sz += SIZE_FWBLK) {
+ memcpy(dst, data + sz, MIN(SIZE_FWBLK, len - sz));
+ mhu_secure_message_send(SCPI_CMD_COPY_FW);
+ }
+}
+
+static inline void scpi_set_scp_addr(uint64_t addr, size_t len)
+{
+ volatile uint64_t *dst = (uint64_t *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+
+ /*
+ * It is ok as GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD is mapped as
+ * non cachable
+ */
+ *dst = addr;
+ scpi_secure_message_send(SCPI_CMD_SET_FW_ADDR, sizeof(addr));
+ mhu_secure_message_wait();
+
+ mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
+ scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
+ mhu_secure_message_wait();
+}
+
+static inline void scpi_send_fw_hash(uint8_t hash[], size_t len)
+{
+ void *dst = (void *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+
+ memcpy(dst, hash, len);
+ mhu_secure_message_send(0xd0);
+ mhu_secure_message_send(0xd1);
+ mhu_secure_message_send(0xd5);
+ mhu_secure_message_end();
+}
+
+/**
+ * Upload a FW to SCP.
+ *
+ * @param addr: firmware data address
+ * @param size: size of firmware
+ * @param send: If set, actually copy the firmware in SCP memory otherwise only
+ * send the firmware address.
+ */
+void scpi_upload_scp_fw(uintptr_t addr, size_t size, int send)
+{
+ struct asd_ctx ctx;
+
+ asd_sha_init(&ctx, ASM_SHA256);
+ asd_sha_update(&ctx, (void *)addr, size);
+ asd_sha_finalize(&ctx);
+
+ mhu_secure_message_start();
+ if (send == 0)
+ scpi_set_scp_addr(addr, size);
+ else
+ scpi_copy_scp_data((void *)addr, size);
+
+ scpi_send_fw_hash(ctx.digest, sizeof(ctx.digest));
+}
diff --git a/plat/amlogic/gxl/gxl_sip_svc.c b/plat/amlogic/gxl/gxl_sip_svc.c
new file mode 100644
index 00000000..74fbc80e
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_sip_svc.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <common/runtime_svc.h>
+#include <stdint.h>
+
+#include "gxl_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/amlogic/gxl/gxl_thermal.c b/plat/amlogic/gxl/gxl_thermal.c
new file mode 100644
index 00000000..3af1c6dc
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_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 "gxl_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/amlogic/gxl/gxl_topology.c b/plat/amlogic/gxl/gxl_topology.c
new file mode 100644
index 00000000..cca3ead5
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_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 "gxl_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/amlogic/gxl/include/plat_macros.S b/plat/amlogic/gxl/include/plat_macros.S
new file mode 100644
index 00000000..c721c21b
--- /dev/null
+++ b/plat/amlogic/gxl/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 <drivers/arm/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/amlogic/gxl/include/platform_def.h b/plat/amlogic/gxl/include/platform_def.h
new file mode 100644
index 00000000..b32ec56d
--- /dev/null
+++ b/plat/amlogic/gxl/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 <lib/utils_def.h>
+
+#include "../gxl_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 6
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/amlogic/gxl/platform.mk b/plat/amlogic/gxl/platform.mk
new file mode 100644
index 00000000..9cdf37ac
--- /dev/null
+++ b/plat/amlogic/gxl/platform.mk
@@ -0,0 +1,87 @@
+#
+# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+DOIMAGEPATH ?= tools/amlogic
+DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
+
+PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
+ -Iinclude/drivers/amlogic/gxl \
+ -Iplat/amlogic/gxl/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/amlogic/console/aarch64/meson_console.S \
+ plat/amlogic/gxl/gxl_common.c \
+ plat/amlogic/gxl/gxl_topology.c \
+ ${XLAT_TABLES_LIB_SRCS}
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/amlogic/gxl/aarch64/gxl_helpers.S \
+ plat/amlogic/gxl/gxl_bl31_setup.c \
+ plat/amlogic/gxl/gxl_efuse.c \
+ plat/amlogic/gxl/gxl_mhu.c \
+ plat/amlogic/gxl/gxl_pm.c \
+ plat/amlogic/gxl/gxl_scpi.c \
+ plat/amlogic/gxl/gxl_sip_svc.c \
+ plat/amlogic/gxl/gxl_thermal.c \
+ drivers/amlogic/gxl/crypto/sha_dma.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_855873 := 1
+ERRATA_A53_819472 := 1
+ERRATA_A53_824069 := 1
+ERRATA_A53_827319 := 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
+
+# Verify build config
+# -------------------
+
+ifneq (${RESET_TO_BL31}, 0)
+ $(error Error: gxl needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on gxl)
+endif
+
+all: ${BUILD_PLAT}/bl31.img
+distclean realclean clean: cleanimage
+
+cleanimage:
+ ${Q}${MAKE} -C ${DOIMAGEPATH} clean
+
+${DOIMAGETOOL}:
+ ${Q}${MAKE} -C ${DOIMAGEPATH}
+
+${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
+ ${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
+