feat(synquacer): add BL2 support

Add BL2 support by default. Move the legacy mode behind the
RESET_TO_BL31 define.

Cc: Sumit Garg <sumit.garg@linaro.org>
Cc: Masahisa Kojima <masahisa.kojima@linaro.org>
Cc: Manish V Badarkhe <manish.badarkhe@arm.com>
Cc: Leonardo Sandoval <leonardo.sandoval@linaro.org>
Change-Id: Ic490745a7e8f6114172733428ebd6bd6adfcc1ec
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
diff --git a/plat/socionext/synquacer/include/platform_def.h b/plat/socionext/synquacer/include/platform_def.h
index 49ffbf9..c03c7a4 100644
--- a/plat/socionext/synquacer/include/platform_def.h
+++ b/plat/socionext/synquacer/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -44,14 +44,43 @@
 
 #define PLATFORM_STACK_SIZE		0x400
 
+#if !RESET_TO_BL31
+
+/* A mailbox page will be mapped from BL2 and BL31 */
+#define BL2_MAILBOX_BASE		0x0403f000
+#define BL2_MAILBOX_SIZE		0x1000
+
+#define MAX_IO_HANDLES			2
+#define MAX_IO_DEVICES			2
+#define MAX_IO_BLOCK_DEVICES	U(1)
+
+#define BL2_BASE			0x04000000
+#define BL2_SIZE			(256 * 1024)
+#define BL2_LIMIT			(BL2_BASE + BL2_SIZE)
+
+/* If BL2 is enabled, the BL31 is loaded on secure DRAM */
+#define BL31_BASE			0xfbe00000
+#define BL31_SIZE			0x00100000
+#else
+
 #define BL31_BASE			0x04000000
 #define BL31_SIZE			0x00080000
+#endif
+
 #define BL31_LIMIT			(BL31_BASE + BL31_SIZE)
 
 #define BL32_BASE			0xfc000000
 #define BL32_SIZE			0x03c00000
 #define BL32_LIMIT			(BL32_BASE + BL32_SIZE)
 
+/* Alternative BL33 */
+#define PLAT_SQ_BL33_BASE		0xe0000000
+#define PLAT_SQ_BL33_SIZE		0x00100000
+
+/* FIP IO base */
+#define PLAT_SQ_FIP_IOBASE		0x08600000
+#define PLAT_SQ_FIP_MAXSIZE		0x00400000
+
 #define PLAT_SQ_CCN_BASE		0x32000000
 #define PLAT_SQ_CLUSTER_TO_CCN_ID_MAP					\
 					0,	/* Cluster 0 */		\
diff --git a/plat/socionext/synquacer/include/sq_common.h b/plat/socionext/synquacer/include/sq_common.h
index b09d22a..eef0e1f 100644
--- a/plat/socionext/synquacer/include/sq_common.h
+++ b/plat/socionext/synquacer/include/sq_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -39,6 +39,8 @@
 void sq_gic_cpuif_disable(void);
 void sq_gic_pcpu_init(void);
 
+int sq_io_setup(void);
+struct image_info *sq_get_image_info(unsigned int image_id);
 void sq_mmap_setup(uintptr_t total_base, size_t total_size,
 		   const struct mmap_region *mmap);
 
diff --git a/plat/socionext/synquacer/platform.mk b/plat/socionext/synquacer/platform.mk
index 98a4c3e..e467324 100644
--- a/plat/socionext/synquacer/platform.mk
+++ b/plat/socionext/synquacer/platform.mk
@@ -4,15 +4,23 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-override RESET_TO_BL31			:= 1
 override PROGRAMMABLE_RESET_ADDRESS	:= 1
 override USE_COHERENT_MEM		:= 1
 override SEPARATE_CODE_AND_RODATA	:= 1
 override ENABLE_SVE_FOR_NS		:= 0
 # Enable workarounds for selected Cortex-A53 erratas.
 ERRATA_A53_855873		:= 1
