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/stingray/src/scp_utils.c b/plat/brcm/board/stingray/src/scp_utils.c
new file mode 100644
index 0000000..1d82cef
--- /dev/null
+++ b/plat/brcm/board/stingray/src/scp_utils.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2017-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <bcm_elog_ddr.h>
+#include <brcm_mhu.h>
+#include <brcm_scpi.h>
+#include <chimp.h>
+#include <cmn_plat_util.h>
+#include <ddr_init.h>
+#include <scp.h>
+#include <scp_cmd.h>
+#include <scp_utils.h>
+
+#include "m0_cfg.h"
+#include "m0_ipc.h"
+
+#ifdef BCM_ELOG
+static void prepare_elog(void)
+{
+#if (CLEAN_DDR && !defined(MMU_DISABLED))
+	/*
+	 * Now DDR has been initialized. We want to copy all the logs in SRAM
+	 * into DDR so we will have much more space to store the logs in the
+	 * next boot stage
+	 */
+	bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE,
+			   MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE)
+			 );
+
+	/*
+	 * We are almost at the end of BL2, and we can stop log here so we do
+	 * not need to add 'bcm_elog_exit' to the standard BL2 code. The
+	 * benefit of capturing BL2 logs after this is very minimal in a
+	 * production system.
+	 */
+	bcm_elog_exit();
+#endif
+
+	/*
+	 * Notify CRMU that now it should pull logs from DDR instead of from
+	 * FS4 SRAM.
+	 */
+	SCP_WRITE_CFG(flash_log.can_use_ddr, 1);
+}
+#endif
+
+bool is_crmu_alive(void)
+{
+	return (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0, SCP_CMD_DEFAULT_TIMEOUT_US)
+		== 0);
+}
+
+bool bcm_scp_issue_sys_reset(void)
+{
+	return (scp_send_cmd(MCU_IPC_MCU_CMD_L1_RESET, 0,
+			     SCP_CMD_DEFAULT_TIMEOUT_US));
+}
+
+/*
+ * Note that this is just a temporary implementation until
+ * channels are introduced
+ */
+
+int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+	int scp_patch_activated, scp_patch_version;
+#ifndef EMULATION_SETUP
+	uint8_t active_ch_bitmap, i;
+#endif
+	uint32_t reset_state = 0;
+	uint32_t mcu_ap_init_param = 0;
+
+	/*
+	 * First check if SCP patch has already been loaded
+	 * Send NOP command and see if there is a valid response
+	 */
+	scp_patch_activated =
+		(scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0,
+		SCP_CMD_DEFAULT_TIMEOUT_US) == 0);
+	if (scp_patch_activated) {
+		INFO("SCP Patch is already active.\n");
+
+		reset_state =  SCP_READ_CFG(board_cfg.reset_state);
+		mcu_ap_init_param = SCP_READ_CFG(board_cfg.mcu_init_param);
+
+		/* Clear reset state, it's been already read */
+		SCP_WRITE_CFG(board_cfg.reset_state, 0);
+
+		if (mcu_ap_init_param & MCU_PATCH_LOADED_BY_NITRO) {
+			/*
+			 * Reset "MCU_PATCH_LOADED_BY_NITRO" flag, but
+			 * Preserve any other flags we don't deal with here
+			 */
+			INFO("AP booted by Nitro\n");
+			SCP_WRITE_CFG(
+					board_cfg.mcu_init_param,
+					mcu_ap_init_param &
+						~MCU_PATCH_LOADED_BY_NITRO
+				      );
+		}
+	} else {
+		/*
+		 * MCU Patch not loaded, so load it.
+		 * MCU patch stamps critical points in REG9 (debug test-point)
+		 * Display its last content here. This helps to locate
+		 * where crash occurred if a CRMU watchdog kicked in.
+		 */
+		int ret;
+
+		INFO("MCU Patch Point: 0x%x\n",
+			mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9));
+
+		ret = download_scp_patch((void *)scp_bl2_image_info->image_base,
+				scp_bl2_image_info->image_size);
+		if (ret != 0)
+			return ret;
+
+		VERBOSE("SCP Patch loaded OK.\n");
+
+		ret = scp_send_cmd(MCU_IPC_MCU_CMD_INIT,
+				MCU_PATCH_LOADED_BY_AP,
+				SCP_CMD_SCP_BOOT_TIMEOUT_US);
+		if (ret) {
+			ERROR("SCP Patch could not initialize; error %d\n",
+				ret);
+			return ret;
+		}
+
+		INFO("SCP Patch successfully initialized.\n");
+	}
+
+	scp_patch_version = scp_send_cmd(MCU_IPC_MCU_CMD_GET_FW_VERSION, 0,
+				SCP_CMD_DEFAULT_TIMEOUT_US);
+	INFO("SCP Patch version :0x%x\n", scp_patch_version);
+
+	/* Next block just reports current AVS voltages (if applicable) */
+	{
+		uint16_t vcore_mv, ihost03_mv, ihost12_mv;
+
+		vcore_mv = SCP_READ_CFG16(vcore.millivolts) +
+				SCP_READ_CFG8(vcore.avs_cfg.additive_margin);
+		ihost03_mv = SCP_READ_CFG16(ihost03.millivolts) +
+				SCP_READ_CFG8(ihost03.avs_cfg.additive_margin);
+		ihost12_mv = SCP_READ_CFG16(ihost12.millivolts) +
+				SCP_READ_CFG8(ihost12.avs_cfg.additive_margin);
+
+		if (vcore_mv || ihost03_mv || ihost12_mv) {
+			INFO("AVS voltages from cfg (including margin)\n");
+			if (vcore_mv > 0)
+				INFO("%s\tVCORE: %dmv\n",
+					SCP_READ_CFG8(vcore.avs_cfg.avs_set) ?
+					"*" : "n/a", vcore_mv);
+			if (ihost03_mv > 0)
+				INFO("%s\tIHOST03: %dmv\n",
+				SCP_READ_CFG8(ihost03.avs_cfg.avs_set) ?
+					"*" : "n/a", ihost03_mv);
+			if (ihost12_mv > 0)
+				INFO("%s\tIHOST12: %dmv\n",
+				SCP_READ_CFG8(ihost12.avs_cfg.avs_set) ?
+					"*" : "n/a", ihost12_mv);
+		} else {
+			INFO("AVS settings not applicable\n");
+		}
+	}
+
+#if (CLEAN_DDR && !defined(MMU_DISABLED) && !defined(EMULATION_SETUP))
+	/* This will clean the DDR and enable ECC if set */
+	check_ddr_clean();
+#endif
+
+#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR)
+	elog_init_ddr_log();
+#endif
+
+#ifdef BCM_ELOG
+	/* Prepare ELOG to use DDR */
+	prepare_elog();
+#endif
+
+#ifndef EMULATION_SETUP
+	/* Ask ddr_init to save obtained DDR information into DDR */
+	ddr_info_save();
+#endif
+
+	/*
+	 * Configure TMON DDR address.
+	 * This cfg is common for all cases
+	 */
+	SCP_WRITE_CFG(tmon_cfg.ddr_desc, TMON_SHARED_DDR_ADDRESS);
+
+	if (reset_state == SOFT_RESET_L3 && !mcu_ap_init_param) {
+		INFO("SCP configuration after L3 RESET done.\n");
+		return 0;
+	}
+
+	if (bcm_chimp_is_nic_mode())
+		/* Configure AP WDT to not reset the NIC interface */
+		SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3);
+
+#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR)
+	/* When AP WDog triggers perform L3 reset if DDR err logging enabled */
+	SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3);
+#endif
+
+#ifndef EMULATION_SETUP
+
+#ifdef DDR_SCRUB_ENA
+	ddr_scrub_enable();
+#endif
+	/* Fill the Active channel information */
+	active_ch_bitmap = get_active_ddr_channel();
+	for (i = 0; i < MAX_NR_DDR_CH; i++)
+		SCP_WRITE_CFG(ddr_cfg.ddr_cfg[i],
+			      (active_ch_bitmap & BIT(i)) ? 1 : 0);
+#endif
+	return 0;
+}