Add BL2 support for Broadcom stingray platform

Change-Id: I5daa3f2b4b9d85cb857547a588571a9aa8ad05c2
Signed-off-by: Sheetal Tigadoli <sheetal.tigadoli@broadcom.com>
diff --git a/plat/brcm/board/common/bcm_elog_ddr.c b/plat/brcm/board/common/bcm_elog_ddr.c
new file mode 100644
index 0000000..89e7bff
--- /dev/null
+++ b/plat/brcm/board/common/bcm_elog_ddr.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2019-2020 Broadcom.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <ddr_init.h>
+#include <scp_cmd.h>
+#include <scp_utils.h>
+#include <platform_def.h>
+
+#include "bcm_elog_ddr.h"
+#include "m0_cfg.h"
+#include "m0_ipc.h"
+
+void elog_init_ddr_log(void)
+{
+	struct elog_setup setup = {0};
+	struct elog_global_header global;
+	struct elog_meta_record rec;
+	unsigned int rec_idx = 0;
+	uint32_t log_offset;
+	uintptr_t metadata;
+	char *rec_desc[ELOG_SUPPORTED_REC_CNT] = {"SYSRESET", "THERMAL",
+						  "DDR_ECC", "APBOOTLG",
+						  "IDM"};
+
+	/*
+	 * If this is warm boot, return immediately.
+	 * We expect metadata to be initialized already
+	 */
+	if (is_warmboot()) {
+		WARN("Warmboot detected, skip ELOG metadata initialization\n");
+		return;
+	}
+
+	memset(&global, 0, sizeof(global));
+
+	global.sector_size = ELOG_SECTOR_SIZE;
+	global.signature = ELOG_GLOBAL_META_HDR_SIG;
+	global.rec_count = ELOG_SUPPORTED_REC_CNT;
+
+	/* Start of logging area in DDR memory */
+	log_offset = ELOG_STORE_OFFSET;
+
+	/* Shift to the first RECORD header */
+	log_offset += 2 * global.sector_size;
+
+	/* Temporary place to hold metadata */
+	metadata = TMP_ELOG_METADATA_BASE;
+
+	memcpy((void *)metadata, &global, sizeof(global));
+	metadata += sizeof(global);
+
+	while (rec_idx < global.rec_count) {
+		memset(&rec, 0, sizeof(rec));
+
+		rec.type = rec_idx;
+		if (rec_idx == ELOG_REC_UART_LOG) {
+			rec.format =  ELOG_REC_FMT_ASCII;
+			rec.src_mem_type =  ELOG_SRC_MEM_TYPE_DDR;
+			rec.alt_src_mem_type =  ELOG_SRC_MEM_TYPE_FS4_SCRATCH;
+			rec.src_mem_addr =  BCM_ELOG_BL31_BASE;
+			rec.alt_src_mem_addr =  BCM_ELOG_BL2_BASE;
+			rec.rec_size =  ELOG_APBOOTLG_REC_SIZE;
+		} else if (rec_idx == ELOG_REC_IDM_LOG) {
+			rec.type = IDM_ELOG_REC_TYPE;
+			rec.format = ELOG_REC_FMT_CUSTOM;
+			rec.src_mem_type =  ELOG_SRC_MEM_TYPE_DDR;
+			rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
+			rec.src_mem_addr =  ELOG_IDM_SRC_MEM_ADDR;
+			rec.alt_src_mem_addr =  0x0;
+			rec.rec_size =  ELOG_DEFAULT_REC_SIZE;
+		} else {
+			rec.format = ELOG_REC_FMT_CUSTOM;
+			rec.src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
+			rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
+			rec.src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
+			rec.alt_src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
+			rec.rec_size = ELOG_DEFAULT_REC_SIZE;
+		}
+
+		rec.nvm_type = LOG_MEDIA_DDR;
+		rec.sector_size = ELOG_SECTOR_SIZE;
+
+		rec.rec_addr = (uint64_t)log_offset;
+		log_offset += rec.rec_size;
+
+		/* Sanity checks */
+		if (rec.type > ELOG_MAX_REC_COUNT ||
+		    rec.format > ELOG_MAX_REC_FORMAT ||
+		    (rec.nvm_type > ELOG_MAX_NVM_TYPE &&
+		     rec.nvm_type != ELOG_NVM_DEFAULT) ||
+		    !rec.rec_size ||
+		    !rec.sector_size ||
+		    rec_idx >= ELOG_SUPPORTED_REC_CNT) {
+			ERROR("Invalid ELOG record(%u) detected\n", rec_idx);
+			return;
+		}
+
+		memset(rec.rec_desc, ' ', sizeof(rec.rec_desc));
+
+		memcpy(rec.rec_desc, rec_desc[rec_idx],
+		       strlen(rec_desc[rec_idx]));
+
+		memcpy((void *)metadata, &rec, sizeof(rec));
+		metadata += sizeof(rec);
+
+		rec_idx++;
+	}
+
+	setup.params[0] = TMP_ELOG_METADATA_BASE;
+	setup.params[1] = (sizeof(global) + global.rec_count * sizeof(rec));
+	setup.cmd = ELOG_SETUP_CMD_WRITE_META;
+
+	flush_dcache_range((uintptr_t)&setup, sizeof(struct elog_setup));
+	flush_dcache_range((uintptr_t)setup.params[0], setup.params[1]);
+
+	/* initialize DDR Logging METADATA if this is NOT warmboot */
+	if (!is_warmboot()) {
+		if (scp_send_cmd(MCU_IPC_MCU_CMD_ELOG_SETUP,
+				 (uint32_t)(uintptr_t)(&setup),
+				 SCP_CMD_DEFAULT_TIMEOUT_US)) {
+			ERROR("scp_send_cmd: timeout/error for elog setup\n");
+			return;
+		}
+	}
+
+	NOTICE("MCU Error logging initialized\n");
+}