-# Enable SCMI support
-SQ_USE_SCMI_DRIVER		?= 0
+
+ifeq (${RESET_TO_BL31}, 1)
+override RESET_TO_BL31          := 1
+override TRUSTED_BOARD_BOOT     := 0
+SQ_USE_SCMI_DRIVER              ?= 0
+else
+override RESET_TO_BL31          := 0
+override BL2_AT_EL3             := 1
+SQ_USE_SCMI_DRIVER              := 1
+BL2_CPPFLAGS                    += -DPLAT_XLAT_TABLES_DYNAMIC
+endif
 
 # Libraries
 include lib/xlat_tables_v2/xlat_tables.mk
@@ -35,6 +43,16 @@
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
 
+ifneq (${RESET_TO_BL31}, 1)
+BL2_SOURCES		+=	common/desc_image_load.c		\
+				drivers/io/io_fip.c			\
+				drivers/io/io_memmap.c			\
+				drivers/io/io_storage.c			\
+				$(PLAT_PATH)/sq_bl2_setup.c		\
+				$(PLAT_PATH)/sq_image_desc.c	\
+				$(PLAT_PATH)/sq_io_storage.c
+endif
+
 BL31_SOURCES		+=	drivers/arm/ccn/ccn.c			\
 				${GICV3_SOURCES}			\
 				plat/common/plat_gicv3.c		\
diff --git a/plat/socionext/synquacer/sq_bl2_setup.c b/plat/socionext/synquacer/sq_bl2_setup.c
new file mode 100644
index 0000000..a98d912
--- /dev/null
+++ b/plat/socionext/synquacer/sq_bl2_setup.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2022, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/image_decompress.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/io/io_storage.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+#include <sq_common.h>
+
+static console_t console;
+
+void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
+				  u_register_t x2, u_register_t x3)
+{
+	/* Initialize the console to provide early debug support */
+	(void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
+			       PLAT_SQ_BOOT_UART_CLK_IN_HZ,
+			       SQ_CONSOLE_BAUDRATE, &console);
+	console_set_scope(&console, CONSOLE_FLAG_BOOT);
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+	int ret;
+
+	sq_mmap_setup(BL2_BASE, BL2_SIZE, NULL);
+
+	ret = sq_io_setup();
+	if (ret) {
+		ERROR("failed to setup io devices\n");
+		plat_error_handler(ret);
+	}
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+void plat_flush_next_bl_params(void)
+{
+	flush_bl_params_desc();
+}
+
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+	return get_bl_load_info_from_mem_params_desc();
+}
+
+bl_params_t *plat_get_next_bl_params(void)
+{
+	return get_next_bl_params_from_mem_params_desc();
+}
+
+void bl2_plat_preload_setup(void)
+{
+}
+
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+	struct image_info *image_info;
+
+	image_info = sq_get_image_info(image_id);
+
+	return mmap_add_dynamic_region(image_info->image_base,
+				      image_info->image_base,
+				      image_info->image_max_size,
+				      MT_MEMORY | MT_RW | MT_NS);
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	return 0;
+}
diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c
index a7a0ce0..967437b 100644
--- a/plat/socionext/synquacer/sq_bl31_setup.c
+++ b/plat/socionext/synquacer/sq_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -44,6 +44,35 @@
 	return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info;
 }
 
+#if !RESET_TO_BL31
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	void *from_bl2 = (void *) arg0;
+	bl_params_node_t *bl_params = ((bl_params_t *) from_bl2)->head;
+
+	/* Initialize the console to provide early debug support */
+	(void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
+			       PLAT_SQ_BOOT_UART_CLK_IN_HZ,
+			       SQ_CONSOLE_BAUDRATE, &console);
+
+	console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+
+	/* Initialize power controller before setting up topology */
+	plat_sq_pwrc_setup();
+
+	while (bl_params) {
+		if (bl_params->image_id == BL32_IMAGE_ID)
+			bl32_image_ep_info = *bl_params->ep_info;
+
+		if (bl_params->image_id == BL33_IMAGE_ID)
+			bl33_image_ep_info = *bl_params->ep_info;
+
+		bl_params = bl_params->next_params_info;
+	}
+}
+
+#else
 /*******************************************************************************
  * Gets SPSR for BL32 entry
  ******************************************************************************/
@@ -129,6 +158,7 @@
 	bl33_image_ep_info.spsr = sq_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 }
+#endif
 
 static void sq_configure_sys_timer(void)
 {
@@ -192,6 +222,11 @@
 				PLAT_SQ_SP_PRIV_SIZE,
 				MT_RW_DATA | MT_SECURE),
 #endif
+#if !RESET_TO_BL31
+		MAP_REGION_FLAT(BL2_MAILBOX_BASE,
+				BL2_MAILBOX_SIZE,
+				MT_RW | MT_SECURE),
+#endif
 		{0},
 	};
 
diff --git a/plat/socionext/synquacer/sq_helpers.S b/plat/socionext/synquacer/sq_helpers.S
index 7a2d97b..5f9eab4 100644
--- a/plat/socionext/synquacer/sq_helpers.S
+++ b/plat/socionext/synquacer/sq_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,7 +46,12 @@
  * code that secondary CPUs jump to.
  */
 func plat_secondary_cold_boot_setup
+#if !RESET_TO_BL31
+	mov_imm	x0, BL2_MAILBOX_BASE
+	ldr	x0, [x0]
+#else
 	ldr	x0, sq_sec_entrypoint
+#endif
 
 	/* Wait until the mailbox gets populated */
 poll_mailbox:
diff --git a/plat/socionext/synquacer/sq_image_desc.c b/plat/socionext/synquacer/sq_image_desc.c
new file mode 100644
index 0000000..5fe125b
--- /dev/null
+++ b/plat/socionext/synquacer/sq_image_desc.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2022, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <common/desc_image_load.h>
+
+#include <platform_def.h>
+
+static struct bl_mem_params_node sq_image_descs[] = {
+	{
+		.image_id = BL31_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t, 0),
+		.image_info.image_base = BL31_BASE,
+		.image_info.image_max_size = BL31_SIZE,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | EXECUTABLE | EP_FIRST_EXE),
+		.ep_info.pc = BL31_BASE,
+		.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+					DISABLE_ALL_EXCEPTIONS),
+
+		.next_handoff_image_id = BL32_IMAGE_ID,
+	},
+	{
+		.image_id = BL32_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t, 0),
+		.image_info.image_base = BL32_BASE,
+		.image_info.image_max_size = BL32_SIZE,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | EXECUTABLE),
+		.ep_info.pc = BL32_BASE,
+		.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+					DISABLE_ALL_EXCEPTIONS),
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+	{
+		.image_id = BL33_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t, 0),
+		.image_info.image_base = PLAT_SQ_BL33_BASE,
+		.image_info.image_max_size = PLAT_SQ_BL33_SIZE,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | EXECUTABLE),
+		.ep_info.pc = PLAT_SQ_BL33_BASE,
+		.ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+					DISABLE_ALL_EXCEPTIONS),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+};
+REGISTER_BL_IMAGE_DESCS(sq_image_descs)
+
+struct image_info *sq_get_image_info(unsigned int image_id)
+{
+	struct bl_mem_params_node *desc;
+
+	desc = get_bl_mem_params_node(image_id);
+	assert(desc);
+	return &desc->image_info;
+}
diff --git a/plat/socionext/synquacer/sq_io_storage.c b/plat/socionext/synquacer/sq_io_storage.c
new file mode 100644
index 0000000..d0fe2d3
--- /dev/null
+++ b/plat/socionext/synquacer/sq_io_storage.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2022, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <sq_common.h>
+
+static const io_dev_connector_t *sq_fip_dev_con;
+static uintptr_t sq_fip_dev_handle;
+
+static const io_dev_connector_t *sq_backend_dev_con;
+static uintptr_t sq_backend_dev_handle;
+
+static io_block_spec_t sq_fip_spec = {
+	.offset = PLAT_SQ_FIP_IOBASE,	/* FIP Image is at 5MB offset on memory-mapped NOR flash */
+	.length = PLAT_SQ_FIP_MAXSIZE,	/* Expected maximum FIP image size */
+};
+
+static const io_uuid_spec_t sq_bl2_spec = {
+	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t sq_bl31_spec = {
+	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t sq_bl32_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t sq_bl33_spec = {
+	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+struct sq_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	uintptr_t init_params;
+};
+
+static const struct sq_io_policy sq_io_policies[] = {
+	[FIP_IMAGE_ID] = {
+		.dev_handle = &sq_backend_dev_handle,
+		.image_spec = (uintptr_t)&sq_fip_spec,
+	},
+	[BL2_IMAGE_ID] = {
+		.dev_handle = &sq_fip_dev_handle,
+		.image_spec = (uintptr_t)&sq_bl2_spec,
+		.init_params = FIP_IMAGE_ID,
+	},
+	[BL31_IMAGE_ID] = {
+		.dev_handle = &sq_fip_dev_handle,
+		.image_spec = (uintptr_t)&sq_bl31_spec,
+		.init_params = FIP_IMAGE_ID,
+	},
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &sq_fip_dev_handle,
+		.image_spec = (uintptr_t)&sq_bl32_spec,
+		.init_params = FIP_IMAGE_ID,
+	},
+	[BL33_IMAGE_ID] = {
+		.dev_handle = &sq_fip_dev_handle,
+		.image_spec = (uintptr_t)&sq_bl33_spec,
+		.init_params = FIP_IMAGE_ID,
+	},
+};
+
+static int sq_io_memmap_setup(void)
+{
+	int ret;
+
+	ret = mmap_add_dynamic_region(sq_fip_spec.offset, sq_fip_spec.offset,
+				      sq_fip_spec.length, MT_RO_DATA | MT_SECURE);
+	if (ret) {
+		return ret;
+	}
+
+	ret = register_io_dev_memmap(&sq_backend_dev_con);
+	if (ret) {
+		return ret;
+	}
+
+	return io_dev_open(sq_backend_dev_con, 0, &sq_backend_dev_handle);
+}
+
+static int sq_io_fip_setup(void)
+{
+	int ret;
+
+	ret = register_io_dev_fip(&sq_fip_dev_con);
+	if (ret) {
+		return ret;
+	}
+
+	return io_dev_open(sq_fip_dev_con, 0, &sq_fip_dev_handle);
+}
+
+int sq_io_setup(void)
+{
+	int ret;
+
+	ret = sq_io_memmap_setup();
+	if (ret) {
+		return ret;
+	}
+
+	ret = sq_io_fip_setup();
+	if (ret) {
+		return ret;
+	}
+
+	return 0;
+}
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	uintptr_t init_params;
+
+	assert(image_id < ARRAY_SIZE(sq_io_policies));
+
+	*dev_handle = *sq_io_policies[image_id].dev_handle;
+	*image_spec = sq_io_policies[image_id].image_spec;
+	init_params = sq_io_policies[image_id].init_params;
+
+	return io_dev_init(*dev_handle, init_params);
+}
diff --git a/plat/socionext/synquacer/sq_psci.c b/plat/socionext/synquacer/sq_psci.c
index 3062f63..017516f 100644
--- a/plat/socionext/synquacer/sq_psci.c
+++ b/plat/socionext/synquacer/sq_psci.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -197,9 +197,17 @@
 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
 			const struct plat_psci_ops **psci_ops)
 {
+#if !RESET_TO_BL31
+	uintptr_t *sq_sec_ep = (uintptr_t *)BL2_MAILBOX_BASE;
+
+	*sq_sec_ep = sec_entrypoint;
+	flush_dcache_range((uint64_t)sq_sec_ep,
+			   sizeof(*sq_sec_ep));
+#else
 	sq_sec_entrypoint = sec_entrypoint;
 	flush_dcache_range((uint64_t)&sq_sec_entrypoint,
 			   sizeof(sq_sec_entrypoint));
+#endif
 
 	*psci_ops = &sq_psci_ops;