Merge "xlat_tables_v2: use get_current_el_maybe_constant() in is_dcache_enabled()" into integration
diff --git a/docs/plat/brcm-stingray.rst b/docs/plat/brcm-stingray.rst
new file mode 100644
index 0000000..c43c850
--- /dev/null
+++ b/docs/plat/brcm-stingray.rst
@@ -0,0 +1,40 @@
+Description
+===========
+Broadcom's Stingray(BCM958742t) is a multi-core processor with 8 Cortex-A72 cores.
+Trusted Firmware-A (TF-A) is used to implement secure world firmware, supporting
+BL2 and BL31 for Broadcom Stingray SoCs
+
+On Poweron, Boot ROM will load bl2 image and Bl2 will initialize the hardware,
+then loads bl31 and bl33 into DDR and boots to bl33.
+
+Boot Sequence
+=============
+
+Bootrom --> TF-A BL2 --> TF-A BL31 --> BL33(u-boot)
+
+Code Locations
+--------------
+-  Trusted Firmware-A:
+   `link <https://github.com/ARM-software/arm-trusted-firmware>`__
+
+How to build
+============
+
+Build Procedure
+---------------
+
+-  Prepare AARCH64 toolchain.
+
+-  Build u-boot first, and get the binary image: u-boot.bin,
+
+-  Build TF-A
+
+   Build fip:
+
+   .. code::shell
+
+       make CROSS_COMPILE=aarch64-linux-gnu- PLAT=stingray BOARD_CFG=bcm958742t all fip BL33=u-boot.bin
+
+Deploy TF-A Images
+-----------------
+The u-boot will be upstreamed soon, this doc will be updated once they are ready, and the link will be posted.
diff --git a/drivers/brcm/chimp.c b/drivers/brcm/chimp.c
new file mode 100644
index 0000000..81767bb
--- /dev/null
+++ b/drivers/brcm/chimp.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <drivers/delay_timer.h>
+
+#include <chimp.h>
+#include <chimp_nv_defs.h>
+
+#define CHIMP_DEFAULT_STARTUP_ADDR 0xb4300000
+
+/* ChiMP's view of APE scratchpad memory for fastboot */
+#define CHIMP_FASTBOOT_ADDR 0x61000000
+
+#define CHIMP_PREPARE_ACCESS_WINDOW(addr) \
+	(\
+		mmio_write_32(\
+			NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT, \
+			addr & 0xffc00000)\
+	)
+#define CHIMP_INDIRECT_TGT_ADDR(addr) \
+	(CHIMP_INDIRECT_BASE + (addr & CHIMP_INDIRECT_ADDR_MASK))
+
+#define CHIMP_CTRL_ADDR(x) (CHIMP_REG_CTRL_BASE + x)
+
+/* For non-PAXC builds */
+#ifndef CHIMP_FB1_ENTRY
+#define CHIMP_FB1_ENTRY 0
+#endif
+
+#define CHIMP_DBG	VERBOSE
+
+void bcm_chimp_write(uintptr_t addr, uint32_t value)
+{
+	CHIMP_PREPARE_ACCESS_WINDOW(addr);
+	mmio_write_32(CHIMP_INDIRECT_TGT_ADDR(addr), value);
+}
+
+uint32_t bcm_chimp_read(uintptr_t addr)
+{
+	CHIMP_PREPARE_ACCESS_WINDOW(addr);
+	return mmio_read_32(CHIMP_INDIRECT_TGT_ADDR(addr));
+}
+
+void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits)
+{
+	CHIMP_PREPARE_ACCESS_WINDOW(addr);
+	mmio_clrbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits);
+}
+
+void bcm_chimp_setbits(uintptr_t addr, uint32_t bits)
+{
+	CHIMP_PREPARE_ACCESS_WINDOW(addr);
+	mmio_setbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits);
+}
+
+int bcm_chimp_is_nic_mode(void)
+{
+	uint32_t val;
+
+	/* Check if ChiMP straps are set */
+	val = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
+	val &= CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK;
+
+	return val == CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK;
+}
+
+void bcm_chimp_fru_prog_done(bool is_done)
+{
+	uint32_t val;
+
+	val = is_done ? (1 << CHIMP_FRU_PROG_DONE_BIT) : 0;
+	bcm_chimp_setbits(CHIMP_REG_ECO_RESERVED, val);
+}
+
+int bcm_chimp_handshake_done(void)
+{
+	uint32_t value;
+
+	value = bcm_chimp_read(CHIMP_REG_ECO_RESERVED);
+	value &= (1 << CHIMP_FLASH_ACCESS_DONE_BIT);
+
+	return value != 0;
+}
+
+int bcm_chimp_wait_handshake(void)
+{
+	uint32_t timeout = CHIMP_HANDSHAKE_TIMEOUT_MS;
+	uint32_t status;
+
+	INFO("Waiting for ChiMP handshake...\n");
+	do {
+		if (bcm_chimp_handshake_done())
+			break;
+		/* No need to wait if ChiMP reported an error */
+		status = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG);
+		if (status & CHIMP_ERROR_MASK) {
+			ERROR("ChiMP error 0x%x. Wait aborted\n", status);
+			break;
+		}
+		mdelay(1);
+	} while (--timeout);
+
+	if (!bcm_chimp_handshake_done()) {
+		if (timeout == 0) {
+			WARN("Timeout waiting for ChiMP handshake\n");
+		}
+	} else {
+		INFO("Got handshake from ChiMP!\n");
+	}
+
+	return bcm_chimp_handshake_done();
+}
+
+uint32_t bcm_chimp_read_ctrl(uint32_t offset)
+{
+	return bcm_chimp_read(CHIMP_CTRL_ADDR(offset));
+}
+
+static int bcm_chimp_nitro_reset(void)
+{
+	uint32_t timeout;
+
+	/* Perform tasks done by M0 in NIC mode */
+	CHIMP_DBG("Taking Nitro out of reset\n");
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
+		/* MHB_RESET_N */
+		(1 << CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R)  |
+		/* PCI_RESET_N */
+		(1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) |
+		/* PM_RESET_N */
+		(1 << CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R)   |
+		/* NIC_RESET_N */
+		(1 << CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R)
+	);
+
+	/* Wait until Nitro is out of reset */
+	timeout = NIC_RESET_RELEASE_TIMEOUT_US;
+	do {
+		uint32_t value;
+
+		value = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG);
+		if ((value & CHIMP_BPE_MODE_ID_MASK) ==
+				CHIMP_BPE_MODE_ID_PATTERN)
+			break;
+		udelay(1);
+	} while (--timeout);
+
+	if (timeout == 0) {
+		ERROR("NIC reset release timed out\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void bcm_nitro_secure_mode_enable(void)
+{
+	mmio_setbits_32(CDRU_NITRO_CONTROL,
+		(1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R) |
+		(1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R));
+	mmio_write_32(NITRO_TZPC_TZPCDECPROT0clr,
+		/* NITRO_TZPC */
+		1 << NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R);
+}
+
+static int bcm_chimp_reset_and_initial_setup(void)
+{
+
+	int err;
+	uint32_t handshake_reg;
+
+	err = bcm_chimp_nitro_reset();
+	if (err)
+		return err;
+
+	/* Enable Nitro secure mode */
+	bcm_nitro_secure_mode_enable();
+
+	/* Force ChiMP back into reset */
+	bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
+		1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R);
+
+	handshake_reg = (1 << SR_IN_SMARTNIC_MODE_BIT);
+
+	/* Get OTP secure Chimp boot status */
+	if (mmio_read_32(CRMU_OTP_STATUS) & (1 << CRMU_OTP_STATUS_BIT))
+		handshake_reg |= (1 << SR_CHIMP_SECURE_BOOT_BIT);
+
+	bcm_chimp_write(CHIMP_REG_ECO_RESERVED, handshake_reg);
+
+	CHIMP_DBG("ChiMP reset and initial handshake parameters set\n");
+
+	return 0;
+}
+
+static void bcm_nitro_chimp_release_reset(void)
+{
+	bcm_chimp_clrbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
+		1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R);
+
+	CHIMP_DBG("Nitro Reset Released\n");
+}
+
+static void bcm_chimp_set_fastboot(int mode)
+{
+	uint32_t fb_entry;
+
+	/* 1. Enable fastboot */
+	bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
+			(1 << CHIMP_FAST_BOOT_MODE_BIT));
+	fb_entry = CHIMP_FASTBOOT_ADDR | mode;
+	if (mode == CHIMP_FASTBOOT_JUMP_IN_PLACE)
+		fb_entry = CHIMP_FB1_ENTRY;
+	/* 2. Write startup address and mode */
+	INFO("Setting fastboot type %d entry to 0x%x\n", mode, fb_entry);
+	bcm_chimp_write(
+			CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
+			fb_entry);
+}
+
+#ifndef CHIMPFW_USE_SIDELOAD
+static void bcm_chimp_load_fw_from_spi(uintptr_t spi_addr, size_t size)
+{
+	uintptr_t ape_scpad;
+	uintptr_t dest;
+	size_t bytes_left;
+
+	ape_scpad = CHIMP_REG_CHIMP_APE_SCPAD;
+	dest = CHIMP_INDIRECT_TGT_ADDR(CHIMP_REG_CHIMP_APE_SCPAD);
+	bytes_left = size;
+
+	while (bytes_left) {
+		uint32_t delta;
+
+		delta = bytes_left > CHIMP_WINDOW_SIZE ?
+			bytes_left - CHIMP_WINDOW_SIZE : bytes_left;
+		CHIMP_PREPARE_ACCESS_WINDOW(ape_scpad);
+		INFO("Transferring %d byte(s) from 0x%lx to 0x%lx\n",
+			delta, spi_addr, dest);
+	/*
+	 * This single memcpy call takes significant amount of time
+	 * on Palladium. Be patient
+	 */
+		memcpy((void *)dest, (void *)spi_addr, delta);
+		bytes_left -= delta;
+		INFO("Transferred %d byte(s) from 0x%lx to 0x%lx (%lu%%)\n",
+			delta, spi_addr, dest,
+			((size - bytes_left) * 100)/size);
+		spi_addr += delta;
+		dest += delta;
+		ape_scpad += delta;
+	}
+}
+
+static int bcm_chimp_find_fw_in_spi(uintptr_t *addr, size_t *size)
+{
+	int i;
+	bnxnvm_master_block_header_t *master_block_hdr;
+	bnxnvm_directory_block_header_t *dir_block_hdr;
+	bnxnvm_directory_entry_t *dir_entry;
+	int found;
+
+	found = 0;
+
+	/* Read the master block */
+	master_block_hdr =
+		(bnxnvm_master_block_header_t *)(uintptr_t)QSPI_BASE_ADDR;
+	if (master_block_hdr->sig != BNXNVM_MASTER_BLOCK_SIG) {
+		WARN("Invalid masterblock 0x%x (expected 0x%x)\n",
+			master_block_hdr->sig,
+			BNXNVM_MASTER_BLOCK_SIG);
+		return -NV_NOT_NVRAM;
+	}
+	if ((master_block_hdr->block_size > NV_MAX_BLOCK_SIZE) ||
+		(master_block_hdr->directory_offset >=
+			master_block_hdr->nvram_size)) {
+		WARN("Invalid masterblock block size 0x%x or directory offset 0x%x\n",
+			master_block_hdr->block_size,
+			master_block_hdr->directory_offset);
+		return -NV_BAD_MB;
+	}
+
+	/* Skip to the Directory block start */
+	dir_block_hdr =
+		(bnxnvm_directory_block_header_t *)
+			((uintptr_t)QSPI_BASE_ADDR +
+				master_block_hdr->directory_offset);
+	if (dir_block_hdr->sig != BNXNVM_DIRECTORY_BLOCK_SIG) {
+		WARN("Invalid directory header 0x%x (expected 0x%x)\n",
+			dir_block_hdr->sig,
+			BNXNVM_DIRECTORY_BLOCK_SIG);
+		return -NV_BAD_DIR_HEADER;
+	}
+
+	/* Locate the firmware */
+	for (i = 0; i < dir_block_hdr->entries; i++) {
+		*addr = ((uintptr_t)dir_block_hdr + dir_block_hdr->length +
+			i * dir_block_hdr->entry_length);
+		dir_entry = (bnxnvm_directory_entry_t *)(*addr);
+		if ((dir_entry->type == BNX_DIR_TYPE_BOOTCODE) ||
+				(dir_entry->type == BNX_DIR_TYPE_BOOTCODE_2)) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		return -NV_FW_NOT_FOUND;
+
+	*addr = QSPI_BASE_ADDR + dir_entry->item_location;
+	*size = dir_entry->data_length;
+
+	INFO("Found chimp firmware at 0x%lx, size %lu byte(s)\n",
+			*addr, *size);
+
+	return NV_OK;
+}
+#endif
+
+int bcm_chimp_initiate_fastboot(int fastboot_type)
+{
+	int err;
+
+	if ((fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) &&
+			(fastboot_type <= CHIMP_FASTBOOT_JUMP_DECOMPRESS)) {
+		CHIMP_DBG("Initiating ChiMP fastboot type %d\n", fastboot_type);
+	}
+
+	/*
+	 * If we are here, M0 did not setup Nitro because NIC mode
+	 * strap was not present
+	 */
+	err = bcm_chimp_reset_and_initial_setup();
+	if (err)
+		return err;
+
+	if (fastboot_type > CHIMP_FASTBOOT_JUMP_DECOMPRESS) {
+		WARN("ChiMP setup deferred\n");
+		return -1;
+	}
+
+	if (fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) {
+
+		if ((fastboot_type == CHIMP_FASTBOOT_JUMP_IN_PLACE) &&
+			(CHIMP_FB1_ENTRY == 0)) {
+			ERROR("Missing ESAL entry point for fastboot type 1.\n"
+			"Fastboot failed\n");
+			return -1;
+		}
+
+		/*
+		 * TODO: We need to think of the way to load the ChiMP fw.
+		 * This could be SPI, NAND, etc.
+		 * For now we temporarily stick to the SPI load unless
+		 * CHIMPFW_USE_SIDELOAD is defined. Note that for the SPI NVRAM
+		 * image we need to parse directory and get the image.
+		 * When we load image from other media there is no need to
+		 * parse because fw image can be directly placed into the APE's
+		 * scratchpad.
+		 * For sideload method we simply reset the ChiMP, set bpe_reg
+		 * to do fastboot with the type we define, and release from
+		 * reset so that ROM loader would initiate fastboot immediately
+		 */
+#ifndef CHIMPFW_USE_SIDELOAD
+		{
+			uintptr_t spi_addr;
+			size_t size;
+
+			err = bcm_chimp_find_fw_in_spi(&spi_addr, &size);
+			if (!err) {
+				INFO("Loading ChiMP firmware, addr 0x%lx, size %lu byte(s)\n",
+					spi_addr, size);
+				bcm_chimp_load_fw_from_spi(spi_addr, size);
+			} else {
+				ERROR("Error %d ChiMP firmware not in NVRAM directory!\n",
+					err);
+			}
+		}
+#else
+		INFO("Skip ChiMP QSPI fastboot type %d due to sideload requested\n",
+		     fastboot_type);
+#endif
+		if (!err) {
+			INFO("Instruct ChiMP to fastboot\n");
+			bcm_chimp_set_fastboot(fastboot_type);
+			INFO("Fastboot mode set\n");
+		}
+	}
+
+	bcm_nitro_chimp_release_reset();
+
+	return err;
+}
diff --git a/drivers/brcm/emmc/emmc_chal_sd.c b/drivers/brcm/emmc/emmc_chal_sd.c
new file mode 100644
index 0000000..34d761c
--- /dev/null
+++ b/drivers/brcm/emmc/emmc_chal_sd.c
@@ -0,0 +1,1017 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#include "bcm_emmc.h"
+#include "emmc_chal_types.h"
+#include "emmc_chal_sd.h"
+#include "emmc_pboot_hal_memory_drv.h"
+
+extern void emmc_soft_reset(void);
+
+#define SD_VDD_WINDOW_1_6_TO_1_7        0x00000010	// 1.6 V to 1.7 Volts
+#define SD_VDD_WINDOW_1_7_TO_1_8        0x00000020	// 1.7 V to 1.8 Volts
+#define SD_VDD_WINDOW_1_8_TO_1_9        0x00000040	// 1.8 V to 1.9 Volts
+#define SD_VDD_WINDOW_1_9_TO_2_0        0x00000080	// 1.9 V to 2.0 Volts
+#define SD_VDD_WINDOW_2_0_TO_2_1        0x00000100	// 2.0 V to 2.1 Volts
+#define SD_VDD_WINDOW_2_1_TO_2_2        0x00000200	// 2.1 V to 2.2 Volts
+#define SD_VDD_WINDOW_2_2_TO_2_3        0x00000400	// 2.2 V to 2.3 Volts
+#define SD_VDD_WINDOW_2_3_TO_2_4        0x00000800	// 2.3 V to 2.4 Volts
+#define SD_VDD_WINDOW_2_4_TO_2_5        0x00001000	// 2.4 V to 2.5 Volts
+#define SD_VDD_WINDOW_2_5_TO_2_6        0x00002000	// 2.5 V to 2.6 Volts
+#define SD_VDD_WINDOW_2_6_TO_2_7        0x00004000	// 2.6 V to 2.7 Volts
+#define SD_VDD_WINDOW_2_7_TO_2_8        0x00008000	// 2.7 V to 2.8 Volts
+#define SD_VDD_WINDOW_2_8_TO_2_9        0x00010000	// 2.8 V to 2.9 Volts
+#define SD_VDD_WINDOW_2_9_TO_3_0        0x00020000	// 2.9 V to 3.0 Volts
+#define SD_VDD_WINDOW_3_0_TO_3_1        0x00040000	// 3.0 V to 3.1 Volts
+#define SD_VDD_WINDOW_3_1_TO_3_2        0x00080000	// 3.1 V to 3.2 Volts
+#define SD_VDD_WINDOW_3_2_TO_3_3        0x00100000	// 3.2 V to 3.3 Volts
+#define SD_VDD_WINDOW_3_3_TO_3_4        0x00200000	// 3.3 V to 3.4 Volts
+#define SD_VDD_WINDOW_3_4_TO_3_5        0x00400000	// 3.4 V to 3.5 Volts
+#define SD_VDD_WINDOW_3_5_TO_3_6        0x00800000	// 3.5 V to 3.6 Volts
+
+#define SD_VDD_WINDOW_1_6_TO_2_6        (SD_VDD_WINDOW_1_6_TO_1_7 |	\
+					 SD_VDD_WINDOW_1_7_TO_1_8 |	\
+					 SD_VDD_WINDOW_1_8_TO_1_9 |	\
+					 SD_VDD_WINDOW_1_9_TO_2_0 |	\
+					 SD_VDD_WINDOW_2_0_TO_2_1 |	\
+					 SD_VDD_WINDOW_2_1_TO_2_2 |	\
+					 SD_VDD_WINDOW_2_2_TO_2_3 |	\
+					 SD_VDD_WINDOW_2_3_TO_2_4 |	\
+					 SD_VDD_WINDOW_2_4_TO_2_5 |	\
+					 SD_VDD_WINDOW_2_5_TO_2_6)
+
+#define SD_VDD_WINDOW_2_6_TO_3_2        (SD_VDD_WINDOW_2_6_TO_2_7 |	\
+					 SD_VDD_WINDOW_2_7_TO_2_8 |	\
+					 SD_VDD_WINDOW_2_8_TO_2_9 |	\
+					 SD_VDD_WINDOW_2_9_TO_3_0 |	\
+					 SD_VDD_WINDOW_3_0_TO_3_1 |	\
+					 SD_VDD_WINDOW_3_1_TO_3_2)
+
+#define SD_VDD_WINDOW_3_2_TO_3_6        (SD_VDD_WINDOW_3_2_TO_3_3 |	\
+					 SD_VDD_WINDOW_3_3_TO_3_4 |	\
+					 SD_VDD_WINDOW_3_4_TO_3_5 |	\
+					 SD_VDD_WINDOW_3_5_TO_3_6)
+
+
+static int32_t chal_sd_set_power(struct sd_dev *handle,
+				 uint32_t voltage, uint32_t state);
+
+static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary);
+
+static int32_t chal_sd_setup_handler(struct sd_dev *handle,
+				     uint32_t sdBbase, uint32_t hostBase);
+
+/*
+ * Configure host controller pwr settings,
+ * to match voltage requirements by SD Card
+ */
+static int32_t chal_sd_set_power(struct sd_dev *handle,
+				 uint32_t voltage, uint32_t state)
+{
+	int32_t rc, rval = SD_FAIL;
+	uint32_t time = 0;
+
+	if (handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr +
+			   SD4_EMMC_TOP_CTRL_OFFSET,
+			   (SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK |
+			    SD4_EMMC_TOP_CTRL_SDPWR_MASK),
+			   (voltage << 9));
+
+	/*
+	 * Long delay is required here in emulation.  Without this, the initial
+	 * commands sent to the eMMC card timeout.  We don't know if this
+	 * delay is necessary with silicon, leaving in for safety.
+	 * It is observed that 403ms on emulation system and as per the clock
+	 * calculations it is expected to complete with in 1ms on chip
+	 */
+	do {
+		rc =  mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				   SD4_EMMC_TOP_INTR_OFFSET);
+
+		if ((rc & SD4_EMMC_TOP_INTR_CRDINS_MASK) ==
+				SD4_EMMC_TOP_INTR_CRDINS_MASK)
+			break;
+
+		mdelay(1);
+	} while (time++ < EMMC_CARD_DETECT_TIMEOUT_MS);
+
+	if (time >= EMMC_CARD_DETECT_TIMEOUT_MS) {
+		ERROR("EMMC: Card insert event detection timeout\n");
+		return rval;
+	}
+
+	VERBOSE("EMMC: Card detection delay: %dms\n", time);
+
+	if (state)
+		mmio_setbits_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET,
+				SD4_EMMC_TOP_CTRL_SDPWR_MASK);
+
+	/* dummy write & ack to verify if the sdio is ready to send commads */
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, 0);
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, 0);
+
+	/*
+	 * 63ms observed on emulation system, As per clock calculations
+	 * it will complete  < 1ms on chip.
+	 */
+	time = 0;
+	do {
+		rc = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				  SD4_EMMC_TOP_INTR_OFFSET);
+
+		if (rc & SD4_EMMC_TOP_INTR_ERRIRQ_MASK)
+			break;
+
+		if ((rc & SD4_EMMC_TOP_INTR_CMDDONE_MASK) ==
+				SD4_EMMC_TOP_INTR_CMDDONE_MASK)
+			break;
+
+		mdelay(1);
+	} while (time++ < EMMC_CMD_TIMEOUT_MS);
+
+	if (time >= EMMC_CMD_TIMEOUT_MS) {
+		WARN("%s %d Initial dummy command timeout is happened\n",
+		      __func__, __LINE__);
+		return rval;
+	}
+
+	VERBOSE("EMMC: Dummy Command delay: %dms\n", time);
+
+	return SD_OK;
+}
+
+/*
+ * Configure DMA Boundaries
+ */
+static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary)
+{
+	if (handle == NULL)
+		return;
+
+	mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr +
+			   SD4_EMMC_TOP_BLOCK_OFFSET,
+			   SD4_EMMC_TOP_BLOCK_HSBS_MASK, boundary);
+}
+
+static int32_t chal_sd_setup_handler(struct sd_dev *handle, uint32_t sdBase,
+				     uint32_t hostBase)
+{
+	if (handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle->ctrl.sdRegBaseAddr = sdBase;
+	handle->ctrl.hostRegBaseAddr = hostBase;
+	handle->ctrl.present = 0;
+	handle->ctrl.rca = 0;
+	handle->ctrl.blkGapEnable = 0;
+	handle->ctrl.cmdStatus = 0;
+
+	return SD_OK;
+}
+
+/*
+ * Initialize SD Host controller
+ */
+int32_t chal_sd_init(CHAL_HANDLE *sd_handle)
+{
+	uint32_t cap_val_l = 0;
+	uint32_t ctl_val, voltage;
+	uint32_t timeout_val;
+	struct sd_dev *handle;
+	uint32_t reg_val;
+	int32_t rval = SD_FAIL;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *)sd_handle;
+
+	/*
+	 * Set SDIO Host Controller capabilities register
+	 */
+	EMMC_TRACE("Set Host Controller Capabilities register\n");
+
+	reg_val = 0;
+	reg_val |= (1 << ICFG_SDIO0_CAP0__SLOT_TYPE_R);
+	reg_val |= (0 << ICFG_SDIO0_CAP0__INT_MODE_R);
+	reg_val |= (0 << ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__SUSPEND_RESUME_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__SDMA_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__HIGH_SPEED_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__ADMA2_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R);
+	reg_val |= (2 << ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R);
+	reg_val |= (0xd0 << ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R);
+	reg_val |= (0x30 << ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R);
+
+	mmio_write_32(ICFG_SDIO0_CAP0, reg_val);
+
+	reg_val = 0;
+	reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_MODE_R);
+	reg_val |= (0 << ICFG_SDIO0_CAP1__CLK_MULT_R);
+	reg_val |= (0 << ICFG_SDIO0_CAP1__RETUNING_MODE_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__TUNE_SDR50_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__TIME_RETUNE_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_D_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_C_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_A_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__DDR50_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__SDR104_R);
+	reg_val |= (1 << ICFG_SDIO0_CAP1__SDR50_R);
+
+	mmio_write_32(ICFG_SDIO0_CAP1, reg_val);
+
+	/* Reset the SDIO controller */
+	chal_sd_stop();
+
+	/* Turn on SD clock */
+	chal_sd_set_clock(sd_handle,
+			  chal_sd_freq_2_div_ctrl_setting(INIT_CLK_FREQ), 1);
+
+	/* program data time out value to the max */
+	timeout_val = SD_HOST_CORE_TIMEOUT;
+
+	ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			       SD4_EMMC_TOP_CTRL1_OFFSET);
+	ctl_val |= ((timeout_val & 0xf) << SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT);
+
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
+		      ctl_val);
+
+	/* enable all interrupt status */
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET,
+		      0);
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET,
+		      0);
+
+	SD_US_DELAY(100);
+
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET,
+		      SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS);
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET,
+		      SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS);
+
+	/* Select SD bus voltage */
+	cap_val_l = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				 SD4_EMMC_TOP_CAPABILITIES1_OFFSET);
+	handle->cfg.voltage = 0;
+	voltage = 0x7;
+
+	if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V33_MASK) {
+		handle->cfg.voltage |= SD_VDD_WINDOW_3_3_TO_3_4;
+		voltage = 0x7;
+	} else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V3_MASK) {
+		handle->cfg.voltage |= SD_VDD_WINDOW_3_0_TO_3_1;
+		voltage = 0x6;
+	} else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V18_MASK) {
+		handle->cfg.voltage |= SD_VDD_WINDOW_1_8_TO_1_9;
+		voltage = 0x5;
+	}
+
+	rval = chal_sd_set_power(handle, voltage, SD4_EMMC_TOP_CTRL_SDPWR_MASK);
+
+	ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			       SD4_EMMC_TOP_HCVERSIRQ_OFFSET);
+	handle->ctrl.version = ((ctl_val >> 16) & 0xFF);
+
+	return rval;
+}
+
+void chal_sd_set_speed(CHAL_HANDLE *sd_handle, uint32_t speed)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	if (speed) {
+		EMMC_TRACE("enable HighSpeed\n");
+		mmio_setbits_32(handle->ctrl.sdRegBaseAddr +
+				SD4_EMMC_TOP_CTRL_OFFSET,
+				SD4_EMMC_TOP_CTRL_HSEN_MASK);
+	} else {
+		EMMC_TRACE("disable HighSpeed\n");
+		mmio_clrbits_32(handle->ctrl.sdRegBaseAddr +
+				SD4_EMMC_TOP_CTRL_OFFSET,
+				SD4_EMMC_TOP_CTRL_HSEN_MASK);
+	}
+}
+
+int32_t chal_sd_stop(void)
+{
+	uintptr_t idm_rst_ctrl_addr = EMMC_IDM_RESET_CTRL_ADDR;
+
+	/* Configure IO pins */
+	emmc_soft_reset();
+
+	/* Reset the SDIO controller */
+	mmio_write_32(idm_rst_ctrl_addr, 1);
+	SD_US_DELAY(100);
+	mmio_write_32(idm_rst_ctrl_addr, 0);
+	SD_US_DELAY(100);
+
+	return SD_OK;
+}
+
+/*
+ * Check if host supports specified capability
+ * returns -ve val on error, 0 if capability not supported else 1.
+ */
+int32_t chal_sd_check_cap(CHAL_HANDLE *sd_handle, uint32_t caps)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	if (caps & mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				SD4_EMMC_TOP_CAPABILITIES1_OFFSET))
+		return 1;
+	else
+		return 0;
+}
+
+int32_t chal_sd_start(CHAL_HANDLE *sd_handle,
+		      uint32_t mode, uint32_t sd_base, uint32_t host_base)
+{
+
+	struct sd_dev *handle;
+	int32_t rval = SD_FAIL;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	handle->cfg.mode = SD_PIO_MODE;	/* set to PIO mode first for init */
+	handle->cfg.dma = SD_DMA_OFF;
+
+	chal_sd_setup_handler(handle, sd_base, host_base);
+
+	/* init and start hw */
+	rval = chal_sd_init(sd_handle);
+	if (rval != SD_OK)
+		return rval;
+
+	chal_sd_clear_pending_irq(sd_handle);
+
+	handle->ctrl.eventList = 0;
+	handle->cfg.mode = mode;
+
+	return SD_OK;
+}
+
+/*
+ * Function to check 8bits of err generated from auto CMD12
+ */
+int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sd_handle)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	return (mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			     SD4_EMMC_TOP_ERRSTAT_OFFSET) & 0xFF);
+}
+
+/*
+ * Read present state register
+ */
+uint32_t chal_sd_get_present_status(CHAL_HANDLE *sd_handle)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	return mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			    SD4_EMMC_TOP_PSTATE_OFFSET);
+}
+
+/*
+ * Set SD bus width
+ */
+int32_t chal_sd_config_bus_width(CHAL_HANDLE *sd_handle, int32_t width)
+{
+	uint32_t ctl_val;
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *)sd_handle;
+
+	ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			       SD4_EMMC_TOP_CTRL_OFFSET);
+
+	switch (width) {
+#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
+	case SD_BUS_DATA_WIDTH_8BIT:
+		ctl_val &= ~SD_BUS_DATA_WIDTH_4BIT;
+		ctl_val |= SD_BUS_DATA_WIDTH_8BIT;
+		break;
+#endif
+	case SD_BUS_DATA_WIDTH_4BIT:
+		ctl_val &= ~SD_BUS_DATA_WIDTH_8BIT;
+		ctl_val |= SD_BUS_DATA_WIDTH_4BIT;
+		break;
+	case SD_BUS_DATA_WIDTH_1BIT:
+		ctl_val &= ~(SD_BUS_DATA_WIDTH_4BIT | SD_BUS_DATA_WIDTH_8BIT);
+		break;
+	default:
+		return SD_INV_DATA_WIDTH;
+	};
+
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET,
+		      ctl_val);
+
+	return SD_OK;
+}
+
+/*
+ * Function to enable or disable DMA control.
+ */
+int32_t chal_sd_set_dma(CHAL_HANDLE *sd_handle, uint32_t mode)
+{
+	uint32_t val;
+	struct sd_dev *handle;
+	int32_t rc;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *)sd_handle;
+
+	if (mode) {
+		rc = chal_sd_check_cap(sd_handle,
+				       SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK |
+				       SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK);
+		if (rc < 0)
+			return rc;
+
+		if (rc) {
+
+			handle->cfg.dma = mode;
+			val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+					   SD4_EMMC_TOP_CTRL_OFFSET);
+			val &= ~(SD4_EMMC_TOP_CTRL_DMASEL_MASK);
+			val |= handle->cfg.dma - 1;
+			mmio_write_32(handle->ctrl.sdRegBaseAddr +
+				      SD4_EMMC_TOP_CTRL_OFFSET, val);
+			return SD_OK;
+		}
+	}
+	handle->cfg.dma = 0;
+
+	return SD_FAIL;
+}
+
+/*
+ * Get current DMA address.
+ * Called only when there is no data transaction activity.
+ */
+uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *sd_handle)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	if (handle->cfg.dma == SD_DMA_OFF)
+		return 0;
+
+	return (uintptr_t)mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				       SD4_EMMC_TOP_SYSADDR_OFFSET);
+}
+
+int32_t chal_sd_send_cmd(CHAL_HANDLE *sd_handle, uint32_t cmd_idx,
+			 uint32_t argument, uint32_t options)
+{
+	uint32_t cmd_mode_reg = 0;
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	EMMC_TRACE("%s %d cmd:%d argReg:%x options:%x\n",
+		   __func__, __LINE__, cmd_idx, argument, options);
+
+	/* Configure the value for command and mode registers */
+	cmd_mode_reg = (cmd_idx << 24) | options;
+
+	/*
+	 * 1. Write block size reg & block count reg,
+	 * this is done in the tx or rx setup
+	 */
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_BLOCK_OFFSET,
+		      handle->ctrl.blkReg);
+
+	/* 2. Write argument reg */
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET,
+		      argument);
+	handle->ctrl.argReg = argument;
+
+	/*
+	 * 3. Write transfer mode reg & command reg, check the DMA bit which is
+	 *    set before this function call if it is selected.
+	 */
+	if (cmd_idx == 24 || cmd_idx == 25 || cmd_idx == 18 || cmd_idx == 17 ||
+	    cmd_idx == 42 || cmd_idx == 51 || cmd_idx == 53)
+		cmd_mode_reg |= ((handle->cfg.dma) ? 1 : 0);
+
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET,
+		      cmd_mode_reg);
+
+	handle->ctrl.cmdIndex = cmd_idx;
+
+	return SD_OK;
+}
+
+int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sd_handle, uintptr_t address)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	if (handle->cfg.dma == SD_DMA_OFF)
+		return SD_FAIL;
+
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET,
+		      address);
+	return SD_OK;
+}
+
+uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq)
+{
+	/*
+	 * Divider control setting represents 1/2 of the actual divider value.
+	 *
+	 * DesiredFreq = BaseClockFreq / (2 * div_ctrl_setting)
+	 *
+	 * ==> div_ctrl_setting = BaseClockFreq / (2 * DesiredFreq)
+	 */
+	uint32_t div_ctrl_setting;
+	uint32_t actual_freq;
+
+	assert(desired_freq != 0);
+
+	/* Special case, 0 = divider of 1. */
+	if (desired_freq >= BASE_CLK_FREQ)
+		return 0;
+
+	/* Normal case, desired_freq < BASE_CLK_FREQ */
+	div_ctrl_setting = BASE_CLK_FREQ / (2 * desired_freq);
+
+	actual_freq = BASE_CLK_FREQ / (2 * div_ctrl_setting);
+
+	if (actual_freq > desired_freq) {
+		/*
+		 * Division does not result in exact freqency match.
+		 * Make sure resulting frequency does not exceed requested freq.
+		 */
+		div_ctrl_setting++;
+	}
+
+	return div_ctrl_setting;
+}
+
+int32_t chal_sd_set_clock(CHAL_HANDLE *sd_handle, uint32_t div_ctrl_setting,
+			  uint32_t on)
+{
+	uint32_t value;
+	struct sd_dev *handle;
+	uint32_t time;
+	uint32_t clk_sel_high_byte = 0xFF & (div_ctrl_setting >> 8);
+	uint32_t clk_sel_low_byte = 0xFF & div_ctrl_setting;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	EMMC_TRACE("set_clock(div_ctrl_setting=%d,on=%d)\n",
+		   div_ctrl_setting, on);
+
+	handle = (struct sd_dev *) sd_handle;
+
+	/* Read control register content. */
+	value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			     SD4_EMMC_TOP_CTRL1_OFFSET);
+
+	/* Disable Clock */
+	value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK);
+
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
+		      value);
+
+	/* Clear bits of interest. */
+	value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK |
+		   SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK);
+
+	/* Set bits of interest to new value. */
+	value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK &
+		  (clk_sel_low_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT));
+	value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK &
+		  (clk_sel_high_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT));
+	value |= SD4_EMMC_TOP_CTRL1_ICLKEN_MASK;
+
+	/* Write updated value back to control register. */
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
+		      value);
+
+	time = 0;
+	do {
+		value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				     SD4_EMMC_TOP_CTRL1_OFFSET);
+
+		if ((value & SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) ==
+				SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK)
+			break;
+
+		mdelay(1);
+	} while (time++ < EMMC_CLOCK_SETTING_TIMEOUT_MS);
+
+	if (time >= EMMC_CLOCK_SETTING_TIMEOUT_MS)
+		WARN("%s %d clock settings timeout happenedi (%dms)\n",
+			 __func__, __LINE__, time);
+
+	VERBOSE("EMMC: clock settings delay: %dms\n", time);
+
+	value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			     SD4_EMMC_TOP_CTRL1_OFFSET);
+
+	if (on)
+		value |= SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK;
+
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
+		      value);
+
+	return SD_OK;
+}
+
+/*
+ * function to setup DMA buffer and data length, calculates block
+ * size and the number of blocks to be transferred and return
+ * the DMA buffer address.
+ */
+int32_t chal_sd_setup_xfer(CHAL_HANDLE *sd_handle,
+			   uint8_t *data, uint32_t length, int32_t dir)
+{
+	uint32_t blocks = 0;
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	if (length <= handle->cfg.blockSize) {
+		handle->ctrl.blkReg = length | handle->cfg.dmaBoundary;
+	} else {
+		blocks = length / handle->cfg.blockSize;
+		handle->ctrl.blkReg = (blocks << 16) | handle->cfg.blockSize |
+					handle->cfg.dmaBoundary;
+	}
+
+	if (handle->cfg.dma != SD_DMA_OFF) {
+		/* For DMA target address setting, physical address should be used */
+		mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET,
+				(uintptr_t)data);
+	}
+
+	return SD_OK;
+}
+
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+/*
+ * function to write one block data directly to the
+ * host controller's FIFO which is 1K uint8_t or
+ * 2K uint8_t in size.
+ * It is used in Non-DMA mode for data transmission.
+ */
+int32_t chal_sd_write_buffer(CHAL_HANDLE *sd_handle, uint32_t length,
+			     uint8_t *data)
+{
+	uint32_t i, leftOver = 0, blockSize, size, value = 0;
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	blockSize = handle->cfg.blockSize;
+
+	if (length == 0)
+		return SD_OK;
+
+	/* PIO mode, push into fifo word by word */
+	if (length >= blockSize) {
+		size = blockSize;
+	} else {
+		size = ((length >> 2) << 2);
+		leftOver = length % 4;
+	}
+
+	for (i = 0; i < size; i += 4) {
+		value = *(uint32_t *)(data + i);
+		mmio_write_32(handle->ctrl.sdRegBaseAddr +
+			      SD4_EMMC_TOP_BUFDAT_OFFSET, value);
+	}
+/*
+ * BUG ALERT:
+ *    This implementation has TWO issues that must be addressed before you
+ *    can safely INCLUDE_EMMC_DRIVER_WRITE_CODE.
+ *
+ *    (1) For the last leftOver bytes, driver writes full word, which means
+ *        some of the eMMC content (i.e. "4 - leftOver" will be erroneously
+ *        overwritten).
+ *    (2) eMMC is a block device. What happens when less than a full block of
+ *        data is submitted???
+ */
+	if (leftOver > 0) {
+		value = ((*(uint32_t *)(data + i)) << (4 - leftOver));
+		mmio_write_32(handle->ctrl.sdRegBaseAddr +
+			      SD4_EMMC_TOP_BUFDAT_OFFSET, value);
+	}
+
+	return SD_OK;
+}
+#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
+
+/*
+ * Function to read maximal one block data directly
+ * from the data port of the host controller (FIFO). It is used
+ * in Non-DMA mode for data transmission.
+ */
+int32_t chal_sd_read_buffer(CHAL_HANDLE *sd_handle, uint32_t length,
+			    uint8_t *data)
+{
+	uint32_t i, size, leftOver, blockSize, value;
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *)sd_handle;
+
+	value = 0;
+
+	blockSize = handle->cfg.blockSize;
+
+	/* PIO mode, extract fifo word by word */
+	if (length >= blockSize) {
+		size = blockSize;
+		leftOver = 0;
+	} else {
+		leftOver = length % 4;
+		size = ((length >> 2) << 2);
+	}
+
+	for (i = 0; i < size; i += 4) {
+		value =
+		    mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				    SD4_EMMC_TOP_BUFDAT_OFFSET);
+		memcpy((void *)(data + i), &value, sizeof(uint32_t));
+	}
+
+	if (leftOver > 0) {
+		value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				     SD4_EMMC_TOP_BUFDAT_OFFSET);
+
+		/*
+		 * Copy remaining non-full word bytes.
+		 * (We run ARM as Little Endian)
+		 */
+		uint8_t j = 0;
+
+		for (j = 0; j < leftOver; j++) {
+			data[i + j] = (value >> (j * 8)) & 0xFF;
+		}
+	}
+
+	return SD_OK;
+}
+
+/*
+ * Resets both DAT or CMD line.
+ */
+int32_t chal_sd_reset_line(CHAL_HANDLE *sd_handle, uint32_t line)
+{
+	uint32_t control, flag;
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	flag = SD4_EMMC_TOP_CTRL1_CMDRST_MASK | SD4_EMMC_TOP_CTRL1_DATRST_MASK;
+
+	if (flag != (line | flag))
+		return SD_FAIL;
+
+	control = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			       SD4_EMMC_TOP_CTRL1_OFFSET);
+	control |= line;
+	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
+		      control);
+
+	/* reset CMD and DATA line should always work, no need to timed out */
+	do {
+		control = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+				       SD4_EMMC_TOP_CTRL1_OFFSET);
+	} while (control & line);
+
+	return SD_OK;
+}
+
+/*
+ * Function to be called once a SD command is done to read
+ * back it's response data.
+ */
+int32_t chal_sd_get_response(CHAL_HANDLE *sd_handle, uint32_t *resp)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+	resp[0] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			       SD4_EMMC_TOP_RESP0_OFFSET);
+	resp[1] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			       SD4_EMMC_TOP_RESP2_OFFSET);
+	resp[2] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			       SD4_EMMC_TOP_RESP4_OFFSET);
+	resp[3] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			       SD4_EMMC_TOP_RESP6_OFFSET);
+
+	return SD_OK;
+}
+
+/*
+ * The function is called to clean all the pending interrupts.
+ */
+int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sd_handle)
+{
+	uint32_t status = SD_OK;
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *)sd_handle;
+
+	/* Make sure clean all interrupts */
+	do {
+		mmio_write_32(handle->ctrl.sdRegBaseAddr +
+			      SD4_EMMC_TOP_INTR_OFFSET, 0xFFFFFFFF);
+		SD_US_DELAY(10);
+	} while (mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			      SD4_EMMC_TOP_INTR_OFFSET));
+
+	return status;
+}
+
+/*
+ * The function returns interrupt status register value.
+ */
+int32_t chal_sd_get_irq_status(CHAL_HANDLE *sd_handle)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	return (mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			     SD4_EMMC_TOP_INTR_OFFSET));
+}
+
+/*
+ * The function clears interrupt(s) specified in the mask.
+ */
+int32_t chal_sd_clear_irq(CHAL_HANDLE *sd_handle, uint32_t mask)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	/* Make sure clean masked interrupts */
+	do {
+		mmio_write_32(handle->ctrl.sdRegBaseAddr +
+			      SD4_EMMC_TOP_INTR_OFFSET, mask);
+		SD_US_DELAY(10);
+	} while (mask &
+		 mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			      SD4_EMMC_TOP_INTR_OFFSET));
+
+	return SD_OK;
+}
+
+/*
+ * Description: The function configures the SD host controller.
+ */
+int32_t chal_sd_config(CHAL_HANDLE *sd_handle, uint32_t speed, uint32_t retry,
+		       uint32_t boundary, uint32_t blkSize, uint32_t dma)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return SD_INVALID_HANDLE;
+
+	handle = (struct sd_dev *) sd_handle;
+
+	handle->cfg.speedMode = speed;
+	handle->cfg.retryLimit = retry;
+	handle->cfg.dmaBoundary = boundary;
+	handle->cfg.blockSize = blkSize;
+
+	chal_sd_set_dma(sd_handle, dma);
+	SD_US_DELAY(100);
+	chal_sd_set_dma_boundary(handle, boundary);
+	SD_US_DELAY(100);
+
+	chal_sd_set_speed(sd_handle, speed);
+
+	SD_US_DELAY(100);
+	return SD_OK;
+}
+
+/*
+ * Cleans up HC FIFO.
+ */
+void chal_sd_dump_fifo(CHAL_HANDLE *sd_handle)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return;
+
+	handle = (struct sd_dev *)sd_handle;
+
+	/* in case there still data in the host buffer */
+	while (mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			    SD4_EMMC_TOP_PSTATE_OFFSET) & 0x800) {
+		mmio_read_32(handle->ctrl.sdRegBaseAddr +
+			     SD4_EMMC_TOP_BUFDAT_OFFSET);
+	};
+}
+
+/*
+ * Enable or disable a SD interrupt signal.
+ */
+void chal_sd_set_irq_signal(CHAL_HANDLE *sd_handle, uint32_t mask,
+			    uint32_t state)
+{
+	struct sd_dev *handle;
+
+	if (sd_handle == NULL)
+		return;
+
+	handle = (struct sd_dev *)sd_handle;
+
+	if (state)
+		mmio_setbits_32(handle->ctrl.sdRegBaseAddr +
+				SD4_EMMC_TOP_INTREN2_OFFSET, mask);
+	else
+		mmio_clrbits_32(handle->ctrl.sdRegBaseAddr +
+				SD4_EMMC_TOP_INTREN2_OFFSET, mask);
+}
diff --git a/drivers/brcm/emmc/emmc_csl_sdcard.c b/drivers/brcm/emmc/emmc_csl_sdcard.c
new file mode 100644
index 0000000..d6ad4bc
--- /dev/null
+++ b/drivers/brcm/emmc/emmc_csl_sdcard.c
@@ -0,0 +1,1087 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+
+#include "bcm_emmc.h"
+#include "emmc_chal_types.h"
+#include "emmc_csl_sdprot.h"
+#include "emmc_chal_sd.h"
+#include "emmc_csl_sdcmd.h"
+#include "emmc_csl_sd.h"
+#include "emmc_pboot_hal_memory_drv.h"
+
+#define SD_CARD_BUSY                    0x80000000
+#define SD_CARD_RETRY_LIMIT             1000
+#define SD_CARD_HIGH_SPEED_PS           13
+#define SD_CHK_HIGH_SPEED_MODE          0x00FFFFF1
+#define SD_SET_HIGH_SPEED_MODE          0x80FFFFF1
+#define SD_MMC_ENABLE_HIGH_SPEED        0x03b90100	//0x03b90103
+#define SD_MMC_8BIT_MODE                0x03b70200
+#define SD_MMC_4BIT_MODE                0x03b70100
+#define SD_MMC_1BIT_MODE                0x03b70000
+
+#define SD_MMC_BOOT_8BIT_MODE           0x03b10200
+#define SD_MMC_BOOT_4BIT_MODE           0x03b10100
+#define SD_MMC_BOOT_1BIT_MODE           0x03b10000
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_CNF   0X03B30000
+
+#ifdef USE_EMMC_FIP_TOC_CACHE
+/*
+ * Cache size mirrors the size of the global eMMC temp buffer
+ * which is used for non-image body reads such as headers, ToC etc.
+ */
+#define CACHE_SIZE           ((EMMC_BLOCK_SIZE) * 2)
+#define PARTITION_BLOCK_ADDR ((PLAT_FIP_ATTEMPT_OFFSET)/(EMMC_BLOCK_SIZE))
+
+static uint32_t cached_partition_block;
+static uint8_t cached_block[CACHE_SIZE];
+#endif
+
+static int set_card_data_width(struct sd_handle *handle, int width);
+static int abort_err(struct sd_handle *handle);
+static int err_recovery(struct sd_handle *handle, uint32_t errors);
+static int xfer_data(struct sd_handle *handle, uint32_t mode, uint32_t addr,
+		     uint32_t length, uint8_t *base);
+
+int set_boot_config(struct sd_handle *handle, uint32_t config)
+{
+	return mmc_cmd6(handle, SDIO_HW_EMMC_EXT_CSD_BOOT_CNF | config);
+}
+
+void process_csd_mmc_speed(struct sd_handle *handle, uint32_t csd_mmc_speed)
+{
+	uint32_t div_ctrl_setting;
+
+	/* CSD field TRAN_SPEED:
+	 * Bits [2:0] 0 = 100 KHz
+	 *            1 = 1 MHz
+	 *            2 = 10 MHz
+	 *            3 = 100 MHz
+	 *            4...7 Reserved.
+	 * Bits [6:3] 0 = Reserved
+	 *            1 = 1.0
+	 *            2 = 1.2
+	 *            3 = 1.3
+	 *            4 = 1.5
+	 *            5 = 2.0
+	 *            6 = 2.6
+	 *            7 = 3.0
+	 *            8 = 3.5
+	 *            9 = 4.0
+	 *            A = 4.5
+	 *            B = 5.2
+	 *            C = 5.5
+	 *            D = 6.0
+	 *            E = 7.0
+	 *            F = 8.0
+	 * For cards supporting version 4.0, 4.1, and 4.2 of the standard,
+	 * the value shall be 20 MHz (0x2A).
+	 * For cards supporting version 4.3 , the value shall be 26 MHz (0x32)
+	 */
+
+	switch (csd_mmc_speed & 0x7F) {
+	case 0x2A:
+		EMMC_TRACE("Speeding up eMMC clock to 20MHz\n");
+		div_ctrl_setting =
+		    chal_sd_freq_2_div_ctrl_setting(20 * 1000 * 1000);
+		break;
+	case 0x32:
+		EMMC_TRACE("Speeding up eMMC clock to 26MHz\n");
+		div_ctrl_setting =
+		    chal_sd_freq_2_div_ctrl_setting(26 * 1000 * 1000);
+		break;
+	default:
+		/* Unknown */
+		return;
+	}
+
+	chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 0);
+
+	chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 1);
+
+	SD_US_DELAY(1000);
+}
+
+
+/*
+ * The function changes SD/SDIO/MMC card data width if
+ * the card support configurable data width. The host controller
+ * and the card has to be in the same bus data width.
+ */
+int set_card_data_width(struct sd_handle *handle, int width)
+{
+	uint32_t data_width = 0;
+	int is_valid_arg = 1;
+	int rc = SD_FAIL;
+	char *bitwidth_str = " ";
+	char *result_str = "failed";
+
+	switch (width) {
+#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
+	case SD_BUS_DATA_WIDTH_8BIT:
+		data_width = SD_MMC_8BIT_MODE;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+		bitwidth_str = "8_BIT";
+#endif
+		break;
+#endif
+	case SD_BUS_DATA_WIDTH_4BIT:
+		data_width = SD_MMC_4BIT_MODE;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+		bitwidth_str = "4_BIT";
+#endif
+		break;
+
+	case SD_BUS_DATA_WIDTH_1BIT:
+		data_width = SD_MMC_1BIT_MODE;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+		bitwidth_str = "1_BIT";
+#endif
+		break;
+
+	default:
+		is_valid_arg = 0;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+		bitwidth_str = "unknown";
+#endif
+		break;
+	}
+
+	if (is_valid_arg) {
+		rc = mmc_cmd6(handle, data_width);
+		if (rc == SD_OK) {
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+			result_str = "succeeded";
+#endif
+			chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
+						 width);
+		} else {
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+			result_str = "failed";
+#endif
+		}
+	} else {
+		rc = SD_FAIL;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+		result_str = "ignored";
+#endif
+	}
+
+	VERBOSE("SDIO Data Width(%s) %s.\n", bitwidth_str, result_str);
+
+	return rc;
+}
+
+
+/*
+ * Error handling routine. Does abort data
+ * transmission if error is found.
+ */
+static int abort_err(struct sd_handle *handle)
+{
+	uint32_t present, options, event, rel = 0;
+	struct sd_resp cmdRsp;
+
+	handle->device->ctrl.argReg = 0;
+	handle->device->ctrl.cmdIndex = SD_CMD_STOP_TRANSMISSION;
+
+	options = (SD_CMD_STOP_TRANSMISSION << 24) |
+		  (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
+
+	chal_sd_send_cmd((CHAL_HANDLE *) handle->device,
+			 handle->device->ctrl.cmdIndex,
+			 handle->device->ctrl.argReg, options);
+
+	event = wait_for_event(handle,
+			       SD4_EMMC_TOP_INTR_CMDDONE_MASK |
+			       SD_ERR_INTERRUPTS,
+			       handle->device->cfg.wfe_retry);
+
+	if (event & SD_CMD_ERROR_INT) {
+		rel = SD_ERROR_NON_RECOVERABLE;
+	} else {
+		if (event & SD_DAT_TIMEOUT) {
+			return SD_ERROR_NON_RECOVERABLE;
+		}
+
+		chal_sd_get_response((CHAL_HANDLE *) handle->device,
+				     (uint32_t *)&cmdRsp);
+
+		process_cmd_response(handle, handle->device->ctrl.cmdIndex,
+				     cmdRsp.data.r2.rsp1, cmdRsp.data.r2.rsp2,
+				     cmdRsp.data.r2.rsp3, cmdRsp.data.r2.rsp4,
+				     &cmdRsp);
+
+		SD_US_DELAY(2000);
+
+		present =
+		    chal_sd_get_present_status((CHAL_HANDLE *) handle->device);
+
+		if ((present & 0x00F00000) == 0x00F00000)
+			rel = SD_ERROR_RECOVERABLE;
+		else
+			rel = SD_ERROR_NON_RECOVERABLE;
+	}
+
+	return rel;
+}
+
+
+/*
+ * The function handles real data transmission on both DMA and
+ * none DMA mode, In None DMA mode the data transfer starts
+ * when the command is sent to the card, data has to be written
+ * into the host contollers buffer at this time one block
+ * at a time.
+ * In DMA mode, the real data transfer is done by the DMA engine
+ * and this functions just waits for the data transfer to complete.
+ *
+ */
+int process_data_xfer(struct sd_handle *handle, uint8_t *buffer, uint32_t addr,
+		      uint32_t length, int dir)
+{
+	if (dir == SD_XFER_HOST_TO_CARD) {
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+		if (handle->device->cfg.dma == SD_DMA_OFF) {
+			/*
+			 * In NON DMA mode, the real data xfer starts from here
+			 */
+			if (write_buffer(handle, length, buffer))
+				return SD_WRITE_ERROR;
+		} else {
+			wait_for_event(handle,
+				       SD4_EMMC_TOP_INTR_TXDONE_MASK |
+				       SD_ERR_INTERRUPTS,
+				       handle->device->cfg.wfe_retry);
+
+			if (handle->device->ctrl.cmdStatus == SD_OK)
+				return SD_OK;
+
+			check_error(handle, handle->device->ctrl.cmdStatus);
+			return SD_WRITE_ERROR;
+		}
+#else
+		return SD_WRITE_ERROR;
+#endif
+	} else {		/* SD_XFER_CARD_TO_HOST */
+
+		if (handle->device->cfg.dma == SD_DMA_OFF) {
+			/* In NON DMA mode, the real data
+			 * transfer starts from here
+			 */
+			if (read_buffer(handle, length, buffer))
+				return SD_READ_ERROR;
+
+		} else {	/* for DMA mode */
+
+			/*
+			 * once the data transmission is done
+			 * copy data to the host buffer.
+			 */
+			wait_for_event(handle,
+				       SD4_EMMC_TOP_INTR_TXDONE_MASK |
+				       SD_ERR_INTERRUPTS,
+				       handle->device->cfg.wfe_retry);
+
+			if (handle->device->ctrl.cmdStatus == SD_OK)
+				return SD_OK;
+
+			check_error(handle, handle->device->ctrl.cmdStatus);
+			return SD_READ_ERROR;
+		}
+	}
+	return SD_OK;
+}
+
+
+/*
+ * The function sets block size for the next SD/SDIO/MMC
+ * card read/write command.
+ */
+int select_blk_sz(struct sd_handle *handle, uint16_t size)
+{
+	return sd_cmd16(handle, size);
+}
+
+
+/*
+ * The function initalizes the SD/SDIO/MMC/CEATA and detects
+ * the card according to the flag of detection.
+ * Once this function is called, the card is put into ready state
+ * so application can do data transfer to and from the card.
+ */
+int init_card(struct sd_handle *handle, int detection)
+{
+	/*
+	 * After Reset, eMMC comes up in 1 Bit Data Width by default.
+	 * Set host side to match.
+	 */
+	chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
+				 SD_BUS_DATA_WIDTH_1BIT);
+
+#ifdef USE_EMMC_FIP_TOC_CACHE
+	cached_partition_block = 0;
+#endif
+	handle->device->ctrl.present = 0; /* init card present to be no card */
+
+	init_mmc_card(handle);
+
+	handle->device->ctrl.present = 1; /* card is detected */
+
+	/* switch the data width back */
+	if (handle->card->type != SD_CARD_MMC)
+		return SD_FAIL;
+
+	/*
+	 * Dynamically set Data Width to highest supported value.
+	 * Try different data width settings (highest to lowest).
+	 * Verify each setting by reading EXT_CSD and comparing
+	 * against the EXT_CSD contents previously read in call to
+	 * init_mmc_card() earlier. Stop at first verified data width
+	 * setting.
+	 */
+	{
+#define EXT_CSD_PROPERTIES_SECTION_START_INDEX	192
+#define EXT_CSD_PROPERTIES_SECTION_END_INDEX	511
+		uint8_t buffer[EXT_CSD_SIZE];
+#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
+		/* Try 8 Bit Data Width */
+		chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
+					 SD_BUS_DATA_WIDTH_8BIT);
+		if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_8BIT)) &&
+		    (!mmc_cmd8(handle, buffer)) &&
+		    (!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX],
+			     &(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]),
+			     EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1)))
+
+			return SD_OK;
+#endif
+		/* Fall back to 4 Bit Data Width */
+		chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
+					 SD_BUS_DATA_WIDTH_4BIT);
+		if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_4BIT)) &&
+		    (!mmc_cmd8(handle, buffer)) &&
+		    (!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX],
+			     &(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]),
+			     EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1)))
+
+			return SD_OK;
+
+		/* Fall back to 1 Bit Data Width */
+		chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
+					 SD_BUS_DATA_WIDTH_1BIT);
+		/* Just use 1 Bit Data Width then. */
+		if (!set_card_data_width(handle, SD_BUS_DATA_WIDTH_1BIT))
+			return SD_OK;
+
+	}
+	return SD_CARD_INIT_ERROR;
+}
+
+
+/*
+ * The function handles MMC/CEATA card initalization.
+ */
+int init_mmc_card(struct sd_handle *handle)
+{
+	uint32_t ocr = 0, newOcr, rc, limit = 0;
+	uint32_t cmd1_option = 0x40300000;
+	uint32_t sec_count;
+
+	handle->card->type = SD_CARD_MMC;
+
+	do {
+		SD_US_DELAY(1000);
+		newOcr = 0;
+		ocr = 0;
+		rc = sd_cmd1(handle, cmd1_option, &newOcr);
+		limit++;
+
+		if (rc == SD_OK)
+			ocr = newOcr;
+
+	} while (((ocr & SD_CARD_BUSY) == 0) && (limit < SD_CARD_RETRY_LIMIT));
+
+	if (limit >= SD_CARD_RETRY_LIMIT) {
+		handle->card->type = SD_CARD_UNKNOWN;
+		EMMC_TRACE("CMD1 Timeout: Device is not ready\n");
+		return SD_CARD_UNKNOWN;
+	}
+
+	/* Save the ocr register */
+	handle->device->ctrl.ocr = ocr;
+
+	/* Ready State */
+	rc = sd_cmd2(handle);
+	if (rc != SD_OK) {
+		handle->card->type = SD_CARD_UNKNOWN;
+		return SD_CARD_UNKNOWN;
+	}
+
+	rc = sd_cmd3(handle);
+	if (rc != SD_OK) {
+		handle->card->type = SD_CARD_UNKNOWN;
+		return SD_CARD_UNKNOWN;
+	}
+	/* read CSD */
+	rc = sd_cmd9(handle, &emmc_global_vars_ptr->cardData);
+	if (rc != SD_OK) {
+		handle->card->type = SD_CARD_UNKNOWN;
+		return SD_CARD_UNKNOWN;
+	}
+
+	/* Increase clock frequency according to what the card advertises */
+	EMMC_TRACE("From CSD...  cardData.csd.mmc.speed = 0x%X\n",
+		   emmc_global_vars_ptr->cardData.csd.mmc.speed);
+	process_csd_mmc_speed(handle,
+			      emmc_global_vars_ptr->cardData.csd.mmc.speed);
+
+	/* goto transfer mode */
+	rc = sd_cmd7(handle, handle->device->ctrl.rca);
+	if (rc != SD_OK) {
+		handle->card->type = SD_CARD_UNKNOWN;
+		return SD_CARD_UNKNOWN;
+	}
+
+	rc = mmc_cmd8(handle, emmc_global_buf_ptr->u.Ext_CSD_storage);
+	if (rc == SD_OK) {
+		/* calcul real capacity */
+		sec_count = emmc_global_buf_ptr->u.Ext_CSD_storage[212] |
+			    emmc_global_buf_ptr->u.Ext_CSD_storage[213] << 8 |
+			    emmc_global_buf_ptr->u.Ext_CSD_storage[214] << 16 |
+			    emmc_global_buf_ptr->u.Ext_CSD_storage[215] << 24;
+
+		EMMC_TRACE("Device density = %ldMBytes\n",
+			   handle->card->size / (1024 * 1024));
+
+		if (sec_count > 0) {
+			handle->card->size = (uint64_t)sec_count * 512;
+
+			EMMC_TRACE("Updated Device density = %ldMBytes\n",
+				   handle->card->size / (1024 * 1024));
+		}
+
+		if (sec_count > (2u * 1024 * 1024 * 1024) / 512) {
+			handle->device->ctrl.ocr |= SD_CARD_HIGH_CAPACITY;
+			handle->device->cfg.blockSize = 512;
+		}
+
+		if (handle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
+			EMMC_TRACE("Sector addressing\n");
+		else
+			EMMC_TRACE("Byte addressing\n");
+
+		EMMC_TRACE("Ext_CSD_storage[162]: 0x%02X  Ext_CSD_storage[179]: 0x%02X\n",
+			   emmc_global_buf_ptr->u.Ext_CSD_storage[162],
+			   emmc_global_buf_ptr->u.Ext_CSD_storage[179]);
+	}
+
+	return handle->card->type;
+}
+
+
+/*
+ * The function send reset command to the card.
+ * The card will be in ready status after the reset.
+ */
+int reset_card(struct sd_handle *handle)
+{
+	int res = SD_OK;
+
+	/* on reset, card's RCA should return to 0 */
+	handle->device->ctrl.rca = 0;
+
+	res = sd_cmd0(handle);
+
+	if (res != SD_OK)
+		return SD_RESET_ERROR;
+
+	return res;
+}
+
+
+/*
+ * The function sends command to the card and starts
+ * data transmission.
+ */
+static int xfer_data(struct sd_handle *handle,
+		     uint32_t mode,
+		     uint32_t addr, uint32_t length, uint8_t *base)
+{
+	int rc = SD_OK;
+
+	VERBOSE("XFER: dest: 0x%llx, addr: 0x%x, size: 0x%x bytes\n",
+		(uint64_t)base, addr, length);
+
+	if ((length / handle->device->cfg.blockSize) > 1) {
+		if (mode == SD_OP_READ) {
+			inv_dcache_range((uintptr_t)base, (uint64_t)length);
+			rc = sd_cmd18(handle, addr, length, base);
+		} else {
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+			flush_dcache_range((uintptr_t)base, (uint64_t)length);
+			rc = sd_cmd25(handle, addr, length, base);
+#else
+			rc = SD_DATA_XFER_ERROR;
+#endif
+		}
+	} else {
+		if (mode == SD_OP_READ) {
+			inv_dcache_range((uintptr_t)base, (uint64_t)length);
+			rc = sd_cmd17(handle, addr,
+				      handle->device->cfg.blockSize, base);
+		} else {
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+			flush_dcache_range((uintptr_t)base, (uint64_t)length);
+			rc = sd_cmd24(handle, addr,
+				      handle->device->cfg.blockSize, base);
+#else
+			rc = SD_DATA_XFER_ERROR;
+#endif
+		}
+	}
+
+	if (rc != SD_OK)
+		return SD_DATA_XFER_ERROR;
+
+	return SD_OK;
+}
+
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks)
+{
+	uint32_t end_addr;
+
+	INFO("ERASE: addr: 0x%x, num of sectors: 0x%x\n", addr, blocks);
+
+	if (sd_cmd35(handle, addr) != SD_OK)
+		return SD_FAIL;
+
+	end_addr = addr + blocks - 1;
+	if (sd_cmd36(handle, end_addr) != SD_OK)
+		return SD_FAIL;
+
+	if (sd_cmd38(handle) != SD_OK)
+		return SD_FAIL;
+
+	return SD_OK;
+}
+#endif
+
+/*
+ * The function reads block data from a card.
+ */
+#ifdef USE_EMMC_FIP_TOC_CACHE
+int read_block(struct sd_handle *handle,
+	       uint8_t *dst, uint32_t addr, uint32_t len)
+{
+	int rel = SD_OK;
+
+	/*
+	 * Avoid doing repeated reads of the partition block
+	 * by caching.
+	 */
+	if (cached_partition_block &&
+	    addr == PARTITION_BLOCK_ADDR &&
+	    len == CACHE_SIZE) {
+		memcpy(dst, cached_block, len);
+	} else {
+		rel = xfer_data(handle, SD_OP_READ, addr, len, dst);
+
+		if (len == CACHE_SIZE && addr == PARTITION_BLOCK_ADDR) {
+			cached_partition_block = 1;
+			memcpy(cached_block, dst, len);
+		}
+	}
+
+	return rel;
+}
+#else
+int read_block(struct sd_handle *handle,
+	       uint8_t *dst, uint32_t addr, uint32_t len)
+{
+	return xfer_data(handle, SD_OP_READ, addr, len, dst);
+}
+#endif
+
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+
+/*
+ * The function writes block data to a card.
+ */
+int write_block(struct sd_handle *handle,
+		uint8_t *src, uint32_t addr, uint32_t len)
+{
+	int rel = SD_OK;
+
+	/*
+	 * Current HC has problem to get response of cmd16 after cmd12,
+	 * the delay is necessary to sure the next cmd16 will not be timed out.
+	 * The delay has to be at least 4 ms.
+	 * The code removed cmd16 and use cmd13 to get card status before
+	 * sending cmd18 or cmd25 to make sure the card is ready and thus
+	 * no need to have delay here.
+	 */
+
+	rel = xfer_data(handle, SD_OP_WRITE, addr, len, src);
+
+	EMMC_TRACE("wr_blk addr:0x%08X src:0x%08X len:0x%08X result:%d\n",
+		   addr, src, len, rel);
+
+	return rel;
+}
+
+
+/*
+ * The function is called to write one block data directly to
+ * a card's data buffer.
+ * it is used in Non-DMA mode for card data transmission.
+ */
+int write_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data)
+{
+	uint32_t rem, blockSize, event;
+	uint8_t *pData = data;
+
+	blockSize = handle->device->cfg.blockSize;
+	rem = length;
+
+	if (rem == 0)
+		return SD_OK;
+
+	while (rem > 0) {
+
+		event = wait_for_event(handle,
+				       SD4_EMMC_TOP_INTR_BWRDY_MASK |
+				       SD_ERR_INTERRUPTS,
+				       handle->device->cfg.wfe_retry);
+
+		if (handle->device->ctrl.cmdStatus) {
+			check_error(handle, handle->device->ctrl.cmdStatus);
+			return SD_WRITE_ERROR;
+		}
+
+		if (rem >= blockSize)
+			chal_sd_write_buffer((CHAL_HANDLE *) handle->device,
+					     blockSize, pData);
+		else
+			chal_sd_write_buffer((CHAL_HANDLE *) handle->device,
+					     rem, pData);
+
+		if (rem > blockSize) {
+			rem -= blockSize;
+			pData += blockSize;
+		} else {
+			pData += rem;
+			rem = 0;
+		}
+	}
+
+	if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) !=
+	    SD4_EMMC_TOP_INTR_TXDONE_MASK) {
+		event = wait_for_event(handle,
+				       SD4_EMMC_TOP_INTR_TXDONE_MASK |
+				       SD_ERR_INTERRUPTS,
+				       handle->device->cfg.wfe_retry);
+
+		if (handle->device->ctrl.cmdStatus != SD_OK) {
+			check_error(handle, handle->device->ctrl.cmdStatus);
+			return SD_WRITE_ERROR;
+		}
+	} else {
+		handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK;
+	}
+
+	return SD_OK;
+}
+#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
+
+
+/*
+ * The function is called to read maximal one block data
+ * directly from a card
+ * It is used in Non-DMA mode for card data transmission.
+ */
+int read_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data)
+{
+	uint32_t rem, blockSize, event = 0;
+	uint8_t *pData = data;
+
+	blockSize = handle->device->cfg.blockSize;
+	rem = length;
+
+	if (rem == 0)
+		return SD_OK;
+
+	while (rem > 0) {
+		event = wait_for_event(handle,
+				       SD4_EMMC_TOP_INTR_BRRDY_MASK |
+				       SD_ERR_INTERRUPTS,
+				       handle->device->cfg.wfe_retry);
+
+		if (handle->device->ctrl.cmdStatus) {
+			check_error(handle, handle->device->ctrl.cmdStatus);
+			return SD_READ_ERROR;
+		}
+
+		if (rem >= blockSize)
+			chal_sd_read_buffer((CHAL_HANDLE *) handle->device,
+					    blockSize, pData);
+		else
+			chal_sd_read_buffer((CHAL_HANDLE *) handle->device, rem,
+					    pData);
+
+		if (rem > blockSize) {
+			rem -= blockSize;
+			pData += blockSize;
+		} else {
+			pData += rem;
+			rem = 0;
+		}
+	}
+
+	/* In case, there are extra data in the SD FIFO, just dump them. */
+	chal_sd_dump_fifo((CHAL_HANDLE *) handle->device);
+
+	if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) !=
+	    SD4_EMMC_TOP_INTR_TXDONE_MASK) {
+		event = wait_for_event(handle, SD4_EMMC_TOP_INTR_TXDONE_MASK,
+				       handle->device->cfg.wfe_retry);
+
+		if (handle->device->ctrl.cmdStatus) {
+			check_error(handle, handle->device->ctrl.cmdStatus);
+			return SD_READ_ERROR;
+		}
+	} else {
+		handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK;
+	}
+
+	return SD_OK;
+}
+
+
+/*
+ * Error handling routine.
+ * The function just reset the DAT
+ * and CMD line if an error occures during data transmission.
+ */
+int check_error(struct sd_handle *handle, uint32_t ints)
+{
+	uint32_t rel;
+
+	chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
+			       SD_ERR_INTERRUPTS, 0);
+
+	if (ints & SD4_EMMC_TOP_INTR_CMDERROR_MASK) {
+
+		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
+				   SD4_EMMC_TOP_CTRL1_CMDRST_MASK);
+		rel = abort_err(handle);
+
+		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
+				   SD4_EMMC_TOP_CTRL1_DATRST_MASK);
+		chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
+				       SD_ERR_INTERRUPTS, 1);
+
+		return (rel == SD_ERROR_NON_RECOVERABLE) ?
+				SD_ERROR_NON_RECOVERABLE : SD_ERROR_RECOVERABLE;
+	} else {
+		rel = err_recovery(handle, ints);
+	}
+
+	chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
+			       SD_ERR_INTERRUPTS, 1);
+
+	return rel;
+}
+
+
+/*
+ * Error recovery routine.
+ * Try to recover from the error.
+ */
+static int err_recovery(struct sd_handle *handle, uint32_t errors)
+{
+	uint32_t rel = 0;
+
+	/*
+	 * In case of timeout error, the cmd line and data line maybe
+	 * still active or stuck at atcitve so it is needed to reset
+	 * either data line or cmd line to make sure a new cmd can be sent.
+	 */
+
+	if (errors & SD_CMD_ERROR_INT)
+		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
+				   SD4_EMMC_TOP_CTRL1_CMDRST_MASK);
+
+	if (errors & SD_DAT_ERROR_INT)
+		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
+				   SD4_EMMC_TOP_CTRL1_DATRST_MASK);
+
+	/* Abort transaction by sending out stop command */
+	if ((handle->device->ctrl.cmdIndex == 18) ||
+	    (handle->device->ctrl.cmdIndex == 25))
+		rel = abort_err(handle);
+
+	return rel;
+}
+
+
+/*
+ * The function is called to read one block data directly from a card.
+ * It is used in Non-DMA mode for card data transmission.
+ */
+int process_cmd_response(struct sd_handle *handle,
+			 uint32_t cmdIndex,
+			 uint32_t rsp0,
+			 uint32_t rsp1,
+			 uint32_t rsp2, uint32_t rsp3, struct sd_resp *resp)
+{
+	int result = SD_OK;
+
+	/* R6 */
+	uint32_t rca = (rsp0 >> 16) & 0xffff;
+	uint32_t cardStatus = rsp0;
+
+	/* R4 */
+	uint32_t cBit = (rsp0 >> 31) & 0x1;
+	uint32_t funcs = (rsp0 >> 28) & 0x7;
+	uint32_t memPresent = (rsp0 >> 27) & 0x1;
+
+	resp->r1 = 0x3f;
+	resp->cardStatus = cardStatus;
+
+	if (cmdIndex == SD_CMD_IO_SEND_OP_COND) {
+		resp->data.r4.cardReady = cBit;
+		resp->data.r4.funcs = funcs;
+		resp->data.r4.memPresent = memPresent;
+		resp->data.r4.ocr = cardStatus;
+	}
+
+	if (cmdIndex == SD_CMD_MMC_SET_RCA) {
+		resp->data.r6.rca = rca;
+		resp->data.r6.cardStatus = cardStatus & 0xFFFF;
+	}
+
+	if (cmdIndex == SD_CMD_SELECT_DESELECT_CARD) {
+		resp->data.r7.rca = rca;
+	}
+
+	if (cmdIndex == SD_CMD_IO_RW_DIRECT) {
+		if (((rsp0 >> 16) & 0xffff) != 0)
+			result = SD_CMD_ERR_INVALID_RESPONSE;
+
+		resp->data.r5.data = rsp0 & 0xff;
+	}
+
+	if (cmdIndex == SD_CMD_IO_RW_EXTENDED) {
+		if (((rsp0 >> 16) & 0xffff) != 0)
+			result = SD_CMD_ERR_INVALID_RESPONSE;
+
+		resp->data.r5.data = rsp0 & 0xff;
+	}
+
+	if (cmdIndex == SD_ACMD_SD_SEND_OP_COND ||
+	    cmdIndex == SD_CMD_SEND_OPCOND)
+		resp->data.r3.ocr = cardStatus;
+
+	if (cmdIndex == SD_CMD_SEND_CSD ||
+	    cmdIndex == SD_CMD_SEND_CID ||
+	    cmdIndex == SD_CMD_ALL_SEND_CID) {
+		resp->data.r2.rsp4 = rsp3;
+		resp->data.r2.rsp3 = rsp2;
+		resp->data.r2.rsp2 = rsp1;
+		resp->data.r2.rsp1 = rsp0;
+	}
+
+	if ((cmdIndex == SD_CMD_READ_EXT_CSD) &&
+	    (handle->card->type == SD_CARD_SD)) {
+		if ((resp->cardStatus & 0xAA) != 0xAA) {
+			result = SD_CMD_ERR_INVALID_RESPONSE;
+		}
+	}
+
+	return result;
+}
+
+
+/*
+ * The function sets DMA buffer and data length, process
+ * block size and the number of blocks to be transferred.
+ * It returns the DMA buffer address.
+ * It copies dma data from user buffer to the DMA buffer
+ * if the operation is to write data to the SD card.
+ */
+void data_xfer_setup(struct sd_handle *handle, uint8_t *data, uint32_t length,
+		     int dir)
+{
+	chal_sd_setup_xfer((CHAL_HANDLE *)handle->device, data, length, dir);
+}
+
+
+/*
+ * The function does soft reset the host SD controller. After
+ * the function call all host controller's register are reset
+ * to default vallue;
+ *
+ * Note    This function only resets the host controller it does not
+ *          reset the controller's handler.
+ */
+int reset_host_ctrl(struct sd_handle *handle)
+{
+	chal_sd_stop();
+
+	return SD_OK;
+}
+
+static void pstate_log(struct sd_handle *handle)
+{
+	ERROR("PSTATE: 0x%x\n", mmio_read_32
+		(handle->device->ctrl.sdRegBaseAddr +
+			SD4_EMMC_TOP_PSTATE_SD4_OFFSET));
+	ERROR("ERRSTAT: 0x%x\n", mmio_read_32
+		(handle->device->ctrl.sdRegBaseAddr +
+			SD4_EMMC_TOP_ERRSTAT_OFFSET));
+}
+
+/*
+ * The function waits for one or a group of interrupts specified
+ * by mask. The function returns if any one the interrupt status
+ * is set. If interrupt mode is not enabled then it will poll
+ * the interrupt status register until a interrupt status is set
+ * an error interrupt happens. If interrupt mode is enabled then
+ * this function should be called after the interrupt
+ * is received by ISR routine.
+ */
+uint32_t wait_for_event(struct sd_handle *handle,
+			uint32_t mask, uint32_t retry)
+{
+	uint32_t regval, cmd12, time = 0;
+
+	handle->device->ctrl.cmdStatus = 0;	/* no error */
+	EMMC_TRACE("%s %d mask:0x%x timeout:%d irq_status:0x%x\n",
+		   __func__, __LINE__, mask, retry,
+		   chal_sd_get_irq_status((CHAL_HANDLE *)handle->device));
+
+	/* Polling mode */
+	do {
+		regval = chal_sd_get_irq_status((CHAL_HANDLE *)handle->device);
+
+		if (regval & SD4_EMMC_TOP_INTR_DMAIRQ_MASK) {
+			chal_sd_set_dma_addr((CHAL_HANDLE *)handle->device,
+					(uintptr_t)
+				chal_sd_get_dma_addr((CHAL_HANDLE *)
+						handle->device));
+			chal_sd_clear_irq((CHAL_HANDLE *)handle->device,
+					  SD4_EMMC_TOP_INTR_DMAIRQ_MASK);
+		}
+
+		if (time++ > retry) {
+			ERROR("EMMC: No response (cmd%d) after %dus.\n",
+			      handle->device->ctrl.cmdIndex,
+			      time * EMMC_WFE_RETRY_DELAY_US);
+			handle->device->ctrl.cmdStatus = SD_CMD_MISSING;
+			pstate_log(handle);
+			ERROR("EMMC: INT[0x%x]\n", regval);
+			break;
+		}
+
+		if (regval & SD4_EMMC_TOP_INTR_CTOERR_MASK) {
+			ERROR("EMMC: Cmd%d timeout INT[0x%x]\n",
+			      handle->device->ctrl.cmdIndex, regval);
+			handle->device->ctrl.cmdStatus =
+			    SD4_EMMC_TOP_INTR_CTOERR_MASK;
+			pstate_log(handle);
+			break;
+		}
+		if (regval & SD_CMD_ERROR_FLAGS) {
+			ERROR("EMMC: Cmd%d error INT[0x%x]\n",
+			      handle->device->ctrl.cmdIndex, regval);
+			handle->device->ctrl.cmdStatus = SD_CMD_ERROR_FLAGS;
+			pstate_log(handle);
+			break;
+		}
+
+		cmd12 = chal_sd_get_atuo12_error((CHAL_HANDLE *)handle->device);
+		if (cmd12) {
+			ERROR("EMMC: Cmd%d auto cmd12 err:0x%x\n",
+			      handle->device->ctrl.cmdIndex, cmd12);
+			handle->device->ctrl.cmdStatus = cmd12;
+			pstate_log(handle);
+			break;
+		}
+
+		if (SD_DATA_ERROR_FLAGS & regval) {
+			ERROR("EMMC: Data for cmd%d error, INT[0x%x]\n",
+			      handle->device->ctrl.cmdIndex, regval);
+			handle->device->ctrl.cmdStatus =
+			    (SD_DATA_ERROR_FLAGS & regval);
+			pstate_log(handle);
+			break;
+		}
+
+		if ((regval & mask) == 0)
+			udelay(EMMC_WFE_RETRY_DELAY_US);
+
+	} while ((regval & mask) == 0);
+
+	/* clear the interrupt since it is processed */
+	chal_sd_clear_irq((CHAL_HANDLE *)handle->device, (regval & mask));
+
+	return (regval & mask);
+}
+
+int32_t set_config(struct sd_handle *handle, uint32_t speed, uint32_t retry,
+		    uint32_t dma, uint32_t dmaBound, uint32_t blkSize,
+		    uint32_t wfe_retry)
+{
+	int32_t rel = 0;
+
+	if (handle == NULL)
+		return SD_FAIL;
+
+	handle->device->cfg.wfe_retry = wfe_retry;
+
+	rel = chal_sd_config((CHAL_HANDLE *)handle->device, speed, retry,
+			     dmaBound, blkSize, dma);
+	return rel;
+
+}
+
+int mmc_cmd1(struct sd_handle *handle)
+{
+	uint32_t newOcr, res;
+	uint32_t cmd1_option = MMC_OCR_OP_VOLT | MMC_OCR_SECTOR_ACCESS_MODE;
+
+	/*
+	 * After Reset, eMMC comes up in 1 Bit Data Width by default.
+	 * Set host side to match.
+	 */
+	chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
+				 SD_BUS_DATA_WIDTH_1BIT);
+
+#ifdef USE_EMMC_FIP_TOC_CACHE
+	cached_partition_block = 0;
+#endif
+	handle->device->ctrl.present = 0; /* init card present to be no card */
+
+	handle->card->type = SD_CARD_MMC;
+
+	res = sd_cmd1(handle, cmd1_option, &newOcr);
+
+	if (res != SD_OK) {
+		EMMC_TRACE("CMD1 Timeout: Device is not ready\n");
+		res = SD_CARD_UNKNOWN;
+	}
+	return res;
+}
diff --git a/drivers/brcm/emmc/emmc_csl_sdcmd.c b/drivers/brcm/emmc/emmc_csl_sdcmd.c
new file mode 100644
index 0000000..c62886c
--- /dev/null
+++ b/drivers/brcm/emmc/emmc_csl_sdcmd.c
@@ -0,0 +1,842 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+
+#include "bcm_emmc.h"
+#include "emmc_chal_types.h"
+#include "emmc_chal_sd.h"
+#include "emmc_csl_sdprot.h"
+#include "emmc_csl_sdcmd.h"
+#include "emmc_csl_sd.h"
+#include "emmc_chal_sd.h"
+#include "emmc_pboot_hal_memory_drv.h"
+
+int sd_cmd0(struct sd_handle *handle)
+{
+	int res;
+	uint32_t argument = 0x0; /* Go to IDLE state. */
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_GO_IDLE_STATE, argument, 0, NULL);
+
+	if (res == SD_OK) {
+		/* Clear all other interrupts */
+		chal_sd_clear_irq((void *)handle->device, 0xffffffff);
+	}
+
+	return res;
+}
+
+int sd_cmd1(struct sd_handle *handle, uint32_t ocr, uint32_t *ocr_output)
+{
+	int res;
+	uint32_t options;
+	struct sd_resp resp;
+
+	options = SD_CMDR_RSP_TYPE_R3_4 << SD_CMDR_RSP_TYPE_S;
+
+	if (ocr_output == NULL) {
+		EMMC_TRACE("Invalid args\n");
+		return SD_FAIL;
+	}
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_SEND_OPCOND, ocr, options, &resp);
+
+	if (res == SD_OK)
+		*ocr_output = resp.data.r3.ocr;
+
+	return res;
+}
+
+int sd_cmd2(struct sd_handle *handle)
+{
+	uint32_t options;
+	struct sd_resp resp;
+
+	/* send cmd and parse result */
+	options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S;
+
+	return send_cmd(handle, SD_CMD_ALL_SEND_CID, 0, options, &resp);
+}
+
+int sd_cmd3(struct sd_handle *handle)
+{
+	int res;
+	uint32_t options = 0;
+	uint32_t argument;
+	struct sd_resp resp;
+
+	/* use non zero and non 0x1 value for rca */
+	handle->device->ctrl.rca = 0x5;
+	argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_MMC_SET_RCA, argument, options, &resp);
+
+	if (res != SD_OK)
+		handle->device->ctrl.rca = 0;
+
+	return res;
+}
+
+int sd_cmd7(struct sd_handle *handle, uint32_t rca)
+{
+	int res;
+	uint32_t argument, options;
+	struct sd_resp resp;
+
+	argument = (rca << SD_CMD7_ARG_RCA_SHIFT);
+
+	/*
+	 * Response to CMD7 is:
+	 * R1 while selectiing from Stand-By State to Transfer State
+	 * R1b while selecting from Disconnected State to Programming State.
+	 *
+	 * In this driver, we only issue a CMD7 once, to go to transfer mode
+	 * during init_mmc_card().
+	 */
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_SELECT_DESELECT_CARD, argument, options,
+		       &resp);
+
+	if (res == SD_OK)
+		/* Clear all other interrupts */
+		chal_sd_clear_irq((void *)handle->device, 0xffffffff);
+
+	return res;
+}
+
+
+/*
+ * CMD8 Get CSD_EXT
+ */
+int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg)
+{
+	uint32_t res, options;
+	struct sd_resp resp;
+
+	data_xfer_setup(handle, extCsdReg, CEATA_EXT_CSDBLOCK_SIZE,
+			    SD_XFER_CARD_TO_HOST);
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_READ_EXT_CSD, 0, options, &resp);
+
+	if (res == SD_OK)
+		res = process_data_xfer(handle, extCsdReg, 0,
+					CEATA_EXT_CSDBLOCK_SIZE,
+					SD_XFER_CARD_TO_HOST);
+
+	return res;
+}
+
+int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card)
+{
+	int res;
+	uint32_t argument, options, iBlkNum, multiFactor = 1;
+	uint32_t maxReadBlockLen = 1, maxWriteBlockLen = 1;
+	struct sd_resp resp;
+
+	argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
+
+	options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_SEND_CSD, argument, options, &resp);
+
+	if (res != SD_OK)
+		return res;
+
+	if (handle->card->type == SD_CARD_MMC) {
+		card->csd.mmc.structure = (resp.data.r2.rsp4 >> 22) & 0x3;
+		card->csd.mmc.csdSpecVer = (resp.data.r2.rsp4 >> 18) & 0x0f;
+		card->csd.mmc.taac = (resp.data.r2.rsp4 >> 8) & 0xff;
+		card->csd.mmc.nsac = resp.data.r2.rsp4 & 0xff;
+		card->csd.mmc.speed = resp.data.r2.rsp3 >> 24;
+		card->csd.mmc.classes = (resp.data.r2.rsp3 >> 12) & 0xfff;
+		card->csd.mmc.rdBlkLen = (resp.data.r2.rsp3 >> 8) & 0xf;
+		card->csd.mmc.rdBlkPartial = (resp.data.r2.rsp3 >> 7) & 0x01;
+		card->csd.mmc.wrBlkMisalign = (resp.data.r2.rsp3 >> 6) & 0x1;
+		card->csd.mmc.rdBlkMisalign = (resp.data.r2.rsp3 >> 5) & 0x1;
+		card->csd.mmc.dsr = (resp.data.r2.rsp2 >> 4) & 0x01;
+		card->csd.mmc.size =
+		    ((resp.data.r2.rsp3 & 0x3) << 10) +
+		    ((resp.data.r2.rsp2 >> 22) & 0x3ff);
+		card->csd.mmc.vddRdCurrMin = (resp.data.r2.rsp2 >> 19) & 0x7;
+		card->csd.mmc.vddRdCurrMax = (resp.data.r2.rsp2 >> 16) & 0x7;
+		card->csd.mmc.vddWrCurrMin = (resp.data.r2.rsp2 >> 13) & 0x7;
+		card->csd.mmc.vddWrCurrMax = (resp.data.r2.rsp2 >> 10) & 0x7;
+		card->csd.mmc.devSizeMulti = (resp.data.r2.rsp2 >> 7) & 0x7;
+		card->csd.mmc.eraseGrpSize = (resp.data.r2.rsp2 >> 2) & 0x1f;
+		card->csd.mmc.eraseGrpSizeMulti =
+		    ((resp.data.r2.rsp2 & 0x3) << 3) +
+		    ((resp.data.r2.rsp1 >> 29) & 0x7);
+		card->csd.mmc.wrProtGroupSize =
+		    ((resp.data.r2.rsp1 >> 24) & 0x1f);
+		card->csd.mmc.wrProtGroupEnable =
+		    (resp.data.r2.rsp1 >> 23) & 0x1;
+		card->csd.mmc.manuDefEcc = (resp.data.r2.rsp1 >> 21) & 0x3;
+		card->csd.mmc.wrSpeedFactor = (resp.data.r2.rsp1 >> 18) & 0x7;
+		card->csd.mmc.wrBlkLen = (resp.data.r2.rsp1 >> 14) & 0xf;
+		card->csd.mmc.wrBlkPartial = (resp.data.r2.rsp1 >> 13) & 0x1;
+		card->csd.mmc.protAppl = (resp.data.r2.rsp1 >> 8) & 0x1;
+		card->csd.mmc.copyFlag = (resp.data.r2.rsp1 >> 7) & 0x1;
+		card->csd.mmc.permWrProt = (resp.data.r2.rsp1 >> 6) & 0x1;
+		card->csd.mmc.tmpWrProt = (resp.data.r2.rsp1 >> 5) & 0x1;
+		card->csd.mmc.fileFormat = (resp.data.r2.rsp1 >> 4) & 0x03;
+		card->csd.mmc.eccCode = resp.data.r2.rsp1 & 0x03;
+		maxReadBlockLen <<= card->csd.mmc.rdBlkLen;
+		maxWriteBlockLen <<= card->csd.mmc.wrBlkLen;
+
+		iBlkNum = card->csd.mmc.size + 1;
+		multiFactor = (1 << (card->csd.mmc.devSizeMulti + 2));
+
+		handle->card->size =
+		    iBlkNum * multiFactor * (1 << card->csd.mmc.rdBlkLen);
+	}
+
+	handle->card->maxRdBlkLen = maxReadBlockLen;
+	handle->card->maxWtBlkLen = maxWriteBlockLen;
+
+	if (handle->card->size < 0xA00000) {
+		/*
+		 * 10MB Too small size mean, cmd9 response is wrong,
+		 * Use default value 1G
+		 */
+		handle->card->size = 0x40000000;
+		handle->card->maxRdBlkLen = 512;
+		handle->card->maxWtBlkLen = 512;
+	}
+
+	if ((handle->card->maxRdBlkLen > 512) ||
+	    (handle->card->maxWtBlkLen > 512)) {
+		handle->card->maxRdBlkLen = 512;
+		handle->card->maxWtBlkLen = 512;
+	} else if ((handle->card->maxRdBlkLen == 0) ||
+		   (handle->card->maxWtBlkLen == 0)) {
+		handle->card->maxRdBlkLen = 512;
+		handle->card->maxWtBlkLen = 512;
+	}
+
+	handle->device->cfg.blockSize = handle->card->maxRdBlkLen;
+
+	return res;
+}
+
+int sd_cmd13(struct sd_handle *handle, uint32_t *status)
+{
+	int res;
+	uint32_t argument, options;
+	struct sd_resp resp;
+
+	argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_SEND_STATUS, argument, options, &resp);
+
+	if (res == SD_OK) {
+		*status = resp.cardStatus;
+	}
+
+	return res;
+}
+
+int sd_cmd16(struct sd_handle *handle, uint32_t length)
+{
+	int res;
+	uint32_t argument, options, ntry;
+	struct sd_resp resp;
+
+	argument = length;
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
+
+	ntry = 0;
+	do {
+		res = sd_cmd13(handle, &resp.cardStatus);
+		if (res != SD_OK) {
+			EMMC_TRACE(
+				"cmd13 failed before cmd16: rca 0x%0x, return %d, response 0x%0x\n",
+				handle->device->ctrl.rca, res, resp.cardStatus);
+			return res;
+		}
+
+		if (resp.cardStatus & 0x100)
+			break;
+
+		EMMC_TRACE("cmd13 rsp:0x%08x before cmd16\n", resp.cardStatus);
+
+		if (ntry > handle->device->cfg.retryLimit) {
+			EMMC_TRACE("cmd13 retry reach limit %d\n",
+				   handle->device->cfg.retryLimit);
+			return SD_CMD_TIMEOUT;
+		}
+
+		ntry++;
+		EMMC_TRACE("cmd13 retry %d\n", ntry);
+
+		SD_US_DELAY(1000);
+
+	} while (1);
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_SET_BLOCKLEN, argument, options, &resp);
+
+	return res;
+}
+
+int sd_cmd17(struct sd_handle *handle,
+	     uint32_t addr, uint32_t len, uint8_t *buffer)
+{
+	int res;
+	uint32_t argument, options, ntry;
+	struct sd_resp resp;
+
+	ntry = 0;
+	do {
+		res = sd_cmd13(handle, &resp.cardStatus);
+		if (res != SD_OK) {
+			EMMC_TRACE(
+				"cmd 13 failed before cmd17: rca 0x%0x, return %d, response 0x%0x\n",
+				handle->device->ctrl.rca, res, resp.cardStatus);
+			return res;
+		}
+
+		if (resp.cardStatus & 0x100)
+			break;
+
+		EMMC_TRACE("cmd13 rsp:0x%08x before cmd17\n", resp.cardStatus);
+
+		if (ntry > handle->device->cfg.retryLimit) {
+			EMMC_TRACE("cmd13 retry reach limit %d\n",
+				   handle->device->cfg.retryLimit);
+			return SD_CMD_TIMEOUT;
+		}
+
+		ntry++;
+		EMMC_TRACE("cmd13 retry %d\n", ntry);
+
+		SD_US_DELAY(1000);
+
+	} while (1);
+
+	data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST);
+
+	/* send cmd and parse result */
+	argument = addr;
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
+
+	res = send_cmd(handle, SD_CMD_READ_SINGLE_BLOCK, argument, options,
+		       &resp);
+
+	if (res != SD_OK)
+		return res;
+
+	res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST);
+
+	return res;
+}
+
+int sd_cmd18(struct sd_handle *handle,
+	     uint32_t addr, uint32_t len, uint8_t *buffer)
+{
+	int res;
+	uint32_t argument, options, ntry;
+	struct sd_resp resp;
+
+	ntry = 0;
+	do {
+		res = sd_cmd13(handle, &resp.cardStatus);
+		if (res != SD_OK) {
+			EMMC_TRACE(
+				"cmd 13 failed before cmd18: rca 0x%0x, return %d, response 0x%0x\n",
+				handle->device->ctrl.rca, res, resp.cardStatus);
+			return res;
+		}
+
+		if (resp.cardStatus & 0x100)
+			break;
+
+		EMMC_TRACE("cmd13 rsp:0x%08x before cmd18\n", resp.cardStatus);
+
+		if (ntry > handle->device->cfg.retryLimit) {
+			EMMC_TRACE("cmd13 retry reach limit %d\n",
+				   handle->device->cfg.retryLimit);
+			return SD_CMD_TIMEOUT;
+		}
+
+		ntry++;
+		EMMC_TRACE("cmd13 retry %d\n", ntry);
+
+		SD_US_DELAY(1000);
+	} while (1);
+
+	data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST);
+
+	argument = addr;
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
+		  SD4_EMMC_TOP_CMD_MSBS_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
+		  SD4_EMMC_TOP_CMD_BCEN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK |
+		  BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT);
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_READ_MULTIPLE_BLOCK, argument, options,
+		       &resp);
+
+	if (res != SD_OK)
+		return res;
+
+	res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST);
+
+	return res;
+}
+
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+static int card_sts_resp(struct sd_handle *handle, uint32_t *status)
+{
+	int res;
+	uint32_t ntry = 0;
+
+	do {
+		res = sd_cmd13(handle, status);
+		if (res != SD_OK) {
+			EMMC_TRACE(
+				"cmd 13 failed before cmd35: rca 0x%0x, return %d\n",
+				handle->device->ctrl.rca, res);
+			return res;
+		}
+
+		if (*status & 0x100)
+			break;
+
+		EMMC_TRACE("cmd13 rsp:0x%08x before cmd35\n", resp.cardStatus);
+
+		if (ntry > handle->device->cfg.retryLimit) {
+			EMMC_TRACE("cmd13 retry reach limit %d\n",
+				   handle->device->cfg.retryLimit);
+			return SD_CMD_TIMEOUT;
+		}
+
+		ntry++;
+		EMMC_TRACE("cmd13 retry %d\n", ntry);
+
+		SD_US_DELAY(1000);
+	} while (1);
+
+	return SD_OK;
+}
+
+int sd_cmd35(struct sd_handle *handle, uint32_t start)
+{
+	int res;
+	uint32_t argument, options;
+	struct sd_resp resp;
+
+	res = card_sts_resp(handle, &resp.cardStatus);
+	if (res != SD_OK)
+		return res;
+
+	argument = start;
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_ERASE_GROUP_START,
+		       argument, options, &resp);
+
+	if (res != SD_OK)
+		return res;
+
+	return res;
+}
+
+int sd_cmd36(struct sd_handle *handle, uint32_t end)
+{
+	int res;
+	uint32_t argument, options;
+	struct sd_resp resp;
+
+	res = card_sts_resp(handle, &resp.cardStatus);
+	if (res != SD_OK)
+		return res;
+
+	argument = end;
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_ERASE_GROUP_END,
+		       argument, options, &resp);
+
+	if (res != SD_OK)
+		return res;
+
+	return res;
+}
+
+int sd_cmd38(struct sd_handle *handle)
+{
+	int res;
+	uint32_t argument, options;
+	struct sd_resp resp;
+
+	res = card_sts_resp(handle, &resp.cardStatus);
+	if (res != SD_OK)
+		return res;
+
+	argument = 0;
+
+	options = (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_ERASE, argument, options, &resp);
+
+	if (res != SD_OK)
+		return res;
+
+	return res;
+}
+#endif
+
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+
+int sd_cmd24(struct sd_handle *handle,
+	     uint32_t addr, uint32_t len, uint8_t *buffer)
+{
+	int res;
+	uint32_t argument, options, ntry;
+	struct sd_resp resp;
+
+	ntry = 0;
+	do {
+		res = sd_cmd13(handle, &resp.cardStatus);
+		if (res != SD_OK) {
+			EMMC_TRACE(
+				"cmd 13 failed before cmd24: rca 0x%0x, return %d, response 0x%0x\n",
+				handle->device->ctrl.rca, res, &resp.cardStatus);
+			return res;
+		}
+
+		if (resp.cardStatus & 0x100)
+			break;
+
+		EMMC_TRACE("cmd13 rsp:0x%08x before cmd24\n", resp.cardStatus);
+
+		if (ntry > handle->device->cfg.retryLimit) {
+			EMMC_TRACE("cmd13 retry reach limit %d\n",
+				   handle->device->cfg.retryLimit);
+			return SD_CMD_TIMEOUT;
+		}
+
+		ntry++;
+		EMMC_TRACE("cmd13 retry %d\n", ntry);
+
+		SD_US_DELAY(1000);
+
+	} while (1);
+
+	data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD);
+
+	argument = addr;
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_WRITE_BLOCK, argument, options, &resp);
+
+	if (res != SD_OK)
+		return res;
+
+	res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD);
+
+	return res;
+}
+
+int sd_cmd25(struct sd_handle *handle,
+	     uint32_t addr, uint32_t len, uint8_t *buffer)
+{
+	int res = SD_OK;
+	uint32_t argument, options, ntry;
+	struct sd_resp resp;
+
+	ntry = 0;
+	do {
+		res = sd_cmd13(handle, &resp.cardStatus);
+		if (res != SD_OK) {
+			EMMC_TRACE(
+				"cmd 13 failed before cmd25: rca 0x%0x, return %d, response 0x%0x\n",
+				handle->device->ctrl.rca, res, &resp.cardStatus);
+			return res;
+		}
+
+		if (resp.cardStatus & 0x100)
+			break;
+
+		EMMC_TRACE("cmd13 rsp:0x%08x before cmd25\n", resp.cardStatus);
+
+		if (ntry > handle->device->cfg.retryLimit) {
+			EMMC_TRACE("cmd13 retry reach limit %d\n",
+				   handle->device->cfg.retryLimit);
+			return SD_CMD_TIMEOUT;
+		}
+
+		ntry++;
+		EMMC_TRACE("cmd13 retry %d\n", ntry);
+
+		SD_US_DELAY(1000);
+	} while (1);
+
+	data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD);
+
+	argument = addr;
+
+	options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_MSBS_MASK |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_BCEN_MASK |
+		  SD4_EMMC_TOP_CMD_CRC_EN_MASK |
+		  BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT);
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_CMD_WRITE_MULTIPLE_BLOCK,
+		       argument, options, &resp);
+
+	if (res != SD_OK)
+		return res;
+
+	res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD);
+
+	return res;
+}
+#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
+
+int mmc_cmd6(struct sd_handle *handle, uint32_t argument)
+{
+	int res;
+	uint32_t options;
+	struct sd_resp resp;
+
+	options = SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S |
+		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK;
+
+	EMMC_TRACE("Sending CMD6 with argument 0x%X\n", argument);
+
+	/* send cmd and parse result */
+	res = send_cmd(handle, SD_ACMD_SET_BUS_WIDTH, argument, options, &resp);
+
+	/*
+	 * For R1b type response:
+	 * controller issues a COMMAND COMPLETE interrupt when the R1
+	 * response is received,
+	 * then controller monitors DAT0 for busy status,
+	 * controller issues a TRANSFER COMPLETE interrupt when busy signal
+	 * clears.
+	 */
+	wait_for_event(handle,
+		       SD4_EMMC_TOP_INTR_TXDONE_MASK | SD_ERR_INTERRUPTS,
+		       handle->device->cfg.wfe_retry);
+
+	if (res == SD_OK) {
+		/* Check result of Cmd6 using Cmd13 to check card status */
+
+		/* Check status using Cmd13 */
+		res = sd_cmd13(handle, &resp.cardStatus);
+
+		if (res == SD_OK) {
+			/* Check bit 7 (SWITCH_ERROR) in card status */
+			if ((resp.cardStatus & 0x80) != 0) {
+				EMMC_TRACE("cmd6 failed: SWITCH_ERROR\n");
+				res = SD_FAIL;
+			}
+		} else {
+			EMMC_TRACE("cmd13 failed after cmd6: ");
+			EMMC_TRACE("rca 0x%0x, return %d, response 0x%0x\n",
+				handle->device->ctrl.rca, res, resp.cardStatus);
+		}
+	}
+
+	return res;
+}
+
+
+#define SD_BUSY_CHECK		0x00203000
+#define DAT0_LEVEL_MASK		0x100000	/* bit20 in PSTATE */
+#define DEV_BUSY_TIMEOUT	600000		/* 60 Sec : 600000 * 100us */
+
+int send_cmd(struct sd_handle *handle, uint32_t cmdIndex, uint32_t argument,
+	     uint32_t options, struct sd_resp *resp)
+{
+	int status = SD_OK;
+	uint32_t event = 0, present, timeout = 0, retry = 0, mask = 3;
+	uint32_t temp_resp[4];
+
+	if (handle == NULL) {
+		EMMC_TRACE("Invalid handle for cmd%d\n", cmdIndex);
+		return SD_INVALID_HANDLE;
+	}
+
+	mask = (SD_BUSY_CHECK & options) ? 3 : 1;
+
+RETRY_WRITE_CMD:
+	do {
+		/* Make sure it is ok to send command */
+		present =
+		    chal_sd_get_present_status((CHAL_HANDLE *) handle->device);
+		timeout++;
+
+		if (present & mask)
+			SD_US_DELAY(1000);
+		else
+			break;
+
+	} while (timeout < EMMC_BUSY_CMD_TIMEOUT_MS);
+
+	if (timeout >= EMMC_BUSY_CMD_TIMEOUT_MS) {
+		status = SD_CMD_MISSING;
+		EMMC_TRACE("cmd%d timedout %dms\n", cmdIndex, timeout);
+	}
+
+	/* Reset both DAT and CMD line if only of them are stuck */
+	if (present & mask)
+		check_error(handle, SD4_EMMC_TOP_INTR_CMDERROR_MASK);
+
+	handle->device->ctrl.argReg = argument;
+	chal_sd_send_cmd((CHAL_HANDLE *) handle->device, cmdIndex,
+			 handle->device->ctrl.argReg, options);
+
+	handle->device->ctrl.cmdIndex = cmdIndex;
+
+	event = wait_for_event(handle,
+			       (SD4_EMMC_TOP_INTR_CMDDONE_MASK |
+				SD_ERR_INTERRUPTS),
+			       handle->device->cfg.wfe_retry);
+
+	if (handle->device->ctrl.cmdStatus == SD_CMD_MISSING) {
+		retry++;
+
+		if (retry >= handle->device->cfg.retryLimit) {
+			status = SD_CMD_MISSING;
+			EMMC_TRACE("cmd%d retry reaches the limit %d\n",
+				   cmdIndex, retry);
+		} else {
+			/* reset both DAT & CMD line if one of them is stuck */
+			present = chal_sd_get_present_status((CHAL_HANDLE *)
+							     handle->device);
+
+			if (present & mask)
+				check_error(handle,
+					    SD4_EMMC_TOP_INTR_CMDERROR_MASK);
+
+			EMMC_TRACE("cmd%d retry %d PSTATE[0x%08x]\n",
+				   cmdIndex, retry,
+				   chal_sd_get_present_status((CHAL_HANDLE *)
+							      handle->device));
+			goto RETRY_WRITE_CMD;
+		}
+	}
+
+	if (handle->device->ctrl.cmdStatus == SD_OK) {
+		if (resp != NULL) {
+			status =
+			    chal_sd_get_response((CHAL_HANDLE *) handle->device,
+						 temp_resp);
+			process_cmd_response(handle,
+					     handle->device->ctrl.cmdIndex,
+					     temp_resp[0], temp_resp[1],
+					     temp_resp[2], temp_resp[3], resp);
+		}
+
+		/* Check Device busy after CMD */
+		if ((cmdIndex == 5) || (cmdIndex == 6) || (cmdIndex == 7) ||
+		    (cmdIndex == 28) || (cmdIndex == 29) || (cmdIndex == 38)) {
+
+			timeout = 0;
+			do {
+				present =
+				    chal_sd_get_present_status((CHAL_HANDLE *)
+							       handle->device);
+
+				timeout++;
+
+				/* Dat[0]:bit20 low means device busy */
+				if ((present & DAT0_LEVEL_MASK) == 0) {
+					EMMC_TRACE("Device busy: ");
+					EMMC_TRACE(
+					  "cmd%d arg:0x%08x: PSTATE[0x%08x]\n",
+					  cmdIndex, argument, present);
+					SD_US_DELAY(100);
+				} else {
+					break;
+				}
+			} while (timeout < DEV_BUSY_TIMEOUT);
+		}
+	} else if (handle->device->ctrl.cmdStatus &&
+		   handle->device->ctrl.cmdStatus != SD_CMD_MISSING) {
+		retry++;
+		status = check_error(handle, handle->device->ctrl.cmdStatus);
+
+		EMMC_TRACE(
+			"cmd%d error: cmdStatus:0x%08x error_status:0x%08x\n",
+			cmdIndex, handle->device->ctrl.cmdStatus, status);
+
+		if ((handle->device->ctrl.cmdIndex == 1) ||
+		    (handle->device->ctrl.cmdIndex == 5)) {
+			status = event;
+		} else if ((handle->device->ctrl.cmdIndex == 7) ||
+			   (handle->device->ctrl.cmdIndex == 41)) {
+			status = event;
+		} else if ((status == SD_ERROR_RECOVERABLE) &&
+			   (retry < handle->device->cfg.retryLimit)) {
+			EMMC_TRACE("cmd%d recoverable error ", cmdIndex);
+			EMMC_TRACE("retry %d PSTATE[0x%08x].\n", retry,
+				   chal_sd_get_present_status((CHAL_HANDLE *)
+							      handle->device));
+			goto RETRY_WRITE_CMD;
+		} else {
+			EMMC_TRACE("cmd%d retry reaches the limit %d\n",
+				   cmdIndex, retry);
+			status = event;
+		}
+	}
+
+	handle->device->ctrl.blkReg = 0;
+	/* clear error status for next command */
+	handle->device->ctrl.cmdStatus = 0;
+
+	return status;
+}
diff --git a/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c b/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c
new file mode 100644
index 0000000..68f93e7
--- /dev/null
+++ b/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <emmc_api.h>
+#include <cmn_plat_util.h>
+
+#define MAX_CMD_RETRY      10
+
+#if EMMC_USE_DMA
+#define USE_DMA 1
+#else
+#define USE_DMA 0
+#endif
+
+struct emmc_global_buffer emmc_global_buf;
+struct emmc_global_buffer *emmc_global_buf_ptr = &emmc_global_buf;
+
+struct emmc_global_vars emmc_global_vars;
+struct emmc_global_vars *emmc_global_vars_ptr = &emmc_global_vars;
+
+static struct sd_handle *sdio_gethandle(void);
+static uint32_t sdio_idle(struct sd_handle *p_sdhandle);
+
+static uint32_t sdio_read(struct sd_handle *p_sdhandle,
+			  uintptr_t mem_addr,
+			  uintptr_t storage_addr,
+			  size_t storage_size,
+			  size_t bytes_to_read);
+
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+static uint32_t sdio_write(struct sd_handle *p_sdhandle,
+			   uintptr_t mem_addr,
+			   uintptr_t data_addr,
+			   size_t bytes_to_write);
+#endif
+
+static struct sd_handle *sdio_init(void);
+static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle);
+
+static void init_globals(void)
+{
+	memset((void *)emmc_global_buf_ptr, 0, sizeof(*emmc_global_buf_ptr));
+	memset((void *)emmc_global_vars_ptr, 0, sizeof(*emmc_global_vars_ptr));
+}
+
+/*
+ * This function is used to change partition
+ */
+uint32_t emmc_partition_select(uint32_t partition)
+{
+	int rc;
+	struct sd_handle *sd_handle = sdio_gethandle();
+
+	if (sd_handle->device == 0) {
+		EMMC_TRACE("eMMC init is not done");
+		return 0;
+	}
+
+	switch (partition) {
+	case EMMC_BOOT_PARTITION1:
+		rc = set_boot_config(sd_handle,
+				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1);
+		EMMC_TRACE(
+		     "Change to Boot Partition 1 result:%d  (0 means SD_OK)\n",
+		     rc);
+		break;
+
+	case EMMC_BOOT_PARTITION2:
+		rc = set_boot_config(sd_handle,
+				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2);
+		EMMC_TRACE(
+		     "Change to Boot Partition 2 result:%d  (0 means SD_OK)\n",
+		     rc);
+		break;
+
+	case EMMC_USE_CURRENT_PARTITION:
+		rc = SD_OK;
+		EMMC_TRACE("Stay on current partition");
+		break;
+
+	case EMMC_USER_AREA:
+	default:
+		rc = set_boot_config(sd_handle,
+				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER);
+		EMMC_TRACE("Change to User area result:%d  (0 means SD_OK)\n",
+			   rc);
+		break;
+
+	}
+	return (rc == SD_OK);
+}
+
+/*
+ * Initialize emmc controller for eMMC
+ * Returns 0 on fail condition
+ */
+uint32_t bcm_emmc_init(bool card_rdy_only)
+{
+	struct sd_handle *p_sdhandle;
+	uint32_t result = 0;
+
+	EMMC_TRACE("Enter emmc_controller_init()\n");
+
+	/* If eMMC is already initialized, skip init */
+	if (emmc_global_vars_ptr->init_done)
+		return 1;
+
+	init_globals();
+
+	p_sdhandle = sdio_init();
+
+	if (p_sdhandle == NULL) {
+		ERROR("eMMC init failed");
+		return result;
+	}
+
+	if (card_rdy_only) {
+		/* Put the card in Ready state, Not complete init */
+		result = bcm_emmc_card_ready_state(p_sdhandle);
+		return !result;
+	}
+
+	if (sdio_idle(p_sdhandle) == EMMC_BOOT_OK) {
+		set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, USE_DMA,
+			   SD_DMA_BOUNDARY_256K, EMMC_BLOCK_SIZE,
+			   EMMC_WFE_RETRY);
+
+		if (!select_blk_sz(p_sdhandle,
+				   p_sdhandle->device->cfg.blockSize)) {
+			emmc_global_vars_ptr->init_done = 1;
+			result = 1;
+		} else {
+			ERROR("Select Block Size failed\n");
+		}
+	} else {
+		ERROR("eMMC init failed");
+	}
+
+	/* Initialization is failed, so deinit HW setting */
+	if (result == 0)
+		emmc_deinit();
+
+	return result;
+}
+
+/*
+ * Function to de-init SDIO controller for eMMC
+ */
+void emmc_deinit(void)
+{
+	emmc_global_vars_ptr->init_done = 0;
+	emmc_global_vars_ptr->sdHandle.card = 0;
+	emmc_global_vars_ptr->sdHandle.device = 0;
+}
+
+/*
+ * Read eMMC memory
+ * Returns read_size
+ */
+uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr,
+		   size_t storage_size, size_t bytes_to_read)
+{
+	struct sd_handle *sd_handle = sdio_gethandle();
+
+	if (sd_handle->device == 0) {
+		EMMC_TRACE("eMMC init is not done");
+		return 0;
+	}
+
+	return sdio_read(sdio_gethandle(), mem_addr, storage_addr,
+			 storage_size, bytes_to_read);
+}
+
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+#define EXT_CSD_ERASE_GRP_SIZE 224
+
+static int emmc_block_erase(uintptr_t mem_addr, size_t blocks)
+{
+	struct sd_handle *sd_handle = sdio_gethandle();
+
+	if (sd_handle->device == 0) {
+		ERROR("eMMC init is not done");
+		return -1;
+	}
+
+	return erase_card(sdio_gethandle(), mem_addr, blocks);
+}
+
+int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition)
+{
+	int err = 0;
+	size_t block_count = 0, blocks = 0;
+	size_t erase_group = 0;
+
+	erase_group =
+	emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_ERASE_GRP_SIZE]*1024;
+
+	INFO("eMMC Erase Group Size=0x%lx\n", erase_group);
+
+	emmc_partition_select(partition);
+
+	while (block_count < num_of_blocks) {
+		blocks = ((num_of_blocks - block_count) > erase_group) ?
+				  erase_group : (num_of_blocks - block_count);
+			err = emmc_block_erase(mem_addr + block_count, blocks);
+		if (err)
+			break;
+
+		block_count += blocks;
+	}
+
+	if (err == 0)
+		INFO("eMMC Erase of partition %d successful\n", partition);
+	else
+		ERROR("eMMC Erase of partition %d Failed(%i)\n", partition, err);
+
+	return err;
+}
+#endif
+
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+/*
+ * Write to eMMC memory
+ * Returns written_size
+ */
+uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr,
+		    size_t bytes_to_write)
+{
+	struct sd_handle *sd_handle = sdio_gethandle();
+
+	if (sd_handle->device == 0) {
+		EMMC_TRACE("eMMC init is not done");
+		return 0;
+	}
+
+	return sdio_write(sd_handle, mem_addr, data_addr, bytes_to_write);
+}
+#endif
+
+/*
+ * Send SDIO Cmd
+ * Return 0 for pass condition
+ */
+uint32_t send_sdio_cmd(uint32_t cmdIndex, uint32_t argument,
+		       uint32_t options, struct sd_resp *resp)
+{
+	struct sd_handle *sd_handle = sdio_gethandle();
+
+	if (sd_handle->device == 0) {
+		EMMC_TRACE("eMMC init is not done");
+		return 1;
+	}
+
+	return send_cmd(sd_handle, cmdIndex, argument, options, resp);
+}
+
+
+/*
+ * This function return SDIO handle
+ */
+struct sd_handle *sdio_gethandle(void)
+{
+	return &emmc_global_vars_ptr->sdHandle;
+}
+
+/*
+ * Initialize SDIO controller
+ */
+struct sd_handle *sdio_init(void)
+{
+	uint32_t SDIO_base;
+	struct sd_handle *p_sdhandle = &emmc_global_vars_ptr->sdHandle;
+
+	SDIO_base = EMMC_CTRL_REGS_BASE_ADDR;
+
+	if (SDIO_base == SDIO0_EMMCSDXC_SYSADDR)
+		EMMC_TRACE(" ---> for SDIO 0 Controller\n\n");
+
+	memset(p_sdhandle, 0, sizeof(struct sd_handle));
+
+	p_sdhandle->device = &emmc_global_vars_ptr->sdDevice;
+	p_sdhandle->card = &emmc_global_vars_ptr->sdCard;
+
+	memset(p_sdhandle->device, 0, sizeof(struct sd_dev));
+	memset(p_sdhandle->card, 0, sizeof(struct sd_card_info));
+
+	if (chal_sd_start((CHAL_HANDLE *) p_sdhandle->device,
+			  SD_PIO_MODE, SDIO_base, SDIO_base) != SD_OK)
+		return NULL;
+
+	set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, SD_DMA_OFF,
+		   SD_DMA_BOUNDARY_4K, EMMC_BLOCK_SIZE, EMMC_WFE_RETRY);
+
+	return &emmc_global_vars_ptr->sdHandle;
+}
+
+uint32_t sdio_idle(struct sd_handle *p_sdhandle)
+{
+	reset_card(p_sdhandle);
+
+	SD_US_DELAY(1000);
+
+	if (init_card(p_sdhandle, SD_CARD_DETECT_MMC) != SD_OK) {
+		reset_card(p_sdhandle);
+		reset_host_ctrl(p_sdhandle);
+		return EMMC_BOOT_NO_CARD;
+	}
+
+	return EMMC_BOOT_OK;
+}
+
+/*
+ * This function read eMMC
+ */
+uint32_t sdio_read(struct sd_handle *p_sdhandle,
+		   uintptr_t mem_addr,
+		   uintptr_t storage_addr,
+		   size_t storage_size, size_t bytes_to_read)
+{
+	uint32_t offset = 0, blockAddr, readLen = 0, rdCount;
+	uint32_t remSize, manual_copy_size;
+	uint8_t *outputBuf = (uint8_t *) storage_addr;
+	const size_t blockSize = p_sdhandle->device->cfg.blockSize;
+
+	VERBOSE("EMMC READ: dst=0x%lx, src=0x%lx, size=0x%lx\n",
+			storage_addr, mem_addr, bytes_to_read);
+
+	if (storage_size < bytes_to_read)
+		/* Don't have sufficient storage to complete the operation */
+		return 0;
+
+	/* Range check non high capacity memory */
+	if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
+		if (mem_addr > 0x80000000)
+			return 0;
+	}
+
+	/* High capacity card use block address mode */
+	if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
+		blockAddr = (uint32_t) (mem_addr / blockSize);
+		offset = (uint32_t) (mem_addr - (blockAddr * blockSize));
+	} else {
+		blockAddr = (uint32_t) (mem_addr / blockSize) * blockSize;
+		offset = (uint32_t) (mem_addr - blockAddr);
+	}
+
+	remSize = bytes_to_read;
+
+	rdCount = 0;
+
+	/* Process first unaligned block of MAX_READ_LENGTH */
+	if (offset > 0) {
+		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
+				blockAddr, SD_MAX_READ_LENGTH)) {
+
+			if (remSize < (blockSize - offset)) {
+				rdCount += remSize;
+				manual_copy_size = remSize;
+				remSize = 0;	/* read is done */
+			} else {
+				remSize -= (blockSize - offset);
+				rdCount += (blockSize - offset);
+				manual_copy_size = blockSize - offset;
+			}
+
+			/* Check for overflow */
+			if (manual_copy_size > storage_size ||
+			    (((uintptr_t)outputBuf + manual_copy_size) >
+			     (storage_addr + storage_size))) {
+				ERROR("EMMC READ: Overflow 1\n");
+				return 0;
+			}
+
+			memcpy(outputBuf,
+			       (void *)((uintptr_t)
+				(emmc_global_buf_ptr->u.tempbuf + offset)),
+			       manual_copy_size);
+
+			/* Update Physical address */
+			outputBuf += manual_copy_size;
+
+			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
+				blockAddr++;
+			else
+				blockAddr += blockSize;
+		} else {
+			return 0;
+		}
+	}
+
+	while (remSize >= blockSize) {
+
+		if (remSize >= SD_MAX_BLK_TRANSFER_LENGTH)
+			readLen = SD_MAX_BLK_TRANSFER_LENGTH;
+		else
+			readLen = (remSize / blockSize) * blockSize;
+
+		/* Check for overflow */
+		if ((rdCount + readLen) > storage_size ||
+		    (((uintptr_t) outputBuf + readLen) >
+		     (storage_addr + storage_size))) {
+			ERROR("EMMC READ: Overflow\n");
+			return 0;
+		}
+
+		if (!read_block(p_sdhandle, outputBuf, blockAddr, readLen)) {
+			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
+				blockAddr += (readLen / blockSize);
+			else
+				blockAddr += readLen;
+
+			remSize -= readLen;
+			rdCount += readLen;
+
+			/* Update Physical address */
+			outputBuf += readLen;
+		} else {
+			return 0;
+		}
+	}
+
+	/* process the last unaligned block reading */
+	if (remSize > 0) {
+		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
+				blockAddr, SD_MAX_READ_LENGTH)) {
+
+			rdCount += remSize;
+			/* Check for overflow */
+			if (rdCount > storage_size ||
+			    (((uintptr_t) outputBuf + remSize) >
+			     (storage_addr + storage_size))) {
+				ERROR("EMMC READ: Overflow\n");
+				return 0;
+			}
+
+			memcpy(outputBuf,
+				emmc_global_buf_ptr->u.tempbuf, remSize);
+
+			/* Update Physical address */
+			outputBuf += remSize;
+		} else {
+			rdCount = 0;
+		}
+	}
+
+	return rdCount;
+}
+
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+static uint32_t sdio_write(struct sd_handle *p_sdhandle, uintptr_t mem_addr,
+			   uintptr_t data_addr, size_t bytes_to_write)
+{
+
+	uint32_t offset, blockAddr, writeLen, wtCount = 0;
+	uint32_t remSize, manual_copy_size = 0;
+
+	uint8_t *inputBuf = (uint8_t *)data_addr;
+
+	/* range check non high capacity memory */
+	if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
+		if (mem_addr > 0x80000000)
+			return 0;
+	}
+
+	/* the high capacity card use block address mode */
+	if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
+		blockAddr =
+		    (uint32_t)(mem_addr / p_sdhandle->device->cfg.blockSize);
+		offset =
+		    (uint32_t)(mem_addr -
+			       blockAddr * p_sdhandle->device->cfg.blockSize);
+	} else {
+		blockAddr =
+		    ((uint32_t)mem_addr / p_sdhandle->device->cfg.blockSize) *
+		    p_sdhandle->device->cfg.blockSize;
+		offset = (uint32_t) mem_addr - blockAddr;
+	}
+
+	remSize = bytes_to_write;
+
+	wtCount = 0;
+
+	/* process first unaligned block */
+	if (offset > 0) {
+		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
+				blockAddr, p_sdhandle->device->cfg.blockSize)) {
+
+			if (remSize <
+			    (p_sdhandle->device->cfg.blockSize - offset))
+				manual_copy_size = remSize;
+			else
+				manual_copy_size =
+				    p_sdhandle->device->cfg.blockSize - offset;
+
+			memcpy((void *)((uintptr_t)
+				(emmc_global_buf_ptr->u.tempbuf + offset)),
+			       inputBuf,
+			       manual_copy_size);
+
+			/* Update Physical address */
+
+			if (!write_block(p_sdhandle,
+					 emmc_global_buf_ptr->u.tempbuf,
+					 blockAddr,
+					 p_sdhandle->device->cfg.blockSize)) {
+
+				if (remSize <
+				    (p_sdhandle->device->cfg.blockSize -
+				     offset)) {
+					wtCount += remSize;
+					manual_copy_size = remSize;
+					remSize = 0;	/* read is done */
+				} else {
+					remSize -=
+					    (p_sdhandle->device->cfg.blockSize -
+					     offset);
+					wtCount +=
+					    (p_sdhandle->device->cfg.blockSize -
+					     offset);
+					manual_copy_size =
+					    p_sdhandle->device->cfg.blockSize -
+					    offset;
+				}
+
+				inputBuf += manual_copy_size;
+
+				if (p_sdhandle->device->ctrl.ocr &
+				    SD_CARD_HIGH_CAPACITY)
+					blockAddr++;
+				else
+					blockAddr +=
+					    p_sdhandle->device->cfg.blockSize;
+			} else
+				return 0;
+		} else {
+			return 0;
+		}
+	}
+
+	/* process block writing */
+	while (remSize >= p_sdhandle->device->cfg.blockSize) {
+		if (remSize >= SD_MAX_READ_LENGTH) {
+			writeLen = SD_MAX_READ_LENGTH;
+		} else {
+			writeLen =
+			    (remSize / p_sdhandle->device->cfg.blockSize) *
+			     p_sdhandle->device->cfg.blockSize;
+		}
+
+		if (!write_block(p_sdhandle, inputBuf, blockAddr, writeLen)) {
+			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
+				blockAddr +=
+				    (writeLen /
+				     p_sdhandle->device->cfg.blockSize);
+			else
+				blockAddr += writeLen;
+
+			remSize -= writeLen;
+			wtCount += writeLen;
+			inputBuf += writeLen;
+		} else {
+			return 0;
+		}
+	}
+
+	/* process the last unaligned block reading */
+	if (remSize > 0) {
+		if (!read_block(p_sdhandle,
+				emmc_global_buf_ptr->u.tempbuf,
+				blockAddr, p_sdhandle->device->cfg.blockSize)) {
+
+			memcpy(emmc_global_buf_ptr->u.tempbuf,
+			       inputBuf, remSize);
+
+			/* Update Physical address */
+
+			if (!write_block(p_sdhandle,
+					 emmc_global_buf_ptr->u.tempbuf,
+					 blockAddr,
+					 p_sdhandle->device->cfg.blockSize)) {
+				wtCount += remSize;
+				inputBuf += remSize;
+			} else {
+				return 0;
+			}
+		} else {
+			wtCount = 0;
+		}
+	}
+
+	return wtCount;
+}
+#endif
+
+/*
+ * Function to put the card in Ready state by sending CMD0 and CMD1
+ */
+static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle)
+{
+	int32_t result = 0;
+	uint32_t argument = MMC_CMD_IDLE_RESET_ARG; /* Exit from Boot mode */
+
+	if (p_sdhandle) {
+		send_sdio_cmd(SD_CMD_GO_IDLE_STATE, argument, 0, NULL);
+
+		result = reset_card(p_sdhandle);
+		if (result != SD_OK) {
+			EMMC_TRACE("eMMC Reset error\n");
+			return SD_RESET_ERROR;
+		}
+		SD_US_DELAY(2000);
+		result = mmc_cmd1(p_sdhandle);
+	}
+
+	return result;
+}
diff --git a/drivers/brcm/iproc_gpio.c b/drivers/brcm/iproc_gpio.c
new file mode 100644
index 0000000..f61a3bc
--- /dev/null
+++ b/drivers/brcm/iproc_gpio.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/gpio.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <iproc_gpio.h>
+#include <platform_def.h>
+
+#define IPROC_GPIO_DATA_IN_OFFSET     0x00
+#define IPROC_GPIO_DATA_OUT_OFFSET    0x04
+#define IPROC_GPIO_OUT_EN_OFFSET      0x08
+#define IPROC_GPIO_PAD_RES_OFFSET     0x34
+#define IPROC_GPIO_RES_EN_OFFSET      0x38
+
+#define PINMUX_OFFSET(gpio)           ((gpio) * 4)
+#define PINCONF_OFFSET(gpio)          ((gpio) * 4)
+#define PINCONF_PULL_UP               BIT(4)
+#define PINCONF_PULL_DOWN             BIT(5)
+
+/*
+ * iProc GPIO bank is always 0x200 per bank,
+ * with each bank supporting 32 GPIOs.
+ */
+#define GPIO_BANK_SIZE                0x200
+#define NGPIOS_PER_BANK               32
+#define GPIO_BANK(pin)                ((pin) / NGPIOS_PER_BANK)
+
+#define IPROC_GPIO_REG(pin, reg)      (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg))
+#define IPROC_GPIO_SHIFT(pin)         ((pin) % NGPIOS_PER_BANK)
+
+#define MUX_GPIO_MODE                 0x3
+
+/*
+ * @base: base address of the gpio controller
+ * @pinconf_base: base address of the pinconf
+ * @pinmux_base: base address of the mux controller
+ * @nr_gpios: maxinum number of GPIOs
+ */
+struct iproc_gpio {
+	uintptr_t base;
+	uintptr_t pinconf_base;
+	uintptr_t pinmux_base;
+	int nr_gpios;
+};
+
+static struct iproc_gpio iproc_gpio;
+
+static void gpio_set_bit(uintptr_t base, unsigned int reg, int gpio, bool set)
+{
+	unsigned int offset = IPROC_GPIO_REG(gpio, reg);
+	unsigned int shift = IPROC_GPIO_SHIFT(gpio);
+	uint32_t val;
+
+	val = mmio_read_32(base + offset);
+	if (set)
+		val |= BIT(shift);
+	else
+		val &= ~BIT(shift);
+
+	mmio_write_32(base + offset, val);
+}
+
+static bool gpio_get_bit(uintptr_t base, unsigned int reg, int gpio)
+{
+	unsigned int offset = IPROC_GPIO_REG(gpio, reg);
+	unsigned int shift = IPROC_GPIO_SHIFT(gpio);
+
+	return !!(mmio_read_32(base + offset) & BIT(shift));
+}
+
+static void mux_to_gpio(struct iproc_gpio *g, int gpio)
+{
+	/* mux pad to GPIO if IOPAD configuration is mandatory */
+	if (g->pinmux_base)
+		mmio_write_32(g->pinmux_base + PINMUX_OFFSET(gpio),
+			      MUX_GPIO_MODE);
+}
+
+static void set_direction(int gpio, int direction)
+{
+	struct iproc_gpio *g = &iproc_gpio;
+	bool dir = (direction == GPIO_DIR_OUT) ? true : false;
+
+	assert(gpio < g->nr_gpios);
+
+	mux_to_gpio(g, gpio);
+	gpio_set_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio, dir);
+}
+
+static int get_direction(int gpio)
+{
+	struct iproc_gpio *g = &iproc_gpio;
+	int dir;
+
+	assert(gpio < g->nr_gpios);
+
+	mux_to_gpio(g, gpio);
+	dir = gpio_get_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio) ?
+		GPIO_DIR_OUT : GPIO_DIR_IN;
+
+	return dir;
+}
+
+static int get_value(int gpio)
+{
+	struct iproc_gpio *g = &iproc_gpio;
+	unsigned int offset;
+
+	assert(gpio < g->nr_gpios);
+
+	mux_to_gpio(g, gpio);
+
+	/*
+	 * If GPIO is configured as output, read from the GPIO_OUT register;
+	 * otherwise, read from the GPIO_IN register
+	 */
+	offset = gpio_get_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio) ?
+		IPROC_GPIO_DATA_OUT_OFFSET : IPROC_GPIO_DATA_IN_OFFSET;
+
+	return gpio_get_bit(g->base, offset, gpio);
+}
+
+static void set_value(int gpio, int val)
+{
+	struct iproc_gpio *g = &iproc_gpio;
+
+	assert(gpio < g->nr_gpios);
+
+	mux_to_gpio(g, gpio);
+
+	/* make sure GPIO is configured to output, and then set the value */
+	gpio_set_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio, true);
+	gpio_set_bit(g->base, IPROC_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
+}
+
+static int get_pull(int gpio)
+{
+	struct iproc_gpio *g = &iproc_gpio;
+	uint32_t val;
+
+	assert(gpio < g->nr_gpios);
+	mux_to_gpio(g, gpio);
+
+	/* when there's a valid pinconf_base, use it */
+	if (g->pinconf_base) {
+		val = mmio_read_32(g->pinconf_base + PINCONF_OFFSET(gpio));
+
+		if (val & PINCONF_PULL_UP)
+			return GPIO_PULL_UP;
+		else if (val & PINCONF_PULL_DOWN)
+			return GPIO_PULL_DOWN;
+		else
+			return GPIO_PULL_NONE;
+	}
+
+	/* no pinconf_base. fall back to GPIO internal pull control */
+	if (!gpio_get_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio))
+		return GPIO_PULL_NONE;
+
+	return gpio_get_bit(g->base, IPROC_GPIO_PAD_RES_OFFSET, gpio) ?
+		GPIO_PULL_UP : GPIO_PULL_DOWN;
+}
+
+static void set_pull(int gpio, int pull)
+{
+	struct iproc_gpio *g = &iproc_gpio;
+	uint32_t val;
+
+	assert(gpio < g->nr_gpios);
+	mux_to_gpio(g, gpio);
+
+	/* when there's a valid pinconf_base, use it */
+	if (g->pinconf_base) {
+		val = mmio_read_32(g->pinconf_base + PINCONF_OFFSET(gpio));
+
+		if (pull == GPIO_PULL_NONE) {
+			val &= ~(PINCONF_PULL_UP | PINCONF_PULL_DOWN);
+		} else if (pull == GPIO_PULL_UP) {
+			val |= PINCONF_PULL_UP;
+			val &= ~PINCONF_PULL_DOWN;
+		} else if (pull == GPIO_PULL_DOWN) {
+			val |= PINCONF_PULL_DOWN;
+			val &= ~PINCONF_PULL_UP;
+		} else {
+			return;
+		}
+		mmio_write_32(g->pinconf_base + PINCONF_OFFSET(gpio), val);
+	}
+
+	/* no pinconf_base. fall back to GPIO internal pull control */
+	if (pull == GPIO_PULL_NONE) {
+		gpio_set_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio, false);
+		return;
+	}
+
+	/* enable pad register and pull up or down */
+	gpio_set_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio, true);
+	gpio_set_bit(g->base, IPROC_GPIO_PAD_RES_OFFSET, gpio,
+		     !!(pull == GPIO_PULL_UP));
+}
+
+const gpio_ops_t iproc_gpio_ops = {
+	.get_direction = get_direction,
+	.set_direction = set_direction,
+	.get_value = get_value,
+	.set_value = set_value,
+	.get_pull = get_pull,
+	.set_pull = set_pull,
+};
+
+void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base,
+		     uintptr_t pinconf_base)
+{
+	iproc_gpio.base = base;
+	iproc_gpio.nr_gpios = nr_gpios;
+
+	/* pinmux/pinconf base is optional for some SoCs */
+	if (pinmux_base)
+		iproc_gpio.pinmux_base = pinmux_base;
+
+	if (pinconf_base)
+		iproc_gpio.pinconf_base = pinconf_base;
+
+	gpio_init(&iproc_gpio_ops);
+}
diff --git a/drivers/brcm/ocotp.c b/drivers/brcm/ocotp.c
new file mode 100644
index 0000000..6ff8554
--- /dev/null
+++ b/drivers/brcm/ocotp.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <ocotp.h>
+#include <platform_def.h>
+
+#define OTP_MAP 2
+#define OTP_NUM_WORDS 2048
+/*
+ * # of tries for OTP Status. The time to execute a command varies. The slowest
+ * commands are writes which also vary based on the # of bits turned on. Writing
+ * 0xffffffff takes ~3800 us.
+ */
+#define OTPC_RETRIES_US                 5000
+
+/* Sequence to enable OTP program */
+#define OTPC_PROG_EN_SEQ             { 0xf, 0x4, 0x8, 0xd }
+
+/* OTPC Commands */
+#define OTPC_CMD_READ                0x0
+#define OTPC_CMD_OTP_PROG_ENABLE     0x2
+#define OTPC_CMD_OTP_PROG_DISABLE    0x3
+#define OTPC_CMD_PROGRAM             0x8
+#define OTPC_CMD_ECC                 0x10
+#define OTPC_ECC_ADDR                0x1A
+#define OTPC_ECC_VAL                 0x00EC0000
+
+/* OTPC Status Bits */
+#define OTPC_STAT_CMD_DONE           BIT(1)
+#define OTPC_STAT_PROG_OK            BIT(2)
+
+/* OTPC register definition */
+#define OTPC_MODE_REG_OFFSET         0x0
+#define OTPC_MODE_REG_OTPC_MODE      0
+#define OTPC_COMMAND_OFFSET          0x4
+#define OTPC_COMMAND_COMMAND_WIDTH   6
+#define OTPC_CMD_START_OFFSET        0x8
+#define OTPC_CMD_START_START         0
+#define OTPC_CPU_STATUS_OFFSET       0xc
+#define OTPC_CPUADDR_REG_OFFSET      0x28
+#define OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH 16
+#define OTPC_CPU_WRITE_REG_OFFSET    0x2c
+
+#define OTPC_CMD_MASK  (BIT(OTPC_COMMAND_COMMAND_WIDTH) - 1)
+#define OTPC_ADDR_MASK (BIT(OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH) - 1)
+
+#define OTPC_MODE_REG			OCOTP_REGS_BASE
+
+struct chip_otp_cfg {
+	uint32_t base;
+	uint32_t num_words;
+};
+
+struct chip_otp_cfg ocotp_cfg = {
+	.base = OTPC_MODE_REG,
+	.num_words = 2048,
+};
+
+struct otpc_priv {
+	uint32_t base;
+	struct otpc_map *map;
+	int size;
+	int state;
+};
+
+struct otpc_priv otpc_info;
+
+static inline void set_command(uint32_t base, uint32_t command)
+{
+	mmio_write_32(base + OTPC_COMMAND_OFFSET, command & OTPC_CMD_MASK);
+}
+
+static inline void set_cpu_address(uint32_t base, uint32_t addr)
+{
+	mmio_write_32(base + OTPC_CPUADDR_REG_OFFSET, addr & OTPC_ADDR_MASK);
+}
+
+static inline void set_start_bit(uint32_t base)
+{
+	mmio_write_32(base + OTPC_CMD_START_OFFSET, 1 << OTPC_CMD_START_START);
+}
+
+static inline void reset_start_bit(uint32_t base)
+{
+	mmio_write_32(base + OTPC_CMD_START_OFFSET, 0);
+}
+
+static inline void write_cpu_data(uint32_t base, uint32_t value)
+{
+	mmio_write_32(base + OTPC_CPU_WRITE_REG_OFFSET, value);
+}
+
+static int poll_cpu_status(uint32_t base, uint32_t value)
+{
+	uint32_t status;
+	uint32_t retries;
+
+	for (retries = 0; retries < OTPC_RETRIES_US; retries++) {
+		status = mmio_read_32(base + OTPC_CPU_STATUS_OFFSET);
+		if (status & value)
+			break;
+		udelay(1);
+	}
+	if (retries == OTPC_RETRIES_US)
+		return -1;
+
+	return 0;
+}
+
+static int bcm_otpc_ecc(uint32_t enable)
+{
+	struct otpc_priv *priv = &otpc_info;
+	int ret;
+
+	set_command(priv->base, OTPC_CMD_ECC);
+	set_cpu_address(priv->base, OTPC_ECC_ADDR);
+
+	if (!enable)
+		write_cpu_data(priv->base, OTPC_ECC_VAL);
+	else
+		write_cpu_data(priv->base, ~OTPC_ECC_VAL);
+
+	set_start_bit(priv->base);
+	ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE);
+	if (ret) {
+		ERROR("otp ecc op error: 0x%x", ret);
+		return -1;
+	}
+	reset_start_bit(priv->base);
+
+	return 0;
+}
+
+/*
+ * bcm_otpc_read read otp data in the size of 8 byte rows.
+ * bytes has to be the multiple of 8.
+ * return -1 in error case, return read bytes in success.
+ */
+int bcm_otpc_read(unsigned int offset, void *val, uint32_t bytes,
+		  uint32_t ecc_flag)
+{
+	struct otpc_priv *priv = &otpc_info;
+	uint32_t *buf = val;
+	uint32_t bytes_read;
+	uint32_t address = offset / priv->map->word_size;
+	int i, ret;
+
+	if (!priv->state) {
+		ERROR("OCOTP read failed\n");
+		return -1;
+	}
+
+	bcm_otpc_ecc(ecc_flag);
+
+	for (bytes_read = 0; (bytes_read + priv->map->word_size) <= bytes;) {
+		set_command(priv->base, OTPC_CMD_READ);
+		set_cpu_address(priv->base, address++);
+		set_start_bit(priv->base);
+		ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE);
+		if (ret) {
+			ERROR("otp read error: 0x%x", ret);
+			return -1;
+		}
+
+		for (i = 0; i < priv->map->otpc_row_size; i++) {
+			*buf++ = mmio_read_32(priv->base +
+					priv->map->data_r_offset[i]);
+			bytes_read += sizeof(*buf);
+		}
+
+		reset_start_bit(priv->base);
+	}
+
+	return bytes_read;
+}
+
+int bcm_otpc_init(struct otpc_map *map)
+{
+	struct otpc_priv *priv;
+
+	priv = &otpc_info;
+	priv->base = ocotp_cfg.base;
+	priv->map = map;
+
+	priv->size = 4 * ocotp_cfg.num_words;
+
+	/* Enable CPU access to OTPC. */
+	mmio_setbits_32(priv->base + OTPC_MODE_REG_OFFSET,
+			BIT(OTPC_MODE_REG_OTPC_MODE));
+	reset_start_bit(priv->base);
+	priv->state = 1;
+	VERBOSE("OTPC Initialization done\n");
+
+	return 0;
+}
diff --git a/drivers/brcm/scp.c b/drivers/brcm/scp.c
new file mode 100644
index 0000000..6196073
--- /dev/null
+++ b/drivers/brcm/scp.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+/* MCU binary image structure: <header> <data>
+ *
+ * Header structure:
+ * <magic-start>
+ * <num-sections>
+ * {<src-offset> <src-size> <dst-addr>}*
+ * <magic-end>
+ *
+ * MCU data (<data>) consists of several sections of code/data, to be
+ *             installed (copied) into MCU memories.
+ * Header (<header>) gives information about sections contained in <data>.
+ *
+ * The installer code iterates over sections in MCU binary.
+ * For each section, it copies the section into MCU memory.
+ *
+ * The header contains:
+ *	 - <magic-start> - 32-bit magic number to mark header start
+ *	 - <num-sections> - number of sections in <data>
+ *	 - <num-sections> tuples. Each tuple describes a section.
+ *			 A tuple contains three 32-bit words.
+ *	 - <magic-end> - 32-bit magic number to mark header end
+ *
+ * Each section is describes by a tuple, consisting of three 32-bit words:
+ *	 - offset of section within MCU binary (relative to beginning of <data>)
+ *	 - section size (in bytes) in MCU binary
+ *	 - target address (in MCU memory). Section is copied to this location.
+ *
+ * All fields are 32-bit unsigned integers in little endian format.
+ * All sizes are assumed to be 32-bit aligned.
+ */
+
+#define SCP_BIN_HEADER_MAGIC_START 0xfa587D01
+#define SCP_BIN_HEADER_MAGIC_END 0xf3e06a85
+
+int download_scp_patch(void *image, unsigned int image_size)
+{
+	unsigned int *pheader = (unsigned int *)(image);
+	unsigned int header_size;
+	unsigned char *pdata;
+	void *dest;
+	unsigned int num_sections;
+	unsigned int section_src_offset;
+	unsigned int section_size;
+
+	if (pheader && (pheader[0] != SCP_BIN_HEADER_MAGIC_START)) {
+		ERROR("SCP: Could not find SCP header.\n");
+		return -1;
+	}
+
+	num_sections = pheader[1];
+	INFO("...Number of sections: %d\n", num_sections);
+	header_size = 4 * (1 + 1 + 3 * num_sections + 1);
+
+	if (image_size < header_size) {
+		ERROR("SCP: Wrong size.\n");
+		return -1;
+	}
+
+	if (*(pheader + header_size/4 - 1) != SCP_BIN_HEADER_MAGIC_END) {
+		ERROR("SCP: Could not find SCP footer.\n");
+		return -1;
+	}
+
+	VERBOSE("SCP image header validated successfully\n");
+	pdata = (unsigned char *)pheader + header_size;
+
+	for (pheader += 2; num_sections > 0; num_sections--) {
+
+		section_src_offset = pheader[0];
+		section_size = pheader[1];
+		dest = (void *)(unsigned long)pheader[2];
+
+		INFO("section: src:0x%x, size:%d, dst:0x%x\n",
+				section_src_offset, section_size, pheader[2]);
+
+		if ((section_src_offset + section_size) > image_size) {
+			ERROR("SCP: Section points to outside of patch.\n");
+			return -1;
+		}
+
+		/* copy from source to target section */
+		memcpy(dest, pdata + section_src_offset, section_size);
+		flush_dcache_range((uintptr_t)dest, section_size);
+
+		/* next section */
+		pheader += 3;
+	}
+	return 0;
+}
diff --git a/drivers/brcm/sotp.c b/drivers/brcm/sotp.c
new file mode 100644
index 0000000..63c4820
--- /dev/null
+++ b/drivers/brcm/sotp.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <sotp.h>
+
+#include <platform_def.h>
+#include <platform_sotp.h>
+
+#ifdef USE_SOFT_SOTP
+extern uint64_t soft_sotp[];
+#endif
+
+#define SOTP_PROG_CONTROL (SOTP_REGS_OTP_BASE + 0x0000)
+#define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN 15
+#define SOTP_PROG_CONTROL__OTP_DISABLE_ECC 9
+#define SOTP_PROG_CONTROL__OTP_ECC_WREN 8
+
+#define SOTP_WRDATA_0 (SOTP_REGS_OTP_BASE + 0x0004)
+#define SOTP_WRDATA_1 (SOTP_REGS_OTP_BASE + 0x0008)
+
+#define SOTP_ADDR (SOTP_REGS_OTP_BASE + 0x000c)
+#define SOTP_ADDR__OTP_ROW_ADDR_R 6
+#define SOTP_ADDR_MASK 0x3FF
+
+#define SOTP_CTRL_0 (SOTP_REGS_OTP_BASE + 0x0010)
+#define SOTP_CTRL_0__START 0
+#define SOTP_CTRL_0__OTP_CMD 1
+
+#define SOTP_STATUS_0 (SOTP_REGS_OTP_BASE + 0x0018)
+#define SOTP_STATUS__FDONE 3
+
+#define SOTP_STATUS_1 (SOTP_REGS_OTP_BASE + 0x001c)
+#define SOTP_STATUS_1__CMD_DONE 1
+#define SOTP_STATUS_1__ECC_DET 17
+
+#define SOTP_RDDATA_0 (SOTP_REGS_OTP_BASE + 0x0020)
+#define SOTP_RDDATA_1 (SOTP_REGS_OTP_BASE + 0x0024)
+
+#define SOTP_READ 0
+
+#define SOTP_PROG_WORD 10
+#define SOTP_STATUS__PROGOK 2
+#define SOTP_PROG_ENABLE 2
+
+#define SOTP_ROW_DATA_MASK 0xffffffff
+#define SOTP_ECC_ERR_BITS_MASK 0x1ff00000000
+
+#define SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES 4
+#define SOTP_CHIP_CTRL_SW_MANU_PROG 5
+#define SOTP_CHIP_CTRL_SW_CID_PROG 6
+#define SOTP_CHIP_CTRL_SW_AB_DEVICE 8
+#define SOTP_CHIP_CTRL_SW_AB_DEV_MODE 9
+#define CHIP_STATE_UNPROGRAMMED 0x1
+#define CHIP_STATE_UNASSIGNED 0x2
+
+uint64_t sotp_mem_read(uint32_t offset, uint32_t sotp_add_ecc)
+{
+#ifdef USE_SOFT_SOTP
+	(void)sotp_add_ecc;
+
+	return soft_sotp[offset];
+#else
+	uint64_t read_data = 0;
+	uint64_t read_data1 = 0;
+	uint64_t read_data2 = 0;
+
+	/* Check for FDONE status */
+	while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) !=
+	       BIT(SOTP_STATUS__FDONE))
+		;
+
+	/* Enable OTP access by CPU */
+	mmio_setbits_32(SOTP_PROG_CONTROL,
+			BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
+
+	if (sotp_add_ecc == 1) {
+		mmio_clrbits_32(SOTP_PROG_CONTROL,
+				BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC));
+	}
+
+	if (sotp_add_ecc == 0) {
+		mmio_setbits_32(SOTP_PROG_CONTROL,
+				BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC));
+	}
+
+	mmio_write_32(SOTP_ADDR,
+		      ((offset & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R));
+	mmio_write_32(SOTP_CTRL_0, (SOTP_READ << SOTP_CTRL_0__OTP_CMD));
+
+	/* Start bit to tell SOTP to send command to the OTP controller */
+	mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
+
+	/* Wait for SOTP command done to be set */
+	while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) !=
+	      BIT(SOTP_STATUS_1__CMD_DONE))
+		;
+
+	/* Clr Start bit after command done */
+	mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
+
+	if ((offset > SOTP_DEVICE_SECURE_CFG3_ROW) &&
+	    (mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__ECC_DET))) {
+		ERROR("SOTP ECC ERROR Detected row offset %d\n", offset);
+		read_data = SOTP_ECC_ERR_DETECT;
+	} else {
+		read_data1 = (uint64_t)mmio_read_32(SOTP_RDDATA_0);
+		read_data1 = read_data1 & 0xFFFFFFFF;
+		read_data2 = (uint64_t)mmio_read_32(SOTP_RDDATA_1);
+		read_data2 = (read_data2 & 0x1ff) << 32;
+		read_data = read_data1 | read_data2;
+	}
+
+	/* Command done is cleared */
+	mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
+
+	/* disable OTP access by CPU */
+	mmio_clrbits_32(SOTP_PROG_CONTROL,
+			BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
+
+	return read_data;
+#endif
+}
+
+void sotp_mem_write(uint32_t addr, uint32_t sotp_add_ecc, uint64_t wdata)
+{
+#ifdef USE_SOFT_SOTP
+	(void)sotp_add_ecc;
+
+	soft_sotp[addr] = wdata;
+#else
+	uint32_t loop;
+	uint8_t prog_array[4] = { 0x0F, 0x04, 0x08, 0x0D };
+
+	uint32_t chip_state_default =
+		(CHIP_STATE_UNASSIGNED|CHIP_STATE_UNPROGRAMMED);
+	uint32_t chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES);
+	uint32_t chip_ctrl_default = 0;
+
+	/*
+	 * The override settings is required to allow the customer to program
+	 * the application specific keys into SOTP, before the conversion to
+	 * one of the AB modes.
+	 * At the end of write operation, the chip ctrl settings will restored
+	 * to the state prior to write call
+	 */
+	if (chip_state & chip_state_default) {
+		uint32_t chip_ctrl;
+
+		chip_ctrl_default = mmio_read_32(SOTP_CHIP_CTRL);
+		INFO("SOTP: enable special prog mode\n");
+
+		chip_ctrl = BIT(SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES) |
+			    BIT(SOTP_CHIP_CTRL_SW_MANU_PROG) |
+			    BIT(SOTP_CHIP_CTRL_SW_CID_PROG) |
+			    BIT(SOTP_CHIP_CTRL_SW_AB_DEVICE);
+		mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl);
+	}
+
+	/*  Check for FDONE status */
+	while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) !=
+	       BIT(SOTP_STATUS__FDONE))
+		;
+
+	/*  Enable OTP acces by CPU */
+	mmio_setbits_32(SOTP_PROG_CONTROL,
+			BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
+
+	if (addr > SOTP_DEVICE_SECURE_CFG3_ROW) {
+		if (sotp_add_ecc == 0) {
+			mmio_clrbits_32(SOTP_PROG_CONTROL,
+					BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
+		}
+		if (sotp_add_ecc == 1) {
+			mmio_setbits_32(SOTP_PROG_CONTROL,
+					BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
+		}
+	} else {
+		mmio_clrbits_32(SOTP_PROG_CONTROL,
+				BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
+	}
+
+	mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_ENABLE << 1));
+
+	/*
+	 * In order to avoid unintentional writes / programming of the OTP
+	 * array, the OTP Controller must be put into programming mode before
+	 * it will accept program commands. This is done by writing 0xF, 0x4,
+	 * 0x8, 0xD with program commands prior to starting the actual
+	 * programming sequence
+	 */
+	for (loop = 0; loop < 4; loop++) {
+		mmio_write_32(SOTP_WRDATA_0, prog_array[loop]);
+
+		/*
+		 * Start bit to tell SOTP to send command to the OTP controller
+		 */
+		mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
+
+		/*  Wait for SOTP command done to <-- be set */
+		while ((mmio_read_32(SOTP_STATUS_1) &
+			BIT(SOTP_STATUS_1__CMD_DONE)) !=
+		       BIT(SOTP_STATUS_1__CMD_DONE))
+			;
+
+		/* Command done is cleared w1c */
+		mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
+
+		/* Clr Start bit after command done */
+		mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
+	}
+
+	/*  Check for PROGOK */
+	while ((mmio_read_32(SOTP_STATUS_0) & 0x4) != BIT(SOTP_STATUS__PROGOK))
+		;
+
+	/* Set  10 bit row address */
+	mmio_write_32(SOTP_ADDR,
+		      ((addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R));
+
+	/* Set SOTP Row data */
+	mmio_write_32(SOTP_WRDATA_0, (wdata & SOTP_ROW_DATA_MASK));
+
+	/* Set SOTP ECC and error bits */
+	mmio_write_32(SOTP_WRDATA_1, ((wdata & SOTP_ECC_ERR_BITS_MASK) >> 32));
+
+	/* Set prog_word command */
+	mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_WORD << 1));
+
+	/*  Start bit to tell SOTP to send command to the OTP controller */
+	mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
+
+	/*  Wait for SOTP command done to be set */
+	while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) !=
+	       BIT(SOTP_STATUS_1__CMD_DONE))
+		;
+
+	/* Command done is cleared w1c */
+	mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
+
+	/* disable OTP acces by CPU */
+	mmio_clrbits_32(SOTP_PROG_CONTROL,
+			BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
+
+	/* Clr Start bit after command done */
+	mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
+
+	if (chip_state & chip_state_default)
+		mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl_default);
+
+#endif
+}
+
+int sotp_read_key(uint8_t *key, size_t keysize, int start_row, int end_row)
+{
+	int row;
+	uint32_t status = 0;
+	uint32_t status2 = 0xFFFFFFFF;
+	uint64_t row_data;
+	uint32_t data;
+	uint32_t *temp_key = (uint32_t *)key;
+
+	row = start_row;
+	while ((keysize > 0) && (row <= end_row)) {
+		row_data = sotp_mem_read(row, SOTP_ROW_ECC);
+		if (!(row_data & (SOTP_ECC_ERR_DETECT | SOTP_FAIL_BITS))) {
+			memcpy(temp_key++, &row_data, sizeof(uint32_t));
+			keysize -= sizeof(uint32_t);
+			data = (uint32_t)(row_data & SOTP_ROW_DATA_MASK);
+			status |= data;
+			status2 &= data;
+		}
+		row++;
+	}
+
+	if ((status2 == 0xFFFFFFFF) || (status == 0) || (row > end_row))
+		return -1;
+
+	return 0;
+}
+
+int sotp_key_erased(void)
+{
+	uint64_t row_data;
+	int status = 0;
+
+	row_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
+	if (row_data & SOTP_DEVICE_SECURE_CFG0_OTP_ERASED_MASK)
+		status = 1;
+
+	else if (mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES) &
+			SOTP_REGS_SOTP_CHIP_STATES_OTP_ERASED_MASK)
+		status = 1;
+
+	return status;
+}
+
+/*
+ * This function optimise the SOTP redundancy
+ * by considering the 00- zero and 01,10,11 - one
+ */
+uint32_t sotp_redundancy_reduction(uint32_t sotp_row_data)
+{
+	uint32_t opt_data;
+	uint32_t opt_loop;
+	uint32_t temp_data;
+
+	opt_data = 0;
+
+	for (opt_loop = 0; opt_loop < 16; opt_loop = opt_loop + 1) {
+		temp_data = ((sotp_row_data >> (opt_loop * 2)) & 0x3);
+
+		if (temp_data != 0x0)
+			opt_data = (opt_data | (1 << opt_loop));
+	}
+	return opt_data;
+}
diff --git a/drivers/brcm/spi/iproc_qspi.c b/drivers/brcm/spi/iproc_qspi.c
new file mode 100644
index 0000000..4c533d5
--- /dev/null
+++ b/drivers/brcm/spi/iproc_qspi.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <endian.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+#include <spi.h>
+
+#include "iproc_qspi.h"
+
+struct bcmspi_priv spi_cfg;
+
+/* Redefined by platform to force appropriate information */
+#pragma weak plat_spi_init
+int plat_spi_init(uint32_t *max_hz)
+{
+	return 0;
+}
+
+/* Initialize & setup iproc qspi controller */
+int iproc_qspi_setup(uint32_t bus, uint32_t cs, uint32_t max_hz, uint32_t mode)
+{
+	struct bcmspi_priv *priv = NULL;
+	uint32_t spbr;
+
+	priv = &spi_cfg;
+	priv->spi_mode = mode;
+	priv->state = QSPI_STATE_DISABLED;
+	priv->bspi_hw = QSPI_BSPI_MODE_REG_BASE;
+	priv->mspi_hw = QSPI_MSPI_MODE_REG_BASE;
+
+	/* Initialize clock and platform specific */
+	if (plat_spi_init(&max_hz) != 0)
+		return -1;
+
+	priv->max_hz = max_hz;
+
+	/* MSPI: Basic hardware initialization */
+	mmio_write_32(priv->mspi_hw + MSPI_SPCR1_LSB_REG, 0);
+	mmio_write_32(priv->mspi_hw + MSPI_SPCR1_MSB_REG, 0);
+	mmio_write_32(priv->mspi_hw + MSPI_NEWQP_REG, 0);
+	mmio_write_32(priv->mspi_hw + MSPI_ENDQP_REG, 0);
+	mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG, 0);
+
+	/* MSPI: SCK configuration */
+	spbr = (QSPI_AXI_CLK - 1) / (2 * priv->max_hz) + 1;
+	spbr = MIN(spbr, SPBR_DIV_MAX);
+	spbr = MAX(spbr, SPBR_DIV_MIN);
+	mmio_write_32(priv->mspi_hw + MSPI_SPCR0_LSB_REG, spbr);
+
+	/* MSPI: Mode configuration (8 bits by default) */
+	priv->mspi_16bit = 0;
+	mmio_write_32(priv->mspi_hw + MSPI_SPCR0_MSB_REG,
+		      BIT(MSPI_SPCR0_MSB_REG_MSTR_SHIFT) |		/* Master */
+		      MSPI_SPCR0_MSB_REG_16_BITS_PER_WD_SHIFT |		/* 16 bits per word */
+		      (priv->spi_mode & MSPI_SPCR0_MSB_REG_MODE_MASK));	/* mode: CPOL / CPHA */
+
+	/* Display bus info */
+	VERBOSE("SPI: SPCR0_LSB: 0x%x\n",
+		mmio_read_32(priv->mspi_hw + MSPI_SPCR0_LSB_REG));
+	VERBOSE("SPI: SPCR0_MSB: 0x%x\n",
+		mmio_read_32(priv->mspi_hw + MSPI_SPCR0_MSB_REG));
+	VERBOSE("SPI: SPCR1_LSB: 0x%x\n",
+		mmio_read_32(priv->mspi_hw + MSPI_SPCR1_LSB_REG));
+	VERBOSE("SPI: SPCR1_MSB: 0x%x\n",
+		mmio_read_32(priv->mspi_hw + MSPI_SPCR1_MSB_REG));
+	VERBOSE("SPI: SPCR2: 0x%x\n",
+		mmio_read_32(priv->mspi_hw + MSPI_SPCR2_REG));
+	VERBOSE("SPI: CLK: %d\n", priv->max_hz);
+
+	return 0;
+}
+
+void bcmspi_enable_bspi(struct bcmspi_priv *priv)
+{
+	if (priv->state != QSPI_STATE_BSPI) {
+		/* Switch to BSPI */
+		mmio_write_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG, 0);
+
+		priv->state = QSPI_STATE_BSPI;
+	}
+}
+
+static int bcmspi_disable_bspi(struct bcmspi_priv *priv)
+{
+	uint32_t retry;
+
+	if (priv->state == QSPI_STATE_MSPI)
+		return 0;
+
+	/* Switch to MSPI if not yet */
+	if ((mmio_read_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG) &
+	     MSPI_CTRL_MASK) == 0) {
+		retry = QSPI_RETRY_COUNT_US_MAX;
+		do {
+			if ((mmio_read_32(
+				priv->bspi_hw + BSPI_BUSY_STATUS_REG) &
+				BSPI_BUSY_MASK) == 0) {
+				mmio_write_32(priv->bspi_hw +
+				       BSPI_MAST_N_BOOT_CTRL_REG,
+				       MSPI_CTRL_MASK);
+				udelay(1);
+				break;
+			}
+			udelay(1);
+		} while (retry--);
+
+		if ((mmio_read_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG) &
+		     MSPI_CTRL_MASK) != MSPI_CTRL_MASK) {
+			ERROR("QSPI: Switching to QSPI error.\n");
+			return -1;
+		}
+	}
+
+	/* Update state */
+	priv->state = QSPI_STATE_MSPI;
+
+	return 0;
+}
+
+int iproc_qspi_claim_bus(void)
+{
+	struct bcmspi_priv *priv = &spi_cfg;
+
+	/* Switch to MSPI by default */
+	if (bcmspi_disable_bspi(priv) != 0)
+		return -1;
+
+	return 0;
+}
+
+void iproc_qspi_release_bus(void)
+{
+	struct bcmspi_priv *priv = &spi_cfg;
+
+	/* Switch to BSPI by default */
+	bcmspi_enable_bspi(priv);
+}
+
+static int mspi_xfer(struct bcmspi_priv *priv, uint32_t bytes,
+		     const uint8_t *tx, uint8_t *rx, uint32_t flag)
+{
+	uint32_t retry;
+	uint32_t mode = CDRAM_PCS0;
+
+	if (flag & SPI_XFER_QUAD) {
+		mode |= CDRAM_QUAD_MODE;
+		VERBOSE("SPI: QUAD mode\n");
+
+		if (!tx) {
+			VERBOSE("SPI: 4 lane input\n");
+			mode |= CDRAM_RBIT_INPUT;
+		}
+	}
+
+	/* Use 8-bit queue for odd-bytes transfer */
+	if (bytes & 1)
+		priv->mspi_16bit = 0;
+	else {
+		priv->mspi_16bit = 1;
+		mode |= CDRAM_BITS_EN;
+	}
+
+	while (bytes) {
+		uint32_t chunk;
+		uint32_t queues;
+		uint32_t i;
+
+		/* Separate code for 16bit and 8bit transfers for performance */
+		if (priv->mspi_16bit) {
+			VERBOSE("SPI: 16 bits xfer\n");
+			/* Determine how many bytes to process this time */
+			chunk = MIN(bytes, NUM_CDRAM_BYTES * 2);
+			queues = (chunk - 1) / 2 + 1;
+			bytes -= chunk;
+
+			/* Fill CDRAMs */
+			for (i = 0; i < queues; i++)
+				mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG +
+					      (i << 2), mode | CDRAM_CONT);
+
+			/* Fill TXRAMs */
+			for (i = 0; i < chunk; i++)
+				if (tx)
+					mmio_write_32(priv->mspi_hw +
+						MSPI_TXRAM_REG +
+						(i << 2), tx[i]);
+		} else {
+			VERBOSE("SPI: 8 bits xfer\n");
+			/* Determine how many bytes to process this time */
+			chunk = MIN(bytes, NUM_CDRAM_BYTES);
+			queues = chunk;
+			bytes -= chunk;
+
+			/* Fill CDRAMs and TXRAMS */
+			for (i = 0; i < chunk; i++) {
+				mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG +
+					      (i << 2), mode | CDRAM_CONT);
+				if (tx)
+					mmio_write_32(priv->mspi_hw +
+						MSPI_TXRAM_REG +
+						(i << 3), tx[i]);
+			}
+		}
+
+		/* Advance pointers */
+		if (tx)
+			tx += chunk;
+
+		/* Setup queue pointers */
+		mmio_write_32(priv->mspi_hw + MSPI_NEWQP_REG, 0);
+		mmio_write_32(priv->mspi_hw + MSPI_ENDQP_REG, queues - 1);
+
+		/* Remove CONT on the last byte command */
+		if (bytes == 0 && (flag & SPI_XFER_END))
+			mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG +
+				      ((queues - 1) << 2), mode);
+
+		/* Kick off */
+		mmio_write_32(priv->mspi_hw + MSPI_STATUS_REG, 0);
+		if (bytes == 0 && (flag & SPI_XFER_END))
+			mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG, MSPI_SPE);
+		else
+			mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG,
+				      MSPI_SPE | MSPI_CONT_AFTER_CMD);
+
+		/* Wait for completion */
+		retry = QSPI_RETRY_COUNT_US_MAX;
+		do {
+			if (mmio_read_32(priv->mspi_hw + MSPI_STATUS_REG) &
+			    MSPI_CMD_COMPLETE_MASK)
+				break;
+			udelay(1);
+		} while (retry--);
+
+		if ((mmio_read_32(priv->mspi_hw + MSPI_STATUS_REG) &
+		     MSPI_CMD_COMPLETE_MASK) == 0) {
+			ERROR("SPI: Completion timeout.\n");
+			return -1;
+		}
+
+		/* Read data out */
+		if (rx) {
+			if (priv->mspi_16bit) {
+				for (i = 0; i < chunk; i++) {
+					rx[i] = mmio_read_32(priv->mspi_hw +
+							MSPI_RXRAM_REG +
+						       (i << 2))
+						& 0xff;
+				}
+			} else {
+				for (i = 0; i < chunk; i++) {
+					rx[i] = mmio_read_32(priv->mspi_hw +
+						       MSPI_RXRAM_REG +
+						       (((i << 1) + 1) << 2))
+						& 0xff;
+				}
+			}
+			rx += chunk;
+		}
+	}
+
+	return 0;
+}
+
+int iproc_qspi_xfer(uint32_t bitlen,
+		    const void *dout, void *din, unsigned long flags)
+{
+	struct bcmspi_priv *priv;
+	const uint8_t *tx = dout;
+	uint8_t *rx = din;
+	uint32_t bytes = bitlen / 8;
+	int ret = 0;
+
+	priv = &spi_cfg;
+
+	if (priv->state == QSPI_STATE_DISABLED) {
+		ERROR("QSPI: state disabled\n");
+		return -1;
+	}
+
+	/* we can only do 8 bit transfers */
+	if (bitlen % 8) {
+		ERROR("QSPI: Only support 8 bit transfers (requested %d)\n",
+			bitlen);
+		return -1;
+	}
+
+	/* MSPI: Enable write lock at the beginning */
+	if (flags & SPI_XFER_BEGIN) {
+		/* Switch to MSPI if not yet */
+		if (bcmspi_disable_bspi(priv) != 0) {
+			ERROR("QSPI: Switch to MSPI failed\n");
+			return -1;
+		}
+
+		mmio_write_32(priv->mspi_hw + MSPI_WRITE_LOCK_REG, 1);
+	}
+
+	/* MSPI: Transfer it */
+	if (bytes)
+		ret = mspi_xfer(priv, bytes, tx, rx, flags);
+
+	/* MSPI: Disable write lock if it's done */
+	if (flags & SPI_XFER_END)
+		mmio_write_32(priv->mspi_hw + MSPI_WRITE_LOCK_REG, 0);
+
+	return ret;
+}
diff --git a/drivers/brcm/spi/iproc_qspi.h b/drivers/brcm/spi/iproc_qspi.h
new file mode 100644
index 0000000..7a8bd91
--- /dev/null
+++ b/drivers/brcm/spi/iproc_qspi.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IPROC_QSPI_H
+#define IPROC_QSPI_H
+
+#include <platform_def.h>
+
+/*SPI configuration enable*/
+#define IPROC_QSPI_CLK_SPEED	62500000
+#define SPI_CPHA		(1 << 0)
+#define SPI_CPOL		(1 << 1)
+#define IPROC_QSPI_MODE0	0
+#define IPROC_QSPI_MODE3	(SPI_CPOL|SPI_CPHA)
+
+#define IPROC_QSPI_BUS                   0
+#define IPROC_QSPI_CS                    0
+#define IPROC_QSPI_BASE_REG              QSPI_CTRL_BASE_ADDR
+#define IPROC_QSPI_CRU_CONTROL_REG       QSPI_CLK_CTRL
+
+#define QSPI_AXI_CLK                        200000000
+
+#define QSPI_RETRY_COUNT_US_MAX             200000
+
+/* Chip attributes */
+#define QSPI_REG_BASE			IPROC_QSPI_BASE_REG
+#define CRU_CONTROL_REG			IPROC_QSPI_CRU_CONTROL_REG
+#define SPBR_DIV_MIN			8U
+#define SPBR_DIV_MAX			255U
+#define NUM_CDRAM_BYTES			16U
+
+/* Register fields */
+#define MSPI_SPCR0_MSB_BITS_8		0x00000020
+
+/* Flash opcode and parameters */
+#define CDRAM_PCS0			2
+#define CDRAM_CONT			(1 << 7)
+#define CDRAM_BITS_EN			(1 << 6)
+#define CDRAM_QUAD_MODE			(1 << 8)
+#define CDRAM_RBIT_INPUT		(1 << 10)
+
+/* MSPI registers */
+#define QSPI_MSPI_MODE_REG_BASE		(QSPI_REG_BASE + 0x200)
+#define MSPI_SPCR0_LSB_REG		0x000
+#define MSPI_SPCR0_MSB_REG		0x004
+#define MSPI_SPCR1_LSB_REG		0x008
+#define MSPI_SPCR1_MSB_REG		0x00c
+#define MSPI_NEWQP_REG			0x010
+#define MSPI_ENDQP_REG			0x014
+#define MSPI_SPCR2_REG			0x018
+#define MSPI_STATUS_REG			0x020
+#define MSPI_CPTQP_REG			0x024
+#define MSPI_TXRAM_REG			0x040
+#define MSPI_RXRAM_REG			0x0c0
+#define MSPI_CDRAM_REG			0x140
+#define MSPI_WRITE_LOCK_REG		0x180
+#define MSPI_DISABLE_FLUSH_GEN_REG	0x184
+
+#define MSPI_SPCR0_MSB_REG_MSTR_SHIFT		7
+#define MSPI_SPCR0_MSB_REG_16_BITS_PER_WD_SHIFT	(0 << 2)
+#define MSPI_SPCR0_MSB_REG_MODE_MASK		0x3
+
+/* BSPI registers */
+#define QSPI_BSPI_MODE_REG_BASE		QSPI_REG_BASE
+#define BSPI_MAST_N_BOOT_CTRL_REG	0x008
+#define BSPI_BUSY_STATUS_REG		0x00c
+
+#define MSPI_CMD_COMPLETE_MASK		1
+#define BSPI_BUSY_MASK			1
+#define MSPI_CTRL_MASK			1
+
+#define MSPI_SPE			(1 << 6)
+#define MSPI_CONT_AFTER_CMD		(1 << 7)
+
+/* State */
+enum bcm_qspi_state {
+	QSPI_STATE_DISABLED,
+	QSPI_STATE_MSPI,
+	QSPI_STATE_BSPI
+};
+
+/* QSPI private data */
+struct bcmspi_priv {
+	/* Specified SPI parameters */
+	uint32_t max_hz;
+	uint32_t spi_mode;
+
+	/* State */
+	enum bcm_qspi_state state;
+	int mspi_16bit;
+
+	/* Registers */
+	uintptr_t mspi_hw;
+	uintptr_t bspi_hw;
+};
+
+int iproc_qspi_setup(uint32_t bus, uint32_t cs,
+		     uint32_t max_hz, uint32_t mode);
+int iproc_qspi_claim_bus(void);
+void iproc_qspi_release_bus(void);
+int iproc_qspi_xfer(uint32_t bitlen, const void *dout,
+		    void *din, unsigned long flags);
+
+#endif	/* _IPROC_QSPI_H_ */
diff --git a/drivers/brcm/spi/iproc_spi.c b/drivers/brcm/spi/iproc_spi.c
new file mode 100644
index 0000000..551e587
--- /dev/null
+++ b/drivers/brcm/spi/iproc_spi.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <spi.h>
+
+#include "iproc_qspi.h"
+
+int spi_init(void)
+{
+	return iproc_qspi_setup(IPROC_QSPI_BUS, IPROC_QSPI_CS,
+				IPROC_QSPI_CLK_SPEED, IPROC_QSPI_MODE0);
+}
+
+int spi_claim_bus(void)
+{
+	return iproc_qspi_claim_bus();
+}
+
+void spi_release_bus(void)
+{
+	iproc_qspi_release_bus();
+}
+
+int spi_xfer(uint32_t bitlen, const void *dout,
+	     void *din, uint32_t flags)
+{
+	return iproc_qspi_xfer(bitlen, dout, din, flags);
+}
diff --git a/drivers/brcm/spi_flash.c b/drivers/brcm/spi_flash.c
new file mode 100644
index 0000000..336d230
--- /dev/null
+++ b/drivers/brcm/spi_flash.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+
+#include <sf.h>
+#include <spi.h>
+
+#define SPI_FLASH_CMD_LEN	4
+#define QSPI_WAIT_TIMEOUT_US	200000U /* usec */
+
+#define FINFO(jedec_id, ext_id, _sector_size, _n_sectors, _page_size, _flags) \
+		.id = {							\
+			((jedec_id) >> 16) & 0xff,			\
+			((jedec_id) >> 8) & 0xff,			\
+			(jedec_id) & 0xff,				\
+			((ext_id) >> 8) & 0xff,				\
+			(ext_id) & 0xff,				\
+			},						\
+		.id_len = (!(jedec_id) ? 0 : (3 + ((ext_id) ? 2 : 0))),	\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = _page_size,				\
+		.flags = (_flags),
+
+/* SPI/QSPI flash device params structure */
+const struct spi_flash_info spi_flash_ids[] = {
+	{"W25Q64CV", FINFO(0xef4017, 0x0, 64 * 1024, 128, 256, WR_QPP | SECT_4K)},
+	{"W25Q64DW", FINFO(0xef6017, 0x0, 64 * 1024, 128, 256, WR_QPP | SECT_4K)},
+	{"W25Q32",   FINFO(0xef4016, 0x0, 64 * 1024, 64,  256, SECT_4K)},
+	{"MX25l3205D",  FINFO(0xc22016, 0x0, 64 * 1024, 64, 256, SECT_4K)},
+};
+
+static void spi_flash_addr(uint32_t addr, uint8_t *cmd)
+{
+	/*
+	 * cmd[0] holds a SPI Flash command, stored earlier
+	 * cmd[1/2/3] holds 24bit flash address
+	 */
+	cmd[1] = addr >> 16;
+	cmd[2] = addr >> 8;
+	cmd[3] = addr >> 0;
+}
+
+static const struct spi_flash_info *spi_flash_read_id(void)
+{
+	const struct spi_flash_info *info;
+	uint8_t id[SPI_FLASH_MAX_ID_LEN];
+	int ret;
+
+	ret = spi_flash_cmd(CMD_READ_ID, id, SPI_FLASH_MAX_ID_LEN);
+	if (ret < 0) {
+		ERROR("SF: Error %d reading JEDEC ID\n", ret);
+		return NULL;
+	}
+
+	for (info = spi_flash_ids; info->name != NULL; info++) {
+		if (info->id_len) {
+			if (!memcmp(info->id, id, info->id_len))
+				return info;
+		}
+	}
+
+	printf("SF: unrecognized JEDEC id bytes: %02x, %02x, %02x\n",
+	       id[0], id[1], id[2]);
+	return NULL;
+}
+
+/* Enable writing on the SPI flash */
+static inline int spi_flash_cmd_write_enable(struct spi_flash *flash)
+{
+	return spi_flash_cmd(CMD_WRITE_ENABLE, NULL, 0);
+}
+
+static int spi_flash_cmd_wait(struct spi_flash *flash)
+{
+	uint8_t cmd;
+	uint32_t i;
+	uint8_t status;
+	int ret;
+
+	i = 0;
+	while (1) {
+		cmd = CMD_RDSR;
+		ret = spi_flash_cmd_read(&cmd, 1, &status, 1);
+		if (ret < 0) {
+			ERROR("SF: cmd wait failed\n");
+			break;
+		}
+		if (!(status & STATUS_WIP))
+			break;
+
+		i++;
+		if (i >= QSPI_WAIT_TIMEOUT_US) {
+			ERROR("SF: cmd wait timeout\n");
+			ret = -1;
+			break;
+		}
+		udelay(1);
+	}
+
+	return ret;
+}
+
+static int spi_flash_write_common(struct spi_flash *flash, const uint8_t *cmd,
+				  size_t cmd_len, const void *buf,
+				  size_t buf_len)
+{
+	int ret;
+
+	ret = spi_flash_cmd_write_enable(flash);
+	if (ret < 0) {
+		ERROR("SF: enabling write failed\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_write(cmd, cmd_len, buf, buf_len);
+	if (ret < 0) {
+		ERROR("SF: write cmd failed\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_wait(flash);
+	if (ret < 0) {
+		ERROR("SF: write timed out\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int spi_flash_read_common(const uint8_t *cmd, size_t cmd_len,
+				 void *data, size_t data_len)
+{
+	int ret;
+
+	ret = spi_flash_cmd_read(cmd, cmd_len, data, data_len);
+	if (ret < 0) {
+		ERROR("SF: read cmd failed\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+int spi_flash_read(struct spi_flash *flash, uint32_t offset,
+		   uint32_t len, void *data)
+{
+	uint32_t read_len = 0, read_addr;
+	uint8_t cmd[SPI_FLASH_CMD_LEN];
+	int ret;
+
+	ret = spi_claim_bus();
+	if (ret) {
+		ERROR("SF: unable to claim SPI bus\n");
+		return ret;
+	}
+
+	cmd[0] = CMD_READ_NORMAL;
+	while (len) {
+		read_addr = offset;
+		read_len = MIN(flash->page_size, (len - read_len));
+		spi_flash_addr(read_addr, cmd);
+
+		ret = spi_flash_read_common(cmd, sizeof(cmd), data, read_len);
+		if (ret < 0) {
+			ERROR("SF: read failed\n");
+			break;
+		}
+
+		offset += read_len;
+		len -= read_len;
+		data += read_len;
+	}
+	SPI_DEBUG("SF read done\n");
+
+	spi_release_bus();
+	return ret;
+}
+
+int spi_flash_write(struct spi_flash *flash, uint32_t offset,
+		    uint32_t len, void *buf)
+{
+	unsigned long byte_addr, page_size;
+	uint8_t cmd[SPI_FLASH_CMD_LEN];
+	uint32_t chunk_len, actual;
+	uint32_t write_addr;
+	int ret;
+
+	ret = spi_claim_bus();
+	if (ret) {
+		ERROR("SF: unable to claim SPI bus\n");
+		return ret;
+	}
+
+	page_size = flash->page_size;
+
+	cmd[0] = flash->write_cmd;
+	for (actual = 0; actual < len; actual += chunk_len) {
+		write_addr = offset;
+		byte_addr = offset % page_size;
+		chunk_len = MIN(len - actual,
+				(uint32_t)(page_size - byte_addr));
+		spi_flash_addr(write_addr, cmd);
+
+		SPI_DEBUG("SF:0x%p=>cmd:{0x%02x 0x%02x%02x%02x} chunk_len:%d\n",
+			  buf + actual, cmd[0], cmd[1],
+			  cmd[2], cmd[3], chunk_len);
+
+		ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
+					     buf + actual, chunk_len);
+		if (ret < 0) {
+			ERROR("SF: write cmd failed\n");
+			break;
+		}
+
+		offset += chunk_len;
+	}
+	SPI_DEBUG("SF write done\n");
+
+	spi_release_bus();
+	return ret;
+}
+
+int spi_flash_erase(struct spi_flash *flash, uint32_t offset, uint32_t len)
+{
+	uint8_t cmd[SPI_FLASH_CMD_LEN];
+	uint32_t erase_size, erase_addr;
+	int ret;
+
+	erase_size = flash->erase_size;
+
+	if (offset % erase_size || len % erase_size) {
+		ERROR("SF: Erase offset/length not multiple of erase size\n");
+		return -1;
+	}
+
+	ret = spi_claim_bus();
+	if (ret) {
+		ERROR("SF: unable to claim SPI bus\n");
+		return ret;
+	}
+
+	cmd[0] = flash->erase_cmd;
+	while (len) {
+		erase_addr = offset;
+		spi_flash_addr(erase_addr, cmd);
+
+		SPI_DEBUG("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
+			cmd[2], cmd[3], erase_addr);
+
+		ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
+		if (ret < 0) {
+			ERROR("SF: erase failed\n");
+			break;
+		}
+
+		offset += erase_size;
+		len -= erase_size;
+	}
+	SPI_DEBUG("sf erase done\n");
+
+	spi_release_bus();
+	return ret;
+}
+
+int spi_flash_probe(struct spi_flash *flash)
+{
+	const struct spi_flash_info *info = NULL;
+	int ret;
+
+	ret = spi_claim_bus();
+	if (ret) {
+		ERROR("SF: Unable to claim SPI bus\n");
+		ERROR("SF: probe failed\n");
+		return ret;
+	}
+
+	info = spi_flash_read_id();
+	if (!info)
+		goto probe_fail;
+
+	INFO("Flash Name: %s sectors %x, sec size %x\n",
+	     info->name, info->n_sectors,
+	     info->sector_size);
+	flash->size = info->n_sectors * info->sector_size;
+	flash->sector_size = info->sector_size;
+	flash->page_size = info->page_size;
+	flash->flags = info->flags;
+
+	flash->read_cmd = CMD_READ_NORMAL;
+	flash->write_cmd = CMD_PAGE_PROGRAM;
+	flash->erase_cmd = CMD_ERASE_64K;
+	flash->erase_size = ERASE_SIZE_64K;
+
+probe_fail:
+	spi_release_bus();
+	return ret;
+}
diff --git a/drivers/brcm/spi_sf.c b/drivers/brcm/spi_sf.c
new file mode 100644
index 0000000..8bbb09f
--- /dev/null
+++ b/drivers/brcm/spi_sf.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+
+#include <spi.h>
+
+#define BITS_PER_BYTE		8
+#define CMD_LEN1		1
+
+static int spi_flash_read_write(const uint8_t *cmd,
+				size_t cmd_len,
+				const uint8_t *data_out,
+				uint8_t *data_in,
+				size_t data_len)
+{
+	unsigned long flags = SPI_XFER_BEGIN;
+	int ret;
+
+	if (data_len == 0)
+		flags |= SPI_XFER_END;
+
+	ret = spi_xfer(cmd_len * BITS_PER_BYTE, cmd, NULL, flags);
+	if (ret) {
+		ERROR("SF: Failed to send command (%zu bytes): %d\n",
+		      cmd_len, ret);
+	} else if (data_len != 0) {
+		ret = spi_xfer(data_len * BITS_PER_BYTE, data_out,
+			       data_in, SPI_XFER_END);
+		if (ret)
+			ERROR("SF: Failed to transfer %zu bytes of data: %d\n",
+			      data_len, ret);
+	}
+
+	return ret;
+}
+
+int spi_flash_cmd_read(const uint8_t *cmd,
+		       size_t cmd_len,
+		       void *data,
+		       size_t data_len)
+{
+	return spi_flash_read_write(cmd, cmd_len, NULL, data, data_len);
+}
+
+int spi_flash_cmd(uint8_t cmd, void *response, size_t len)
+{
+	return spi_flash_cmd_read(&cmd, CMD_LEN1, response, len);
+}
+
+int spi_flash_cmd_write(const uint8_t *cmd,
+			size_t cmd_len,
+			const void *data,
+			size_t data_len)
+{
+	return spi_flash_read_write(cmd, cmd_len, data, NULL, data_len);
+}
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 5d49fff..02f85d6 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,6 +46,7 @@
  */
 typedef struct {
 	uintptr_t dev_spec;
+	uint16_t plat_toc_flag;
 } fip_dev_state_t;
 
 static const uuid_t uuid_null;
@@ -220,6 +221,11 @@
 	uintptr_t backend_handle;
 	fip_toc_header_t header;
 	size_t bytes_read;
+	fip_dev_state_t *state;
+
+	assert(dev_info != NULL);
+
+	state = (fip_dev_state_t *)dev_info->info;
 
 	/* Obtain a reference to the image by querying the platform layer */
 	result = plat_get_image_source(image_id, &backend_dev_handle,
@@ -248,6 +254,11 @@
 			result = -ENOENT;
 		} else {
 			VERBOSE("FIP header looks OK.\n");
+			/*
+			 * Store 16-bit Platform ToC flags field which occupies
+			 * bits [32-47] in fip header.
+			 */
+			state->plat_toc_flag = (header.flags >> 32) & 0xffff;
 		}
 	}
 
@@ -453,3 +464,17 @@
 
 	return result;
 }
+
+/* Function to retrieve plat_toc_flags, previously saved in FIP dev */
+int fip_dev_get_plat_toc_flag(io_dev_info_t *dev_info, uint16_t *plat_toc_flag)
+{
+	fip_dev_state_t *state;
+
+	assert(dev_info != NULL);
+
+	state = (fip_dev_state_t *)dev_info->info;
+
+	*plat_toc_flag =  state->plat_toc_flag;
+
+	return 0;
+}
diff --git a/include/drivers/auth/auth_mod.h b/include/drivers/auth/auth_mod.h
index 6c48124..1dc9ff4 100644
--- a/include/drivers/auth/auth_mod.h
+++ b/include/drivers/auth/auth_mod.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,8 @@
 #include <drivers/auth/auth_common.h>
 #include <drivers/auth/img_parser_mod.h>
 
+#include <lib/utils_def.h>
+
 /*
  * Image flags
  */
@@ -41,9 +43,11 @@
 /* Macro to register a CoT defined as an array of auth_img_desc_t pointers */
 #define REGISTER_COT(_cot) \
 	const auth_img_desc_t *const *const cot_desc_ptr = (_cot); \
+	const size_t cot_desc_size = ARRAY_SIZE(_cot);		   \
 	unsigned int auth_img_flags[MAX_NUMBER_IDS]
 
 extern const auth_img_desc_t *const *const cot_desc_ptr;
+extern const size_t cot_desc_size;
 extern unsigned int auth_img_flags[MAX_NUMBER_IDS];
 
 #endif /* TRUSTED_BOARD_BOOT */
diff --git a/include/drivers/brcm/chimp.h b/include/drivers/brcm/chimp.h
new file mode 100644
index 0000000..02d528b
--- /dev/null
+++ b/include/drivers/brcm/chimp.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SR_CHIMP_H
+#define SR_CHIMP_H
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define CHIMP_WINDOW_SIZE 0x400000
+#define CHIMP_ERROR_OFFSET 28
+#define CHIMP_ERROR_MASK 0xf0000000
+
+#ifndef EMULATION_SETUP
+#define CHIMP_HANDSHAKE_TIMEOUT_MS 10000
+#else
+/*
+ * 1hr timeout for test in emulator
+ * By doing this ChiMP is given a chance to boot
+ * fully from the QSPI
+ * (on Palladium this takes upto 50 min depending on QSPI clk)
+ */
+
+#define CHIMP_HANDSHAKE_TIMEOUT_MS 3600000
+#endif
+
+#define CHIMP_BPE_MODE_ID_PATTERN				(0x25000000)
+#define CHIMP_BPE_MODE_ID_MASK					(0x7f000000)
+#define NIC_RESET_RELEASE_TIMEOUT_US		(10)
+
+/* written by M0, used by ChiMP ROM */
+#define SR_IN_SMARTNIC_MODE_BIT					0
+/* written by M0, used by ChiMP ROM */
+#define SR_CHIMP_SECURE_BOOT_BIT				1
+/* cleared by AP, set by ChiMP BC2 code */
+#define SR_FLASH_ACCESS_DONE_BIT				2
+
+#ifdef USE_CHIMP
+void bcm_chimp_write(uintptr_t addr, uint32_t value);
+uint32_t bcm_chimp_read(uintptr_t addr);
+uint32_t bcm_chimp_read_ctrl(uint32_t offset);
+void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits);
+void bcm_chimp_setbits(uintptr_t addr, uint32_t bits);
+int bcm_chimp_is_nic_mode(void);
+void bcm_chimp_fru_prog_done(bool status);
+int bcm_chimp_handshake_done(void);
+int bcm_chimp_wait_handshake(void);
+/* Fastboot-related*/
+int bcm_chimp_initiate_fastboot(int fastboot_type);
+#else
+static inline void bcm_chimp_write(uintptr_t addr, uint32_t value)
+{
+}
+static inline uint32_t bcm_chimp_read(uintptr_t addr)
+{
+	return 0;
+}
+static inline uint32_t bcm_chimp_read_ctrl(uint32_t offset)
+{
+	return 0;
+}
+static inline void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits)
+{
+}
+static inline void bcm_chimp_setbits(uintptr_t addr, uint32_t bits)
+{
+}
+static inline int bcm_chimp_is_nic_mode(void)
+{
+	return 0;
+}
+static inline void bcm_chimp_fru_prog_done(bool status)
+{
+}
+static inline int bcm_chimp_handshake_done(void)
+{
+	return 0;
+}
+static inline int bcm_chimp_wait_handshake(void)
+{
+	return 0;
+}
+static inline int bcm_chimp_initiate_fastboot(int fastboot_type)
+{
+	return 0;
+}
+#endif /* USE_CHIMP */
+#endif
diff --git a/include/drivers/brcm/chimp_nv_defs.h b/include/drivers/brcm/chimp_nv_defs.h
new file mode 100644
index 0000000..9be361f
--- /dev/null
+++ b/include/drivers/brcm/chimp_nv_defs.h
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BNXNVM_DEFS_H
+#define BNXNVM_DEFS_H
+
+#if defined(__GNUC__)
+	#define PACKED_STRUCT __packed
+#else /* non-GCC compiler */
+
+#ifndef DOS_DRIVERS
+		#pragma pack(push)
+		#pragma pack(1)
+#endif
+		#define PACKED_STRUCT
+#endif
+
+typedef uint32_t u32_t;
+typedef uint8_t u8_t;
+typedef uint16_t u16_t;
+
+#define BNXNVM_DEFAULT_BLOCK_SIZE		4096
+#define BNXNVM_UNUSED_BYTE_VALUE		0xff
+
+#define NV_MAX_BLOCK_SIZE		16384
+
+#define BITS_PER_BYTE		(8)
+#define SIZEOF_IN_BITS(x)	(sizeof(x)*BITS_PER_BYTE)
+
+/************************/
+/* byte-swapping macros */
+/************************/
+#define BYTE_SWAP_16(x)	\
+	((((u16_t)(x) & 0xff00) >> 8) | \
+	(((u16_t)(x) & 0x00ff) << 8))
+#define BYTE_SWAP_32(x)	\
+	((((u32_t)(x) & 0xff000000) >> 24) | \
+	(((u32_t)(x) & 0x00ff0000) >> 8)   | \
+	(((u32_t)(x) & 0x0000ff00) << 8)   | \
+	(((u32_t)(x) & 0x000000ff) << 24))
+
+/* auto-detect integer size */
+#define BYTE_SWAP_INT(x)	\
+	(SIZEOF_IN_BITS(x) == 16 ? BYTE_SWAP_16(x) : \
+		SIZEOF_IN_BITS(x) == 32 ? BYTE_SWAP_32(x) : (x))
+
+/********************************/
+/* Architecture-specific macros */
+/********************************/
+#ifdef __BIG_ENDIAN__	/* e.g. Motorola */
+
+	#define BE_INT16(x)		(x)
+	#define BE_INT32(x)		(x)
+	#define BE_INT(x)		(x)
+	#define LE_INT16(x)		BYTE_SWAP_16(x)
+	#define LE_INT32(x)		BYTE_SWAP_32(x)
+	#define LE_INT(x)		BYTE_SWAP_INT(x)
+
+#else	/* Little Endian (e.g. Intel) */
+
+	#define LE_INT16(x)		(x)
+	#define LE_INT32(x)		(x)
+	#define LE_INT(x)		(x)
+	#define BE_INT16(x)		BYTE_SWAP_16(x)
+	#define BE_INT32(x)		BYTE_SWAP_32(x)
+	#define BE_INT(x)		BYTE_SWAP_INT(x)
+
+#endif
+
+
+enum {
+	NV_OK = 0,
+	NV_NOT_NVRAM,
+	NV_BAD_MB,
+	NV_BAD_DIR_HEADER,
+	NV_BAD_DIR_ENTRY,
+	NV_FW_NOT_FOUND,
+};
+
+typedef struct {
+#define BNXNVM_MASTER_BLOCK_SIG	BE_INT32(0x424E5834)	/*"BNX4"*/
+	/* Signature*/
+	u32_t    sig;
+	/* Length of Master Block Header, in bytes [32] */
+	u32_t    length;
+	/* Block size, in bytes [4096] */
+	u32_t    block_size;
+	/* Byte-offset to Directory Block (translated) */
+	u32_t    directory_offset;
+	/* Byte-offset to Block Redirection Table (non-translated) */
+	u32_t    redirect_offset;
+	/* Size, in bytes of Reserved Blocks region (at end of NVRAM) */
+	u32_t    reserved_size;
+	/*
+	 * Size of NVRAM (in bytes) - may be used to
+	 * override auto-detected size
+	 */
+	u32_t    nvram_size;
+	/* CRC-32 (IEEE 802.3 compatible) of the above */
+	u32_t    chksum;
+} PACKED_STRUCT bnxnvm_master_block_header_t;
+
+typedef struct {
+#define BNXNVM_DIRECTORY_BLOCK_SIG BE_INT32(0x44697230)	/* "Dir0" */
+	/* Signature */
+	u32_t    sig;
+	/* Length of Directory Header, in bytes [16] */
+	u32_t    length;
+	/* Number of Directory Entries */
+	u32_t    entries;
+	/* Length of each Directory Entry, in bytes [24] */
+	u32_t    entry_length;
+} PACKED_STRUCT bnxnvm_directory_block_header_t;
+
+typedef struct {
+	/* Directory Entry Type (see enum bnxnvm_directory_type) */
+	u16_t    type;
+	/* Instance of this Directory Entry type (0-based) */
+	u16_t    ordinal;
+	/*
+	 * Directory Entry Extension flags used to identify
+	 * secondary instances of a type:ordinal combinations
+	 */
+	u16_t    ext;
+	/* Directory Entry Attribute flags used to describe the item contents */
+	u16_t    attr;
+	/* Item location in NVRAM specified as offset (in bytes) */
+	u32_t	 item_location;
+	/*
+	 * Length of NVRAM item in bytes
+	 * (including padding - multiple of block size)
+	 */
+	u32_t    item_length;
+	/* Length of item data in bytes (excluding padding) */
+	u32_t    data_length;
+	/*
+	 * CRC-32 (IEEE 802.3 compatible) of item data
+	 * (excluding padding) (optional)
+	 */
+	u32_t    data_chksum;
+} PACKED_STRUCT bnxnvm_directory_entry_t;
+
+enum bnxnvm_version_format {
+	/* US-ASCII string (not necessarily null-terminated) */
+	BNX_VERSION_FMT_ASCII				= 0,
+	/* Each field 16-bits, displayed as unpadded decimal (e.g. "1.2.3.4") */
+	BNX_VERSION_FMT_DEC				= 1,
+	/* A single hexadecimal value, up to 64-bits (no dots) */
+	BNX_VERSION_FMT_HEX				= 2,
+	/* Multiple version values (three 8-bit version fields) */
+	BNX_VERSION_FMT_MULTI				= 3
+};
+
+/* This structure definition must not change: */
+typedef struct {
+	u16_t	flags; /* bit-flags (defaults to 0x0000) */
+	u8_t	version_format; /* enum bnxnvm_version_format */
+	u8_t	version_length; /* in bytes */
+	u8_t	version[16];		/* version value */
+	u16_t	dir_type;		/* enum bnxnvm_directory_type */
+	/* size of the entire trailer (to locate end of component data) */
+	u16_t	trailer_length;
+#define BNXNVM_COMPONENT_TRAILER_SIG BE_INT32(0x54726c72)	/* "Trlr" */
+	u32_t	sig;
+	u32_t	chksum;	/* CRC-32 of all bytes to this point */
+} PACKED_STRUCT bnxnvm_component_trailer_base_t;
+
+typedef struct {
+	/*
+	 * new trailer members (e.g. digital signature)
+	 * go here (insert at top):
+	 */
+	u8_t rsa_sig[256]; /* 2048-bit RSA-encrypted SHA-256 hash */
+	bnxnvm_component_trailer_base_t	base;
+} PACKED_STRUCT bnxnvm_component_trailer_t;
+
+#define BNX_MAX_LEN_DIR_NAME		12
+#define BNX_MAX_LEN_DIR_DESC		50
+/*********************************************************
+ * NVRAM Directory Entry/Item Types, Names, and Descriptions
+ *
+ * If you see a name or description that needs improvement,
+ * please correct it or raise for discussion.
+ * When adding a new directory type, it would be appreciated
+ * if you also updated ../../libs/nvm/bnxt_nvm_str.c.
+ * DIR_NAME macros may contain up to 12 alpha-numeric
+ * US-ASCII characters only, camelCase is preferred for clarity.
+ * DIR_DESC macros may contain up to 50 US-ASCII characters
+ * providing a verbose description of the directory type.
+ */
+enum bnxnvm_directory_type {
+	/* 0x00 Unused directory entry, available for use */
+		BNX_DIR_TYPE_UNUSED				= 0,
+#define BNX_DIR_NAME_UNUSED				"unused"
+#define BNX_DIR_DESC_UNUSED				"Deleted directory entry, available for reuse"
+	/* 0x01 Package installation log */
+	BNX_DIR_TYPE_PKG_LOG			= 1,
+#define BNX_DIR_NAME_PKG_LOG			"pkgLog"
+#define BNX_DIR_DESC_PKG_LOG			"Package Installation Log"
+	BNX_DIR_TYPE_CHIMP_PATCH        = 3,
+#define BNX_DIR_NAME_CHIMP_PATCH		"chimpPatch"
+#define BNX_DIR_DESC_CHIMP_PATCH		"ChiMP Patch Firmware"
+	/* 0x04 ChiMP firmware: Boot Code phase 1 */
+	BNX_DIR_TYPE_BOOTCODE			= 4,
+#define BNX_DIR_NAME_BOOTCODE			"chimpBoot"
+#define BNX_DIR_DESC_BOOTCODE			"Chip Management Processor Boot Firmware"
+	/* 0x05 VPD data block */
+	BNX_DIR_TYPE_VPD				= 5,
+#define BNX_DIR_NAME_VPD				"VPD"
+#define BNX_DIR_DESC_VPD				"Vital Product Data"
+	/* 0x06 Exp ROM MBA */
+	BNX_DIR_TYPE_EXP_ROM_MBA		= 6,
+#define BNX_DIR_NAME_EXP_ROM_MBA		"MBA"
+#define BNX_DIR_DESC_EXP_ROM_MBA		"Multiple Boot Agent Expansion ROM"
+	BNX_DIR_TYPE_AVS		= 7,	/* 0x07 AVS FW */
+#define BNX_DIR_NAME_AVS				"AVS"
+#define BNX_DIR_DESC_AVS				"Adaptive Voltage Scaling Firmware"
+	BNX_DIR_TYPE_PCIE	= 8,	/* 0x08 PCIE FW */
+#define BNX_DIR_NAME_PCIE				"PCIEucode"
+#define BNX_DIR_DESC_PCIE				"PCIe Microcode"
+	BNX_DIR_TYPE_PORT_MACRO			= 9,	/* 0x09 PORT MACRO FW */
+#define BNX_DIR_NAME_PORT_MACRO			"portMacro"
+#define BNX_DIR_DESC_PORT_MACRO			"Port Macro Firmware"
+	BNX_DIR_TYPE_APE_FW		= 10,		/* 0x0A APE Firmware */
+#define BNX_DIR_NAME_APE_FW				"apeFW"
+#define BNX_DIR_DESC_APE_FW			"Application Processing Engine Firmware"
+	/* 0x0B Patch firmware executed by APE ROM */
+	BNX_DIR_TYPE_APE_PATCH		= 11,
+#define BNX_DIR_NAME_APE_PATCH			"apePatch"
+#define BNX_DIR_DESC_APE_PATCH			"APE Patch Firmware"
+	BNX_DIR_TYPE_KONG_FW		= 12,	/* 0x0C Kong Firmware */
+#define BNX_DIR_NAME_KONG_FW		"kongFW"
+#define BNX_DIR_DESC_KONG_FW		"Kong Firmware"
+	/* 0x0D Patch firmware executed by Kong ROM */
+	BNX_DIR_TYPE_KONG_PATCH		= 13,
+#define BNX_DIR_NAME_KONG_PATCH			"kongPatch"
+#define BNX_DIR_DESC_KONG_PATCH			"Kong Patch Firmware"
+	BNX_DIR_TYPE_BONO_FW		= 14,	/* 0x0E Bono Firmware */
+#define BNX_DIR_NAME_BONO_FW		"bonoFW"
+#define BNX_DIR_DESC_BONO_FW		"Bono Firmware"
+	/* 0x0F Patch firmware executed by Bono ROM */
+	BNX_DIR_TYPE_BONO_PATCH		= 15,
+#define BNX_DIR_NAME_BONO_PATCH			"bonoPatch"
+#define BNX_DIR_DESC_BONO_PATCH			"Bono Patch Firmware"
+	BNX_DIR_TYPE_TANG_FW		= 16,	/* 0x10 Tang firmware */
+#define BNX_DIR_NAME_TANG_FW			"tangFW"
+#define BNX_DIR_DESC_TANG_FW			"Tang Firmware"
+	/* 0x11 Patch firmware executed by Tang ROM */
+	BNX_DIR_TYPE_TANG_PATCH		= 17,
+#define BNX_DIR_NAME_TANG_PATCH			"tangPatch"
+#define BNX_DIR_DESC_TANG_PATCH			"Tang Patch Firmware"
+	/* 0x12 ChiMP firmware: Boot Code phase 2 (loaded by phase 1) */
+	BNX_DIR_TYPE_BOOTCODE_2		= 18,
+#define BNX_DIR_NAME_BOOTCODE_2			"chimpHWRM"
+#define BNX_DIR_DESC_BOOTCODE_2			"ChiMP Hardware Resource Manager Firmware"
+	BNX_DIR_TYPE_CCM	= 19,	/* 0x13 CCM ROM binary */
+#define	BNX_DIR_NAME_CCM	"CCM"
+#define BNX_DIR_DESC_CCM	"Comprehensive Configuration Management"
+	/* 0x14 PCI-IDs, PCI-related configuration properties */
+	BNX_DIR_TYPE_PCI_CFG	= 20,
+#define BNX_DIR_NAME_PCI_CFG		"pciCFG"
+#define BNX_DIR_DESC_PCI_CFG		"PCIe Configuration Data"
+
+	BNX_DIR_TYPE_TSCF_UCODE		= 21,	/* 0x15 TSCF micro-code */
+#define BNX_DIR_NAME_TSCF_UCODE		"PHYucode"
+#define BNX_DIR_DESC_TSCF_UCODE		"Falcon PHY Microcode"
+	BNX_DIR_TYPE_ISCSI_BOOT		= 22,	/* 0x16 iSCSI Boot */
+#define BNX_DIR_NAME_ISCSI_BOOT			"iSCSIboot"
+#define BNX_DIR_DESC_ISCSI_BOOT			"iSCSI Boot Software Initiator"
+	/* 0x18 iSCSI Boot IPV6 - ***DEPRECATED*** */
+	BNX_DIR_TYPE_ISCSI_BOOT_IPV6	= 24,
+	/* 0x19 iSCSI Boot IPV4N6 - ***DEPRECATED*** */
+	BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6	= 25,
+	BNX_DIR_TYPE_ISCSI_BOOT_CFG	= 26,	/* 0x1a iSCSI Boot CFG v6 */
+#define BNX_DIR_NAME_ISCSI_BOOT_CFG		"iSCSIcfg"
+#define BNX_DIR_DESC_ISCSI_BOOT_CFG		"iSCSI Boot Configuration Data"
+	BNX_DIR_TYPE_EXT_PHY		= 27,	/* 0x1b External PHY FW */
+#define BNX_DIR_NAME_EXT_PHY			"extPHYfw"
+#define BNX_DIR_DESC_EXT_PHY			"External PHY Firmware"
+	BNX_DIR_TYPE_MODULES_PN	= 28,	/* 0x1c Modules PartNum list */
+#define BNX_DIR_NAME_MODULES_PN			"modPartNums"
+#define BNX_DIR_DESC_MODULES_PN			"Optical Modules Part Number List"
+	BNX_DIR_TYPE_SHARED_CFG	= 40,	/* 0x28 shared configuration block */
+#define BNX_DIR_NAME_SHARED_CFG			"sharedCFG"
+#define BNX_DIR_DESC_SHARED_CFG			"Shared Configuration Data"
+	BNX_DIR_TYPE_PORT_CFG	= 41,	/* 0x29 port configuration block */
+#define BNX_DIR_NAME_PORT_CFG			"portCFG"
+#define BNX_DIR_DESC_PORT_CFG			"Port Configuration Data"
+	BNX_DIR_TYPE_FUNC_CFG	= 42,	/* 0x2A func configuration block */
+#define BNX_DIR_NAME_FUNC_CFG			"funcCFG"
+#define BNX_DIR_DESC_FUNC_CFG			"Function Configuration Data"
+
+	/* Management Firmware (TruManage) related dir entries*/
+	/* 0x30 Management firmware configuration (see BMCFG library)*/
+	BNX_DIR_TYPE_MGMT_CFG			= 48,
+#define BNX_DIR_NAME_MGMT_CFG			"mgmtCFG"
+#define BNX_DIR_DESC_MGMT_CFG			"Out-of-band Management Configuration Data"
+	BNX_DIR_TYPE_MGMT_DATA	= 49,	/* 0x31 "Opaque Management Data" */
+#define BNX_DIR_NAME_MGMT_DATA			"mgmtData"
+#define BNX_DIR_DESC_MGMT_DATA			"Out-of-band Management Data"
+	BNX_DIR_TYPE_MGMT_WEB_DATA = 50,	/* 0x32 "Web GUI" file data */
+#define BNX_DIR_NAME_MGMT_WEB_DATA		"webData"
+#define BNX_DIR_DESC_MGMT_WEB_DATA		"Out-of-band Management Web Data"
+	/* 0x33 "Web GUI" file metadata */
+	BNX_DIR_TYPE_MGMT_WEB_META = 51,
+#define BNX_DIR_NAME_MGMT_WEB_META		"webMeta"
+#define BNX_DIR_DESC_MGMT_WEB_META		"Out-of-band Management Web Metadata"
+	/* 0x34 Management firmware Event Log (a.k.a. "SEL") */
+	BNX_DIR_TYPE_MGMT_EVENT_LOG	= 52,
+#define BNX_DIR_NAME_MGMT_EVENT_LOG		"eventLog"
+#define BNX_DIR_DESC_MGMT_EVENT_LOG		"Out-of-band Management Event Log"
+	/* 0x35 Management firmware Audit Log */
+	BNX_DIR_TYPE_MGMT_AUDIT_LOG	= 53
+#define BNX_DIR_NAME_MGMT_AUDIT_LOG		"auditLog"
+#define BNX_DIR_DESC_MGMT_AUDIT_LOG		"Out-of-band Management Audit Log"
+
+};
+
+/* For backwards compatibility only, may be removed later */
+#define BNX_DIR_TYPE_ISCSI_BOOT_CFG6 BNX_DIR_TYPE_ISCSI_BOOT_CFG
+
+/* Firmware NVM items of "APE BIN" format are identified with
+ * the following macro:
+ */
+#define BNX_DIR_TYPE_IS_APE_BIN_FMT(type)\
+	((type) == BNX_DIR_TYPE_CHIMP_PATCH	\
+		|| (type) == BNX_DIR_TYPE_BOOTCODE		\
+		|| (type) == BNX_DIR_TYPE_BOOTCODE_2	\
+		|| (type) == BNX_DIR_TYPE_APE_FW		\
+		|| (type) == BNX_DIR_TYPE_APE_PATCH		\
+		|| (type) == BNX_DIR_TYPE_TANG_FW		\
+		|| (type) == BNX_DIR_TYPE_TANG_PATCH	\
+		|| (type) == BNX_DIR_TYPE_KONG_FW		\
+		|| (type) == BNX_DIR_TYPE_KONG_PATCH	\
+		|| (type) == BNX_DIR_TYPE_BONO_FW		\
+		|| (type) == BNX_DIR_TYPE_BONO_PATCH	\
+	)
+
+/* Other (non APE BIN) executable NVM items are identified with
+ * the following macro:
+ */
+#define BNX_DIR_TYPE_IS_OTHER_EXEC(type)\
+	((type) == BNX_DIR_TYPE_AVS	\
+		|| (type) == BNX_DIR_TYPE_EXP_ROM_MBA	\
+		|| (type) == BNX_DIR_TYPE_PCIE			\
+		|| (type) == BNX_DIR_TYPE_TSCF_UCODE	\
+		|| (type) == BNX_DIR_TYPE_EXT_PHY		\
+		|| (type) == BNX_DIR_TYPE_CCM			\
+		|| (type) == BNX_DIR_TYPE_ISCSI_BOOT	\
+	)
+
+/* Executable NVM items (e.g. microcode, firmware, software) identified
+ * with the following macro
+ */
+#define BNX_DIR_TYPE_IS_EXECUTABLE(type)	\
+	(BNX_DIR_TYPE_IS_APE_BIN_FMT(type) \
+	|| BNX_DIR_TYPE_IS_OTHER_EXEC(type))
+
+#define BNX_DIR_ORDINAL_FIRST	0	/* Ordinals are 0-based */
+
+/* No extension flags for this directory entry */
+#define BNX_DIR_EXT_NONE	0
+/* Directory entry is inactive (not used, not hidden,
+ * not available for reuse)
+ */
+#define BNX_DIR_EXT_INACTIVE	(1 << 0)
+/* Directory content is a temporary staging location for
+ * updating the primary (non-update) directory entry contents
+ * (e.g. performing a secure firmware update)
+ */
+#define BNX_DIR_EXT_UPDATE	(1 << 1)
+
+/* No attribute flags set for this directory entry */
+#define BNX_DIR_ATTR_NONE	0
+/* Directory entry checksum of contents is purposely incorrect */
+#define BNX_DIR_ATTR_NO_CHKSUM	(1 << 0)
+/* Directory contents are in the form of a property-stream
+ * (e.g. configuration properties)
+ */
+#define BNX_DIR_ATTR_PROP_STREAM	(1 << 1)
+/* Directory content (e.g. iSCSI boot) supports IPv4 */
+#define BNX_DIR_ATTR_IPv4	(1 << 2)
+/* Directory content (e.g. iSCSI boot) supports IPv6 */
+#define BNX_DIR_ATTR_IPv6	(1 << 3)
+/* Directory content includes standard NVM component trailer
+ * (bnxnvm_component_trailer_t)
+ */
+#define BNX_DIR_ATTR_TRAILER	(1 << 4)
+
+/* Index of tab-delimited fields in each package log
+ * (BNX_DIR_TYPE_PKG_LOG) record (\n-terminated line):
+ */
+enum bnxnvm_pkglog_field_index {
+	/* Package installation date/time in ISO-8601 format */
+	BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP	= 0,
+	/* Installed package description (from package header) or "N/A" */
+	BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION	= 1,
+	/* Installed package version string (from package header) or "N/A" */
+	BNX_PKG_LOG_FIELD_IDX_PKG_VERSION	= 2,
+	/* Installed package creation/modification timestamp (ISO-8601) */
+	BNX_PKG_LOG_FIELD_IDX_PKG_TIMESTAMP = 3,
+	/* Installed package checksum in hexadecimal (CRC-32) or "N/A" */
+	BNX_PKG_LOG_FIELD_IDX_PKG_CHECKSUM	= 4,
+	/* Total number of packaged items applied in this installation */
+	BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS	= 5,
+	/* Hexadecimal bit-mask identifying which items were installed */
+	BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK	= 6
+};
+
+#if !defined(__GNUC__)
+#ifndef DOS_DRIVERS
+	#pragma pack(pop)		/* original packing */
+#endif
+#endif
+
+#endif /* Don't add anything after this line */
diff --git a/include/drivers/brcm/dmu.h b/include/drivers/brcm/dmu.h
new file mode 100644
index 0000000..3a57bbd
--- /dev/null
+++ b/include/drivers/brcm/dmu.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DMU_H
+#define DMU_H
+
+/* Clock field should be 2 bits only */
+#define CLKCONFIG_MASK 0x3
+
+/* argument */
+struct DmuBlockEnable {
+	uint32_t sotp:1;
+	uint32_t pka_rng:1;
+	uint32_t crypto:1;
+	uint32_t spl:1;
+	uint32_t cdru_vgm:1;
+	uint32_t apbs_s0_idm:1;
+	uint32_t smau_s0_idm:1;
+};
+
+/* prototype */
+uint32_t bcm_dmu_block_enable(struct DmuBlockEnable dbe);
+uint32_t bcm_dmu_block_disable(struct DmuBlockEnable dbe);
+uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel);
+uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num);
+
+#define PLL_FREQ_BYPASS 0x0
+#define PLL_FREQ_FULL  0x1
+#define PLL_FREQ_HALF  0x2
+#define PLL_FREQ_QRTR  0x3
+
+#endif
diff --git a/include/drivers/brcm/emmc/bcm_emmc.h b/include/drivers/brcm/emmc/bcm_emmc.h
new file mode 100644
index 0000000..67f0602
--- /dev/null
+++ b/include/drivers/brcm/emmc/bcm_emmc.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMMC_H
+#define EMMC_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+
+#include <platform_def.h>
+
+#include "emmc_chal_types.h"
+#include "emmc_chal_sd.h"
+#include "emmc_csl_sdprot.h"
+#include "emmc_csl_sdcmd.h"
+#include "emmc_pboot_hal_memory_drv.h"
+
+/* ------------------------------------------------------------------- */
+#define EXT_CSD_SIZE		512
+
+#ifdef PLAT_SD_MAX_READ_LENGTH
+#define SD_MAX_READ_LENGTH PLAT_SD_MAX_READ_LENGTH
+#ifdef USE_EMMC_LARGE_BLK_TRANSFER_LENGTH
+#define SD_MAX_BLK_TRANSFER_LENGTH	0x10000000
+#else
+#define SD_MAX_BLK_TRANSFER_LENGTH	0x1000
+#endif
+#else
+#define SD_MAX_READ_LENGTH EMMC_BLOCK_SIZE
+#define SD_MAX_BLK_TRANSFER_LENGTH EMMC_BLOCK_SIZE
+#endif
+
+struct emmc_global_buffer {
+	union {
+		uint8_t Ext_CSD_storage[EXT_CSD_SIZE];
+		uint8_t tempbuf[SD_MAX_READ_LENGTH];
+	} u;
+};
+
+struct emmc_global_vars {
+	struct sd_card_data cardData;
+	struct sd_handle sdHandle;
+	struct sd_dev sdDevice;
+	struct sd_card_info sdCard;
+	unsigned int init_done;
+};
+
+#define ICFG_SDIO0_CAP0__SLOT_TYPE_R 27
+#define ICFG_SDIO0_CAP0__INT_MODE_R 26
+#define ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R 25
+#define ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R 24
+#define ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R 23
+#define ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R 22
+#define ICFG_SDIO0_CAP0__SUSPEND_RESUME_R 21
+#define ICFG_SDIO0_CAP0__SDMA_R 20
+#define ICFG_SDIO0_CAP0__HIGH_SPEED_R 19
+#define ICFG_SDIO0_CAP0__ADMA2_R 18
+#define ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R 17
+#define ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R 15
+#define ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R 7
+#define ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R 6
+#define ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R 0
+#define ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R 22
+#define ICFG_SDIO0_CAP1__SPI_MODE_R 21
+#define ICFG_SDIO0_CAP1__CLK_MULT_R 13
+#define ICFG_SDIO0_CAP1__RETUNING_MODE_R 11
+#define ICFG_SDIO0_CAP1__TUNE_SDR50_R 10
+#define ICFG_SDIO0_CAP1__TIME_RETUNE_R 6
+#define ICFG_SDIO0_CAP1__DRIVER_D_R 5
+#define ICFG_SDIO0_CAP1__DRIVER_C_R 4
+#define ICFG_SDIO0_CAP1__DRIVER_A_R 3
+#define ICFG_SDIO0_CAP1__DDR50_R 2
+#define ICFG_SDIO0_CAP1__SDR104_R 1
+#define ICFG_SDIO0_CAP1__SDR50_R 0
+
+#define SDIO0_CTRL_REGS_BASE_ADDR	   (SDIO0_EMMCSDXC_SYSADDR)
+#define SDIO0_IDM_RESET_CTRL_ADDR	   (SDIO_IDM0_IDM_RESET_CONTROL)
+
+#define EMMC_CTRL_REGS_BASE_ADDR	    SDIO0_CTRL_REGS_BASE_ADDR
+#define EMMC_IDM_RESET_CTRL_ADDR	    SDIO0_IDM_RESET_CTRL_ADDR
+#define EMMC_IDM_IO_CTRL_DIRECT_ADDR	SDIO_IDM0_IO_CONTROL_DIRECT
+
+extern struct emmc_global_buffer *emmc_global_buf_ptr;
+
+extern struct emmc_global_vars *emmc_global_vars_ptr;
+
+#define EMMC_CARD_DETECT_TIMEOUT_MS 1200
+#define EMMC_CMD_TIMEOUT_MS 200
+#define EMMC_BUSY_CMD_TIMEOUT_MS 200
+#define EMMC_CLOCK_SETTING_TIMEOUT_MS 100
+#define EMMC_WFE_RETRY 40000
+#define EMMC_WFE_RETRY_DELAY_US 10
+
+#ifdef EMMC_DEBUG
+#define EMMC_TRACE INFO
+#else
+#define EMMC_TRACE(...)
+#endif
+
+#endif /* EMMC_H */
diff --git a/include/drivers/brcm/emmc/emmc_api.h b/include/drivers/brcm/emmc/emmc_api.h
new file mode 100644
index 0000000..c4c2a58
--- /dev/null
+++ b/include/drivers/brcm/emmc/emmc_api.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMMC_API_H
+#define EMMC_API_H
+
+#include "bcm_emmc.h"
+#include "emmc_pboot_hal_memory_drv.h"
+
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+/*
+ * The erasable unit of the eMMC is the Erase Group
+ * Erase group is measured in write blocks which
+ * are the basic writable units of the Device
+ * EMMC_ERASE_GROUP_SIZE is the number of writeable
+ * units (each unit is 512 bytes)
+ */
+
+/* Start address (sector) */
+#define EMMC_ERASE_START_BLOCK		0x0
+/* Number of blocks to be erased */
+#define EMMC_ERASE_BLOCK_COUNT		0x1
+
+#define EMMC_ERASE_USER_AREA		0
+#define EMMC_ERASE_BOOT_PARTITION1	1
+#define EMMC_ERASE_BOOT_PARTITION2	2
+
+/* eMMC partition to be erased */
+#define EMMC_ERASE_PARTITION EMMC_ERASE_USER_AREA
+#endif
+
+uint32_t bcm_emmc_init(bool card_rdy_only);
+void emmc_deinit(void);
+
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition);
+#endif
+
+uint32_t emmc_partition_select(uint32_t partition);
+uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr,
+		   size_t storage_size, size_t bytes_to_read);
+uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr,
+		    size_t bytes_to_write);
+#endif /* EMMC_API_H */
diff --git a/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h b/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h
new file mode 100644
index 0000000..96c333d
--- /dev/null
+++ b/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h
@@ -0,0 +1,1116 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BRCM_RDB_SD4_EMMC_TOP_H
+#define BRCM_RDB_SD4_EMMC_TOP_H
+
+#define SD4_EMMC_TOP_SYSADDR_OFFSET              0x00000000
+#define SD4_EMMC_TOP_SYSADDR_DEFAULT             0x00000000
+#define SD4_EMMC_TOP_SYSADDR_TYPE                uint32_t
+#define SD4_EMMC_TOP_SYSADDR_RESERVED_MASK       0x00000000
+#define SD4_EMMC_TOP_SYSADDR_SYSADDR_SHIFT       0
+#define SD4_EMMC_TOP_SYSADDR_SYSADDR_MASK        0xFFFFFFFF
+
+#define SD4_EMMC_TOP_BLOCK_OFFSET                0x00000004
+#define SD4_EMMC_TOP_BLOCK_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_BLOCK_TYPE                  uint32_t
+#define SD4_EMMC_TOP_BLOCK_RESERVED_MASK         0x00008000
+#define SD4_EMMC_TOP_BLOCK_BCNT_SHIFT            16
+#define SD4_EMMC_TOP_BLOCK_BCNT_MASK             0xFFFF0000
+#define SD4_EMMC_TOP_BLOCK_HSBS_SHIFT            12
+#define SD4_EMMC_TOP_BLOCK_HSBS_MASK             0x00007000
+#define SD4_EMMC_TOP_BLOCK_TBS_SHIFT             0
+#define SD4_EMMC_TOP_BLOCK_TBS_MASK              0x00000FFF
+
+#define SD4_EMMC_TOP_ARG_OFFSET                  0x00000008
+#define SD4_EMMC_TOP_ARG_DEFAULT                 0x00000000
+#define SD4_EMMC_TOP_ARG_TYPE                    uint32_t
+#define SD4_EMMC_TOP_ARG_RESERVED_MASK           0x00000000
+#define SD4_EMMC_TOP_ARG_ARG_SHIFT               0
+#define SD4_EMMC_TOP_ARG_ARG_MASK                0xFFFFFFFF
+
+#define SD4_EMMC_TOP_CMD_OFFSET                  0x0000000C
+#define SD4_EMMC_TOP_CMD_DEFAULT                 0x00000000
+#define SD4_EMMC_TOP_CMD_TYPE                    uint32_t
+#define SD4_EMMC_TOP_CMD_RESERVED_MASK           0xC004FFC0
+#define SD4_EMMC_TOP_CMD_CIDX_SHIFT              24
+#define SD4_EMMC_TOP_CMD_CIDX_MASK               0x3F000000
+#define SD4_EMMC_TOP_CMD_CTYP_SHIFT              22
+#define SD4_EMMC_TOP_CMD_CTYP_MASK               0x00C00000
+#define SD4_EMMC_TOP_CMD_DPS_SHIFT               21
+#define SD4_EMMC_TOP_CMD_DPS_MASK                0x00200000
+#define SD4_EMMC_TOP_CMD_CCHK_EN_SHIFT           20
+#define SD4_EMMC_TOP_CMD_CCHK_EN_MASK            0x00100000
+#define SD4_EMMC_TOP_CMD_CRC_EN_SHIFT            19
+#define SD4_EMMC_TOP_CMD_CRC_EN_MASK             0x00080000
+#define SD4_EMMC_TOP_CMD_RTSEL_SHIFT             16
+#define SD4_EMMC_TOP_CMD_RTSEL_MASK              0x00030000
+#define SD4_EMMC_TOP_CMD_MSBS_SHIFT              5
+#define SD4_EMMC_TOP_CMD_MSBS_MASK               0x00000020
+#define SD4_EMMC_TOP_CMD_DTDS_SHIFT              4
+#define SD4_EMMC_TOP_CMD_DTDS_MASK               0x00000010
+#define SD4_EMMC_TOP_CMD_ACMDEN_SHIFT            2
+#define SD4_EMMC_TOP_CMD_ACMDEN_MASK             0x0000000C
+#define SD4_EMMC_TOP_CMD_BCEN_SHIFT              1
+#define SD4_EMMC_TOP_CMD_BCEN_MASK               0x00000002
+#define SD4_EMMC_TOP_CMD_DMA_SHIFT               0
+#define SD4_EMMC_TOP_CMD_DMA_MASK                0x00000001
+
+#define SD4_EMMC_TOP_CMD_SD4_OFFSET              0x0000000C
+#define SD4_EMMC_TOP_CMD_SD4_DEFAULT             0x00000000
+#define SD4_EMMC_TOP_CMD_SD4_TYPE                uint32_t
+#define SD4_EMMC_TOP_CMD_SD4_RESERVED_MASK       0xC004FE00
+#define SD4_EMMC_TOP_CMD_SD4_CIDX_SHIFT          24
+#define SD4_EMMC_TOP_CMD_SD4_CIDX_MASK           0x3F000000
+#define SD4_EMMC_TOP_CMD_SD4_CTYP_SHIFT          22
+#define SD4_EMMC_TOP_CMD_SD4_CTYP_MASK           0x00C00000
+#define SD4_EMMC_TOP_CMD_SD4_DPS_SHIFT           21
+#define SD4_EMMC_TOP_CMD_SD4_DPS_MASK            0x00200000
+#define SD4_EMMC_TOP_CMD_SD4_CCHK_EN_SHIFT       20
+#define SD4_EMMC_TOP_CMD_SD4_CCHK_EN_MASK        0x00100000
+#define SD4_EMMC_TOP_CMD_SD4_CRC_EN_SHIFT        19
+#define SD4_EMMC_TOP_CMD_SD4_CRC_EN_MASK         0x00080000
+#define SD4_EMMC_TOP_CMD_SD4_RTSEL_SHIFT         16
+#define SD4_EMMC_TOP_CMD_SD4_RTSEL_MASK          0x00030000
+#define SD4_EMMC_TOP_CMD_SD4_RESPIRQDIS_SHIFT    8
+#define SD4_EMMC_TOP_CMD_SD4_RESPIRQDIS_MASK     0x00000100
+#define SD4_EMMC_TOP_CMD_SD4_RESPERRCHKEN_SHIFT  7
+#define SD4_EMMC_TOP_CMD_SD4_RESPERRCHKEN_MASK   0x00000080
+#define SD4_EMMC_TOP_CMD_SD4_RESPR1R5_SHIFT      6
+#define SD4_EMMC_TOP_CMD_SD4_RESPR1R5_MASK       0x00000040
+#define SD4_EMMC_TOP_CMD_SD4_MSBS_SHIFT          5
+#define SD4_EMMC_TOP_CMD_SD4_MSBS_MASK           0x00000020
+#define SD4_EMMC_TOP_CMD_SD4_DTDS_SHIFT          4
+#define SD4_EMMC_TOP_CMD_SD4_DTDS_MASK           0x00000010
+#define SD4_EMMC_TOP_CMD_SD4_ACMDEN_SHIFT        2
+#define SD4_EMMC_TOP_CMD_SD4_ACMDEN_MASK         0x0000000C
+#define SD4_EMMC_TOP_CMD_SD4_BCEN_SHIFT          1
+#define SD4_EMMC_TOP_CMD_SD4_BCEN_MASK           0x00000002
+#define SD4_EMMC_TOP_CMD_SD4_DMA_SHIFT           0
+#define SD4_EMMC_TOP_CMD_SD4_DMA_MASK            0x00000001
+
+#define SD4_EMMC_TOP_RESP0_OFFSET                0x00000010
+#define SD4_EMMC_TOP_RESP0_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_RESP0_TYPE                  uint32_t
+#define SD4_EMMC_TOP_RESP0_RESERVED_MASK         0x00000000
+#define SD4_EMMC_TOP_RESP0_RESP0_SHIFT           0
+#define SD4_EMMC_TOP_RESP0_RESP0_MASK            0xFFFFFFFF
+
+#define SD4_EMMC_TOP_RESP2_OFFSET                0x00000014
+#define SD4_EMMC_TOP_RESP2_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_RESP2_TYPE                  uint32_t
+#define SD4_EMMC_TOP_RESP2_RESERVED_MASK         0x00000000
+#define SD4_EMMC_TOP_RESP2_RESP2_SHIFT           0
+#define SD4_EMMC_TOP_RESP2_RESP2_MASK            0xFFFFFFFF
+
+#define SD4_EMMC_TOP_RESP4_OFFSET                0x00000018
+#define SD4_EMMC_TOP_RESP4_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_RESP4_TYPE                  uint32_t
+#define SD4_EMMC_TOP_RESP4_RESERVED_MASK         0x00000000
+#define SD4_EMMC_TOP_RESP4_RESP4_SHIFT           0
+#define SD4_EMMC_TOP_RESP4_RESP4_MASK            0xFFFFFFFF
+
+#define SD4_EMMC_TOP_RESP6_OFFSET                0x0000001C
+#define SD4_EMMC_TOP_RESP6_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_RESP6_TYPE                  uint32_t
+#define SD4_EMMC_TOP_RESP6_RESERVED_MASK         0x00000000
+#define SD4_EMMC_TOP_RESP6_RESP6_SHIFT           0
+#define SD4_EMMC_TOP_RESP6_RESP6_MASK            0xFFFFFFFF
+
+#define SD4_EMMC_TOP_BUFDAT_OFFSET               0x00000020
+#define SD4_EMMC_TOP_BUFDAT_DEFAULT              0x00000000
+#define SD4_EMMC_TOP_BUFDAT_TYPE                 uint32_t
+#define SD4_EMMC_TOP_BUFDAT_RESERVED_MASK        0x00000000
+#define SD4_EMMC_TOP_BUFDAT_BUFDAT_SHIFT         0
+#define SD4_EMMC_TOP_BUFDAT_BUFDAT_MASK          0xFFFFFFFF
+
+#define SD4_EMMC_TOP_PSTATE_OFFSET               0x00000024
+#define SD4_EMMC_TOP_PSTATE_DEFAULT              0x1FFC0000
+#define SD4_EMMC_TOP_PSTATE_TYPE                 uint32_t
+#define SD4_EMMC_TOP_PSTATE_RESERVED_MASK        0xE000F0F0
+#define SD4_EMMC_TOP_PSTATE_DLS7_4_SHIFT         25
+#define SD4_EMMC_TOP_PSTATE_DLS7_4_MASK          0x1E000000
+#define SD4_EMMC_TOP_PSTATE_CLSL_SHIFT           24
+#define SD4_EMMC_TOP_PSTATE_CLSL_MASK            0x01000000
+#define SD4_EMMC_TOP_PSTATE_DLS3_0_SHIFT         20
+#define SD4_EMMC_TOP_PSTATE_DLS3_0_MASK          0x00F00000
+#define SD4_EMMC_TOP_PSTATE_WPSL_SHIFT           19
+#define SD4_EMMC_TOP_PSTATE_WPSL_MASK            0x00080000
+#define SD4_EMMC_TOP_PSTATE_CDPL_SHIFT           18
+#define SD4_EMMC_TOP_PSTATE_CDPL_MASK            0x00040000
+#define SD4_EMMC_TOP_PSTATE_CSS_SHIFT            17
+#define SD4_EMMC_TOP_PSTATE_CSS_MASK             0x00020000
+#define SD4_EMMC_TOP_PSTATE_CINS_SHIFT           16
+#define SD4_EMMC_TOP_PSTATE_CINS_MASK            0x00010000
+#define SD4_EMMC_TOP_PSTATE_BREN_SHIFT           11
+#define SD4_EMMC_TOP_PSTATE_BREN_MASK            0x00000800
+#define SD4_EMMC_TOP_PSTATE_BWEN_SHIFT           10
+#define SD4_EMMC_TOP_PSTATE_BWEN_MASK            0x00000400
+#define SD4_EMMC_TOP_PSTATE_RXACT_SHIFT          9
+#define SD4_EMMC_TOP_PSTATE_RXACT_MASK           0x00000200
+#define SD4_EMMC_TOP_PSTATE_WXACT_SHIFT          8
+#define SD4_EMMC_TOP_PSTATE_WXACT_MASK           0x00000100
+#define SD4_EMMC_TOP_PSTATE_RETUNE_REQ_SHIFT     3
+#define SD4_EMMC_TOP_PSTATE_RETUNE_REQ_MASK      0x00000008
+#define SD4_EMMC_TOP_PSTATE_DATACT_SHIFT         2
+#define SD4_EMMC_TOP_PSTATE_DATACT_MASK          0x00000004
+#define SD4_EMMC_TOP_PSTATE_DATINH_SHIFT         1
+#define SD4_EMMC_TOP_PSTATE_DATINH_MASK          0x00000002
+#define SD4_EMMC_TOP_PSTATE_CMDINH_SHIFT         0
+#define SD4_EMMC_TOP_PSTATE_CMDINH_MASK          0x00000001
+
+#define SD4_EMMC_TOP_PSTATE_SD4_OFFSET               0x00000024
+#define SD4_EMMC_TOP_PSTATE_SD4_DEFAULT              0x01FC00F0
+#define SD4_EMMC_TOP_PSTATE_SD4_TYPE                 uint32_t
+#define SD4_EMMC_TOP_PSTATE_SD4_RESERVED_MASK        0x1E00F000
+#define SD4_EMMC_TOP_PSTATE_SD4_STBLDET_SHIFT        31
+#define SD4_EMMC_TOP_PSTATE_SD4_STBLDET_MASK         0x80000000
+#define SD4_EMMC_TOP_PSTATE_SD4_LANESYNC_SHIFT       30
+#define SD4_EMMC_TOP_PSTATE_SD4_LANESYNC_MASK        0x40000000
+#define SD4_EMMC_TOP_PSTATE_SD4_INDORMNTSTATE_SHIFT  29
+#define SD4_EMMC_TOP_PSTATE_SD4_INDORMNTSTATE_MASK   0x20000000
+#define SD4_EMMC_TOP_PSTATE_SD4_CLSL_SHIFT           24
+#define SD4_EMMC_TOP_PSTATE_SD4_CLSL_MASK            0x01000000
+#define SD4_EMMC_TOP_PSTATE_SD4_DLS3_0_SHIFT         20
+#define SD4_EMMC_TOP_PSTATE_SD4_DLS3_0_MASK          0x00F00000
+#define SD4_EMMC_TOP_PSTATE_SD4_WPSL_SHIFT       19
+#define SD4_EMMC_TOP_PSTATE_SD4_WPSL_MASK        0x00080000
+#define SD4_EMMC_TOP_PSTATE_SD4_CDPL_SHIFT       18
+#define SD4_EMMC_TOP_PSTATE_SD4_CDPL_MASK        0x00040000
+#define SD4_EMMC_TOP_PSTATE_SD4_CSS_SHIFT        17
+#define SD4_EMMC_TOP_PSTATE_SD4_CSS_MASK         0x00020000
+#define SD4_EMMC_TOP_PSTATE_SD4_CINS_SHIFT       16
+#define SD4_EMMC_TOP_PSTATE_SD4_CINS_MASK        0x00010000
+#define SD4_EMMC_TOP_PSTATE_SD4_BREN_SHIFT       11
+#define SD4_EMMC_TOP_PSTATE_SD4_BREN_MASK        0x00000800
+#define SD4_EMMC_TOP_PSTATE_SD4_BWEN_SHIFT       10
+#define SD4_EMMC_TOP_PSTATE_SD4_BWEN_MASK        0x00000400
+#define SD4_EMMC_TOP_PSTATE_SD4_RXACT_SHIFT      9
+#define SD4_EMMC_TOP_PSTATE_SD4_RXACT_MASK       0x00000200
+#define SD4_EMMC_TOP_PSTATE_SD4_WXACT_SHIFT      8
+#define SD4_EMMC_TOP_PSTATE_SD4_WXACT_MASK       0x00000100
+#define SD4_EMMC_TOP_PSTATE_SD4_DLS7_4_SHIFT     4
+#define SD4_EMMC_TOP_PSTATE_SD4_DLS7_4_MASK      0x000000F0
+#define SD4_EMMC_TOP_PSTATE_SD4_RETUNE_REQ_SHIFT 3
+#define SD4_EMMC_TOP_PSTATE_SD4_RETUNE_REQ_MASK  0x00000008
+#define SD4_EMMC_TOP_PSTATE_SD4_DATACT_SHIFT     2
+#define SD4_EMMC_TOP_PSTATE_SD4_DATACT_MASK      0x00000004
+#define SD4_EMMC_TOP_PSTATE_SD4_DATINH_SHIFT     1
+#define SD4_EMMC_TOP_PSTATE_SD4_DATINH_MASK      0x00000002
+#define SD4_EMMC_TOP_PSTATE_SD4_CMDINH_SHIFT     0
+#define SD4_EMMC_TOP_PSTATE_SD4_CMDINH_MASK      0x00000001
+
+#define SD4_EMMC_TOP_CTRL_OFFSET                 0x00000028
+#define SD4_EMMC_TOP_CTRL_DEFAULT                0x00000000
+#define SD4_EMMC_TOP_CTRL_TYPE                   uint32_t
+#define SD4_EMMC_TOP_CTRL_RESERVED_MASK          0xF800E000
+#define SD4_EMMC_TOP_CTRL_WAKENRMV_SHIFT         26
+#define SD4_EMMC_TOP_CTRL_WAKENRMV_MASK          0x04000000
+#define SD4_EMMC_TOP_CTRL_WAKENINS_SHIFT         25
+#define SD4_EMMC_TOP_CTRL_WAKENINS_MASK          0x02000000
+#define SD4_EMMC_TOP_CTRL_WAKENIRQ_SHIFT         24
+#define SD4_EMMC_TOP_CTRL_WAKENIRQ_MASK          0x01000000
+#define SD4_EMMC_TOP_CTRL_BOOTACK_SHIFT          23
+#define SD4_EMMC_TOP_CTRL_BOOTACK_MASK           0x00800000
+#define SD4_EMMC_TOP_CTRL_ATLBOOTEN_SHIFT        22
+#define SD4_EMMC_TOP_CTRL_ATLBOOTEN_MASK         0x00400000
+#define SD4_EMMC_TOP_CTRL_BOOTEN_SHIFT           21
+#define SD4_EMMC_TOP_CTRL_BOOTEN_MASK            0x00200000
+#define SD4_EMMC_TOP_CTRL_SPIMODE_SHIFT          20
+#define SD4_EMMC_TOP_CTRL_SPIMODE_MASK           0x00100000
+#define SD4_EMMC_TOP_CTRL_BLKIRQ_SHIFT           19
+#define SD4_EMMC_TOP_CTRL_BLKIRQ_MASK            0x00080000
+#define SD4_EMMC_TOP_CTRL_RDWTCRTL_SHIFT         18
+#define SD4_EMMC_TOP_CTRL_RDWTCRTL_MASK          0x00040000
+#define SD4_EMMC_TOP_CTRL_CONTREQ_SHIFT          17
+#define SD4_EMMC_TOP_CTRL_CONTREQ_MASK           0x00020000
+#define SD4_EMMC_TOP_CTRL_BLKSTPREQ_SHIFT        16
+#define SD4_EMMC_TOP_CTRL_BLKSTPREQ_MASK         0x00010000
+#define SD4_EMMC_TOP_CTRL_HRESET_SHIFT           12
+#define SD4_EMMC_TOP_CTRL_HRESET_MASK            0x00001000
+#define SD4_EMMC_TOP_CTRL_SDVSELVDD1_SHIFT       9
+#define SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK        0x00000E00
+#define SD4_EMMC_TOP_CTRL_SDPWR_SHIFT            8
+#define SD4_EMMC_TOP_CTRL_SDPWR_MASK             0x00000100
+#define SD4_EMMC_TOP_CTRL_CDSD_SHIFT             7
+#define SD4_EMMC_TOP_CTRL_CDSD_MASK              0x00000080
+#define SD4_EMMC_TOP_CTRL_CDTL_SHIFT             6
+#define SD4_EMMC_TOP_CTRL_CDTL_MASK              0x00000040
+#define SD4_EMMC_TOP_CTRL_SDB_SHIFT              5
+#define SD4_EMMC_TOP_CTRL_SDB_MASK               0x00000020
+#define SD4_EMMC_TOP_CTRL_DMASEL_SHIFT           3
+#define SD4_EMMC_TOP_CTRL_DMASEL_MASK            0x00000018
+#define SD4_EMMC_TOP_CTRL_HSEN_SHIFT             2
+#define SD4_EMMC_TOP_CTRL_HSEN_MASK              0x00000004
+#define SD4_EMMC_TOP_CTRL_DXTW_SHIFT             1
+#define SD4_EMMC_TOP_CTRL_DXTW_MASK              0x00000002
+#define SD4_EMMC_TOP_CTRL_LEDCTL_SHIFT           0
+#define SD4_EMMC_TOP_CTRL_LEDCTL_MASK            0x00000001
+
+#define SD4_EMMC_TOP_CTRL_SD4_OFFSET             0x00000028
+#define SD4_EMMC_TOP_CTRL_SD4_DEFAULT            0x00000000
+#define SD4_EMMC_TOP_CTRL_SD4_TYPE               uint32_t
+#define SD4_EMMC_TOP_CTRL_SD4_RESERVED_MASK      0xF8F00000
+#define SD4_EMMC_TOP_CTRL_SD4_WAKENRMV_SHIFT     26
+#define SD4_EMMC_TOP_CTRL_SD4_WAKENRMV_MASK      0x04000000
+#define SD4_EMMC_TOP_CTRL_SD4_WAKENINS_SHIFT     25
+#define SD4_EMMC_TOP_CTRL_SD4_WAKENINS_MASK      0x02000000
+#define SD4_EMMC_TOP_CTRL_SD4_WAKENIRQ_SHIFT     24
+#define SD4_EMMC_TOP_CTRL_SD4_WAKENIRQ_MASK      0x01000000
+#define SD4_EMMC_TOP_CTRL_SD4_BLKIRQ_SHIFT       19
+#define SD4_EMMC_TOP_CTRL_SD4_BLKIRQ_MASK        0x00080000
+#define SD4_EMMC_TOP_CTRL_SD4_RDWTCRTL_SHIFT     18
+#define SD4_EMMC_TOP_CTRL_SD4_RDWTCRTL_MASK      0x00040000
+#define SD4_EMMC_TOP_CTRL_SD4_CONTREQ_SHIFT      17
+#define SD4_EMMC_TOP_CTRL_SD4_CONTREQ_MASK       0x00020000
+#define SD4_EMMC_TOP_CTRL_SD4_BLKSTPREQ_SHIFT    16
+#define SD4_EMMC_TOP_CTRL_SD4_BLKSTPREQ_MASK     0x00010000
+#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD2_SHIFT   13
+#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD2_MASK    0x0000E000
+#define SD4_EMMC_TOP_CTRL_SD4_SDPWRVDD2_SHIFT    12
+#define SD4_EMMC_TOP_CTRL_SD4_SDPWRVDD2_MASK     0x00001000
+#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD1_SHIFT   9
+#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD1_MASK    0x00000E00
+#define SD4_EMMC_TOP_CTRL_SD4_SDPWR_SHIFT        8
+#define SD4_EMMC_TOP_CTRL_SD4_SDPWR_MASK         0x00000100
+#define SD4_EMMC_TOP_CTRL_SD4_CDSD_SHIFT         7
+#define SD4_EMMC_TOP_CTRL_SD4_CDSD_MASK          0x00000080
+#define SD4_EMMC_TOP_CTRL_SD4_CDTL_SHIFT         6
+#define SD4_EMMC_TOP_CTRL_SD4_CDTL_MASK          0x00000040
+#define SD4_EMMC_TOP_CTRL_SD4_SDB_SHIFT          5
+#define SD4_EMMC_TOP_CTRL_SD4_SDB_MASK           0x00000020
+#define SD4_EMMC_TOP_CTRL_SD4_DMASEL_SHIFT       3
+#define SD4_EMMC_TOP_CTRL_SD4_DMASEL_MASK        0x00000018
+#define SD4_EMMC_TOP_CTRL_SD4_HSEN_SHIFT         2
+#define SD4_EMMC_TOP_CTRL_SD4_HSEN_MASK          0x00000004
+#define SD4_EMMC_TOP_CTRL_SD4_DXTW_SHIFT         1
+#define SD4_EMMC_TOP_CTRL_SD4_DXTW_MASK          0x00000002
+#define SD4_EMMC_TOP_CTRL_SD4_LEDCTL_SHIFT       0
+#define SD4_EMMC_TOP_CTRL_SD4_LEDCTL_MASK        0x00000001
+
+#define SD4_EMMC_TOP_CTRL1_OFFSET                0x0000002C
+#define SD4_EMMC_TOP_CTRL1_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_CTRL1_TYPE                  uint32_t
+#define SD4_EMMC_TOP_CTRL1_RESERVED_MASK         0xF8F00018
+#define SD4_EMMC_TOP_CTRL1_DATRST_SHIFT          26
+#define SD4_EMMC_TOP_CTRL1_DATRST_MASK           0x04000000
+#define SD4_EMMC_TOP_CTRL1_CMDRST_SHIFT          25
+#define SD4_EMMC_TOP_CTRL1_CMDRST_MASK           0x02000000
+#define SD4_EMMC_TOP_CTRL1_RST_SHIFT             24
+#define SD4_EMMC_TOP_CTRL1_RST_MASK              0x01000000
+#define SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT           16
+#define SD4_EMMC_TOP_CTRL1_DTCNT_MASK            0x000F0000
+#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT        8
+#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK         0x0000FF00
+#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT     6
+#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK      0x000000C0
+#define SD4_EMMC_TOP_CTRL1_CLKGENSEL_SHIFT       5
+#define SD4_EMMC_TOP_CTRL1_CLKGENSEL_MASK        0x00000020
+#define SD4_EMMC_TOP_CTRL1_SDCLKEN_SHIFT         2
+#define SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK          0x00000004
+#define SD4_EMMC_TOP_CTRL1_ICLKSTB_SHIFT         1
+#define SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK          0x00000002
+#define SD4_EMMC_TOP_CTRL1_ICLKEN_SHIFT          0
+#define SD4_EMMC_TOP_CTRL1_ICLKEN_MASK           0x00000001
+
+#define SD4_EMMC_TOP_INTR_OFFSET                 0x00000030
+#define SD4_EMMC_TOP_INTR_DEFAULT                0x00000000
+#define SD4_EMMC_TOP_INTR_TYPE                   uint32_t
+#define SD4_EMMC_TOP_INTR_RESERVED_MASK          0xEC000000
+#define SD4_EMMC_TOP_INTR_TRESPERR_SHIFT         28
+#define SD4_EMMC_TOP_INTR_TRESPERR_MASK          0x10000000
+#define SD4_EMMC_TOP_INTR_ADMAERR_SHIFT          25
+#define SD4_EMMC_TOP_INTR_ADMAERR_MASK           0x02000000
+#define SD4_EMMC_TOP_INTR_CMDERROR_SHIFT         24
+#define SD4_EMMC_TOP_INTR_CMDERROR_MASK          0x01000000
+#define SD4_EMMC_TOP_INTR_IERR_SHIFT             23
+#define SD4_EMMC_TOP_INTR_IERR_MASK              0x00800000
+#define SD4_EMMC_TOP_INTR_DEBERR_SHIFT           22
+#define SD4_EMMC_TOP_INTR_DEBERR_MASK            0x00400000
+#define SD4_EMMC_TOP_INTR_DCRCERR_SHIFT          21
+#define SD4_EMMC_TOP_INTR_DCRCERR_MASK           0x00200000
+#define SD4_EMMC_TOP_INTR_DTOERR_SHIFT           20
+#define SD4_EMMC_TOP_INTR_DTOERR_MASK            0x00100000
+#define SD4_EMMC_TOP_INTR_CMDIDXERR_SHIFT        19
+#define SD4_EMMC_TOP_INTR_CMDIDXERR_MASK         0x00080000
+#define SD4_EMMC_TOP_INTR_CEBERR_SHIFT           18
+#define SD4_EMMC_TOP_INTR_CEBERR_MASK            0x00040000
+#define SD4_EMMC_TOP_INTR_CCRCERR_SHIFT          17
+#define SD4_EMMC_TOP_INTR_CCRCERR_MASK           0x00020000
+#define SD4_EMMC_TOP_INTR_CTOERR_SHIFT           16
+#define SD4_EMMC_TOP_INTR_CTOERR_MASK            0x00010000
+#define SD4_EMMC_TOP_INTR_ERRIRQ_SHIFT           15
+#define SD4_EMMC_TOP_INTR_ERRIRQ_MASK            0x00008000
+#define SD4_EMMC_TOP_INTR_BTIRQ_SHIFT            14
+#define SD4_EMMC_TOP_INTR_BTIRQ_MASK             0x00004000
+#define SD4_EMMC_TOP_INTR_BTACKRX_SHIFT          13
+#define SD4_EMMC_TOP_INTR_BTACKRX_MASK           0x00002000
+#define SD4_EMMC_TOP_INTR_RETUNE_EVENT_SHIFT     12
+#define SD4_EMMC_TOP_INTR_RETUNE_EVENT_MASK      0x00001000
+#define SD4_EMMC_TOP_INTR_INT_C_SHIFT            11
+#define SD4_EMMC_TOP_INTR_INT_C_MASK             0x00000800
+#define SD4_EMMC_TOP_INTR_INT_B_SHIFT            10
+#define SD4_EMMC_TOP_INTR_INT_B_MASK             0x00000400
+#define SD4_EMMC_TOP_INTR_INT_A_SHIFT            9
+#define SD4_EMMC_TOP_INTR_INT_A_MASK             0x00000200
+#define SD4_EMMC_TOP_INTR_CRDIRQ_SHIFT           8
+#define SD4_EMMC_TOP_INTR_CRDIRQ_MASK            0x00000100
+#define SD4_EMMC_TOP_INTR_CRDRMV_SHIFT           7
+#define SD4_EMMC_TOP_INTR_CRDRMV_MASK            0x00000080
+#define SD4_EMMC_TOP_INTR_CRDINS_SHIFT           6
+#define SD4_EMMC_TOP_INTR_CRDINS_MASK            0x00000040
+#define SD4_EMMC_TOP_INTR_BRRDY_SHIFT            5
+#define SD4_EMMC_TOP_INTR_BRRDY_MASK             0x00000020
+#define SD4_EMMC_TOP_INTR_BWRDY_SHIFT            4
+#define SD4_EMMC_TOP_INTR_BWRDY_MASK             0x00000010
+#define SD4_EMMC_TOP_INTR_DMAIRQ_SHIFT           3
+#define SD4_EMMC_TOP_INTR_DMAIRQ_MASK            0x00000008
+#define SD4_EMMC_TOP_INTR_BLKENT_SHIFT           2
+#define SD4_EMMC_TOP_INTR_BLKENT_MASK            0x00000004
+#define SD4_EMMC_TOP_INTR_TXDONE_SHIFT           1
+#define SD4_EMMC_TOP_INTR_TXDONE_MASK            0x00000002
+#define SD4_EMMC_TOP_INTR_CMDDONE_SHIFT          0
+#define SD4_EMMC_TOP_INTR_CMDDONE_MASK           0x00000001
+
+#define SD4_EMMC_TOP_INTR_SD4_OFFSET             0x00000030
+#define SD4_EMMC_TOP_INTR_SD4_DEFAULT            0x00000000
+#define SD4_EMMC_TOP_INTR_SD4_TYPE               uint32_t
+#define SD4_EMMC_TOP_INTR_SD4_RESERVED_MASK      0xF0006000
+#define SD4_EMMC_TOP_INTR_SD4_TRESPERR_SHIFT     27
+#define SD4_EMMC_TOP_INTR_SD4_TRESPERR_MASK      0x08000000
+#define SD4_EMMC_TOP_INTR_SD4_TUNEERR_SHIFT      26
+#define SD4_EMMC_TOP_INTR_SD4_TUNEERR_MASK       0x04000000
+#define SD4_EMMC_TOP_INTR_SD4_ADMAERR_SHIFT      25
+#define SD4_EMMC_TOP_INTR_SD4_ADMAERR_MASK       0x02000000
+#define SD4_EMMC_TOP_INTR_SD4_CMDERROR_SHIFT     24
+#define SD4_EMMC_TOP_INTR_SD4_CMDERROR_MASK      0x01000000
+#define SD4_EMMC_TOP_INTR_SD4_IERR_SHIFT         23
+#define SD4_EMMC_TOP_INTR_SD4_IERR_MASK          0x00800000
+#define SD4_EMMC_TOP_INTR_SD4_DEBERR_SHIFT       22
+#define SD4_EMMC_TOP_INTR_SD4_DEBERR_MASK        0x00400000
+#define SD4_EMMC_TOP_INTR_SD4_DCRCERR_SHIFT      21
+#define SD4_EMMC_TOP_INTR_SD4_DCRCERR_MASK       0x00200000
+#define SD4_EMMC_TOP_INTR_SD4_DTOERR_SHIFT       20
+#define SD4_EMMC_TOP_INTR_SD4_DTOERR_MASK        0x00100000
+#define SD4_EMMC_TOP_INTR_SD4_CMDIDXERR_SHIFT    19
+#define SD4_EMMC_TOP_INTR_SD4_CMDIDXERR_MASK     0x00080000
+#define SD4_EMMC_TOP_INTR_SD4_CEBERR_SHIFT       18
+#define SD4_EMMC_TOP_INTR_SD4_CEBERR_MASK        0x00040000
+#define SD4_EMMC_TOP_INTR_SD4_CCRCERR_SHIFT      17
+#define SD4_EMMC_TOP_INTR_SD4_CCRCERR_MASK       0x00020000
+#define SD4_EMMC_TOP_INTR_SD4_CTOERR_SHIFT       16
+#define SD4_EMMC_TOP_INTR_SD4_CTOERR_MASK        0x00010000
+#define SD4_EMMC_TOP_INTR_SD4_ERRIRQ_SHIFT       15
+#define SD4_EMMC_TOP_INTR_SD4_ERRIRQ_MASK        0x00008000
+#define SD4_EMMC_TOP_INTR_SD4_RETUNE_EVENT_SHIFT 12
+#define SD4_EMMC_TOP_INTR_SD4_RETUNE_EVENT_MASK  0x00001000
+#define SD4_EMMC_TOP_INTR_SD4_INT_C_SHIFT        11
+#define SD4_EMMC_TOP_INTR_SD4_INT_C_MASK         0x00000800
+#define SD4_EMMC_TOP_INTR_SD4_INT_B_SHIFT        10
+#define SD4_EMMC_TOP_INTR_SD4_INT_B_MASK         0x00000400
+#define SD4_EMMC_TOP_INTR_SD4_INT_A_SHIFT        9
+#define SD4_EMMC_TOP_INTR_SD4_INT_A_MASK         0x00000200
+#define SD4_EMMC_TOP_INTR_SD4_CRDIRQ_SHIFT       8
+#define SD4_EMMC_TOP_INTR_SD4_CRDIRQ_MASK        0x00000100
+#define SD4_EMMC_TOP_INTR_SD4_CRDRMV_SHIFT       7
+#define SD4_EMMC_TOP_INTR_SD4_CRDRMV_MASK        0x00000080
+#define SD4_EMMC_TOP_INTR_SD4_CRDINS_SHIFT       6
+#define SD4_EMMC_TOP_INTR_SD4_CRDINS_MASK        0x00000040
+#define SD4_EMMC_TOP_INTR_SD4_BRRDY_SHIFT        5
+#define SD4_EMMC_TOP_INTR_SD4_BRRDY_MASK         0x00000020
+#define SD4_EMMC_TOP_INTR_SD4_BWRDY_SHIFT        4
+#define SD4_EMMC_TOP_INTR_SD4_BWRDY_MASK         0x00000010
+#define SD4_EMMC_TOP_INTR_SD4_DMAIRQ_SHIFT       3
+#define SD4_EMMC_TOP_INTR_SD4_DMAIRQ_MASK        0x00000008
+#define SD4_EMMC_TOP_INTR_SD4_BLKENT_SHIFT       2
+#define SD4_EMMC_TOP_INTR_SD4_BLKENT_MASK        0x00000004
+#define SD4_EMMC_TOP_INTR_SD4_TXDONE_SHIFT       1
+#define SD4_EMMC_TOP_INTR_SD4_TXDONE_MASK        0x00000002
+#define SD4_EMMC_TOP_INTR_SD4_CMDDONE_SHIFT      0
+#define SD4_EMMC_TOP_INTR_SD4_CMDDONE_MASK       0x00000001
+
+#define SD4_EMMC_TOP_INTREN1_OFFSET                0x00000034
+#define SD4_EMMC_TOP_INTREN1_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_INTREN1_TYPE                  uint32_t
+#define SD4_EMMC_TOP_INTREN1_RESERVED_MASK         0xEC000000
+#define SD4_EMMC_TOP_INTREN1_TRESPERREN_SHIFT      28
+#define SD4_EMMC_TOP_INTREN1_TRESPERREN_MASK       0x10000000
+#define SD4_EMMC_TOP_INTREN1_ADMAEREN_SHIFT        25
+#define SD4_EMMC_TOP_INTREN1_ADMAEREN_MASK         0x02000000
+#define SD4_EMMC_TOP_INTREN1_CMDERREN_SHIFT        24
+#define SD4_EMMC_TOP_INTREN1_CMDERREN_MASK         0x01000000
+#define SD4_EMMC_TOP_INTREN1_ILIMERREN_SHIFT       23
+#define SD4_EMMC_TOP_INTREN1_ILIMERREN_MASK        0x00800000
+#define SD4_EMMC_TOP_INTREN1_DEBERREN_SHIFT        22
+#define SD4_EMMC_TOP_INTREN1_DEBERREN_MASK         0x00400000
+#define SD4_EMMC_TOP_INTREN1_DCRCERREN_SHIFT       21
+#define SD4_EMMC_TOP_INTREN1_DCRCERREN_MASK        0x00200000
+#define SD4_EMMC_TOP_INTREN1_DTOERREN_SHIFT        20
+#define SD4_EMMC_TOP_INTREN1_DTOERREN_MASK         0x00100000
+#define SD4_EMMC_TOP_INTREN1_CIDXERREN_SHIFT       19
+#define SD4_EMMC_TOP_INTREN1_CIDXERREN_MASK        0x00080000
+#define SD4_EMMC_TOP_INTREN1_CEBERREN_SHIFT        18
+#define SD4_EMMC_TOP_INTREN1_CEBERREN_MASK         0x00040000
+#define SD4_EMMC_TOP_INTREN1_CMDCRCEN_SHIFT        17
+#define SD4_EMMC_TOP_INTREN1_CMDCRCEN_MASK         0x00020000
+#define SD4_EMMC_TOP_INTREN1_CMDTOEN_SHIFT         16
+#define SD4_EMMC_TOP_INTREN1_CMDTOEN_MASK          0x00010000
+#define SD4_EMMC_TOP_INTREN1_FIXZ_SHIFT            15
+#define SD4_EMMC_TOP_INTREN1_FIXZ_MASK             0x00008000
+#define SD4_EMMC_TOP_INTREN1_BTIRQEN_SHIFT         14
+#define SD4_EMMC_TOP_INTREN1_BTIRQEN_MASK          0x00004000
+#define SD4_EMMC_TOP_INTREN1_BTACKRXEN_SHIFT       13
+#define SD4_EMMC_TOP_INTREN1_BTACKRXEN_MASK        0x00002000
+#define SD4_EMMC_TOP_INTREN1_RETUNE_EVENTEN_SHIFT  12
+#define SD4_EMMC_TOP_INTREN1_RETUNE_EVENTEN_MASK   0x00001000
+#define SD4_EMMC_TOP_INTREN1_INT_C_EN_SHIFT        11
+#define SD4_EMMC_TOP_INTREN1_INT_C_EN_MASK         0x00000800
+#define SD4_EMMC_TOP_INTREN1_INT_B_EN_SHIFT        10
+#define SD4_EMMC_TOP_INTREN1_INT_B_EN_MASK         0x00000400
+#define SD4_EMMC_TOP_INTREN1_INT_A_EN_SHIFT        9
+#define SD4_EMMC_TOP_INTREN1_INT_A_EN_MASK         0x00000200
+#define SD4_EMMC_TOP_INTREN1_CIRQEN_SHIFT          8
+#define SD4_EMMC_TOP_INTREN1_CIRQEN_MASK           0x00000100
+#define SD4_EMMC_TOP_INTREN1_CRDRMVEN_SHIFT        7
+#define SD4_EMMC_TOP_INTREN1_CRDRMVEN_MASK         0x00000080
+#define SD4_EMMC_TOP_INTREN1_CRDINSEN_SHIFT        6
+#define SD4_EMMC_TOP_INTREN1_CRDINSEN_MASK         0x00000040
+#define SD4_EMMC_TOP_INTREN1_BUFRREN_SHIFT         5
+#define SD4_EMMC_TOP_INTREN1_BUFRREN_MASK          0x00000020
+#define SD4_EMMC_TOP_INTREN1_BUFWREN_SHIFT         4
+#define SD4_EMMC_TOP_INTREN1_BUFWREN_MASK          0x00000010
+#define SD4_EMMC_TOP_INTREN1_DMAIRQEN_SHIFT        3
+#define SD4_EMMC_TOP_INTREN1_DMAIRQEN_MASK         0x00000008
+#define SD4_EMMC_TOP_INTREN1_BLKEN_SHIFT           2
+#define SD4_EMMC_TOP_INTREN1_BLKEN_MASK            0x00000004
+#define SD4_EMMC_TOP_INTREN1_TXDONEEN_SHIFT        1
+#define SD4_EMMC_TOP_INTREN1_TXDONEEN_MASK         0x00000002
+#define SD4_EMMC_TOP_INTREN1_CMDDONEEN_SHIFT       0
+#define SD4_EMMC_TOP_INTREN1_CMDDONEEN_MASK        0x00000001
+
+#define SD4_EMMC_TOP_INTREN1_SD4_OFFSET               0x00000034
+#define SD4_EMMC_TOP_INTREN1_SD4_DEFAULT              0x00000000
+#define SD4_EMMC_TOP_INTREN1_SD4_TYPE                 uint32_t
+#define SD4_EMMC_TOP_INTREN1_SD4_RESERVED_MASK        0x00006000
+#define SD4_EMMC_TOP_INTREN1_SD4_VNDRERREN_SHIFT      28
+#define SD4_EMMC_TOP_INTREN1_SD4_VNDRERREN_MASK       0xF0000000
+#define SD4_EMMC_TOP_INTREN1_SD4_TRESPERREN_SHIFT     27
+#define SD4_EMMC_TOP_INTREN1_SD4_TRESPERREN_MASK      0x08000000
+#define SD4_EMMC_TOP_INTREN1_SD4_TUNEERREN_SHIFT      26
+#define SD4_EMMC_TOP_INTREN1_SD4_TUNEERREN_MASK       0x04000000
+#define SD4_EMMC_TOP_INTREN1_SD4_ADMAEREN_SHIFT       25
+#define SD4_EMMC_TOP_INTREN1_SD4_ADMAEREN_MASK        0x02000000
+#define SD4_EMMC_TOP_INTREN1_SD4_CMDERREN_SHIFT       24
+#define SD4_EMMC_TOP_INTREN1_SD4_CMDERREN_MASK        0x01000000
+#define SD4_EMMC_TOP_INTREN1_SD4_ILIMERREN_SHIFT      23
+#define SD4_EMMC_TOP_INTREN1_SD4_ILIMERREN_MASK       0x00800000
+#define SD4_EMMC_TOP_INTREN1_SD4_DEBERREN_SHIFT       22
+#define SD4_EMMC_TOP_INTREN1_SD4_DEBERREN_MASK        0x00400000
+#define SD4_EMMC_TOP_INTREN1_SD4_DCRCERREN_SHIFT      21
+#define SD4_EMMC_TOP_INTREN1_SD4_DCRCERREN_MASK       0x00200000
+#define SD4_EMMC_TOP_INTREN1_SD4_DTOERREN_SHIFT       20
+#define SD4_EMMC_TOP_INTREN1_SD4_DTOERREN_MASK        0x00100000
+#define SD4_EMMC_TOP_INTREN1_SD4_CIDXERREN_SHIFT      19
+#define SD4_EMMC_TOP_INTREN1_SD4_CIDXERREN_MASK       0x00080000
+#define SD4_EMMC_TOP_INTREN1_SD4_CEBERREN_SHIFT       18
+#define SD4_EMMC_TOP_INTREN1_SD4_CEBERREN_MASK        0x00040000
+#define SD4_EMMC_TOP_INTREN1_SD4_CMDCRCEN_SHIFT       17
+#define SD4_EMMC_TOP_INTREN1_SD4_CMDCRCEN_MASK        0x00020000
+#define SD4_EMMC_TOP_INTREN1_SD4_CMDTOEN_SHIFT        16
+#define SD4_EMMC_TOP_INTREN1_SD4_CMDTOEN_MASK         0x00010000
+#define SD4_EMMC_TOP_INTREN1_SD4_FIXZ_SHIFT           15
+#define SD4_EMMC_TOP_INTREN1_SD4_FIXZ_MASK            0x00008000
+#define SD4_EMMC_TOP_INTREN1_SD4_RETUNE_EVENTEN_SHIFT 12
+#define SD4_EMMC_TOP_INTREN1_SD4_RETUNE_EVENTEN_MASK  0x00001000
+#define SD4_EMMC_TOP_INTREN1_SD4_INT_C_EN_SHIFT       11
+#define SD4_EMMC_TOP_INTREN1_SD4_INT_C_EN_MASK        0x00000800
+#define SD4_EMMC_TOP_INTREN1_SD4_INT_B_EN_SHIFT       10
+#define SD4_EMMC_TOP_INTREN1_SD4_INT_B_EN_MASK        0x00000400
+#define SD4_EMMC_TOP_INTREN1_SD4_INT_A_EN_SHIFT       9
+#define SD4_EMMC_TOP_INTREN1_SD4_INT_A_EN_MASK        0x00000200
+#define SD4_EMMC_TOP_INTREN1_SD4_CIRQEN_SHIFT         8
+#define SD4_EMMC_TOP_INTREN1_SD4_CIRQEN_MASK          0x00000100
+#define SD4_EMMC_TOP_INTREN1_SD4_CRDRMVEN_SHIFT       7
+#define SD4_EMMC_TOP_INTREN1_SD4_CRDRMVEN_MASK        0x00000080
+#define SD4_EMMC_TOP_INTREN1_SD4_CRDINSEN_SHIFT       6
+#define SD4_EMMC_TOP_INTREN1_SD4_CRDINSEN_MASK        0x00000040
+#define SD4_EMMC_TOP_INTREN1_SD4_BUFRREN_SHIFT        5
+#define SD4_EMMC_TOP_INTREN1_SD4_BUFRREN_MASK         0x00000020
+#define SD4_EMMC_TOP_INTREN1_SD4_BUFWREN_SHIFT        4
+#define SD4_EMMC_TOP_INTREN1_SD4_BUFWREN_MASK         0x00000010
+#define SD4_EMMC_TOP_INTREN1_SD4_DMAIRQEN_SHIFT       3
+#define SD4_EMMC_TOP_INTREN1_SD4_DMAIRQEN_MASK        0x00000008
+#define SD4_EMMC_TOP_INTREN1_SD4_BLKEN_SHIFT          2
+#define SD4_EMMC_TOP_INTREN1_SD4_BLKEN_MASK           0x00000004
+#define SD4_EMMC_TOP_INTREN1_SD4_TXDONEEN_SHIFT       1
+#define SD4_EMMC_TOP_INTREN1_SD4_TXDONEEN_MASK        0x00000002
+#define SD4_EMMC_TOP_INTREN1_SD4_CMDDONEEN_SHIFT      0
+#define SD4_EMMC_TOP_INTREN1_SD4_CMDDONEEN_MASK       0x00000001
+
+#define SD4_EMMC_TOP_INTREN2_OFFSET                   0x00000038
+#define SD4_EMMC_TOP_INTREN2_DEFAULT                  0x00000000
+#define SD4_EMMC_TOP_INTREN2_TYPE                     uint32_t
+#define SD4_EMMC_TOP_INTREN2_RESERVED_MASK            0xEC000000
+#define SD4_EMMC_TOP_INTREN2_TRESPERRSEN_SHIFT        28
+#define SD4_EMMC_TOP_INTREN2_TRESPERRSEN_MASK         0x10000000
+#define SD4_EMMC_TOP_INTREN2_ADMASIGEN_SHIFT          25
+#define SD4_EMMC_TOP_INTREN2_ADMASIGEN_MASK           0x02000000
+#define SD4_EMMC_TOP_INTREN2_CMDSIGEN_SHIFT           24
+#define SD4_EMMC_TOP_INTREN2_CMDSIGEN_MASK            0x01000000
+#define SD4_EMMC_TOP_INTREN2_ILIMSIGEN_SHIFT          23
+#define SD4_EMMC_TOP_INTREN2_ILIMSIGEN_MASK           0x00800000
+#define SD4_EMMC_TOP_INTREN2_DEBSIGEN_SHIFT           22
+#define SD4_EMMC_TOP_INTREN2_DEBSIGEN_MASK            0x00400000
+#define SD4_EMMC_TOP_INTREN2_DCRCSIGEN_SHIFT          21
+#define SD4_EMMC_TOP_INTREN2_DCRCSIGEN_MASK           0x00200000
+#define SD4_EMMC_TOP_INTREN2_DTOSIGEN_SHIFT           20
+#define SD4_EMMC_TOP_INTREN2_DTOSIGEN_MASK            0x00100000
+#define SD4_EMMC_TOP_INTREN2_CIDXSIGEN_SHIFT          19
+#define SD4_EMMC_TOP_INTREN2_CIDXSIGEN_MASK           0x00080000
+#define SD4_EMMC_TOP_INTREN2_CEBSIGEN_SHIFT           18
+#define SD4_EMMC_TOP_INTREN2_CEBSIGEN_MASK            0x00040000
+#define SD4_EMMC_TOP_INTREN2_CMDCRCSIGEN_SHIFT        17
+#define SD4_EMMC_TOP_INTREN2_CMDCRCSIGEN_MASK         0x00020000
+#define SD4_EMMC_TOP_INTREN2_CMDTOSIGEN_SHIFT         16
+#define SD4_EMMC_TOP_INTREN2_CMDTOSIGEN_MASK          0x00010000
+#define SD4_EMMC_TOP_INTREN2_FIXZERO_SHIFT            15
+#define SD4_EMMC_TOP_INTREN2_FIXZERO_MASK             0x00008000
+#define SD4_EMMC_TOP_INTREN2_BTIRQSEN_SHIFT           14
+#define SD4_EMMC_TOP_INTREN2_BTIRQSEN_MASK            0x00004000
+#define SD4_EMMC_TOP_INTREN2_BTACKRXSEN_SHIFT         13
+#define SD4_EMMC_TOP_INTREN2_BTACKRXSEN_MASK          0x00002000
+#define SD4_EMMC_TOP_INTREN2_RETUNE_EVENTSIGEN_SHIFT  12
+#define SD4_EMMC_TOP_INTREN2_RETUNE_EVENTSIGEN_MASK   0x00001000
+#define SD4_EMMC_TOP_INTREN2_INT_C_SIGEN_SHIFT        11
+#define SD4_EMMC_TOP_INTREN2_INT_C_SIGEN_MASK         0x00000800
+#define SD4_EMMC_TOP_INTREN2_INT_B_SIGEN_SHIFT        10
+#define SD4_EMMC_TOP_INTREN2_INT_B_SIGEN_MASK         0x00000400
+#define SD4_EMMC_TOP_INTREN2_INT_A_SIGEN_SHIFT        9
+#define SD4_EMMC_TOP_INTREN2_INT_A_SIGEN_MASK         0x00000200
+#define SD4_EMMC_TOP_INTREN2_CRDIRQEN_SHIFT           8
+#define SD4_EMMC_TOP_INTREN2_CRDIRQEN_MASK            0x00000100
+#define SD4_EMMC_TOP_INTREN2_CRDRVMEN_SHIFT           7
+#define SD4_EMMC_TOP_INTREN2_CRDRVMEN_MASK            0x00000080
+#define SD4_EMMC_TOP_INTREN2_CRDINSEN_SHIFT           6
+#define SD4_EMMC_TOP_INTREN2_CRDINSEN_MASK            0x00000040
+#define SD4_EMMC_TOP_INTREN2_BUFRRDYEN_SHIFT          5
+#define SD4_EMMC_TOP_INTREN2_BUFRRDYEN_MASK           0x00000020
+#define SD4_EMMC_TOP_INTREN2_BUFWRDYEN_SHIFT          4
+#define SD4_EMMC_TOP_INTREN2_BUFWRDYEN_MASK           0x00000010
+#define SD4_EMMC_TOP_INTREN2_DMAIRQEN_SHIFT           3
+#define SD4_EMMC_TOP_INTREN2_DMAIRQEN_MASK            0x00000008
+#define SD4_EMMC_TOP_INTREN2_BLKGAPEN_SHIFT           2
+#define SD4_EMMC_TOP_INTREN2_BLKGAPEN_MASK            0x00000004
+#define SD4_EMMC_TOP_INTREN2_TXDONE_SHIFT             1
+#define SD4_EMMC_TOP_INTREN2_TXDONE_MASK              0x00000002
+#define SD4_EMMC_TOP_INTREN2_CMDDONE_SHIFT            0
+#define SD4_EMMC_TOP_INTREN2_CMDDONE_MASK             0x00000001
+
+#define SD4_EMMC_TOP_INTREN2_SD4_OFFSET                   0x00000038
+#define SD4_EMMC_TOP_INTREN2_SD4_DEFAULT                  0x00000000
+#define SD4_EMMC_TOP_INTREN2_SD4_TYPE                     uint32_t
+#define SD4_EMMC_TOP_INTREN2_SD4_RESERVED_MASK            0xF0006000
+#define SD4_EMMC_TOP_INTREN2_SD4_TRESPERRSEN_SHIFT        27
+#define SD4_EMMC_TOP_INTREN2_SD4_TRESPERRSEN_MASK         0x08000000
+#define SD4_EMMC_TOP_INTREN2_SD4_TUNERRSIGEN_SHIFT        26
+#define SD4_EMMC_TOP_INTREN2_SD4_TUNERRSIGEN_MASK         0x04000000
+#define SD4_EMMC_TOP_INTREN2_SD4_ADMASIGEN_SHIFT          25
+#define SD4_EMMC_TOP_INTREN2_SD4_ADMASIGEN_MASK           0x02000000
+#define SD4_EMMC_TOP_INTREN2_SD4_CMDSIGEN_SHIFT           24
+#define SD4_EMMC_TOP_INTREN2_SD4_CMDSIGEN_MASK            0x01000000
+#define SD4_EMMC_TOP_INTREN2_SD4_ILIMSIGEN_SHIFT          23
+#define SD4_EMMC_TOP_INTREN2_SD4_ILIMSIGEN_MASK           0x00800000
+#define SD4_EMMC_TOP_INTREN2_SD4_DEBSIGEN_SHIFT           22
+#define SD4_EMMC_TOP_INTREN2_SD4_DEBSIGEN_MASK            0x00400000
+#define SD4_EMMC_TOP_INTREN2_SD4_DCRCSIGEN_SHIFT          21
+#define SD4_EMMC_TOP_INTREN2_SD4_DCRCSIGEN_MASK           0x00200000
+#define SD4_EMMC_TOP_INTREN2_SD4_DTOSIGEN_SHIFT           20
+#define SD4_EMMC_TOP_INTREN2_SD4_DTOSIGEN_MASK            0x00100000
+#define SD4_EMMC_TOP_INTREN2_SD4_CIDXSIGEN_SHIFT          19
+#define SD4_EMMC_TOP_INTREN2_SD4_CIDXSIGEN_MASK           0x00080000
+#define SD4_EMMC_TOP_INTREN2_SD4_CEBSIGEN_SHIFT           18
+#define SD4_EMMC_TOP_INTREN2_SD4_CEBSIGEN_MASK            0x00040000
+#define SD4_EMMC_TOP_INTREN2_SD4_CMDCRCSIGEN_SHIFT        17
+#define SD4_EMMC_TOP_INTREN2_SD4_CMDCRCSIGEN_MASK         0x00020000
+#define SD4_EMMC_TOP_INTREN2_SD4_CMDTOSIGEN_SHIFT         16
+#define SD4_EMMC_TOP_INTREN2_SD4_CMDTOSIGEN_MASK          0x00010000
+#define SD4_EMMC_TOP_INTREN2_SD4_FIXZERO_SHIFT            15
+#define SD4_EMMC_TOP_INTREN2_SD4_FIXZERO_MASK             0x00008000
+#define SD4_EMMC_TOP_INTREN2_SD4_RETUNE_EVENTSIGEN_SHIFT  12
+#define SD4_EMMC_TOP_INTREN2_SD4_RETUNE_EVENTSIGEN_MASK   0x00001000
+#define SD4_EMMC_TOP_INTREN2_SD4_INT_C_SIGEN_SHIFT        11
+#define SD4_EMMC_TOP_INTREN2_SD4_INT_C_SIGEN_MASK         0x00000800
+#define SD4_EMMC_TOP_INTREN2_SD4_INT_B_SIGEN_SHIFT        10
+#define SD4_EMMC_TOP_INTREN2_SD4_INT_B_SIGEN_MASK         0x00000400
+#define SD4_EMMC_TOP_INTREN2_SD4_INT_A_SIGEN_SHIFT        9
+#define SD4_EMMC_TOP_INTREN2_SD4_INT_A_SIGEN_MASK         0x00000200
+#define SD4_EMMC_TOP_INTREN2_SD4_CRDIRQEN_SHIFT           8
+#define SD4_EMMC_TOP_INTREN2_SD4_CRDIRQEN_MASK            0x00000100
+#define SD4_EMMC_TOP_INTREN2_SD4_CRDRVMEN_SHIFT           7
+#define SD4_EMMC_TOP_INTREN2_SD4_CRDRVMEN_MASK            0x00000080
+#define SD4_EMMC_TOP_INTREN2_SD4_CRDINSEN_SHIFT           6
+#define SD4_EMMC_TOP_INTREN2_SD4_CRDINSEN_MASK            0x00000040
+#define SD4_EMMC_TOP_INTREN2_SD4_BUFRRDYEN_SHIFT          5
+#define SD4_EMMC_TOP_INTREN2_SD4_BUFRRDYEN_MASK           0x00000020
+#define SD4_EMMC_TOP_INTREN2_SD4_BUFWRDYEN_SHIFT          4
+#define SD4_EMMC_TOP_INTREN2_SD4_BUFWRDYEN_MASK           0x00000010
+#define SD4_EMMC_TOP_INTREN2_SD4_DMAIRQEN_SHIFT           3
+#define SD4_EMMC_TOP_INTREN2_SD4_DMAIRQEN_MASK            0x00000008
+#define SD4_EMMC_TOP_INTREN2_SD4_BLKGAPEN_SHIFT           2
+#define SD4_EMMC_TOP_INTREN2_SD4_BLKGAPEN_MASK            0x00000004
+#define SD4_EMMC_TOP_INTREN2_SD4_TXDONE_SHIFT             1
+#define SD4_EMMC_TOP_INTREN2_SD4_TXDONE_MASK              0x00000002
+#define SD4_EMMC_TOP_INTREN2_SD4_CMDDONE_SHIFT            0
+#define SD4_EMMC_TOP_INTREN2_SD4_CMDDONE_MASK             0x00000001
+
+#define SD4_EMMC_TOP_ERRSTAT_OFFSET                0x0000003C
+#define SD4_EMMC_TOP_ERRSTAT_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_ERRSTAT_TYPE                  uint32_t
+#define SD4_EMMC_TOP_ERRSTAT_RESERVED_MASK         0x3F00FF60
+#define SD4_EMMC_TOP_ERRSTAT_PRESETEN_SHIFT        31
+#define SD4_EMMC_TOP_ERRSTAT_PRESETEN_MASK         0x80000000
+#define SD4_EMMC_TOP_ERRSTAT_ASYNC_INTREN_SHIFT    30
+#define SD4_EMMC_TOP_ERRSTAT_ASYNC_INTREN_MASK     0x40000000
+#define SD4_EMMC_TOP_ERRSTAT_SAMPLECLOCKSEL_SHIFT  23
+#define SD4_EMMC_TOP_ERRSTAT_SAMPLECLOCKSEL_MASK   0x00800000
+#define SD4_EMMC_TOP_ERRSTAT_EXECTUNE_SHIFT        22
+#define SD4_EMMC_TOP_ERRSTAT_EXECTUNE_MASK         0x00400000
+#define SD4_EMMC_TOP_ERRSTAT_DRVSTRESEL_SHIFT      20
+#define SD4_EMMC_TOP_ERRSTAT_DRVSTRESEL_MASK       0x00300000
+#define SD4_EMMC_TOP_ERRSTAT_EN1P8V_SHIFT          19
+#define SD4_EMMC_TOP_ERRSTAT_EN1P8V_MASK           0x00080000
+#define SD4_EMMC_TOP_ERRSTAT_UHSMODESEL_SHIFT      16
+#define SD4_EMMC_TOP_ERRSTAT_UHSMODESEL_MASK       0x00070000
+#define SD4_EMMC_TOP_ERRSTAT_NOCMD_SHIFT           7
+#define SD4_EMMC_TOP_ERRSTAT_NOCMD_MASK            0x00000080
+#define SD4_EMMC_TOP_ERRSTAT_CMDIDXERR_SHIFT       4
+#define SD4_EMMC_TOP_ERRSTAT_CMDIDXERR_MASK        0x00000010
+#define SD4_EMMC_TOP_ERRSTAT_CMDENDERR_SHIFT       3
+#define SD4_EMMC_TOP_ERRSTAT_CMDENDERR_MASK        0x00000008
+#define SD4_EMMC_TOP_ERRSTAT_CMDCRCERR_SHIFT       2
+#define SD4_EMMC_TOP_ERRSTAT_CMDCRCERR_MASK        0x00000004
+#define SD4_EMMC_TOP_ERRSTAT_CMDTOERR_SHIFT        1
+#define SD4_EMMC_TOP_ERRSTAT_CMDTOERR_MASK         0x00000002
+#define SD4_EMMC_TOP_ERRSTAT_CMDNOEXEC_SHIFT       0
+#define SD4_EMMC_TOP_ERRSTAT_CMDNOEXEC_MASK        0x00000001
+
+#define SD4_EMMC_TOP_ERRSTAT_SD4_OFFSET                0x0000003C
+#define SD4_EMMC_TOP_ERRSTAT_SD4_DEFAULT               0x00000000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_TYPE                  uint32_t
+#define SD4_EMMC_TOP_ERRSTAT_SD4_RESERVED_MASK         0x0E00FF40
+#define SD4_EMMC_TOP_ERRSTAT_SD4_PRESETEN_SHIFT        31
+#define SD4_EMMC_TOP_ERRSTAT_SD4_PRESETEN_MASK         0x80000000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_ASYNC_INTREN_SHIFT    30
+#define SD4_EMMC_TOP_ERRSTAT_SD4_ASYNC_INTREN_MASK     0x40000000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_ADDR64_SHIFT          29
+#define SD4_EMMC_TOP_ERRSTAT_SD4_ADDR64_MASK           0x20000000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_HOSTVER4_00_SHIFT     28
+#define SD4_EMMC_TOP_ERRSTAT_SD4_HOSTVER4_00_MASK      0x10000000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_UHS2INTFEN_SHIFT      24
+#define SD4_EMMC_TOP_ERRSTAT_SD4_UHS2INTFEN_MASK       0x01000000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_SAMPLECLOCKSEL_SHIFT  23
+#define SD4_EMMC_TOP_ERRSTAT_SD4_SAMPLECLOCKSEL_MASK   0x00800000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_EXECTUNE_SHIFT        22
+#define SD4_EMMC_TOP_ERRSTAT_SD4_EXECTUNE_MASK         0x00400000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_DRVSTRESEL_SHIFT      20
+#define SD4_EMMC_TOP_ERRSTAT_SD4_DRVSTRESEL_MASK       0x00300000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_EN1P8V_SHIFT          19
+#define SD4_EMMC_TOP_ERRSTAT_SD4_EN1P8V_MASK           0x00080000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_UHSMODESEL_SHIFT      16
+#define SD4_EMMC_TOP_ERRSTAT_SD4_UHSMODESEL_MASK       0x00070000
+#define SD4_EMMC_TOP_ERRSTAT_SD4_NOCMD_SHIFT           7
+#define SD4_EMMC_TOP_ERRSTAT_SD4_NOCMD_MASK            0x00000080
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDRESPERR_SHIFT      5
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDRESPERR_MASK       0x00000020
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDIDXERR_SHIFT       4
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDIDXERR_MASK        0x00000010
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDENDERR_SHIFT       3
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDENDERR_MASK        0x00000008
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDCRCERR_SHIFT       2
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDCRCERR_MASK        0x00000004
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDTOERR_SHIFT        1
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDTOERR_MASK         0x00000002
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDNOEXEC_SHIFT       0
+#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDNOEXEC_MASK        0x00000001
+
+#define SD4_EMMC_TOP_CAPABILITIES1_OFFSET           0x00000040
+#define SD4_EMMC_TOP_CAPABILITIES1_DEFAULT          0x17EFD0B0
+#define SD4_EMMC_TOP_CAPABILITIES1_TYPE             uint32_t
+#define SD4_EMMC_TOP_CAPABILITIES1_RESERVED_MASK    0x08100040
+#define SD4_EMMC_TOP_CAPABILITIES1_SLOTTYPE_SHIFT   30
+#define SD4_EMMC_TOP_CAPABILITIES1_SLOTTYPE_MASK    0xC0000000
+#define SD4_EMMC_TOP_CAPABILITIES1_ASYNCHIRQ_SHIFT  29
+#define SD4_EMMC_TOP_CAPABILITIES1_ASYNCHIRQ_MASK   0x20000000
+#define SD4_EMMC_TOP_CAPABILITIES1_SYSBUS64_SHIFT   28
+#define SD4_EMMC_TOP_CAPABILITIES1_SYSBUS64_MASK    0x10000000
+#define SD4_EMMC_TOP_CAPABILITIES1_V18_SHIFT        26
+#define SD4_EMMC_TOP_CAPABILITIES1_V18_MASK         0x04000000
+#define SD4_EMMC_TOP_CAPABILITIES1_V3_SHIFT         25
+#define SD4_EMMC_TOP_CAPABILITIES1_V3_MASK          0x02000000
+#define SD4_EMMC_TOP_CAPABILITIES1_V33_SHIFT        24
+#define SD4_EMMC_TOP_CAPABILITIES1_V33_MASK         0x01000000
+#define SD4_EMMC_TOP_CAPABILITIES1_SUPRSM_SHIFT     23
+#define SD4_EMMC_TOP_CAPABILITIES1_SUPRSM_MASK      0x00800000
+#define SD4_EMMC_TOP_CAPABILITIES1_SDMA_SHIFT       22
+#define SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK        0x00400000
+#define SD4_EMMC_TOP_CAPABILITIES1_HSPEED_SHIFT     21
+#define SD4_EMMC_TOP_CAPABILITIES1_HSPEED_MASK      0x00200000
+#define SD4_EMMC_TOP_CAPABILITIES1_ADMA2_SHIFT      19
+#define SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK       0x00080000
+#define SD4_EMMC_TOP_CAPABILITIES1_EXTBUSMED_SHIFT  18
+#define SD4_EMMC_TOP_CAPABILITIES1_EXTBUSMED_MASK   0x00040000
+#define SD4_EMMC_TOP_CAPABILITIES1_MAXBLK_SHIFT     16
+#define SD4_EMMC_TOP_CAPABILITIES1_MAXBLK_MASK      0x00030000
+#define SD4_EMMC_TOP_CAPABILITIES1_BCLK_SHIFT       8
+#define SD4_EMMC_TOP_CAPABILITIES1_BCLK_MASK        0x0000FF00
+#define SD4_EMMC_TOP_CAPABILITIES1_TOUT_SHIFT       7
+#define SD4_EMMC_TOP_CAPABILITIES1_TOUT_MASK        0x00000080
+#define SD4_EMMC_TOP_CAPABILITIES1_TOUTFREQ_SHIFT   0
+#define SD4_EMMC_TOP_CAPABILITIES1_TOUTFREQ_MASK    0x0000003F
+
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_OFFSET           0x00000040
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_DEFAULT          0x10E934B4
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TYPE             uint32_t
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_RESERVED_MASK    0x08100040
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SLOTTYPE_SHIFT   30
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SLOTTYPE_MASK    0xC0000000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ASYNCHIRQ_SHIFT  29
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ASYNCHIRQ_MASK   0x20000000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SYSBUS64_SHIFT   28
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SYSBUS64_MASK    0x10000000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V18_SHIFT        26
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V18_MASK         0x04000000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V3_SHIFT         25
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V3_MASK          0x02000000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V33_SHIFT        24
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V33_MASK         0x01000000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SUPRSM_SHIFT     23
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SUPRSM_MASK      0x00800000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SDMA_SHIFT       22
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SDMA_MASK        0x00400000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_HSPEED_SHIFT     21
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_HSPEED_MASK      0x00200000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ADMA2_SHIFT      19
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ADMA2_MASK       0x00080000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_EXTBUSMED_SHIFT  18
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_EXTBUSMED_MASK   0x00040000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_MAXBLK_SHIFT     16
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_MAXBLK_MASK      0x00030000
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_BCLK_SHIFT       8
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_BCLK_MASK        0x0000FF00
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUT_SHIFT       7
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUT_MASK        0x00000080
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUTFREQ_SHIFT   0
+#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUTFREQ_MASK    0x0000003F
+
+#define SD4_EMMC_TOP_CAPABILITIES2_OFFSET               0x00000044
+#define SD4_EMMC_TOP_CAPABILITIES2_DEFAULT              0x03002177
+#define SD4_EMMC_TOP_CAPABILITIES2_TYPE                 uint32_t
+#define SD4_EMMC_TOP_CAPABILITIES2_RESERVED_MASK        0xFC001088
+#define SD4_EMMC_TOP_CAPABILITIES2_SPIBLOCKMODE_SHIFT   25
+#define SD4_EMMC_TOP_CAPABILITIES2_SPIBLOCKMODE_MASK    0x02000000
+#define SD4_EMMC_TOP_CAPABILITIES2_SPIMODE_CAP_SHIFT    24
+#define SD4_EMMC_TOP_CAPABILITIES2_SPIMODE_CAP_MASK     0x01000000
+#define SD4_EMMC_TOP_CAPABILITIES2_CLOCKMULT_SHIFT      16
+#define SD4_EMMC_TOP_CAPABILITIES2_CLOCKMULT_MASK       0x00FF0000
+#define SD4_EMMC_TOP_CAPABILITIES2_RETUNE_MODE_SHIFT    14
+#define SD4_EMMC_TOP_CAPABILITIES2_RETUNE_MODE_MASK     0x0000C000
+#define SD4_EMMC_TOP_CAPABILITIES2_USETUNE_SDR50_SHIFT  13
+#define SD4_EMMC_TOP_CAPABILITIES2_USETUNE_SDR50_MASK   0x00002000
+#define SD4_EMMC_TOP_CAPABILITIES2_TMRCNT_RETUNE_SHIFT  8
+#define SD4_EMMC_TOP_CAPABILITIES2_TMRCNT_RETUNE_MASK   0x00000F00
+#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPED_SHIFT     6
+#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPED_MASK      0x00000040
+#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEC_SHIFT     5
+#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEC_MASK      0x00000020
+#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEA_SHIFT     4
+#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEA_MASK      0x00000010
+#define SD4_EMMC_TOP_CAPABILITIES2_DDR50_SHIFT          2
+#define SD4_EMMC_TOP_CAPABILITIES2_DDR50_MASK           0x00000004
+#define SD4_EMMC_TOP_CAPABILITIES2_SDR104_SHIFT         1
+#define SD4_EMMC_TOP_CAPABILITIES2_SDR104_MASK          0x00000002
+#define SD4_EMMC_TOP_CAPABILITIES2_SDR50_SHIFT          0
+#define SD4_EMMC_TOP_CAPABILITIES2_SDR50_MASK           0x00000001
+
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_OFFSET               0x00000044
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DEFAULT              0x10000064
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TYPE                 uint32_t
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RESERVED_MASK        0xE7001080
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_VDD2_18_SHIFT        28
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_VDD2_18_MASK         0x10000000
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_ADMA3_SHIFT          27
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_ADMA3_MASK           0x08000000
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_CLOCKMULT_SHIFT      16
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_CLOCKMULT_MASK       0x00FF0000
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RETUNE_MODE_SHIFT    14
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RETUNE_MODE_MASK     0x0000C000
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_USETUNE_SDR50_SHIFT  13
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_USETUNE_SDR50_MASK   0x00002000
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TMRCNT_RETUNE_SHIFT  8
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TMRCNT_RETUNE_MASK   0x00000F00
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPED_SHIFT     6
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPED_MASK      0x00000040
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEC_SHIFT     5
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEC_MASK      0x00000020
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEA_SHIFT     4
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEA_MASK      0x00000010
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_UHS_II_SHIFT         3
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_UHS_II_MASK          0x00000008
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DDR50_SHIFT          2
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DDR50_MASK           0x00000004
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR104_SHIFT         1
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR104_MASK          0x00000002
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR50_SHIFT          0
+#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR50_MASK           0x00000001
+
+#define SD4_EMMC_TOP_MAX_A1_OFFSET                  0x00000048
+#define SD4_EMMC_TOP_MAX_A1_DEFAULT                 0x00000001
+#define SD4_EMMC_TOP_MAX_A1_TYPE                    uint32_t
+#define SD4_EMMC_TOP_MAX_A1_RESERVED_MASK           0xFF000000
+#define SD4_EMMC_TOP_MAX_A1_MAXA18_SHIFT            16
+#define SD4_EMMC_TOP_MAX_A1_MAXA18_MASK             0x00FF0000
+#define SD4_EMMC_TOP_MAX_A1_MAXA30_SHIFT            8
+#define SD4_EMMC_TOP_MAX_A1_MAXA30_MASK             0x0000FF00
+#define SD4_EMMC_TOP_MAX_A1_MAXA33_SHIFT            0
+#define SD4_EMMC_TOP_MAX_A1_MAXA33_MASK             0x000000FF
+
+#define SD4_EMMC_TOP_MAX_A2_OFFSET                  0x0000004C
+#define SD4_EMMC_TOP_MAX_A2_DEFAULT                 0x00000000
+#define SD4_EMMC_TOP_MAX_A2_TYPE                    uint32_t
+#define SD4_EMMC_TOP_MAX_A2_RESERVED_MASK           0xFFFFFFFF
+
+#define SD4_EMMC_TOP_MAX_A2_SD4_OFFSET              0x0000004C
+#define SD4_EMMC_TOP_MAX_A2_SD4_DEFAULT             0x00000001
+#define SD4_EMMC_TOP_MAX_A2_SD4_TYPE                uint32_t
+#define SD4_EMMC_TOP_MAX_A2_SD4_RESERVED_MASK       0xFFFFFF00
+#define SD4_EMMC_TOP_MAX_A2_SD4_MAXAVDD2_SHIFT      0
+#define SD4_EMMC_TOP_MAX_A2_SD4_MAXAVDD2_MASK       0x000000FF
+
+#define SD4_EMMC_TOP_CMDENTSTAT_OFFSET           0x00000050
+#define SD4_EMMC_TOP_CMDENTSTAT_DEFAULT          0x00000000
+#define SD4_EMMC_TOP_CMDENTSTAT_TYPE             uint32_t
+#define SD4_EMMC_TOP_CMDENTSTAT_RESERVED_MASK    0x2C00FF60
+#define SD4_EMMC_TOP_CMDENTSTAT_VSES_SHIFT       30
+#define SD4_EMMC_TOP_CMDENTSTAT_VSES_MASK        0xC0000000
+#define SD4_EMMC_TOP_CMDENTSTAT_TRERR_SHIFT      28
+#define SD4_EMMC_TOP_CMDENTSTAT_TRERR_MASK       0x10000000
+#define SD4_EMMC_TOP_CMDENTSTAT_ADMAERR_SHIFT    25
+#define SD4_EMMC_TOP_CMDENTSTAT_ADMAERR_MASK     0x02000000
+#define SD4_EMMC_TOP_CMDENTSTAT_ACMDERR_SHIFT    24
+#define SD4_EMMC_TOP_CMDENTSTAT_ACMDERR_MASK     0x01000000
+#define SD4_EMMC_TOP_CMDENTSTAT_ILERR_SHIFT      23
+#define SD4_EMMC_TOP_CMDENTSTAT_ILERR_MASK       0x00800000
+#define SD4_EMMC_TOP_CMDENTSTAT_DENDERR_SHIFT    22
+#define SD4_EMMC_TOP_CMDENTSTAT_DENDERR_MASK     0x00400000
+#define SD4_EMMC_TOP_CMDENTSTAT_DCRCERR_SHIFT    21
+#define SD4_EMMC_TOP_CMDENTSTAT_DCRCERR_MASK     0x00200000
+#define SD4_EMMC_TOP_CMDENTSTAT_DTOUTERR_SHIFT   20
+#define SD4_EMMC_TOP_CMDENTSTAT_DTOUTERR_MASK    0x00100000
+#define SD4_EMMC_TOP_CMDENTSTAT_CIDXERR_SHIFT    19
+#define SD4_EMMC_TOP_CMDENTSTAT_CIDXERR_MASK     0x00080000
+#define SD4_EMMC_TOP_CMDENTSTAT_CENDERR_SHIFT    18
+#define SD4_EMMC_TOP_CMDENTSTAT_CENDERR_MASK     0x00040000
+#define SD4_EMMC_TOP_CMDENTSTAT_CCRCERR_SHIFT    17
+#define SD4_EMMC_TOP_CMDENTSTAT_CCRCERR_MASK     0x00020000
+#define SD4_EMMC_TOP_CMDENTSTAT_CTOUTERR_SHIFT   16
+#define SD4_EMMC_TOP_CMDENTSTAT_CTOUTERR_MASK    0x00010000
+#define SD4_EMMC_TOP_CMDENTSTAT_NOFRCENT_SHIFT   7
+#define SD4_EMMC_TOP_CMDENTSTAT_NOFRCENT_MASK    0x00000080
+#define SD4_EMMC_TOP_CMDENTSTAT_IDXERR_SHIFT     4
+#define SD4_EMMC_TOP_CMDENTSTAT_IDXERR_MASK      0x00000010
+#define SD4_EMMC_TOP_CMDENTSTAT_EBITERR_SHIFT    3
+#define SD4_EMMC_TOP_CMDENTSTAT_EBITERR_MASK     0x00000008
+#define SD4_EMMC_TOP_CMDENTSTAT_CRCERR_SHIFT     2
+#define SD4_EMMC_TOP_CMDENTSTAT_CRCERR_MASK      0x00000004
+#define SD4_EMMC_TOP_CMDENTSTAT_TOUTERR_SHIFT    1
+#define SD4_EMMC_TOP_CMDENTSTAT_TOUTERR_MASK     0x00000002
+#define SD4_EMMC_TOP_CMDENTSTAT_AUTONOEX_SHIFT   0
+#define SD4_EMMC_TOP_CMDENTSTAT_AUTONOEX_MASK    0x00000001
+
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_OFFSET          0x00000050
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DEFAULT         0x00000000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TYPE            uint32_t
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESERVED_MASK   0x0000FF40
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_VSES_SHIFT      28
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_VSES_MASK       0xF0000000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TRESPERR_SHIFT  27
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TRESPERR_MASK   0x08000000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TUNERR_SHIFT    26
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TUNERR_MASK     0x04000000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ADMAERR_SHIFT   25
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ADMAERR_MASK    0x02000000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ACMDERR_SHIFT   24
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ACMDERR_MASK    0x01000000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ILERR_SHIFT     23
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ILERR_MASK      0x00800000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DENDERR_SHIFT   22
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DENDERR_MASK    0x00400000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DCRCERR_SHIFT   21
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DCRCERR_MASK    0x00200000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DTOUTERR_SHIFT  20
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DTOUTERR_MASK   0x00100000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CIDXERR_SHIFT   19
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CIDXERR_MASK    0x00080000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CENDERR_SHIFT   18
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CENDERR_MASK    0x00040000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CCRCERR_SHIFT   17
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CCRCERR_MASK    0x00020000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CTOUTERR_SHIFT  16
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CTOUTERR_MASK   0x00010000
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_NOFRCENT_SHIFT  7
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_NOFRCENT_MASK   0x00000080
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESPERR_SHIFT   5
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESPERR_MASK    0x00000020
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_IDXERR_SHIFT    4
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_IDXERR_MASK     0x00000010
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_EBITERR_SHIFT   3
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_EBITERR_MASK    0x00000008
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CRCERR_SHIFT    2
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CRCERR_MASK     0x00000004
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TOUTERR_SHIFT   1
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TOUTERR_MASK    0x00000002
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_AUTONOEX_SHIFT  0
+#define SD4_EMMC_TOP_CMDENTSTAT_SD4_AUTONOEX_MASK   0x00000001
+
+#define SD4_EMMC_TOP_ADMAERR_OFFSET                 0x00000054
+#define SD4_EMMC_TOP_ADMAERR_DEFAULT                0x00000000
+#define SD4_EMMC_TOP_ADMAERR_TYPE                   uint32_t
+#define SD4_EMMC_TOP_ADMAERR_RESERVED_MASK          0xFFFFFFF8
+#define SD4_EMMC_TOP_ADMAERR_ADMALERR_SHIFT         2
+#define SD4_EMMC_TOP_ADMAERR_ADMALERR_MASK          0x00000004
+#define SD4_EMMC_TOP_ADMAERR_ADMAERR_SHIFT          0
+#define SD4_EMMC_TOP_ADMAERR_ADMAERR_MASK           0x00000003
+
+#define SD4_EMMC_TOP_ADMAADDR0_OFFSET               0x00000058
+#define SD4_EMMC_TOP_ADMAADDR0_DEFAULT              0x00000000
+#define SD4_EMMC_TOP_ADMAADDR0_TYPE                 uint32_t
+#define SD4_EMMC_TOP_ADMAADDR0_RESERVED_MASK        0x00000000
+#define SD4_EMMC_TOP_ADMAADDR0_ADMAADDR0_SHIFT      0
+#define SD4_EMMC_TOP_ADMAADDR0_ADMAADDR0_MASK       0xFFFFFFFF
+
+#define SD4_EMMC_TOP_ADMAADDR1_OFFSET                   0x0000005C
+#define SD4_EMMC_TOP_ADMAADDR1_DEFAULT                  0x00000000
+#define SD4_EMMC_TOP_ADMAADDR1_TYPE                     uint32_t
+#define SD4_EMMC_TOP_ADMAADDR1_RESERVED_MASK            0x00000000
+#define SD4_EMMC_TOP_ADMAADDR1_ADMAADDR1_SHIFT          0
+#define SD4_EMMC_TOP_ADMAADDR1_ADMAADDR1_MASK           0xFFFFFFFF
+
+#define SD4_EMMC_TOP_PRESETVAL1_OFFSET                  0x00000060
+#define SD4_EMMC_TOP_PRESETVAL1_DEFAULT                 0x00000000
+#define SD4_EMMC_TOP_PRESETVAL1_TYPE                    uint32_t
+#define SD4_EMMC_TOP_PRESETVAL1_RESERVED_MASK           0x38003800
+#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_DFS_SHIFT      30
+#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_DFS_MASK       0xC0000000
+#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_DFS_SHIFT     26
+#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_DFS_MASK      0x04000000
+#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_DFS_SHIFT      16
+#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_DFS_MASK       0x03FF0000
+#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_INIT_SHIFT     14
+#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_INIT_MASK      0x0000C000
+#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_INIT_SHIFT    10
+#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_INIT_MASK     0x00000400
+#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_INIT_SHIFT     0
+#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_INIT_MASK      0x000003FF
+
+#define SD4_EMMC_TOP_PRESETVAL2_OFFSET                  0x00000064
+#define SD4_EMMC_TOP_PRESETVAL2_DEFAULT                 0x00000000
+#define SD4_EMMC_TOP_PRESETVAL2_TYPE                    uint32_t
+#define SD4_EMMC_TOP_PRESETVAL2_RESERVED_MASK           0x38003800
+#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_SDR12_SHIFT    30
+#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_SDR12_MASK     0xC0000000
+#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_SDR12_SHIFT   26
+#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_SDR12_MASK    0x04000000
+#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_SDR12_SHIFT    16
+#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_SDR12_MASK     0x03FF0000
+#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_HS_SHIFT       14
+#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_HS_MASK        0x0000C000
+#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_HS_SHIFT      10
+#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_HS_MASK       0x00000400
+#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_HS_SHIFT       0
+#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_HS_MASK        0x000003FF
+
+#define SD4_EMMC_TOP_PRESETVAL3_OFFSET                  0x00000068
+#define SD4_EMMC_TOP_PRESETVAL3_DEFAULT                 0x00000000
+#define SD4_EMMC_TOP_PRESETVAL3_TYPE                    uint32_t
+#define SD4_EMMC_TOP_PRESETVAL3_RESERVED_MASK           0x38003800
+#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR50_SHIFT    30
+#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR50_MASK     0xC0000000
+#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR50_SHIFT   26
+#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR50_MASK    0x04000000
+#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR50_SHIFT    16
+#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR50_MASK     0x03FF0000
+#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR25_SHIFT    14
+#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR25_MASK     0x0000C000
+#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR25_SHIFT   10
+#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR25_MASK    0x00000400
+#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR25_SHIFT    0
+#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR25_MASK     0x000003FF
+
+#define SD4_EMMC_TOP_PRESETVAL4_OFFSET                  0x0000006C
+#define SD4_EMMC_TOP_PRESETVAL4_DEFAULT                 0x00000000
+#define SD4_EMMC_TOP_PRESETVAL4_TYPE                    uint32_t
+#define SD4_EMMC_TOP_PRESETVAL4_RESERVED_MASK           0x38003800
+#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_DDR50_SHIFT    30
+#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_DDR50_MASK     0xC0000000
+#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_DDR50_SHIFT   26
+#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_DDR50_MASK    0x04000000
+#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_DDR50_SHIFT    16
+#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_DDR50_MASK     0x03FF0000
+#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_SDR104_SHIFT   14
+#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_SDR104_MASK    0x0000C000
+#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_SDR104_SHIFT  10
+#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_SDR104_MASK   0x00000400
+#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_SDR104_SHIFT   0
+#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_SDR104_MASK    0x000003FF
+
+#define SD4_EMMC_TOP_BOOTTIMEOUT_OFFSET                        0x00000070
+#define SD4_EMMC_TOP_BOOTTIMEOUT_DEFAULT                       0x00000000
+#define SD4_EMMC_TOP_BOOTTIMEOUT_TYPE                          uint32_t
+#define SD4_EMMC_TOP_BOOTTIMEOUT_RESERVED_MASK                 0x00000000
+#define SD4_EMMC_TOP_BOOTTIMEOUT_BOOTDATATIMEOUTCTRVALUE_SHIFT 0
+#define SD4_EMMC_TOP_BOOTTIMEOUT_BOOTDATATIMEOUTCTRVALUE_MASK  0xFFFFFFFF
+
+#define SD4_EMMC_TOP_DBGSEL_OFFSET         0x00000074
+#define SD4_EMMC_TOP_DBGSEL_DEFAULT        0x00000000
+#define SD4_EMMC_TOP_DBGSEL_TYPE           uint32_t
+#define SD4_EMMC_TOP_DBGSEL_RESERVED_MASK  0xFFFFFFFE
+#define SD4_EMMC_TOP_DBGSEL_DBGSEL_SHIFT   0
+#define SD4_EMMC_TOP_DBGSEL_DBGSEL_MASK    0x00000001
+
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_OFFSET                 0x00000074
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_DEFAULT                0x00000000
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_TYPE                   uint32_t
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_RESERVED_MASK          0xFFFF3800
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_DRVSTRVAL_SHIFT        14
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_DRVSTRVAL_MASK         0x0000C000
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_CLKGENSELVAL_SHIFT     10
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_CLKGENSELVAL_MASK      0x00000400
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_SDCLKFREQSELVAL_SHIFT  0
+#define SD4_EMMC_TOP_UHS2_PRESETVAL_SDCLKFREQSELVAL_MASK   0x000003FF
+
+#define SD4_EMMC_TOP_HCVERSIRQ_OFFSET            0x000000FC
+#define SD4_EMMC_TOP_HCVERSIRQ_DEFAULT           0x10020000
+#define SD4_EMMC_TOP_HCVERSIRQ_TYPE              uint32_t
+#define SD4_EMMC_TOP_HCVERSIRQ_RESERVED_MASK     0x0000FF00
+#define SD4_EMMC_TOP_HCVERSIRQ_VENDVER_SHIFT     24
+#define SD4_EMMC_TOP_HCVERSIRQ_VENDVER_MASK      0xFF000000
+#define SD4_EMMC_TOP_HCVERSIRQ_SPECVER_SHIFT     16
+#define SD4_EMMC_TOP_HCVERSIRQ_SPECVER_MASK      0x00FF0000
+#define SD4_EMMC_TOP_HCVERSIRQ_SIRQ_SHIFT        0
+#define SD4_EMMC_TOP_HCVERSIRQ_SIRQ_MASK         0x000000FF
+
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_OFFSET        0x000000FC
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_DEFAULT       0x01030000
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_TYPE          uint32_t
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_RESERVED_MASK 0x0000FF00
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_VENDVER_SHIFT 24
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_VENDVER_MASK  0xFF000000
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SPECVER_SHIFT 16
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SPECVER_MASK  0x00FF0000
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SIRQ_SHIFT    0
+#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SIRQ_MASK     0x000000FF
+
+#endif /* BRCM_RDB_SD4_EMMC_TOP_H */
diff --git a/include/drivers/brcm/emmc/emmc_chal_sd.h b/include/drivers/brcm/emmc/emmc_chal_sd.h
new file mode 100644
index 0000000..8d223f9
--- /dev/null
+++ b/include/drivers/brcm/emmc/emmc_chal_sd.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef	CHAL_SD_H
+#define	CHAL_SD_H
+
+#include <stddef.h>
+
+#define BASE_CLK_FREQ   (200 * 1000 * 1000)
+#define INIT_CLK_FREQ   (400 * 1000)
+
+#define SD_ERROR_RECOVERABLE                   0
+#define SD_ERROR_NON_RECOVERABLE               1
+
+#define SD_OK                                  0
+#define SD_FAIL                                (-1)
+#define SD_INVALID_HANDLE                      (-2)
+#define SD_CEATA_INIT_ERROR                    (-3)
+#define SD_RESET_ERROR                         (-4)
+#define SD_CARD_INIT_ERROR                     (-5)
+#define SD_INV_DATA_WIDTH                      (-6)
+#define SD_SET_BUS_WIDTH_ERROR                 (-7)
+#define SD_DMA_NOT_SUPPORT                     (-8)
+#define SD_SDIO_READ_ERROR                     (-9)
+#define SD_SDIO_WRITE_ERROR                    (-10)
+#define SD_WRITE_ERROR                         (-11)
+#define SD_READ_ERROR                          (-12)
+#define SD_READ_SIZE_ERROR                     (-13)
+#define SD_RW_ADDRESS_ERROR                    (-14)
+#define SD_XFER_ADDRESS_ERROR                  (-15)
+#define SD_DATA_XFER_ADDR_ERROR                (-16)
+#define SD_DATA_XFER_ERROR                     (-17)
+#define SD_WRITE_SIZE_ERROR                    (-18)
+#define SD_CMD_STATUS_UPDATE_ERR               (-19)
+#define SD_CMD12_ERROR                         (-20)
+#define SD_CMD_DATA_ERROR                      (-21)
+#define SD_CMD_TIMEOUT                         (-22)
+#define SD_CMD_NO_RESPONSE                     (-22)
+#define SD_CMD_ABORT_ERROR                     (-23)
+#define SD_CMD_INVALID                         (-24)
+#define SD_CMD_RESUME_ERROR                    (-25)
+#define SD_CMD_ERR_INVALID_RESPONSE            (-26)
+#define SD_WAIT_TIMEOUT                        (-27)
+#define SD_READ_TIMEOUT                        (-28)
+#define SD_CEATA_REST_ERROR                    (-29)
+#define SD_INIT_CAED_FAILED                    (-30)
+#define SD_ERROR_CLOCK_OFFLIMIT                (-31)
+#define SD_INV_SLOT                            (-32)
+
+#define SD_NOR_INTERRUPTS                      0x000000FF
+#define SD_ERR_INTERRUPTS                      0x03FF0000
+#define SD_CMD_ERROR_INT                       0x010F0000
+#define SD_DAT_ERROR_INT                       0x02F00000
+#define SD_DAT_TIMEOUT                         0x00100000
+
+/* Operation modes */
+#define SD_PIO_MODE		               0
+#define SD_INT_MODE		               1
+
+/* Support both ADMA and SDMA (for version 2.0 and above) */
+#define SD_DMA_OFF                             0
+#define SD_DMA_SDMA                            1
+#define SD_DMA_ADMA                            2
+
+#define SD_NORMAL_SPEED                        0
+#define SD_HIGH_SPEED                          1
+
+#define SD_XFER_CARD_TO_HOST                   3
+#define SD_XFER_HOST_TO_CARD                   4
+
+#define SD_CARD_DETECT_AUTO                    0
+#define SD_CARD_DETECT_SD                      1
+#define SD_CARD_DETECT_SDIO                    2
+#define SD_CARD_DETECT_MMC                     3
+#define SD_CARD_DETECT_CEATA                   4
+
+#define SD_ABORT_SYNC_MODE                     0
+#define SD_ABORT_ASYNC_MODE                    1
+
+#define SD_CMD_ERROR_FLAGS                     (0x18F << 16)
+#define SD_DATA_ERROR_FLAGS                    (0x70  << 16)
+#define SD_AUTO_CMD12_ERROR_FLAGS              (0x9F)
+
+#define SD_CARD_STATUS_ERROR                   0x10000000
+#define SD_CMD_MISSING                         0x80000000
+#define SD_ERROR_INT                           0x8000
+
+#define SD_TRAN_HIGH_SPEED                     0x32
+#define SD_CARD_HIGH_CAPACITY                  0x40000000
+#define SD_CARD_POWER_UP_STATUS                0x80000000
+
+#define	SD_HOST_CORE_TIMEOUT                   0x0E
+
+/* SD CARD and Host Controllers bus width */
+#define	SD_BUS_DATA_WIDTH_1BIT                 0x00
+#define	SD_BUS_DATA_WIDTH_4BIT                 0x02
+#define	SD_BUS_DATA_WIDTH_8BIT                 0x20
+
+/* dma boundary settings */
+#define SD_DMA_BOUNDARY_4K                     0
+#define SD_DMA_BOUNDARY_8K                     (1 << 12)
+#define SD_DMA_BOUNDARY_16K                    (2 << 12)
+#define SD_DMA_BOUNDARY_32K                    (3 << 12)
+#define SD_DMA_BOUNDARY_64K                    (4 << 12)
+#define SD_DMA_BOUNDARY_128K                   (5 << 12)
+#define SD_DMA_BOUNDARY_256K                   (6 << 12)
+#define SD_DMA_BOUNDARY_512K                   (7 << 12)
+
+#define SD_CMDR_CMD_NORMAL                     0x00000000
+#define SD_CMDR_CMD_SUSPEND                    0x00400000
+#define SD_CMDR_CMD_RESUME                     0x00800000
+#define SD_CMDR_CMD_ABORT                      0x00c00000
+
+#define SD_CMDR_RSP_TYPE_NONE                  0x0
+#define SD_CMDR_RSP_TYPE_R2                    0x1
+#define SD_CMDR_RSP_TYPE_R3_4                  0x2
+#define SD_CMDR_RSP_TYPE_R1_5_6                0x2
+#define SD_CMDR_RSP_TYPE_R1b_5b                0x3
+#define SD_CMDR_RSP_TYPE_S                     16
+
+struct sd_ctrl_info {
+	uint32_t blkReg;	/* current block register cache value */
+	uint32_t cmdReg;	/* current command register cache value */
+	uint32_t argReg;	/* current argument register cache value */
+	uint32_t cmdIndex;	/* current command index */
+	uint32_t cmdStatus;	/* current command status, cmd/data compelete */
+	uint16_t rca;	/* relative card address */
+	uint32_t ocr;	/* operation codition */
+	uint32_t eventList;	/* events list */
+	uint32_t blkGapEnable;
+
+	uint32_t capability;	/* controller's capbilities */
+	uint32_t maxCurrent;	/* maximum current supported */
+	uint32_t present;	/* if card is inserted or removed */
+	uint32_t version;	/* SD spec version 1.0 or 2.0 */
+	uint32_t vendor;	/* vendor number */
+
+	uintptr_t sdRegBaseAddr;	/* sdio control registers */
+	uintptr_t hostRegBaseAddr;	/* SD Host control registers */
+};
+
+struct sd_cfg {
+	uint32_t mode;	/* interrupt or polling */
+	uint32_t dma;	/* dma enabled or disabled */
+	uint32_t retryLimit;	/* command retry limit */
+	uint32_t speedMode;	/* speed mode, 0 standard, 1 high speed */
+	uint32_t voltage;	/* voltage level */
+	uint32_t blockSize;	/* access block size (512 for HC card) */
+	uint32_t dmaBoundary;	/* dma address boundary */
+	uint32_t detSignal;	/* card det signal src, for test purpose only */
+	uint32_t rdWaiting;
+	uint32_t wakeupOut;
+	uint32_t wakeupIn;
+	uint32_t wakeupInt;
+	uint32_t wfe_retry;
+	uint32_t gapInt;
+	uint32_t readWait;
+	uint32_t led;
+};
+
+struct sd_dev {
+	struct sd_cfg cfg;		/* SD configuration */
+	struct sd_ctrl_info ctrl;	/* SD info */
+};
+
+int32_t chal_sd_start(CHAL_HANDLE *sdHandle, uint32_t mode,
+		      uint32_t sdBase, uint32_t hostBase);
+int32_t chal_sd_config(CHAL_HANDLE *sdHandle, uint32_t speed,
+		       uint32_t retry, uint32_t boundary,
+		       uint32_t blkSize, uint32_t dma);
+int32_t chal_sd_stop(void);
+int32_t chal_sd_set_dma(CHAL_HANDLE *sdHandle, uint32_t mode);
+uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *handle);
+int32_t chal_sd_config_bus_width(CHAL_HANDLE *sdHandle, int32_t width);
+int32_t chal_sd_send_cmd(CHAL_HANDLE *sdHandle, uint32_t cmdIndex,
+			 uint32_t arg, uint32_t options);
+int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sdHandle, uintptr_t address);
+int32_t chal_sd_set_clock(CHAL_HANDLE *sdHandle,
+			  uint32_t div_ctrl_setting, uint32_t on);
+uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq);
+int32_t chal_sd_setup_xfer(CHAL_HANDLE *sdHandle, uint8_t *data,
+			   uint32_t length, int32_t dir);
+int32_t chal_sd_write_buffer(CHAL_HANDLE *sdHandle, uint32_t length,
+			     uint8_t *data);
+int32_t chal_sd_read_buffer(CHAL_HANDLE *sdHandle, uint32_t length,
+			    uint8_t *data);
+int32_t chal_sd_reset_line(CHAL_HANDLE *sdHandle, uint32_t line);
+int32_t chal_sd_get_response(CHAL_HANDLE *sdHandle, uint32_t *resp);
+int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sdHandle);
+int32_t chal_sd_get_irq_status(CHAL_HANDLE *sdHandle);
+int32_t chal_sd_clear_irq(CHAL_HANDLE *sdHandle, uint32_t mask);
+uint32_t chal_sd_get_present_status(CHAL_HANDLE *sdHandle);
+int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sdHandle);
+void chal_sd_set_speed(CHAL_HANDLE *sdHandle, uint32_t speed);
+int32_t chal_sd_check_cap(CHAL_HANDLE *sdHandle, uint32_t cap);
+void chal_sd_set_irq_signal(CHAL_HANDLE *sdHandle, uint32_t mask,
+			    uint32_t state);
+void chal_sd_dump_fifo(CHAL_HANDLE *sdHandle);
+#endif /* CHAL_SD_H */
diff --git a/include/drivers/brcm/emmc/emmc_chal_types.h b/include/drivers/brcm/emmc/emmc_chal_types.h
new file mode 100644
index 0000000..9563273
--- /dev/null
+++ b/include/drivers/brcm/emmc/emmc_chal_types.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef CHAL_TYPES_H
+#define CHAL_TYPES_H
+
+#include <stdint.h>
+
+//
+// Generic cHAL handler
+//
+#ifndef CHAL_HANDLE
+	typedef void *CHAL_HANDLE;	///< void pointer (32 bits wide)
+#endif
+
+#endif	/* _CHAL_TYPES_H_ */
diff --git a/include/drivers/brcm/emmc/emmc_csl_sd.h b/include/drivers/brcm/emmc/emmc_csl_sd.h
new file mode 100644
index 0000000..52b8bc8
--- /dev/null
+++ b/include/drivers/brcm/emmc/emmc_csl_sd.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef	CSL_SD_H
+#define	CSL_SD_H
+
+#define SD_CLOCK_BASE				104000000
+#define SD_CLOCK_52MHZ				52000000
+#define SD_CLOCK_26MHZ				26000000
+#define SD_CLOCK_17MHZ				17330000
+#define SD_CLOCK_13MHZ				13000000
+#define SD_CLOCK_10MHZ				10000000
+#define SD_CLOCK_9MHZ				9000000
+#define SD_CLOCK_7MHZ				7000000
+#define SD_CLOCK_5MHZ				5000000
+#define SD_CLOCK_1MHZ				1000000
+#define SD_CLOCK_400KHZ				400000
+
+#define SD_DRIVE_STRENGTH_MASK			0x38000000
+#if defined(_BCM213x1_) || defined(_BCM21551_) || defined(_ATHENA_)
+#define SD_DRIVE_STRENGTH			0x28000000
+#elif defined(_BCM2153_)
+#define SD_DRIVE_STRENGTH			0x38000000
+#else
+#define SD_DRIVE_STRENGTH			0x00000000
+#endif
+
+#define SD_NUM_HOST				2
+
+#define SD_CARD_UNLOCK				0
+#define SD_CARD_LOCK				0x4
+#define SD_CARD_CLEAR_PWD			0x2
+#define SD_CARD_SET_PWD				0x1
+#define	SD_CARD_ERASE_PWD			0x8
+
+#define SD_CARD_LOCK_STATUS			0x02000000
+#define SD_CARD_UNLOCK_STATUS			0x01000000
+
+#define SD_CMD_ERROR_FLAGS			(0x18F << 16)
+#define SD_DATA_ERROR_FLAGS			(0x70  << 16)
+#define SD_AUTO_CMD12_ERROR_FLAGS		(0x9F)
+#define SD_CARD_STATUS_ERROR			0x10000000
+#define SD_CMD_MISSING				0x80000000
+
+#define SD_TRAN_HIGH_SPEED			0x32
+#define SD_CARD_HIGH_CAPACITY			0x40000000
+#define SD_CARD_POWER_UP_STATUS			0x80000000
+
+struct sd_dev_info {
+	uint32_t mode; /* interrupt or polling */
+	uint32_t dma; /* dma enabled or disabled */
+	uint32_t voltage; /* voltage level */
+	uint32_t slot; /* if the HC is locatd at slot 0 or slot 1 */
+	uint32_t version; /* 1.0 or 2.0 */
+	uint32_t curSystemAddr; /* system address */
+	uint32_t dataWidth; /* data width for the controller */
+	uint32_t clock; /* clock rate */
+	uint32_t status; /* if device is active on transfer or not */
+};
+
+void data_xfer_setup(struct sd_handle *handle, uint8_t *data,
+		     uint32_t length, int dir);
+int reset_card(struct sd_handle *handle);
+int reset_host_ctrl(struct sd_handle *handle);
+int init_card(struct sd_handle *handle, int detection);
+int init_mmc_card(struct sd_handle *handle);
+int write_buffer(struct sd_handle *handle, uint32_t len, uint8_t *buffer);
+int read_buffer(struct sd_handle *handle, uint32_t len, uint8_t *buffer);
+int select_blk_sz(struct sd_handle *handle, uint16_t size);
+int check_error(struct sd_handle *handle, uint32_t ints);
+
+int process_data_xfer(struct sd_handle *handle, uint8_t *buffer,
+			  uint32_t addr, uint32_t length, int dir);
+int read_block(struct sd_handle *handle, uint8_t *dst, uint32_t addr,
+		uint32_t len);
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks);
+#endif
+int write_block(struct sd_handle *handle, uint8_t *src, uint32_t addr,
+		 uint32_t len);
+int process_cmd_response(struct sd_handle *handle, uint32_t cmdIndex,
+			 uint32_t rsp0, uint32_t rsp1, uint32_t rsp2,
+			 uint32_t rsp3, struct sd_resp *resp);
+int32_t set_config(struct sd_handle *handle, uint32_t speed,
+		   uint32_t retry, uint32_t dma, uint32_t dmaBound,
+		   uint32_t blkSize, uint32_t wfe_retry);
+
+uint32_t wait_for_event(struct sd_handle *handle, uint32_t mask,
+			uint32_t retry);
+int set_boot_config(struct sd_handle *handle, uint32_t config);
+
+int mmc_cmd1(struct sd_handle *handle);
+#endif /* CSL_SD_H */
diff --git a/include/drivers/brcm/emmc/emmc_csl_sdcmd.h b/include/drivers/brcm/emmc/emmc_csl_sdcmd.h
new file mode 100644
index 0000000..425603f
--- /dev/null
+++ b/include/drivers/brcm/emmc/emmc_csl_sdcmd.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CSL_SD_CMD_H
+#define CSL_SD_CMD_H
+
+#define SD_CMD_OK      0
+#define SD_CMD_ERROR  -1
+
+#define SD_CMD_ERR_NO_IO_FUNC           5
+#define SD_CMD_ERR_INVALID_PARAMETER    6
+#define SD_CMD_ERR_R1_ILLEGAL_COMMAND   7
+#define SD_CMD_ERR_R1_COM_CRC_ERROR     8
+#define SD_CMD_ERR_R1_FUNC_NUM_ERROR    9
+#define SD_CMD_ERR_R1_ADDRESS_ERROR    10
+#define SD_CMD_ERR_R1_PARAMETER_ERROR  11
+#define SD_CMD_ERR_DATA_ERROR_TOKEN    12
+#define SD_CMD_ERR_DATA_NOT_ACCEPTED   13
+#define SD_CMD7_ARG_RCA_SHIFT          16
+
+#define SD_CARD_STATUS_PENDING                 0x01
+#define SD_CARD_STATUS_BUFFER_OVERFLOW         0x01
+#define SD_CARD_STATUS_DEVICE_BUSY             0x02
+#define SD_CARD_STATUS_UNSUCCESSFUL            0x03
+#define SD_CARD_STATUS_NOT_IMPLEMENTED         0x04
+#define SD_CARD_STATUS_ACCESS_VIOLATION        0x05
+#define SD_CARD_STATUS_INVALID_HANDLE          0x06
+#define SD_CARD_STATUS_INVALID_PARAMETER       0x07
+#define SD_CARD_STATUS_NO_SUCH_DEVICE          0x08
+#define SD_CARD_STATUS_INVALID_DEVICE_REQUEST  0x09
+#define SD_CARD_STATUS_NO_MEMORY               0x0A
+#define SD_CARD_STATUS_BUS_DRIVER_NOT_READY    0x0B
+#define SD_CARD_STATUS_DATA_ERROR              0x0C
+#define SD_CARD_STATUS_CRC_ERROR               0x0D
+#define SD_CARD_STATUS_INSUFFICIENT_RESOURCES  0x0E
+#define SD_CARD_STATUS_DEVICE_NOT_CONNECTED    0x10
+#define SD_CARD_STATUS_DEVICE_REMOVED          0x11
+#define SD_CARD_STATUS_DEVICE_NOT_RESPONDING   0x12
+#define SD_CARD_STATUS_CANCELED                0x13
+#define SD_CARD_STATUS_RESPONSE_TIMEOUT        0x14
+#define SD_CARD_STATUS_DATA_TIMEOUT            0x15
+#define SD_CARD_STATUS_DEVICE_RESPONSE_ERROR   0x16
+#define SD_CARD_STATUS_DEVICE_UNSUPPORTED      0x17
+
+/* Response structure */
+struct sd_r2_resp {
+	uint32_t rsp4;	/* 127:96 */
+	uint32_t rsp3;	/* 95:64 */
+	uint32_t rsp2;	/* 63:32 */
+	uint32_t rsp1;	/* 31:0 */
+};
+
+struct sd_r3_resp {
+	uint32_t ocr;
+};
+
+struct sd_r4_resp {
+	uint8_t cardReady;
+	uint8_t funcs;
+	uint8_t memPresent;
+	uint32_t ocr;
+};
+
+struct  sd_r5_resp {
+	uint8_t data;
+};
+
+struct sd_r6_resp {
+	uint16_t rca;
+	uint16_t cardStatus;
+};
+
+struct sd_r7_resp {
+	uint16_t rca;
+};
+
+struct sd_resp {
+	uint8_t r1;
+	uint32_t cardStatus;
+	uint32_t rawData[4];
+	union {
+		struct sd_r2_resp r2;
+		struct sd_r3_resp r3;
+		struct sd_r4_resp r4;
+		struct sd_r5_resp r5;
+		struct sd_r6_resp r6;
+		struct sd_r7_resp r7;
+	} data;
+};
+
+struct sd_card_info {
+	uint32_t type;	/* card type SD, MMC or SDIO */
+	uint64_t size;	/* card size */
+	uint32_t speed;	/* card speed */
+	uint32_t voltage;	/* voltage supported */
+	uint32_t mId;	/* manufacturer ID */
+	uint32_t oId;	/* OEM ID */
+	uint32_t classes;	/* card class */
+	uint32_t name1;	/* product name part 1 */
+	uint32_t name2;	/* product name part 2 */
+	uint32_t revision;	/* revison */
+	uint32_t sn;	/* serial number */
+	uint32_t numIoFuns;	/* total I/O function number */
+	uint32_t maxRdBlkLen;	/* max read block length */
+	uint32_t maxWtBlkLen;	/* max write block length */
+	uint32_t blkMode;	/* sdio card block mode support */
+	uint32_t f0Cis;	/* sdio card block mode support */
+	uint32_t f1Cis;	/* sdio card block mode support */
+
+	uint8_t partRead;	/* partial block read allowed */
+	uint8_t partWrite;	/* partial block write allowed */
+	uint8_t dsr;	/* card DSR */
+	uint8_t rdCurMin;	/* min current for read */
+	uint8_t rdCurMax;	/* max current for read */
+	uint8_t wtCurMin;	/* min current for write */
+	uint8_t wtCurMax;	/* max current for write */
+	uint8_t erase;	/* erase enable */
+	uint8_t eraseSecSize;	/* erase sector size */
+	uint8_t proGrpSize;	/* write protection group size */
+	uint8_t protect;	/* permanent write protection or not */
+	uint8_t tmpProt;	/* temp write protection or not */
+	uint8_t wtSpeed;	/* write speed relatively to read */
+	uint8_t version;	/* card version 0:1.0 - 1.01, 1:1.10, 2:2.0 */
+	uint8_t eraseState;	/* if the data will be 0 or 1 after erase */
+	uint8_t bus;	/* data with supported */
+	uint8_t security;	/* security support 0, 2:1.01 3:2.0 */
+	uint8_t format;	/* file format */
+	uint8_t fileGrp;	/* file group */
+	char pwd[20];	/* password */
+};
+
+struct sd_handle {
+	struct sd_dev *device;
+	struct sd_card_info *card;
+};
+
+int sd_cmd0(struct sd_handle *handle);
+int sd_cmd1(struct sd_handle *handle, uint32_t initOcr, uint32_t *ocr);
+int sd_cmd2(struct sd_handle *handle);
+int sd_cmd3(struct sd_handle *handle);
+int sd_cmd7(struct sd_handle *handle, uint32_t rca);
+int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card);
+int sd_cmd13(struct sd_handle *handle, uint32_t *status);
+int sd_cmd16(struct sd_handle *handle, uint32_t blockLen);
+int sd_cmd17(struct sd_handle *handle,
+	     uint32_t addr, uint32_t len, uint8_t *buffer);
+int sd_cmd18(struct sd_handle *handle,
+	     uint32_t addr, uint32_t len, uint8_t *buffer);
+#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
+int sd_cmd24(struct sd_handle *handle,
+	     uint32_t addr, uint32_t len, uint8_t *buffer);
+int sd_cmd25(struct sd_handle *handle,
+	     uint32_t addr, uint32_t len, uint8_t *buffer);
+#endif
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+int sd_cmd35(struct sd_handle *handle, uint32_t start);
+int sd_cmd36(struct sd_handle *handle, uint32_t end);
+int sd_cmd38(struct sd_handle *handle);
+#endif
+int mmc_cmd6(struct sd_handle *handle, uint32_t argument);
+int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg);
+
+int send_cmd(struct sd_handle *handle, uint32_t cmdIndex,
+	     uint32_t argument, uint32_t options, struct sd_resp *resp);
+#endif /* CSL_SD_CMD_H */
diff --git a/include/drivers/brcm/emmc/emmc_csl_sdprot.h b/include/drivers/brcm/emmc/emmc_csl_sdprot.h
new file mode 100644
index 0000000..597e1e0
--- /dev/null
+++ b/include/drivers/brcm/emmc/emmc_csl_sdprot.h
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef	CSL_SD_PROT_H
+#define	CSL_SD_PROT_H
+
+#define SD_CARD_UNKNOWN		0	/* bad type or unrecognized */
+#define SD_CARD_SD		1	/* IO only card */
+#define SD_CARD_SDIO		2	/* memory only card */
+#define SD_CARD_COMBO		3	/* IO and memory combo card */
+#define SD_CARD_MMC		4	/* memory only card */
+#define SD_CARD_CEATA		5	/* IO and memory combo card */
+
+#define SD_IO_FIXED_ADDRESS	0	/* fix Address */
+#define SD_IO_INCREMENT_ADDRESS	1
+
+#define SD_HIGH_CAPACITY_CARD	0x40000000
+
+#define MMC_CMD_IDLE_RESET_ARG	0xF0F0F0F0
+
+/* Supported operating voltages are 3.2-3.3 and 3.3-3.4 */
+#define MMC_OCR_OP_VOLT			0x00300000
+/* Enable sector access mode */
+#define MMC_OCR_SECTOR_ACCESS_MODE	0x40000000
+
+/* command index */
+#define SD_CMD_GO_IDLE_STATE		0	/* mandatory for SDIO */
+#define SD_CMD_SEND_OPCOND		1
+#define SD_CMD_ALL_SEND_CID		2
+#define SD_CMD_MMC_SET_RCA		3
+#define SD_CMD_MMC_SET_DSR		4
+#define SD_CMD_IO_SEND_OP_COND		5	/* mandatory for SDIO */
+#define SD_ACMD_SET_BUS_WIDTH		6
+#define SD_CMD_SWITCH_FUNC		6
+#define SD_CMD_SELECT_DESELECT_CARD	7
+#define SD_CMD_READ_EXT_CSD		8
+#define SD_CMD_SEND_CSD			9
+#define SD_CMD_SEND_CID			10
+#define SD_CMD_STOP_TRANSMISSION	12
+#define SD_CMD_SEND_STATUS		13
+#define SD_ACMD_SD_STATUS		13
+#define SD_CMD_GO_INACTIVE_STATE	15
+#define SD_CMD_SET_BLOCKLEN		16
+#define SD_CMD_READ_SINGLE_BLOCK	17
+#define SD_CMD_READ_MULTIPLE_BLOCK	18
+#define SD_CMD_WRITE_BLOCK		24
+#define SD_CMD_WRITE_MULTIPLE_BLOCK	25
+#define SD_CMD_PROGRAM_CSD		27
+#define SD_CMD_SET_WRITE_PROT		28
+#define SD_CMD_CLR_WRITE_PROT		29
+#define SD_CMD_SEND_WRITE_PROT		30
+#define SD_CMD_ERASE_WR_BLK_START	32
+#define SD_CMD_ERASE_WR_BLK_END		33
+#define SD_CMD_ERASE_GROUP_START	35
+#define SD_CMD_ERASE_GROUP_END		36
+#define SD_CMD_ERASE			38
+#define SD_CMD_LOCK_UNLOCK		42
+#define SD_CMD_IO_RW_DIRECT		52	/* mandatory for SDIO */
+#define SD_CMD_IO_RW_EXTENDED		53	/* mandatory for SDIO */
+#define SD_CMD_APP_CMD			55
+#define SD_CMD_GEN_CMD			56
+#define SD_CMD_READ_OCR			58
+#define SD_CMD_CRC_ON_OFF		59	/* mandatory for SDIO */
+#define SD_ACMD_SEND_NUM_WR_BLOCKS	22
+#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT	23
+#define SD_ACMD_SD_SEND_OP_COND		41
+#define SD_ACMD_SET_CLR_CARD_DETECT	42
+#define SD_ACMD_SEND_SCR		51
+
+/* response parameters */
+#define SD_RSP_NO_NONE	0
+#define SD_RSP_NO_1	1
+#define SD_RSP_NO_2	2
+#define SD_RSP_NO_3	3
+#define SD_RSP_NO_4	4
+#define SD_RSP_NO_5	5
+#define SD_RSP_NO_6	6
+
+/* Modified R6 response (to CMD3) */
+#define SD_RSP_MR6_COM_CRC_ERROR	0x8000
+#define SD_RSP_MR6_ILLEGAL_COMMAND	0x4000
+#define SD_RSP_MR6_ERROR		0x2000
+
+/* Modified R1 in R4 Response (to CMD5) */
+#define SD_RSP_MR1_SBIT			0x80
+#define SD_RSP_MR1_PARAMETER_ERROR	0x40
+#define SD_RSP_MR1_RFU5			0x20
+#define SD_RSP_MR1_FUNC_NUM_ERROR	0x10
+#define SD_RSP_MR1_COM_CRC_ERROR	0x80
+#define SD_RSP_MR1_ILLEGAL_COMMAND	0x40
+#define SD_RSP_MR1_RFU1			0x20
+#define SD_RSP_MR1_IDLE_STATE		0x01
+
+/* R5 response (to CMD52 and CMD53) */
+#define SD_RSP_R5_COM_CRC_ERROR		0x80
+#define SD_RSP_R5_ILLEGAL_COMMAND	0x40
+#define SD_RSP_R5_IO_CURRENTSTATE1	0x20
+#define SD_RSP_R5_IO_CURRENTSTATE0	0x10
+#define SD_RSP_R5_ERROR			0x80
+#define SD_RSP_R5_RFU			0x40
+#define SD_RSP_R5_FUNC_NUM_ERROR	0x20
+#define SD_RSP_R5_OUT_OF_RANGE		0x01
+
+/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */
+#define SD_OP_READ			0 /* Read_Write */
+#define SD_OP_WRITE			1 /* Read_Write */
+
+#define SD_RW_NORMAL			0 /* no RAW */
+#define SD_RW_RAW			1 /* RAW */
+
+#define SD_BYTE_MODE			0 /* Byte Mode */
+#define SD_BLOCK_MODE			1 /* BlockMode */
+
+#define SD_FIXED_ADDRESS		0 /* fix Address */
+#define SD_INCREMENT_ADDRESS		1 /* IncrementAddress */
+
+#define SD_CMD5_ARG_IO_OCR_MASK		0x00FFFFFF
+#define SD_CMD5_ARG_IO_OCR_SHIFT	0
+#define SD_CMD55_ARG_RCA_SHIFT		16
+#define SD_CMD59_ARG_CRC_OPTION_MASK	0x01
+#define SD_CMD59_ARG_CRC_OPTION_SHIFT	0
+
+/* SD_CMD_IO_RW_DIRECT Argument */
+#define SdioIoRWDirectArg(rw, raw, func, addr, data) \
+		(((rw & 1) << 31) | ((func & 0x7) << 28) | \
+		((raw & 1) << 27) | ((addr & 0x1FFFF) << 9) | \
+		(data & 0xFF))
+
+/* build SD_CMD_IO_RW_EXTENDED Argument */
+#define SdioIoRWExtArg(rw, blk, func, addr, inc_addr, count) \
+		(((rw & 1) << 31) | ((func & 0x7) << 28) | \
+		((blk & 1) << 27) | ((inc_addr & 1) << 26) | \
+		((addr & 0x1FFFF) << 9) | (count & 0x1FF))
+
+/*
+ * The Common I/O area shall be implemented on all SDIO cards and
+ * is accessed the the host via I/O reads and writes to function 0,
+ * the registers within the CIA are provided to enable/disable
+ * the operationo fthe i/o funciton.
+ */
+
+/* cccr_sdio_rev */
+#define SDIO_REV_SDIOID_MASK		0xf0 /* SDIO spec revision number */
+#define SDIO_REV_CCCRID_MASK		0x0f /* CCCR format version number */
+
+/* sd_rev */
+#define SDIO_REV_PHY_MASK	    0x0f /* SD format version number */
+#define SDIO_FUNC_ENABLE_1	    0x02 /* function 1 I/O enable */
+#define SDIO_FUNC_READY_1	    0x02 /* function 1 I/O ready */
+#define SDIO_INTR_CTL_FUNC1_EN	    0x2  /* interrupt enable for function 1 */
+#define SDIO_INTR_CTL_MASTER_EN	    0x1  /* interrupt enable master */
+#define SDIO_INTR_STATUS_FUNC1	    0x2  /* interrupt pending for function 1 */
+#define SDIO_IO_ABORT_RESET_ALL	    0x08 /* I/O card reset */
+#define SDIO_IO_ABORT_FUNC_MASK	    0x07 /* abort selection: function x */
+#define SDIO_BUS_CARD_DETECT_DIS    0x80 /* Card Detect disable */
+#define SDIO_BUS_SPI_CONT_INTR_CAP  0x40 /* support continuous SPI interrupt */
+#define SDIO_BUS_SPI_CONT_INTR_EN   0x20 /* continuous SPI interrupt enable */
+#define SDIO_BUS_DATA_WIDTH_MASK    0x03 /* bus width mask */
+#define SDIO_BUS_DATA_WIDTH_4BIT    0x02 /* bus width 4-bit mode */
+#define SDIO_BUS_DATA_WIDTH_1BIT    0x00 /* bus width 1-bit mode */
+
+/* capability */
+#define SDIO_CAP_4BLS  0x80 /* 4-bit support for low speed card */
+#define SDIO_CAP_LSC   0x40 /* low speed card */
+#define SDIO_CAP_E4MI  0x20 /* enable int between block in 4-bit mode */
+#define SDIO_CAP_S4MI  0x10 /* support int between block in 4-bit mode */
+#define SDIO_CAP_SBS   0x08 /* support suspend/resume */
+#define SDIO_CAP_SRW   0x04 /* support read wait */
+#define SDIO_CAP_SMB   0x02 /* support multi-block transfer */
+#define SDIO_CAP_SDC   0x01 /* Support Direct cmd during multi-uint8 transfer */
+
+/* CIA FBR1 registers */
+#define SDIO_FUNC1_INFO           0x100 /* basic info for function 1 */
+#define SDIO_FUNC1_EXT            0x101 /* extension of standard I/O device */
+#define SDIO_CIS_FUNC1_BASE_LOW   0x109 /* function 1 cis address bit 0-7 */
+#define SDIO_CIS_FUNC1_BASE_MID   0x10A /* function 1 cis address bit 8-15 */
+#define SDIO_CIS_FUNC1_BASE_HIGH  0x10B /* function 1 cis address bit 16 */
+#define SDIO_CSA_BASE_LOW         0x10C /* CSA base address uint8_t 0 */
+#define SDIO_CSA_BASE_MID         0x10D /* CSA base address uint8_t 1 */
+#define SDIO_CSA_BASE_HIGH        0x10E /* CSA base address uint8_t 2 */
+#define SDIO_CSA_DATA_OFFSET      0x10F /* CSA data register */
+#define SDIO_IO_BLK_SIZE_LOW      0x110 /* I/O block size uint8_t 0 */
+#define SDIO_IO_BLK_SIZE_HIGH     0x111 /* I/O block size uint8_t 1 */
+
+/* SD_SDIO_FUNC1_INFO bits */
+#define SDIO_FUNC1_INFO_DIC     0x0f	/* device interface code */
+#define SDIO_FUNC1_INFO_CSA     0x40	/* CSA support flag */
+#define SDIO_FUNC1_INFO_CSA_EN  0x80	/* CSA enabled */
+
+/* SD_SDIO_FUNC1_EXT bits */
+#define SDIO_FUNC1_EXT_SHP		0x03	/* support high power */
+#define SDIO_FUNC1_EXT_EHP		0x04	/* enable high power */
+
+/* devctr */
+/* I/O device interface code */
+#define SDIO_DEVCTR_DEVINTER		0x0f
+/* support CSA */
+#define SDIO_DEVCTR_CSA_SUP		0x40
+/* enable CSA */
+#define SDIO_DEVCTR_CSA_EN		0x80
+
+/* ext_dev */
+/* supports high-power mask */
+#define SDIO_HIGHPWR_SUPPORT_M		0x3
+/* enable high power */
+#define SDIO_HIGHPWR_EN			0x4
+/* standard power function(up to 200mA */
+#define SDIO_HP_STD			0
+/* need high power to operate */
+#define SDIO_HP_REQUIRED		0x2
+/* can work with standard power, but prefer high power */
+#define SDIO_HP_DESIRED			0x3
+
+/* misc define */
+/* macro to calculate fbr register base */
+#define FBR_REG_BASE(n)			(n*0x100)
+#define SDIO_FUNC_0			0
+#define SDIO_FUNC_1			1
+#define SDIO_FUNC_2			2
+#define SDIO_FUNC_3			3
+#define SDIO_FUNC_4			4
+#define SDIO_FUNC_5			5
+#define SDIO_FUNC_6			6
+#define SDIO_FUNC_7			7
+
+/* maximum block size for block mode operation */
+#define SDIO_MAX_BLOCK_SIZE		2048
+/* minimum block size for block mode operation */
+#define SDIO_MIN_BLOCK_SIZE		1
+
+/* Card registers: status bit position */
+#define SDIO_STATUS_OUTOFRANGE		31
+#define SDIO_STATUS_COMCRCERROR		23
+#define SDIO_STATUS_ILLEGALCOMMAND	22
+#define SDIO_STATUS_ERROR		19
+#define SDIO_STATUS_IOCURRENTSTATE3	12
+#define SDIO_STATUS_IOCURRENTSTATE2	11
+#define SDIO_STATUS_IOCURRENTSTATE1	10
+#define SDIO_STATUS_IOCURRENTSTATE0	9
+#define SDIO_STATUS_FUN_NUM_ERROR	4
+
+#define GET_SDIOCARD_STATUS(x)		((x >> 9) & 0x0f)
+#define SDIO_STATUS_STATE_IDLE		0
+#define SDIO_STATUS_STATE_READY		1
+#define SDIO_STATUS_STATE_IDENT		2
+#define SDIO_STATUS_STATE_STBY		3
+#define SDIO_STATUS_STATE_TRAN		4
+#define SDIO_STATUS_STATE_DATA		5
+#define SDIO_STATUS_STATE_RCV		6
+#define SDIO_STATUS_STATE_PRG		7
+#define SDIO_STATUS_STATE_DIS		8
+
+/* sprom */
+#define SBSDIO_SPROM_CS        0x10000	/* command and status */
+#define SBSDIO_SPROM_INFO      0x10001	/* info register */
+#define SBSDIO_SPROM_DATA_LOW  0x10002	/* indirect access data uint8_t 0 */
+#define SBSDIO_SPROM_DATA_HIGH 0x10003	/* indirect access data uint8_t 1 */
+#define SBSDIO_SPROM_ADDR_LOW  0x10004	/* indirect access addr uint8_t 0 */
+#define SBSDIO_SPROM_ADDR_HIGH 0x10005	/* indirect access addr uint8_t 0 */
+#define SBSDIO_CHIP_CTRL_DATA  0x10006	/* xtal_pu data output */
+#define SBSDIO_CHIP_CTRL_EN    0x10007	/* xtal_pu enable */
+#define SBSDIO_WATERMARK       0x10008	/* retired in rev 7 */
+#define SBSDIO_DEVICE_CTL      0x10009	/* control busy signal generation */
+
+#define SBSDIO_SPROM_IDLE      0
+#define SBSDIO_SPROM_WRITE     1
+#define SBSDIO_SPROM_READ      2
+#define SBSDIO_SPROM_WEN       4
+#define SBSDIO_SPROM_WDS       7
+#define SBSDIO_SPROM_DONE      8
+
+/* SBSDIO_SPROM_INFO */
+#define SBSDIO_SROM_SZ_MASK		0x03	/* SROM size, 1: 4k, 2: 16k */
+#define SBSDIO_SROM_BLANK		0x04	/* depreciated in corerev 6 */
+#define	SBSDIO_SROM_OTP			0x80	/* OTP present */
+
+/* SBSDIO_CHIP_CTRL */
+/* or'd with onchip xtal_pu, 1: power on oscillator */
+#define SBSDIO_CHIP_CTRL_XTAL		0x01
+
+/* SBSDIO_WATERMARK */
+/* number of bytes minus 1 for sd device to wait before sending data to host */
+#define SBSDIO_WATERMARK_MASK		0x3f
+
+/* SBSDIO_DEVICE_CTL */
+/* 1: device will assert busy signal when receiving CMD53 */
+#define SBSDIO_DEVCTL_SETBUSY		0x01
+/* 1: assertion of sdio interrupt is synchronous to the sdio clock */
+#define SBSDIO_DEVCTL_SPI_INTR_SYNC	0x02
+
+/* function 1 OCP space */
+/* sb offset addr is <= 15 bits, 32k */
+#define SBSDIO_SB_OFT_ADDR_MASK		0x07FFF
+#define SBSDIO_SB_OFT_ADDR_LIMIT	0x08000
+/* sdsdio function 1 OCP space has 16/32 bit section */
+#define SBSDIO_SB_ACCESS_2_4B_FLAG	0x08000
+
+/* direct(mapped) cis space */
+/* MAPPED common CIS address */
+#define SBSDIO_CIS_BASE_COMMON		0x1000
+/* function 0(common) cis size in bytes */
+#define SBSDIO_CIS_FUNC0_LIMIT		0x020
+/* funciton 1 cis size in bytes */
+#define SBSDIO_CIS_SIZE_LIMIT		0x200
+/* cis offset addr is < 17 bits */
+#define SBSDIO_CIS_OFT_ADDR_MASK	0x1FFFF
+/* manfid tuple length, include tuple, link bytes */
+#define SBSDIO_CIS_MANFID_TUPLE_LEN	6
+
+/* indirect cis access (in sprom) */
+/* 8 control bytes first, CIS starts from 8th uint8_t */
+#define SBSDIO_SPROM_CIS_OFFSET		0x8
+/* sdio uint8_t mode: maximum length of one data comamnd */
+#define SBSDIO_BYTEMODE_DATALEN_MAX	64
+/* 4317 supports less */
+#define SBSDIO_BYTEMODE_DATALEN_MAX_4317	52
+/* sdio core function one address mask */
+#define SBSDIO_CORE_ADDR_MASK	0x1FFFF
+
+/* CEATA defines */
+#define CEATA_EXT_CSDBLOCK_SIZE         512
+#define CEATA_FAST_IO                   39
+#define CEATA_MULTIPLE_REGISTER_RW      60
+#define CEATA_MULTIPLE_BLOCK_RW         61
+
+/* defines CE ATA task file registers */
+#define CEATA_SCT_CNT_EXP_REG           0x02
+#define CEATA_LBA_LOW_EXP_REG           0x03
+#define CEATA_LBA_MID_EXP_REG           0x04
+#define CEATA_LBA_HIGH_EXP_REG          0x05
+#define CEATA_CNTRL_REG                 0x06
+#define CEATA_FEATURE_REG               0x09	/* write */
+#define CEATA_ERROR_REG                 0x09	/* read */
+#define CEATA_SCT_CNT_REG               0x0A
+#define CEATA_LBA_LOW_REG               0x0B
+#define CEATA_LBA_MID_REG               0x0C
+#define CEATA_LBA_HIGH_REG              0x0D
+#define CEATA_DEV_HEAD_REG              0x0E
+#define CEATA_STA_REG                   0x0F	/* read */
+#define CEATA_CMD_REG                   0x0F	/* write */
+
+/* defines CEATA control and status registers for ce ata client driver */
+#define CEATA_SCR_TEMPC_REG             0x80
+#define CEATA_SCR_TEMPMAXP_REG          0x84
+#define CEATA_TEMPMINP_REG              0x88
+#define CEATA_SCR_STATUS_REG            0x8C
+#define CEATA_SCR_REALLOCSA_REG         0x90
+#define CEATA_SCR_ERETRACTSA_REG        0x94
+#define CEATA_SCR_CAPABILITIES_REG      0x98
+#define CEATA_SCR_CONTROL_REG           0xC0
+
+/* defines for SCR capabilities register bits for ce ata client driver */
+#define CEATA_SCR_CAP_512               0x00000001
+#define CEATA_SCR_CAP_1K                0x00000002
+#define CEATA_SCR_CAP_4K                0x00000004
+
+/* defines CE ATA Control reg bits for ce ata client driver */
+#define CEATA_CNTRL_ENABLE_INTR         0x00
+#define CEATA_CNTRL_DISABLE_INTR        0x02
+#define CEATA_CNTRL_SRST                0x04
+#define CEATA_CNTRL_RSRST               0x00
+
+/* define CE ATA Status reg bits for ce ata client driver */
+#define CEATA_STA_ERROR_BIT             0x01
+#define CEATA_STA_OVR_BIT               0x02
+#define CEATA_STA_SPT_BIT               0x04
+#define CEATA_STA_DRQ_BIT               0x08
+#define CEATA_STA_DRDY_BIT              0x40
+#define CEATA_STA_BSY_BIT               0x80
+
+/* define CE ATA Error reg bits for ce ata client driver */
+#define CEATA_ERROR_ABORTED_BIT         0x04
+#define CEATA_ERROR_IDNF_BIT            0x10
+#define CEATA_ERROR_UNCORRECTABLE_BIT   0x40
+#define CEATA_ERROR_ICRC_BIT            0x80
+
+/* define CE ATA Commands for ce ata client driver */
+#define CEATA_CMD_IDENTIFY_DEVICE       0xEC
+#define CEATA_CMD_READ_DMA_EXT          0x25
+#define CEATA_CMD_WRITE_DMA_EXT         0x35
+#define CEATA_CMD_STANDBY_IMMEDIATE     0xE0
+#define CEATA_CMD_FLUSH_CACHE_EXT       0xEA
+
+struct csd_mmc {
+	uint32_t padding:8;
+	uint32_t structure:2;
+	uint32_t csdSpecVer:4;
+	uint32_t reserved1:2;
+	uint32_t taac:8;
+	uint32_t nsac:8;
+	uint32_t speed:8;
+	uint32_t classes:12;
+	uint32_t rdBlkLen:4;
+	uint32_t rdBlkPartial:1;
+	uint32_t wrBlkMisalign:1;
+	uint32_t rdBlkMisalign:1;
+	uint32_t dsr:1;
+	uint32_t reserved2:2;
+	uint32_t size:12;
+	uint32_t vddRdCurrMin:3;
+	uint32_t vddRdCurrMax:3;
+	uint32_t vddWrCurrMin:3;
+	uint32_t vddWrCurrMax:3;
+	uint32_t devSizeMulti:3;
+	uint32_t eraseGrpSize:5;
+	uint32_t eraseGrpSizeMulti:5;
+	uint32_t wrProtGroupSize:5;
+	uint32_t wrProtGroupEnable:1;
+	uint32_t manuDefEcc:2;
+	uint32_t wrSpeedFactor:3;
+	uint32_t wrBlkLen:4;
+	uint32_t wrBlkPartial:1;
+	uint32_t reserved5:4;
+	uint32_t protAppl:1;
+	uint32_t fileFormatGrp:1;
+	uint32_t copyFlag:1;
+	uint32_t permWrProt:1;
+	uint32_t tmpWrProt:1;
+	uint32_t fileFormat:2;
+	uint32_t eccCode:2;
+};
+
+/* CSD register*/
+union sd_csd {
+	uint32_t csd[4];
+	struct csd_mmc mmc;
+};
+
+struct sd_card_data {
+	union sd_csd csd;
+};
+#endif /* CSL_SD_PROT_H */
diff --git a/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h b/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h
new file mode 100644
index 0000000..8e61b51
--- /dev/null
+++ b/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PBOOT_HAL_MEMORY_EMMC_DRV_H
+#define PBOOT_HAL_MEMORY_EMMC_DRV_H
+
+#include <drivers/delay_timer.h>
+
+#include "emmc_chal_types.h"
+#include "emmc_chal_sd.h"
+#include "emmc_csl_sdprot.h"
+#include "emmc_csl_sdcmd.h"
+#include "emmc_csl_sd.h"
+#include "emmc_brcm_rdb_sd4_top.h"
+
+#define CLK_SDIO_DIV_52MHZ      0x0
+#define SYSCFG_IOCR4_PAD_10MA   0x38000000
+
+#define SDCLK_CNT_PER_MS  52000
+#define BOOT_ACK_TIMEOUT  (50 * SDCLK_CNT_PER_MS)
+#define BOOT_DATA_TIMEOUT (1000 * SDCLK_CNT_PER_MS)
+
+#define EMMC_BOOT_OK             0
+#define EMMC_BOOT_ERROR          1
+#define EMMC_BOOT_TIMEOUT        2
+#define EMMC_BOOT_INVALIDIMAGE   3
+#define EMMC_BOOT_NO_CARD        4
+
+#define EMMC_USER_AREA             0
+#define EMMC_BOOT_PARTITION1       1
+#define EMMC_BOOT_PARTITION2       2
+#define EMMC_USE_CURRENT_PARTITION 3
+
+#define EMMC_BOOT_PARTITION_SIZE (128*1024)
+#define EMMC_BLOCK_SIZE          512
+#define EMMC_DMA_SIZE            (4*1024)
+
+/*
+ * EMMC4.3 definitions
+ * Table 6 EXT_CSD access mode
+ * Access
+ * Bits Access Name Operation
+ * 00 Command Set The command set is changed according to the Cmd Set field of
+ * the argument
+ * 01 Set Bits The bits in the pointed uint8_t are set,
+ * according to the 1 bits in the Value field.
+ * 10 Clear Bits The bits in the pointed uint8_t are cleared,
+ * according to the 1 bits in the Value field.
+ * 11 Write Byte The Value field is written into the pointed uint8_t.
+ */
+
+#define  SDIO_HW_EMMC_EXT_CSD_WRITE_BYTE             0X03000000
+
+/* Boot bus width1 BOOT_BUS_WIDTH 1 R/W [177] */
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_BUS_WIDTH_OFFSET   0X00B10000
+
+/* Boot configuration BOOT_CONFIG 1 R/W [179] */
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_CONFIG_OFFSET      0X00B30000
+
+/* Bus width mode BUS_WIDTH 1 WO [183] */
+#define SDIO_HW_EMMC_EXT_CSD_BUS_WIDTH_OFFSET        0X00B70000
+
+/*
+ * Bit 6: BOOT_ACK (non-volatile)
+ * 0x0 : No boot acknowledge sent (default)
+ * 0x1 : Boot acknowledge sent during boot operation
+ * Bit[5:3] : BOOT_PARTITION_ENABLE (non-volatile)
+ * User selects boot data that will be sent to master
+ * 0x0 : Device not boot enabled (default)
+ * 0x1 : Boot partition 1 enabled for boot
+ * 0x2 : Boot partition 2 enabled for boot
+ * 0x3-0x6 : Reserved
+ * 0x7 : User area enabled for boot
+ * Bit[2:0] : BOOT_PARTITION_ACCESS
+ * User selects boot partition for read and write operation
+ * 0x0 : No access to boot partition (default)
+ * 0x1 : R/W boot partition 1
+ * 0x2 : R/W boot partition 2
+ * 0x3-0x7 : Reserved
+ */
+
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1     0X00000100
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2     0X00000200
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER      0X00000000
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_BOOT1      0X00004800
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_BOOT2      0X00005000
+#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_USER       0X00007800
+
+#define SD_US_DELAY(x) udelay(x)
+
+#endif
diff --git a/include/drivers/brcm/fru.h b/include/drivers/brcm/fru.h
new file mode 100644
index 0000000..ee863b4
--- /dev/null
+++ b/include/drivers/brcm/fru.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FRU_H
+#define FRU_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/* max string length */
+#define FRU_MAX_STR_LEN      32
+
+/* max number of DDR channels */
+#define BCM_MAX_NR_DDR       3
+
+/* max supported FRU table size */
+#define BCM_MAX_FRU_LEN      512
+
+/* FRU table starting offset */
+#define BCM_FRU_TBL_OFFSET   0x300000
+
+/* FRU time constants */
+#define MINS_PER_DAY        1440
+#define MINS_PER_HOUR       60
+#define FRU_YEAR_START      1996
+#define FRU_MONTH_START     1
+#define FRU_DAY_START       1
+#define MONTHS_PER_YEAR     12
+
+/*
+ * FRU areas based on the spec
+ */
+enum fru_area_name {
+	FRU_AREA_INTERNAL = 0,
+	FRU_AREA_CHASSIS_INFO,
+	FRU_AREA_BOARD_INFO,
+	FRU_AREA_PRODUCT_INFO,
+	FRU_AREA_MRECORD_INFO,
+	FRU_MAX_NR_AREAS
+};
+
+/*
+ * FRU area information
+ *
+ * @use: indicate this area is being used
+ * @version: format version
+ * @offset: offset of this area from the beginning of the FRU table
+ * @len: total length of the area
+ */
+struct fru_area_info {
+	bool use;
+	uint8_t version;
+	unsigned int offset;
+	unsigned int len;
+};
+
+/*
+ * DDR MCB information
+ *
+ * @idx: DDR channel index
+ * @size_mb: DDR size of this channel in MB
+ * @ref_id: DDR MCB reference ID
+ */
+struct ddr_mcb {
+	unsigned int idx;
+	unsigned int size_mb;
+	uint32_t ref_id;
+};
+
+/*
+ * DDR information
+ *
+ * @ddr_info: array that contains MCB related info for each channel
+ */
+struct ddr_info {
+	struct ddr_mcb mcb[BCM_MAX_NR_DDR];
+};
+
+/*
+ * FRU board area information
+ *
+ * @lang: Language code
+ * @mfg_date: Manufacturing date
+ * @manufacturer: Manufacturer
+ * @product_name: Product name
+ * @serial_number: Serial number
+ * @part_number: Part number
+ * @file_id: FRU file ID
+ */
+struct fru_board_info {
+	unsigned char lang;
+	unsigned int mfg_date;
+	unsigned char manufacturer[FRU_MAX_STR_LEN];
+	unsigned char product_name[FRU_MAX_STR_LEN];
+	unsigned char serial_number[FRU_MAX_STR_LEN];
+	unsigned char part_number[FRU_MAX_STR_LEN];
+	unsigned char file_id[FRU_MAX_STR_LEN];
+};
+
+/*
+ * FRU manufacture date in human readable format
+ */
+struct fru_time {
+	unsigned int min;
+	unsigned int hour;
+	unsigned int day;
+	unsigned int month;
+	unsigned int year;
+};
+
+#ifdef USE_FRU
+int fru_validate(uint8_t *data, struct fru_area_info *fru_area);
+int fru_parse_ddr(uint8_t *data, struct fru_area_info *area,
+		  struct ddr_info *ddr);
+int fru_parse_board(uint8_t *data, struct fru_area_info *area,
+		    struct fru_board_info *board);
+void fru_format_time(unsigned int min, struct fru_time *tm);
+#else
+static inline int fru_validate(uint8_t *data, struct fru_area_info *fru_area)
+{
+	return -1;
+}
+
+static inline int fru_parse_ddr(uint8_t *data, struct fru_area_info *area,
+				struct ddr_info *ddr)
+{
+	return -1;
+}
+
+static inline int fru_parse_board(uint8_t *data, struct fru_area_info *area,
+				  struct fru_board_info *board)
+{
+	return -1;
+}
+
+static inline void fru_format_time(unsigned int min, struct fru_time *tm)
+{
+}
+#endif /* USE_FRU */
+
+#endif /* FRU_H */
diff --git a/include/drivers/brcm/iproc_gpio.h b/include/drivers/brcm/iproc_gpio.h
new file mode 100644
index 0000000..be971f6
--- /dev/null
+++ b/include/drivers/brcm/iproc_gpio.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IPROC_GPIO_H
+#define IPROC_GPIO_H
+
+#ifdef USE_GPIO
+void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base,
+		     uintptr_t pinconf_base);
+#else
+static void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base,
+			    uintptr_t pinconf_base)
+{
+}
+#endif /* IPROC_GPIO */
+
+#endif /* IPROC_GPIO_H */
diff --git a/include/drivers/brcm/ocotp.h b/include/drivers/brcm/ocotp.h
new file mode 100644
index 0000000..830b3e4
--- /dev/null
+++ b/include/drivers/brcm/ocotp.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef OCOTP_H
+#define OCOTP_H
+
+#include <stdint.h>
+
+struct otpc_map {
+	/* in words. */
+	uint32_t otpc_row_size;
+	/* 128 bit row / 4 words support. */
+	uint16_t data_r_offset[4];
+	/* 128 bit row / 4 words support. */
+	uint16_t data_w_offset[4];
+	int word_size;
+	int stride;
+};
+
+int bcm_otpc_init(struct otpc_map *map);
+int bcm_otpc_read(unsigned int offset, void *val, uint32_t bytes,
+		  uint32_t ecc_flag);
+
+#endif /* OCOTP_H */
diff --git a/include/drivers/brcm/scp.h b/include/drivers/brcm/scp.h
new file mode 100644
index 0000000..b7b5bad
--- /dev/null
+++ b/include/drivers/brcm/scp.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCP_H_
+#define SCP_H
+
+#include <stdint.h>
+
+int download_scp_patch(void *image, unsigned int image_size);
+
+#endif /* SCP_H */
diff --git a/include/drivers/brcm/sf.h b/include/drivers/brcm/sf.h
new file mode 100644
index 0000000..c32cbeb
--- /dev/null
+++ b/include/drivers/brcm/sf.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SF_H
+#define SF_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef SPI_DEBUG
+#define SPI_DEBUG(fmt, ...)	INFO(fmt, ##__VA_ARGS__)
+#else
+#define SPI_DEBUG(fmt, ...)
+#endif
+
+#define SPI_FLASH_MAX_ID_LEN	6
+
+#define CMD_WRSR		0x01 /* Write status register */
+#define CMD_PAGE_PROGRAM	0x02
+#define CMD_READ_NORMAL		0x03
+#define CMD_RDSR		0x05
+#define CMD_WRITE_ENABLE	0x06
+#define CMD_RDFSR		0x70
+#define CMD_READ_ID		0x9f
+#define CMD_ERASE_4K		0x20
+#define CMD_ERASE_64K		0xd8
+#define ERASE_SIZE_64K		(64 * 1024)
+
+/* Common status */
+#define STATUS_WIP		BIT(0)
+
+struct spi_flash {
+	struct spi_slave *spi;
+	uint32_t size;
+	uint32_t page_size;
+	uint32_t sector_size;
+	uint32_t erase_size;
+	uint8_t erase_cmd;
+	uint8_t read_cmd;
+	uint8_t write_cmd;
+	uint8_t flags;
+};
+
+struct spi_flash_info {
+	const char *name;
+
+	/*
+	 * This array stores the ID bytes.
+	 * The first three bytes are the JEDIC ID.
+	 * JEDEC ID zero means "no ID" (mostly older chips).
+	 */
+	uint8_t id[SPI_FLASH_MAX_ID_LEN];
+	uint8_t id_len;
+
+	uint32_t sector_size;
+	uint32_t n_sectors;
+	uint16_t page_size;
+
+	uint8_t flags;
+};
+
+/* Enum list - Full read commands */
+enum spi_read_cmds {
+	ARRAY_SLOW              = BIT(0),
+	ARRAY_FAST              = BIT(1),
+	DUAL_OUTPUT_FAST        = BIT(2),
+	DUAL_IO_FAST            = BIT(3),
+	QUAD_OUTPUT_FAST        = BIT(4),
+	QUAD_IO_FAST            = BIT(5),
+};
+
+/* sf param flags */
+enum spi_param_flag {
+	SECT_4K         = BIT(0),
+	SECT_32K        = BIT(1),
+	E_FSR           = BIT(2),
+	SST_BP          = BIT(3),
+	SST_WP          = BIT(4),
+	WR_QPP          = BIT(5),
+};
+
+int spi_flash_cmd_read(const uint8_t *cmd, size_t cmd_len,
+		       void *data, size_t data_len);
+int spi_flash_cmd(uint8_t cmd, void *response, size_t len);
+int spi_flash_cmd_write(const uint8_t *cmd, size_t cmd_len,
+			const void *data, size_t data_len);
+#endif
diff --git a/include/drivers/brcm/sotp.h b/include/drivers/brcm/sotp.h
new file mode 100644
index 0000000..a93d687
--- /dev/null
+++ b/include/drivers/brcm/sotp.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOTP_H
+#define SOTP_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <platform_sotp.h>
+
+#define SOTP_ROW_NO_ECC 0
+#define SOTP_ROW_ECC 1
+
+#define SOTP_STATUS_1 (SOTP_REGS_OTP_BASE + 0x001c)
+#define SOTP_FAIL_BITS 0x18000000000
+#define SOTP_ECC_ERR_DETECT 0x8000000000000000
+
+#define SOTP_REGS_SOTP_CHIP_STATES (SOTP_REGS_OTP_BASE + 0x0028)
+#define SOTP_REGS_OTP_WR_LOCK (SOTP_REGS_OTP_BASE + 0x0038)
+
+#define SOTP_CHIP_STATES_MANU_DEBUG_MASK (1 << 8)
+#define SOTP_DEVICE_SECURE_CFG0_OTP_ERASED_MASK (3 << 16)
+#define SOTP_REGS_SOTP_CHIP_STATES_OTP_ERASED_MASK (1 << 16)
+
+#define SOTP_DEVICE_SECURE_CFG0_CID_MASK (3 << 2)
+#define SOTP_DEVICE_SECURE_CFG0_AB_MASK  (3 << 6)
+#define SOTP_DEVICE_SECURE_CFG0_DEV_MASK (3 << 8)
+
+#define SOTP_BOOT_SOURCE_SHIFT 8
+/* bits 14 and 15 */
+#define SOTP_BOOT_SOURCE_ENABLE_MASK (0xC0 << SOTP_BOOT_SOURCE_SHIFT)
+/* bits 8 to 13 */
+#define SOTP_BOOT_SOURCE_BITS0 (0x03 << SOTP_BOOT_SOURCE_SHIFT)
+#define SOTP_BOOT_SOURCE_BITS1 (0x0C << SOTP_BOOT_SOURCE_SHIFT)
+#define SOTP_BOOT_SOURCE_BITS2 (0x30 << SOTP_BOOT_SOURCE_SHIFT)
+#define SOTP_BOOT_SOURCE_MASK (0x3F << SOTP_BOOT_SOURCE_SHIFT)
+
+#define SOTP_ATF_CFG_ROW_ID SOTP_DEVICE_SECURE_CFG2_ROW
+/* bits 28 and 29 */
+#define SOTP_SBL_MASK (3 << 28)
+/* bits 30 and 31 */
+#define SOTP_ATF_NVCOUNTER_ENABLE_MASK ((uint64_t)3 << 30)
+/* bits 32 and 33 */
+#define SOTP_ATF_WATCHDOG_ENABLE_MASK ((uint64_t)3 << 32)
+/* bits 34 and 35 */
+#define SOTP_ATF_PLL_ON ((uint64_t)3 << 34)
+/* bits 36 and 37 */
+#define SOTP_ATF_RESET_RETRY ((uint64_t)3 << 36)
+/* bits 38 to 40 */
+#define SOTP_ATF_LOG_LEVEL_SHIFT 38
+#define SOTP_ATF_LOG_LEVEL ((uint64_t)7 << SOTP_ATF_LOG_LEVEL_SHIFT)
+
+#define SOTP_ATF2_CFG_ROW_ID SOTP_DEVICE_SECURE_CFG3_ROW
+/* bits 16 and 17 */
+#define SOTP_ROMKEY_MASK (3 << 16)
+/* bits 18 and 19 */
+#define SOTP_EC_EN_MASK (3 << 18)
+
+#define SOTP_ENC_DEV_TYPE_AB_DEV ((uint64_t)0x19999800000)
+#define SOTP_ENC_DEV_TYPE_MASK   ((uint64_t)0x1ffff800000)
+
+uint64_t sotp_mem_read(uint32_t offset, uint32_t sotp_add_ecc);
+void sotp_mem_write(uint32_t addr, uint32_t sotp_add_ecc, uint64_t wdata);
+int sotp_read_key(uint8_t *key, size_t keysize, int start_row, int end_row);
+int sotp_key_erased(void);
+uint32_t sotp_redundancy_reduction(uint32_t sotp_row_data);
+#endif
diff --git a/include/drivers/brcm/spi.h b/include/drivers/brcm/spi.h
new file mode 100644
index 0000000..9d92d8c
--- /dev/null
+++ b/include/drivers/brcm/spi.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPI_H
+#define SPI_H
+
+#include <stdint.h>
+
+#define SPI_XFER_BEGIN (1 << 0)	/* Assert CS before transfer */
+#define SPI_XFER_END   (1 << 1)	/* De-assert CS after transfer */
+#define SPI_XFER_QUAD  (1 << 2)
+
+int spi_init(void);
+int spi_claim_bus(void);
+void spi_release_bus(void);
+int spi_xfer(uint32_t bitlen, const void *dout, void *din, uint32_t flags);
+
+#endif /* _SPI_H_ */
diff --git a/include/drivers/brcm/spi_flash.h b/include/drivers/brcm/spi_flash.h
new file mode 100644
index 0000000..bbaaa50
--- /dev/null
+++ b/include/drivers/brcm/spi_flash.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPI_FLASH_H
+#define SPI_FLASH_H
+
+#include <sf.h>
+
+int spi_flash_probe(struct spi_flash *flash);
+int spi_flash_erase(struct spi_flash *flash, uint32_t offset, uint32_t len);
+int spi_flash_write(struct spi_flash *flash, uint32_t offset,
+		    uint32_t len, void *buf);
+int spi_flash_read(struct spi_flash *flash, uint32_t offset,
+		   uint32_t len, void *data);
+#endif /* _SPI_FLASH_H_ */
diff --git a/include/drivers/io/io_fip.h b/include/drivers/io/io_fip.h
index e0b5746..7e65436 100644
--- a/include/drivers/io/io_fip.h
+++ b/include/drivers/io/io_fip.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,5 +10,6 @@
 struct io_dev_connector;
 
 int register_io_dev_fip(const struct io_dev_connector **dev_con);
+int fip_dev_get_plat_toc_flag(io_dev_info_t *dev_info, uint16_t *plat_toc_flag);
 
 #endif /* IO_FIP_H */
diff --git a/include/lib/fconf/fconf_tbbr_getter.h b/include/lib/fconf/fconf_tbbr_getter.h
index eddc0c4..db98b68 100644
--- a/include/lib/fconf/fconf_tbbr_getter.h
+++ b/include/lib/fconf/fconf_tbbr_getter.h
@@ -7,10 +7,15 @@
 #ifndef FCONF_TBBR_GETTER_H
 #define FCONF_TBBR_GETTER_H
 
+#include <assert.h>
+
 #include <lib/fconf/fconf.h>
 
 /* TBBR related getter */
-#define tbbr__cot_getter(id)	cot_desc_ptr[id]
+#define tbbr__cot_getter(id) __extension__ ({	\
+	assert((id) < cot_desc_size);		\
+	cot_desc_ptr[id];			\
+})
 
 #define tbbr__dyn_config_getter(id)	tbbr_dyn_config.id
 
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 9fe4a6e..8eb84a8 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -66,6 +66,11 @@
 #define MT_EXECUTE_SHIFT	U(5)
 /* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */
 #define MT_USER_SHIFT		U(6)
+
+/* Shareability attribute for the memory region */
+#define MT_SHAREABILITY_SHIFT	U(7)
+#define MT_SHAREABILITY_MASK	(U(3) << MT_SHAREABILITY_SHIFT)
+#define MT_SHAREABILITY(_attr)	((_attr) & MT_SHAREABILITY_MASK)
 /* All other bits are reserved */
 
 /*
@@ -106,6 +111,18 @@
 #define MT_USER			(U(1) << MT_USER_SHIFT)
 #define MT_PRIVILEGED		(U(0) << MT_USER_SHIFT)
 
+/*
+ * Shareability defines the visibility of any cache changes to
+ * all masters belonging to a shareable domain.
+ *
+ * MT_SHAREABILITY_ISH: For inner shareable domain
+ * MT_SHAREABILITY_OSH: For outer shareable domain
+ * MT_SHAREABILITY_NSH: For non shareable domain
+ */
+#define MT_SHAREABILITY_ISH	(U(1) << MT_SHAREABILITY_SHIFT)
+#define MT_SHAREABILITY_OSH	(U(2) << MT_SHAREABILITY_SHIFT)
+#define MT_SHAREABILITY_NSH	(U(3) << MT_SHAREABILITY_SHIFT)
+
 /* Compound attributes for most common usages */
 #define MT_CODE			(MT_MEMORY | MT_RO | MT_EXECUTE)
 #define MT_RO_DATA		(MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
diff --git a/include/plat/arm/common/arm_fconf_getter.h b/include/plat/arm/common/arm_fconf_getter.h
index 28913a4..8fd8c7a 100644
--- a/include/plat/arm/common/arm_fconf_getter.h
+++ b/include/plat/arm/common/arm_fconf_getter.h
@@ -7,10 +7,15 @@
 #ifndef ARM_FCONF_GETTER
 #define ARM_FCONF_GETTER
 
+#include <assert.h>
+
 #include <lib/fconf/fconf.h>
 
 /* ARM io policies */
-#define arm__io_policies_getter(id)	&policies[id]
+#define arm__io_policies_getter(id) __extension__ ({	\
+	assert((id) < MAX_NUMBER_IDS);			\
+	&policies[id];					\
+})
 
 struct plat_io_policy {
 	uintptr_t *dev_handle;
diff --git a/include/plat/brcm/common/bcm_console.h b/include/plat/brcm/common/bcm_console.h
new file mode 100644
index 0000000..7b653d8
--- /dev/null
+++ b/include/plat/brcm/common/bcm_console.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BCM_CONSOLE_H
+#define BCM_CONSOLE_H
+
+void bcm_console_boot_init(void);
+void bcm_console_boot_end(void);
+void bcm_console_runtime_init(void);
+void bcm_console_runtime_end(void);
+
+#endif /* BCM_CONSOLE_H */
diff --git a/include/plat/brcm/common/bcm_elog.h b/include/plat/brcm/common/bcm_elog.h
new file mode 100644
index 0000000..ea4b169
--- /dev/null
+++ b/include/plat/brcm/common/bcm_elog.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BCM_ELOG_H
+#define BCM_ELOG_H
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#if defined(BCM_ELOG) && (defined(IMAGE_BL2) || defined(IMAGE_BL31))
+int bcm_elog_init(void *base, uint32_t size, unsigned int level);
+void bcm_elog_exit(void);
+int bcm_elog_copy_log(void *dst, uint32_t max_size);
+void bcm_elog(const char *fmt, ...);
+#else
+static inline int bcm_elog_init(void *base, uint32_t size,
+				unsigned int level)
+{
+	return 0;
+}
+static inline void bcm_elog_exit(void)
+{
+}
+static inline int bcm_elog_copy_log(void *dst, uint32_t max_size)
+{
+	return 0;
+}
+static inline void bcm_elog(const char *fmt, ...)
+{
+}
+#endif /* BCM_ELOG */
+
+#endif /* __ASSEMBLER__ */
+#endif /* BCM_ELOG_H */
diff --git a/include/plat/brcm/common/brcm_def.h b/include/plat/brcm/common/brcm_def.h
new file mode 100644
index 0000000..c9137bc
--- /dev/null
+++ b/include/plat/brcm/common/brcm_def.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BRCM_DEF_H
+#define BRCM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/common_def.h>
+
+#include <platform_def.h>
+
+#define PLAT_PHY_ADDR_SPACE_SIZE	BIT_64(32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	BIT_64(32)
+
+#define BL11_DAUTH_ID			0x796C51ab
+#define BL11_DAUTH_BASE			BL11_RW_BASE
+
+/* We keep a table at the end of ROM for function pointers */
+#define ROM_TABLE_SIZE			32
+#define BL1_ROM_TABLE			(BL1_RO_LIMIT - ROM_TABLE_SIZE)
+
+/*
+ * The top 16MB of DRAM1 is configured as secure access only using the TZC
+ *   - SCP TZC DRAM: If present, DRAM reserved for SCP use
+ *   - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use
+ */
+#define BRCM_TZC_DRAM1_SIZE		ULL(0x01000000)
+
+#define BRCM_SCP_TZC_DRAM1_BASE		(BRCM_DRAM1_BASE +		\
+					 BRCM_DRAM1_SIZE -		\
+					 BRCM_SCP_TZC_DRAM1_SIZE)
+#define BRCM_SCP_TZC_DRAM1_SIZE		PLAT_BRCM_SCP_TZC_DRAM1_SIZE
+
+#define BRCM_AP_TZC_DRAM1_BASE		(BRCM_DRAM1_BASE +		\
+					 BRCM_DRAM1_SIZE -		\
+					 BRCM_TZC_DRAM1_SIZE)
+#define BRCM_AP_TZC_DRAM1_SIZE		(BRCM_TZC_DRAM1_SIZE -		\
+					 BRCM_SCP_TZC_DRAM1_SIZE)
+
+#define BRCM_NS_DRAM1_BASE		BRCM_DRAM1_BASE
+#define BRCM_NS_DRAM1_SIZE		(BRCM_DRAM1_SIZE -		\
+					 BRCM_TZC_DRAM1_SIZE)
+
+#ifdef BRCM_SHARED_DRAM_BASE
+#define BRCM_NS_SHARED_DRAM_BASE	BRCM_SHARED_DRAM_BASE
+#define BRCM_NS_SHARED_DRAM_SIZE	BRCM_SHARED_DRAM_SIZE
+#endif
+
+#define BRCM_MAP_SHARED_RAM		MAP_REGION_FLAT(		\
+						BRCM_SHARED_RAM_BASE,	\
+						BRCM_SHARED_RAM_SIZE,	\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define BRCM_MAP_NS_DRAM1		MAP_REGION_FLAT(		\
+						BRCM_NS_DRAM1_BASE,	\
+						BRCM_NS_DRAM1_SIZE,	\
+						MT_MEMORY | MT_RW | MT_NS)
+
+#ifdef BRCM_SHARED_DRAM_BASE
+#define BRCM_MAP_NS_SHARED_DRAM		MAP_REGION_FLAT(		 \
+						BRCM_NS_SHARED_DRAM_BASE, \
+						BRCM_NS_SHARED_DRAM_SIZE, \
+						MT_MEMORY | MT_RW | MT_NS)
+#endif
+
+#ifdef BRCM_EXT_SRAM_BASE
+#define BRCM_MAP_EXT_SRAM		MAP_REGION_FLAT(		\
+						BRCM_EXT_SRAM_BASE,	\
+						BRCM_EXT_SRAM_SIZE,	\
+						MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#define BRCM_MAP_NAND_RO		MAP_REGION_FLAT(NAND_BASE_ADDR,\
+						NAND_SIZE,	\
+						MT_MEMORY | MT_RO | MT_SECURE)
+
+#define BRCM_MAP_QSPI_RO		MAP_REGION_FLAT(QSPI_BASE_ADDR,\
+						QSPI_SIZE,	\
+						MT_MEMORY | MT_RO | MT_SECURE)
+
+#define HSLS_REGION	MAP_REGION_FLAT(HSLS_BASE_ADDR, \
+					HSLS_SIZE, \
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define CCN_REGION	MAP_REGION_FLAT(PLAT_BRCM_CCN_BASE, \
+					CCN_SIZE, \
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define GIC500_REGION	MAP_REGION_FLAT(GIC500_BASE, \
+					GIC500_SIZE, \
+					MT_DEVICE | MT_RW | MT_SECURE)
+#ifdef PERIPH0_BASE
+#define PERIPH0_REGION	MAP_REGION_FLAT(PERIPH0_BASE, \
+					PERIPH0_SIZE, \
+					MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#ifdef PERIPH1_BASE
+#define PERIPH1_REGION	MAP_REGION_FLAT(PERIPH1_BASE, \
+					PERIPH1_SIZE, \
+					MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#ifdef PERIPH2_BASE
+#define PERIPH2_REGION	MAP_REGION_FLAT(PERIPH2_BASE, \
+					PERIPH2_SIZE, \
+					MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#if BRCM_BL31_IN_DRAM
+#if IMAGE_BL2
+#define BRCM_MAP_BL31_SEC_DRAM		MAP_REGION_FLAT(		\
+						BL31_BASE,		\
+						PLAT_BRCM_MAX_BL31_SIZE,\
+						MT_DEVICE | MT_RW | MT_SECURE)
+#else
+#define BRCM_MAP_BL31_SEC_DRAM		MAP_REGION_FLAT(		\
+						BL31_BASE,		\
+						PLAT_BRCM_MAX_BL31_SIZE,\
+						MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+#endif
+
+#if defined(USB_BASE) && defined(DRIVER_USB_ENABLE)
+#define USB_REGION			MAP_REGION_FLAT(  \
+						USB_BASE, \
+						USB_SIZE, \
+						MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#ifdef USE_CRMU_SRAM
+#define CRMU_SRAM_REGION		MAP_REGION_FLAT(		\
+						CRMU_SRAM_BASE,		\
+						CRMU_SRAM_SIZE,		\
+						MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+/*
+ * The number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#if USE_COHERENT_MEM
+#define BRCM_BL_REGIONS			3
+#else
+#define BRCM_BL_REGIONS			2
+#endif
+
+#endif /* BRCM_DEF_H */
diff --git a/include/plat/brcm/common/plat_brcm.h b/include/plat/brcm/common/plat_brcm.h
new file mode 100644
index 0000000..66ed2cb
--- /dev/null
+++ b/include/plat/brcm/common/plat_brcm.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_BRCM_H
+#define PLAT_BRCM_H
+
+#include <stdint.h>
+
+#include <lib/cassert.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include <platform_def.h>
+
+struct image_info;
+
+/* Global variables */
+extern const mmap_region_t plat_brcm_mmap[];
+
+uint32_t brcm_get_spsr_for_bl32_entry(void);
+uint32_t brcm_get_spsr_for_bl33_entry(void);
+const mmap_region_t *plat_brcm_get_mmap(void);
+int bcm_bl2_handle_scp_bl2(struct image_info *image_info);
+unsigned int plat_brcm_calc_core_pos(u_register_t mpidr);
+void plat_brcm_gic_driver_init(void);
+void plat_brcm_gic_init(void);
+void plat_brcm_gic_cpuif_enable(void);
+void plat_brcm_gic_cpuif_disable(void);
+void plat_brcm_gic_pcpu_init(void);
+void plat_brcm_gic_redistif_on(void);
+void plat_brcm_gic_redistif_off(void);
+void plat_brcm_interconnect_init(void);
+void plat_brcm_interconnect_enter_coherency(void);
+void plat_brcm_interconnect_exit_coherency(void);
+void plat_brcm_io_setup(void);
+void plat_brcm_process_flags(uint16_t plat_toc_flags);
+
+#endif /* PLAT_BRCM_H */
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index b2259e5..bb6d184 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -109,6 +109,7 @@
 {
 	uint64_t desc;
 	uint32_t mem_type;
+	uint32_t shareability_type;
 
 	/* Make sure that the granularity is fine enough to map this address. */
 	assert((addr_pa & XLAT_BLOCK_MASK(level)) == 0U);
@@ -194,8 +195,16 @@
 			desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
 		}
 
+		shareability_type = MT_SHAREABILITY(attr);
 		if (mem_type == MT_MEMORY) {
-			desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
+			desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX);
+			if (shareability_type == MT_SHAREABILITY_NSH) {
+				desc |= LOWER_ATTRS(NSH);
+			} else if (shareability_type == MT_SHAREABILITY_OSH) {
+				desc |= LOWER_ATTRS(OSH);
+			} else {
+				desc |= LOWER_ATTRS(ISH);
+			}
 
 			/* Check if Branch Target Identification is enabled */
 #if ENABLE_BTI
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index b4f38fa..302aabf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -66,12 +66,13 @@
 				lib/cpus/aarch64/cortex_a75.S
 endif
 
-FPGA_GIC_SOURCES	:=	drivers/arm/gic/v3/gicv3_helpers.c	\
-				drivers/arm/gic/v3/gicdv3_helpers.c     \
-                                drivers/arm/gic/v3/gicrv3_helpers.c     \
-                                drivers/arm/gic/v3/gicv3_main.c         \
-				drivers/arm/gic/v3/gic600.c		\
-				drivers/arm/gic/common/gic_common.c     \
+# GIC-600 configuration
+GICV3_IMPL		:=	GIC600
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+FPGA_GIC_SOURCES	:=	${GICV3_SOURCES}			\
 				plat/common/plat_gicv3.c		\
 				plat/arm/board/arm_fpga/fpga_gicv3.c
 
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index 6fcfbd6..34b4101 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -4,8 +4,6 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <assert.h>
-
 #include <common/debug.h>
 #include <drivers/io/io_driver.h>
 #include <drivers/io/io_fip.h>
@@ -116,8 +114,6 @@
 	int result;
 	const struct plat_io_policy *policy;
 
-	assert(image_id < MAX_NUMBER_IDS);
-
 	policy = FCONF_GET_PROPERTY(arm, io_policies, image_id);
 	result = policy->check(policy->image_spec);
 	if (result == 0) {
diff --git a/plat/brcm/board/common/bcm_console.c b/plat/brcm/board/common/bcm_console.c
new file mode 100644
index 0000000..d484a6f
--- /dev/null
+++ b/plat/brcm/board/common/bcm_console.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/ti/uart/uart_16550.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Functions that set up the console
+ ******************************************************************************/
+static console_t bcm_boot_console;
+static console_t bcm_runtime_console;
+
+/* Initialize the console to provide early debug support */
+void bcm_console_boot_init(void)
+{
+	int rc = console_16550_register(PLAT_BRCM_BOOT_UART_BASE,
+					PLAT_BRCM_BOOT_UART_CLK_IN_HZ,
+					BRCM_CONSOLE_BAUDRATE,
+					&bcm_boot_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(&bcm_boot_console, CONSOLE_FLAG_BOOT);
+}
+
+void bcm_console_boot_end(void)
+{
+	(void)console_flush();
+
+	(void)console_unregister(&bcm_boot_console);
+}
+
+/* Initialize the runtime console */
+void bcm_console_runtime_init(void)
+{
+	int rc = console_16550_register(PLAT_BRCM_BL31_RUN_UART_BASE,
+					PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ,
+					BRCM_CONSOLE_BAUDRATE,
+					&bcm_runtime_console);
+	if (rc == 0)
+		panic();
+
+	console_set_scope(&bcm_runtime_console, CONSOLE_FLAG_RUNTIME);
+}
+
+void bcm_console_runtime_end(void)
+{
+	(void)console_flush();
+
+	(void)console_unregister(&bcm_runtime_console);
+}
diff --git a/plat/brcm/board/common/bcm_elog.c b/plat/brcm/board/common/bcm_elog.c
new file mode 100644
index 0000000..093157e
--- /dev/null
+++ b/plat/brcm/board/common/bcm_elog.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2018 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+#include <bcm_elog.h>
+
+/* error logging signature */
+#define BCM_ELOG_SIG_OFFSET      0x0000
+#define BCM_ELOG_SIG_VAL         0x75767971
+
+/* current logging offset that points to where new logs should be added */
+#define BCM_ELOG_OFF_OFFSET      0x0004
+
+/* current logging length (excluding header) */
+#define BCM_ELOG_LEN_OFFSET      0x0008
+
+#define BCM_ELOG_HEADER_LEN      12
+
+/*
+ * @base: base address of memory where log is saved
+ * @max_size: max size of memory reserved for logging
+ * @is_active: indicates logging is currently active
+ * @level: current logging level
+ */
+struct bcm_elog {
+	uintptr_t base;
+	uint32_t max_size;
+	unsigned int is_active;
+	unsigned int level;
+};
+
+static struct bcm_elog global_elog;
+
+extern void memcpy16(void *dst, const void *src, unsigned int len);
+
+/*
+ * Log one character
+ */
+static void elog_putchar(struct bcm_elog *elog, unsigned char c)
+{
+	uint32_t offset, len;
+
+	offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET);
+	len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET);
+	mmio_write_8(elog->base + offset, c);
+	offset++;
+
+	/* log buffer is now full and need to wrap around */
+	if (offset >= elog->max_size)
+		offset = BCM_ELOG_HEADER_LEN;
+
+	/* only increment length when log buffer is not full */
+	if (len < elog->max_size - BCM_ELOG_HEADER_LEN)
+		len++;
+
+	mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset);
+	mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len);
+}
+
+static void elog_unsigned_num(struct bcm_elog *elog, unsigned long unum,
+			      unsigned int radix)
+{
+	/* Just need enough space to store 64 bit decimal integer */
+	unsigned char num_buf[20];
+	int i = 0, rem;
+
+	do {
+		rem = unum % radix;
+		if (rem < 0xa)
+			num_buf[i++] = '0' + rem;
+		else
+			num_buf[i++] = 'a' + (rem - 0xa);
+	} while (unum /= radix);
+
+	while (--i >= 0)
+		elog_putchar(elog, num_buf[i]);
+}
+
+static void elog_string(struct bcm_elog *elog, const char *str)
+{
+	while (*str)
+		elog_putchar(elog, *str++);
+}
+
+/*
+ * Routine to initialize error logging
+ */
+int bcm_elog_init(void *base, uint32_t size, unsigned int level)
+{
+	struct bcm_elog *elog = &global_elog;
+	uint32_t val;
+
+	elog->base = (uintptr_t)base;
+	elog->max_size = size;
+	elog->is_active = 1;
+	elog->level = level / 10;
+
+	/*
+	 * If a valid signature can be found, it means logs have been copied
+	 * into designated memory by another software. In this case, we should
+	 * not re-initialize the entry header in the designated memory
+	 */
+	val = mmio_read_32(elog->base + BCM_ELOG_SIG_OFFSET);
+	if (val != BCM_ELOG_SIG_VAL) {
+		mmio_write_32(elog->base + BCM_ELOG_SIG_OFFSET,
+			      BCM_ELOG_SIG_VAL);
+		mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET,
+			      BCM_ELOG_HEADER_LEN);
+		mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, 0);
+	}
+
+	return 0;
+}
+
+/*
+ * Routine to disable error logging
+ */
+void bcm_elog_exit(void)
+{
+	struct bcm_elog *elog = &global_elog;
+
+	if (!elog->is_active)
+		return;
+
+	elog->is_active = 0;
+
+	flush_dcache_range(elog->base, elog->max_size);
+}
+
+/*
+ * Routine to copy error logs from current memory to 'dst' memory and continue
+ * logging from the new 'dst' memory.
+ * dst and base addresses must be 16-bytes aligned.
+ */
+int bcm_elog_copy_log(void *dst, uint32_t max_size)
+{
+	struct bcm_elog *elog = &global_elog;
+	uint32_t offset, len;
+
+	if (!elog->is_active || ((uintptr_t)dst == elog->base))
+		return -1;
+
+	/* flush cache before copying logs */
+	flush_dcache_range(elog->base, max_size);
+
+	/*
+	 * If current offset exceeds the new max size, then that is considered
+	 * as a buffer overflow situation. In this case, we reset the offset
+	 * back to the beginning
+	 */
+	offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET);
+	if (offset >= max_size) {
+		offset = BCM_ELOG_HEADER_LEN;
+		mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset);
+	}
+
+	/* note payload length does not include header */
+	len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET);
+	if (len > max_size - BCM_ELOG_HEADER_LEN) {
+		len = max_size - BCM_ELOG_HEADER_LEN;
+		mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len);
+	}
+
+	/* Need to copy everything including the header. */
+	memcpy16(dst, (const void *)elog->base, len + BCM_ELOG_HEADER_LEN);
+	elog->base = (uintptr_t)dst;
+	elog->max_size = max_size;
+
+	return 0;
+}
+
+/*
+ * Main routine to save logs into memory
+ */
+void bcm_elog(const char *fmt, ...)
+{
+	va_list args;
+	const char *prefix_str;
+	int bit64;
+	int64_t num;
+	uint64_t unum;
+	char *str;
+	struct bcm_elog *elog = &global_elog;
+
+	/* We expect the LOG_MARKER_* macro as the first character */
+	unsigned int level = fmt[0];
+
+	if (!elog->is_active || level > elog->level)
+		return;
+
+	prefix_str = plat_log_get_prefix(level);
+
+	while (*prefix_str != '\0') {
+		elog_putchar(elog, *prefix_str);
+		prefix_str++;
+	}
+
+	va_start(args, fmt);
+	fmt++;
+	while (*fmt) {
+		bit64 = 0;
+
+		if (*fmt == '%') {
+			fmt++;
+			/* Check the format specifier */
+loop:
+			switch (*fmt) {
+			case 'i': /* Fall through to next one */
+			case 'd':
+				if (bit64)
+					num = va_arg(args, int64_t);
+				else
+					num = va_arg(args, int32_t);
+
+				if (num < 0) {
+					elog_putchar(elog, '-');
+					unum = (unsigned long)-num;
+				} else
+					unum = (unsigned long)num;
+
+				elog_unsigned_num(elog, unum, 10);
+				break;
+			case 's':
+				str = va_arg(args, char *);
+				elog_string(elog, str);
+				break;
+			case 'x':
+				if (bit64)
+					unum = va_arg(args, uint64_t);
+				else
+					unum = va_arg(args, uint32_t);
+
+				elog_unsigned_num(elog, unum, 16);
+				break;
+			case 'l':
+				bit64 = 1;
+				fmt++;
+				goto loop;
+			case 'u':
+				if (bit64)
+					unum = va_arg(args, uint64_t);
+				else
+					unum = va_arg(args, uint32_t);
+
+				elog_unsigned_num(elog, unum, 10);
+				break;
+			default:
+				/* Exit on any other format specifier */
+				goto exit;
+			}
+			fmt++;
+			continue;
+		}
+		elog_putchar(elog, *fmt++);
+	}
+exit:
+	va_end(args);
+}
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");
+}
diff --git a/plat/brcm/board/common/bcm_elog_ddr.h b/plat/brcm/board/common/bcm_elog_ddr.h
new file mode 100644
index 0000000..6f21a68
--- /dev/null
+++ b/plat/brcm/board/common/bcm_elog_ddr.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2019-2020 Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BCM_ELOG_DDR_H
+#define BCM_ELOG_DDR_H
+
+#define ELOG_GLOBAL_META_HDR_SIG	0x45524c47
+#define ELOG_MAX_REC_COUNT		13
+#define ELOG_MAX_REC_FORMAT		1
+#define ELOG_MAX_NVM_TYPE		4
+/* Use a default NVM, set by m0 configuration */
+#define ELOG_NVM_DEFAULT		0xff
+
+/* Max. number of cmd parameters per elog spec */
+#define ELOG_PARAM_COUNT		3
+/*
+ * Number of supported RECORD Types-
+ * SYSRESET, THERMAL, DDR_ECC, APBOOTLG, IDM
+ */
+#define ELOG_SUPPORTED_REC_CNT		5
+
+#define ELOG_REC_DESC_LENGTH		8
+
+#define ELOG_SECTOR_SIZE		0x1000
+
+/* Default Record size for all record types except APBOOTLOG */
+#define ELOG_DEFAULT_REC_SIZE		0x10000
+
+/* Default record size for APBOOTLOG record */
+#define ELOG_APBOOTLG_REC_SIZE		0x60000
+
+/* Use default CRMU provided mem address */
+#define ELOG_USE_DEFAULT_MEM_ADDR	0x0
+
+/* Temporary place to hold metadata */
+#define TMP_ELOG_METADATA_BASE		(ELOG_AP_UART_LOG_BASE + \
+					 BCM_ELOG_BL2_SIZE)
+/* IDM ELOG source memory address */
+#define ELOG_IDM_SRC_MEM_ADDR		0x8f213000
+
+#define IDM_ELOG_REC_TYPE		5
+
+enum elog_record_type {
+	ELOG_REC_SYS_RESET_EVT = 0,
+	ELOG_REC_THERMAL_EVT,
+	ELOG_REC_DDR_ECC,
+	ELOG_REC_UART_LOG,
+	ELOG_REC_IDM_LOG,
+	ELOG_REC_MAX
+};
+
+enum elog_record_format {
+	ELOG_REC_FMT_ASCII = 0,
+	ELOG_REC_FMT_CUSTOM
+};
+
+enum elog_src_memory_type {
+	ELOG_SRC_MEM_TYPE_CRMU_SCRATCH = 0,
+	ELOG_SRC_MEM_TYPE_FS4_SCRATCH,
+	ELOG_SRC_MEM_TYPE_DDR,
+	ELOG_SRC_MEM_TYPE_CHIMP_SCRATCH
+};
+
+enum elog_setup_cmd {
+	ELOG_SETUP_CMD_VALIDATE_META,
+	ELOG_SETUP_CMD_WRITE_META,
+	ELOG_SETUP_CMD_ERASE,
+	ELOG_SETUP_CMD_READ,
+	ELOG_SETUP_CMD_CHECK
+};
+
+struct elog_setup {
+	uint32_t cmd;
+	uint32_t params[ELOG_PARAM_COUNT];
+	uint32_t result;
+	uint32_t ret_code;
+};
+
+struct elog_meta_record {
+	uint8_t type;
+	uint8_t format;
+	uint8_t src_mem_type;
+	uint8_t alt_src_mem_type;
+	uint8_t nvm_type;
+	char rec_desc[ELOG_REC_DESC_LENGTH];
+	uint64_t src_mem_addr;
+	uint64_t alt_src_mem_addr;
+	uint64_t rec_addr;
+	uint32_t rec_size;
+	uint32_t sector_size;
+	uint8_t padding[3];
+} __packed;
+
+struct elog_global_header {
+	uint32_t signature;
+	uint32_t sector_size;
+	uint8_t revision;
+	uint8_t rec_count;
+	uint16_t padding;
+} __packed;
+
+void elog_init_ddr_log(void);
+
+#endif /* BCM_ELOG_DDR_H */
diff --git a/plat/brcm/board/common/board_arm_trusted_boot.c b/plat/brcm/board/common/board_arm_trusted_boot.c
new file mode 100644
index 0000000..7a4dad0
--- /dev/null
+++ b/plat/brcm/board/common/board_arm_trusted_boot.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright 2015 - 2020 Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <tools_share/tbbr_oid.h>
+
+#include <sbl_util.h>
+#include <sotp.h>
+
+/* Weak definition may be overridden in specific platform */
+#pragma weak plat_match_rotpk
+#pragma weak plat_get_nv_ctr
+#pragma weak plat_set_nv_ctr
+
+/* SHA256 algorithm */
+#define SHA256_BYTES			32
+
+/* ROTPK locations */
+#define ARM_ROTPK_REGS_ID		1
+#define ARM_ROTPK_DEVEL_RSA_ID		2
+#define BRCM_ROTPK_SOTP_RSA_ID		3
+
+#if !ARM_ROTPK_LOCATION_ID
+  #error "ARM_ROTPK_LOCATION_ID not defined"
+#endif
+
+static const unsigned char rotpk_hash_hdr[] =
+		"\x30\x31\x30\x0D\x06\x09\x60\x86\x48"
+		"\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20";
+static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1;
+static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES];
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
+static const unsigned char arm_devel_rotpk_hash[] =
+		"\xB0\xF3\x82\x09\x12\x97\xD8\x3A"
+		"\x37\x7A\x72\x47\x1B\xEC\x32\x73"
+		"\xE9\x92\x32\xE2\x49\x59\xF6\x5E"
+		"\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA";
+#endif
+
+#pragma weak plat_rotpk_hash
+const unsigned char plat_rotpk_hash[] =
+		"\xdb\x06\x67\x95\x4f\x88\x2b\x88"
+		"\x49\xbf\x70\x3f\xde\x50\x4a\x96"
+		"\xd8\x17\x69\xd4\xa0\x6c\xba\xee"
+		"\x66\x3e\x71\x82\x2d\x95\x69\xe4";
+
+#pragma weak rom_slice
+const unsigned char rom_slice[] =
+		"\x77\x06\xbc\x98\x40\xbe\xfd\xab"
+		"\x60\x4b\x74\x3c\x9a\xb3\x80\x75"
+		"\x39\xb6\xda\x27\x07\x2e\x5b\xbf"
+		"\x5c\x47\x91\xc9\x95\x26\x26\x0c";
+
+#if (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID)
+static int plat_is_trusted_boot(void)
+{
+	uint64_t section3_row0_data;
+
+	section3_row0_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
+
+	if ((section3_row0_data & SOTP_DEVICE_SECURE_CFG0_AB_MASK) == 0) {
+		INFO("NOT AB\n");
+		return 0;
+	}
+
+	INFO("AB\n");
+	return TRUSTED_BOARD_BOOT;
+}
+
+/*
+ * FAST AUTH is enabled if all following conditions are met:
+ * - AB part
+ * - SOTP.DEV != 0
+ * - SOTP.CID != 0
+ * - SOTP.ENC_DEV_TYPE = ENC_AB_DEV
+ * - Manuf_debug strap set high
+ */
+static int plat_fast_auth_enabled(void)
+{
+	uint32_t chip_state;
+	uint64_t section3_row0_data;
+	uint64_t section3_row1_data;
+
+	section3_row0_data =
+		sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
+	section3_row1_data =
+		sotp_mem_read(SOTP_DEVICE_SECURE_CFG1_ROW, 0);
+
+	chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES);
+
+	if (plat_is_trusted_boot() &&
+	    (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_DEV_MASK) &&
+	    (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_CID_MASK) &&
+	    ((section3_row1_data & SOTP_ENC_DEV_TYPE_MASK) ==
+	     SOTP_ENC_DEV_TYPE_AB_DEV) &&
+	    (chip_state & SOTP_CHIP_STATES_MANU_DEBUG_MASK))
+		return 1;
+
+	return 0;
+}
+#endif
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm         OBJECT IDENTIFIER,
+ *     parameters        ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm   AlgorithmIdentifier,
+ *     digest            OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	uint8_t *dst;
+
+	assert(key_ptr != NULL);
+	assert(key_len != NULL);
+	assert(flags != NULL);
+
+	*flags = 0;
+
+	/* Copy the DER header */
+	memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
+	dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len];
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
+	memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES);
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+	uint32_t *src, tmp;
+	unsigned int words, i;
+
+	/*
+	 * Append the hash from Trusted Root-Key Storage registers. The hash has
+	 * not been written linearly into the registers, so we have to do a bit
+	 * of byte swapping:
+	 *
+	 *     0x00    0x04    0x08    0x0C    0x10    0x14    0x18    0x1C
+	 * +---------------------------------------------------------------+
+	 * | Reg0  | Reg1  | Reg2  | Reg3  | Reg4  | Reg5  | Reg6  | Reg7  |
+	 * +---------------------------------------------------------------+
+	 *  | ...                    ... |   | ...                   ...  |
+	 *  |       +--------------------+   |                    +-------+
+	 *  |       |                        |                    |
+	 *  +----------------------------+   +----------------------------+
+	 *          |                    |                        |       |
+	 *  +-------+                    |   +--------------------+       |
+	 *  |                            |   |                            |
+	 *  v                            v   v                            v
+	 * +---------------------------------------------------------------+
+	 * |                               |                               |
+	 * +---------------------------------------------------------------+
+	 *  0                           15  16                           31
+	 *
+	 * Additionally, we have to access the registers in 32-bit words
+	 */
+	words = SHA256_BYTES >> 3;
+
+	/* Swap bytes 0-15 (first four registers) */
+	src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
+	for (i = 0 ; i < words ; i++) {
+		tmp = src[words - 1 - i];
+		/* Words are read in little endian */
+		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+		*dst++ = (uint8_t)(tmp & 0xFF);
+	}
+
+	/* Swap bytes 16-31 (last four registers) */
+	src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2);
+	for (i = 0 ; i < words ; i++) {
+		tmp = src[words - 1 - i];
+		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+		*dst++ = (uint8_t)(tmp & 0xFF);
+	}
+#elif (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID)
+{
+	int i;
+	int ret = -1;
+
+	/*
+	 * In non-AB mode, we do not read the key.
+	 * In AB mode:
+	 * - The Dauth is in BL11 if SBL is enabled
+	 * - The Dauth is in SOTP if SBL is disabled.
+	 */
+	if (plat_is_trusted_boot() == 0) {
+
+		INFO("NON-AB: Do not read DAUTH!\n");
+		*flags = ROTPK_NOT_DEPLOYED;
+		ret = 0;
+
+	} else if ((sbl_status() == SBL_ENABLED) &&
+		(mmio_read_32(BL11_DAUTH_BASE) == BL11_DAUTH_ID)) {
+
+		/* Read hash from BL11 */
+		INFO("readKeys (DAUTH) from BL11\n");
+
+		memcpy(dst,
+			(void *)(BL11_DAUTH_BASE + sizeof(uint32_t)),
+			SHA256_BYTES);
+
+		for (i = 0; i < SHA256_BYTES; i++)
+			if (dst[i] != 0)
+				break;
+
+		if (i >= SHA256_BYTES)
+			ERROR("Hash not valid from BL11\n");
+		else
+			ret = 0;
+
+	} else if (sotp_key_erased()) {
+
+		memcpy(dst, plat_rotpk_hash, SHA256_BYTES);
+
+		INFO("SOTP erased, Use internal key hash.\n");
+		ret = 0;
+
+	} else if (plat_fast_auth_enabled()) {
+
+		INFO("AB DEV: FAST AUTH!\n");
+		*flags = ROTPK_NOT_DEPLOYED;
+		ret = 0;
+
+	} else if (!(mmio_read_32(SOTP_STATUS_1) & SOTP_DAUTH_ECC_ERROR_MASK)) {
+
+		/* Read hash from SOTP */
+		ret = sotp_read_key(dst,
+				    SHA256_BYTES,
+				    SOTP_DAUTH_ROW,
+				    SOTP_K_HMAC_ROW-1);
+
+		INFO("sotp_read_key (DAUTH): %i\n", ret);
+
+	} else {
+
+		uint64_t row_data;
+		uint32_t k;
+
+		for (k = 0; k < (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW); k++) {
+			row_data = sotp_mem_read(SOTP_DAUTH_ROW + k,
+					SOTP_ROW_NO_ECC);
+
+			if (row_data != 0)
+				break;
+		}
+
+		if (k == (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW)) {
+			INFO("SOTP NOT PROGRAMMED: Do not use DAUTH!\n");
+
+			if (sotp_mem_read(SOTP_ATF2_CFG_ROW_ID,
+					SOTP_ROW_NO_ECC) & SOTP_ROMKEY_MASK) {
+				memcpy(dst, plat_rotpk_hash, SHA256_BYTES);
+
+				INFO("Use internal key hash.\n");
+				ret = 0;
+			} else {
+				*flags = ROTPK_NOT_DEPLOYED;
+				ret = 0;
+			}
+		} else {
+			INFO("No hash found in SOTP\n");
+		}
+	}
+	if (ret)
+		return ret;
+}
+#endif
+
+	*key_ptr = (void *)rotpk_hash_der;
+	*key_len = (unsigned int)sizeof(rotpk_hash_der);
+	*flags |= ROTPK_IS_HASH;
+
+	return 0;
+}
+
+#define SOTP_NUM_BITS_PER_ROW 41
+#define SOTP_NVCTR_ROW_ALL_ONES 0x1ffffffffff
+#define SOTP_NVCTR_TRUSTED_IN_USE \
+		((uint64_t)0x3 << (SOTP_NUM_BITS_PER_ROW-2))
+#define SOTP_NVCTR_NON_TRUSTED_IN_USE ((uint64_t)0x3)
+#define SOTP_NVCTR_TRUSTED_NEAR_END SOTP_NVCTR_NON_TRUSTED_IN_USE
+#define SOTP_NVCTR_NON_TRUSTED_NEAR_END SOTP_NVCTR_TRUSTED_IN_USE
+
+#define SOTP_NVCTR_ROW_START 64
+#define SOTP_NVCTR_ROW_END   75
+
+/*
+ * SOTP NVCTR are stored in section 10 of SOTP (rows 64-75).
+ * Each row of SOTP is 41 bits.
+ * NVCTR's are stored in a bitstream format.
+ * We are tolerant to consecutive bit errors.
+ * Trusted NVCTR starts at the top of row 64 in bitstream format.
+ * Non Trusted NVCTR starts at the bottom of row 75 in reverse bitstream.
+ * Each row can only be used by 1 of the 2 counters.  This is determined
+ * by 2 zeros remaining at the beginning or end of the last available row.
+ * If one counter has already starting using a row, the other will be
+ * prevent from writing to that row.
+ *
+ * Example counter values for SOTP programmed below:
+ * Trusted Counter (rows64-69) = 5 * 41 + 40 = 245
+ * NonTrusted Counter (row75-71) = 3 * 41 + 4 = 127
+ *        40 39 38 37 36 ..... 5 4 3 2 1 0
+ * row 64  1  1  1  1  1       1 1 1 1 1 1
+ * row 65  1  1  1  1  1       1 1 1 1 1 1
+ * row 66  1  1  1  1  1       1 1 1 1 1 1
+ * row 67  1  1  1  1  1       1 1 1 1 1 1
+ * row 68  1  1  1  1  1       1 1 1 1 1 1
+ * row 69  1  1  1  1  1       1 1 1 1 1 0
+ * row 71  0  0  0  0  0       0 0 0 0 0 0
+ * row 71  0  0  0  0  0       0 0 0 0 0 0
+ * row 71  0  0  0  0  0       0 0 1 1 1 1
+ * row 73  1  1  1  1  1       1 1 1 1 1 1
+ * row 74  1  1  1  1  1       1 1 1 1 1 1
+ * row 75  1  1  1  1  1       1 1 1 1 1 1
+ *
+ */
+
+#if (DEBUG == 1)
+/*
+ * Dump sotp rows
+ */
+void sotp_dump_rows(uint32_t start_row, uint32_t end_row)
+{
+	int32_t rownum;
+	uint64_t rowdata;
+
+	for (rownum = start_row; rownum <= end_row; rownum++) {
+		rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
+		INFO("%d 0x%llx\n", rownum, rowdata);
+	}
+}
+#endif
+
+/*
+ * Get SOTP Trusted nvctr
+ */
+unsigned int sotp_get_trusted_nvctr(void)
+{
+	uint64_t rowdata;
+	uint64_t nextrowdata;
+	uint32_t rownum;
+	unsigned int nvctr;
+
+	rownum = SOTP_NVCTR_ROW_START;
+	nvctr = SOTP_NUM_BITS_PER_ROW;
+
+	/*
+	 * Determine what row has last valid data for trusted ctr
+	 */
+	rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
+	while ((rowdata & SOTP_NVCTR_TRUSTED_IN_USE) &&
+	       (rowdata & SOTP_NVCTR_TRUSTED_NEAR_END) &&
+	       (rownum < SOTP_NVCTR_ROW_END)) {
+		/*
+		 * Current row in use and has data in last 2 bits as well.
+		 * Check if next row also has data for this counter
+		 */
+		nextrowdata = sotp_mem_read(rownum+1, SOTP_ROW_NO_ECC);
+		if (nextrowdata & SOTP_NVCTR_TRUSTED_IN_USE) {
+			/* Next row also has data so increment rownum */
+			rownum++;
+			nvctr += SOTP_NUM_BITS_PER_ROW;
+			rowdata = nextrowdata;
+		} else {
+			/* Next row does not have data */
+			break;
+		}
+	}
+
+	if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) {
+		while ((rowdata & 0x1) == 0) {
+			nvctr--;
+			rowdata >>= 1;
+		}
+	} else
+		nvctr -= SOTP_NUM_BITS_PER_ROW;
+
+	INFO("CTR %i\n", nvctr);
+	return nvctr;
+}
+
+/*
+ * Get SOTP NonTrusted nvctr
+ */
+unsigned int sotp_get_nontrusted_nvctr(void)
+{
+	uint64_t rowdata;
+	uint64_t nextrowdata;
+	uint32_t rownum;
+	unsigned int nvctr;
+
+	nvctr = SOTP_NUM_BITS_PER_ROW;
+	rownum = SOTP_NVCTR_ROW_END;
+
+	/*
+	 * Determine what row has last valid data for nontrusted ctr
+	 */
+	rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
+	while ((rowdata & SOTP_NVCTR_NON_TRUSTED_NEAR_END) &&
+	       (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) &&
+	       (rownum > SOTP_NVCTR_ROW_START)) {
+		/*
+		 * Current row in use and has data in last 2 bits as well.
+		 * Check if next row also has data for this counter
+		 */
+		nextrowdata = sotp_mem_read(rownum-1, SOTP_ROW_NO_ECC);
+		if (nextrowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) {
+			/* Next row also has data so decrement rownum */
+			rownum--;
+			nvctr += SOTP_NUM_BITS_PER_ROW;
+			rowdata = nextrowdata;
+		} else {
+			/* Next row does not have data */
+			break;
+		}
+	}
+
+	if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) {
+		while ((rowdata & ((uint64_t)0x1 << (SOTP_NUM_BITS_PER_ROW-1)))
+			==
+			0) {
+			nvctr--;
+			rowdata <<= 1;
+		}
+	} else
+		nvctr -= SOTP_NUM_BITS_PER_ROW;
+
+	INFO("NCTR %i\n", nvctr);
+	return nvctr;
+}
+
+/*
+ * Set SOTP Trusted nvctr
+ */
+int sotp_set_trusted_nvctr(unsigned int nvctr)
+{
+	int numrows_available;
+	uint32_t nontrusted_rownum;
+	uint32_t trusted_rownum;
+	uint64_t rowdata;
+	unsigned int maxnvctr;
+
+	/*
+	 * Read SOTP to find out how many rows are used by the
+	 * NON Trusted nvctr
+	 */
+	nontrusted_rownum = SOTP_NVCTR_ROW_END;
+	do {
+		rowdata = sotp_mem_read(nontrusted_rownum, SOTP_ROW_NO_ECC);
+		if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE)
+			nontrusted_rownum--;
+		else
+			break;
+	} while (nontrusted_rownum >= SOTP_NVCTR_ROW_START);
+
+	/*
+	 * Calculate maximum value we can have for nvctr based on
+	 * number of available rows.
+	 */
+	numrows_available = nontrusted_rownum - SOTP_NVCTR_ROW_START + 1;
+	maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW;
+	if (maxnvctr) {
+		/*
+		 * Last 2 bits of counter can't be written or it will
+		 * overflow with nontrusted counter
+		 */
+		maxnvctr -= 2;
+	}
+
+	if (nvctr > maxnvctr) {
+		/* Error - not enough room */
+		WARN("tctr not set\n");
+		return 1;
+	}
+
+	/*
+	 * It is safe to write the nvctr, fill all 1's up to the
+	 * last row and then fill the last row with partial bitstream
+	 */
+	trusted_rownum = SOTP_NVCTR_ROW_START;
+	rowdata = SOTP_NVCTR_ROW_ALL_ONES;
+
+	while (nvctr >= SOTP_NUM_BITS_PER_ROW) {
+		sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata);
+		nvctr -= SOTP_NUM_BITS_PER_ROW;
+		trusted_rownum++;
+	}
+	rowdata <<= (SOTP_NUM_BITS_PER_ROW - nvctr);
+	sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata);
+	return 0;
+}
+
+/*
+ * Set SOTP NonTrusted nvctr
+ */
+int sotp_set_nontrusted_nvctr(unsigned int nvctr)
+{
+	int numrows_available;
+	uint32_t nontrusted_rownum;
+	uint32_t trusted_rownum;
+	uint64_t rowdata;
+	unsigned int maxnvctr;
+
+	/*
+	 * Read SOTP to find out how many rows are used by the
+	 * Trusted nvctr
+	 */
+	trusted_rownum = SOTP_NVCTR_ROW_START;
+	do {
+		rowdata = sotp_mem_read(trusted_rownum, SOTP_ROW_NO_ECC);
+		if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE)
+			trusted_rownum++;
+		else
+			break;
+	} while (trusted_rownum <= SOTP_NVCTR_ROW_END);
+
+	/*
+	 * Calculate maximum value we can have for nvctr based on
+	 * number of available rows.
+	 */
+	numrows_available = SOTP_NVCTR_ROW_END - trusted_rownum + 1;
+	maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW;
+	if (maxnvctr) {
+		/*
+		 * Last 2 bits of counter can't be written or it will
+		 * overflow with nontrusted counter
+		 */
+		maxnvctr -= 2;
+	}
+
+	if (nvctr > maxnvctr) {
+		/* Error - not enough room */
+		WARN("nctr not set\n");
+		return 1;
+	}
+
+	/*
+	 * It is safe to write the nvctr, fill all 1's up to the
+	 * last row and then fill the last row with partial bitstream
+	 */
+	nontrusted_rownum = SOTP_NVCTR_ROW_END;
+	rowdata = SOTP_NVCTR_ROW_ALL_ONES;
+
+	while (nvctr >= SOTP_NUM_BITS_PER_ROW) {
+		sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata);
+		nvctr -= SOTP_NUM_BITS_PER_ROW;
+		nontrusted_rownum--;
+	}
+	rowdata >>= (SOTP_NUM_BITS_PER_ROW - nvctr);
+	sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata);
+	return 0;
+}
+
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+	const char *oid;
+
+	assert(cookie != NULL);
+	assert(nv_ctr != NULL);
+
+	*nv_ctr = 0;
+	if ((sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
+			SOTP_ATF_NVCOUNTER_ENABLE_MASK)) {
+		oid = (const char *)cookie;
+		if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0)
+			*nv_ctr = sotp_get_trusted_nvctr();
+		else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0)
+			*nv_ctr = sotp_get_nontrusted_nvctr();
+		else
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Store a new non-volatile counter value.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+	const char *oid;
+
+	if (sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
+			SOTP_ATF_NVCOUNTER_ENABLE_MASK) {
+		INFO("set CTR %i\n", nv_ctr);
+		oid = (const char *)cookie;
+		if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0)
+			return sotp_set_trusted_nvctr(nv_ctr);
+		else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0)
+			return sotp_set_nontrusted_nvctr(nv_ctr);
+		return 1;
+	}
+	return 0;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+	return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/brcm/board/common/board_common.c b/plat/brcm/board/common/board_common.c
new file mode 100644
index 0000000..2f764ab
--- /dev/null
+++ b/plat/brcm/board/common/board_common.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <brcm_def.h>
+#include <plat_brcm.h>
+
+#if IMAGE_BL2
+const mmap_region_t plat_brcm_mmap[] = {
+	HSLS_REGION,
+	BRCM_MAP_SHARED_RAM,
+	BRCM_MAP_NAND_RO,
+	BRCM_MAP_QSPI_RO,
+#ifdef PERIPH0_REGION
+	PERIPH0_REGION,
+#endif
+#ifdef PERIPH1_REGION
+	PERIPH1_REGION,
+#endif
+#ifdef USE_DDR
+	BRCM_MAP_NS_DRAM1,
+#if BRCM_BL31_IN_DRAM
+	BRCM_MAP_BL31_SEC_DRAM,
+#endif
+#else
+#ifdef BRCM_MAP_EXT_SRAM
+	BRCM_MAP_EXT_SRAM,
+#endif
+#endif
+#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE)
+	CRMU_SRAM_REGION,
+#endif
+	{0}
+};
+#endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_brcm_mmap[] = {
+	HSLS_REGION,
+#ifdef PERIPH0_REGION
+	PERIPH0_REGION,
+#endif
+#ifdef PERIPH1_REGION
+	PERIPH1_REGION,
+#endif
+#ifdef PERIPH2_REGION
+	PERIPH2_REGION,
+#endif
+#ifdef USB_REGION
+	USB_REGION,
+#endif
+#ifdef USE_DDR
+	BRCM_MAP_NS_DRAM1,
+#ifdef BRCM_MAP_NS_SHARED_DRAM
+	BRCM_MAP_NS_SHARED_DRAM,
+#endif
+#else
+#ifdef BRCM_MAP_EXT_SRAM
+	BRCM_MAP_EXT_SRAM,
+#endif
+#endif
+#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE)
+	CRMU_SRAM_REGION,
+#endif
+	{0}
+};
+#endif
+
+CASSERT((ARRAY_SIZE(plat_brcm_mmap) - 1) <= PLAT_BRCM_MMAP_ENTRIES,
+	assert_plat_brcm_mmap_mismatch);
+CASSERT((PLAT_BRCM_MMAP_ENTRIES + BRCM_BL_REGIONS) <= MAX_MMAP_REGIONS,
+	assert_max_mmap_regions);
diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
new file mode 100644
index 0000000..1795ce7
--- /dev/null
+++ b/plat/brcm/board/common/board_common.mk
@@ -0,0 +1,278 @@
+#
+# Copyright (c) 2015 - 2020, Broadcom
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_BL_COMMON_SOURCES	+=	plat/brcm/board/common/board_common.c
+
+# If no board config makefile, do not include it
+ifneq (${BOARD_CFG},)
+BOARD_CFG_MAKE := $(shell find plat/brcm/board/${PLAT} -name '${BOARD_CFG}.mk')
+$(eval $(call add_define,BOARD_CFG))
+ifneq (${BOARD_CFG_MAKE},)
+$(info Including ${BOARD_CFG_MAKE})
+include ${BOARD_CFG_MAKE}
+else
+$(error Error: File ${BOARD_CFG}.mk not found in plat/brcm/board/${PLAT})
+endif
+endif
+
+# To compile with highest log level (VERBOSE) set value to 50
+LOG_LEVEL := 40
+
+# Use custom generic timer clock
+ifneq (${GENTIMER_ACTUAL_CLOCK},)
+$(info Using GENTIMER_ACTUAL_CLOCK=$(GENTIMER_ACTUAL_CLOCK))
+SYSCNT_FREQ := $(GENTIMER_ACTUAL_CLOCK)
+$(eval $(call add_define,SYSCNT_FREQ))
+endif
+
+ifeq (${DRIVER_EMMC_ENABLE},)
+DRIVER_EMMC_ENABLE :=1
+endif
+
+ifeq (${DRIVER_SPI_ENABLE},)
+DRIVER_SPI_ENABLE := 0
+endif
+
+# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set
+ifeq (${BRCM_DISABLE_TRUSTED_WDOG},)
+BRCM_DISABLE_TRUSTED_WDOG	:=	0
+endif
+ifeq (${SPIN_ON_BL1_EXIT}, 1)
+BRCM_DISABLE_TRUSTED_WDOG	:=	1
+endif
+
+$(eval $(call assert_boolean,BRCM_DISABLE_TRUSTED_WDOG))
+$(eval $(call add_define,BRCM_DISABLE_TRUSTED_WDOG))
+
+# Process ARM_BL31_IN_DRAM flag
+ifeq (${ARM_BL31_IN_DRAM},)
+ARM_BL31_IN_DRAM		:=	0
+endif
+$(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
+$(eval $(call add_define,ARM_BL31_IN_DRAM))
+
+ifeq (${STANDALONE_BL2},yes)
+BL2_LOG_LEVEL := 40
+$(eval $(call add_define,MMU_DISABLED))
+endif
+
+# BL2 XIP from QSPI
+RUN_BL2_FROM_QSPI := 0
+ifeq (${RUN_BL2_FROM_QSPI},1)
+$(eval $(call add_define,RUN_BL2_FROM_QSPI))
+endif
+
+# BL2 XIP from NAND
+RUN_BL2_FROM_NAND := 0
+ifeq (${RUN_BL2_FROM_NAND},1)
+$(eval $(call add_define,RUN_BL2_FROM_NAND))
+endif
+
+ifneq (${ELOG_AP_UART_LOG_BASE},)
+$(eval $(call add_define,ELOG_AP_UART_LOG_BASE))
+endif
+
+ifeq (${ELOG_SUPPORT},1)
+ifeq (${ELOG_STORE_MEDIA},DDR)
+$(eval $(call add_define,ELOG_STORE_MEDIA_DDR))
+ifneq (${ELOG_STORE_OFFSET},)
+$(eval $(call add_define,ELOG_STORE_OFFSET))
+endif
+endif
+endif
+
+ifneq (${BL2_LOG_LEVEL},)
+$(eval $(call add_define,BL2_LOG_LEVEL))
+endif
+
+ifneq (${BL31_LOG_LEVEL},)
+$(eval $(call add_define,BL31_LOG_LEVEL))
+endif
+
+# Use CRMU SRAM from iHOST
+ifneq (${USE_CRMU_SRAM},)
+$(eval $(call add_define,USE_CRMU_SRAM))
+endif
+
+# Use PIO mode if DDR is not used
+ifeq (${USE_DDR},yes)
+EMMC_USE_DMA	:=	1
+else
+EMMC_USE_DMA	:=	0
+endif
+$(eval $(call add_define,EMMC_USE_DMA))
+
+# On BRCM platforms, separate the code and read-only data sections to allow
+# mapping the former as executable and the latter as execute-never.
+SEPARATE_CODE_AND_RODATA	:=	1
+
+# Use generic OID definition (tbbr_oid.h)
+USE_TBBR_DEFS			:=	1
+
+PLAT_INCLUDES		+=	-Iplat/brcm/board/common \
+				-Iinclude/drivers/brcm \
+				-Iinclude/drivers/brcm/emmc
+
+PLAT_BL_COMMON_SOURCES	+=	plat/brcm/common/brcm_common.c \
+				plat/brcm/board/common/cmn_sec.c \
+				plat/brcm/board/common/bcm_console.c \
+				plat/brcm/board/common/brcm_mbedtls.c \
+				plat/brcm/board/common/plat_setup.c \
+				plat/brcm/board/common/platform_common.c \
+				drivers/arm/sp804/sp804_delay_timer.c \
+				drivers/brcm/sotp.c \
+				drivers/delay_timer/delay_timer.c \
+				drivers/io/io_fip.c \
+				drivers/io/io_memmap.c \
+				drivers/io/io_storage.c \
+				plat/brcm/common/brcm_io_storage.c \
+				plat/brcm/board/common/err.c \
+				plat/brcm/board/common/sbl_util.c \
+				drivers/arm/sp805/sp805.c
+
+# Add eMMC driver
+ifeq (${DRIVER_EMMC_ENABLE},1)
+$(eval $(call add_define,DRIVER_EMMC_ENABLE))
+
+EMMC_SOURCES		+=	drivers/brcm/emmc/emmc_chal_sd.c \
+				drivers/brcm/emmc/emmc_csl_sdcard.c \
+				drivers/brcm/emmc/emmc_csl_sdcmd.c \
+				drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c
+
+PLAT_BL_COMMON_SOURCES += ${EMMC_SOURCES}
+
+ifeq (${DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT},)
+$(eval $(call add_define,DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT))
+endif
+endif
+
+BL2_SOURCES		+=	plat/brcm/common/brcm_bl2_mem_params_desc.c \
+				plat/brcm/common/brcm_image_load.c \
+				common/desc_image_load.c
+
+BL2_SOURCES		+= 	plat/brcm/common/brcm_bl2_setup.c
+
+BL31_SOURCES		+=	plat/brcm/common/brcm_bl31_setup.c
+
+ifeq (${BCM_ELOG},yes)
+ELOG_SOURCES		+= 	plat/brcm/board/common/bcm_elog.c
+BL2_SOURCES		+= 	${ELOG_SOURCES}
+BL31_SOURCES		+= 	${ELOG_SOURCES}
+endif
+
+# Add spi driver
+ifeq (${DRIVER_SPI_ENABLE},1)
+PLAT_BL_COMMON_SOURCES	+=	drivers/brcm/spi/iproc_spi.c \
+				drivers/brcm/spi/iproc_qspi.c
+endif
+
+# Add spi nor/flash driver
+ifeq (${DRIVER_SPI_NOR_ENABLE},1)
+PLAT_BL_COMMON_SOURCES	+=	drivers/brcm/spi_sf.c \
+				drivers/brcm/spi_flash.c
+endif
+
+ifeq (${DRIVER_OCOTP_ENABLE},1)
+$(eval $(call add_define,DRIVER_OCOTP_ENABLE))
+BL2_SOURCES		+= drivers/brcm/ocotp.c
+endif
+
+# Enable FRU table support
+ifeq (${USE_FRU},yes)
+$(eval $(call add_define,USE_FRU))
+BL2_SOURCES		+= drivers/brcm/fru.c
+endif
+
+# Enable GPIO support
+ifeq (${USE_GPIO},yes)
+$(eval $(call add_define,USE_GPIO))
+BL2_SOURCES             += drivers/gpio/gpio.c
+BL2_SOURCES             += drivers/brcm/iproc_gpio.c
+ifeq (${GPIO_SUPPORT_FLOAT_DETECTION},yes)
+$(eval $(call add_define,GPIO_SUPPORT_FLOAT_DETECTION))
+endif
+endif
+
+# Include mbedtls if it can be located
+MBEDTLS_DIR := mbedtls
+MBEDTLS_CHECK := $(shell find ${MBEDTLS_DIR}/include -name '${MBEDTLS_DIR}')
+
+ifneq (${MBEDTLS_CHECK},)
+$(info Found mbedTLS at ${MBEDTLS_DIR})
+PLAT_INCLUDES += -I${MBEDTLS_DIR}/include/mbedtls
+# Specify mbedTLS configuration file
+MBEDTLS_CONFIG_FILE	:=	"<brcm_mbedtls_config.h>"
+
+# By default, use RSA keys
+KEY_ALG := rsa_1_5
+
+# Include common TBB sources
+AUTH_SOURCES	+= 	drivers/auth/auth_mod.c \
+			drivers/auth/crypto_mod.c \
+			drivers/auth/img_parser_mod.c \
+			drivers/auth/tbbr/tbbr_cot.c
+
+BL2_SOURCES	+=	${AUTH_SOURCES}
+
+# Use ATF framework for MBEDTLS
+TRUSTED_BOARD_BOOT := 1
+CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk
+IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk
+$(info Including ${CRYPTO_LIB_MK})
+include ${CRYPTO_LIB_MK}
+$(info Including ${IMG_PARSER_LIB_MK})
+include ${IMG_PARSER_LIB_MK}
+
+# Use ATF secure boot functions
+# Use Hardcoded hash for devel
+
+ARM_ROTPK_LOCATION=arm_rsa
+ifeq (${ARM_ROTPK_LOCATION}, arm_rsa)
+ARM_ROTPK_LOCATION_ID=ARM_ROTPK_DEVEL_RSA_ID
+ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
+else ifeq (${ARM_ROTPK_LOCATION}, brcm_rsa)
+ARM_ROTPK_LOCATION_ID=BRCM_ROTPK_SOTP_RSA_ID
+ifeq (${ROT_KEY},)
+ROT_KEY=plat/brcm/board/common/rotpk/rsa_dauth2048_key.pem
+endif
+KEY_FIND := $(shell m="${ROT_KEY}"; [ -f "$$m" ] && echo "$$m")
+ifeq (${KEY_FIND},)
+$(error Error: No ${ROT_KEY} located)
+else
+$(info Using ROT_KEY: ${ROT_KEY})
+endif
+else
+$(error "Unsupported ARM_ROTPK_LOCATION value")
+endif
+
+$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+PLAT_BL_COMMON_SOURCES+=plat/brcm/board/common/board_arm_trusted_boot.c
+endif
+
+#M0 runtime firmware
+ifdef SCP_BL2
+$(eval $(call add_define,NEED_SCP_BL2))
+SCP_CFG_DIR=$(dir ${SCP_BL2})
+PLAT_INCLUDES += -I${SCP_CFG_DIR}
+endif
+
+ifneq (${NEED_BL33},yes)
+# If there is no BL33, BL31 will jump to this address.
+ifeq (${USE_DDR},yes)
+PRELOADED_BL33_BASE := 0x80000000
+else
+PRELOADED_BL33_BASE := 0x74000000
+endif
+endif
+
+# Use translation tables library v1 by default
+ARM_XLAT_TABLES_LIB_V1		:=	1
+ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
+$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
+$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
+PLAT_BL_COMMON_SOURCES	+=	lib/xlat_tables/aarch64/xlat_tables.c \
+				lib/xlat_tables/xlat_tables_common.c
+endif
diff --git a/plat/brcm/board/common/brcm_mbedtls.c b/plat/brcm/board/common/brcm_mbedtls.c
new file mode 100644
index 0000000..af42b86
--- /dev/null
+++ b/plat/brcm/board/common/brcm_mbedtls.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2015 - 2020 Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+
+void tls_exit(int code)
+{
+	INFO("%s: 0x%x\n", __func__, code);
+}
diff --git a/plat/brcm/board/common/chip_id.h b/plat/brcm/board/common/chip_id.h
new file mode 100644
index 0000000..842ac1f
--- /dev/null
+++ b/plat/brcm/board/common/chip_id.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CHIP_ID_H
+#define CHIP_ID_H
+
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define CHIP_REV_MAJOR_MASK	0xF0
+#define CHIP_REV_MAJOR_AX	0x00
+#define CHIP_REV_MAJOR_BX	0x10
+#define CHIP_REV_MAJOR_CX	0x20
+#define CHIP_REV_MAJOR_DX	0x30
+
+/* Get Chip ID (product number) of the chip */
+static inline unsigned int chip_get_product_id(void)
+{
+	return PLAT_CHIP_ID_GET;
+}
+
+/* Get Revision ID (major and minor) number of the chip */
+static inline unsigned int chip_get_rev_id(void)
+{
+	return PLAT_CHIP_REV_GET;
+}
+
+static inline unsigned int chip_get_rev_id_major(void)
+{
+	return (chip_get_rev_id() & CHIP_REV_MAJOR_MASK);
+}
+
+#endif
diff --git a/plat/brcm/board/common/cmn_plat_def.h b/plat/brcm/board/common/cmn_plat_def.h
new file mode 100644
index 0000000..8aa7fd4
--- /dev/null
+++ b/plat/brcm/board/common/cmn_plat_def.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CMN_PLAT_DEF_H
+#define CMN_PLAT_DEF_H
+
+#include <bcm_elog.h>
+
+#ifndef GET_LOG_LEVEL
+#define GET_LOG_LEVEL() LOG_LEVEL
+#endif
+
+#ifndef SET_LOG_LEVEL
+#define SET_LOG_LEVEL(x) ((void)(x))
+#endif
+
+#define PLAT_LOG_NOTICE(...)						 \
+		do {							 \
+			if (GET_LOG_LEVEL() >= LOG_LEVEL_NOTICE) {	 \
+				bcm_elog(LOG_MARKER_NOTICE __VA_ARGS__); \
+				tf_log(LOG_MARKER_NOTICE __VA_ARGS__);	 \
+			}						 \
+		} while (0)
+
+#define PLAT_LOG_ERROR(...)						 \
+		do {							 \
+			if (GET_LOG_LEVEL() >= LOG_LEVEL_ERROR) {	 \
+				bcm_elog(LOG_MARKER_ERROR, __VA_ARGS__); \
+				tf_log(LOG_MARKER_ERROR __VA_ARGS__);	 \
+			}						 \
+		} while (0)
+
+#define PLAT_LOG_WARN(...)						 \
+		do {							 \
+			if (GET_LOG_LEVEL() >= LOG_LEVEL_WARNING) {	 \
+				bcm_elog(LOG_MARKER_WARNING, __VA_ARGS__);\
+				tf_log(LOG_MARKER_WARNING __VA_ARGS__);	 \
+			}						 \
+		} while (0)
+
+#define PLAT_LOG_INFO(...)						 \
+		do {							 \
+			if (GET_LOG_LEVEL() >= LOG_LEVEL_INFO) {	 \
+				bcm_elog(LOG_MARKER_INFO __VA_ARGS__);	 \
+				tf_log(LOG_MARKER_INFO  __VA_ARGS__);    \
+			}						 \
+		} while (0)
+
+#define PLAT_LOG_VERBOSE(...)						 \
+		do {							 \
+			if (GET_LOG_LEVEL()  >= LOG_LEVEL_VERBOSE) {	 \
+				bcm_elog(LOG_MARKER_VERBOSE __VA_ARGS__);\
+				tf_log(LOG_MARKER_VERBOSE __VA_ARGS__);	 \
+			}						 \
+		} while (0)
+
+/* Print file and line number on assert */
+#define PLAT_LOG_LEVEL_ASSERT LOG_LEVEL_INFO
+
+/*
+ * The number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#if USE_COHERENT_MEM
+#define CMN_BL_REGIONS	3
+#else
+#define CMN_BL_REGIONS	2
+#endif
+
+/*
+ * FIP definitions
+ */
+#define PLAT_FIP_ATTEMPT_OFFSET		0x20000
+#define PLAT_FIP_NUM_ATTEMPTS		128
+
+#define PLAT_BRCM_FIP_QSPI_BASE		QSPI_BASE_ADDR
+#define PLAT_BRCM_FIP_NAND_BASE		NAND_BASE_ADDR
+#define PLAT_BRCM_FIP_MAX_SIZE		0x01000000
+
+#define PLAT_BRCM_FIP_BASE	PLAT_BRCM_FIP_QSPI_BASE
+#endif
diff --git a/plat/brcm/board/common/cmn_plat_util.h b/plat/brcm/board/common/cmn_plat_util.h
new file mode 100644
index 0000000..178c843
--- /dev/null
+++ b/plat/brcm/board/common/cmn_plat_util.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CMN_PLAT_UTIL_H
+#define CMN_PLAT_UTIL_H
+
+#include <lib/mmio.h>
+
+/* BOOT source */
+#define BOOT_SOURCE_MASK	7
+#define BOOT_SOURCE_QSPI	0
+#define BOOT_SOURCE_NAND	1
+#define BOOT_SOURCE_SPI_NAND	2
+#define BOOT_SOURCE_UART	3
+#define BOOT_SOURCE_RES4	4
+#define BOOT_SOURCE_EMMC	5
+#define BOOT_SOURCE_ATE		6
+#define BOOT_SOURCE_USB		7
+#define BOOT_SOURCE_MAX		8
+#define BOOT_SOURCE_UNKNOWN	(-1)
+
+#define KHMAC_SHA256_KEY_SIZE	32
+
+#define SOFT_PWR_UP_RESET_L0	0
+#define SOFT_SYS_RESET_L1	1
+#define SOFT_RESET_L3		0x3
+
+#define BOOT_SOURCE_SOFT_DATA_OFFSET	8
+#define BOOT_SOURCE_SOFT_ENABLE_OFFSET	14
+#define BOOT_SOURCE_SOFT_ENABLE_MASK	BIT(BOOT_SOURCE_SOFT_ENABLE_OFFSET)
+
+typedef struct _key {
+	uint8_t  hmac_sha256[KHMAC_SHA256_KEY_SIZE];
+} cmn_key_t;
+
+uint32_t boot_source_get(void);
+void bl1_platform_wait_events(void);
+void plat_soft_reset(uint32_t reset);
+
+#endif
diff --git a/plat/brcm/board/common/cmn_sec.c b/plat/brcm/board/common/cmn_sec.c
new file mode 100644
index 0000000..c80d5dd
--- /dev/null
+++ b/plat/brcm/board/common/cmn_sec.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <cmn_sec.h>
+
+#pragma weak plat_tz_master_default_cfg
+#pragma weak plat_tz_sdio_ns_master_set
+#pragma weak plat_tz_usb_ns_master_set
+
+void plat_tz_master_default_cfg(void)
+{
+	/* This function should be implemented in the platform side. */
+	ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
+}
+
+void plat_tz_sdio_ns_master_set(uint32_t ns)
+{
+	/* This function should be implemented in the platform side. */
+	ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
+}
+
+void plat_tz_usb_ns_master_set(uint32_t ns)
+{
+	/* This function should be implemented in the platform side. */
+	ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
+}
+
+void tz_master_default_cfg(void)
+{
+	plat_tz_master_default_cfg();
+}
+
+void tz_sdio_ns_master_set(uint32_t ns)
+{
+	plat_tz_sdio_ns_master_set(ns);
+}
+
+void tz_usb_ns_master_set(uint32_t ns)
+{
+	plat_tz_usb_ns_master_set(ns);
+}
diff --git a/plat/brcm/board/common/cmn_sec.h b/plat/brcm/board/common/cmn_sec.h
new file mode 100644
index 0000000..f74863d
--- /dev/null
+++ b/plat/brcm/board/common/cmn_sec.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CMN_SEC_H
+#define CMN_SEC_H
+
+#include <stdint.h>
+
+#define SECURE_MASTER 0
+#define NS_MASTER 1
+
+void tz_master_default_cfg(void);
+void tz_usb_ns_master_set(uint32_t ns);
+void tz_sdio_ns_master_set(uint32_t ns);
+
+#endif
diff --git a/plat/brcm/board/common/err.c b/plat/brcm/board/common/err.c
new file mode 100644
index 0000000..1fc73c4
--- /dev/null
+++ b/plat/brcm/board/common/err.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define L0_RESET 0x2
+
+/*
+ * Brcm error handler
+ */
+void plat_error_handler(int err)
+{
+	INFO("L0 reset...\n");
+
+	/* Ensure the characters are flushed out */
+	console_flush();
+
+	mmio_write_32(CRMU_SOFT_RESET_CTRL, L0_RESET);
+
+	/*
+	 * In case we get here:
+	 * Loop until the watchdog resets the system
+	 */
+	while (1) {
+		wfi();
+	}
+}
diff --git a/plat/brcm/board/common/plat_setup.c b/plat/brcm/board/common/plat_setup.c
new file mode 100644
index 0000000..95e12ed
--- /dev/null
+++ b/plat/brcm/board/common/plat_setup.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*
+ * This function returns the fixed clock frequency at which private
+ * timers run. This value will be programmed into CNTFRQ_EL0.
+ */
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYSCNT_FREQ;
+}
+
+static const char * const plat_prefix_str[] = {
+	"E: ", "N: ", "W: ", "I: ", "V: "
+};
+
+const char *plat_log_get_prefix(unsigned int log_level)
+{
+	return plat_prefix_str[log_level - 1U];
+}
diff --git a/plat/brcm/board/common/platform_common.c b/plat/brcm/board/common/platform_common.c
new file mode 100644
index 0000000..f4c9a73
--- /dev/null
+++ b/plat/brcm/board/common/platform_common.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/brcm/sotp.h>
+
+#include <cmn_plat_util.h>
+#include <platform_def.h>
+
+uint32_t boot_source_get(void)
+{
+	uint32_t data;
+
+#ifdef FORCE_BOOTSOURCE
+	data = FORCE_BOOTSOURCE;
+#else
+	/* Read primary boot strap from CRMU persistent registers */
+	data = mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1);
+	if (data & BOOT_SOURCE_SOFT_ENABLE_MASK) {
+		data >>= BOOT_SOURCE_SOFT_DATA_OFFSET;
+	} else {
+		uint64_t sotp_atf_row;
+
+		sotp_atf_row =
+			sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC);
+
+		if (sotp_atf_row & SOTP_BOOT_SOURCE_ENABLE_MASK) {
+			/* Construct the boot source based on SOTP bits */
+			data = 0;
+			if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS0)
+				data |= 0x1;
+			if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS1)
+				data |= 0x2;
+			if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS2)
+				data |= 0x4;
+		} else {
+
+			/*
+			 * This path is for L0 reset with
+			 * Primary Boot source disabled in SOTP.
+			 * BOOT_SOURCE_FROM_PR_ON_L1 compile flag will allow
+			 * to never come back here so that the
+			 * external straps will not be read on L1 reset.
+			 */
+
+			/* Use the external straps */
+			data = mmio_read_32(ROM_S0_IDM_IO_STATUS);
+
+#ifdef BOOT_SOURCE_FROM_PR_ON_L1
+			/* Enable boot source read from PR#1 */
+			mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1,
+				BOOT_SOURCE_SOFT_ENABLE_MASK);
+
+			/* set boot source */
+			data &= BOOT_SOURCE_MASK;
+			mmio_clrsetbits_32(CRMU_IHOST_SW_PERSISTENT_REG1,
+			BOOT_SOURCE_MASK << BOOT_SOURCE_SOFT_DATA_OFFSET,
+			data << BOOT_SOURCE_SOFT_DATA_OFFSET);
+#endif
+		}
+	}
+#endif
+	return (data & BOOT_SOURCE_MASK);
+}
+
+void __dead2 plat_soft_reset(uint32_t reset)
+{
+	if (reset == SOFT_RESET_L3) {
+		mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, reset);
+		mmio_write_32(CRMU_MAIL_BOX0, 0x0);
+		mmio_write_32(CRMU_MAIL_BOX1, 0xFFFFFFFF);
+	}
+
+	if (reset != SOFT_SYS_RESET_L1)
+		reset = SOFT_PWR_UP_RESET_L0;
+
+	if (reset == SOFT_PWR_UP_RESET_L0)
+		INFO("L0 RESET...\n");
+
+	if (reset == SOFT_SYS_RESET_L1)
+		INFO("L1 RESET...\n");
+
+	console_flush();
+
+	mmio_clrbits_32(CRMU_SOFT_RESET_CTRL, 1 << reset);
+
+	while (1) {
+		;
+	}
+}
diff --git a/plat/brcm/board/common/sbl_util.c b/plat/brcm/board/common/sbl_util.c
new file mode 100644
index 0000000..06e5b33
--- /dev/null
+++ b/plat/brcm/board/common/sbl_util.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+
+#include <platform_def.h>
+#include <sbl_util.h>
+#include <sotp.h>
+
+#pragma weak plat_sbl_status
+
+int plat_sbl_status(uint64_t sbl_status)
+{
+	return sbl_status ? 1:0;
+}
+
+int sbl_status(void)
+{
+	uint64_t sbl_sotp = 0;
+	int ret = SBL_DISABLED;
+
+	sbl_sotp = sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC);
+
+	if (sbl_sotp != SOTP_ECC_ERR_DETECT) {
+
+		sbl_sotp &= SOTP_SBL_MASK;
+
+		if (plat_sbl_status(sbl_sotp))
+			ret = SBL_ENABLED;
+	}
+
+	VERBOSE("SBL status: %d\n", ret);
+
+	return ret;
+}
diff --git a/plat/brcm/board/common/sbl_util.h b/plat/brcm/board/common/sbl_util.h
new file mode 100644
index 0000000..0747389
--- /dev/null
+++ b/plat/brcm/board/common/sbl_util.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SBL_UTIL_H
+#define SBL_UTIL_H
+
+#include <stdint.h>
+
+#include <sotp.h>
+
+#define SBL_DISABLED 0
+#define SBL_ENABLED 1
+
+int sbl_status(void);
+
+#endif /* #ifdef SBL_UTIL_H */
diff --git a/plat/brcm/board/common/timer_sync.c b/plat/brcm/board/common/timer_sync.c
new file mode 100644
index 0000000..7e33a94
--- /dev/null
+++ b/plat/brcm/board/common/timer_sync.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+#include <timer_sync.h>
+
+/*******************************************************************************
+ * Defines related to time sync and satelite timers
+ ******************************************************************************/
+#define TIME_SYNC_WR_ENA	((uint32_t)0xACCE55 << 8)
+#define IHOST_STA_TMR_CTRL	0x1800
+#define IHOST_SAT_TMR_INC_L	0x1814
+#define IHOST_SAT_TMR_INC_H	0x1818
+
+#define SAT_TMR_CYCLE_DELAY	2
+#define SAT_TMR_32BIT_WRAP_VAL	(BIT_64(32) - SAT_TMR_CYCLE_DELAY)
+
+void ihost_enable_satellite_timer(unsigned int cluster_id)
+{
+	uintptr_t ihost_base;
+	uint32_t time_lx, time_h;
+	uintptr_t ihost_enable;
+
+	VERBOSE("Program iHost%u satellite timer\n", cluster_id);
+	ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
+
+	/* this read starts the satellite timer counting from 0 */
+	ihost_enable = CENTRAL_TIMER_GET_IHOST_ENA_BASE + cluster_id * 4;
+	time_lx = mmio_read_32(ihost_enable);
+
+	/*
+	 * Increment the satellite timer by the central timer plus 2
+	 * to accommodate for a 1 cycle delay through NOC
+	 * plus counter starting from 0.
+	 */
+	mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_L,
+		      time_lx + SAT_TMR_CYCLE_DELAY);
+
+	/*
+	 * Read the latched upper data, if lx will wrap by adding 2 to it
+	 * we need to handle the wrap
+	 */
+	time_h = mmio_read_32(CENTRAL_TIMER_GET_H);
+	if (time_lx >= SAT_TMR_32BIT_WRAP_VAL)
+		mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h + 1);
+	else
+		mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h);
+}
+
+void brcm_timer_sync_init(void)
+{
+	unsigned int cluster_id;
+
+	/* Get the Time Sync module out of reset */
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
+			BIT(CDRU_MISC_RESET_CONTROL_TS_RESET_N));
+
+	/* Deassert the Central Timer TIMER_EN signal for all module */
+	mmio_write_32(CENTRAL_TIMER_SAT_TMR_ENA, TIME_SYNC_WR_ENA);
+
+	/* enables/programs iHost0 satellite timer*/
+	cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
+	ihost_enable_satellite_timer(cluster_id);
+}
diff --git a/plat/brcm/board/stingray/aarch64/plat_helpers.S b/plat/brcm/board/stingray/aarch64/plat_helpers.S
new file mode 100644
index 0000000..6095532
--- /dev/null
+++ b/plat/brcm/board/stingray/aarch64/plat_helpers.S
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <cpu_macros.S>
+#include <cortex_a72.h>
+#include <drivers/ti/uart/uart_16550.h>
+
+#include <platform_def.h>
+
+	.globl	plat_reset_handler
+	.globl	platform_get_entrypoint
+	.globl	plat_secondary_cold_boot_setup
+	.globl	platform_mem_init
+	.globl	platform_check_mpidr
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
+	.globl	plat_disable_acp
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_my_core_pos
+	.globl	platform_is_primary_cpu
+	.globl	plat_brcm_calc_core_pos
+	.globl	plat_get_my_entrypoint
+
+
+	/* ------------------------------------------------------------
+	 * void plat_l2_init(void);
+	 *
+	 * BL1 and BL2 run with one core, one cluster
+	 * This is safe to disable cluster coherency
+	 * to make use of the data cache MMU WB attribute
+	 * for the SRAM.
+	 *
+	 * Set L2 Auxiliary Control Register
+	 * --------------------------------------------------------------------
+	 */
+func plat_l2_init
+	mrs x0, CORTEX_A72_L2ACTLR_EL1
+#if (IMAGE_BL1 || IMAGE_BL2) || defined(USE_SINGLE_CLUSTER)
+	orr x0, x0, #CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI
+#else
+	bic x0, x0, #CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI
+#endif
+	msr CORTEX_A72_L2ACTLR_EL1, x0
+
+	/* Set L2 Control Register */
+	mrs x0, CORTEX_A72_L2CTLR_EL1
+	mov x1, #((CORTEX_A72_L2_DATA_RAM_LATENCY_MASK << \
+			CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+			(CORTEX_A72_L2_TAG_RAM_LATENCY_MASK << \
+			CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT) | \
+			(U(0x1) << CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT) | \
+			(U(0x1) << CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT))
+	bic x0, x0, x1
+	mov x1, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << \
+			CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+			(U(0x1) << CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT) | \
+			(U(0x1) << CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT))
+	orr x0, x0, x1
+	msr CORTEX_A72_L2CTLR_EL1, x0
+
+	isb
+	ret
+endfunc plat_l2_init
+
+	/* --------------------------------------------------------------------
+	 * void plat_reset_handler(void);
+	 *
+	 * Before adding code in this function, refer to the guidelines in
+	 * docs/firmware-design.md.
+	 *
+	 * --------------------------------------------------------------------
+	 */
+func plat_reset_handler
+	mov	x9, x30
+	bl	plat_l2_init
+	mov	x30, x9
+	ret
+endfunc plat_reset_handler
+
+	/* -----------------------------------------------------
+	 * void platform_get_entrypoint (unsigned int mpid);
+	 *
+	 * Main job of this routine is to distinguish between
+	 * a cold and warm boot.
+	 * On a cold boot the secondaries first wait for the
+	 * platform to be initialized after which they are
+	 * hotplugged in. The primary proceeds to perform the
+	 * platform initialization.
+	 * -----------------------------------------------------
+	 */
+func platform_get_entrypoint
+	/*TBD-STINGRAY*/
+	mov x0, #0
+	ret
+endfunc platform_get_entrypoint
+
+	/* -----------------------------------------------------
+	 * void plat_secondary_cold_boot_setup (void);
+	 *
+	 * This function performs any platform specific actions
+	 * needed for a secondary cpu after a cold reset e.g
+	 * mark the cpu's presence, mechanism to place it in a
+	 * holding pen etc.
+	 * -----------------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+	bl	plat_my_core_pos
+	mov_imm	x1, SECONDARY_CPU_SPIN_BASE_ADDR
+	add	x0, x1, x0, LSL #3
+	mov	x1, #0
+	str	x1, [x0]
+
+	/* Wait until the entrypoint gets populated */
+poll_mailbox:
+	ldr	x1, [x0]
+	cbz	x1, 1f
+	br	x1
+1:
+	wfe
+	b	poll_mailbox
+endfunc plat_secondary_cold_boot_setup
+
+
+	/* -----------------------------------------------------
+	 * void platform_mem_init(void);
+	 *
+	 * We don't need to carry out any memory initialization
+	 * on CSS platforms. The Secure RAM is accessible straight away.
+	 * -----------------------------------------------------
+	 */
+func platform_mem_init
+	/*TBD-STINGRAY*/
+	ret
+endfunc platform_mem_init
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platform.
+	 * -----------------------------------------------------
+	 */
+func platform_check_mpidr
+	/*TBD-STINGRAY*/
+	mov	x0, xzr
+	ret
+endfunc platform_check_mpidr
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0, x1, x2
+	 * ---------------------------------------------
+	 */
+
+func plat_crash_console_init
+	mov_imm	x0, BRCM_CRASH_CONSOLE_BASE
+	mov_imm	x1, BRCM_CRASH_CONSOLE_REFCLK
+	mov_imm	x2, BRCM_CRASH_CONSOLE_BAUDRATE
+	b	console_16550_core_init
+	ret
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(void)
+	 * Function to print a character on the crash
+	 * console without a C Runtime.
+	 * Clobber list : x1, x2, x3
+	 * ---------------------------------------------
+	 */
+
+func plat_crash_console_putc
+	mov_imm x1, BRCM_CRASH_CONSOLE_BASE
+	b	console_16550_core_putc
+	ret
+endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush(void)
+	 * Function to flush crash console
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm x0, BRCM_CRASH_CONSOLE_BASE
+	b	console_16550_core_flush
+	ret
+endfunc plat_crash_console_flush
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platform. This function is allowed to use
+	 * registers x0 - x17.
+	 * -----------------------------------------------------
+	 */
+
+func plat_disable_acp
+	/*TBD-STINGRAY*/
+	ret
+endfunc plat_disable_acp
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_is_my_cpu_primary (void);
+	 *
+	 * Find out whether the current cpu is the primary
+	 * cpu (applicable only after a cold boot)
+	 * -----------------------------------------------------
+	 */
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	b	platform_is_primary_cpu
+endfunc plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the plat_brcm_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_brcm_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int platform_is_primary_cpu (void);
+	 *
+	 * Find out whether the current cpu is the primary
+	 * cpu (applicable only after a cold boot)
+	 * -----------------------------------------------------
+	 */
+func platform_is_primary_cpu
+	mov	x9, x30
+	bl	plat_my_core_pos
+	cmp	x0, #PRIMARY_CPU
+	cset	x0, eq
+	ret	x9
+endfunc platform_is_primary_cpu
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_brcm_calc_core_pos(uint64_t mpidr)
+	 *  Helper function to calculate the core position.
+	 *  With this function: CorePos = (ClusterId * 4) +
+	 *  				  CoreId
+	 * -----------------------------------------------------
+	 */
+func plat_brcm_calc_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #7
+	ret
+endfunc plat_brcm_calc_core_pos
+
+func plat_get_my_entrypoint
+	mrs	x0, mpidr_el1
+	b	platform_get_entrypoint
+endfunc plat_get_my_entrypoint
diff --git a/plat/brcm/board/stingray/bcm958742t-ns3.mk b/plat/brcm/board/stingray/bcm958742t-ns3.mk
new file mode 100644
index 0000000..5164eeb
--- /dev/null
+++ b/plat/brcm/board/stingray/bcm958742t-ns3.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2015 - 2020, Broadcom
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#######################################################
+# Board config file for bcm958742t-ns3 Stingray SST100-NS3
+#######################################################
+
+include plat/brcm/board/stingray/bcm958742t.mk
+
+# Load BL33 at 0xFF00_0000 address
+ifneq (${BL33_OVERRIDE_LOAD_ADDR},)
+$(eval $(call add_define_val,BL33_OVERRIDE_LOAD_ADDR,0xFF000000))
+endif
+
+# Nitro DDR secure memory
+# Nitro FW and config 0x8AE00000 - 0x8B000000
+# Nitro Crash dump 0x8B000000 - 0x8D000000
+DDR_NITRO_SECURE_REGION_START := 0x8AE00000
+DDR_NITRO_SECURE_REGION_END := 0x8D000000
diff --git a/plat/brcm/board/stingray/bcm958742t.mk b/plat/brcm/board/stingray/bcm958742t.mk
new file mode 100644
index 0000000..5e164b8
--- /dev/null
+++ b/plat/brcm/board/stingray/bcm958742t.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2015 - 2020, Broadcom
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#######################################################
+# Board config file for bcm958742t Stingray SST100
+#######################################################
+BOARD_FAMILY := "<bcm958742t.h>"
+$(eval $(call add_define,BOARD_FAMILY))
+
+# Board has internal programmable regulator
+IHOST_REG_TYPE := IHOST_REG_INTEGRATED
+$(eval $(call add_define,IHOST_REG_TYPE))
+
+# Board has internal programmable regulator
+VDDC_REG_TYPE := VDDC_REG_INTEGRATED
+$(eval $(call add_define,VDDC_REG_TYPE))
diff --git a/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h b/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h
new file mode 100644
index 0000000..b2427cf
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_FAMILY_H
+#define BOARD_FAMILY_H
+
+#if defined(DRIVER_SPD_ENABLE) && !defined(DRIVER_SPD_SPOOF)
+#include <spd.h>
+#endif
+
+#ifdef USE_GPIO
+/* max number of supported GPIOs to construct the bitmap for board detection */
+#define MAX_NR_GPIOS           4
+
+/* max GPIO bitmap value */
+#define MAX_GPIO_BITMAP_VAL    (BIT(MAX_NR_GPIOS) - 1)
+#endif
+
+struct mcb_ref_group {
+	uint32_t mcb_ref;
+	unsigned int *mcb_cfg;
+};
+
+#define MCB_REF_GROUP(ref)		\
+{					\
+	.mcb_ref =  0x ## ref,		\
+	.mcb_cfg = mcb_ ## ref,		\
+}
+
+#endif
diff --git a/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c
new file mode 100644
index 0000000..74d2077
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+static void brcm_stingray_pnor_pinmux_init(void)
+{
+	unsigned int i;
+
+	INFO(" - pnor pinmux init start.\n");
+
+	/* Set PNOR_ADV_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2dc),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_BAA_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e0),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_BLS_0_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e4),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_BLS_1_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e8),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_CRE_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2ec),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_CS_2_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f0),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_CS_1_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f4),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_CS_0_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f8),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_WE_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2fc),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_OE_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x300),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_INTR_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x304),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set PNOR_DAT_x_MODE_SEL_CONTROL.fsel = 0x2 */
+	for (i = 0; i < 0x40; i += 0x4) {
+		mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x308 + i),
+				   MODE_SEL_CONTROL_FSEL_MASK,
+				   MODE_SEL_CONTROL_FSEL_MODE2);
+	}
+
+	/* Set NAND_CE1_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x348),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set NAND_CE0_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x34c),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set NAND_WE_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x350),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set NAND_WP_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x354),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set NAND_RE_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x358),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set NAND_RDY_BSY_N_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x35c),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set NAND_IOx_0_MODE_SEL_CONTROL.fsel = 0x2 */
+	for (i = 0; i < 0x40; i += 0x4) {
+		mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x360 + i),
+				   MODE_SEL_CONTROL_FSEL_MASK,
+				   MODE_SEL_CONTROL_FSEL_MODE2);
+	}
+
+	/* Set NAND_ALE_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x3a0),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	/* Set NAND_CLE_MODE_SEL_CONTROL.fsel = 0x2 */
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x3a4),
+			   MODE_SEL_CONTROL_FSEL_MASK,
+			   MODE_SEL_CONTROL_FSEL_MODE2);
+
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x40), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x44), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x48), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x4c), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x50), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x54), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x58), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x5c), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x60), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x64), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x68), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x6c), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x70), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x74), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x78), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x7c), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x80), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x84), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x88), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x8c), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x90), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x94), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x98), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x9c), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa0), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa4), (7 << 1), 0x8);
+	mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa8), (7 << 1), 0x8);
+
+	INFO(" - pnor pinmux init done.\n");
+}
+
+#if BL2_TEST_EXT_SRAM
+#define SRAM_CHECKS_GRANUL	0x100000
+#define SRAM_CHECKS_CNT		8
+static unsigned int sram_checks[SRAM_CHECKS_CNT] = {
+	/* offset, magic */
+	0xd00dfeed,
+	0xfadebabe,
+	0xc001d00d,
+	0xa5a5b5b5,
+	0x5a5a5b5b,
+	0xc5c5d5d5,
+	0x5c5c5d5d,
+	0xe5e5f5f5,
+};
+#endif
+
+static void brcm_stingray_pnor_sram_init(void)
+{
+	unsigned int val, tmp;
+#if BL2_TEST_EXT_SRAM
+	unsigned int off, i;
+#endif
+	INFO(" - pnor sram init start.\n");
+
+	/* Enable PNOR Clock */
+	INFO(" -- enable pnor clock\n");
+	mmio_write_32((uintptr_t)(PNOR_IDM_IO_CONTROL_DIRECT), 0x1);
+	udelay(500);
+
+	/* Reset PNOR */
+	INFO(" -- reset pnor\n");
+	mmio_setbits_32((uintptr_t)(PNOR_IDM_IO_RESET_CONTROL), 0x1);
+	udelay(500);
+	mmio_clrbits_32((uintptr_t)(PNOR_IDM_IO_RESET_CONTROL), 0x1);
+	udelay(500);
+
+	/* Configure slave address to chip-select mapping */
+	INFO(" -- configure pnor slave address to chip-select mapping\n");
+	/* 0x74000000-0x75ffffff => CS0 (32MB) */
+	val = (0xfe << PNOR_ICFG_CS_x_MASK0_SHIFT);
+	val |= (0x74);
+	mmio_write_32((uintptr_t)(PNOR_ICFG_CS_0), val);
+	/* 0x76000000-0x77ffffff => CS1 (32MB) */
+	val = (0xfe << PNOR_ICFG_CS_x_MASK0_SHIFT);
+	val |= (0x76);
+	mmio_write_32((uintptr_t)(PNOR_ICFG_CS_1), val);
+	/* 0xffffffff-0xffffffff => CS2 (0MB) */
+	val = (0x00 << PNOR_ICFG_CS_x_MASK0_SHIFT);
+	val |= (0xff);
+	mmio_write_32((uintptr_t)(PNOR_ICFG_CS_2), val);
+
+	/* Print PNOR ID */
+	tmp = 0x0;
+	val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID0));
+	tmp |= (val & PNOR_REG_PERIPH_IDx_MASK);
+	val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID1));
+	tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 8);
+	val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID2));
+	tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 16);
+	val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID3));
+	tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 24);
+	INFO(" -- pnor primecell_id = 0x%x\n", tmp);
+
+	/* PNOR set_cycles */
+#ifdef EMULATION_SETUP
+	val = 0x00129A44;
+#else
+	val = 0x00125954; /* 0x00002DEF; */
+#endif
+	mmio_write_32((uintptr_t)(PNOR_REG_SET_CYCLES), val);
+	INFO(" -- pnor set_cycles = 0x%x\n", val);
+
+	/* PNOR set_opmode */
+	val = 0x0;
+#ifdef EMULATION_SETUP
+	/* TODO: Final values to be provided by DV folks */
+	val &= ~(0x7 << 7); /* set_wr_bl */
+	val &= ~(0x7 << 3);  /* set_rd_bl */
+	val &= ~(0x3);
+	val |= (0x1); /* set_mw */
+#else
+	/* TODO: Final values to be provided by DV folks */
+	val &= ~(0x7 << 7); /* set_wr_bl */
+	val &= ~(0x7 << 3);  /* set_rd_bl */
+	val &= ~(0x3);
+	val |= (0x1); /* set_mw */
+#endif
+	mmio_write_32((uintptr_t)(PNOR_REG_SET_OPMODE), val);
+	INFO(" -- pnor set_opmode = 0x%x\n", val);
+
+#ifndef EMULATION_SETUP
+	/* Actual SRAM chip will require self-refresh */
+	val = 0x1;
+	mmio_write_32((uintptr_t)(PNOR_REG_REFRESH_0), val);
+	INFO(" -- pnor refresh_0 = 0x%x\n", val);
+#endif
+
+#if BL2_TEST_EXT_SRAM
+	/* Check PNOR SRAM access */
+	for (off = 0; off < NOR_SIZE; off += SRAM_CHECKS_GRANUL) {
+		i = (off / SRAM_CHECKS_GRANUL) % SRAM_CHECKS_CNT;
+		val = sram_checks[i];
+		INFO(" -- pnor sram write addr=0x%lx value=0x%lx\n",
+		     (unsigned long)(NOR_BASE_ADDR + off),
+		     (unsigned long)val);
+		mmio_write_32((uintptr_t)(NOR_BASE_ADDR + off), val);
+	}
+	tmp = 0;
+	for (off = 0; off < NOR_SIZE; off += SRAM_CHECKS_GRANUL) {
+		i = (off / SRAM_CHECKS_GRANUL) % SRAM_CHECKS_CNT;
+		val = mmio_read_32((uintptr_t)(NOR_BASE_ADDR + off));
+		INFO(" -- pnor sram read addr=0x%lx value=0x%lx\n",
+		     (unsigned long)(NOR_BASE_ADDR + off),
+		     (unsigned long)val);
+		if (val == sram_checks[i])
+			tmp++;
+	}
+	INFO(" -- pnor sram checks pass=%d total=%d\n",
+	     tmp, (NOR_SIZE / SRAM_CHECKS_GRANUL));
+
+	if (tmp != (NOR_SIZE / SRAM_CHECKS_GRANUL)) {
+		INFO(" - pnor sram init failed.\n");
+		while (1)
+			;
+	} else {
+		INFO(" - pnor sram init done.\n");
+	}
+#endif
+}
+
+void ext_sram_init(void)
+{
+	INFO("%s start.\n", __func__);
+
+	brcm_stingray_pnor_pinmux_init();
+
+	brcm_stingray_pnor_sram_init();
+
+	INFO("%s done.\n", __func__);
+}
diff --git a/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h
new file mode 100644
index 0000000..8508653
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EXT_SRAM_INIT_H
+#define EXT_SRAM_INIT_H
+
+void ext_sram_init(void);
+#endif
diff --git a/plat/brcm/board/stingray/driver/ihost_pll_config.c b/plat/brcm/board/stingray/driver/ihost_pll_config.c
new file mode 100644
index 0000000..1184928
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ihost_pll_config.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <dmu.h>
+
+#define IHOST0_CONFIG_ROOT	0x66000000
+#define IHOST1_CONFIG_ROOT	0x66002000
+#define IHOST2_CONFIG_ROOT	0x66004000
+#define IHOST3_CONFIG_ROOT	0x66006000
+#define A72_CRM_PLL_PWR_ON	0x00000070
+#define A72_CRM_PLL_PWR_ON__PLL0_RESETB_R	4
+#define A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R	5
+#define A72_CRM_PLL_CHNL_BYPS_EN		0x000000ac
+#define A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R	0
+#define A72_CRM_PLL_CHNL_BYPS_EN_DATAMASK	0x0000ec1f
+#define A72_CRM_PLL_CMD				0x00000080
+#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R		0
+#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R		1
+#define A72_CRM_PLL_STATUS			0x00000084
+#define A72_CRM_PLL_STATUS__PLL0_LOCK_R		9
+#define A72_CRM_PLL0_CTRL1			0x00000100
+#define A72_CRM_PLL0_CTRL2 			0x00000104
+#define A72_CRM_PLL0_CTRL3 			0x00000108
+#define A72_CRM_PLL0_CTRL3__PLL0_PDIV_R 12
+#define A72_CRM_PLL0_CTRL4 			0x0000010c
+#define A72_CRM_PLL0_CTRL4__PLL0_KP_R		0
+#define A72_CRM_PLL0_CTRL4__PLL0_KI_R		4
+#define A72_CRM_PLL0_CTRL4__PLL0_KA_R		7
+#define A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R	10
+
+#define PLL_MODE_VCO		0x0
+#define PLL_MODE_BYPASS		0x1
+#define PLL_RESET_TYPE_PLL	0x1
+#define PLL_RESET_TYPE_POST	0x2
+#define PLL_VCO			0x1
+#define PLL_POSTDIV		0x2
+#define ARM_FREQ_3G		PLL_FREQ_FULL
+#define ARM_FREQ_1P5G		PLL_FREQ_HALF
+#define ARM_FREQ_750M		PLL_FREQ_QRTR
+
+static unsigned int ARMCOE_crm_getBaseAddress(unsigned int cluster_num)
+{
+	unsigned int ihostx_config_root;
+
+	switch (cluster_num) {
+	case 0:
+	default:
+		ihostx_config_root = IHOST0_CONFIG_ROOT;
+		break;
+	case 1:
+		ihostx_config_root = IHOST1_CONFIG_ROOT;
+		break;
+	case 2:
+		ihostx_config_root = IHOST2_CONFIG_ROOT;
+		break;
+	case 3:
+		ihostx_config_root = IHOST3_CONFIG_ROOT;
+		break;
+	}
+
+	return ihostx_config_root;
+}
+
+static void ARMCOE_crm_pllAssertReset(unsigned int cluster_num,
+				      unsigned int reset_type)
+{
+	unsigned long ihostx_config_root;
+	unsigned int pll_rst_ctrl;
+
+	ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+	pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
+
+	// PLL reset
+	if (reset_type & PLL_RESET_TYPE_PLL) {
+		pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
+	}
+	// post-div channel reset
+	if (reset_type & PLL_RESET_TYPE_POST) {
+		pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
+	}
+
+	mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
+}
+
+static void ARMCOE_crm_pllSetMode(unsigned int cluster_num, unsigned int mode)
+{
+	unsigned long ihostx_config_root;
+	unsigned int pll_byp_ctrl;
+
+	ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+	pll_byp_ctrl = mmio_read_32(ihostx_config_root +
+				    A72_CRM_PLL_CHNL_BYPS_EN);
+
+	if (mode == PLL_MODE_VCO) {
+		// use PLL DCO output
+		pll_byp_ctrl &=
+			~BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
+	} else {
+		// use PLL bypass sources
+		pll_byp_ctrl |=
+			BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
+	}
+
+	mmio_write_32(ihostx_config_root + A72_CRM_PLL_CHNL_BYPS_EN,
+		      pll_byp_ctrl);
+}
+
+static void ARMCOE_crm_pllFreqSet(unsigned int cluster_num,
+				  unsigned int ihost_pll_freq_sel,
+				  unsigned int pdiv)
+{
+	unsigned int ndiv_int;
+	unsigned int ndiv_frac_low, ndiv_frac_high;
+	unsigned long ihostx_config_root;
+
+	ndiv_frac_low = 0x0;
+	ndiv_frac_high = 0x0;
+
+	if (ihost_pll_freq_sel == ARM_FREQ_3G) {
+		ndiv_int = 0x78;
+	} else if (ihost_pll_freq_sel == ARM_FREQ_1P5G) {
+		ndiv_int = 0x3c;
+	} else if (ihost_pll_freq_sel == ARM_FREQ_750M) {
+		ndiv_int = 0x1e;
+	} else {
+		return;
+	}
+
+	ndiv_int &= 0x3FF;                // low 10 bits
+	ndiv_frac_low &= 0x3FF;
+	ndiv_frac_high &= 0x3FF;
+
+	ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+
+	mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL1, ndiv_frac_low);
+	mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL2, ndiv_frac_high);
+	mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL3,
+		      ndiv_int |
+		      ((pdiv << A72_CRM_PLL0_CTRL3__PLL0_PDIV_R & 0xF000)));
+
+	mmio_write_32(ihostx_config_root + A72_CRM_PLL0_CTRL4,
+			/* From Section 10 of PLL spec */
+			(3 << A72_CRM_PLL0_CTRL4__PLL0_KP_R) |
+			/* From Section 10 of PLL spec */
+			(2 << A72_CRM_PLL0_CTRL4__PLL0_KI_R) |
+			/* Normal mode (i.e. not fast-locking) */
+			(0 << A72_CRM_PLL0_CTRL4__PLL0_KA_R) |
+			/* 50 MHz */
+			(50 << A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R));
+}
+
+static void ARMCOE_crm_pllDeassertReset(unsigned int cluster_num,
+					unsigned int reset_type)
+{
+	unsigned long ihostx_config_root;
+	unsigned int pll_rst_ctrl;
+
+	ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+	pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
+
+	// PLL reset
+	if (reset_type & PLL_RESET_TYPE_PLL) {
+		pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
+	}
+
+	// post-div channel reset
+	if (reset_type & PLL_RESET_TYPE_POST) {
+		pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
+	}
+
+	mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
+}
+
+static void ARMCOE_crm_pllUpdate(unsigned int cluster_num, unsigned int type)
+{
+	unsigned long ihostx_config_root;
+	unsigned int pll_cmd;
+
+	ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+	pll_cmd = mmio_read_32(ihostx_config_root + A72_CRM_PLL_CMD);
+
+	// VCO update
+	if (type & PLL_VCO) {
+		pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R);
+	}
+	// post-div channel update
+	if (type & PLL_POSTDIV) {
+		pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R);
+	}
+
+	mmio_write_32(ihostx_config_root+A72_CRM_PLL_CMD, pll_cmd);
+}
+
+static void insert_delay(unsigned int delay)
+{
+	volatile unsigned int index;
+
+	for (index = 0; index < delay; index++)
+		;
+}
+
+
+/*
+ * Returns 1 if PLL locked within certain interval
+ */
+static unsigned int ARMCOE_crm_pllIsLocked(unsigned int cluster_num)
+{
+	unsigned long ihostx_config_root;
+	unsigned int lock_status;
+	unsigned int i;
+
+	ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+
+	/* wait a while for pll to lock before returning from this function */
+	for (i = 0; i < 1500; i++) {
+		insert_delay(256);
+		lock_status = mmio_read_32(ihostx_config_root +
+					   A72_CRM_PLL_STATUS);
+		if (lock_status & BIT(A72_CRM_PLL_STATUS__PLL0_LOCK_R))
+			return 1;
+	}
+
+	ERROR("PLL of Cluster #%u failed to lock\n", cluster_num);
+	return 0;
+}
+
+/*
+ * ihost PLL Variable Frequency Configuration
+ *
+ * Frequency Limit {VCO,ARM} (GHz):
+ *	0 - no limit,
+ *	1 - {3.0,1.5},
+ *	2 - {4.0,2.0},
+ *	3 - {5.0,2.5}
+ */
+uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel)
+{
+	NOTICE("cluster: %u, freq_sel:0x%x\n", cluster_num, ihost_pll_freq_sel);
+
+	//bypass PLL
+	ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_BYPASS);
+	//assert reset
+	ARMCOE_crm_pllAssertReset(cluster_num,
+				  PLL_RESET_TYPE_PLL | PLL_RESET_TYPE_POST);
+	//set ndiv_int for different freq
+	ARMCOE_crm_pllFreqSet(cluster_num, ihost_pll_freq_sel, 0x1);
+	//de-assert reset
+	ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_PLL);
+	ARMCOE_crm_pllUpdate(cluster_num, PLL_VCO);
+	//waiting for PLL lock
+	ARMCOE_crm_pllIsLocked(cluster_num);
+	ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_POST);
+	//disable bypass PLL
+	ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_VCO);
+
+	return 0;
+}
+
+uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num)
+{
+	unsigned long ihostx_config_root;
+	uint32_t ndiv_int;
+	uint32_t ihost_pll_freq_sel;
+
+	ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+	ndiv_int = mmio_read_32(ihostx_config_root+A72_CRM_PLL0_CTRL3) & 0x3FF;
+
+	if (ndiv_int == 0x78) {
+		ihost_pll_freq_sel = ARM_FREQ_3G;
+	} else if (ndiv_int == 0x3c) {
+		ihost_pll_freq_sel = ARM_FREQ_1P5G;
+	} else if (ndiv_int == 0x1e) {
+		ihost_pll_freq_sel = ARM_FREQ_750M;
+	} else {
+		/* return unlimit otherwise*/
+		ihost_pll_freq_sel = 0;
+	}
+	return ihost_pll_freq_sel;
+}
diff --git a/plat/brcm/board/stingray/driver/plat_emmc.c b/plat/brcm/board/stingray/driver/plat_emmc.c
new file mode 100644
index 0000000..82085e1
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/plat_emmc.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define ICFG_IPROC_IOPAD_CTRL_4 (IPROC_ROOT + 0x9c0)
+#define ICFG_IPROC_IOPAD_CTRL_5 (IPROC_ROOT + 0x9c4)
+#define ICFG_IPROC_IOPAD_CTRL_6 (IPROC_ROOT + 0x9c8)
+#define ICFG_IPROC_IOPAD_CTRL_7 (IPROC_ROOT + 0x9cc)
+
+#define IOPAD_CTRL4_SDIO0_CD_IND_R 30
+#define IOPAD_CTRL4_SDIO0_CD_SRC_R 31
+#define IOPAD_CTRL4_SDIO0_CD_HYS_R 29
+#define IOPAD_CTRL4_SDIO0_CD_PULL_R 28
+#define IOPAD_CTRL4_SDIO0_CD_DRIVE_R 24
+#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R 23
+#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R 21
+#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R 17
+
+#define IOPAD_CTRL4_SDIO0_DATA0_SRC_R 15
+#define IOPAD_CTRL4_SDIO0_DATA0_HYS_R 13
+#define IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R 9
+#define IOPAD_CTRL4_SDIO0_DATA1_SRC_R 7
+#define IOPAD_CTRL4_SDIO0_DATA1_HYS_R 5
+#define IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R 1
+
+#define IOPAD_CTRL5_SDIO0_DATA2_SRC_R 31
+#define IOPAD_CTRL5_SDIO0_DATA2_HYS_R 29
+#define IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R 25
+#define IOPAD_CTRL5_SDIO0_DATA3_SRC_R 23
+#define IOPAD_CTRL5_SDIO0_DATA3_IND_R 22
+#define IOPAD_CTRL5_SDIO0_DATA3_HYS_R 21
+#define IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R 17
+#define IOPAD_CTRL5_SDIO0_DATA4_SRC_R 15
+#define IOPAD_CTRL5_SDIO0_DATA4_HYS_R 13
+#define IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R 9
+#define IOPAD_CTRL5_SDIO0_DATA5_SRC_R 7
+#define IOPAD_CTRL5_SDIO0_DATA5_HYS_R 5
+#define IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R 1
+
+#define IOPAD_CTRL6_SDIO0_DATA6_SRC_R 31
+#define IOPAD_CTRL6_SDIO0_DATA6_HYS_R 29
+#define IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R 25
+#define IOPAD_CTRL6_SDIO0_DATA7_SRC_R 23
+#define IOPAD_CTRL6_SDIO0_DATA7_HYS_R 21
+#define IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R 17
+
+void emmc_soft_reset(void)
+{
+	uint32_t val = 0;
+
+	val = (BIT(IOPAD_CTRL6_SDIO0_DATA7_SRC_R) |
+	       BIT(IOPAD_CTRL6_SDIO0_DATA7_HYS_R) |
+	       BIT(IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R) |
+	       BIT(IOPAD_CTRL6_SDIO0_DATA6_SRC_R) |
+	       BIT(IOPAD_CTRL6_SDIO0_DATA6_HYS_R) |
+	       BIT(IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R));
+
+	mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val);
+
+	val = (BIT(IOPAD_CTRL5_SDIO0_DATA3_SRC_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA3_HYS_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA4_SRC_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA4_HYS_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA5_SRC_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA5_HYS_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R));
+
+	mmio_write_32(ICFG_IPROC_IOPAD_CTRL_5, val);
+
+	val = (BIT(IOPAD_CTRL4_SDIO0_DATA0_SRC_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_DATA0_HYS_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_DATA1_SRC_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_DATA1_HYS_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA2_SRC_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA2_HYS_R) |
+	       BIT(IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R));
+
+	mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val);
+
+	val = (BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_CD_SRC_R) |
+	       BIT(IOPAD_CTRL4_SDIO0_CD_HYS_R));
+
+	/*
+	 * set pull-down, clear pull-up=0
+	 * bit 12: pull-down  bit 11: pull-up
+	 * Note:  In emulation, this pull-down setting was not
+	 * sufficient.  Board design likely requires pull down on
+	 * this pin for eMMC.
+	 */
+
+	val |= BIT(IOPAD_CTRL4_SDIO0_CD_PULL_R);
+
+	mmio_write_32(ICFG_IPROC_IOPAD_CTRL_4, val);
+}
diff --git a/plat/brcm/board/stingray/driver/swreg.c b/plat/brcm/board/stingray/driver/swreg.c
new file mode 100644
index 0000000..2b7c53b
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/swreg.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <sr_utils.h>
+#include <swreg.h>
+
+#define MIN_VOLT                760000
+#define MAX_VOLT                1060000
+
+#define BSTI_WRITE              0x1
+#define BSTI_READ               0x2
+#define BSTI_COMMAND_TA         0x2
+#define BSTI_COMMAND_DATA       0xFF
+#define BSTI_CONTROL_VAL        0x81
+#define BSTI_CONTROL_BUSY       0x100
+#define BSTI_TOGGLE_BIT         0x2
+#define BSTI_CONFI_DONE_MASK    0xFFFFFFFD
+#define BSTI_REG_DATA_MASK      0xFFFF
+#define BSTI_CMD(sb, op, pa, ra, ta, data) \
+	((((sb) & 0x3) << 30) | (((op) & 0x3) << 28) | \
+	(((pa) & 0x1F) << 23) | (((ra) & 0x1F) << 18) | \
+	(((ta) & 0x3) << 16) | (data))
+
+#define PHY_REG0        0x0
+#define PHY_REG1        0x1
+#define PHY_REG4        0x4
+#define PHY_REG5        0x5
+#define PHY_REG6        0x6
+#define PHY_REG7        0x7
+#define PHY_REGC        0xc
+
+#define IHOST_VDDC_DATA 0x560
+#define DDR_CORE_DATA   0x2560
+#define UPDATE_POS_EDGE(data, set)    ((data) | ((set) << 1))
+
+/*
+ * Formula for SR A2 reworked board:
+ * step = ((vol/(1.4117 * 0.98)) - 500000)/3125
+ * where,
+ *      vol    - input voltage
+ *      500000 - Reference voltage
+ *      3125   - one step value
+ */
+#define A2_VOL_REF         500000
+#define ONE_STEP_VALUE  3125
+#define VOL_DIV(vol)    (((vol*10000ull)/(14117*98ull)) * 100ull)
+#define STEP_VALUE(vol) \
+	((((((VOL_DIV(vol)) - A2_VOL_REF) / ONE_STEP_VALUE) & 0xFF) << 8) | 4)
+
+#define B0_VOL_REF         ((500000/100)*98)
+#define B0_ONE_STEP_VALUE  3125
+/*
+ * Formula for SR B0 chip for IHOST12/03 and VDDC_CORE
+ * step = ((vol/1.56) - (500000 * 0.98))/3125
+ * where,
+ *      vol    - input voltage
+ *      500000 - Reference voltage
+ *      3125   - one step value
+ */
+#define B0_VOL_DIV(vol)    (((vol)*100ull)/156)
+#define B0_STEP_VALUE(vol) \
+	((((((B0_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \
+		& 0xFF) << 8) | 4)
+
+/*
+ * Formula for SR B0 chip for DDR-CORE
+ * step = ((vol/1) - (500000 * 0.98))/3125
+ * where,
+ *      vol    - input voltage
+ *      500000 - Reference voltage
+ *      3125   - one step value
+ */
+#define B0_DDR_VDDC_VOL_DIV(vol)    ((vol)/1)
+#define B0_DDR_VDDC_STEP_VALUE(vol) \
+	((((((B0_DDR_VDDC_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \
+		& 0xFF) << 8) | 4)
+
+#define MAX_SWREG_CNT       8
+#define MAX_ADDR_PER_SWREG  16
+#define MAX_REG_ADDR        0xF
+#define MIN_REG_ADDR        0x0
+
+static const char *sw_reg_name[MAX_SWREG_CNT] = {
+	"DDR_VDDC",
+	"IHOST03",
+	"IHOST12",
+	"IHOST_ARRAY",
+	"DDRIO_SLAVE",
+	"VDDC_CORE",
+	"VDDC1",
+	"DDRIO_MASTER"
+};
+
+/* firmware values for all SWREG for 3.3V input operation */
+static const uint16_t swreg_fm_data_bx[MAX_SWREG_CNT][MAX_ADDR_PER_SWREG] = {
+	/* DDR logic: Power Domains independent of 12v or 3p3v */
+	{0x25E0, 0x2D54, 0x0EC6, 0x01EC, 0x28BB, 0x1144, 0x0200, 0x69C0,
+	 0x0010, 0x0EDF, 0x90D7, 0x8000, 0x820C, 0x0003, 0x0001, 0x0000},
+
+	/* ihost03, 3p3V */
+	{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
+	 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
+
+	/* ihost12 3p3v */
+	{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
+	 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
+
+	/* ihost array */
+	{0x25E0, 0x2D94, 0x0EC6, 0x01EC, 0x2ABB, 0x1144, 0x0340, 0x69C0,
+	 0x0010, 0x0EDF, 0x90D7, 0x8000, 0x860C, 0x0003, 0x0001, 0x0000},
+
+	/* ddr io slave : 3p3v */
+	{0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380,
+	 0x003F, 0x0FFF, 0x10D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000},
+
+	/* core master 3p3v */
+	{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
+	 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
+
+	/* core slave 3p3v */
+	{0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380,
+	 0x003F, 0x0FFF, 0x10D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
+
+	/* ddr io master : 3p3v */
+	{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
+	 0x003F, 0x0FFF, 0x90D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000},
+};
+
+#define FM_DATA swreg_fm_data_bx
+
+static int swreg_poll(void)
+{
+	uint32_t data;
+	int retry = 100;
+
+	do {
+		data = mmio_read_32(BSTI_CONTROL_OFFSET);
+		if ((data & BSTI_CONTROL_BUSY) != BSTI_CONTROL_BUSY)
+			return 0;
+		retry--;
+		udelay(1);
+	} while (retry > 0);
+
+	return -ETIMEDOUT;
+}
+
+static int write_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t data)
+{
+	uint32_t cmd;
+	int ret;
+
+	cmd = BSTI_CMD(0x1, BSTI_WRITE, reg_id, addr, BSTI_COMMAND_TA, data);
+	mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL);
+	mmio_write_32(BSTI_COMMAND_OFFSET, cmd);
+	ret = swreg_poll();
+	if (ret) {
+		ERROR("Failed to write swreg %s addr 0x%x\n",
+			sw_reg_name[reg_id-1], addr);
+		return ret;
+	}
+	return ret;
+}
+
+static int read_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t *data)
+{
+	uint32_t cmd;
+	int ret;
+
+	cmd = BSTI_CMD(0x1, BSTI_READ, reg_id, addr, BSTI_COMMAND_TA, PHY_REG0);
+	mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL);
+	mmio_write_32(BSTI_COMMAND_OFFSET, cmd);
+	ret = swreg_poll();
+	if (ret) {
+		ERROR("Failed to read swreg %s addr 0x%x\n",
+			sw_reg_name[reg_id-1], addr);
+		return ret;
+	}
+
+	*data = mmio_read_32(BSTI_COMMAND_OFFSET);
+	*data &= BSTI_REG_DATA_MASK;
+	return ret;
+}
+
+static int swreg_config_done(enum sw_reg reg_id)
+{
+	uint32_t read_data;
+	int ret;
+
+	ret = read_swreg_config(reg_id, PHY_REG0, &read_data);
+	if (ret)
+		return ret;
+
+	read_data &= BSTI_CONFI_DONE_MASK;
+	read_data |= BSTI_TOGGLE_BIT;
+	ret = write_swreg_config(reg_id, PHY_REG0, read_data);
+	if (ret)
+		return ret;
+
+	ret = read_swreg_config(reg_id, PHY_REG0, &read_data);
+	if (ret)
+		return ret;
+
+	read_data &= BSTI_CONFI_DONE_MASK;
+	ret = write_swreg_config(reg_id, PHY_REG0, read_data);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+#ifdef DUMP_SWREG
+static void dump_swreg_firmware(void)
+{
+	enum sw_reg reg_id;
+	uint32_t data;
+	int addr;
+	int ret;
+
+	for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
+		INFO("SWREG: %s\n", sw_reg_name[reg_id - 1]);
+		for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) {
+			ret = read_swreg_config(reg_id, addr, &data);
+			if (ret)
+				ERROR("Failed to read offset %d\n", addr);
+			INFO("\t0x%x: 0x%04x\n", addr, data);
+		}
+	}
+}
+#endif
+
+int set_swreg(enum sw_reg reg_id, uint32_t micro_volts)
+{
+	uint32_t step, programmed_step;
+	uint32_t data = IHOST_VDDC_DATA;
+	int ret;
+
+	if ((micro_volts > MAX_VOLT) || (micro_volts < MIN_VOLT)) {
+		ERROR("input voltage out-of-range\n");
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	ret = read_swreg_config(reg_id, PHY_REGC, &programmed_step);
+	if (ret)
+		goto failed;
+
+	if (reg_id == DDR_VDDC)
+		step = B0_DDR_VDDC_STEP_VALUE(micro_volts);
+	else
+		step = B0_STEP_VALUE(micro_volts);
+
+	if ((step >> 8) != (programmed_step >> 8)) {
+		ret = write_swreg_config(reg_id, PHY_REGC, step);
+		if (ret)
+			goto failed;
+
+		if (reg_id == DDR_VDDC)
+			data = DDR_CORE_DATA;
+
+		ret = write_swreg_config(reg_id, PHY_REG0,
+					UPDATE_POS_EDGE(data, 1));
+		if (ret)
+			goto failed;
+
+		ret = write_swreg_config(reg_id, PHY_REG0,
+					UPDATE_POS_EDGE(data, 0));
+		if (ret)
+			goto failed;
+	}
+
+	INFO("%s voltage updated to %duV\n", sw_reg_name[reg_id-1],
+		micro_volts);
+	return ret;
+
+failed:
+	/*
+	 * Stop booting if voltages are not set
+	 * correctly. Booting will fail at random point
+	 * if we continue with wrong voltage settings.
+	 */
+	ERROR("Failed to set %s voltage to %duV\n", sw_reg_name[reg_id-1],
+		micro_volts);
+	assert(0);
+
+	return ret;
+}
+
+/* Update SWREG firmware for all power doman for A2 chip */
+int swreg_firmware_update(void)
+{
+	enum sw_reg reg_id;
+	uint32_t data;
+	int addr;
+	int ret;
+
+	/* write firmware values */
+	for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
+		/* write higher location first */
+		for (addr = MAX_REG_ADDR; addr >= MIN_REG_ADDR; addr--) {
+			ret = write_swreg_config(reg_id, addr,
+						 FM_DATA[reg_id - 1][addr]);
+			if (ret)
+				goto exit;
+		}
+	}
+
+	/* trigger SWREG firmware update */
+	for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
+		/*
+		 * Slave regulator doesn't have to be updated,
+		 * Updating Master is enough
+		 */
+		if ((reg_id == DDRIO_SLAVE) || (reg_id == VDDC1))
+			continue;
+
+		ret = swreg_config_done(reg_id);
+		if (ret) {
+			ERROR("Failed to trigger SWREG firmware update for %s\n"
+				, sw_reg_name[reg_id-1]);
+			return ret;
+		}
+	}
+
+	for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
+		/*
+		 * IHOST_ARRAY will be used on some boards like STRATUS and
+		 * there will not be any issue even if it is updated on other
+		 * boards where it is not used.
+		 */
+		if (reg_id == IHOST_ARRAY)
+			continue;
+
+		for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) {
+			ret = read_swreg_config(reg_id, addr, &data);
+			if (ret || (!ret &&
+				(data != FM_DATA[reg_id - 1][addr]))) {
+				ERROR("swreg fm update failed: %s at off %d\n",
+					sw_reg_name[reg_id - 1], addr);
+				ERROR("Read val: 0x%x, expected val: 0x%x\n",
+					data, FM_DATA[reg_id - 1][addr]);
+				return -1;
+			}
+		}
+	}
+
+	INFO("Updated SWREG firmware\n");
+
+#ifdef DUMP_SWREG
+	dump_swreg_firmware();
+#endif
+	return ret;
+
+exit:
+	/*
+	 * Stop booting if swreg firmware update fails.
+	 * Booting will fail at random point if we
+	 * continue with wrong voltage settings.
+	 */
+	ERROR("Failed to update firmware for %s SWREG\n",
+		sw_reg_name[reg_id-1]);
+	assert(0);
+
+	return ret;
+}
diff --git a/plat/brcm/board/stingray/include/bl33_info.h b/plat/brcm/board/stingray/include/bl33_info.h
new file mode 100644
index 0000000..1dac48c
--- /dev/null
+++ b/plat/brcm/board/stingray/include/bl33_info.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL33_INFO_H
+#define BL33_INFO_H
+
+/* Increase version number each time this file is modified */
+#define BL33_INFO_VERSION	4
+
+struct chip_info {
+	unsigned int chip_id;
+	unsigned int rev_id;
+};
+
+struct boot_time_info {
+	unsigned int bl1_start;
+	unsigned int bl1_end;
+	unsigned int bl2_start;
+	unsigned int bl2_end;
+	unsigned int bl31_start;
+	unsigned int bl31_end;
+	unsigned int bl32_start;
+	unsigned int bl32_end;
+	unsigned int bl33_start;
+	unsigned int bl33_prompt;
+	unsigned int bl33_end;
+};
+
+struct bl33_info {
+	unsigned int version;
+	struct chip_info chip;
+	struct boot_time_info boot_time_info;
+};
+
+#endif
diff --git a/plat/brcm/board/stingray/include/board_info.h b/plat/brcm/board/stingray/include/board_info.h
new file mode 100644
index 0000000..8901259
--- /dev/null
+++ b/plat/brcm/board/stingray/include/board_info.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_INFO_H
+#define BOARD_INFO_H
+
+#define IHOST_REG_INTEGRATED 0
+#define IHOST_REG_EXT_PROGRAMMABLE 1
+#define IHOST_REG_EXT_FIXED 2
+
+#if defined(IHOST_REG_TYPE)
+	#if ((IHOST_REG_TYPE != IHOST_REG_INTEGRATED) && \
+		(IHOST_REG_TYPE != IHOST_REG_EXT_PROGRAMMABLE) && \
+		(IHOST_REG_TYPE != IHOST_REG_EXT_FIXED))
+		#error "IHOST_REG_TYPE not valid"
+	#endif
+#else
+	#define IHOST_REG_TYPE IHOST_REG_INTEGRATED
+#endif
+
+#define VDDC_REG_INTEGRATED 0
+#define VDDC_REG_EXT_PROGRAMMABLE 1
+#define VDDC_REG_EXT_FIXED 2
+
+#if defined(VDDC_REG_TYPE)
+	#if ((VDDC_REG_TYPE != VDDC_REG_INTEGRATED) && \
+		(VDDC_REG_TYPE != VDDC_REG_EXT_PROGRAMMABLE) && \
+		(VDDC_REG_TYPE != VDDC_REG_EXT_FIXED))
+		#error "VDDC_REG_TYPE not valid"
+	#endif
+#else
+	#define VDDC_REG_TYPE VDDC_REG_INTEGRATED
+#endif
+
+#endif
diff --git a/plat/brcm/board/stingray/include/crmu_def.h b/plat/brcm/board/stingray/include/crmu_def.h
new file mode 100644
index 0000000..ebc2bb6
--- /dev/null
+++ b/plat/brcm/board/stingray/include/crmu_def.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CRMU_DEF_H
+#define CRMU_DEF_H
+
+#define CRMU_REGS_BASE			0x66410000
+/* 32 kB IDRAM */
+#define CRMU_IDRAM_BASE_ADDR		CRMU_REGS_BASE
+#define CRMU_IDRAM_SIZE			0x8000
+/* 4 kB Scratch RAM */
+#define CRMU_SRAM_BASE			(CRMU_IDRAM_BASE_ADDR + CRMU_IDRAM_SIZE)
+#define CRMU_SRAM_SIZE			0x1000
+
+#define CRMU_RESERVED_SPACE		0x3000
+#define CRMU_CORE_BASE			(CRMU_SRAM_BASE + CRMU_SRAM_SIZE + \
+					 CRMU_RESERVED_SPACE)
+
+#define CRMU_SHARED_SRAM_BASE		CRMU_SRAM_BASE
+#define CRMU_SHARED_SRAM_SIZE		0x200
+#define CRMU_CFG_BASE			(CRMU_SHARED_SRAM_BASE + \
+					 CRMU_SHARED_SRAM_SIZE)
+
+#define CRMU_PWR_GOOD_STATUS		CRMU_CORE_BASE
+#define CRMU_PWR_GOOD_STATUS__BBL_POWER_GOOD 0
+#define CRMU_ISO_CELL_CONTROL		(CRMU_CORE_BASE + 0x4)
+#define CRMU_ISO_CELL_CONTROL__CRMU_ISO_PDBBL 16
+#define CRMU_ISO_CELL_CONTROL__CRMU_ISO_PDBBL_TAMPER 24
+#define CRMU_SPRU_SOURCE_SEL_STAT	(CRMU_CORE_BASE + 0xc)
+#define CRMU_SPRU_SOURCE_SEL_STAT__SPRU_SOURCE_SELECT 0
+#define BSTI_BASE			(CRMU_CORE_BASE + 0x28)
+#define BSTI_CONTROL_OFFSET		BSTI_BASE
+#define BSTI_COMMAND_OFFSET		(BSTI_BASE + 0x4)
+
+#define OCOTP_REGS_BASE			(CRMU_CORE_BASE + 0x400)
+
+#define CRMU_TCI_BASE			(CRMU_CORE_BASE + 0x800)
+#define CRMU_SWREG_STATUS_ADDR		(CRMU_TCI_BASE + 0x0c)
+#define CRMU_CHIP_OTPC_STATUS		(CRMU_TCI_BASE + 0x10)
+#define CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE 19
+#define CRMU_BISR_PDG_MASK		(CRMU_TCI_BASE + 0x4c)
+#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST0 2
+#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST1 3
+#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST2 4
+#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST3 0
+#define CRMU_POWER_POLL			(CRMU_TCI_BASE + 0x60)
+#define CRMU_OTP_STATUS			CRMU_POWER_POLL
+#define CRMU_OTP_STATUS_BIT		1
+#define CRMU_DDR_PHY_AON_CTRL		(CRMU_TCI_BASE + 0x64)
+#define CRMU_DDRPHY2_HW_RESETN_R	BIT(21)
+#define CRMU_DDRPHY2_PWROKIN_PHY_R	BIT(20)
+#define CRMU_DDRPHY2_PWRONIN_PHY_R	BIT(19)
+#define CRMU_DDRPHY2_ISO_PHY_DFI_R	BIT(18)
+#define CRMU_DDRPHY2_ISO_PHY_REGS_R	BIT(17)
+#define CRMU_DDRPHY2_ISO_PHY_PLL_R	BIT(16)
+#define CRMU_DDRPHY1_HW_RESETN_R	BIT(13)
+#define CRMU_DDRPHY1_PWROKIN_PHY_R	BIT(12)
+#define CRMU_DDRPHY1_PWRONIN_PHY_R	BIT(11)
+#define CRMU_DDRPHY1_ISO_PHY_DFI_R	BIT(10)
+#define CRMU_DDRPHY1_ISO_PHY_REGS_R	BIT(9)
+#define CRMU_DDRPHY1_ISO_PHY_PLL_R	BIT(8)
+#define CRMU_DDRPHY0_HW_RESETN_R	BIT(5)
+#define CRMU_DDRPHY0_PWROKIN_PHY_R	BIT(4)
+#define CRMU_DDRPHY0_PWRONIN_PHY_R	BIT(3)
+#define CRMU_DDRPHY0_ISO_PHY_DFI_R	BIT(2)
+#define CRMU_DDRPHY0_ISO_PHY_REGS_R	BIT(1)
+#define CRMU_DDRPHY0_ISO_PHY_PLL_R	BIT(0)
+#define CRMU_EMEM_RESET_N_R		BIT(16)
+#define CRMU_EMEM_PRESET_N_R		BIT(0)
+#define CRMU_SWREG_CTRL_ADDR		(CRMU_TCI_BASE + 0x6c)
+#define CRMU_AON_CTRL1			(CRMU_TCI_BASE + 0x70)
+#define CRMU_AON_CTRL1__LCPLL1_ISO_IN    18
+#define CRMU_AON_CTRL1__LCPLL1_PWRON_LDO 19
+#define CRMU_AON_CTRL1__LCPLL1_PWR_ON    20
+#define CRMU_AON_CTRL1__LCPLL0_ISO_IN    21
+#define CRMU_AON_CTRL1__LCPLL0_PWRON_LDO 22
+#define CRMU_AON_CTRL1__LCPLL0_PWR_ON    23
+#define CRMU_PCIE_LCPLL_PWR_ON_SHIFT     29
+#define CRMU_PCIE_LCPLL_PWR_ON_MASK      BIT(CRMU_PCIE_LCPLL_PWR_ON_SHIFT)
+#define CRMU_PCIE_LCPLL_PWRON_LDO_SHIFT  28
+#define CRMU_PCIE_LCPLL_PWRON_LDO_MASK   BIT(CRMU_PCIE_LCPLL_PWRON_LDO_SHIFT)
+#define CRMU_PCIE_LCPLL_ISO_IN_SHIFT     27
+#define CRMU_PCIE_LCPLL_ISO_IN_MASK      BIT(CRMU_PCIE_LCPLL_ISO_IN_SHIFT)
+#define CRMU_MASTER_AXI_ARUSER_CONFIG	(CRMU_TCI_BASE + 0x74)
+#define CRMU_MASTER_AXI_AWUSER_CONFIG	(CRMU_TCI_BASE + 0x78)
+#define CRMU_DDR_PHY_AON_CTRL_1		(CRMU_TCI_BASE + 0x8c)
+
+#define CDRU_BASE_ADDR			(CRMU_CORE_BASE + 0x1000)
+#define CDRU_MISC_RESET_CONTROL		CDRU_BASE_ADDR
+#define CDRU_MISC_RESET_CONTROL_TS_RESET_N		16
+#define CDRU_MISC_RESET_CONTROL__CDRU_USBSS_RESET_N	14
+#define CDRU_MISC_RESET_CONTROL__CDRU_SATA_RESET_N_R	15
+#define CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R	13
+#define CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R	3
+#define CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R	2
+#define CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R	1
+
+#define CDRU_PROC_EVENT_CLEAR		(CDRU_BASE_ADDR + 0x48)
+#define CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2		0
+#define CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI		3
+#define CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2		5
+#define CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI		8
+#define CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2		10
+#define CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI		13
+#define CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2		15
+#define CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI		18
+
+#define CDRU_CHIP_STRAP_CTRL		(CDRU_BASE_ADDR + 0x50)
+#define CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE 31
+
+#define CDRU_CHIP_IO_PAD_CONTROL	(CDRU_BASE_ADDR + 0x58)
+#define CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PDN_R	8
+#define CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R	0
+
+#define CDRU_CHIP_STRAP_DATA_LSW	(CDRU_BASE_ADDR + 0x5c)
+#define CDRU_CHIP_STRAP_DATA_LSW__BISR_BYPASS_MODE		18
+#define CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK		BIT(8)
+#define CDRU_CHIP_STRAP_DATA_LSW_PAD_USB_MODE		BIT(26)
+
+#define CDRU_CHIP_STRAP_DATA		(CDRU_BASE_ADDR + 0x5c)
+#define CDRU_DDR0_CONTROL_OFFSET	(CDRU_BASE_ADDR + 0xb8)
+#define CDRU_DDR1_CONTROL_OFFSET	(CDRU_BASE_ADDR + 0xbc)
+#define CDRU_DDR2_CONTROL_OFFSET	(CDRU_BASE_ADDR + 0xc0)
+#define CRMU_SW_POR_RESET_CTRL		(CDRU_BASE_ADDR + 0x100)
+
+#define CDRU_GENPLL2_CONTROL1		(CDRU_BASE_ADDR + 0x1b0)
+#define CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK		BIT(11)
+#define CDRU_GENPLL5_CONTROL1		(CDRU_BASE_ADDR + 0x24c)
+#define CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK		BIT(6)
+#define CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK	BIT(7)
+#define CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK	BIT(8)
+
+#define CDRU_NITRO_CONTROL		(CDRU_BASE_ADDR + 0x2c4)
+#define CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R		20
+#define CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R		16
+
+#define CDRU_MISC_CLK_ENABLE_CONTROL	(CDRU_BASE_ADDR + 0x2c8)
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM2_CLK_EN_R	11
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM1_CLK_EN_R	10
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM0_CLK_EN_R	9
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SATA_CLK_EN_R	8
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_USBSS_CLK_EN_R	7
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_MHB_CLK_EN_R		6
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_HSLS_CLK_EN_R	5
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SCR_CLK_EN_R		4
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_FS4_CLK_EN_R		3
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_PCIE_CLK_EN_R	2
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_PM_CLK_EN_R		1
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_NITRO_CLK_EN_R	0
+
+#define CDRU_CCN_REGISTER_CONTROL_1	(CDRU_BASE_ADDR + 0x324)
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM0_BIT 6
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM1_BIT 5
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM2_BIT 4
+
+#define CDRU_CHIP_TOP_SPARE_REG0	(CDRU_BASE_ADDR + 0x378)
+#define CDRU_CHIP_TOP_SPARE_REG1	(CDRU_BASE_ADDR + 0x37c)
+
+#define CENTRAL_TIMER_BASE		(CRMU_CORE_BASE + 0x5000)
+#define CENTRAL_TIMER_CTRL		(CENTRAL_TIMER_BASE + 0x0)
+#define CENTRAL_TIMER_GET_L		(CENTRAL_TIMER_BASE + 0x4)
+#define CENTRAL_TIMER_GET_L0		(CENTRAL_TIMER_BASE + 0x8) /* SCR STM */
+#define CENTRAL_TIMER_GET_L1		(CENTRAL_TIMER_BASE + 0xC) /* FS STM */
+#define CENTRAL_TIMER_GET_L2		(CENTRAL_TIMER_BASE + 0x10) /* iHost0 */
+#define CENTRAL_TIMER_GET_L3		(CENTRAL_TIMER_BASE + 0x14) /* iHost1 */
+#define CENTRAL_TIMER_GET_L4		(CENTRAL_TIMER_BASE + 0x18) /* iHost2 */
+#define CENTRAL_TIMER_GET_L5		(CENTRAL_TIMER_BASE + 0x1C) /* iHost3 */
+#define CENTRAL_TIMER_GET_H		(CENTRAL_TIMER_BASE + 0x28)
+#define CENTRAL_TIMER_SAT_TMR_ENA	(CENTRAL_TIMER_BASE + 0x34)
+#define CENTRAL_TIMER_GET_IHOST_ENA_BASE	(CENTRAL_TIMER_GET_L2)
+
+#define CRMU_WDT_REGS_BASE		(CRMU_CORE_BASE + 0x6000)
+
+#define CRMU_MAIL_BOX0			(CRMU_CORE_BASE + 0x8024)
+#define CRMU_MAIL_BOX1			(CRMU_CORE_BASE + 0x8028)
+#define CRMU_READ_MAIL_BOX0		(CRMU_CORE_BASE + 0x802c)
+#define CRMU_READ_MAIL_BOX1		(CRMU_CORE_BASE + 0x8030)
+#define AP_TO_SCP_MAILBOX1		CRMU_MAIL_BOX1
+#define SCP_TO_AP_MAILBOX1		CRMU_READ_MAIL_BOX1
+#define CRMU_IHOST_POWER_CONFIG		(CRMU_CORE_BASE + 0x8038)
+#define CRMU_RESET_EVENT_LOG		(CRMU_CORE_BASE + 0x8064)
+#define CRMU_SOFT_RESET_CTRL		(CRMU_CORE_BASE + 0x8090)
+#define CRMU_SOFT_RESET_CTRL__SOFT_PWR_UP_RST 0
+#define CRMU_SOFT_RESET_CTRL__SOFT_SYS_RST 1
+#define CRMU_SPARE_REG_0		(CRMU_CORE_BASE + 0x80b8)
+#define CRMU_SPARE_REG_1		(CRMU_CORE_BASE + 0x80bc)
+#define CRMU_SPARE_REG_2		(CRMU_CORE_BASE + 0x80c0)
+#define CRMU_SPARE_REG_3		(CRMU_CORE_BASE + 0x80c4)
+#define CRMU_SPARE_REG_4		(CRMU_CORE_BASE + 0x80c8)
+#define CRMU_SPARE_REG_5		(CRMU_CORE_BASE + 0x80cc)
+#define CRMU_CORE_ADDR_RANGE0_LOW	(CRMU_CORE_BASE + 0x8c30)
+#define CRMU_CORE_ADDR_RANGE1_LOW	(CRMU_CORE_BASE + 0x8c38)
+#define CRMU_CORE_ADDR_RANGE2_LOW	(CRMU_CORE_BASE + 0x8c40)
+#define CRMU_IHOST_SW_PERSISTENT_REG0	(CRMU_CORE_BASE + 0x8c54)
+#define CRMU_IHOST_SW_PERSISTENT_REG1	(CRMU_CORE_BASE + 0x8c58)
+#define CRMU_IHOST_SW_PERSISTENT_REG2	(CRMU_CORE_BASE + 0x8c5c)
+#define CRMU_IHOST_SW_PERSISTENT_REG3	(CRMU_CORE_BASE + 0x8c60)
+#define CRMU_IHOST_SW_PERSISTENT_REG4	(CRMU_CORE_BASE + 0x8c64)
+#define CRMU_IHOST_SW_PERSISTENT_REG5	(CRMU_CORE_BASE + 0x8c68)
+#define CRMU_IHOST_SW_PERSISTENT_REG6	(CRMU_CORE_BASE + 0x8c6c)
+#define CRMU_IHOST_SW_PERSISTENT_REG7	(CRMU_CORE_BASE + 0x8c70)
+#define CRMU_BBL_AUTH_CHECK		(CRMU_CORE_BASE + 0x8c78)
+#define CRMU_SOTP_NEUTRALIZE_ENABLE	(CRMU_CORE_BASE + 0x8c84)
+#define CRMU_IHOST_SW_PERSISTENT_REG8	(CRMU_CORE_BASE + 0x8c88)
+#define CRMU_IHOST_SW_PERSISTENT_REG9	(CRMU_CORE_BASE + 0x8c8c)
+#define CRMU_IHOST_SW_PERSISTENT_REG10	(CRMU_CORE_BASE + 0x8c90)
+#define CRMU_IHOST_SW_PERSISTENT_REG11	(CRMU_CORE_BASE + 0x8c94)
+
+#define CNT_CONTROL_BASE		(CRMU_CORE_BASE + 0x9000)
+#define CNTCR				(CNT_CONTROL_BASE)
+#define CNTCR__EN			BIT(0)
+
+#define SPRU_BBL_WDATA			(CRMU_CORE_BASE + 0xa000)
+#define SPRU_BBL_CMD			(CRMU_CORE_BASE + 0xa004)
+#define SPRU_BBL_CMD__IND_SOFT_RST_N	10
+#define SPRU_BBL_CMD__IND_WR		11
+#define SPRU_BBL_CMD__BBL_ADDR_R	0
+#define SPRU_BBL_CMD__IND_RD		12
+#define SPRU_BBL_CMD__BBL_ADDR_R	0
+#define SPRU_BBL_STATUS			(CRMU_CORE_BASE + 0xa008)
+#define SPRU_BBL_STATUS__ACC_DONE	0
+#define SPRU_BBL_RDATA			(CRMU_CORE_BASE + 0xa00c)
+
+#endif /* CRMU_DEF_H */
diff --git a/plat/brcm/board/stingray/include/ddr_init.h b/plat/brcm/board/stingray/include/ddr_init.h
new file mode 100644
index 0000000..0c135b1
--- /dev/null
+++ b/plat/brcm/board/stingray/include/ddr_init.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DDR_INIT_H
+#define DDR_INIT_H
+
+#include <fru.h>
+
+#pragma weak ddr_initialize
+#pragma weak ddr_secure_region_config
+#pragma weak ddr_info_save
+#pragma weak get_active_ddr_channel
+#pragma weak is_warmboot
+
+void ddr_initialize(struct ddr_info *ddr)
+{
+}
+
+void ddr_secure_region_config(uint64_t start, uint64_t end)
+{
+}
+
+void ddr_info_save(void)
+{
+}
+
+unsigned char get_active_ddr_channel(void)
+{
+	return 0;
+}
+
+static inline unsigned int is_warmboot(void)
+{
+	return 0;
+}
+#endif
diff --git a/plat/brcm/board/stingray/include/fsx.h b/plat/brcm/board/stingray/include/fsx.h
new file mode 100644
index 0000000..c52ff0a
--- /dev/null
+++ b/plat/brcm/board/stingray/include/fsx.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FSX_H
+#define FSX_H
+
+#include <stdbool.h>
+
+typedef enum FSX_TYPE {
+	eFS4_RAID,
+	eFS4_CRYPTO,
+	eFS6_PKI,
+} eFSX_TYPE;
+
+void fsx_init(eFSX_TYPE fsx_type,
+	      unsigned int ring_count,
+	      unsigned int dme_count,
+	      unsigned int ae_count,
+	      unsigned int start_stream_id,
+	      unsigned int msi_dev_id,
+	      uintptr_t idm_io_control_direct,
+	      uintptr_t idm_reset_control,
+	      uintptr_t base,
+	      uintptr_t dme_base);
+
+void fsx_meminit(const char *name,
+		 uintptr_t idm_io_control_direct,
+		 uintptr_t idm_io_status);
+
+void fs4_disable_clocks(bool disable_sram,
+			bool disable_crypto,
+			bool disable_raid);
+
+#endif /* FSX_H */
diff --git a/plat/brcm/board/stingray/include/ihost_pm.h b/plat/brcm/board/stingray/include/ihost_pm.h
new file mode 100644
index 0000000..83493ab
--- /dev/null
+++ b/plat/brcm/board/stingray/include/ihost_pm.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IHOST_PM
+#define IHOST_PM
+
+#include <stdint.h>
+
+#define CLUSTER_POWER_ON	0x1
+#define CLUSTER_POWER_OFF	0x0
+
+void ihost_power_on_cluster(u_register_t mpidr);
+void ihost_power_on_secondary_core(u_register_t mpidr, uint64_t rvbar);
+void ihost_enable_satellite_timer(unsigned int cluster_id);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/iommu.h b/plat/brcm/board/stingray/include/iommu.h
new file mode 100644
index 0000000..e7b2985
--- /dev/null
+++ b/plat/brcm/board/stingray/include/iommu.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IOMMU_H
+#define IOMMU_H
+
+enum iommu_domain {
+	PCIE_PAXC,
+	DOMAIN_CRMU,
+};
+
+void arm_smmu_create_identity_map(enum iommu_domain dom);
+void arm_smmu_reserve_secure_cntxt(void);
+void arm_smmu_enable_secure_client_port(void);
+
+#endif /* IOMMU_H */
diff --git a/plat/brcm/board/stingray/include/ncsi.h b/plat/brcm/board/stingray/include/ncsi.h
new file mode 100644
index 0000000..04dd640
--- /dev/null
+++ b/plat/brcm/board/stingray/include/ncsi.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NCSI_H
+#define NCSI_H
+
+/*
+ * There are 10 registers for NCSI IO drivers.
+ */
+#define NITRO_NCSI_IOPAD_CONTROL_NUM	10
+#define NITRO_NCSI_IOPAD_CONTROL_BASE	0x60e05080
+
+/*
+ * NCSI IO Drive strength
+ *   000 - Drives 2mA
+ *   001 - Drives 4mA
+ *   010 - Drives 6mA
+ *   011 - Drives 8mA
+ *   100 - Drives 10mA
+ *   101 - Drives 12mA
+ *   110 - Drives 14mA
+ *   111 - Drives 16mA
+ */
+#define PAD_SELX_VALUE(selx)	((selx) << 1)
+#define PAD_SELX_MASK		(0x7 << 1)
+
+void brcm_stingray_ncsi_init(void);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/paxb.h b/plat/brcm/board/stingray/include/paxb.h
new file mode 100644
index 0000000..c64c8a6
--- /dev/null
+++ b/plat/brcm/board/stingray/include/paxb.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PAXB_H
+#define PAXB_H
+
+/* total number of PCIe cores */
+#define NUM_OF_SR_PCIE_CORES           8
+#define NUM_OF_NS3Z_PCIE_CORES         1
+
+/*
+ * List of PCIe core and PAXB wrapper memory power registers
+ */
+#define PCIE_CORE_BASE                   0x40000800
+#define PCIE_CORE_SOFT_RST_CFG_BASE      (PCIE_CORE_BASE + 0x40)
+#define PCIE_CORE_SOFT_RST               0x1
+#define PCIE_CORE_ISO_CFG_BASE           (PCIE_CORE_BASE + 0x54)
+#define PCIE_CORE_MEM_ISO                0x2
+#define PCIE_CORE_ISO                    0x1
+
+#define PCIE_CORE_MEM_PWR_BASE           (PCIE_CORE_BASE + 0x58)
+#define PCIE_PAXB_MEM_PWR_BASE           (PCIE_CORE_BASE + 0x5c)
+#define PCIE_CORE_PMI_CFG_BASE           (PCIE_CORE_BASE + 0x64)
+#define PCIE_CORE_RESERVED_CFG           (PCIE_CORE_BASE + 0x6c)
+#define PCIE_CORE_MEM_PWR_STATUS_BASE    (PCIE_CORE_BASE + 0x74)
+#define PCIE_PAXB_MEM_PWR_STATUS_BASE    (PCIE_CORE_BASE + 0x78)
+#define PCIE_CORE_PWR_OFFSET           0x100
+
+#define SR_A0_DEVICE_ID                 0xd713
+#define SR_B0_DEVICE_ID                 0xd714
+/* TODO: Modify device ID once available */
+#define NS3Z_DEVICE_ID                  0xd715
+
+/* FIXME: change link speed to GEN3 when it's ready */
+#define GEN1_LINK_SPEED               1
+#define GEN2_LINK_SPEED               2
+#define GEN3_LINK_SPEED               3
+
+typedef struct {
+	uint32_t type;
+	uint32_t device_id;
+	uint32_t pipemux_idx;
+	uint32_t num_cores;
+	int (*pipemux_init)(void);
+	int (*phy_init)(void);
+	int (*core_needs_enable)(unsigned int core_idx);
+	unsigned int (*get_link_width)(unsigned int core_idx);
+	unsigned int (*get_link_speed)(void);
+} paxb_cfg;
+
+enum paxb_type {
+	PAXB_SR,
+	PAXB_NS3Z,
+};
+
+extern const paxb_cfg *paxb;
+
+#ifdef USE_PAXB
+void paxb_init(void);
+void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where,
+		       uint32_t val);
+unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where);
+int pcie_core_needs_enable(unsigned int core_idx);
+const paxb_cfg *paxb_get_sr_config(void);
+#else
+static inline void paxb_init(void)
+{
+}
+#endif
+
+#endif /* PAXB_H */
diff --git a/plat/brcm/board/stingray/include/paxc.h b/plat/brcm/board/stingray/include/paxc.h
new file mode 100644
index 0000000..ae1af2e
--- /dev/null
+++ b/plat/brcm/board/stingray/include/paxc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PAXC_H
+#define PAXC_H
+
+#ifdef USE_PAXC
+void paxc_init(void);
+void paxc_mhb_ns_init(void);
+#else
+static inline void paxc_init(void)
+{
+}
+
+static inline void paxc_mhb_ns_init(void)
+{
+}
+#endif
+
+#endif /* PAXC_H */
diff --git a/plat/brcm/board/stingray/include/plat_macros.S b/plat/brcm/board/stingray/include/plat_macros.S
new file mode 100644
index 0000000..dccd54a
--- /dev/null
+++ b/plat/brcm/board/stingray/include/plat_macros.S
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+.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 registers whenever an
+ * unhandled exception is taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+	nop
+.endm
+
+/* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_print_gic_regs
+	nop
+	/*TBD-STINGRAY*/
+.endm
+
+/* ------------------------------------------------
+ * The below required platform porting macro prints
+ * out relevant interconnect registers whenever an
+ * unhandled exception is taken in BL3-1.
+  * ------------------------------------------------
+ */
+.macro plat_print_interconnect_regs
+	nop
+	/*TBD-STINGRAY*/
+.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/brcm/board/stingray/include/platform_def.h b/plat/brcm/board/stingray/include/platform_def.h
new file mode 100644
index 0000000..4742124
--- /dev/null
+++ b/plat/brcm/board/stingray/include/platform_def.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <plat/common/common_def.h>
+
+#include <brcm_def.h>
+#include "sr_def.h"
+#include <cmn_plat_def.h>
+
+/*
+ * Most platform porting definitions provided by included headers
+ */
+#define PLAT_BRCM_SCP_TZC_DRAM1_SIZE	ULL(0x0)
+
+/*
+ * Required by standard platform porting definitions
+ */
+#define PLATFORM_CLUSTER0_CORE_COUNT	2
+#define PLATFORM_CLUSTER1_CORE_COUNT	2
+#define PLATFORM_CLUSTER2_CORE_COUNT	2
+#define PLATFORM_CLUSTER3_CORE_COUNT	2
+
+#define BRCM_SYSTEM_COUNT 1
+#define BRCM_CLUSTER_COUNT 4
+
+#define PLATFORM_CORE_COUNT	(PLATFORM_CLUSTER0_CORE_COUNT + \
+					PLATFORM_CLUSTER1_CORE_COUNT+ \
+					PLATFORM_CLUSTER2_CORE_COUNT+ \
+					PLATFORM_CLUSTER3_CORE_COUNT)
+
+#define PLAT_NUM_PWR_DOMAINS	(BRCM_SYSTEM_COUNT + \
+				 BRCM_CLUSTER_COUNT + \
+				 PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL	MPIDR_AFFLVL2
+
+/* TBD-STINGRAY */
+#define CACHE_WRITEBACK_SHIFT       6
+/*
+ * 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_GRANULE         (1 << CACHE_WRITEBACK_SHIFT)
+
+/* TBD-STINGRAY */
+#define PLATFORM_MAX_AFFLVL             MPIDR_AFFLVL1
+
+#define BL1_PLATFORM_STACK_SIZE 0x3300
+#define BL2_PLATFORM_STACK_SIZE 0xc000
+#define BL11_PLATFORM_STACK_SIZE 0x2b00
+#define DEFAULT_PLATFORM_STACK_SIZE 0x400
+#if IMAGE_BL1
+# define PLATFORM_STACK_SIZE BL1_PLATFORM_STACK_SIZE
+#else
+#if IMAGE_BL2
+#ifdef USE_BL1_RW
+# define PLATFORM_STACK_SIZE BL2_PLATFORM_STACK_SIZE
+#else
+# define PLATFORM_STACK_SIZE BL1_PLATFORM_STACK_SIZE
+#endif
+#else
+#if IMAGE_BL11
+# define PLATFORM_STACK_SIZE BL11_PLATFORM_STACK_SIZE
+#else
+# define PLATFORM_STACK_SIZE DEFAULT_PLATFORM_STACK_SIZE
+#endif
+#endif
+#endif
+
+#define PLAT_BRCM_TRUSTED_SRAM_BASE	0x66D00000
+#define PLAT_BRCM_TRUSTED_SRAM_SIZE	0x00040000
+
+#ifdef RUN_BL1_FROM_QSPI /* BL1 XIP from QSPI */
+# define PLAT_BRCM_TRUSTED_ROM_BASE	QSPI_BASE_ADDR
+#elif RUN_BL1_FROM_NAND /* BL1 XIP from NAND */
+# define PLAT_BRCM_TRUSTED_ROM_BASE	NAND_BASE_ADDR
+#else /* BL1 executed in ROM */
+# define PLAT_BRCM_TRUSTED_ROM_BASE	ROM_BASE_ADDR
+#endif
+#define PLAT_BRCM_TRUSTED_ROM_SIZE	0x00040000
+
+/*******************************************************************************
+ * BL1 specific defines.
+ ******************************************************************************/
+#define BL1_RO_BASE		        PLAT_BRCM_TRUSTED_ROM_BASE
+#define BL1_RO_LIMIT			(PLAT_BRCM_TRUSTED_ROM_BASE \
+					+ PLAT_BRCM_TRUSTED_ROM_SIZE)
+
+/*
+ * Put BL1 RW at the beginning of the Trusted SRAM.
+ */
+#define BL1_RW_BASE			(BRCM_BL_RAM_BASE)
+#define BL1_RW_LIMIT			(BL1_RW_BASE + 0x12000)
+
+#define BL11_RW_BASE		BL1_RW_LIMIT
+#define BL11_RW_LIMIT		(PLAT_BRCM_TRUSTED_SRAM_BASE + \
+				PLAT_BRCM_TRUSTED_SRAM_SIZE)
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+#if RUN_BL2_FROM_QSPI /* BL2 XIP from QSPI */
+#define BL2_BASE			QSPI_BASE_ADDR
+#define BL2_LIMIT			(BL2_BASE + 0x40000)
+#define BL2_RW_BASE		BL1_RW_LIMIT
+#define BL2_RW_LIMIT		(PLAT_BRCM_TRUSTED_SRAM_BASE + \
+				PLAT_BRCM_TRUSTED_SRAM_SIZE)
+#elif RUN_BL2_FROM_NAND /* BL2 XIP from NAND */
+#define BL2_BASE			NAND_BASE_ADDR
+#define BL2_LIMIT			(BL2_BASE + 0x40000)
+#define BL2_RW_BASE		BL1_RW_LIMIT
+#define BL2_RW_LIMIT		(PLAT_BRCM_TRUSTED_SRAM_BASE + \
+				PLAT_BRCM_TRUSTED_SRAM_SIZE)
+#else
+#define BL2_BASE			(BL1_RW_LIMIT + PAGE_SIZE)
+#define BL2_LIMIT			(BRCM_BL_RAM_BASE + BRCM_BL_RAM_SIZE)
+#endif
+
+/*
+ * BL1 persistent area in internal SRAM
+ * This area will increase as more features gets into BL1
+ */
+#define BL1_PERSISTENT_DATA_SIZE 0x2000
+
+/* To reduce BL2 runtime footprint, we can re-use some BL1_RW area */
+#define BL1_RW_RECLAIM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE + \
+			     BL1_PERSISTENT_DATA_SIZE)
+
+/*******************************************************************************
+ * BL3-1 specific defines.
+ ******************************************************************************/
+/* Max Size of BL31 (in DRAM) */
+#define PLAT_BRCM_MAX_BL31_SIZE		0x30000
+
+#ifdef USE_DDR
+#define BL31_BASE			BRCM_AP_TZC_DRAM1_BASE
+
+#define BL31_LIMIT			(BRCM_AP_TZC_DRAM1_BASE + \
+					PLAT_BRCM_MAX_BL31_SIZE)
+#else
+/* Put BL3-1 at the end of external on-board SRAM connected as NOR flash */
+#define BL31_BASE			(NOR_BASE_ADDR + NOR_SIZE - \
+					PLAT_BRCM_MAX_BL31_SIZE)
+
+#define BL31_LIMIT			(NOR_BASE_ADDR + NOR_SIZE)
+#endif
+
+#define SECURE_DDR_END_ADDRESS		BL31_LIMIT
+
+#ifdef NEED_SCP_BL2
+#define SCP_BL2_BASE			BL31_BASE
+#define PLAT_MAX_SCP_BL2_SIZE	0x9000
+#define PLAT_SCP_COM_SHARED_MEM_BASE (CRMU_SHARED_SRAM_BASE)
+/* dummy defined */
+#define PLAT_BRCM_MHU_BASE		0x0
+#endif
+
+#define SECONDARY_CPU_SPIN_BASE_ADDR	BRCM_SHARED_RAM_BASE
+
+/* Generic system timer counter frequency */
+#ifndef SYSCNT_FREQ
+#define SYSCNT_FREQ			(125 * 1000 * 1000)
+#endif
+
+/*
+ * Enable the BL32 definitions, only when optee os is selected as secure
+ * payload (BL32).
+ */
+#ifdef SPD_opteed
+/*
+ * Reserved Memory Map : SHMEM & TZDRAM.
+ *
+ * +--------+----------+ 0x8D000000
+ * | SHMEM (NS)         | 16MB
+ * +-------------------+ 0x8E000000
+ * |        | TEE_RAM(S)| 4MB
+ * + TZDRAM +----------+ 0x8E400000
+ * |        | TA_RAM(S) | 12MB
+ * +-------------------+ 0x8F000000
+ * | BL31 Binary (S)    | 192KB
+ * +-------------------+ 0x8F030000
+ */
+
+#define BL32_VA_SIZE		(4 * 1024 * 1024)
+#define BL32_BASE		(0x8E000000)
+#define BL32_LIMIT		(BL32_BASE + BL32_VA_SIZE)
+#define TSP_SEC_MEM_BASE	BL32_BASE
+#define TSP_SEC_MEM_SIZE	BL32_VA_SIZE
+#endif
+
+#ifdef SPD_opteed
+	#define SECURE_DDR_BASE_ADDRESS BL32_BASE
+#else
+	#define SECURE_DDR_BASE_ADDRESS BL31_BASE
+#endif
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+
+#define MAX_XLAT_TABLES		7
+
+#define PLAT_BRCM_MMAP_ENTRIES	10
+
+#define MAX_MMAP_REGIONS		(PLAT_BRCM_MMAP_ENTRIES +	\
+					 BRCM_BL_REGIONS)
+
+#ifdef USE_DDR
+#ifdef BL33_OVERRIDE_LOAD_ADDR
+#define PLAT_BRCM_NS_IMAGE_OFFSET	BL33_OVERRIDE_LOAD_ADDR
+#else
+/*
+ * BL3-3 image starting offset.
+ * Putting start of DRAM as of now.
+ */
+#define PLAT_BRCM_NS_IMAGE_OFFSET	0x80000000
+#endif /* BL33_OVERRIDE_LOAD_ADDR */
+#else
+/*
+ * BL3-3 image starting offset.
+ * Putting start of external on-board SRAM as of now.
+ */
+#define PLAT_BRCM_NS_IMAGE_OFFSET	NOR_BASE_ADDR
+#endif /* USE_DDR */
+/******************************************************************************
+ * Required platform porting definitions common to all BRCM platforms
+ *****************************************************************************/
+
+#define MAX_IO_DEVICES			5
+#define MAX_IO_HANDLES			6
+
+#define PRIMARY_CPU		0
+
+/* GIC Parameter */
+#define PLAT_BRCM_GICD_BASE	GIC500_BASE
+#define PLAT_BRCM_GICR_BASE	(GIC500_BASE + 0x200000)
+
+/* Define secure interrupt as per Group here */
+#define PLAT_BRCM_G1S_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(BRCM_IRQ_SEC_SPI_0, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE)
+
+#define PLAT_BRCM_G0_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \
+			GIC_INTR_CFG_EDGE), \
+
+/*
+ *CCN 502 related constants.
+ */
+#define PLAT_BRCM_CLUSTER_COUNT 4  /* Number of RN-F Masters */
+#define PLAT_BRCM_CLUSTER_TO_CCN_ID_MAP	CLUSTER0_NODE_ID, CLUSTER1_NODE_ID, CLUSTER2_NODE_ID, CLUSTER3_NODE_ID
+#define CCN_SIZE		0x1000000
+#define CLUSTER0_NODE_ID	1
+#define CLUSTER1_NODE_ID	7
+#define CLUSTER2_NODE_ID	9
+#define CLUSTER3_NODE_ID	15
+
+#endif
diff --git a/plat/brcm/board/stingray/include/platform_sotp.h b/plat/brcm/board/stingray/include/platform_sotp.h
new file mode 100644
index 0000000..0389f38
--- /dev/null
+++ b/plat/brcm/board/stingray/include/platform_sotp.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_SOTP_H
+#define PLATFORM_SOTP_H
+
+#define SOTP_DEVICE_SECURE_CFG0_ROW 17
+#define SOTP_DEVICE_SECURE_CFG1_ROW 18
+#define SOTP_DEVICE_SECURE_CFG2_ROW 19
+#define SOTP_DEVICE_SECURE_CFG3_ROW 20
+#define SOTP_BRCM_SOFTWARE_CFG0_ROW 21
+#define SOTP_BRCM_SOFTWARE_CFG1_ROW 22
+#define SOTP_BRCM_SOFTWARE_CFG2_ROW 23
+#define SOTP_BRCM_SOFTWARE_CFG3_ROW 24
+#define SOTP_CUSTOMER_ID_CFG0_ROW 25
+#define SOTP_CUSTOMER_ID_CFG1_ROW 26
+#define SOTP_CUSTOMER_ID_CFG2_ROW 27
+#define SOTP_CUSTOMER_ID_CFG3_ROW 28
+#define SOTP_CUSTOMER_DEV_CFG0_ROW 29
+#define SOTP_CUSTOMER_DEV_CFG1_ROW 30
+#define SOTP_CUSTOMER_DEV_CFG2_ROW 31
+#define SOTP_CUSTOMER_DEV_CFG3_ROW 32
+#define SOTP_DAUTH_ROW 33
+#define SOTP_K_HMAC_ROW 45
+#define SOTP_K_AES_ROW 57
+#define SOTP_NVCOUNTER_ROW 69
+
+#define SOTP_BRCM_CFG_ECC_ERROR_MASK 0x100000
+#define SOTP_DAUTH_ECC_ERROR_MASK 0x800000
+#define SOTP_K_HMAC_ECC_ERROR_MASK 0x1000000
+#define SOTP_K_AES_ECC_ERROR_MASK 0x2000000
+
+#endif
diff --git a/plat/brcm/board/stingray/include/scp_cmd.h b/plat/brcm/board/stingray/include/scp_cmd.h
new file mode 100644
index 0000000..806ef56
--- /dev/null
+++ b/plat/brcm/board/stingray/include/scp_cmd.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCP_CMD_H
+#define SCP_SMD_H
+
+#include <stdint.h>
+
+typedef struct {
+	int cmd;
+	int completed;
+	int ret;
+} crmu_response_t;
+
+
+#define SCP_CMD_MASK 0xffff
+#define SCP_CMD_DEFAULT_TIMEOUT_US 1000
+#define SCP_CMD_SCP_BOOT_TIMEOUT_US 5000
+
+int scp_send_cmd(uint32_t cmd, uint32_t param, uint32_t timeout);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/scp_utils.h b/plat/brcm/board/stingray/include/scp_utils.h
new file mode 100644
index 0000000..c39b18c
--- /dev/null
+++ b/plat/brcm/board/stingray/include/scp_utils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCP_UTILS_H
+#define SCP_UTILS_H
+
+#include <common/bl_common.h>
+#include <lib/mmio.h>
+
+#include <m0_cfg.h>
+
+int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info);
+
+bool is_crmu_alive(void);
+bool bcm_scp_issue_sys_reset(void);
+
+#define SCP_READ_CFG(cfg) mmio_read_32(CRMU_CFG_BASE + \
+		offsetof(M0CFG, cfg))
+#define SCP_WRITE_CFG(cfg, value) mmio_write_32(CRMU_CFG_BASE + \
+		offsetof(M0CFG, cfg), value)
+
+#define SCP_READ_CFG16(cfg) mmio_read_16(CRMU_CFG_BASE + \
+		offsetof(M0CFG, cfg))
+#define SCP_WRITE_CFG16(cfg, value) mmio_write_16(CRMU_CFG_BASE + \
+		offsetof(M0CFG, cfg), value)
+
+#define SCP_READ_CFG8(cfg) mmio_read_8(CRMU_CFG_BASE + \
+		offsetof(M0CFG, cfg))
+#define SCP_WRITE_CFG8(cfg, value) mmio_write_8(CRMU_CFG_BASE + \
+		offsetof(M0CFG, cfg), value)
+#endif
diff --git a/plat/brcm/board/stingray/include/sdio.h b/plat/brcm/board/stingray/include/sdio.h
new file mode 100644
index 0000000..e08904e
--- /dev/null
+++ b/plat/brcm/board/stingray/include/sdio.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SDIO_H
+#define SDIO_H
+
+#include <stdbool.h>
+
+#define SR_IPROC_SDIO0_CFG_BASE      0x689006e4
+#define SR_IPROC_SDIO0_SID_BASE      0x68900b00
+#define SR_IPROC_SDIO0_PAD_BASE      0x68a4017c
+#define SR_IPROC_SDIO0_IOCTRL_BASE   0x68e02408
+
+#define SR_IPROC_SDIO1_CFG_BASE      0x68900734
+#define SR_IPROC_SDIO1_SID_BASE      0x68900b08
+#define SR_IPROC_SDIO1_PAD_BASE      0x68a401b4
+#define SR_IPROC_SDIO1_IOCTRL_BASE   0x68e03408
+
+#define NS3Z_IPROC_SDIO0_CFG_BASE    0x68a20540
+#define NS3Z_IPROC_SDIO0_SID_BASE    0x68900b00
+#define NS3Z_IPROC_SDIO0_TP_OUT_SEL  0x68a20308
+#define NS3Z_IPROC_SDIO0_PAD_BASE    0x68a20500
+#define NS3Z_IPROC_SDIO0_IOCTRL_BASE 0x68e02408
+
+#define PHY_BYPASS      BIT(14)
+#define LEGACY_EN       BIT(31)
+#define PHY_DISABLE     (LEGACY_EN | PHY_BYPASS)
+
+#define NS3Z_IPROC_SDIO1_CFG_BASE    0x68a30540
+#define NS3Z_IPROC_SDIO1_SID_BASE    0x68900b08
+#define NS3Z_IPROC_SDIO1_PAD_BASE    0x68a30500
+#define NS3Z_IPROC_SDIO1_IOCTRL_BASE 0x68e03408
+
+#define ICFG_SDIO_CAP0          0x10
+#define ICFG_SDIO_CAP1          0x14
+#define ICFG_SDIO_STRAPSTATUS_0 0x0
+#define ICFG_SDIO_STRAPSTATUS_1 0x4
+#define ICFG_SDIO_STRAPSTATUS_2 0x8
+#define ICFG_SDIO_STRAPSTATUS_3 0xc
+#define ICFG_SDIO_STRAPSTATUS_4 0x18
+
+#define ICFG_SDIO_SID_ARADDR    0x0
+#define ICFG_SDIO_SID_AWADDR    0x4
+
+#define ICFG_SDIOx_CAP0__SLOT_TYPE_MASK         0x3
+#define ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT        27
+#define ICFG_SDIOx_CAP0__INT_MODE_SHIFT         26
+#define ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT    25
+#define ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT     24
+#define ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT     23
+#define ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT     22
+#define ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT   21
+#define ICFG_SDIOx_CAP0__SDMA_SHIFT             20
+#define ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT       19
+#define ICFG_SDIOx_CAP0__ADMA2_SHIFT            18
+#define ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT   17
+#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_MASK     0x3
+#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT    15
+#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_MASK     0xff
+#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT    7
+#define ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT     6
+#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_MASK  0x3f
+#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT 0
+
+#define ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT   22
+#define ICFG_SDIOx_CAP1__SPI_MODE_SHIFT         21
+#define ICFG_SDIOx_CAP1__CLK_MULT_MASK          0xff
+#define ICFG_SDIOx_CAP1__CLK_MULT_SHIFT         13
+#define ICFG_SDIOx_CAP1__RETUNING_MODE_MASK     0x3
+#define ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT    11
+#define ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT       10
+#define ICFG_SDIOx_CAP1__TIME_RETUNE_MASK       0xf
+#define ICFG_SDIOx_CAP1__TIME_RETUNE_SHIFT      6
+#define ICFG_SDIOx_CAP1__DRIVER_D_SHIFT         5
+#define ICFG_SDIOx_CAP1__DRIVER_C_SHIFT         4
+#define ICFG_SDIOx_CAP1__DRIVER_A_SHIFT         3
+#define ICFG_SDIOx_CAP1__DDR50_SHIFT            2
+#define ICFG_SDIOx_CAP1__SDR104_SHIFT           1
+#define ICFG_SDIOx_CAP1__SDR50_SHIFT            0
+
+#ifdef USE_DDR
+#define SDIO_DMA  1
+#else
+#define SDIO_DMA  0
+#endif
+
+#define SDIO0_CAP0_CFG  \
+	(0x1 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \
+	| (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \
+	| (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \
+	| (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \
+	| (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \
+	| (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \
+	| (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \
+	| (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT)
+
+#define SDIO0_CAP1_CFG  \
+	(0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\
+	| (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT)
+
+#define SDIO1_CAP0_CFG  \
+	(0x0 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \
+	| (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \
+	| (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \
+	| (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \
+	| (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \
+	| (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \
+	| (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \
+	| (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT)
+
+#define SDIO1_CAP1_CFG  \
+	(0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\
+	| (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT)
+
+#define PAD_SDIO_CLK      0x4
+#define PAD_SDIO_DATA0    0x8
+#define PAD_SDIO_DATA1    0xc
+#define PAD_SDIO_DATA2    0x10
+#define PAD_SDIO_DATA3    0x14
+#define PAD_SDIO_DATA4    0x18
+#define PAD_SDIO_DATA5    0x1c
+#define PAD_SDIO_DATA6    0x20
+#define PAD_SDIO_DATA7    0x24
+#define PAD_SDIO_CMD      0x28
+
+/* 12mA Drive strength*/
+#define PAD_SDIO_SELX     (0x5 << 1)
+#define PAD_SDIO_SRC      (1 << 0)
+#define PAD_SDIO_MASK     (0xF << 0)
+#define PAD_SDIO_VALUE    (PAD_SDIO_SELX | PAD_SDIO_SRC)
+
+/*
+ * SDIO_PRESETVAL0
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field		Bit(s)		Description
+ * ============================================================
+ * SDR25_PRESET		25:13		Preset Value for SDR25
+ * SDR50_PRESET		12:0		Preset Value for SDR50
+ */
+#define SDIO_PRESETVAL0		0x01005001
+
+/*
+ * SDIO_PRESETVAL1
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field		Bit(s)		Description
+ * ============================================================
+ * SDR104_PRESET		25:13		Preset Value for SDR104
+ * SDR12_PRESET		12:0		Preset Value for SDR12
+ */
+#define SDIO_PRESETVAL1		0x03000004
+
+/*
+ * SDIO_PRESETVAL2
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field		Bit(s)		Description
+ * ============================================================
+ * HIGH_SPEED_PRESET	25:13		Preset Value for High Speed
+ * INIT_PRESET		12:0		Preset Value for Initialization
+ */
+#define SDIO_PRESETVAL2		0x010040FA
+
+/*
+ * SDIO_PRESETVAL3
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field		Bit(s)		Description
+ * ============================================================
+ * DDR50_PRESET		25:13		Preset Value for DDR50
+ * DEFAULT_PRESET	12:0		Preset Value for Default Speed
+ */
+#define SDIO_PRESETVAL3		0x01004004
+
+/*
+ * SDIO_PRESETVAL4
+ *
+ * Field			Bit(s)		Description
+ * ============================================================
+ * FORCE_USE_IP_TUNE_CLK	30		Force use IP clock
+ * TUNING_COUNT			29:24		Tuning count
+ * OVERRIDE_1P8V		23:16
+ * OVERRIDE_3P3V		15:8
+ * OVERRIDE_3P0V		7:0
+ */
+#define SDIO_PRESETVAL4		0x20010101
+
+#define SDIO_SID_SHIFT		5
+
+typedef struct {
+	uintptr_t cfg_base;
+	uintptr_t sid_base;
+	uintptr_t io_ctrl_base;
+	uintptr_t pad_base;
+} SDIO_CFG;
+
+void brcm_stingray_sdio_init(void);
+
+#endif /* SDIO_H */
diff --git a/plat/brcm/board/stingray/include/sr_def.h b/plat/brcm/board/stingray/include/sr_def.h
new file mode 100644
index 0000000..ac3ee78
--- /dev/null
+++ b/plat/brcm/board/stingray/include/sr_def.h
@@ -0,0 +1,614 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SR_DEF_H
+#define SR_DEF_H
+
+#ifndef __ASSEMBLER__
+#include <lib/mmio.h>
+#endif
+
+#include <common/interrupt_props.h>
+#include <drivers/arm/gic_common.h>
+
+#include <crmu_def.h>
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define BRCM_BL31_PLAT_PARAM_VAL	ULL(0x0f1e2d3c4b5a6978)
+
+#define MHB_BASE_ADDR		0x60000000
+#define PLAT_BRCM_CCN_BASE	0x61000000
+#define CORESIGHT_BASE_ADDR	0x62000000
+#define SMMU_BASE		0x64000000
+
+/* memory map entries*/
+/* Grouping block device for bigger MMU region */
+/* covers MHB, CNN, coresight, GIC, MMU, APB, CRMU */
+#define PERIPH0_BASE	MHB_BASE_ADDR
+#define PERIPH0_SIZE	0x06d00000
+
+#define PERIPH1_BASE	0x66d80000
+#define PERIPH1_SIZE	0x00f80000
+
+#define HSLS_BASE_ADDR	0x68900000
+#define HSLS_SIZE	0x04500000
+
+#define GIC500_BASE	0x63c00000
+#define GIC500_SIZE	0x400000
+
+/*******************************************************************************
+ * CCN related constants
+ ******************************************************************************/
+#define OLY_MN_REGISTERS_NODE0_SECURE_ACCESS	(PLAT_BRCM_CCN_BASE + 0x0)
+
+#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL	(PLAT_BRCM_CCN_BASE + 0x880500)
+
+/* Used for acceleration of coherent ordered writes */
+#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WUO  BIT(4)
+/* Wait for completion of requests at RN-I */
+#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WFC  BIT(3)
+
+/*
+ * Forces all reads from the RN-I to be sent with the request order bit set
+ * and this ensures ordered allocation of read data buffers in the RN-I
+ */
+#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_RQO  BIT(5)
+
+#define OLY_RNI3PDVM_REGISTERS_NODE14_AUX_CTL	(PLAT_BRCM_CCN_BASE + 0x8e0500)
+
+/* Wait for completion of requests at RN-I */
+#define OLY_RNI3PDVM_REGISTERS_NODE14_AUX_CTL_WFC BIT(3)
+
+#define OLY_HNI_REGISTERS_NODE0_POS_CONTROL	  (PLAT_BRCM_CCN_BASE + 0x80000)
+#define POS_CONTROL_HNI_POS_EN			  BIT(0)
+
+#define OLY_HNI_REGISTERS_NODE0_PCIERC_RNI_NODEID_LIST \
+						  (PLAT_BRCM_CCN_BASE + 0x80008)
+/* PAXB and PAXC connected to 8th Node */
+#define SR_RNI_PCIE_CONNECTED			  BIT(8)
+/* PAXB connected to 6th Node */
+#define SRP_RNI_PCIE_CONNECTED			  BIT(6)
+
+#define OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL	  (PLAT_BRCM_CCN_BASE + 0x80500)
+#define SA_AUX_CTL_POS_EARLY_WR_COMP_EN		  BIT(5)
+#define SA_AUX_CTL_SER_DEVNE_WR			  BIT(9)
+
+/*******************************************************************************
+ * Coresight related constants
+ ******************************************************************************/
+#define CORESIGHT_BASE_ADDR	0x62000000
+
+#define IHOST0_BASE			0x66000000
+#define IHOST_ADDR_SPACE		0x2000
+
+/*******************************************************************************
+ * SCR related constants
+ ******************************************************************************/
+#define SCR_BASE			0x6600a000
+#define SCR_ARCACHE_OFFSET		4
+#define SCR_ARCACHE_MASK		(0x3 << SCR_ARCACHE_OFFSET)
+#define SCR_AWCACHE_OFFSET		6
+#define SCR_AWCACHE_MASK		(0x3 << SCR_AWCACHE_OFFSET)
+#define SCR_AXCACHE_CONFIG_MASK		(SCR_ARCACHE_MASK | SCR_AWCACHE_MASK)
+#define SCR_TBUX_AXCACHE_CONFIG		((0x1 << SCR_AWCACHE_OFFSET) | \
+					 (0x1 << SCR_ARCACHE_OFFSET))
+
+#define SCR_REGS_SCR_SOFT_RESET		(SCR_BASE + 0x1c)
+#define SCR_REGS_GIC_SOFT_RESET		BIT(0)
+
+#define SCR_GPV_BASE			0x66100000
+#define SCR_NOC_SECURITY0		(SCR_GPV_BASE + 0x08)
+#define SCR_NOC_DDR_REGISTER_ACCESS	(SCR_GPV_BASE + 0x30)
+
+/*******************************************************************************
+ * MEMC and DDR related constants
+ ******************************************************************************/
+#define DDR0_CONTROL_ROOT	0x66200000
+#define EMEM_SS_CFG_0_ROOT	0x66202000
+#define EMEM_SYS_IF_0_ROOT	0x66204000
+#define DDR_PHY0_ROOT		0x66240000
+
+#define DDR1_CONTROL_ROOT	0x66280000
+#define EMEM_SS_CFG_1_ROOT	0x66282000
+#define EMEM_SYS_IF_1_ROOT	0x66284000
+#define DDR_PHY1_ROOT		0x662c0000
+
+#define DDR2_CONTROL_ROOT	0x66300000
+#define EMEM_SS_CFG_2_ROOT	0x66302000
+#define EMEM_SYS_IF_2_ROOT	0x66304000
+#define DDR_PHY2_ROOT		0x66340000
+
+/*******************************************************************************
+ * TZC400 related constants
+ ******************************************************************************/
+#define TZC_400_BASE		0x66d84000
+
+/*******************************************************************************
+ * FS4 related constants
+ ******************************************************************************/
+#define FS4_SRAM_IDM_IO_CONTROL_DIRECT	 0x66d8a408
+
+#define FS4_CRYPTO_IDM_IO_CONTROL_DIRECT 0x66d8e408
+#define FS4_CRYPTO_IDM_RESET_CONTROL	 0x66d8e800
+#define FS4_CRYPTO_BASE			 0x67000000
+#define FS4_CRYPTO_DME_BASE		 (FS4_CRYPTO_BASE + 0x280000)
+
+#define FS4_RAID_IDM_IO_CONTROL_DIRECT	 0x66d8f408
+#define FS4_RAID_IDM_IO_STATUS		 0x66d8f500
+#define FS4_RAID_IDM_RESET_CONTROL	 0x66d8f800
+#define FS4_RAID_BASE			 0x67400000
+#define FS4_RAID_DME_BASE		 (FS4_RAID_BASE + 0x280000)
+
+#define FS4_CRYPTO_GPV_BASE		 0x67300000
+#define FS4_RAID_GPV_BASE		 0x67700000
+
+#define FS6_PKI_BASE			0x67400000
+#define FS6_PKI_DME_BASE		0x66D90000
+
+#define TZC400_FS_SRAM_ROOT		 0x66d84000
+#define GATE_KEEPER_OFFSET		 0x8
+#define REGION_ATTRIBUTES_0_OFFSET	 0x110
+#define REGION_ID_ACCESS_0_OFFSET	 0x114
+
+#define NIC400_FS_NOC_ROOT		 0x66e00000
+#define NIC400_FS_NOC_SECURITY2_OFFSET	 0x10
+#define NIC400_FS_NOC_SECURITY4_OFFSET	 0x18
+#define NIC400_FS_NOC_SECURITY7_OFFSET	 0x24
+
+/*******************************************************************************
+ * SATA PHY related constants
+ ******************************************************************************/
+#define SATA_BASE	0x67d00000
+
+/*******************************************************************************
+ * USB related constants
+ ******************************************************************************/
+#define USB_BASE	0x68500000
+#define USB_SIZE	0x00400000
+#define XHC_BASE	(USB_BASE + 0x11000)
+#define MAX_USB_PORTS	3
+
+/*******************************************************************************
+ * HSLS related constants
+ ******************************************************************************/
+#define IPROC_ROOT		0x68900000
+#define HSLS_ICFG_REGS_BASE	IPROC_ROOT
+#define HSLS_IDM_REGS_BASE	0x68e00000
+#define HSLS_MODE_SEL_CONTROL	0x68a40000
+#define HSLS_TZPC_BASE		0x68b40000
+#define HSLS_GPV_BASE		0x6cd00000
+
+/*******************************************************************************
+ * Chip ID related constants
+ ******************************************************************************/
+#define ICFG_CHIP_ID		HSLS_ICFG_REGS_BASE
+#define CHIP_ID_SR		0xd730
+#define CHIP_ID_NS3Z		0xe56d
+#define CHIP_ID_MASK		0xf000
+#define ICFG_CHIP_REVISION_ID	(HSLS_ICFG_REGS_BASE + 0x4)
+#define PLAT_CHIP_ID_GET	(mmio_read_32(ICFG_CHIP_ID))
+#define PLAT_CHIP_REV_GET	(mmio_read_32(ICFG_CHIP_REVISION_ID))
+
+/*******************************************************************************
+ * Timers related constants
+ ******************************************************************************/
+/* ChipcommonG_tim0_TIM_TIMER1Load 0x68930000 */
+#define SP804_TIMER0_BASE	0x68930000
+#define SP804_TIMER1_BASE	0x68940000
+#define SP804_TIMER0_TIMER_VAL_REG_OFFSET 0x4
+#define SP804_TIMER0_CLKMULT	2
+#define SP804_TIMER0_CLKDIV	25
+
+/*******************************************************************************
+ * GPIO related constants
+ ******************************************************************************/
+#define IPROC_GPIO_NS_BASE	0x689d0000
+#define IPROC_GPIO_S_BASE	0x68b00000
+#define IPROC_GPIO_NR		151
+#define GPIO_S_CNTRL_REG	0x68b60000
+
+/*******************************************************************************
+ * I2C SMBUS related constants
+ ******************************************************************************/
+#define SMBUS0_REGS_BASE	0x689b0000
+#define SMBUS1_REGS_BASE	0x689e0000
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define ChipcommonG_UART0_UART_RBR_THR_DLL	0x68a00000
+#define ChipcommonG_UART1_UART_RBR_THR_DLL	0x68a10000
+#define ChipcommonG_UART2_UART_RBR_THR_DLL	0x68a20000
+#define ChipcommonG_UART3_UART_RBR_THR_DLL	0x68a30000
+
+#define UART0_BASE_ADDR		ChipcommonG_UART0_UART_RBR_THR_DLL
+#define UART1_BASE_ADDR		ChipcommonG_UART1_UART_RBR_THR_DLL
+#define UART2_BASE_ADDR		ChipcommonG_UART2_UART_RBR_THR_DLL
+#define UART3_BASE_ADDR		ChipcommonG_UART3_UART_RBR_THR_DLL
+
+#define UART_SPR_OFFSET		0x1c    /* Scratch Pad Register */
+
+#define LOG_LEVEL_REGISTER	CRMU_SPARE_REG_3
+#define GET_LOG_LEVEL()		(mmio_read_32(LOG_LEVEL_REGISTER))
+#define SET_LOG_LEVEL(x)	(mmio_write_32(LOG_LEVEL_REGISTER, x))
+
+#define IO_RETRY_REGISTER	CRMU_SPARE_REG_4
+
+#define DWC_UART_REFCLK		(25 * 1000 * 1000)
+#define DWC_UART_REFCLK_DIV	16
+/* Baud rate in emulation will vary based on setting of 25MHz SCLK */
+#define DWC_UART_BAUDRATE	115200
+
+#define BRCM_CRASH_CONSOLE_BASE		UART1_BASE_ADDR
+#define BRCM_CRASH_CONSOLE_REFCLK	DWC_UART_REFCLK
+#define BRCM_CRASH_CONSOLE_BAUDRATE	DWC_UART_BAUDRATE
+
+#ifdef BOARD_CONSOLE_UART
+#define PLAT_BRCM_BOOT_UART_BASE	BOARD_CONSOLE_UART
+#else
+#define PLAT_BRCM_BOOT_UART_BASE	UART1_BASE_ADDR
+#endif
+#define CONSOLE_UART_ID	((PLAT_BRCM_BOOT_UART_BASE >> 16) & 0x3)
+
+#define PLAT_BRCM_BOOT_UART_CLK_IN_HZ	DWC_UART_REFCLK
+#define BRCM_CONSOLE_BAUDRATE		DWC_UART_BAUDRATE
+
+#define PLAT_BRCM_BL31_RUN_UART_BASE	 PLAT_BRCM_BOOT_UART_BASE
+#define PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ PLAT_BRCM_BOOT_UART_CLK_IN_HZ
+
+/*******************************************************************************
+ * IOMUX related constants
+ ******************************************************************************/
+#define HSLS_IOPAD_BASE			HSLS_MODE_SEL_CONTROL
+#define MODE_SEL_CONTROL_FSEL_MASK	0x7
+#define MODE_SEL_CONTROL_FSEL_MODE0	0x0
+#define MODE_SEL_CONTROL_FSEL_MODE1	0x1
+#define MODE_SEL_CONTROL_FSEL_MODE2	0x2
+#define MODE_SEL_CONTROL_FSEL_MODE3	0x3
+#define MODE_SEL_CONTROL_FSEL_DEBUG	0x4
+#define IPROC_IOPAD_MODE_BASE		(HSLS_MODE_SEL_CONTROL + 0x29c)
+#define UART0_SIN_MODE_SEL_CONTROL	(HSLS_MODE_SEL_CONTROL + 0x4a8)
+#define UART0_SOUT_MODE_SEL_CONTROL	(HSLS_MODE_SEL_CONTROL + 0x4ac)
+#define UART1_SIN_MODE_SEL_CONTROL	(HSLS_MODE_SEL_CONTROL + 0x3b8)
+#define UART1_SOUT_MODE_SEL_CONTROL	(HSLS_MODE_SEL_CONTROL + 0x3bc)
+#define UARTx_SIN_MODE_SEL_CONTROL_FSEL		0
+#define UARTx_SOUT_MODE_SEL_CONTROL_FSEL	0
+
+/*******************************************************************************
+ * PKA constants
+ ******************************************************************************/
+#define ICFG_PKA_MEM_PWR_CTRL			(HSLS_ICFG_REGS_BASE + 0xac0)
+#define ICFG_PKA_MEM_PWR_CTRL__POWERONIN	BIT(0)
+#define ICFG_PKA_MEM_PWR_CTRL__POWEROKIN	BIT(1)
+#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONIN	BIT(2)
+#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKIN	BIT(3)
+#define ICFG_PKA_MEM_PWR_CTRL__POWERONOUT	BIT(4)
+#define ICFG_PKA_MEM_PWR_CTRL__POWEROKOUT	BIT(5)
+#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONOUT	BIT(6)
+#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKOUT	BIT(7)
+#define ICFG_PKA_MEM_PWR_CTRL__ISO		BIT(8)
+
+/*******************************************************************************
+ * Trusted Watchdog constants
+ ******************************************************************************/
+#define ARM_SP805_TWDG_BASE		0x68b30000
+#define ARM_SP805_TWDG_CLK_HZ		((25 * 1000 * 1000) / 2)
+/*
+ * The TBBR document specifies a watchdog timeout of 256 seconds. SP805
+ * asserts reset after two consecutive countdowns (2 x 128 = 256 sec)
+ */
+#define ARM_TWDG_TIMEOUT_SEC		128
+#define ARM_TWDG_LOAD_VAL		(ARM_SP805_TWDG_CLK_HZ * \
+					 ARM_TWDG_TIMEOUT_SEC)
+
+/*******************************************************************************
+ * SOTP related constants
+ ******************************************************************************/
+#define SOTP_REGS_OTP_BASE		0x68b50000
+#define SOTP_CHIP_CTRL			(SOTP_REGS_OTP_BASE + 0x4c)
+#define SOTP_CLEAR_SYSCTRL_ALL_MASTER_NS  0
+
+/*******************************************************************************
+ * DMAC/PL330 related constants
+ ******************************************************************************/
+#define DMAC_M0_IDM_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0x408)
+#define BOOT_MANAGER_NS			BIT(25)
+#define DMAC_M0_IDM_RESET_CONTROL	(HSLS_IDM_REGS_BASE + 0x800)
+#define ICFG_DMAC_CONFIG_0		(HSLS_ICFG_REGS_BASE + 0x190)
+#define ICFG_DMAC_CONFIG_1		(HSLS_ICFG_REGS_BASE + 0x194)
+#define ICFG_DMAC_CONFIG_2		(HSLS_ICFG_REGS_BASE + 0x198)
+#define BOOT_PERIPHERAL_NS		0xffffffff
+#define ICFG_DMAC_CONFIG_3		(HSLS_ICFG_REGS_BASE + 0x19c)
+#define BOOT_IRQ_NS			0x0000ffff
+#define ICFG_DMAC_SID_ARADDR_CONTROL	(HSLS_ICFG_REGS_BASE + 0xaf0)
+#define ICFG_DMAC_SID_AWADDR_CONTROL	(HSLS_ICFG_REGS_BASE + 0xaf4)
+#define ICFG_DMAC_MEM_PWR_CTRL__POWERONIN	BIT(0)
+#define ICFG_DMAC_MEM_PWR_CTRL__POWEROKIN	BIT(1)
+#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONIN	BIT(2)
+#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKIN	BIT(3)
+#define ICFG_DMAC_MEM_PWR_CTRL__POWERONOUT	BIT(4)
+#define ICFG_DMAC_MEM_PWR_CTRL__POWEROKOUT	BIT(5)
+#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONOUT	BIT(6)
+#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKOUT	BIT(7)
+#define ICFG_DMAC_MEM_PWR_CTRL__ISO		BIT(8)
+#define ICFG_DMAC_MEM_PWR_CTRL		(HSLS_ICFG_REGS_BASE + 0xadc)
+
+/*******************************************************************************
+ * PNOR related constants
+ ******************************************************************************/
+#define PNOR_ICFG_BASE			(HSLS_ICFG_REGS_BASE + 0x780)
+#define PNOR_ICFG_CS_0			PNOR_ICFG_BASE
+#define PNOR_ICFG_CS_1			(PNOR_ICFG_BASE + 0x4)
+#define PNOR_ICFG_CS_2			(PNOR_ICFG_BASE + 0x8)
+#define PNOR_ICFG_CS_x_MASK0_MASK	0xff
+#define PNOR_ICFG_CS_x_MASK0_SHIFT	8
+#define PNOR_ICFG_CS_x_MATCH0_MASK	0xff
+#define PNOR_ICFG_CS_x_MATCH0_SHIFT	0
+
+#define PNOR_IDM_BASE			(HSLS_IDM_REGS_BASE + 0xb000)
+#define PNOR_IDM_IO_CONTROL_DIRECT	(PNOR_IDM_BASE + 0x408)
+#define PNOR_IDM_IO_RESET_CONTROL	(PNOR_IDM_BASE + 0x800)
+
+#define PNOR_REG_BASE			0x68c50000
+#define PNOR_REG_DIRECT_CMD		(PNOR_REG_BASE + 0x010)
+#define PNOR_REG_SET_CYCLES		(PNOR_REG_BASE + 0x014)
+#define PNOR_REG_SET_OPMODE		(PNOR_REG_BASE + 0x018)
+#define PNOR_REG_REFRESH_0		(PNOR_REG_BASE + 0x020)
+#define PNOR_REG_PERIPH_ID0		(PNOR_REG_BASE + 0xfe0)
+#define PNOR_REG_PERIPH_ID1		(PNOR_REG_BASE + 0xfe4)
+#define PNOR_REG_PERIPH_ID2		(PNOR_REG_BASE + 0xfe8)
+#define PNOR_REG_PERIPH_ID3		(PNOR_REG_BASE + 0xfec)
+#define PNOR_REG_PERIPH_IDx_MASK	0xff
+
+/*******************************************************************************
+ * NAND related constants
+ ******************************************************************************/
+#define NAND_FLASH_REVISION		0x68c60000
+#define NAND_IDM_IDM_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0xa408)
+#define NAND_IDM_IDM_RESET_CONTROL	(HSLS_IDM_REGS_BASE + 0xa800)
+
+/*******************************************************************************
+ * eMMC related constants
+ ******************************************************************************/
+#define PLAT_SD_MAX_READ_LENGTH		0x400
+
+#define SDIO0_EMMCSDXC_SYSADDR		0x68cf1000
+#define SDIO_IDM0_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0x2408)
+#define SDIO_IDM1_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0x3408)
+#define SDIO_IDM0_IDM_RESET_CONTROL	(HSLS_IDM_REGS_BASE + 0x2800)
+#define ICFG_SDIO0_BASE			(HSLS_ICFG_REGS_BASE + 0x6e4)
+#define ICFG_SDIO1_BASE			(HSLS_ICFG_REGS_BASE + 0x734)
+#define ICFG_SDIO0_CAP0			(ICFG_SDIO0_BASE + 0x10)
+#define ICFG_SDIO0_CAP1			(ICFG_SDIO0_BASE + 0x14)
+#define ICFG_SDIO0_SID			(HSLS_ICFG_REGS_BASE + 0xb00)
+#define ICFG_SDIO1_SID			(HSLS_ICFG_REGS_BASE + 0xb08)
+
+/*******************************************************************************
+ * Bootstrap related constants
+ ******************************************************************************/
+#define ROM_S0_IDM_IO_STATUS		(HSLS_IDM_REGS_BASE + 0x9500)
+
+/*******************************************************************************
+ * ROM related constants
+ ******************************************************************************/
+#define ROM_BASE_ADDR		0x6ce00000
+#define ROM_VERSION_STRING_ADDR	(ROM_BASE_ADDR + 0x28000)
+#define ROM_BUILD_MESSAGE_ADDR	(ROM_BASE_ADDR + 0x28018)
+
+/*******************************************************************************
+ * Boot source peripheral related constants
+ ******************************************************************************/
+#define QSPI_CTRL_BASE_ADDR	0x68c70000
+#define QSPI_BASE_ADDR		0x70000000
+#define QSPI_SIZE		0x08000000
+#define NOR_BASE_ADDR		0x74000000
+#define NOR_SIZE		0x04000000
+#define NAND_BASE_ADDR		0x78000000
+#define NAND_SIZE		0x08000000
+
+#define QSPI_IDM_RESET_CONTROL		(HSLS_IDM_REGS_BASE + 0xc800)
+
+#define APBR_IDM_RESET_CONTROL		(HSLS_IDM_REGS_BASE + 0xe800)
+#define APBS_IDM_IDM_RESET_CONTROL	(HSLS_IDM_REGS_BASE + 0xf800)
+
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0x10408)
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE	0
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_WDOG_SCLK_SEL	2
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM0_SCLK_SEL	4
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM1_SCLK_SEL	6
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM2_SCLK_SEL	8
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM3_SCLK_SEL	10
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM4_SCLK_SEL	12
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM5_SCLK_SEL	13
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM6_SCLK_SEL	14
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM7_SCLK_SEL	15
+
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0x11408)
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE	0
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART0_SCLK_SEL	2
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART1_SCLK_SEL	4
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART2_SCLK_SEL	6
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART3_SCLK_SEL	8
+
+#define APBZ_IDM_IDM_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0x12408)
+#define APBZ_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE	0
+#define APBZ_IDM_IDM_IO_CONTROL_DIRECT_WDOG_SCLK_SEL	2
+
+/*******************************************************************************
+ * Stingray memory map related constants
+ ******************************************************************************/
+
+/* The last 4KB of Trusted SRAM are used as shared memory */
+#define BRCM_SHARED_RAM_SIZE		0x0
+#define BRCM_SHARED_RAM_BASE		(PLAT_BRCM_TRUSTED_SRAM_BASE + \
+					 PLAT_BRCM_TRUSTED_SRAM_SIZE - \
+					 BRCM_SHARED_RAM_SIZE)
+
+/* Reserve 4 KB to store error logs in BL2 */
+#define BCM_ELOG_BL2_SIZE		0x00001000
+#define BCM_ELOG_BL2_BASE		BL1_RW_LIMIT
+
+/* The remaining Trusted SRAM is used to load the BL images */
+#define BRCM_BL_RAM_BASE		(PLAT_BRCM_TRUSTED_SRAM_BASE)
+#define BRCM_BL_RAM_SIZE		(PLAT_BRCM_TRUSTED_SRAM_SIZE - \
+					 BRCM_SHARED_RAM_SIZE)
+
+/* DDR Address where TMON temperature values are written */
+#define TMON_SHARED_DDR_ADDRESS		0x8f100000
+
+/* Reserve 4 kB to pass data to BL33 */
+#define BL33_SHARED_DDR_BASE		0x8f102000
+#define BL33_SHARED_DDR_SIZE		0x1000
+
+/* Default AP error logging base addr */
+#ifndef ELOG_AP_UART_LOG_BASE
+#define ELOG_AP_UART_LOG_BASE		0x8f110000
+#endif
+
+/* Reserve 16 to store error logs in BL31 */
+#define BCM_ELOG_BL31_BASE		ELOG_AP_UART_LOG_BASE
+#define BCM_ELOG_BL31_SIZE		0x4000
+
+/*******************************************************************************
+ * Non-secure DDR Map
+ ******************************************************************************/
+#define BRCM_DRAM1_BASE		ULL(0x80000000)
+#define BRCM_DRAM1_SIZE		ULL(0x10000000)
+#define BRCM_DRAM2_BASE		ULL(0x880000000)
+#define BRCM_DRAM2_SIZE		ULL(0x780000000)
+#define BRCM_DRAM3_BASE		ULL(0x8800000000)
+#define BRCM_DRAM3_SIZE		ULL(0x7800000000)
+#define BRCM_SHARED_DRAM_BASE	BL33_SHARED_DDR_BASE
+#define BRCM_SHARED_DRAM_SIZE	BL33_SHARED_DDR_SIZE
+#define BRCM_EXT_SRAM_BASE	ULL(0x74000000)
+#define BRCM_EXT_SRAM_SIZE	ULL(0x4000000)
+
+/* Priority levels for platforms */
+#define PLAT_RAS_PRI			0x10
+#define PLAT_SDEI_CRITICAL_PRI		0x60
+#define PLAT_SDEI_NORMAL_PRI		0x70
+
+/* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 */
+#define BRCM_IRQ_SEC_SGI_0	14
+#define BRCM_IRQ_SEC_SGI_1	15
+
+/* RTC periodic interrupt */
+#define BRCM_IRQ_SEC_SPI_0	49
+
+/*
+ *  Macros for local power states in SR platforms encoded by State-ID field
+ *  within the power-state parameter.
+ */
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN	0
+
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET	1
+
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF	2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE	PLAT_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE	PLAT_LOCAL_STATE_OFF
+
+/* ChiMP-related constants */
+
+#define NITRO_TZPC_TZPCDECPROT0clr		0x60c01808
+#define NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R		1
+
+#define NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT		0x60e00408
+
+#define CHIMP_INDIRECT_ADDR_MASK		0x3fffff
+#define CHIMP_INDIRECT_BASE		0x60800000
+
+#define CHIMP_REG_ECO_RESERVED		0x3042400
+
+#define CHIMP_FLASH_ACCESS_DONE_BIT		2
+
+/* indicate FRU table programming is done successfully */
+#define CHIMP_FRU_PROG_DONE_BIT			9
+
+#define CHIMP_REG_CTRL_BPE_MODE_REG		0x0
+#define CHIMP_REG_CTRL_BPE_STAT_REG		0x4
+#define CHIMP_REG_CTRL_FSTBOOT_PTR_REG		0x8
+#define CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_L		1
+#define CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R		1
+#define CHIMP_REG_CTRL_BASE		0x3040000
+#define CHIMP_FAST_BOOT_MODE_BIT		2
+#define CHIMP_REG_CHIMP_APE_SCPAD		0x3300000
+#define CHIMP_REG_CHIMP_SCPAD		0x3100000
+
+/* Chimp health status offset in scratch pad ram */
+#define CHIMP_HEALTH_STATUS_OFFSET	0x8
+/*
+ * If not in NIC mode then FASTBOOT can be enabled.
+ *  "Not in NIC mode" means that FORCE_FASTBOOT is set
+ *  and a valid (1 or 2) fastboot type is specified.
+ *
+ *  Three types of fastboot are supported:
+ *  0 = No fastboot. Boots Nitro/ChiMP and lets ROM loader
+ *		initialize ChiMP from NVRAM (QSPI).
+ *
+ *  1 = Jump in place (need a flat image)
+ *		This is intended to speedup Nitro FW boot on Palladium,
+ *		can be used with a real chip as well.
+ *  2 = Jump normally with decompression
+ *		Modus operandi for a real chip. Works also on Palladium
+ *		Note: image decompressing takes time on Palladium.
+ *  3 = No fastboot support. No ChiMP bringup
+ *		(use only for AP debug or for ChiMP's deferred setup).
+ */
+#define CHIMP_FASTBOOT_JUMP_DECOMPRESS		2
+#define CHIMP_FASTBOOT_JUMP_IN_PLACE		1
+#define CHIMP_FASTBOOT_NITRO_RESET		0
+/*
+ * Definitions for a non-Nitro access
+ * to QSPI PAD after the handshake
+ */
+#define	QSPI_HOLD_N_MODE_SEL_CONTROL		(HSLS_MODE_SEL_CONTROL + 0x3e8)
+#define QSPI_WP_N_MODE_SEL_CONTROL		(HSLS_MODE_SEL_CONTROL + 0x3ec)
+#define QSPI_SCK_MODE_SEL_CONTROL		(HSLS_MODE_SEL_CONTROL + 0x3f0)
+#define QSPI_CS_N_MODE_SEL_CONTROL		(HSLS_MODE_SEL_CONTROL + 0x3f4)
+#define QSPI_MOSI_MODE_SEL_CONTROL		(HSLS_MODE_SEL_CONTROL + 0x3f8)
+#define QSPI_MISO_MODE_SEL_CONTROL		(HSLS_MODE_SEL_CONTROL + 0x3fc)
+
+/*******************************************************************************
+ * Stream IDs for different blocks of SR
+ * block_id for different blocks is as follows:
+ * PCIE		: 0x0
+ * PAXC		: 0x1
+ * FS4		: 0x2
+ * Rest of the masters(includes MHB via RNI): 0x3
+ ******************************************************************************/
+#define SR_SID_VAL(block_id, subblock_id, device_num)	((block_id << 13) | \
+							(subblock_id << 11) | \
+							(device_num))
+
+#define CRMU_STREAM_ID		SR_SID_VAL(0x3, 0x0, 0x7)
+#define CRMU_SID_SHIFT		5
+
+#define DMAC_STREAM_ID		SR_SID_VAL(0x3, 0x0, 0x0)
+#define DMAC_SID_SHIFT		5
+
+/* DDR SHMOO Values defines */
+#define IDRAM_SHMOO_VALUES_ADDR CRMU_IDRAM_BASE_ADDR
+#define DDR_SHMOO_VALUES_ADDR 0x8f103000
+#define SHMOO_SIZE_PER_CHANNEL 0x1000
+
+#endif /* SR_DEF_H */
diff --git a/plat/brcm/board/stingray/include/sr_utils.h b/plat/brcm/board/stingray/include/sr_utils.h
new file mode 100644
index 0000000..b3fc735
--- /dev/null
+++ b/plat/brcm/board/stingray/include/sr_utils.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SR_UTILS_H
+#define SR_UTILS_H
+
+#include <lib/mmio.h>
+
+#include <chip_id.h>
+#include <cmn_plat_util.h>
+#include <sr_def.h>
+
+static inline void brcm_stingray_set_qspi_mux(int enable_ap)
+{
+	mmio_write_32(QSPI_HOLD_N_MODE_SEL_CONTROL, enable_ap);
+	mmio_write_32(QSPI_WP_N_MODE_SEL_CONTROL, enable_ap);
+	mmio_write_32(QSPI_SCK_MODE_SEL_CONTROL, enable_ap);
+	mmio_write_32(QSPI_CS_N_MODE_SEL_CONTROL, enable_ap);
+	mmio_write_32(QSPI_MOSI_MODE_SEL_CONTROL, enable_ap);
+	mmio_write_32(QSPI_MISO_MODE_SEL_CONTROL, enable_ap);
+}
+
+static inline void brcm_stingray_set_straps(uint32_t boot_source)
+{
+	/* Enable software strap override */
+	mmio_setbits_32(CDRU_CHIP_STRAP_CTRL,
+			BIT(CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE));
+
+	/* set straps to the next boot source */
+	mmio_clrsetbits_32(CDRU_CHIP_STRAP_DATA,
+			   BOOT_SOURCE_MASK,
+			   boot_source);
+
+	/* Disable software strap override */
+	mmio_clrbits_32(CDRU_CHIP_STRAP_CTRL,
+			BIT(CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE));
+}
+
+#endif
diff --git a/plat/brcm/board/stingray/include/swreg.h b/plat/brcm/board/stingray/include/swreg.h
new file mode 100644
index 0000000..6e971ce
--- /dev/null
+++ b/plat/brcm/board/stingray/include/swreg.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SWREG_H
+#define SWREG_H
+
+/* default voltage if no valid OTP */
+#define VDDC_CORE_DEF_VOLT      910000  /* 0.91v */
+#define IHOST_DEF_VOLT          940000  /* 0.94v */
+
+#define B0_VDDC_CORE_DEF_VOLT   950000  /* 0.95v */
+#define B0_IHOST_DEF_VOLT       950000  /* 0.95v */
+#define B0_DDR_VDDC_DEF_VOLT    1000000 /* 1v */
+
+#define SWREG_IHOST1_DIS        4
+#define SWREG_IHOST1_REG_RESETB 5
+#define SWREG_IHOST1_PMU_STABLE 2
+
+enum sw_reg {
+	DDR_VDDC = 1,
+	IHOST03,
+	IHOST12,
+	IHOST_ARRAY,
+	DDRIO_SLAVE,
+	VDDC_CORE,
+	VDDC1,
+	DDRIO_MASTER
+};
+
+int set_swreg(enum sw_reg reg_id, uint32_t micro_volts);
+int swreg_firmware_update(void);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/timer_sync.h b/plat/brcm/board/stingray/include/timer_sync.h
new file mode 100644
index 0000000..1f15bb0
--- /dev/null
+++ b/plat/brcm/board/stingray/include/timer_sync.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TIMER_SYNC_H
+#define TIMER_SYNC_H
+
+void brcm_timer_sync_init(void);
+
+#endif
diff --git a/plat/brcm/board/stingray/platform.mk b/plat/brcm/board/stingray/platform.mk
new file mode 100644
index 0000000..20ebcdd
--- /dev/null
+++ b/plat/brcm/board/stingray/platform.mk
@@ -0,0 +1,293 @@
+#
+# Copyright (c) 2019-2020, Broadcom
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Set the toc_flags to 1 for 100% speed operation
+# Set the toc_flags to 2 for 50% speed operation
+# Set the toc_flags to 3 for 25% speed operation
+# Set the toc_flags bit 3 to indicate ignore the fip in UEFI copy mode
+PLAT_TOC_FLAGS := 0x0
+
+# Set the IHOST_PLL_FREQ to,
+# 1 for full speed
+# 2 for 50% speed
+# 3 for 25% speed
+# 0 for bypass
+$(eval $(call add_define_val,IHOST_PLL_FREQ,1))
+
+# Enable workaround for ERRATA_A72_859971
+ERRATA_A72_859971 := 1
+
+# Cache Coherency Interconnect Driver needed
+DRIVER_CC_ENABLE := 1
+$(eval $(call add_define,DRIVER_CC_ENABLE))
+
+# Enable to erase eMMC
+INCLUDE_EMMC_DRIVER_ERASE_CODE := 0
+
+ifeq (${INCLUDE_EMMC_DRIVER_ERASE_CODE},1)
+$(eval $(call add_define,INCLUDE_EMMC_DRIVER_ERASE_CODE))
+endif
+
+# BL31 is in DRAM
+ARM_BL31_IN_DRAM	:=	1
+
+ifneq (${USE_EMULATOR},yes)
+STINGRAY_EMULATION_SETUP	:=	0
+ifeq (${FASTBOOT_TYPE},)
+override FASTBOOT_TYPE		:=	0
+endif
+USE_PAXB := yes
+USE_PAXC := yes
+USE_CHIMP := yes
+endif
+
+USE_CRMU_SRAM := yes
+
+# Disable FS4 clocks - they can be reenabled when needed by linux
+FS4_DISABLE_CLOCK := yes
+
+# Enable error logging by default for Stingray
+BCM_ELOG := yes
+
+# Enable FRU support by default for Stingray
+ifeq (${USE_FRU},)
+USE_FRU := no
+endif
+
+# Use single cluster
+ifeq (${USE_SINGLE_CLUSTER},yes)
+$(info Using Single Cluster)
+$(eval $(call add_define,USE_SINGLE_CLUSTER))
+endif
+
+# Use DDR
+ifeq (${USE_DDR},yes)
+$(info Using DDR)
+$(eval $(call add_define,USE_DDR))
+endif
+
+ifeq (${BOARD_CFG},)
+BOARD_CFG := bcm958742k
+endif
+
+# Use PAXB
+ifeq (${USE_PAXB},yes)
+$(info Using PAXB)
+$(eval $(call add_define,USE_PAXB))
+endif
+
+# Use FS4
+ifeq (${USE_FS4},yes)
+$(info Using FS4)
+$(eval $(call add_define,USE_FS4))
+endif
+
+# Use FS6
+ifeq (${USE_FS6},yes)
+$(info Using FS6)
+$(eval $(call add_define,USE_FS6))
+endif
+
+# Disable FS4 clock
+ifeq (${FS4_DISABLE_CLOCK},yes)
+$(info Using FS4_DISABLE_CLOCK)
+$(eval $(call add_define,FS4_DISABLE_CLOCK))
+endif
+
+ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},)
+$(info Using NCSI_IO_DRIVE_STRENGTH_MA)
+$(eval $(call add_define,NCSI_IO_DRIVE_STRENGTH_MA))
+endif
+
+# Use NAND
+ifeq (${USE_NAND},$(filter yes, ${USE_NAND}))
+$(info Using NAND)
+$(eval $(call add_define,USE_NAND))
+endif
+
+# Enable Broadcom error logging support
+ifeq (${BCM_ELOG},yes)
+$(info Using BCM_ELOG)
+$(eval $(call add_define,BCM_ELOG))
+endif
+
+# BL31 build for standalone mode
+ifeq (${STANDALONE_BL31},yes)
+RESET_TO_BL31 := 1
+$(info Using RESET_TO_BL31)
+endif
+
+# BL31 force full frequency for all CPUs
+ifeq (${BL31_FORCE_CPU_FULL_FREQ},yes)
+$(info Using BL31_FORCE_CPU_FULL_FREQ)
+$(eval $(call add_define,BL31_FORCE_CPU_FULL_FREQ))
+endif
+
+# Enable non-secure accesses to CCN registers
+ifeq (${BL31_CCN_NONSECURE},yes)
+$(info Using BL31_CCN_NONSECURE)
+$(eval $(call add_define,BL31_CCN_NONSECURE))
+endif
+
+# Use ChiMP
+ifeq (${USE_CHIMP},yes)
+$(info Using ChiMP)
+$(eval $(call add_define,USE_CHIMP))
+endif
+
+# Use PAXC
+ifeq (${USE_PAXC},yes)
+$(info Using PAXC)
+$(eval $(call add_define,USE_PAXC))
+ifeq (${CHIMPFW_USE_SIDELOAD},yes)
+$(info Using ChiMP FW sideload)
+$(eval $(call add_define,CHIMPFW_USE_SIDELOAD))
+endif
+$(eval $(call add_define,FASTBOOT_TYPE))
+$(eval $(call add_define,CHIMP_FB1_ENTRY))
+endif
+
+ifeq (${DEFAULT_SWREG_CONFIG}, 1)
+$(eval $(call add_define,DEFAULT_SWREG_CONFIG))
+endif
+
+ifeq (${CHIMP_ALWAYS_NEEDS_QSPI},yes)
+$(eval $(call add_define,CHIMP_ALWAYS_NEEDS_QSPI))
+endif
+
+# For testing purposes, use memsys stubs.  Remove once memsys is fully tested.
+USE_MEMSYS_STUBS := yes
+
+# Default, use BL1_RW area
+ifneq (${BL2_USE_BL1_RW},no)
+$(eval $(call add_define,USE_BL1_RW))
+endif
+
+# Default soft reset is L3
+$(eval $(call add_define,CONFIG_SOFT_RESET_L3))
+
+# Enable Chip OTP driver
+DRIVER_OCOTP_ENABLE := 1
+
+ifneq (${WARMBOOT_DDR_S3_SUPPORT},)
+DRIVER_SPI_ENABLE := 1
+endif
+
+include plat/brcm/board/common/board_common.mk
+
+SOC_DIR			:= 	brcm/board/stingray
+
+PLAT_INCLUDES		+=	-Iplat/${SOC_DIR}/include/ \
+				-Iinclude/plat/brcm/common/ \
+				-Iplat/brcm/common/
+
+PLAT_BL_COMMON_SOURCES	+=	lib/cpus/aarch64/cortex_a72.S \
+				plat/${SOC_DIR}/aarch64/plat_helpers.S \
+				drivers/ti/uart/aarch64/16550_console.S \
+				plat/${SOC_DIR}/src/tz_sec.c \
+				drivers/arm/tzc/tzc400.c \
+				plat/${SOC_DIR}/driver/plat_emmc.c \
+				plat/${SOC_DIR}/src/topology.c
+
+ifeq (${USE_CHIMP},yes)
+PLAT_BL_COMMON_SOURCES	+=	drivers/brcm/chimp.c
+endif
+
+BL2_SOURCES		+=	plat/${SOC_DIR}/driver/ihost_pll_config.c \
+				plat/${SOC_DIR}/src/bl2_setup.c \
+				plat/${SOC_DIR}/driver/swreg.c
+
+
+ifeq (${USE_DDR},yes)
+PLAT_INCLUDES		+=	-Iplat/${SOC_DIR}/driver/ddr/soc/include
+else
+PLAT_INCLUDES		+=	-Iplat/${SOC_DIR}/driver/ext_sram_init
+BL2_SOURCES		+=	plat/${SOC_DIR}/driver/ext_sram_init/ext_sram_init.c
+endif
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+BRCM_GIC_SOURCES	:=	${GICV3_SOURCES}		\
+				plat/common/plat_gicv3.c	\
+				plat/brcm/common/brcm_gicv3.c
+
+BL31_SOURCES		+=	\
+				drivers/arm/ccn/ccn.c \
+				plat/brcm/board/common/timer_sync.c \
+				plat/brcm/common/brcm_ccn.c \
+				plat/common/plat_psci_common.c \
+				plat/${SOC_DIR}/driver/ihost_pll_config.c \
+				plat/${SOC_DIR}/src/bl31_setup.c \
+				plat/${SOC_DIR}/src/fsx.c \
+				plat/${SOC_DIR}/src/iommu.c \
+				plat/${SOC_DIR}/src/sdio.c \
+				${BRCM_GIC_SOURCES}
+
+ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},)
+BL31_SOURCES   +=      plat/${SOC_DIR}/src/ncsi.c
+endif
+
+ifeq (${USE_PAXB},yes)
+BL31_SOURCES   +=      plat/${SOC_DIR}/src/paxb.c
+BL31_SOURCES   +=      plat/${SOC_DIR}/src/sr_paxb_phy.c
+endif
+
+ifeq (${USE_PAXC},yes)
+BL31_SOURCES   +=      plat/${SOC_DIR}/src/paxc.c
+endif
+
+ifdef SCP_BL2
+PLAT_INCLUDES		+=	-Iplat/brcm/common/
+
+BL2_SOURCES		+=	plat/brcm/common/brcm_mhu.c \
+				plat/brcm/common/brcm_scpi.c \
+				plat/${SOC_DIR}/src/scp_utils.c \
+				plat/${SOC_DIR}/src/scp_cmd.c \
+				drivers/brcm/scp.c
+
+BL31_SOURCES		+=	plat/brcm/common/brcm_mhu.c \
+				plat/brcm/common/brcm_scpi.c \
+				plat/${SOC_DIR}/src/brcm_pm_ops.c
+else
+BL31_SOURCES		+=	plat/${SOC_DIR}/src/ihost_pm.c \
+				plat/${SOC_DIR}/src/pm.c
+endif
+
+ifeq (${ELOG_SUPPORT},1)
+ifeq (${ELOG_STORE_MEDIA},DDR)
+BL2_SOURCES		+=	plat/brcm/board/common/bcm_elog_ddr.c
+endif
+endif
+
+ifeq (${BL31_BOOT_PRELOADED_SCP}, 1)
+ifdef SCP_BL2
+SCP_CFG_DIR=$(dir ${SCP_BL2})
+PLAT_INCLUDES	+=	-I${SCP_CFG_DIR}
+endif
+PLAT_INCLUDES	+=	-Iplat/brcm/common/
+
+# By default use OPTEE Assigned memory
+PRELOADED_SCP_BASE ?= 0x8E000000
+PRELOADED_SCP_SIZE ?= 0x10000
+$(eval $(call add_define,PRELOADED_SCP_BASE))
+$(eval $(call add_define,PRELOADED_SCP_SIZE))
+$(eval $(call add_define,BL31_BOOT_PRELOADED_SCP))
+BL31_SOURCES += plat/${SOC_DIR}/src/scp_utils.c \
+		plat/${SOC_DIR}/src/scp_cmd.c \
+		drivers/brcm/scp.c
+endif
+
+# Do not execute the startup code on warm reset.
+PROGRAMMABLE_RESET_ADDRESS	:=	1
+
+# Nitro FW, config and Crash log uses secure DDR memory
+# Inaddition to above, Nitro master and slave is also secure
+ifneq ($(NITRO_SECURE_ACCESS),)
+$(eval $(call add_define,NITRO_SECURE_ACCESS))
+$(eval $(call add_define,DDR_NITRO_SECURE_REGION_START))
+$(eval $(call add_define,DDR_NITRO_SECURE_REGION_END))
+endif
diff --git a/plat/brcm/board/stingray/src/bl2_setup.c b/plat/brcm/board/stingray/src/bl2_setup.c
new file mode 100644
index 0000000..9a79744
--- /dev/null
+++ b/plat/brcm/board/stingray/src/bl2_setup.c
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <chimp.h>
+#include <chip_id.h>
+#include <cmn_plat_util.h>
+#include <dmu.h>
+#include <emmc_api.h>
+#include <fru.h>
+#ifdef USE_GPIO
+#include <drivers/gpio.h>
+#include <iproc_gpio.h>
+#endif
+#include <platform_def.h>
+#include <sotp.h>
+#include <swreg.h>
+#include <sr_utils.h>
+#ifdef USE_DDR
+#include <ddr_init.h>
+#else
+#include <ext_sram_init.h>
+#endif
+#if DRIVER_OCOTP_ENABLE
+#include <ocotp.h>
+#endif
+#include "board_info.h"
+
+#define WORD_SIZE              8
+#define SWREG_AVS_OTP_OFFSET   (13 * WORD_SIZE) /* 13th row byte offset */
+#define AON_GPIO_OTP_OFFSET    (28 * WORD_SIZE) /* 28th row byte offset */
+#define BYTES_TO_READ          8
+
+/* OTP voltage step definitions */
+#define MVOLT_STEP_MAX         0x18  /* 1v */
+#define MVOLT_PER_STEP         10    /* 0.01mv per step */
+#define MVOLT_BASE             760   /* 0.76v */
+
+#define STEP_TO_UVOLTS(step) \
+	((MVOLT_BASE + (MVOLT_PER_STEP * (step))) * 1000)
+
+#define GET_BITS(first, last, data) \
+	((data >> first) & ((1 << (last - first + 1)) - 1))
+
+/*
+ * SW-REG OTP encoding:
+ *
+ * SWREG_bits[11:0]  = OTP 13th row 12 bits[55:44]
+ * SWREG_bits[11:10] - Valid Bits (0x2 - valid, if not 0x2 - Invalid)
+ * SWREG_bits[9:5]   - iHost03, iHost12
+ * SWREG_bits[4:0]   - Core VDDC
+ */
+#define SWREG_OTP_BITS_START        12    /* 44th bit in MSB 32-bits */
+#define SWREG_OTP_BITS_END          23    /* 55th bit in MSB 32-bits */
+#define SWREG_VDDC_FIELD_START      0
+#define SWREG_VDDC_FIELD_END        4
+#define SWREG_IHOST_FIELD_START     5
+#define SWREG_IHOST_FIELD_END       9
+#define SWREG_VALID_BIT_START       10
+#define SWREG_VALID_BIT_END         11
+#define SWREG_VALID_BITS            0x2
+
+/*
+ * Row 13 bit 56 is programmed as '1' today. It is not being used, so plan
+ * is to flip this bit to '0' for B1 rev. Hence SW can leverage this bit
+ * to identify Bx chip to program different sw-regulators.
+ */
+#define SPARE_BIT             24
+
+#define IS_SR_B0(data)        (((data) >> SPARE_BIT) & 0x1)
+
+#if DRIVER_OCOTP_ENABLE
+static struct otpc_map otp_stingray_map = {
+	.otpc_row_size = 2,
+	.data_r_offset = {0x10, 0x5c},
+	.data_w_offset = {0x2c, 0x64},
+	.word_size = 8,
+	.stride = 8,
+};
+#endif
+
+void plat_bcm_bl2_early_platform_setup(void)
+{
+	/* Select UART0 for AP via mux setting*/
+	if (PLAT_BRCM_BOOT_UART_BASE == UART0_BASE_ADDR) {
+		mmio_write_32(UART0_SIN_MODE_SEL_CONTROL, 1);
+		mmio_write_32(UART0_SOUT_MODE_SEL_CONTROL, 1);
+	}
+}
+
+#ifdef USE_NAND
+static void brcm_stingray_nand_init(void)
+{
+	unsigned int val;
+	unsigned int nand_idm_reset_control = 0x68e0a800;
+
+	VERBOSE(" stingray nand init start.\n");
+
+	/* Reset NAND */
+	VERBOSE(" - reset nand\n");
+	val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0));
+	mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val | 0x1);
+	udelay(500);
+	val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0));
+	mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val & ~0x1);
+	udelay(500);
+
+	VERBOSE(" stingray nand init done.\n");
+}
+#endif
+
+#if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA)
+#define PCIE_RESCAL_CFG_0 0x40000130
+#define PCIE_CFG_RESCAL_RSTB_R (1 << 16)
+#define PCIE_CFG_RESCAL_PWRDNB_R (1 << 8)
+#define PCIE_RESCAL_STATUS_0 0x4000014c
+#define PCIE_STAT_PON_VALID_R (1 << 0)
+#define PCIE_RESCAL_OUTPUT_STATUS 0x40000154
+#define CDRU_PCIE_RESET_N_R (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R)
+
+#ifdef EMULATION_SETUP
+static void brcm_stingray_pcie_reset(void)
+{
+}
+#else
+static void brcm_stingray_pcie_reset(void)
+{
+	unsigned int data;
+	int try;
+
+	if (bcm_chimp_is_nic_mode()) {
+		INFO("NIC mode detected; PCIe reset/rescal not executed\n");
+		return;
+	}
+
+	mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R);
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R);
+	/* Release reset */
+	mmio_setbits_32(PCIE_RESCAL_CFG_0, PCIE_CFG_RESCAL_RSTB_R);
+	mdelay(1);
+	/* Power UP */
+	mmio_setbits_32(PCIE_RESCAL_CFG_0,
+			(PCIE_CFG_RESCAL_RSTB_R | PCIE_CFG_RESCAL_PWRDNB_R));
+
+	try = 1000;
+	do {
+		udelay(1);
+		data = mmio_read_32(PCIE_RESCAL_STATUS_0);
+		try--;
+	} while ((data & PCIE_STAT_PON_VALID_R) == 0x0 && (try > 0));
+
+	if (try <= 0)
+		ERROR("PCIE_RESCAL_STATUS_0: 0x%x\n", data);
+
+	VERBOSE("PCIE_SATA_RESCAL_STATUS_0 0x%x.\n",
+			mmio_read_32(PCIE_RESCAL_STATUS_0));
+	VERBOSE("PCIE_SATA_RESCAL_OUTPUT_STATUS 0x%x.\n",
+			mmio_read_32(PCIE_RESCAL_OUTPUT_STATUS));
+	INFO("PCIE SATA Rescal Init done\n");
+}
+#endif /* EMULATION_SETUP */
+#endif /* USE_PAXB || USE_PAXC || USE_SATA */
+
+#ifdef USE_PAXC
+void brcm_stingray_chimp_check_and_fastboot(void)
+{
+	int fastboot_init_result;
+
+	if (bcm_chimp_is_nic_mode())
+		/* Do not wait here */
+		return;
+
+#if WARMBOOT_DDR_S3_SUPPORT
+	/*
+	 * Currently DDR shmoo parameters and QSPI boot source are
+	 * tied. DDR shmoo parameters are stored in QSPI, which is
+	 * used for warmboot.
+	 * Do not reset nitro for warmboot
+	 */
+	if (is_warmboot() && (boot_source_get() == BOOT_SOURCE_QSPI))
+		return;
+#endif /* WARMBOOT_DDR_S3_SUPPORT */
+
+	/*
+	 * Not in NIC mode,
+	 * initiate fastboot (if enabled)
+	 */
+	if (FASTBOOT_TYPE == CHIMP_FASTBOOT_NITRO_RESET) {
+
+		VERBOSE("Bring up Nitro/ChiMP\n");
+
+		if (boot_source_get() == BOOT_SOURCE_QSPI)
+			WARN("Nitro boots from QSPI when AP has booted from QSPI.\n");
+		brcm_stingray_set_qspi_mux(0);
+		VERBOSE("Nitro controls the QSPI\n");
+	}
+
+	fastboot_init_result = bcm_chimp_initiate_fastboot(FASTBOOT_TYPE);
+	if (fastboot_init_result && boot_source_get() != BOOT_SOURCE_QSPI)
+		ERROR("Nitro init error %d. Status: 0x%x; bpe_mod reg: 0x%x\n"
+			"fastboot register: 0x%x; handshake register 0x%x\n",
+			fastboot_init_result,
+			bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG),
+			bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG),
+			bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
+			bcm_chimp_read(CHIMP_REG_ECO_RESERVED));
+
+	/*
+	 * CRMU watchdog kicks is an example, which is L1 reset,
+	 * does not clear Nitro scratch pad ram.
+	 * For Nitro resets: Clear the Nitro health status memory.
+	 */
+	bcm_chimp_write((CHIMP_REG_CHIMP_SCPAD + CHIMP_HEALTH_STATUS_OFFSET),
+			0);
+}
+#endif
+
+void set_ihost_vddc_swreg(uint32_t ihost_uvolts, uint32_t vddc_uvolts)
+{
+	NOTICE("ihost_uvolts: %duv, vddc_uvolts: %duv\n",
+	       ihost_uvolts, vddc_uvolts);
+
+	set_swreg(VDDC_CORE, vddc_uvolts);
+	set_swreg(IHOST03, ihost_uvolts);
+	set_swreg(IHOST12, ihost_uvolts);
+}
+
+/*
+ * Reads SWREG AVS OTP bits (13th row) with ECC enabled and get voltage
+ * defined in OTP if valid OTP is found
+ */
+void read_avs_otp_bits(uint32_t *ihost_uvolts, uint32_t *vddc_uvolts)
+{
+	uint32_t offset = SWREG_AVS_OTP_OFFSET;
+	uint32_t ihost_step, vddc_step;
+	uint32_t avs_bits;
+	uint32_t buf[2];
+
+	if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1)
+		return;
+
+	VERBOSE("AVS OTP %d ROW: 0x%x.0x%x\n",
+		offset/WORD_SIZE, buf[1], buf[0]);
+
+	/* get voltage readings from AVS OTP bits */
+	avs_bits = GET_BITS(SWREG_OTP_BITS_START,
+			    SWREG_OTP_BITS_END,
+			    buf[1]);
+
+	/* check for valid otp bits */
+	if (GET_BITS(SWREG_VALID_BIT_START, SWREG_VALID_BIT_END, avs_bits) !=
+	    SWREG_VALID_BITS) {
+		WARN("Invalid AVS OTP bits at %d row\n", offset/WORD_SIZE);
+		return;
+	}
+
+	/* get ihost and vddc step value */
+	vddc_step = GET_BITS(SWREG_VDDC_FIELD_START,
+			     SWREG_VDDC_FIELD_END,
+			     avs_bits);
+
+	ihost_step = GET_BITS(SWREG_IHOST_FIELD_START,
+			      SWREG_IHOST_FIELD_END,
+			      avs_bits);
+
+	if ((ihost_step > MVOLT_STEP_MAX) || (vddc_step > MVOLT_STEP_MAX)) {
+		WARN("OTP entry invalid\n");
+		return;
+	}
+
+	/* get voltage in micro-volts */
+	*ihost_uvolts = STEP_TO_UVOLTS(ihost_step);
+	*vddc_uvolts = STEP_TO_UVOLTS(vddc_step);
+}
+
+/*
+ * This api reads otp bits and program internal swreg's - ihos12, ihost03,
+ * vddc_core and ddr_core based on different chip. External swreg's
+ * programming will be done from crmu.
+ *
+ * For A2 chip:
+ *   Read OTP row 20, bit 50. This bit will be set for A2 chip. Once A2 chip is
+ *   found, read AVS OTP row 13, 12bits[55:44], if valid otp bits are found
+ *   then set ihost and vddc according to avs otp bits else set them to 0.94v
+ *   and 0.91v respectively. Also update the firmware after setting voltage.
+ *
+ * For B0 chip:
+ *   Read OTP row 13, bit 56. This bit will be set for B0 chip. Once B0 chip is
+ *   found then set ihost and vddc to 0.95v and ddr_core to 1v. No AVS OTP bits
+ *   are used get ihost/vddc voltages.
+ *
+ * For B1 chip:
+ *   Read AVS OTP row 13, 12bits[55:44], if valid otp bits are found then set
+ *   ihost and vddc according to avs otp bits else set them to 0.94v and 0.91v
+ *   respectively.
+ */
+void set_swreg_based_on_otp(void)
+{
+	/* default voltage if no valid OTP */
+	uint32_t vddc_uvolts = VDDC_CORE_DEF_VOLT;
+	uint32_t ihost_uvolts = IHOST_DEF_VOLT;
+	uint32_t ddrc_uvolts;
+	uint32_t offset;
+	uint32_t buf[2];
+
+	offset = SWREG_AVS_OTP_OFFSET;
+	if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1)
+		return;
+
+	VERBOSE("OTP %d ROW: 0x%x.0x%x\n",
+		offset/WORD_SIZE, buf[1], buf[0]);
+
+	if (IS_SR_B0(buf[1])) {
+		/* don't read AVS OTP for B0 */
+		ihost_uvolts = B0_IHOST_DEF_VOLT;
+		vddc_uvolts = B0_VDDC_CORE_DEF_VOLT;
+		ddrc_uvolts = B0_DDR_VDDC_DEF_VOLT;
+	} else {
+		read_avs_otp_bits(&ihost_uvolts, &vddc_uvolts);
+	}
+
+#if (IHOST_REG_TYPE == IHOST_REG_INTEGRATED) && \
+	(VDDC_REG_TYPE == VDDC_REG_INTEGRATED)
+	/* enable IHOST12 cluster before changing voltage */
+	NOTICE("Switching on the Regulator idx: %u\n",
+	       SWREG_IHOST1_DIS);
+	mmio_clrsetbits_32(CRMU_SWREG_CTRL_ADDR,
+			   BIT(SWREG_IHOST1_DIS),
+			   BIT(SWREG_IHOST1_REG_RESETB));
+
+	/* wait for regulator supply gets stable */
+	while (!(mmio_read_32(CRMU_SWREG_STATUS_ADDR) &
+	       (1 << SWREG_IHOST1_PMU_STABLE)))
+		;
+
+	INFO("Regulator supply got stable\n");
+
+#ifndef DEFAULT_SWREG_CONFIG
+	swreg_firmware_update();
+#endif
+
+	set_ihost_vddc_swreg(ihost_uvolts, vddc_uvolts);
+#endif
+	if (IS_SR_B0(buf[1])) {
+		NOTICE("ddrc_uvolts: %duv\n", ddrc_uvolts);
+		set_swreg(DDR_VDDC, ddrc_uvolts);
+	}
+}
+
+#ifdef USE_DDR
+static struct ddr_info ddr_info;
+#endif
+#ifdef USE_FRU
+static struct fru_area_info fru_area[FRU_MAX_NR_AREAS];
+static struct fru_board_info board_info;
+static struct fru_time fru_tm;
+static uint8_t fru_tbl[BCM_MAX_FRU_LEN];
+
+static void board_detect_fru(void)
+{
+	uint32_t i, result;
+	int ret = -1;
+
+	result = bcm_emmc_init(false);
+	if (!result) {
+		ERROR("eMMC init failed\n");
+		return;
+	}
+
+	/* go through eMMC boot partitions looking for FRU table */
+	for (i = EMMC_BOOT_PARTITION1; i <= EMMC_BOOT_PARTITION2; i++) {
+		result = emmc_partition_select(i);
+		if (!result) {
+			ERROR("Switching to eMMC part %u failed\n", i);
+			return;
+		}
+
+		result = emmc_read(BCM_FRU_TBL_OFFSET, (uintptr_t)fru_tbl,
+				   BCM_MAX_FRU_LEN, BCM_MAX_FRU_LEN);
+		if (!result) {
+			ERROR("Failed to read from eMMC part %u\n", i);
+			return;
+		}
+
+		/*
+		 * Run sanity check and checksum to make sure valid FRU table
+		 * is detected
+		 */
+		ret = fru_validate(fru_tbl, fru_area);
+		if (ret < 0) {
+			WARN("FRU table not found in eMMC part %u\n", i);
+			continue;
+		}
+
+		/* parse DDR information from FRU table */
+		ret = fru_parse_ddr(fru_tbl, &fru_area[FRU_AREA_INTERNAL],
+				    &ddr_info);
+		if (ret < 0) {
+			WARN("No FRU DDR info found in eMMC part %u\n", i);
+			continue;
+		}
+
+		/* parse board information from FRU table */
+		ret = fru_parse_board(fru_tbl, &fru_area[FRU_AREA_BOARD_INFO],
+				      &board_info);
+		if (ret < 0) {
+			WARN("No FRU board info found in eMMC part %u\n", i);
+			continue;
+		}
+
+		/* if we reach here, valid FRU table is parsed */
+		break;
+	}
+
+	if (ret < 0) {
+		WARN("FRU table missing for this board\n");
+		return;
+	}
+
+	for (i = 0; i < BCM_MAX_NR_DDR; i++) {
+		INFO("DDR channel index: %d\n", ddr_info.mcb[i].idx);
+		INFO("DDR size %u GB\n", ddr_info.mcb[i].size_mb / 1024);
+		INFO("DDR ref ID by SW (Not MCB Ref ID) 0x%x\n",
+		     ddr_info.mcb[i].ref_id);
+	}
+
+	fru_format_time(board_info.mfg_date, &fru_tm);
+
+	INFO("**** FRU board information ****\n");
+	INFO("Language 0x%x\n", board_info.lang);
+	INFO("Manufacturing Date %u.%02u.%02u, %02u:%02u\n",
+	     fru_tm.year, fru_tm.month, fru_tm.day,
+	     fru_tm.hour, fru_tm.min);
+	INFO("Manufacturing Date(Raw) 0x%x\n", board_info.mfg_date);
+	INFO("Manufacturer %s\n", board_info.manufacturer);
+	INFO("Product Name %s\n", board_info.product_name);
+	INFO("Serial number %s\n", board_info.serial_number);
+	INFO("Part number %s\n", board_info.part_number);
+	INFO("File ID %s\n", board_info.file_id);
+}
+#endif /* USE_FRU */
+
+#ifdef USE_GPIO
+
+#define INVALID_GPIO    0xffff
+
+static const int gpio_cfg_bitmap[MAX_NR_GPIOS] = {
+#ifdef BRD_DETECT_GPIO_BIT0
+	BRD_DETECT_GPIO_BIT0,
+#else
+	INVALID_GPIO,
+#endif
+#ifdef BRD_DETECT_GPIO_BIT1
+	BRD_DETECT_GPIO_BIT1,
+#else
+	INVALID_GPIO,
+#endif
+#ifdef BRD_DETECT_GPIO_BIT2
+	BRD_DETECT_GPIO_BIT2,
+#else
+	INVALID_GPIO,
+#endif
+#ifdef BRD_DETECT_GPIO_BIT3
+	BRD_DETECT_GPIO_BIT3,
+#else
+	INVALID_GPIO,
+#endif
+};
+
+static uint8_t gpio_bitmap;
+
+/*
+ * Use an odd number to avoid potential conflict with public GPIO level
+ * defines
+ */
+#define GPIO_STATE_FLOAT         15
+
+/*
+ * If GPIO_SUPPORT_FLOAT_DETECTION is disabled, simply return GPIO level
+ *
+ * If GPIO_SUPPORT_FLOAT_DETECTION is enabled, add additional test for possible
+ * pin floating (unconnected) scenario. This support is assuming externally
+ * applied pull up / pull down will have a stronger pull than the internal pull
+ * up / pull down.
+ */
+static uint8_t gpio_get_state(int gpio)
+{
+	uint8_t val;
+
+	/* set direction to GPIO input */
+	gpio_set_direction(gpio, GPIO_DIR_IN);
+
+#ifndef GPIO_SUPPORT_FLOAT_DETECTION
+	if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH)
+		val = GPIO_LEVEL_HIGH;
+	else
+		val = GPIO_LEVEL_LOW;
+
+	return val;
+#else
+	/*
+	 * Enable internal pull down. If GPIO level is still high, there must
+	 * be an external pull up
+	 */
+	gpio_set_pull(gpio, GPIO_PULL_DOWN);
+	if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) {
+		val = GPIO_LEVEL_HIGH;
+		goto exit;
+	}
+
+	/*
+	 * Enable internal pull up. If GPIO level is still low, there must
+	 * be an external pull down
+	 */
+	gpio_set_pull(gpio, GPIO_PULL_UP);
+	if (gpio_get_value(gpio) == GPIO_LEVEL_LOW) {
+		val = GPIO_LEVEL_LOW;
+		goto exit;
+	}
+
+	/* if reached here, the pin must be not connected */
+	val = GPIO_STATE_FLOAT;
+
+exit:
+	/* make sure internall pull is disabled */
+	if (gpio_get_pull(gpio) != GPIO_PULL_NONE)
+		gpio_set_pull(gpio, GPIO_PULL_NONE);
+
+	return val;
+#endif
+}
+
+static void board_detect_gpio(void)
+{
+	unsigned int i, val;
+	int gpio;
+
+	iproc_gpio_init(IPROC_GPIO_S_BASE, IPROC_GPIO_NR,
+			IPROC_IOPAD_MODE_BASE, HSLS_IOPAD_BASE);
+
+	gpio_bitmap = 0;
+	for (i = 0; i < MAX_NR_GPIOS; i++) {
+		if (gpio_cfg_bitmap[i] == INVALID_GPIO)
+			continue;
+
+		/*
+		 * Construct the bitmap based on GPIO value. Floating pin
+		 * detection is a special case. As soon as a floating pin is
+		 * detected, a special value of MAX_GPIO_BITMAP_VAL is
+		 * assigned and we break out of the loop immediately
+		 */
+		gpio = gpio_cfg_bitmap[i];
+		val = gpio_get_state(gpio);
+		if (val == GPIO_STATE_FLOAT) {
+			gpio_bitmap = MAX_GPIO_BITMAP_VAL;
+			break;
+		}
+
+		if (val == GPIO_LEVEL_HIGH)
+			gpio_bitmap |= BIT(i);
+	}
+
+	memcpy(&ddr_info, &gpio_ddr_info[gpio_bitmap], sizeof(ddr_info));
+	INFO("Board detection GPIO bitmap = 0x%x\n", gpio_bitmap);
+}
+#endif /* USE_GPIO */
+
+static void bcm_board_detect(void)
+{
+#ifdef DDR_LEGACY_MCB_SUPPORTED
+	/* Loading default DDR info */
+	memcpy(&ddr_info, &default_ddr_info, sizeof(ddr_info));
+#endif
+#ifdef USE_FRU
+	board_detect_fru();
+#endif
+#ifdef USE_GPIO
+	board_detect_gpio();
+#endif
+}
+
+static void dump_persistent_regs(void)
+{
+	NOTICE("pr0: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG0));
+	NOTICE("pr1: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1));
+	NOTICE("pr2: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG2));
+	NOTICE("pr3: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG3));
+	NOTICE("pr4: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG4));
+	NOTICE("pr5: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG5));
+	NOTICE("pr6: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG6));
+	NOTICE("pr7: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG7));
+	NOTICE("pr8: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG8));
+	NOTICE("pr9: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9));
+	NOTICE("pr10: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG10));
+	NOTICE("pr11: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG11));
+}
+
+void plat_bcm_bl2_plat_arch_setup(void)
+{
+	if (chip_get_rev_id_major() == CHIP_REV_MAJOR_AX) {
+		if (!(sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
+		      SOTP_ATF_WATCHDOG_ENABLE_MASK)) {
+			/*
+			 * Stop sp805 watchdog timer immediately.
+			 * It might has been set up by MCU patch earlier for
+			 * eMMC workaround.
+			 *
+			 * Note the watchdog timer started in CRMU has a very
+			 * short timeout and needs to be stopped immediately.
+			 * Down below we restart it with a much longer timeout
+			 * for BL2 and BL31
+			 */
+			sp805_stop(ARM_SP805_TWDG_BASE);
+		}
+	}
+
+#if !BRCM_DISABLE_TRUSTED_WDOG
+	/*
+	 * start secure watchdog for BL2 and BL31.
+	 * Note that UART download can take a longer time,
+	 * so do not allow watchdog for UART download,
+	 * as this boot source is not a standard modus operandi.
+	 */
+	if (boot_source_get() != BOOT_SOURCE_UART)
+		sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+#endif
+
+#ifdef BCM_ELOG
+	/* Ensure logging is started out fresh in BL2. */
+	mmio_write_32(BCM_ELOG_BL2_BASE, 0);
+#endif
+	/*
+	 * In BL2, since we have very limited space to store logs, we only
+	 * save logs that are >= the WARNING level.
+	 */
+	bcm_elog_init((void *)BCM_ELOG_BL2_BASE, BCM_ELOG_BL2_SIZE,
+		      LOG_LEVEL_WARNING);
+
+	dump_persistent_regs();
+
+	/* Read CRMU mailbox 0 */
+	NOTICE("RESET (reported by CRMU): 0x%x\n",
+	       mmio_read_32(CRMU_READ_MAIL_BOX0));
+
+	/*
+	 * All non-boot-source PADs are in forced input-mode at
+	 * reset so clear the force on non-boot-source PADs using
+	 * CDRU register.
+	 */
+	mmio_clrbits_32((uintptr_t)CDRU_CHIP_IO_PAD_CONTROL,
+		(1 << CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R));
+
+#if DRIVER_OCOTP_ENABLE
+	bcm_otpc_init(&otp_stingray_map);
+#endif
+
+	set_swreg_based_on_otp();
+
+#if IHOST_PLL_FREQ != 0
+	bcm_set_ihost_pll_freq(0x0, IHOST_PLL_FREQ);
+#endif
+
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+	/* The erasable unit of the eMMC is the "Erase Group";
+	 * Erase group is measured in write blocks which are the
+	 * basic writable units of the Device.
+	 * The size of the Erase Group is a Device specific parameter
+	 */
+	emmc_erase(EMMC_ERASE_START_BLOCK, EMMC_ERASE_BLOCK_COUNT,
+		   EMMC_ERASE_PARTITION);
+#endif
+
+	bcm_board_detect();
+#ifdef DRIVER_EMMC_ENABLE
+	/* Initialize the card, if it is not */
+	if (bcm_emmc_init(true) < 0)
+		WARN("eMMC Card Initialization Failed!!!\n");
+#endif
+
+#if BL2_TEST_I2C
+	i2c_test();
+#endif
+
+#ifdef USE_DDR
+	ddr_initialize(&ddr_info);
+
+	ddr_secure_region_config(SECURE_DDR_BASE_ADDRESS,
+				 SECURE_DDR_END_ADDRESS);
+#ifdef NITRO_SECURE_ACCESS
+	ddr_secure_region_config(DDR_NITRO_SECURE_REGION_START,
+				 DDR_NITRO_SECURE_REGION_END);
+#endif
+#else
+	ext_sram_init();
+#endif
+
+#if BL2_TEST_MEM
+	ddr_test();
+#endif
+
+#ifdef USE_NAND
+	brcm_stingray_nand_init();
+#endif
+
+#if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA)
+	brcm_stingray_pcie_reset();
+#endif
+
+#ifdef USE_PAXC
+	if (boot_source_get() != BOOT_SOURCE_QSPI)
+		brcm_stingray_chimp_check_and_fastboot();
+#endif
+
+#if ((!CLEAN_DDR || 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 not yet at the end of BL2, but 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
+	 * NOTE: BL2 logging must be exited before going forward to setup
+	 * page tables
+	 */
+	bcm_elog_exit();
+#endif
+}
diff --git a/plat/brcm/board/stingray/src/bl31_setup.c b/plat/brcm/board/stingray/src/bl31_setup.c
new file mode 100644
index 0000000..d947551
--- /dev/null
+++ b/plat/brcm/board/stingray/src/bl31_setup.c
@@ -0,0 +1,1068 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <cortex_a72.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+
+#include <bl33_info.h>
+#include <chimp.h>
+#include <cmn_plat_util.h>
+#include <dmu.h>
+#include <fsx.h>
+#include <iommu.h>
+#include <ncsi.h>
+#include <paxb.h>
+#include <paxc.h>
+#include <platform_def.h>
+#include <sdio.h>
+#include <sr_utils.h>
+#include <timer_sync.h>
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup common to ARM standard platforms
+ ******************************************************************************/
+
+static void brcm_stingray_gain_qspi_control(void)
+{
+	if (boot_source_get() != BOOT_SOURCE_QSPI) {
+		if (bcm_chimp_is_nic_mode() &&
+		(!bcm_chimp_handshake_done())) {
+			/*
+			 * Last chance to wait for ChiMP firmware to report
+			 * "I am done" before grabbing the QSPI
+			 */
+			WARN("ChiMP still not booted\n");
+#ifndef CHIMP_ALWAYS_NEEDS_QSPI
+			WARN("ChiMP is given the last chance to boot (%d s)\n",
+				CHIMP_HANDSHAKE_TIMEOUT_MS / 1000);
+
+			if (!bcm_chimp_wait_handshake()) {
+				ERROR("ChiMP failed to boot\n");
+			} else {
+				INFO("ChiMP booted successfully\n");
+			}
+#endif
+		}
+
+#ifndef CHIMP_ALWAYS_NEEDS_QSPI
+		INFO("AP grabs QSPI\n");
+		/*
+		 * For QSPI boot sbl/bl1 has already taken care.
+		 * For other boot sources QSPI needs to be muxed to
+		 * AP for exclusive use
+		 */
+		brcm_stingray_set_qspi_mux(1);
+		INFO("AP (bl31) gained control over QSPI\n");
+#endif
+	}
+}
+
+static void brcm_stingray_dma_pl330_init(void)
+{
+	unsigned int val;
+
+	VERBOSE("dma pl330 init start\n");
+
+	/* Set DMAC boot_manager_ns = 0x1 */
+	VERBOSE(" - configure boot security state\n");
+	mmio_setbits_32(DMAC_M0_IDM_IO_CONTROL_DIRECT, BOOT_MANAGER_NS);
+	/* Set boot_peripheral_ns[n:0] = 0xffffffff */
+	mmio_write_32(ICFG_DMAC_CONFIG_2, BOOT_PERIPHERAL_NS);
+	/* Set boot_irq_ns[n:0] = 0x0000ffff */
+	mmio_write_32(ICFG_DMAC_CONFIG_3, BOOT_IRQ_NS);
+
+	/* Set DMAC stream_id */
+	VERBOSE(" - configure stream_id = 0x6000\n");
+	val = (DMAC_STREAM_ID << DMAC_SID_SHIFT);
+	mmio_write_32(ICFG_DMAC_SID_ARADDR_CONTROL, val);
+	mmio_write_32(ICFG_DMAC_SID_AWADDR_CONTROL, val);
+
+	/* Reset DMAC */
+	VERBOSE(" - reset dma pl330\n");
+
+	mmio_setbits_32(DMAC_M0_IDM_RESET_CONTROL, 0x1);
+	udelay(500);
+
+	mmio_clrbits_32(DMAC_M0_IDM_RESET_CONTROL, 0x1);
+	udelay(500);
+
+	INFO("dma pl330 init done\n");
+}
+
+static void brcm_stingray_spi_pl022_init(uintptr_t idm_reset_control)
+{
+	VERBOSE("spi pl022 init start\n");
+
+	/* Reset APB SPI bridge */
+	VERBOSE(" - reset apb spi bridge\n");
+	mmio_setbits_32(idm_reset_control, 0x1);
+	udelay(500);
+
+	mmio_clrbits_32(idm_reset_control, 0x1);
+	udelay(500);
+
+	INFO("spi pl022 init done\n");
+}
+
+#define CDRU_SATA_RESET_N \
+	BIT(CDRU_MISC_RESET_CONTROL__CDRU_SATA_RESET_N_R)
+#define CDRU_MISC_CLK_SATA \
+	BIT(CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SATA_CLK_EN_R)
+#define CCN_CONFIG_CLK_ENABLE		(1 << 2)
+#define MMU_CONFIG_CLK_ENABLE		(0x3F << 16)
+
+#define SATA_SATA_TOP_CTRL_BUS_CTRL	(SATA_BASE + 0x2044)
+#define DMA_BIT_CTRL_MASK		0x003
+#define DMA_DESCR_ENDIAN_CTRL		(DMA_BIT_CTRL_MASK << 0x002)
+#define DMA_DATA_ENDIAN_CTRL		(DMA_BIT_CTRL_MASK << 0x004)
+
+#define SATA_PORT_SATA3_PCB_REG8	(SATA_BASE + 0x2320)
+#define SATA_PORT_SATA3_PCB_REG11	(SATA_BASE + 0x232c)
+#define SATA_PORT_SATA3_PCB_BLOCK_ADDR	(SATA_BASE + 0x233c)
+
+#define SATA3_AFE_TXRX_ACTRL		0x1d0
+/* TXDriver swing setting is 800mV */
+#define DFS_SWINGNOPE_VALUE		(0x0 << 6)
+#define DFS_SWINGNOPE_MASK		(0x3 << 6)
+
+#define DFS_SWINGPE_VALUE		(0x1 << 4)
+#define DFS_SWINGPE_MASK		(0x3 << 4)
+
+#define DFS_INJSTRENGTH_VALUE		(0x0 << 4)
+#define DFS_INJSTRENGTH_MASK		(0x3 << 4)
+
+#define DFS_INJEN			(0x1 << 3)
+
+#define SATA_CORE_MEM_CTRL		(SATA_BASE + 0x3a08)
+#define SATA_CORE_MEM_CTRL_ISO		BIT(0)
+#define SATA_CORE_MEM_CTRL_ARRPOWEROKIN	BIT(1)
+#define SATA_CORE_MEM_CTRL_ARRPOWERONIN	BIT(2)
+#define SATA_CORE_MEM_CTRL_POWEROKIN	BIT(3)
+#define SATA_CORE_MEM_CTRL_POWERONIN	BIT(4)
+
+#define SATA0_IDM_RESET_CONTROL			(SATA_BASE + 0x500800)
+#define SATA_APBT0_IDM_IO_CONTROL_DIRECT	(SATA_BASE + 0x51a408)
+#define IO_CONTROL_DIRECT_CLK_ENABLE		BIT(0)
+#define SATA_APBT0_IDM_RESET_CONTROL		(SATA_BASE + 0x51a800)
+#define IDM_RESET_CONTROL_RESET			BIT(0)
+
+#define NIC400_SATA_NOC_SECURITY1	0x6830000c
+#define SATA_NOC_SECURITY1_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY2	0x68300010
+#define SATA_NOC_SECURITY2_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY3	0x68300014
+#define SATA_NOC_SECURITY3_FIELD	0x1
+#define NIC400_SATA_NOC_SECURITY4	0x68300018
+#define SATA_NOC_SECURITY4_FIELD	0x1
+#define NIC400_SATA_NOC_SECURITY5	0x6830001c
+#define SATA_NOC_SECURITY5_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY6	0x68300020
+#define SATA_NOC_SECURITY6_FIELD	0x1
+#define NIC400_SATA_NOC_SECURITY7	0x68300024
+#define SATA_NOC_SECURITY7_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY8	0x68300028
+#define SATA_NOC_SECURITY8_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY9	0x6830002c
+#define SATA_NOC_SECURITY9_FIELD	0x1
+
+#define SATA_APBT_IDM_PORT_REG(port, reg) \
+	(((port/4) << 12) + reg)
+
+#define SATA_IDM_PORT_REG(port, reg)	((port << 12) + reg)
+
+#define SATA_PORT_REG(port, reg) \
+	(((port%4) << 16) + ((port/4) << 20) + reg)
+
+#define MAX_SATA_PORTS	8
+#define USE_SATA_PORTS	8
+
+#ifdef USE_SATA
+static const uint8_t sr_b0_sata_port[MAX_SATA_PORTS] = {
+	0, 1, 2, 3, 4, 5, 6, 7
+};
+
+static uint32_t brcm_stingray_get_sata_port(unsigned int port)
+{
+	return sr_b0_sata_port[port];
+}
+
+static void brcm_stingray_sata_init(void)
+{
+	unsigned int port = 0;
+	uint32_t sata_port;
+
+	mmio_setbits_32(CDRU_MISC_CLK_ENABLE_CONTROL,
+			CDRU_MISC_CLK_SATA);
+
+	mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_SATA_RESET_N);
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_SATA_RESET_N);
+
+	for (port = 0; port < USE_SATA_PORTS; port++) {
+
+		sata_port = brcm_stingray_get_sata_port(port);
+		mmio_write_32(SATA_APBT_IDM_PORT_REG(sata_port,
+					SATA_APBT0_IDM_RESET_CONTROL),
+			      0x0);
+		mmio_setbits_32(SATA_APBT_IDM_PORT_REG(sata_port,
+					SATA_APBT0_IDM_IO_CONTROL_DIRECT),
+				IO_CONTROL_DIRECT_CLK_ENABLE);
+		mmio_write_32(SATA_IDM_PORT_REG(sata_port,
+						SATA0_IDM_RESET_CONTROL),
+			      0x0);
+
+		mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_ARRPOWERONIN);
+		mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_ARRPOWEROKIN);
+		mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_POWERONIN);
+		mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_POWEROKIN);
+		mmio_clrbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_ISO);
+
+		mmio_clrbits_32(SATA_PORT_REG(sata_port,
+					      SATA_SATA_TOP_CTRL_BUS_CTRL),
+				(DMA_DESCR_ENDIAN_CTRL | DMA_DATA_ENDIAN_CTRL));
+	}
+
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY1, SATA_NOC_SECURITY1_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY2, SATA_NOC_SECURITY2_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY3, SATA_NOC_SECURITY3_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY4, SATA_NOC_SECURITY4_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY5, SATA_NOC_SECURITY5_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY6, SATA_NOC_SECURITY6_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY7, SATA_NOC_SECURITY7_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY8, SATA_NOC_SECURITY8_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY9, SATA_NOC_SECURITY9_FIELD);
+
+	INFO("sata init done\n");
+}
+#else
+static void poweroff_sata_pll(void)
+{
+	/*
+	 * SATA subsystem is clocked by LCPLL0 which is enabled by
+	 * default by bootrom. Poweroff the PLL if SATA is not used
+	 */
+
+	/* enable isolation */
+	mmio_setbits_32(CRMU_AON_CTRL1,
+			BIT(CRMU_AON_CTRL1__LCPLL0_ISO_IN));
+
+	/* Power off the SATA PLL/LDO */
+	mmio_clrbits_32(CRMU_AON_CTRL1,
+			(BIT(CRMU_AON_CTRL1__LCPLL0_PWRON_LDO) |
+			 BIT(CRMU_AON_CTRL1__LCPLL0_PWR_ON)));
+}
+#endif
+
+#ifdef USE_AMAC
+#ifdef EMULATION_SETUP
+#define ICFG_AMAC_STRAP_CONFIG		(HSLS_ICFG_REGS_BASE + 0xa5c)
+#define ICFG_AMAC_STRAP_DLL_BYPASS	(1 << 2)
+#endif
+#define ICFG_AMAC_MAC_CTRL_REG		(HSLS_ICFG_REGS_BASE + 0xa6c)
+#define ICFG_AMAC_MAC_FULL_DUPLEX	(1 << 1)
+#define ICFG_AMAC_RGMII_PHY_CONFIG	(HSLS_ICFG_REGS_BASE + 0xa60)
+#define ICFG_AMAC_SID_CONTROL		(HSLS_ICFG_REGS_BASE + 0xb10)
+#define ICFG_AMAC_SID_SHIFT		5
+#define ICFG_AMAC_SID_AWADDR_OFFSET	0x0
+#define ICFG_AMAC_SID_ARADDR_OFFSET	0x4
+#define AMAC_RPHY_1000_DATARATE		(1 << 20)
+#define AMAC_RPHY_FULL_DUPLEX		(1 << 5)
+#define AMAC_RPHY_SPEED_OFFSET		2
+#define AMAC_RPHY_SPEED_MASK		(7 << AMAC_RPHY_SPEED_OFFSET)
+#define AMAC_RPHY_1G_SPEED		(2 << AMAC_RPHY_SPEED_OFFSET)
+#define ICFG_AMAC_MEM_PWR_CTRL		(HSLS_ICFG_REGS_BASE + 0xa68)
+#define AMAC_ISO			BIT(9)
+#define AMAC_STDBY			BIT(8)
+#define AMAC_ARRPOWEROKIN		BIT(7)
+#define AMAC_ARRPOWERONIN		BIT(6)
+#define AMAC_POWEROKIN			BIT(5)
+#define AMAC_POWERONIN			BIT(4)
+
+#define AMAC_IDM0_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0x4408)
+#define AMAC_IDM0_ARCACHE_OFFSET	16
+#define AMAC_IDM0_AWCACHE_OFFSET	7
+#define AMAC_IDM0_ARCACHE_MASK		(0xF << AMAC_IDM0_ARCACHE_OFFSET)
+#define AMAC_IDM0_AWCACHE_MASK		(0xF << AMAC_IDM0_AWCACHE_OFFSET)
+/* ARCACHE - AWCACHE is 0xB7 for write-back no allocate */
+#define AMAC_IDM0_ARCACHE_VAL		(0xb << AMAC_IDM0_ARCACHE_OFFSET)
+#define AMAC_IDM0_AWCACHE_VAL		(0x7 << AMAC_IDM0_AWCACHE_OFFSET)
+
+static void brcm_stingray_amac_init(void)
+{
+	unsigned int val;
+	uintptr_t icfg_amac_sid = ICFG_AMAC_SID_CONTROL;
+
+	VERBOSE("amac init start\n");
+
+	val = SR_SID_VAL(0x3, 0x0, 0x4) << ICFG_AMAC_SID_SHIFT;
+	mmio_write_32(icfg_amac_sid + ICFG_AMAC_SID_AWADDR_OFFSET, val);
+	mmio_write_32(icfg_amac_sid + ICFG_AMAC_SID_ARADDR_OFFSET, val);
+
+	mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ARRPOWEROKIN);
+	mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ARRPOWERONIN);
+	mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_POWEROKIN);
+	mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_POWERONIN);
+	mmio_clrbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ISO);
+	mmio_write_32(APBR_IDM_RESET_CONTROL, 0x0);
+	mmio_clrsetbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_SPEED_MASK,
+				AMAC_RPHY_1G_SPEED); /*1 Gbps line rate*/
+	/* 1000 datarate set */
+	mmio_setbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_1000_DATARATE);
+	/* full duplex */
+	mmio_setbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_FULL_DUPLEX);
+#ifdef EMULATION_SETUP
+	/* DLL bypass */
+	mmio_setbits_32(ICFG_AMAC_STRAP_CONFIG, ICFG_AMAC_STRAP_DLL_BYPASS);
+#endif
+	/* serdes full duplex */
+	mmio_setbits_32(ICFG_AMAC_MAC_CTRL_REG, ICFG_AMAC_MAC_FULL_DUPLEX);
+	mmio_clrsetbits_32(AMAC_IDM0_IO_CONTROL_DIRECT, AMAC_IDM0_ARCACHE_MASK,
+				AMAC_IDM0_ARCACHE_VAL);
+	mmio_clrsetbits_32(AMAC_IDM0_IO_CONTROL_DIRECT, AMAC_IDM0_AWCACHE_MASK,
+				AMAC_IDM0_AWCACHE_VAL);
+	INFO("amac init done\n");
+}
+#endif    /* USE_AMAC */
+
+static void brcm_stingray_pka_meminit(void)
+{
+	uintptr_t icfg_mem_ctrl = ICFG_PKA_MEM_PWR_CTRL;
+
+	VERBOSE("pka meminit start\n");
+
+	VERBOSE(" - arrpoweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONOUT))
+		;
+
+	VERBOSE(" - arrpowerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKOUT))
+		;
+
+	VERBOSE(" - poweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_PKA_MEM_PWR_CTRL__POWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_PKA_MEM_PWR_CTRL__POWERONOUT))
+		;
+
+	VERBOSE(" - powerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_PKA_MEM_PWR_CTRL__POWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_PKA_MEM_PWR_CTRL__POWEROKOUT))
+		;
+
+	/* Wait sometime */
+	mdelay(1);
+
+	VERBOSE(" - remove isolation\n");
+	mmio_clrbits_32(icfg_mem_ctrl, ICFG_PKA_MEM_PWR_CTRL__ISO);
+
+	INFO("pka meminit done\n");
+}
+
+static void brcm_stingray_smmu_init(void)
+{
+	unsigned int val;
+	uintptr_t smmu_base = SMMU_BASE;
+
+	VERBOSE("smmu init start\n");
+
+	/* Configure SCR0 */
+	VERBOSE(" - configure scr0\n");
+	val = mmio_read_32(smmu_base + 0x0);
+	val |= (0x1 << 12);
+	mmio_write_32(smmu_base + 0x0, val);
+
+	/* Reserve context banks for secure masters */
+	arm_smmu_reserve_secure_cntxt();
+
+	/* Print configuration */
+	VERBOSE(" - scr0=0x%x scr1=0x%x scr2=0x%x\n",
+		mmio_read_32(smmu_base + 0x0),
+		mmio_read_32(smmu_base + 0x4),
+		mmio_read_32(smmu_base + 0x8));
+
+	VERBOSE(" - idr0=0x%x idr1=0x%x idr2=0x%x\n",
+		mmio_read_32(smmu_base + 0x20),
+		mmio_read_32(smmu_base + 0x24),
+		mmio_read_32(smmu_base + 0x28));
+
+	VERBOSE(" - idr3=0x%x idr4=0x%x idr5=0x%x\n",
+		mmio_read_32(smmu_base + 0x2c),
+		mmio_read_32(smmu_base + 0x30),
+		mmio_read_32(smmu_base + 0x34));
+
+	VERBOSE(" - idr6=0x%x idr7=0x%x\n",
+		mmio_read_32(smmu_base + 0x38),
+		mmio_read_32(smmu_base + 0x3c));
+
+	INFO("smmu init done\n");
+}
+
+static void brcm_stingray_dma_pl330_meminit(void)
+{
+	uintptr_t icfg_mem_ctrl = ICFG_DMAC_MEM_PWR_CTRL;
+
+	VERBOSE("dmac meminit start\n");
+
+	VERBOSE(" - arrpoweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONOUT))
+		;
+
+	VERBOSE(" - arrpowerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKOUT))
+		;
+
+	VERBOSE(" - poweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_DMAC_MEM_PWR_CTRL__POWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_DMAC_MEM_PWR_CTRL__POWERONOUT))
+		;
+
+	VERBOSE(" - powerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_DMAC_MEM_PWR_CTRL__POWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_DMAC_MEM_PWR_CTRL__POWEROKOUT))
+		;
+
+	/* Wait sometime */
+	mdelay(1);
+
+	VERBOSE(" - remove isolation\n");
+	mmio_clrbits_32(icfg_mem_ctrl, ICFG_DMAC_MEM_PWR_CTRL__ISO);
+
+	INFO("dmac meminit done\n");
+}
+
+/* program the crmu access ranges for allowing non sec access*/
+static void brcm_stingray_crmu_access_init(void)
+{
+	/* Enable 0x6641c001 - 0x6641c701 for non secure access */
+	mmio_write_32(CRMU_CORE_ADDR_RANGE0_LOW, 0x6641c001);
+	mmio_write_32(CRMU_CORE_ADDR_RANGE0_LOW + 0x4, 0x6641c701);
+
+	/* Enable 0x6641d001 - 0x66424b01 for non secure access */
+	mmio_write_32(CRMU_CORE_ADDR_RANGE1_LOW, 0x6641d001);
+	mmio_write_32(CRMU_CORE_ADDR_RANGE1_LOW + 0x4, 0x66424b01);
+
+	/* Enable 0x66425001 - 0x66425f01 for non secure access */
+	mmio_write_32(CRMU_CORE_ADDR_RANGE2_LOW, 0x66425001);
+	mmio_write_32(CRMU_CORE_ADDR_RANGE2_LOW + 0x4, 0x66425f01);
+
+	INFO("crmu access init done\n");
+}
+
+static void brcm_stingray_scr_init(void)
+{
+	unsigned int val;
+	uintptr_t scr_base = SCR_BASE;
+	unsigned int clr_mask = SCR_AXCACHE_CONFIG_MASK;
+	unsigned int set_mask = SCR_TBUX_AXCACHE_CONFIG;
+
+	VERBOSE("scr init start\n");
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0x0, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0x0);
+	VERBOSE(" - set tbu0_config=0x%x\n", val);
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0x4, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0x4);
+	VERBOSE(" - set tbu1_config=0x%x\n", val);
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0x8, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0x8);
+	VERBOSE(" - set tbu2_config=0x%x\n", val);
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0xc, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0xc);
+	VERBOSE(" - set tbu3_config=0x%x\n", val);
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0x10, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0x10);
+	VERBOSE(" - set tbu4_config=0x%x\n", val);
+
+	/* awdomain=0x0 and ardomain=0x0 */
+	mmio_clrbits_32(scr_base + 0x14, clr_mask);
+	val = mmio_read_32(scr_base + 0x14);
+	VERBOSE(" - set gic_config=0x%x\n", val);
+
+	INFO("scr init done\n");
+}
+
+static void brcm_stingray_hsls_tzpcprot_init(void)
+{
+	unsigned int val;
+	uintptr_t tzpcdecprot_base = HSLS_TZPC_BASE;
+
+	VERBOSE("hsls tzpcprot init start\n");
+
+	/* Treat third-party masters as non-secured */
+	val = 0;
+	val |= BIT(6); /* SDIO1 */
+	val |= BIT(5); /* SDIO0 */
+	val |= BIT(0); /* AMAC */
+	mmio_write_32(tzpcdecprot_base + 0x810, val);
+
+	/* Print TZPC decode status registers */
+	VERBOSE(" - tzpcdecprot0=0x%x\n",
+		mmio_read_32(tzpcdecprot_base + 0x800));
+
+	VERBOSE(" - tzpcdecprot1=0x%x\n",
+		mmio_read_32(tzpcdecprot_base + 0x80c));
+
+	INFO("hsls tzpcprot init done\n");
+}
+
+#ifdef USE_I2S
+#define ICFG_AUDIO_POWER_CTRL			(HSLS_ICFG_REGS_BASE + 0xaa8)
+#define ICFG_AUDIO_POWER_CTRL__POWERONIN	BIT(0)
+#define ICFG_AUDIO_POWER_CTRL__POWEROKIN	BIT(1)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWERONIN	BIT(2)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWEROKIN	BIT(3)
+#define ICFG_AUDIO_POWER_CTRL__POWERONOUT	BIT(4)
+#define ICFG_AUDIO_POWER_CTRL__POWEROKOUT	BIT(5)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWERONOUT	BIT(6)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWEROKOUT	BIT(7)
+#define ICFG_AUDIO_POWER_CTRL__ISO		BIT(8)
+#define ICFG_AUDIO_SID_CONTROL			(HSLS_ICFG_REGS_BASE + 0xaf8)
+#define ICFG_AUDIO_SID_SHIFT			5
+#define ICFG_AUDIO_SID_AWADDR_OFFSET		0x0
+#define ICFG_AUDIO_SID_ARADDR_OFFSET		0x4
+
+#define I2S_RESET_CONTROL        (HSLS_IDM_REGS_BASE + 0x1800)
+#define I2S_IDM_IO_CONTROL       (HSLS_IDM_REGS_BASE + 0x1408)
+#define IO_CONTROL_CLK_ENABLE    BIT(0)
+#define I2S_IDM0_ARCACHE_OFFSET  16
+#define I2S_IDM0_AWCACHE_OFFSET  20
+#define I2S_IDM0_ARCACHE_MASK    (0xF << I2S_IDM0_ARCACHE_OFFSET)
+#define I2S_IDM0_AWCACHE_MASK    (0xF << I2S_IDM0_AWCACHE_OFFSET)
+/* ARCACHE - AWCACHE is 0x22 Normal Non-cacheable Non-bufferable. */
+#define I2S_IDM0_ARCACHE_VAL     (0x2 << I2S_IDM0_ARCACHE_OFFSET)
+#define I2S_IDM0_AWCACHE_VAL     (0x2 << I2S_IDM0_AWCACHE_OFFSET)
+
+static void brcm_stingray_audio_init(void)
+{
+	unsigned int val;
+	uintptr_t icfg_mem_ctrl = ICFG_AUDIO_POWER_CTRL;
+	uintptr_t icfg_audio_sid = ICFG_AUDIO_SID_CONTROL;
+
+	mmio_write_32(I2S_RESET_CONTROL, 0x0);
+
+	mmio_clrsetbits_32(I2S_IDM_IO_CONTROL, I2S_IDM0_ARCACHE_MASK,
+			   I2S_IDM0_ARCACHE_VAL);
+
+	mmio_clrsetbits_32(I2S_IDM_IO_CONTROL, I2S_IDM0_AWCACHE_MASK,
+			   I2S_IDM0_AWCACHE_VAL);
+
+	mmio_setbits_32(I2S_IDM_IO_CONTROL, IO_CONTROL_CLK_ENABLE);
+
+	VERBOSE("audio meminit start\n");
+
+	VERBOSE(" - configure stream_id = 0x6001\n");
+	val = SR_SID_VAL(0x3, 0x0, 0x1) << ICFG_AUDIO_SID_SHIFT;
+	mmio_write_32(icfg_audio_sid + ICFG_AUDIO_SID_AWADDR_OFFSET, val);
+	mmio_write_32(icfg_audio_sid + ICFG_AUDIO_SID_ARADDR_OFFSET, val);
+
+	VERBOSE(" - arrpoweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_AUDIO_POWER_CTRL__ARRPOWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_AUDIO_POWER_CTRL__ARRPOWERONOUT))
+		;
+
+	VERBOSE(" - arrpowerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_AUDIO_POWER_CTRL__ARRPOWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_AUDIO_POWER_CTRL__ARRPOWEROKOUT))
+		;
+
+	VERBOSE(" - poweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_AUDIO_POWER_CTRL__POWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_AUDIO_POWER_CTRL__POWERONOUT))
+		;
+
+	VERBOSE(" - powerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_AUDIO_POWER_CTRL__POWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_AUDIO_POWER_CTRL__POWEROKOUT))
+		;
+
+	/* Wait sometime */
+	mdelay(1);
+
+	VERBOSE(" - remove isolation\n");
+	mmio_clrbits_32(icfg_mem_ctrl, ICFG_AUDIO_POWER_CTRL__ISO);
+
+	INFO("audio meminit done\n");
+}
+#endif    /* USE_I2S */
+
+/*
+ * These defines do not match the regfile but they are renamed in a way such
+ * that they are much more readible
+ */
+
+#define SCR_GPV_SMMU_NS			(SCR_GPV_BASE + 0x28)
+#define SCR_GPV_GIC500_NS		(SCR_GPV_BASE + 0x34)
+#define HSLS_GPV_NOR_S0_NS		(HSLS_GPV_BASE + 0x14)
+#define HSLS_GPV_IDM1_NS		(HSLS_GPV_BASE + 0x18)
+#define HSLS_GPV_IDM2_NS		(HSLS_GPV_BASE + 0x1c)
+#define HSLS_SDIO0_SLAVE_NS		(HSLS_GPV_BASE + 0x20)
+#define HSLS_SDIO1_SLAVE_NS		(HSLS_GPV_BASE + 0x24)
+#define HSLS_GPV_APBY_NS		(HSLS_GPV_BASE + 0x2c)
+#define HSLS_GPV_APBZ_NS		(HSLS_GPV_BASE + 0x30)
+#define HSLS_GPV_APBX_NS		(HSLS_GPV_BASE + 0x34)
+#define HSLS_GPV_APBS_NS		(HSLS_GPV_BASE + 0x38)
+#define HSLS_GPV_QSPI_S0_NS		(HSLS_GPV_BASE + 0x68)
+#define HSLS_GPV_APBR_NS		(HSLS_GPV_BASE + 0x6c)
+#define FS4_CRYPTO_GPV_RM_SLAVE_NS	(FS4_CRYPTO_GPV_BASE + 0x8)
+#define FS4_CRYPTO_GPV_APB_SWITCH_NS	(FS4_CRYPTO_GPV_BASE + 0xc)
+#define FS4_RAID_GPV_RM_SLAVE_NS	(FS4_RAID_GPV_BASE + 0x8)
+#define FS4_RAID_GPV_APB_SWITCH_NS	(FS4_RAID_GPV_BASE + 0xc)
+#define FS4_CRYPTO_IDM_NS		(NIC400_FS_NOC_ROOT + 0x1c)
+#define FS4_RAID_IDM_NS			(NIC400_FS_NOC_ROOT + 0x28)
+
+#define FS4_CRYPTO_RING_COUNT          32
+#define FS4_CRYPTO_DME_COUNT           10
+#define FS4_CRYPTO_AE_COUNT            10
+#define FS4_CRYPTO_START_STREAM_ID     0x4000
+#define FS4_CRYPTO_MSI_DEVICE_ID       0x4100
+
+#define FS4_RAID_RING_COUNT            32
+#define FS4_RAID_DME_COUNT             8
+#define FS4_RAID_AE_COUNT              8
+#define FS4_RAID_START_STREAM_ID       0x4200
+#define FS4_RAID_MSI_DEVICE_ID         0x4300
+
+#define FS6_PKI_AXI_SLAVE_NS \
+		(NIC400_FS_NOC_ROOT + NIC400_FS_NOC_SECURITY2_OFFSET)
+
+#define FS6_PKI_AE_DME_APB_NS \
+		(NIC400_FS_NOC_ROOT + NIC400_FS_NOC_SECURITY7_OFFSET)
+#define FS6_PKI_IDM_IO_CONTROL_DIRECT	0x0
+#define FS6_PKI_IDM_RESET_CONTROL	0x0
+#define FS6_PKI_RING_COUNT		32
+#define FS6_PKI_DME_COUNT		1
+#define FS6_PKI_AE_COUNT		4
+#define FS6_PKI_START_STREAM_ID		0x4000
+#define FS6_PKI_MSI_DEVICE_ID		0x4100
+
+static void brcm_stingray_security_init(void)
+{
+	unsigned int val;
+
+	val = mmio_read_32(SCR_GPV_SMMU_NS);
+	val |= BIT(0);				/* SMMU NS = 1 */
+	mmio_write_32(SCR_GPV_SMMU_NS, val);
+
+	val = mmio_read_32(SCR_GPV_GIC500_NS);
+	val |= BIT(0);				/* GIC-500 NS = 1 */
+	mmio_write_32(SCR_GPV_GIC500_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_NOR_S0_NS);
+	val |= BIT(0);				/* NOR SLAVE NS = 1 */
+	mmio_write_32(HSLS_GPV_NOR_S0_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_IDM1_NS);
+	val |= BIT(0);				/* DMA IDM NS = 1 */
+	val |= BIT(1);				/* I2S IDM NS = 1 */
+	val |= BIT(2);				/* AMAC IDM NS = 1 */
+	val |= BIT(3);				/* SDIO0 IDM NS = 1 */
+	val |= BIT(4);				/* SDIO1 IDM NS = 1 */
+	val |= BIT(5);				/* DS_3 IDM NS = 1 */
+	mmio_write_32(HSLS_GPV_IDM1_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_IDM2_NS);
+	val |= BIT(2);				/* QSPI IDM NS = 1 */
+	val |= BIT(1);				/* NOR IDM NS = 1 */
+	val |= BIT(0);				/* NAND IDM NS = 1 */
+	mmio_write_32(HSLS_GPV_IDM2_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBY_NS);
+	val |= BIT(10);				/* I2S NS = 1 */
+	val |= BIT(4);				/* IOPAD NS = 1 */
+	val |= 0xf;				/* UARTx NS = 1 */
+	mmio_write_32(HSLS_GPV_APBY_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBZ_NS);
+	val |= BIT(2);			/* RNG NS = 1 */
+	mmio_write_32(HSLS_GPV_APBZ_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBS_NS);
+	val |= 0x3;				/* SPIx NS = 1 */
+	mmio_write_32(HSLS_GPV_APBS_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBR_NS);
+	val |= BIT(7);				/* QSPI APB NS = 1 */
+	val |= BIT(6);				/* NAND APB NS = 1 */
+	val |= BIT(5);				/* NOR APB NS = 1 */
+	val |= BIT(4);				/* AMAC APB NS = 1 */
+	val |= BIT(1);				/* DMA S1 APB NS = 1 */
+	mmio_write_32(HSLS_GPV_APBR_NS, val);
+
+	val = mmio_read_32(HSLS_SDIO0_SLAVE_NS);
+	val |= BIT(0);				/* SDIO0 NS = 1 */
+	mmio_write_32(HSLS_SDIO0_SLAVE_NS, val);
+
+	val = mmio_read_32(HSLS_SDIO1_SLAVE_NS);
+	val |= BIT(0);				/* SDIO1 NS = 1 */
+	mmio_write_32(HSLS_SDIO1_SLAVE_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBX_NS);
+	val |= BIT(14);				/* SMBUS1 NS = 1 */
+	val |= BIT(13);				/* GPIO NS = 1 */
+	val |= BIT(12);				/* WDT NS = 1 */
+	val |= BIT(11);				/* SMBUS0 NS = 1 */
+	val |= BIT(10);				/* Timer7 NS = 1 */
+	val |= BIT(9);				/* Timer6 NS = 1 */
+	val |= BIT(8);				/* Timer5 NS = 1 */
+	val |= BIT(7);				/* Timer4 NS = 1 */
+	val |= BIT(6);				/* Timer3 NS = 1 */
+	val |= BIT(5);				/* Timer2 NS = 1 */
+	val |= BIT(4);				/* Timer1 NS = 1 */
+	val |= BIT(3);				/* Timer0 NS = 1 */
+	val |= BIT(2);				/* MDIO NS = 1 */
+	val |= BIT(1);				/* PWM NS = 1 */
+	mmio_write_32(HSLS_GPV_APBX_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_QSPI_S0_NS);
+	val |= BIT(0);				/* QSPI NS = 1 */
+	mmio_write_32(HSLS_GPV_QSPI_S0_NS, val);
+
+#ifdef USE_FS4
+	val = 0x1;				/* FS4 Crypto rm_slave */
+	mmio_write_32(FS4_CRYPTO_GPV_RM_SLAVE_NS, val);
+	val = 0x1;				/* FS4 Crypto apb_switch */
+	mmio_write_32(FS4_CRYPTO_GPV_APB_SWITCH_NS, val);
+
+	val = 0x1;				/* FS4 Raid rm_slave */
+	mmio_write_32(FS4_RAID_GPV_RM_SLAVE_NS, val);
+	val = 0x1;				/* FS4 Raid apb_switch */
+	mmio_write_32(FS4_RAID_GPV_APB_SWITCH_NS, val);
+
+	val = 0x1;				/* FS4 Crypto IDM */
+	mmio_write_32(FS4_CRYPTO_IDM_NS, val);
+	val = 0x1;				/* FS4 RAID IDM */
+	mmio_write_32(FS4_RAID_IDM_NS, val);
+#endif
+
+#ifdef BL31_CCN_NONSECURE
+	/* Enable non-secure access to CCN registers */
+	mmio_write_32(OLY_MN_REGISTERS_NODE0_SECURE_ACCESS, 0x1);
+#endif
+
+#ifdef DDR_CTRL_PHY_NONSECURE
+	mmio_write_32(SCR_NOC_DDR_REGISTER_ACCESS, 0x1);
+#endif
+
+	paxc_mhb_ns_init();
+
+	/* unlock scr idm for non secure access */
+	mmio_write_32(SCR_NOC_SECURITY0, 0xffffffff);
+
+	INFO("security init done\r\n");
+}
+
+void brcm_gpio_pad_ns_init(void)
+{
+	/* configure all GPIO pads for non secure world access*/
+	mmio_write_32(GPIO_S_CNTRL_REG, 0xffffffff); /* 128-140 gpio pads */
+	mmio_write_32(GPIO_S_CNTRL_REG + 0x4, 0xffffffff); /* 96-127 gpio pad */
+	mmio_write_32(GPIO_S_CNTRL_REG + 0x8, 0xffffffff); /* 64-95 gpio pad */
+	mmio_write_32(GPIO_S_CNTRL_REG + 0xc, 0xffffffff); /* 32-63 gpio pad */
+	mmio_write_32(GPIO_S_CNTRL_REG + 0x10, 0xffffffff); /* 0-31 gpio pad */
+}
+
+#ifndef USE_DDR
+static void brcm_stingray_sram_ns_init(void)
+{
+	uintptr_t sram_root = TZC400_FS_SRAM_ROOT;
+	uintptr_t noc_root = NIC400_FS_NOC_ROOT;
+
+	mmio_write_32(sram_root + GATE_KEEPER_OFFSET, 1);
+	mmio_write_32(sram_root + REGION_ATTRIBUTES_0_OFFSET, 0xc0000000);
+	mmio_write_32(sram_root + REGION_ID_ACCESS_0_OFFSET, 0x00010001);
+	mmio_write_32(noc_root + NIC400_FS_NOC_SECURITY4_OFFSET, 0x1);
+	INFO(" stingray sram ns init done.\n");
+}
+#endif
+
+static void ccn_pre_init(void)
+{
+	/*
+	 * Set WFC bit of RN-I nodes where FS4 is connected.
+	 * This is required inorder to wait for read/write requests
+	 * completion acknowledgment. Otherwise FS4 Ring Manager is
+	 * getting stale data because of re-ordering of read/write
+	 * requests at CCN level
+	 */
+	mmio_setbits_32(OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL,
+			OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WFC);
+}
+
+static void ccn_post_init(void)
+{
+	mmio_setbits_32(OLY_HNI_REGISTERS_NODE0_PCIERC_RNI_NODEID_LIST,
+			SRP_RNI_PCIE_CONNECTED);
+	mmio_setbits_32(OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL,
+			SA_AUX_CTL_SER_DEVNE_WR);
+
+	mmio_clrbits_32(OLY_HNI_REGISTERS_NODE0_POS_CONTROL,
+			POS_CONTROL_HNI_POS_EN);
+	mmio_clrbits_32(OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL,
+			SA_AUX_CTL_POS_EARLY_WR_COMP_EN);
+}
+
+#ifndef BL31_BOOT_PRELOADED_SCP
+static void crmu_init(void)
+{
+	/*
+	 * Configure CRMU for using SMMU
+	 */
+
+	/*Program CRMU Stream ID */
+	mmio_write_32(CRMU_MASTER_AXI_ARUSER_CONFIG,
+			(CRMU_STREAM_ID << CRMU_SID_SHIFT));
+	mmio_write_32(CRMU_MASTER_AXI_AWUSER_CONFIG,
+			(CRMU_STREAM_ID << CRMU_SID_SHIFT));
+
+	/* Create Identity mapping */
+	arm_smmu_create_identity_map(DOMAIN_CRMU);
+
+	/* Enable Client Port for Secure Masters*/
+	arm_smmu_enable_secure_client_port();
+}
+#endif
+
+static void brcm_fsx_init(void)
+{
+#if defined(USE_FS4) && defined(USE_FS6)
+	#error "USE_FS4 and USE_FS6 should not be used together"
+#endif
+
+#ifdef USE_FS4
+	fsx_init(eFS4_CRYPTO, FS4_CRYPTO_RING_COUNT, FS4_CRYPTO_DME_COUNT,
+		FS4_CRYPTO_AE_COUNT, FS4_CRYPTO_START_STREAM_ID,
+		FS4_CRYPTO_MSI_DEVICE_ID, FS4_CRYPTO_IDM_IO_CONTROL_DIRECT,
+		FS4_CRYPTO_IDM_RESET_CONTROL, FS4_CRYPTO_BASE,
+		FS4_CRYPTO_DME_BASE);
+
+	fsx_init(eFS4_RAID, FS4_RAID_RING_COUNT, FS4_RAID_DME_COUNT,
+		FS4_RAID_AE_COUNT, FS4_RAID_START_STREAM_ID,
+		FS4_RAID_MSI_DEVICE_ID, FS4_RAID_IDM_IO_CONTROL_DIRECT,
+		FS4_RAID_IDM_RESET_CONTROL, FS4_RAID_BASE,
+		FS4_RAID_DME_BASE);
+
+	fsx_meminit("raid",
+		FS4_RAID_IDM_IO_CONTROL_DIRECT,
+		FS4_RAID_IDM_IO_STATUS);
+#endif
+}
+
+static void bcm_bl33_pass_info(void)
+{
+	struct bl33_info *info = (struct bl33_info *)BL33_SHARED_DDR_BASE;
+
+	if (sizeof(*info) > BL33_SHARED_DDR_SIZE)
+		WARN("bl33 shared area not reserved\n");
+
+	info->version = BL33_INFO_VERSION;
+	info->chip.chip_id = PLAT_CHIP_ID_GET;
+	info->chip.rev_id = PLAT_CHIP_REV_GET;
+}
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, CORTEX_A72_L2CTLR_EL1)
+
+void plat_bcm_bl31_early_platform_setup(void *from_bl2,
+					bl_params_t *plat_params_from_bl2)
+{
+#ifdef BL31_BOOT_PRELOADED_SCP
+	image_info_t scp_image_info;
+
+	scp_image_info.image_base = PRELOADED_SCP_BASE;
+	scp_image_info.image_size = PRELOADED_SCP_SIZE;
+	bcm_bl2_plat_handle_scp_bl2(&scp_image_info);
+#endif
+	/*
+	 * In BL31, logs are saved to DDR and we have much larger space to
+	 * store logs. We can now afford to save all logs >= the 'INFO' level
+	 */
+	bcm_elog_init((void *)BCM_ELOG_BL31_BASE, BCM_ELOG_BL31_SIZE,
+		      LOG_LEVEL_INFO);
+
+	INFO("L2CTLR = 0x%lx\n", read_l2ctlr_el1());
+
+	brcm_timer_sync_init();
+
+	brcm_stingray_dma_pl330_init();
+
+	brcm_stingray_dma_pl330_meminit();
+
+	brcm_stingray_spi_pl022_init(APBS_IDM_IDM_RESET_CONTROL);
+
+#ifdef USE_AMAC
+	brcm_stingray_amac_init();
+#endif
+
+	brcm_stingray_sdio_init();
+
+#ifdef NCSI_IO_DRIVE_STRENGTH_MA
+	brcm_stingray_ncsi_init();
+#endif
+
+#ifdef USE_USB
+	xhci_phy_init();
+#endif
+
+#ifdef USE_SATA
+	brcm_stingray_sata_init();
+#else
+	poweroff_sata_pll();
+#endif
+
+	ccn_pre_init();
+
+	brcm_fsx_init();
+
+	brcm_stingray_smmu_init();
+
+	brcm_stingray_pka_meminit();
+
+	brcm_stingray_crmu_access_init();
+
+	brcm_stingray_scr_init();
+
+	brcm_stingray_hsls_tzpcprot_init();
+
+#ifdef USE_I2S
+	brcm_stingray_audio_init();
+#endif
+
+	ccn_post_init();
+
+	paxb_init();
+
+	paxc_init();
+
+#ifndef BL31_BOOT_PRELOADED_SCP
+	crmu_init();
+#endif
+
+	/* Note: this should be last thing because
+	 * FS4 GPV registers only work after FS4 block
+	 * (i.e. crypto,raid,cop) is out of reset.
+	 */
+	brcm_stingray_security_init();
+
+	brcm_gpio_pad_ns_init();
+
+#ifndef USE_DDR
+	brcm_stingray_sram_ns_init();
+#endif
+
+#ifdef BL31_FORCE_CPU_FULL_FREQ
+	bcm_set_ihost_pll_freq(0x0, PLL_FREQ_FULL);
+#endif
+
+	brcm_stingray_gain_qspi_control();
+
+#ifdef USE_PAXC
+	/*
+	 * Check that the handshake has occurred and report ChiMP status.
+	 * This is required. Otherwise (especially on Palladium)
+	 * Linux might have booted to the pcie stage whereas
+	 * ChiMP has not yet booted. Note that nic_mode case has already
+	 * been considered above.
+	 */
+	if ((boot_source_get() != BOOT_SOURCE_QSPI) &&
+	    (!bcm_chimp_is_nic_mode()) &&
+	    (!bcm_chimp_wait_handshake())
+	   ) {
+		/* Does ChiMP report an error ? */
+		uint32_t err;
+
+		err = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG);
+		if ((err & CHIMP_ERROR_MASK) == 0)
+		/* ChiMP has not booted yet, but no error reported */
+			WARN("ChiMP not booted yet, but no error reported.\n");
+	}
+
+#if DEBUG
+	if (boot_source_get() != BOOT_SOURCE_QSPI)
+		INFO("Current ChiMP Status: 0x%x; bpe_mod reg: 0x%x\n"
+		     "fastboot register: 0x%x; handshake register 0x%x\n",
+		     bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG),
+		     bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG),
+		     bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
+		     bcm_chimp_read(CHIMP_REG_ECO_RESERVED));
+#endif /* DEBUG */
+#endif
+
+#ifdef FS4_DISABLE_CLOCK
+	flush_dcache_range(
+		PLAT_BRCM_TRUSTED_SRAM_BASE,
+		PLAT_BRCM_TRUSTED_SRAM_SIZE);
+	fs4_disable_clocks(true, true, true);
+#endif
+
+	/* pass information to BL33 through shared DDR region */
+	bcm_bl33_pass_info();
+
+	/*
+	 * We are not yet at the end of BL31, but we can stop log here so we do
+	 * not need to add 'bcm_elog_exit' to the standard BL31 code. The
+	 * benefit of capturing BL31 logs after this is very minimal in a
+	 * production system
+	 */
+	bcm_elog_exit();
+
+#if !BRCM_DISABLE_TRUSTED_WDOG
+	/*
+	 * Secure watchdog was started earlier in BL2, now it's time to stop
+	 * it
+	 */
+	sp805_stop(ARM_SP805_TWDG_BASE);
+#endif
+}
diff --git a/plat/brcm/board/stingray/src/brcm_pm_ops.c b/plat/brcm/board/stingray/src/brcm_pm_ops.c
new file mode 100644
index 0000000..090fbca
--- /dev/null
+++ b/plat/brcm/board/stingray/src/brcm_pm_ops.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/ccn.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+
+#include <brcm_scpi.h>
+#include <chimp.h>
+#include <cmn_plat_util.h>
+#include <plat_brcm.h>
+#include <platform_def.h>
+#include <sr_utils.h>
+
+#include "m0_cfg.h"
+
+
+#define CORE_PWR_STATE(state)	((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state)	\
+			((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state)	((state)->pwr_domain_state[MPIDR_AFFLVL2])
+
+#define VENDOR_RST_TYPE_SHIFT	4
+
+#if HW_ASSISTED_COHERENCY
+/*
+ * On systems where participant CPUs are cache-coherent, we can use spinlocks
+ * instead of bakery locks.
+ */
+spinlock_t event_lock;
+#define event_lock_get(_lock) spin_lock(&_lock)
+#define event_lock_release(_lock) spin_unlock(&_lock)
+
+#else
+/*
+ * Use bakery locks for state coordination as not all participants are
+ * cache coherent now.
+ */
+DEFINE_BAKERY_LOCK(event_lock);
+#define event_lock_get(_lock) bakery_lock_get(&_lock)
+#define event_lock_release(_lock) bakery_lock_release(&_lock)
+#endif
+
+static int brcm_pwr_domain_on(u_register_t mpidr)
+{
+	/*
+	 * SCP takes care of powering up parent power domains so we
+	 * only need to care about level 0
+	 */
+	scpi_set_brcm_power_state(mpidr, scpi_power_on, scpi_power_on,
+				  scpi_power_on);
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Handler called when a power level has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from. This handler would never be invoked with
+ * the system power domain uninitialized as either the primary would have taken
+ * care of it as part of cold boot or the first core awakened from system
+ * suspend would have already initialized it.
+ ******************************************************************************/
+static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
+
+	/* Assert that the system power domain need not be initialized */
+	assert(SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_RUN);
+
+	assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF);
+
+	/*
+	 * Perform the common cluster specific operations i.e enable coherency
+	 * if this cluster was off.
+	 */
+	if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) {
+		INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id);
+		ccn_enter_snoop_dvm_domain(1 << cluster_id);
+	}
+
+	/* Program the gic per-cpu distributor or re-distributor interface */
+	plat_brcm_gic_pcpu_init();
+
+	/* Enable the gic cpu interface */
+	plat_brcm_gic_cpuif_enable();
+}
+
+static void brcm_power_down_common(void)
+{
+	unsigned int standbywfil2, standbywfi;
+	uint64_t mpidr = read_mpidr_el1();
+
+	switch (MPIDR_AFFLVL1_VAL(mpidr)) {
+	case 0x0:
+		standbywfi = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI;
+		standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2;
+		break;
+	case 0x1:
+		standbywfi = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI;
+		standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2;
+		break;
+	case 0x2:
+		standbywfi = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI;
+		standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2;
+		break;
+	case 0x3:
+		standbywfi = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI;
+		standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2;
+		break;
+	default:
+		ERROR("Invalid cluster #%llx\n", MPIDR_AFFLVL1_VAL(mpidr));
+		return;
+	}
+	/* Clear the WFI status bit */
+	event_lock_get(event_lock);
+	mmio_setbits_32(CDRU_PROC_EVENT_CLEAR,
+			(1 << (standbywfi + MPIDR_AFFLVL0_VAL(mpidr))) |
+			(1 << standbywfil2));
+	event_lock_release(event_lock);
+}
+
+/*
+ * Helper function to inform power down state to SCP.
+ */
+static void brcm_scp_suspend(const psci_power_state_t *target_state)
+{
+	uint32_t cluster_state = scpi_power_on;
+	uint32_t system_state = scpi_power_on;
+
+	/* Check if power down at system power domain level is requested */
+	if (SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
+		system_state = scpi_power_retention;
+
+	/* Check if Cluster is to be turned off */
+	if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
+		cluster_state = scpi_power_off;
+
+	/*
+	 * Ask the SCP to power down the appropriate components depending upon
+	 * their state.
+	 */
+	scpi_set_brcm_power_state(read_mpidr_el1(),
+				  scpi_power_off,
+				  cluster_state,
+				  system_state);
+}
+
+/*
+ * Helper function to turn off a CPU power domain and its parent power domains
+ * if applicable. Since SCPI doesn't differentiate between OFF and suspend, we
+ * call the suspend helper here.
+ */
+static void brcm_scp_off(const psci_power_state_t *target_state)
+{
+	brcm_scp_suspend(target_state);
+}
+
+static void brcm_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr_el1());
+
+	assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF);
+	/* Prevent interrupts from spuriously waking up this cpu */
+	plat_brcm_gic_cpuif_disable();
+
+	/* Turn redistributor off */
+	plat_brcm_gic_redistif_off();
+
+	/* If Cluster is to be turned off, disable coherency */
+	if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
+		ccn_exit_snoop_dvm_domain(1 << cluster_id);
+
+	brcm_power_down_common();
+
+	brcm_scp_off(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when the CPU power domain is about to enter standby.
+ ******************************************************************************/
+static void brcm_cpu_standby(plat_local_state_t cpu_state)
+{
+	unsigned int scr;
+
+	assert(cpu_state == PLAT_LOCAL_STATE_RET);
+
+	scr = read_scr_el3();
+	/*
+	 * Enable the Non secure interrupt to wake the CPU.
+	 * In GICv3 affinity routing mode, the non secure group1 interrupts use
+	 * the PhysicalFIQ at EL3 whereas in GICv2, it uses the PhysicalIRQ.
+	 * Enabling both the bits works for both GICv2 mode and GICv3 affinity
+	 * routing mode.
+	 */
+	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+	isb();
+	dsb();
+	wfi();
+
+	/*
+	 * Restore SCR to the original value, synchronisation of scr_el3 is
+	 * done by eret while el3_exit to save some execution cycles.
+	 */
+	write_scr_el3(scr);
+}
+
+/*
+ * Helper function to shutdown the system via SCPI.
+ */
+static void __dead2 brcm_scp_sys_shutdown(void)
+{
+	/*
+	 * Disable GIC CPU interface to prevent pending interrupt
+	 * from waking up the AP from WFI.
+	 */
+	plat_brcm_gic_cpuif_disable();
+
+	/* Flush and invalidate data cache */
+	dcsw_op_all(DCCISW);
+
+	/* Bring Cluster out of coherency domain as its going to die */
+	plat_brcm_interconnect_exit_coherency();
+
+	brcm_power_down_common();
+
+	/* Send the power down request to the SCP */
+	scpi_sys_power_state(scpi_system_shutdown);
+
+	wfi();
+	ERROR("BRCM System Off: operation not handled.\n");
+	panic();
+}
+
+/*
+ * Helper function to reset the system
+ */
+static void __dead2 brcm_scp_sys_reset(unsigned int reset_type)
+{
+	/*
+	 * Disable GIC CPU interface to prevent pending interrupt
+	 * from waking up the AP from WFI.
+	 */
+	plat_brcm_gic_cpuif_disable();
+
+	/* Flush and invalidate data cache */
+	dcsw_op_all(DCCISW);
+
+	/* Bring Cluster out of coherency domain as its going to die */
+	plat_brcm_interconnect_exit_coherency();
+
+	brcm_power_down_common();
+
+	/* Send the system reset request to the SCP
+	 *
+	 * As per PSCI spec system power state could be
+	 * 0-> Shutdown
+	 * 1-> Reboot- Board level Reset
+	 * 2-> Reset - SoC level Reset
+	 *
+	 * Spec allocates 8 bits, 2 nibble, for this. One nibble is sufficient
+	 * for sending the state hence We are utilizing 2nd nibble for vendor
+	 * define reset type.
+	 */
+	scpi_sys_power_state((reset_type << VENDOR_RST_TYPE_SHIFT) |
+			     scpi_system_reboot);
+
+	wfi();
+	ERROR("BRCM System Reset: operation not handled.\n");
+	panic();
+}
+
+static void __dead2 brcm_system_reset(void)
+{
+	unsigned int reset_type;
+
+	if (bcm_chimp_is_nic_mode())
+		reset_type = SOFT_RESET_L3;
+	else
+		reset_type = SOFT_SYS_RESET_L1;
+
+	brcm_scp_sys_reset(reset_type);
+}
+
+static int brcm_system_reset2(int is_vendor, int reset_type,
+		      u_register_t cookie)
+{
+	if (!is_vendor) {
+		/* Architectural warm boot: only warm reset is supported */
+		reset_type = SOFT_RESET_L3;
+	} else {
+		uint32_t boot_source = (uint32_t)cookie;
+
+		boot_source &= BOOT_SOURCE_MASK;
+		brcm_stingray_set_straps(boot_source);
+	}
+	brcm_scp_sys_reset(reset_type);
+
+	/*
+	 * brcm_scp_sys_reset cannot return (it is a __dead function),
+	 * but brcm_system_reset2 has to return some value, even in
+	 * this case.
+	 */
+	return 0;
+}
+
+static int brcm_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+	/*
+	 * Check if the non secure entrypoint lies within the non
+	 * secure DRAM.
+	 */
+	if ((entrypoint >= BRCM_NS_DRAM1_BASE) &&
+	    (entrypoint < (BRCM_NS_DRAM1_BASE + BRCM_NS_DRAM1_SIZE)))
+		return PSCI_E_SUCCESS;
+#ifndef AARCH32
+	if ((entrypoint >= BRCM_DRAM2_BASE) &&
+	    (entrypoint < (BRCM_DRAM2_BASE + BRCM_DRAM2_SIZE)))
+		return PSCI_E_SUCCESS;
+
+	if ((entrypoint >= BRCM_DRAM3_BASE) &&
+	    (entrypoint < (BRCM_DRAM3_BASE + BRCM_DRAM3_SIZE)))
+		return PSCI_E_SUCCESS;
+#endif
+
+	return PSCI_E_INVALID_ADDRESS;
+}
+
+/*******************************************************************************
+ * ARM standard platform handler called to check the validity of the power state
+ * parameter.
+ ******************************************************************************/
+static int brcm_validate_power_state(unsigned int power_state,
+			    psci_power_state_t *req_state)
+{
+	int pstate = psci_get_pstate_type(power_state);
+	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+	int i;
+
+	assert(req_state);
+
+	if (pwr_lvl > PLAT_MAX_PWR_LVL)
+		return PSCI_E_INVALID_PARAMS;
+
+	/* Sanity check the requested state */
+	if (pstate == PSTATE_TYPE_STANDBY) {
+		/*
+		 * It's possible to enter standby only on power level 0
+		 * Ignore any other power level.
+		 */
+		if (pwr_lvl != MPIDR_AFFLVL0)
+			return PSCI_E_INVALID_PARAMS;
+
+		req_state->pwr_domain_state[MPIDR_AFFLVL0] =
+					PLAT_LOCAL_STATE_RET;
+	} else {
+		for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
+			req_state->pwr_domain_state[i] =
+					PLAT_LOCAL_STATE_OFF;
+	}
+
+	/*
+	 * We expect the 'state id' to be zero.
+	 */
+	if (psci_get_pstate_id(power_state))
+		return PSCI_E_INVALID_PARAMS;
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard
+ * platform will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+plat_psci_ops_t plat_brcm_psci_pm_ops = {
+	.pwr_domain_on		= brcm_pwr_domain_on,
+	.pwr_domain_on_finish	= brcm_pwr_domain_on_finish,
+	.pwr_domain_off		= brcm_pwr_domain_off,
+	.cpu_standby		= brcm_cpu_standby,
+	.system_off		= brcm_scp_sys_shutdown,
+	.system_reset		= brcm_system_reset,
+	.system_reset2		= brcm_system_reset2,
+	.validate_ns_entrypoint = brcm_validate_ns_entrypoint,
+	.validate_power_state	= brcm_validate_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const struct plat_psci_ops **psci_ops)
+{
+	*psci_ops = &plat_brcm_psci_pm_ops;
+
+	/* Setup mailbox with entry point. */
+	mmio_write_64(CRMU_CFG_BASE + offsetof(M0CFG, core_cfg.rvbar),
+		      sec_entrypoint);
+
+	return 0;
+}
diff --git a/plat/brcm/board/stingray/src/fsx.c b/plat/brcm/board/stingray/src/fsx.c
new file mode 100644
index 0000000..5725a2e
--- /dev/null
+++ b/plat/brcm/board/stingray/src/fsx.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/common_def.h>
+
+#include <fsx.h>
+#include <platform_def.h>
+#include <sr_utils.h>
+
+#define FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN		0
+
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON		11
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK		12
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON	13
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK	14
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO		15
+#define FS4_IDM_IO_CONTROL_DIRECT__CLK_EN		31
+
+#define FS4_IDM_IO_STATUS__MEM_POWERON			0
+#define FS4_IDM_IO_STATUS__MEM_POWEROK			1
+#define FS4_IDM_IO_STATUS__MEM_ARRPOWERON		2
+#define FS4_IDM_IO_STATUS__MEM_ARRPOWEROK		3
+#define FS4_IDM_IO_STATUS__MEM_ALLOK			0xf
+
+#define FS4_IDM_RESET_CONTROL__RESET			0
+
+#define FSX_RINGx_BASE(__b, __i)			\
+		((__b) + (__i) * 0x10000)
+
+#define FSX_RINGx_VERSION_NUMBER(__b, __i)		\
+		(FSX_RINGx_BASE(__b, __i) + 0x0)
+
+#define FSX_RINGx_MSI_DEV_ID(__b, __i)			\
+		(FSX_RINGx_BASE(__b, __i) + 0x44)
+
+#define FSX_COMM_RINGx_BASE(__b, __i)			\
+		((__b) + 0x200000 + (__i) * 0x100)
+
+#define FSX_COMM_RINGx_CONTROL(__b, __i)		\
+		(FSX_COMM_RINGx_BASE(__b, __i) + 0x0)
+#define FSX_COMM_RINGx_CONTROL__AXI_ID			8
+#define FSX_COMM_RINGx_CONTROL__AXI_ID_MASK		0x1f
+#define FSX_COMM_RINGx_CONTROL__PRIORITY		4
+#define FSX_COMM_RINGx_CONTROL__PRIORITY_MASK		0x7
+#define FSX_COMM_RINGx_CONTROL__AE_GROUP		0
+#define FSX_COMM_RINGx_CONTROL__AE_GROUP_MASK		0x7
+
+#define FSX_COMM_RINGx_MSI_DEV_ID(__b, __i)		\
+		(FSX_COMM_RINGx_BASE(__b, __i) + 0x4)
+
+#define FSX_AEx_BASE(__b, __i)				\
+		((__b) + 0x202000 + (__i) * 0x100)
+
+#define FSX_AEx_CONTROL_REGISTER(__b, __i)		\
+		(FSX_AEx_BASE(__b, __i) + 0x0)
+#define FSX_AEx_CONTROL_REGISTER__ACTIVE		4
+#define FSX_AEx_CONTROL_REGISTER__GROUP_ID		0
+#define FSX_AEx_CONTROL_REGISTER__GROUP_ID_MASK		0x7
+
+#define FSX_COMM_RM_RING_SECURITY_SETTING		0x0
+
+#define FSX_COMM_RM_SSID_CONTROL			0x4
+#define FSX_COMM_RM_SSID_CONTROL__RING_BITS		5
+#define FSX_COMM_RM_SSID_CONTROL__MASK			0x3ff
+
+#define FSX_COMM_RM_CONTROL_REGISTER			0x8
+#define FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE	2
+#define FSX_COMM_RM_CONTROL_REGISTER__AE_TIMEOUT	5
+#define FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING	7
+
+#define FSX_COMM_RM_TIMER_CONTROL_0			0xc
+#define FSX_COMM_RM_TIMER_CONTROL_0__FAST		16
+#define FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM		0
+
+#define FSX_COMM_RM_TIMER_CONTROL_1			0x10
+#define FSX_COMM_RM_TIMER_CONTROL_1__SLOW		16
+#define FSX_COMM_RM_TIMER_CONTROL_1__IDLE		0
+
+#define FSX_COMM_RM_BURST_BD_THRESHOLD			0x14
+#define FSX_COMM_RM_BURST_BD_THRESHOLD_LOW		0
+#define FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH		16
+
+#define FSX_COMM_RM_BURST_LENGTH			0x18
+#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN	16
+#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN_MASK	0x1ff
+#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE		0
+#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE_MASK	0x1ff
+
+#define FSX_COMM_RM_FIFO_THRESHOLD			0x1c
+#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL	16
+#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL_MASK	0x1ff
+#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL	0
+#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL_MASK	0x1f
+
+#define FSX_COMM_RM_AE_TIMEOUT				0x24
+
+#define FSX_COMM_RM_RING_FLUSH_TIMEOUT			0x2c
+
+#define FSX_COMM_RM_MEMORY_CONFIGURATION		0x30
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN	12
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN	13
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN	14
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN	15
+
+#define FSX_COMM_RM_AXI_CONTROL				0x34
+#define FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN	28
+#define FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN	24
+#define FSX_COMM_RM_AXI_CONTROL__AWQOS			20
+#define FSX_COMM_RM_AXI_CONTROL__ARQOS			16
+#define FSX_COMM_RM_AXI_CONTROL__AWPROT			12
+#define FSX_COMM_RM_AXI_CONTROL__ARPROT			8
+#define FSX_COMM_RM_AXI_CONTROL__AWCACHE		4
+#define FSX_COMM_RM_AXI_CONTROL__ARCACHE		0
+
+#define FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR	0x48
+
+#define FSX_COMM_RM_GROUP_PKT_EXTENSION_SUPPORT		0xc0
+
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD		0xc8
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MASK	0x1ff
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX	16
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN	0
+
+#define FSX_COMM_RM_GROUP_RING_COUNT			0xcc
+
+#define FSX_COMM_RM_MAIN_HW_INIT_DONE			0x12c
+#define FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK		0x1
+
+#define FSX_DMEx_BASE(__b, __i)				\
+		((__b) + (__i) * 0x1000)
+
+#define FSX_DMEx_AXI_CONTROL(__b, __i)			\
+		(FSX_DMEx_BASE(__b, __i) + 0x4)
+#define FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN		28
+#define FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN		24
+#define FSX_DMEx_AXI_CONTROL__AWQOS			20
+#define FSX_DMEx_AXI_CONTROL__ARQOS			16
+#define FSX_DMEx_AXI_CONTROL__AWCACHE			4
+#define FSX_DMEx_AXI_CONTROL__ARCACHE			0
+
+#define FSX_DMEx_WR_FIFO_THRESHOLD(__b, __i)		\
+		(FSX_DMEx_BASE(__b, __i) + 0xc)
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MASK		0x3ff
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MAX			10
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MIN			0
+
+#define FSX_DMEx_RD_FIFO_THRESHOLD(__b, __i)		\
+		(FSX_DMEx_BASE(__b, __i) + 0x14)
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MASK		0x3ff
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MAX			10
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MIN			0
+
+#define FS6_SUB_TOP_BASE				0x66D8F800
+#define FS6_PKI_DME_RESET				0x4
+#define PKI_DME_RESET					1
+
+char *fsx_type_names[] = {
+	"fs4-raid",
+	"fs4-crypto",
+	"fs6-pki",
+};
+
+void fsx_init(eFSX_TYPE fsx_type,
+	      unsigned int ring_count,
+	      unsigned int dme_count,
+	      unsigned int ae_count,
+	      unsigned int start_stream_id,
+	      unsigned int msi_dev_id,
+	      uintptr_t idm_io_control_direct,
+	      uintptr_t idm_reset_control,
+	      uintptr_t base,
+	      uintptr_t dme_base)
+{
+	int try;
+	unsigned int i, v, data;
+	uintptr_t fs4_idm_io_control_direct = idm_io_control_direct;
+	uintptr_t fs4_idm_reset_control = idm_reset_control;
+	uintptr_t fsx_comm_rm = (base + 0x203000);
+
+	VERBOSE("fsx %s init start\n", fsx_type_names[fsx_type]);
+
+	if (fsx_type == eFS4_RAID || fsx_type == eFS4_CRYPTO) {
+		/* Enable FSx engine clock */
+		VERBOSE(" - enable fsx clock\n");
+		mmio_write_32(fs4_idm_io_control_direct,
+		      (1U << FS4_IDM_IO_CONTROL_DIRECT__CLK_EN));
+		udelay(500);
+
+		/* Reset FSx engine */
+		VERBOSE(" - reset fsx\n");
+		v = mmio_read_32(fs4_idm_reset_control);
+		v |= (1 << FS4_IDM_RESET_CONTROL__RESET);
+		mmio_write_32(fs4_idm_reset_control, v);
+		udelay(500);
+		v = mmio_read_32(fs4_idm_reset_control);
+		v &= ~(1 << FS4_IDM_RESET_CONTROL__RESET);
+		mmio_write_32(fs4_idm_reset_control, v);
+	} else {
+		/*
+		 * Default RM and AE are out of reset,
+		 * So only DME Reset added here
+		 */
+		v = mmio_read_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET);
+		v &= ~(PKI_DME_RESET);
+		mmio_write_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET, v);
+	}
+
+	/* Wait for HW-init done */
+	VERBOSE(" - wait for HW-init done\n");
+	try = 10000;
+	do {
+		udelay(1);
+		data = mmio_read_32(fsx_comm_rm +
+				    FSX_COMM_RM_MAIN_HW_INIT_DONE);
+		try--;
+	} while (!(data & FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK) && (try > 0));
+
+	if (try <= 0)
+		ERROR("fsx_comm_rm + 0x%x: 0x%x\n",
+		      data, FSX_COMM_RM_MAIN_HW_INIT_DONE);
+
+	/* Make all rings non-secured */
+	VERBOSE(" - make all rings non-secured\n");
+	v = 0xffffffff;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_SECURITY_SETTING, v);
+
+	/* Set start stream-id for rings to */
+	VERBOSE(" - set start stream-id for rings to 0x%x\n",
+		start_stream_id);
+	v = start_stream_id >> FSX_COMM_RM_SSID_CONTROL__RING_BITS;
+	v &= FSX_COMM_RM_SSID_CONTROL__MASK;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_SSID_CONTROL, v);
+
+	/* Set timer configuration */
+	VERBOSE(" - set timer configuration\n");
+	v = 0x0271 << FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM;
+	v |= (0x0138 << FSX_COMM_RM_TIMER_CONTROL_0__FAST);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_0, v);
+	v = 0x09c4 << FSX_COMM_RM_TIMER_CONTROL_1__IDLE;
+	v |= (0x04e2 << FSX_COMM_RM_TIMER_CONTROL_1__SLOW);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_1, v);
+	v = 0x0000f424;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_FLUSH_TIMEOUT, v);
+
+	/* Set burst length and fifo threshold */
+	VERBOSE(" - set burst length, fifo and bd threshold\n");
+	v = 0x0;
+	v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN);
+	v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_LENGTH, v);
+	v = 0x0;
+	v |= (0x67 << FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL);
+	v |= (0x18 << FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_FIFO_THRESHOLD, v);
+	v = 0x0;
+	v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_LOW);
+	v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_BD_THRESHOLD, v);
+
+	/* Set memory configuration */
+	VERBOSE(" - set memory configuration\n");
+	v = 0x0;
+	v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN);
+	v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN);
+	v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN);
+	v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_MEMORY_CONFIGURATION, v);
+
+	/* AXI configuration for RM */
+	v = 0;
+	v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN);
+	v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN);
+	v |= (0xe << FSX_COMM_RM_AXI_CONTROL__AWQOS);
+	v |= (0xa << FSX_COMM_RM_AXI_CONTROL__ARQOS);
+	v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__AWPROT);
+	v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__ARPROT);
+	v |= (0xf << FSX_COMM_RM_AXI_CONTROL__AWCACHE);
+	v |= (0xf << FSX_COMM_RM_AXI_CONTROL__ARCACHE);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL, v);
+	VERBOSE(" - set AXI control = 0x%x\n",
+		mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL));
+	v = 0x0;
+	v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX);
+	v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD, v);
+	VERBOSE(" - set AXI read burst threshold = 0x%x\n",
+	mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD));
+
+	/* Configure group ring count for all groups */
+	/* By default we schedule extended packets
+	 * on all AEs/DMEs in a group.
+	 */
+	v = (dme_count & 0xf) << 0;
+	v |= (dme_count & 0xf) << 4;
+	v |= (dme_count & 0xf) << 8;
+	v |= (dme_count & 0xf) << 12;
+	v |= (dme_count & 0xf) << 16;
+	v |= (dme_count & 0xf) << 20;
+	v |= (dme_count & 0xf) << 24;
+	v |= (dme_count & 0xf) << 28;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_GROUP_RING_COUNT, v);
+
+	/*
+	 * Due to HW issue spurious interrupts are getting generated.
+	 * To fix sw needs to clear the config status interrupts
+	 * before setting CONFIG_DONE.
+	 */
+	mmio_write_32(fsx_comm_rm +
+		      FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR,
+		      0xffffffff);
+
+	/* Configure RM control */
+	VERBOSE(" - configure RM control\n");
+	v = mmio_read_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER);
+	v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v);
+	v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v);
+
+	/* Configure AE timeout */
+	VERBOSE(" - configure AE timeout\n");
+	v = 0x00003fff;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AE_TIMEOUT, v);
+
+	/* Initialize all AEs */
+	for (i = 0; i < ae_count; i++) {
+		VERBOSE(" - initialize AE%d\n", i);
+		v = (0x1 << FSX_AEx_CONTROL_REGISTER__ACTIVE);
+		mmio_write_32(FSX_AEx_CONTROL_REGISTER(base, i), v);
+	}
+
+	/* Initialize all DMEs */
+	for (i = 0; i < dme_count; i++) {
+		VERBOSE(" - initialize DME%d\n", i);
+		v = 0;
+		v |= (0x1 << FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN);
+		v |= (0x1 << FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN);
+		v |= (0xe << FSX_DMEx_AXI_CONTROL__AWQOS);
+		v |= (0xa << FSX_DMEx_AXI_CONTROL__ARQOS);
+		v |= (0xf << FSX_DMEx_AXI_CONTROL__AWCACHE);
+		v |= (0xf << FSX_DMEx_AXI_CONTROL__ARCACHE);
+		mmio_write_32(FSX_DMEx_AXI_CONTROL(dme_base, i), v);
+		VERBOSE(" -- AXI_CONTROL = 0x%x\n",
+		mmio_read_32(FSX_DMEx_AXI_CONTROL(dme_base, i)));
+		v = 0;
+		v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MIN);
+		v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MAX);
+		mmio_write_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i), v);
+		VERBOSE(" -- WR_FIFO_THRESHOLD = 0x%x\n",
+		mmio_read_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i)));
+		v = 0;
+		v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MIN);
+		v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MAX);
+		mmio_write_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i), v);
+		VERBOSE(" -- RD_FIFO_THRESHOLD = 0x%x\n",
+		mmio_read_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i)));
+	}
+
+	/* Configure ring axi id and msi device id */
+	for (i = 0; i < ring_count; i++) {
+		VERBOSE(" - ring%d version=0x%x\n", i,
+			mmio_read_32(FSX_RINGx_VERSION_NUMBER(base, i)));
+		mmio_write_32(FSX_COMM_RINGx_MSI_DEV_ID(base, i),
+			      msi_dev_id);
+		v = 0;
+		v |= ((i & FSX_COMM_RINGx_CONTROL__AXI_ID_MASK) <<
+		      FSX_COMM_RINGx_CONTROL__AXI_ID);
+		mmio_write_32(FSX_COMM_RINGx_CONTROL(base, i), v);
+	}
+
+	INFO("fsx %s init done\n", fsx_type_names[fsx_type]);
+}
+
+void fsx_meminit(const char *name,
+		 uintptr_t idm_io_control_direct,
+		 uintptr_t idm_io_status)
+{
+	int try;
+	unsigned int val;
+
+	VERBOSE("fsx %s meminit start\n", name);
+
+	VERBOSE(" - arrpoweron\n");
+	mmio_setbits_32(idm_io_control_direct,
+			BIT(FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON));
+	while (!(mmio_read_32(idm_io_status) &
+		 BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWERON)))
+		;
+
+	VERBOSE(" - arrpowerok\n");
+	mmio_setbits_32(idm_io_control_direct,
+			(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK));
+	while (!(mmio_read_32(idm_io_status) &
+		 BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWEROK)))
+		;
+
+	VERBOSE(" - poweron\n");
+	mmio_setbits_32(idm_io_control_direct,
+			(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON));
+	while (!(mmio_read_32(idm_io_status) &
+		 BIT(FS4_IDM_IO_STATUS__MEM_POWERON)))
+		;
+
+	VERBOSE(" - powerok\n");
+	mmio_setbits_32(idm_io_control_direct,
+			(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK));
+	while (!(mmio_read_32(idm_io_status) &
+		 BIT(FS4_IDM_IO_STATUS__MEM_POWEROK)))
+		;
+
+	/* Final check on all power bits */
+	try = 10;
+	do {
+		val = mmio_read_32(idm_io_status);
+		if (val == FS4_IDM_IO_STATUS__MEM_ALLOK)
+			break;
+
+		/* Wait sometime */
+		mdelay(1);
+
+		try--;
+	} while (try > 0);
+
+	/* Remove memory isolation if things are fine. */
+	if (try <= 0) {
+		INFO(" - powerup failed\n");
+	} else {
+		VERBOSE(" - remove isolation\n");
+		mmio_clrbits_32(idm_io_control_direct,
+				(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO));
+		VERBOSE(" - powerup done\n");
+	}
+
+	INFO("fsx %s meminit done\n", name);
+}
+
+void fs4_disable_clocks(bool disable_sram,
+			bool disable_crypto,
+			bool disable_raid)
+{
+	VERBOSE("fs4 disable clocks start\n");
+
+	if (disable_sram) {
+		VERBOSE(" - disable sram clock\n");
+		mmio_clrbits_32(FS4_SRAM_IDM_IO_CONTROL_DIRECT,
+			(1 << FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN));
+	}
+
+	if (disable_crypto) {
+		VERBOSE(" - disable crypto clock\n");
+		mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+				CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK);
+	}
+
+	if (disable_raid) {
+		VERBOSE(" - disable raid clock\n");
+		mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+				CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK);
+	}
+
+	if (disable_sram && disable_crypto && disable_raid) {
+		VERBOSE(" - disable root clock\n");
+		mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+				CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK);
+		mmio_setbits_32(CDRU_GENPLL2_CONTROL1,
+				CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK);
+	}
+
+	INFO("fs4 disable clocks done\n");
+}
diff --git a/plat/brcm/board/stingray/src/ihost_pm.c b/plat/brcm/board/stingray/src/ihost_pm.c
new file mode 100644
index 0000000..9141d3e
--- /dev/null
+++ b/plat/brcm/board/stingray/src/ihost_pm.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <dmu.h>
+#include <ihost_pm.h>
+#include <platform_def.h>
+
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST1			2
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST2			1
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST3			0
+#define CDRU_MISC_RESET_CONTROL__CDRU_IH1_RESET				9
+#define CDRU_MISC_RESET_CONTROL__CDRU_IH2_RESET				8
+#define CDRU_MISC_RESET_CONTROL__CDRU_IH3_RESET				7
+#define A72_CRM_SOFTRESETN_0						0x480
+#define A72_CRM_SOFTRESETN_1						0x484
+#define A72_CRM_DOMAIN_4_CONTROL					0x810
+#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_DFT			3
+#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_MEM			6
+#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_I_O			0
+#define A72_CRM_SUBSYSTEM_MEMORY_CONTROL_3				0xB4C
+#define MEMORY_PDA_HI_SHIFT						0x0
+#define A72_CRM_PLL_PWR_ON						0x70
+#define A72_CRM_PLL_PWR_ON__PLL0_ISO_PLLOUT				4
+#define A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO				1
+#define A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL				0
+#define A72_CRM_SUBSYSTEM_MEMORY_CONTROL_2				0xB48
+#define A72_CRM_PLL_INTERRUPT_STATUS					0x8c
+#define A72_CRM_PLL_INTERRUPT_STATUS__PLL0_LOCK_LOST_STATUS		8
+#define A72_CRM_PLL_INTERRUPT_STATUS__PLL0_LOCK_STATUS			9
+#define A72_CRM_INTERRUPT_ENABLE					0x4
+#define A72_CRM_INTERRUPT_ENABLE__PLL0_INT_ENABLE			4
+#define A72_CRM_PLL_INTERRUPT_ENABLE					0x88
+#define A72_CRM_PLL_INTERRUPT_ENABLE__PLL0_LOCK_STATUS_INT_ENB		9
+#define A72_CRM_PLL_INTERRUPT_ENABLE__PLL0_LOCK_LOST_STATUS_INT_ENB	8
+#define A72_CRM_PLL0_CFG0_CTRL						0x120
+#define A72_CRM_PLL0_CFG1_CTRL						0x124
+#define A72_CRM_PLL0_CFG2_CTRL						0x128
+#define A72_CRM_PLL0_CFG3_CTRL						0x12C
+#define A72_CRM_CORE_CONFIG_DBGCTRL__DBGROMADDRV			0
+#define A72_CRM_CORE_CONFIG_DBGCTRL					0xD50
+#define A72_CRM_CORE_CONFIG_DBGROM_LO					0xD54
+#define A72_CRM_CORE_CONFIG_DBGROM_HI					0xD58
+#define A72_CRM_SUBSYSTEM_CONFIG_1__DBGL1RSTDISABLE			2
+#define A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN			0
+#define A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN			1
+#define A72_CRM_AXI_CLK_DESC						0x304
+#define A72_CRM_ACP_CLK_DESC						0x308
+#define A72_CRM_ATB_CLK_DESC						0x30C
+#define A72_CRM_PCLKDBG_DESC						0x310
+#define A72_CRM_CLOCK_MODE_CONTROL					0x40
+#define A72_CRM_CLOCK_MODE_CONTROL__CLK_CHANGE_TRIGGER			0
+#define A72_CRM_CLOCK_CONTROL_0						0x200
+#define A72_CRM_CLOCK_CONTROL_0__ARM_HW_SW_ENABLE_SEL			0
+#define A72_CRM_CLOCK_CONTROL_0__AXI_HW_SW_ENABLE_SEL			2
+#define A72_CRM_CLOCK_CONTROL_0__ACP_HW_SW_ENABLE_SEL			4
+#define A72_CRM_CLOCK_CONTROL_0__ATB_HW_SW_ENABLE_SEL			6
+#define A72_CRM_CLOCK_CONTROL_0__PCLKDBG_HW_SW_ENA_SEL			8
+#define A72_CRM_CLOCK_CONTROL_1						0x204
+#define A72_CRM_CLOCK_CONTROL_1__TMON_HW_SW_ENABLE_SEL			6
+#define A72_CRM_CLOCK_CONTROL_1__APB_HW_SW_ENABLE_SEL			8
+#define A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN			0
+#define A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN			1
+#define A72_CRM_SOFTRESETN_0__AXI_SOFTRESETN				9
+#define A72_CRM_SOFTRESETN_0__ACP_SOFTRESETN				10
+#define A72_CRM_SOFTRESETN_0__ATB_SOFTRESETN				11
+#define A72_CRM_SOFTRESETN_0__PCLKDBG_SOFTRESETN			12
+#define A72_CRM_SOFTRESETN_0__TMON_SOFTRESETN				15
+#define A72_CRM_SOFTRESETN_0__L2_SOFTRESETN				3
+#define A72_CRM_SOFTRESETN_1__APB_SOFTRESETN				8
+
+/* core related regs */
+#define A72_CRM_DOMAIN_0_CONTROL					0x800
+#define A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_MEM			0x6
+#define A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_I_O			0x0
+#define A72_CRM_DOMAIN_1_CONTROL					0x804
+#define A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_MEM			0x6
+#define A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_I_O			0x0
+#define A72_CRM_CORE_CONFIG_RVBA0_LO					0xD10
+#define A72_CRM_CORE_CONFIG_RVBA0_MID					0xD14
+#define A72_CRM_CORE_CONFIG_RVBA0_HI					0xD18
+#define A72_CRM_CORE_CONFIG_RVBA1_LO					0xD20
+#define A72_CRM_CORE_CONFIG_RVBA1_MID					0xD24
+#define A72_CRM_CORE_CONFIG_RVBA1_HI					0xD28
+#define A72_CRM_SUBSYSTEM_CONFIG_0					0xC80
+#define A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT			4
+#define A72_CRM_SOFTRESETN_0__COREPOR0_SOFTRESETN			4
+#define A72_CRM_SOFTRESETN_0__COREPOR1_SOFTRESETN			5
+#define A72_CRM_SOFTRESETN_1__CORE0_SOFTRESETN				0
+#define A72_CRM_SOFTRESETN_1__DEBUG0_SOFTRESETN				4
+#define A72_CRM_SOFTRESETN_1__CORE1_SOFTRESETN				1
+#define A72_CRM_SOFTRESETN_1__DEBUG1_SOFTRESETN				5
+
+#define SPROC_MEMORY_BISR 0
+
+static int cluster_power_status[PLAT_BRCM_CLUSTER_COUNT] = {CLUSTER_POWER_ON,
+							   CLUSTER_POWER_OFF,
+							   CLUSTER_POWER_OFF,
+							   CLUSTER_POWER_OFF};
+
+void ihost_power_on_cluster(u_register_t mpidr)
+{
+	uint32_t rst, d2xs;
+	uint32_t cluster_id;
+	uint32_t ihost_base;
+#if SPROC_MEMORY_BISR
+	uint32_t bisr, cnt;
+#endif
+	cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+	uint32_t cluster0_freq_sel;
+
+	if (cluster_power_status[cluster_id] == CLUSTER_POWER_ON)
+		return;
+
+	cluster_power_status[cluster_id] = CLUSTER_POWER_ON;
+	INFO("enabling Cluster #%u\n", cluster_id);
+
+	switch (cluster_id) {
+	case 1:
+		rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH1_RESET);
+		d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST1);
+#if SPROC_MEMORY_BISR
+		bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST1;
+#endif
+		break;
+	case 2:
+		rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH2_RESET);
+		d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST2);
+#if SPROC_MEMORY_BISR
+		bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST2;
+#endif
+		break;
+	case 3:
+		rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH3_RESET);
+		d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST3);
+#if SPROC_MEMORY_BISR
+		bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST3;
+#endif
+		break;
+	default:
+		ERROR("Invalid cluster :%u\n", cluster_id);
+		return;
+	}
+
+	/* Releasing ihost resets */
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL, rst);
+
+	/* calculate cluster/ihost base address */
+	ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
+
+	/* Remove Cluster IO isolation */
+	mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_4_CONTROL,
+		       (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_I_O),
+		       (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_DFT) |
+		       (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_MEM));
+
+	/*
+	 * Since BISR sequence requires that all cores of cluster should
+	 * have removed I/O isolation hence doing same here.
+	 */
+	/* Remove core0 memory IO isolations */
+	mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_0_CONTROL,
+			  (1 << A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_I_O),
+			  (1 << A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_MEM));
+
+	/* Remove core1 memory IO isolations */
+	mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_1_CONTROL,
+			  (1 << A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_I_O),
+			  (1 << A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_MEM));
+
+#if SPROC_MEMORY_BISR
+	mmio_setbits_32(CRMU_BISR_PDG_MASK, (1 << bisr));
+
+	if (!(mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW) &
+		       (1 << CDRU_CHIP_STRAP_DATA_LSW__BISR_BYPASS_MODE))) {
+		/* BISR completion would take max 2 usec */
+		cnt = 0;
+		while (cnt < 2) {
+			udelay(1);
+			if (mmio_read_32(CRMU_CHIP_OTPC_STATUS) &
+			(1 << CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE))
+				break;
+			cnt++;
+		}
+	}
+
+	/* if BISR is not completed, need to be checked with ASIC team */
+	if (((mmio_read_32(CRMU_CHIP_OTPC_STATUS)) &
+	   (1 << CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE)) == 0) {
+		WARN("BISR did not completed and need to be addressed\n");
+	}
+#endif
+
+	/* PLL Power up. supply is already on. Turn on PLL LDO/PWR */
+	mmio_write_32(ihost_base + A72_CRM_PLL_PWR_ON,
+		     (1 << A72_CRM_PLL_PWR_ON__PLL0_ISO_PLLOUT) |
+		     (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO) |
+		     (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL));
+
+	/* 1us in spec; Doubling it to be safe*/
+	udelay(2);
+
+	/* Remove PLL output ISO */
+	mmio_write_32(ihost_base + A72_CRM_PLL_PWR_ON,
+		     (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO) |
+		     (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL));
+
+	/*
+	 * PLL0 Configuration Control Register
+	 * these 4 registers drive the i_pll_ctrl[63:0] input of pll
+	 * (16b per register).
+	 * the values are derived from the spec (sections 8 and 10).
+	 */
+
+	mmio_write_32(ihost_base + A72_CRM_PLL0_CFG0_CTRL, 0x00000000);
+	mmio_write_32(ihost_base + A72_CRM_PLL0_CFG1_CTRL, 0x00008400);
+	mmio_write_32(ihost_base + A72_CRM_PLL0_CFG2_CTRL, 0x00000001);
+	mmio_write_32(ihost_base + A72_CRM_PLL0_CFG3_CTRL, 0x00000000);
+
+	/* Read the freq_sel from cluster 0, which is up already */
+	cluster0_freq_sel = bcm_get_ihost_pll_freq(0);
+	bcm_set_ihost_pll_freq(cluster_id, cluster0_freq_sel);
+
+	udelay(1);
+
+	/* Release clock source reset */
+	mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+		       (1 << A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN) |
+		       (1 << A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN));
+
+	udelay(1);
+
+	/*
+	 * Integer division for clks (divider value = n+1).
+	 * These are the divisor of ARM PLL clock frequecy.
+	 */
+	mmio_write_32(ihost_base + A72_CRM_AXI_CLK_DESC, 0x00000001);
+	mmio_write_32(ihost_base + A72_CRM_ACP_CLK_DESC, 0x00000001);
+	mmio_write_32(ihost_base + A72_CRM_ATB_CLK_DESC, 0x00000004);
+	mmio_write_32(ihost_base + A72_CRM_PCLKDBG_DESC, 0x0000000b);
+
+	/*
+	 * clock change trigger - must set to take effect after clock
+	 * source change
+	 */
+	mmio_setbits_32(ihost_base + A72_CRM_CLOCK_MODE_CONTROL,
+		       (1 << A72_CRM_CLOCK_MODE_CONTROL__CLK_CHANGE_TRIGGER));
+
+	/* turn on functional clocks */
+	mmio_setbits_32(ihost_base + A72_CRM_CLOCK_CONTROL_0,
+		       (3 << A72_CRM_CLOCK_CONTROL_0__ARM_HW_SW_ENABLE_SEL) |
+		       (3 << A72_CRM_CLOCK_CONTROL_0__AXI_HW_SW_ENABLE_SEL) |
+		       (3 << A72_CRM_CLOCK_CONTROL_0__ACP_HW_SW_ENABLE_SEL) |
+		       (3 << A72_CRM_CLOCK_CONTROL_0__ATB_HW_SW_ENABLE_SEL) |
+		       (3 << A72_CRM_CLOCK_CONTROL_0__PCLKDBG_HW_SW_ENA_SEL));
+
+	mmio_setbits_32(ihost_base + A72_CRM_CLOCK_CONTROL_1,
+		       (3 << A72_CRM_CLOCK_CONTROL_1__TMON_HW_SW_ENABLE_SEL) |
+		       (3 << A72_CRM_CLOCK_CONTROL_1__APB_HW_SW_ENABLE_SEL));
+
+	/* Program D2XS Power Down Registers */
+	mmio_setbits_32(CDRU_CCN_REGISTER_CONTROL_1, d2xs);
+
+	/* Program Core Config Debug ROM Address Registers */
+	/* mark valid for Debug ROM base address */
+	mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGCTRL,
+		     (1 << A72_CRM_CORE_CONFIG_DBGCTRL__DBGROMADDRV));
+
+	/* Program Lo and HI address of coresight DBG rom address */
+	mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGROM_LO,
+		     (CORESIGHT_BASE_ADDR >> 12) & 0xffff);
+	mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGROM_HI,
+		     (CORESIGHT_BASE_ADDR >> 28) & 0xffff);
+
+	/*
+	 * Release soft resets of different components.
+	 * Order: Bus clocks --> PERIPH --> L2 --> cores
+	 */
+
+	/* Bus clocks soft resets */
+	mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+		       (1 << A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN) |
+		       (1 << A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN) |
+		       (1 << A72_CRM_SOFTRESETN_0__AXI_SOFTRESETN) |
+		       (1 << A72_CRM_SOFTRESETN_0__ACP_SOFTRESETN) |
+		       (1 << A72_CRM_SOFTRESETN_0__ATB_SOFTRESETN) |
+		       (1 << A72_CRM_SOFTRESETN_0__PCLKDBG_SOFTRESETN));
+
+	mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_1,
+		       (1 << A72_CRM_SOFTRESETN_1__APB_SOFTRESETN));
+
+	/* Periph component softreset */
+	mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+		       (1 << A72_CRM_SOFTRESETN_0__TMON_SOFTRESETN));
+
+	/* L2 softreset */
+	mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+		       (1 << A72_CRM_SOFTRESETN_0__L2_SOFTRESETN));
+
+	/* Enable and program Satellite timer */
+	ihost_enable_satellite_timer(cluster_id);
+}
+
+void ihost_power_on_secondary_core(u_register_t mpidr, uint64_t rvbar)
+{
+	uint32_t ihost_base;
+	uint32_t coreid = MPIDR_AFFLVL0_VAL(mpidr);
+	uint32_t cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+
+	ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
+	INFO("programming core #%u\n", coreid);
+
+	if (coreid) {
+		/* program the entry point for core1 */
+		mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_LO,
+			      rvbar & 0xFFFF);
+		mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_MID,
+			     (rvbar >> 16) & 0xFFFF);
+		mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_HI,
+			     (rvbar >> 32) & 0xFFFF);
+	} else {
+		/* program the entry point for core */
+		mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_LO,
+			      rvbar & 0xFFFF);
+		mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_MID,
+			     (rvbar >> 16) & 0xFFFF);
+		mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_HI,
+			     (rvbar >> 32) & 0xFFFF);
+	}
+
+	/* Tell debug logic which processor is up */
+	mmio_setbits_32(ihost_base + A72_CRM_SUBSYSTEM_CONFIG_0,
+		       (coreid ?
+		       (2 << A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT) :
+		       (1 << A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT)));
+
+	/* releasing soft resets for IHOST core */
+	mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+		       (coreid ?
+		       (1 << A72_CRM_SOFTRESETN_0__COREPOR1_SOFTRESETN) :
+		       (1 << A72_CRM_SOFTRESETN_0__COREPOR0_SOFTRESETN)));
+
+	mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_1,
+		       (coreid ?
+		       ((1 << A72_CRM_SOFTRESETN_1__CORE1_SOFTRESETN) |
+		       (1 << A72_CRM_SOFTRESETN_1__DEBUG1_SOFTRESETN)) :
+		       ((1 << A72_CRM_SOFTRESETN_1__CORE0_SOFTRESETN) |
+		       (1 << A72_CRM_SOFTRESETN_1__DEBUG0_SOFTRESETN))));
+}
diff --git a/plat/brcm/board/stingray/src/iommu.c b/plat/brcm/board/stingray/src/iommu.c
new file mode 100644
index 0000000..de8b995
--- /dev/null
+++ b/plat/brcm/board/stingray/src/iommu.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <iommu.h>
+#include <platform_def.h>
+
+#define SMMU_BASE		0x64000000
+#define ARM_SMMU_MAX_NUM_CNTXT_BANK	64
+#define SMMU_CTX_BANK_IDX_SECURE_CRMU	63
+#define ARM_SMMU_NUM_SECURE_MASTER	1
+#define ARM_SMMU_NSNUMCBO		(ARM_SMMU_MAX_NUM_CNTXT_BANK - \
+					 ARM_SMMU_NUM_SECURE_MASTER)
+#define ARM_SMMU_NSNUMSMRGO		(ARM_SMMU_MAX_NUM_CNTXT_BANK - \
+					 ARM_SMMU_NUM_SECURE_MASTER)
+/* Reserved Banks. */
+#define SMMU_CTX_BANK_IDX		(SMMU_CTX_BANK_IDX_SECURE_CRMU - \
+					 ARM_SMMU_NUM_SECURE_MASTER)
+#define NUM_OF_SMRS			1
+
+#define STG1_WITH_STG2_BYPASS		1
+#define ARM_LPAE_PGTBL_PHYS_CRMU	0x880000000
+#define ARM_LPAE_PGTBL_PHYS		0x880200000
+#define ARM_LPAE_PGTBL_PTE_CNT		512
+#define ARM_LPAE_PTE_L1_BLOCK_SIZE	0x40000000
+#define ARM_LPAE_PTE_L1_ADDR_MASK	0x0000FFFFC0000000UL
+#define ARM_LPAE_PTE_TABLE		0x2UL
+#define ARM_LPAE_PTE_VALID		0x1UL
+#define ARM_LPAE_PTE_ATTRINDX		2
+#define ARM_LPAE_PTE_NS			5
+#define ARM_LPAE_PTE_AP			6
+#define ARM_LPAE_PTE_AP_EL1_RW		0x0
+#define ARM_LPAE_PTE_AP_EL0_RW		0x1
+#define ARM_LPAE_PTE_SH			8
+#define ARM_LPAE_PTE_SH_NON		0x0
+#define ARM_LPAE_PTE_SH_OUTER		0x2
+#define ARM_LPAE_PTE_SH_INNER		0x3
+#define ARM_LPAE_PTE_AF			10
+#define ARM_SMMU_RES_SIZE		0x80000
+
+#define ARM_LPAE_PTE_NSTABLE		0x8000000000000000UL
+#define ARM_LPAE_PTE_L1_INDEX_SHIFT	30
+#define ARM_LPAE_PTE_L1_INDEX_MASK	0x1ff
+#define ARM_LPAE_PTE_L0_INDEX_SHIFT	39
+#define ARM_LPAE_PTE_L0_INDEX_MASK	0x1ff
+#define ARM_LPAE_PTE_TABLE_MASK		~(0xfffUL)
+/* Configuration registers */
+#define ARM_SMMU_GR0_sCR0	0x0
+#define sCR0_CLIENTPD		(1 << 0)
+#define sCR0_GFRE		(1 << 1)
+#define sCR0_GFIE		(1 << 2)
+#define sCR0_GCFGFRE		(1 << 4)
+#define sCR0_GCFGFIE		(1 << 5)
+#define sCR0_USFCFG		(1 << 10)
+#define sCR0_VMIDPNE		(1 << 11)
+#define sCR0_PTM		(1 << 12)
+#define sCR0_FB			(1 << 13)
+#define sCR0_VMID16EN		(1 << 31)
+#define sCR0_BSU_SHIFT		14
+#define sCR0_BSU_MASK		0x3
+#define ARM_SMMU_SMMU_SCR1	0x4
+#define SCR1_NSNUMCBO_MASK	0xFF
+#define SCR1_NSNUMCBO_SHIFT	0x0
+#define SCR1_NSNUMSMRGO_MASK	0xFF00
+#define SCR1_NSNUMSMRGO_SHIFT	0x8
+
+/* Identification registers */
+#define ARM_SMMU_GR0_ID0		0x20
+#define ARM_SMMU_GR0_ID1		0x24
+#define ARM_SMMU_GR0_ID2		0x28
+#define ARM_SMMU_GR0_ID3		0x2c
+#define ARM_SMMU_GR0_ID4		0x30
+#define ARM_SMMU_GR0_ID5		0x34
+#define ARM_SMMU_GR0_ID6		0x38
+#define ARM_SMMU_GR0_ID7		0x3c
+#define ARM_SMMU_GR0_sGFSR		0x48
+#define ARM_SMMU_GR0_sGFSYNR0		0x50
+#define ARM_SMMU_GR0_sGFSYNR1		0x54
+#define ARM_SMMU_GR0_sGFSYNR2		0x58
+
+#define ID1_PAGESIZE			(1U << 31)
+#define ID1_NUMPAGENDXB_SHIFT		28
+#define ID1_NUMPAGENDXB_MASK		7
+#define ID1_NUMS2CB_SHIFT		16
+#define ID1_NUMS2CB_MASK		0xff
+#define ID1_NUMCB_SHIFT			0
+#define ID1_NUMCB_MASK			0xff
+
+/* SMMU global address space */
+#define ARM_SMMU_GR0(smmu)	((smmu)->base)
+#define ARM_SMMU_GR1(smmu)	((smmu)->base + (1 << (smmu)->pgshift))
+
+/* Stream mapping registers */
+#define ARM_SMMU_GR0_SMR(n)	(0x800 + (n << 2))
+#define SMR_VALID		(1U << 31)
+#define SMR_MASK_SHIFT		16
+#define SMR_ID_SHIFT		0
+
+#define ARM_SMMU_GR0_S2CR(n)	(0xc00 + (n << 2))
+#define S2CR_CBNDX_SHIFT	0
+#define S2CR_CBNDX_MASK		0xff
+#define S2CR_TYPE_SHIFT		16
+#define S2CR_TYPE_MASK		0x3
+
+#define ARM_SMMU_GR1_CBA2R(n)	(0x800 + (n << 2))
+#define CBA2R_RW64_32BIT	(0 << 0)
+#define CBA2R_RW64_64BIT	(1 << 0)
+#define CBA2R_VMID_SHIFT	16
+#define CBA2R_VMID_MASK		0xffff
+
+#define ARM_SMMU_GR1_CBAR(n)	(0x0 + (n << 2))
+#define CBAR_VMID_SHIFT		0
+#define CBAR_VMID_MASK		0xff
+#define CBAR_S1_BPSHCFG_SHIFT	8
+#define CBAR_S1_BPSHCFG_MASK	3
+#define CBAR_S1_BPSHCFG_NSH	3
+#define CBAR_S1_MEMATTR_SHIFT	12
+#define CBAR_S1_MEMATTR_MASK	0xf
+#define CBAR_S1_MEMATTR_WB	0xf
+#define CBAR_TYPE_SHIFT		16
+#define CBAR_TYPE_MASK		0x3
+#define CBAR_TYPE_S2_TRANS		(0 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_BYPASS	(1 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_FAULT	(2 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_TRANS	(3 << CBAR_TYPE_SHIFT)
+#define CBAR_IRPTNDX_SHIFT		24
+#define CBAR_IRPTNDX_MASK		0xff
+
+/* Translation context bank */
+#define ARM_SMMU_CB_BASE(smmu)		((smmu)->base + ((smmu)->size >> 1))
+#define ARM_SMMU_CB(smmu, n)		((n) * (1 << (smmu)->pgshift))
+
+#define ARM_SMMU_CB_SCTLR		0x0
+#define ARM_SMMU_CB_ACTLR		0x4
+#define ARM_SMMU_CB_RESUME		0x8
+#define ARM_SMMU_CB_TTBCR2		0x10
+#define ARM_SMMU_CB_TTBR0		0x20
+#define ARM_SMMU_CB_TTBR1		0x28
+#define ARM_SMMU_CB_TTBCR		0x30
+#define ARM_SMMU_CB_CONTEXTIDR		0x34
+#define ARM_SMMU_CB_S1_MAIR0		0x38
+#define ARM_SMMU_CB_S1_MAIR1		0x3c
+#define ARM_SMMU_CB_PAR			0x50
+#define ARM_SMMU_CB_FSR			0x58
+#define ARM_SMMU_CB_FAR			0x60
+#define ARM_SMMU_CB_FSYNR0		0x68
+#define ARM_SMMU_CB_S1_TLBIVA		0x600
+#define ARM_SMMU_CB_S1_TLBIASID		0x610
+#define ARM_SMMU_CB_S1_TLBIVAL		0x620
+#define ARM_SMMU_CB_S2_TLBIIPAS2	0x630
+#define ARM_SMMU_CB_S2_TLBIIPAS2L	0x638
+#define ARM_SMMU_CB_ATS1PR		0x800
+#define ARM_SMMU_CB_ATSR		0x8f0
+
+#define SCTLR_S1_ASIDPNE		(1 << 12)
+#define SCTLR_CFCFG			(1 << 7)
+#define SCTLR_CFIE			(1 << 6)
+#define SCTLR_CFRE			(1 << 5)
+#define SCTLR_E				(1 << 4)
+#define SCTLR_AFE			(1 << 2)
+#define SCTLR_TRE			(1 << 1)
+#define SCTLR_M				(1 << 0)
+
+/* ARM LPAE configuration. */
+/**************************************************************/
+/* Register bits */
+#define ARM_32_LPAE_TCR_EAE		(1 << 31)
+#define ARM_64_LPAE_S2_TCR_RES1		(1 << 31)
+
+#define ARM_LPAE_TCR_EPD1		(1 << 23)
+
+#define ARM_LPAE_TCR_TG0_4K		(0 << 14)
+#define ARM_LPAE_TCR_TG0_64K		(1 << 14)
+#define ARM_LPAE_TCR_TG0_16K		(2 << 14)
+
+#define ARM_LPAE_TCR_SH0_SHIFT		12
+#define ARM_LPAE_TCR_SH0_MASK		0x3
+#define ARM_LPAE_TCR_SH_NS		0
+#define ARM_LPAE_TCR_SH_OS		2
+#define ARM_LPAE_TCR_SH_IS		3
+
+#define ARM_LPAE_TCR_ORGN0_SHIFT	10
+#define ARM_LPAE_TCR_IRGN0_SHIFT	8
+#define ARM_LPAE_TCR_RGN_MASK		0x3
+#define ARM_LPAE_TCR_RGN_NC		0
+#define ARM_LPAE_TCR_RGN_WBWA		1
+#define ARM_LPAE_TCR_RGN_WT		2
+#define ARM_LPAE_TCR_RGN_WB		3
+
+#define ARM_LPAE_TCR_SL0_SHIFT		6
+#define ARM_LPAE_TCR_SL0_MASK		0x3
+
+#define ARM_LPAE_TCR_T0SZ_SHIFT		0
+#define ARM_LPAE_TCR_SZ_MASK		0xf
+
+#define ARM_LPAE_TCR_PS_SHIFT		16
+#define ARM_LPAE_TCR_PS_MASK		0x7
+
+#define ARM_LPAE_TCR_IPS_SHIFT		32
+#define ARM_LPAE_TCR_IPS_MASK		0x7
+
+#define ARM_LPAE_TCR_PS_32_BIT		0x0ULL
+#define ARM_LPAE_TCR_PS_36_BIT		0x1ULL
+#define ARM_LPAE_TCR_PS_40_BIT		0x2ULL
+#define ARM_LPAE_TCR_PS_42_BIT		0x3ULL
+#define ARM_LPAE_TCR_PS_44_BIT		0x4ULL
+#define ARM_LPAE_TCR_PS_48_BIT		0x5ULL
+
+#define ARM_LPAE_MAIR_ATTR_SHIFT(n)	((n) << 3)
+#define ARM_LPAE_MAIR_ATTR_MASK		0xff
+#define ARM_LPAE_MAIR_ATTR_DEVICE	0x04
+#define ARM_LPAE_MAIR_ATTR_NC		0x44
+#define ARM_LPAE_MAIR_ATTR_WBRWA	0xff
+#define ARM_LPAE_MAIR_ATTR_IDX_NC	0
+#define ARM_LPAE_MAIR_ATTR_IDX_CACHE	1
+#define ARM_LPAE_MAIR_ATTR_IDX_DEV	2
+
+#define TTBRn_ASID_SHIFT		48
+#define TTBCR2_SEP_SHIFT		15
+#define TTBCR2_SEP_UPSTREAM		(0x7 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_AS                       (1 << 4)
+#define TTBCR_T0SZ(ia_bits)		(64 - (ia_bits))
+
+#define S2CR_PRIVCFG_SHIFT		24
+#define S2CR_PRIVCFG_MASK		0x3
+
+/**************************************************************/
+
+uint16_t paxc_stream_ids[] = { 0x2000 };
+
+uint16_t paxc_stream_ids_mask[] = { 0x1fff };
+uint16_t crmu_stream_ids[] = { CRMU_STREAM_ID };
+uint16_t crmu_stream_ids_mask[] = { 0x0 };
+
+enum arm_smmu_s2cr_type {
+	S2CR_TYPE_TRANS,
+	S2CR_TYPE_BYPASS,
+	S2CR_TYPE_FAULT,
+};
+
+enum arm_smmu_s2cr_privcfg {
+	S2CR_PRIVCFG_DEFAULT,
+	S2CR_PRIVCFG_DIPAN,
+	S2CR_PRIVCFG_UNPRIV,
+	S2CR_PRIVCFG_PRIV,
+};
+
+struct arm_smmu_smr {
+	uint16_t mask;
+	uint16_t id;
+	uint32_t valid;
+};
+
+struct arm_smmu_s2cr {
+	int count;
+	enum arm_smmu_s2cr_type type;
+	enum arm_smmu_s2cr_privcfg privcfg;
+	uint8_t cbndx;
+};
+
+struct arm_smmu_cfg {
+	uint8_t cbndx;
+	uint8_t irptndx;
+	uint32_t cbar;
+};
+
+struct arm_smmu_device {
+	uint8_t *base;
+	uint32_t streams;
+	unsigned long size;
+	unsigned long pgshift;
+	unsigned long va_size;
+	unsigned long ipa_size;
+	unsigned long pa_size;
+	struct arm_smmu_smr smr[NUM_OF_SMRS];
+	struct arm_smmu_s2cr s2cr[NUM_OF_SMRS];
+	struct arm_smmu_cfg cfg[NUM_OF_SMRS];
+	uint16_t *stream_ids;
+	uint16_t *stream_ids_mask;
+};
+
+void arm_smmu_enable_secure_client_port(void)
+{
+	uintptr_t smmu_base = SMMU_BASE;
+
+	mmio_clrbits_32(smmu_base, sCR0_CLIENTPD);
+}
+
+void arm_smmu_reserve_secure_cntxt(void)
+{
+	uintptr_t smmu_base = SMMU_BASE;
+
+	mmio_clrsetbits_32(smmu_base + ARM_SMMU_SMMU_SCR1,
+			  (SCR1_NSNUMSMRGO_MASK | SCR1_NSNUMCBO_MASK),
+			  ((ARM_SMMU_NSNUMCBO << SCR1_NSNUMCBO_SHIFT) |
+			  (ARM_SMMU_NSNUMSMRGO << SCR1_NSNUMSMRGO_SHIFT)));
+}
+
+static void arm_smmu_smr_cfg(struct arm_smmu_device *smmu, uint32_t index)
+{
+	uint32_t idx = smmu->cfg[index].cbndx;
+	struct arm_smmu_smr *smr = &smmu->smr[index];
+	uint32_t reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
+
+	if (smr->valid)
+		reg |= SMR_VALID;
+
+	mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
+		      ARM_SMMU_GR0_SMR(idx)), reg);
+}
+
+static void arm_smmu_s2cr_cfg(struct arm_smmu_device *smmu, uint32_t index)
+{
+	uint32_t idx = smmu->cfg[index].cbndx;
+	struct arm_smmu_s2cr *s2cr = &smmu->s2cr[index];
+
+	uint32_t reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT |
+		  (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
+		  (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
+
+	mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
+		      ARM_SMMU_GR0_S2CR(idx)), reg);
+}
+
+static void smmu_set_pgtbl(struct arm_smmu_device *smmu,
+		    enum iommu_domain dom,
+		    uint64_t *pg_table_base)
+{
+	int i, l0_index, l1_index;
+	uint64_t addr, *pte, *l0_base, *l1_base;
+	uint64_t addr_space_limit;
+
+	if (dom == PCIE_PAXC) {
+		addr_space_limit = 0xffffffffff;
+	} else if (dom == DOMAIN_CRMU) {
+		addr_space_limit = 0xffffffff;
+	} else {
+		ERROR("dom is not supported\n");
+		return;
+	}
+
+	l0_base = pg_table_base;
+	/* clear L0 descriptors. */
+	for (i = 0; i < ARM_LPAE_PGTBL_PTE_CNT; i++)
+		l0_base[i] = 0x0;
+
+	addr = 0x0;
+	while (addr < addr_space_limit) {
+		/* find L0 pte */
+		l0_index = ((addr >> ARM_LPAE_PTE_L0_INDEX_SHIFT) &
+			     ARM_LPAE_PTE_L0_INDEX_MASK);
+		l1_base = l0_base + ((l0_index + 1) * ARM_LPAE_PGTBL_PTE_CNT);
+
+		/* setup L0 pte if required */
+		pte = l0_base + l0_index;
+		if (*pte == 0x0) {
+			*pte |= ((uint64_t)l1_base & ARM_LPAE_PTE_TABLE_MASK);
+			if (dom == PCIE_PAXC)
+				*pte |= ARM_LPAE_PTE_NSTABLE;
+			*pte |= ARM_LPAE_PTE_TABLE;
+			*pte |= ARM_LPAE_PTE_VALID;
+		}
+
+		/* find L1 pte */
+		l1_index = ((addr >> ARM_LPAE_PTE_L1_INDEX_SHIFT) &
+			    ARM_LPAE_PTE_L1_INDEX_MASK);
+		pte = l1_base + l1_index;
+
+		/* setup L1 pte */
+		*pte = 0x0;
+		*pte |= (addr & ARM_LPAE_PTE_L1_ADDR_MASK);
+		if (addr < 0x80000000) {
+			*pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV <<
+				 ARM_LPAE_PTE_ATTRINDX);
+			if (dom == PCIE_PAXC)
+				*pte |= (1 << ARM_LPAE_PTE_NS);
+		} else {
+			*pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE <<
+				 ARM_LPAE_PTE_ATTRINDX);
+			*pte |= (1 << ARM_LPAE_PTE_NS);
+		}
+		*pte |= (ARM_LPAE_PTE_AP_EL0_RW << ARM_LPAE_PTE_AP);
+		*pte |= (ARM_LPAE_PTE_SH_INNER << ARM_LPAE_PTE_SH);
+		*pte |= (1 << ARM_LPAE_PTE_AF);
+		*pte |= ARM_LPAE_PTE_VALID;
+
+		addr += ARM_LPAE_PTE_L1_BLOCK_SIZE;
+	}
+}
+
+void arm_smmu_create_identity_map(enum iommu_domain dom)
+{
+	struct arm_smmu_device iommu;
+	struct arm_smmu_device *smmu = &iommu;
+	uint32_t reg, reg2;
+	unsigned long long reg64;
+	uint32_t idx;
+	uint16_t asid;
+	unsigned int context_bank_index;
+	unsigned long long pg_table_base;
+
+	smmu->base = (uint8_t *) SMMU_BASE;
+	reg = mmio_read_32((uintptr_t) (ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID1));
+	smmu->pgshift = (reg & ID1_PAGESIZE) ? 16 : 12;
+	smmu->size = ARM_SMMU_RES_SIZE;
+	smmu->stream_ids = NULL;
+
+	switch (dom) {
+	case PCIE_PAXC:
+		smmu->stream_ids = &paxc_stream_ids[0];
+		smmu->stream_ids_mask = &paxc_stream_ids_mask[0];
+		smmu->streams = ARRAY_SIZE(paxc_stream_ids);
+		context_bank_index = SMMU_CTX_BANK_IDX;
+		pg_table_base = ARM_LPAE_PGTBL_PHYS;
+		break;
+	case DOMAIN_CRMU:
+		smmu->stream_ids = &crmu_stream_ids[0];
+		smmu->stream_ids_mask = &crmu_stream_ids_mask[0];
+		smmu->streams = ARRAY_SIZE(crmu_stream_ids);
+		context_bank_index = SMMU_CTX_BANK_IDX_SECURE_CRMU;
+		pg_table_base = ARM_LPAE_PGTBL_PHYS_CRMU;
+		break;
+	default:
+		ERROR("domain not supported\n");
+		return;
+	}
+
+	if (smmu->streams > NUM_OF_SMRS) {
+		INFO("can not support more than %d sids\n", NUM_OF_SMRS);
+		return;
+	}
+
+	/* set up iommu dev. */
+	for (idx = 0; idx < smmu->streams; idx++) {
+		/* S2CR. */
+		smmu->s2cr[idx].type = S2CR_TYPE_TRANS;
+		smmu->s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT;
+		smmu->s2cr[idx].cbndx = context_bank_index;
+		smmu->cfg[idx].cbndx = context_bank_index;
+		smmu->cfg[idx].cbar = STG1_WITH_STG2_BYPASS << CBAR_TYPE_SHIFT;
+		arm_smmu_s2cr_cfg(smmu, idx);
+
+		/* SMR. */
+		smmu->smr[idx].mask = smmu->stream_ids_mask[idx];
+		smmu->smr[idx].id = smmu->stream_ids[idx];
+		smmu->smr[idx].valid = 1;
+		arm_smmu_smr_cfg(smmu, idx);
+
+		/* CBA2R. 64-bit Translation */
+		mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
+			      ARM_SMMU_GR1_CBA2R(smmu->cfg[idx].cbndx)),
+			      0x1);
+		/* CBAR.*/
+		reg = smmu->cfg[idx].cbar;
+		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
+		       (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+
+		mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
+			      ARM_SMMU_GR1_CBAR(smmu->cfg[idx].cbndx)),
+			      reg);
+
+		/* TTBCR. */
+		reg64 = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) |
+		      (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) |
+		      (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT);
+		reg64 |= ARM_LPAE_TCR_TG0_4K;
+		reg64 |= (ARM_LPAE_TCR_PS_40_BIT << ARM_LPAE_TCR_IPS_SHIFT);
+		/* ias 40 bits.*/
+		reg64 |= TTBCR_T0SZ(40) << ARM_LPAE_TCR_T0SZ_SHIFT;
+		/* Disable speculative walks through TTBR1 */
+		reg64 |= ARM_LPAE_TCR_EPD1;
+		reg = (uint32_t) reg64;
+		reg2 = (uint32_t) (reg64 >> 32);
+		reg2 |= TTBCR2_SEP_UPSTREAM;
+		reg2 |= TTBCR2_AS;
+
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_TTBCR2), reg2);
+
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_TTBCR), reg);
+
+		/* TTBR0. */
+		asid = smmu->cfg[idx].cbndx;
+		reg64 = pg_table_base;
+		reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
+
+		mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_TTBR0), reg64);
+		/* TTBR1. */
+		reg64 = 0;
+		reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
+
+		mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_TTBR1), reg64);
+		/* MAIR. */
+		reg = (ARM_LPAE_MAIR_ATTR_NC
+			<< ARM_LPAE_MAIR_ATTR_SHIFT
+			(ARM_LPAE_MAIR_ATTR_IDX_NC)) |
+			(ARM_LPAE_MAIR_ATTR_WBRWA <<
+			ARM_LPAE_MAIR_ATTR_SHIFT
+			(ARM_LPAE_MAIR_ATTR_IDX_CACHE)) |
+			(ARM_LPAE_MAIR_ATTR_DEVICE <<
+			ARM_LPAE_MAIR_ATTR_SHIFT
+			(ARM_LPAE_MAIR_ATTR_IDX_DEV));
+
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_S1_MAIR0), reg);
+
+		/* MAIR1. */
+		reg = 0;
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_S1_MAIR1), reg);
+		/* SCTLR. */
+		reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M;
+		/* stage 1.*/
+		reg |= SCTLR_S1_ASIDPNE;
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_SCTLR), reg);
+	}
+	smmu_set_pgtbl(smmu, dom, (uint64_t *)pg_table_base);
+}
diff --git a/plat/brcm/board/stingray/src/ncsi.c b/plat/brcm/board/stingray/src/ncsi.c
new file mode 100644
index 0000000..58ea9e2
--- /dev/null
+++ b/plat/brcm/board/stingray/src/ncsi.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <ncsi.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+static const char *const io_drives[] = {
+	"2mA", "4mA", "6mA", "8mA",
+	"10mA", "12mA", "14mA", "16mA"
+};
+
+void brcm_stingray_ncsi_init(void)
+{
+	unsigned int i = 0;
+	unsigned int selx = 0;
+
+#if NCSI_IO_DRIVE_STRENGTH_MA == 2
+	selx = 0x0;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 4
+	selx = 0x1;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 6
+	selx = 0x2;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 8
+	selx = 0x3;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 10
+	selx = 0x4;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 12
+	selx = 0x5;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 14
+	selx = 0x6;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 16
+	selx = 0x7;
+#else
+	ERROR("Unsupported NCSI_IO_DRIVE_STRENGTH_MA. Please check it.\n");
+	return;
+#endif
+	INFO("ncsi io drives: %s\n", io_drives[selx]);
+
+	for (i = 0; i < NITRO_NCSI_IOPAD_CONTROL_NUM; i++) {
+		mmio_clrsetbits_32((NITRO_NCSI_IOPAD_CONTROL_BASE + (i * 4)),
+				   PAD_SELX_MASK, PAD_SELX_VALUE(selx));
+	}
+
+	INFO("ncsi init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/paxb.c b/plat/brcm/board/stingray/src/paxb.c
new file mode 100644
index 0000000..28065f0
--- /dev/null
+++ b/plat/brcm/board/stingray/src/paxb.c
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <paxb.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+#define PCIE_CORE_PWR_ARR_POWERON        0x8
+#define PCIE_CORE_PWR_ARR_POWEROK        0x4
+#define PCIE_CORE_PWR_POWERON            0x2
+#define PCIE_CORE_PWR_POWEROK            0x1
+
+#define PCIE_CORE_USER_CFG               (PCIE_CORE_BASE + 0x38)
+#define PCIE_PAXB_SMMU_SID_CFG           (PCIE_CORE_BASE + 0x60)
+#ifdef SID_B8_D1_F1
+#define PAXB_SMMU_SID_CFG_BUS_WIDTH      (0x8 << 8)
+#define PAXB_SMMU_SID_CFG_DEV_WIDTH      (0x1 << 12)
+#define PAXB_SMMU_SID_CFG_FUN_WIDTH      (0x1 << 16)
+#else
+#define PAXB_SMMU_SID_CFG_BUS_WIDTH      (0x2 << 8)
+#define PAXB_SMMU_SID_CFG_DEV_WIDTH      (0x5 << 12)
+#define PAXB_SMMU_SID_CFG_FUN_WIDTH      (0x3 << 16)
+#endif
+
+#define PAXB_APB_TIMEOUT_COUNT_OFFSET 0x034
+
+/* allow up to 5 ms for each power switch to stabilize */
+#define PCIE_CORE_PWR_TIMEOUT_MS      5
+
+/* wait 1 microsecond for PCIe core soft reset */
+#define PCIE_CORE_SOFT_RST_DELAY_US 1
+
+/*
+ * List of PAXB APB registers
+ */
+#define PAXB_BASE                        0x48000000
+#define PAXB_BASE_OFFSET                 0x4000
+#define PAXB_OFFSET(core)                (PAXB_BASE + \
+					  (core) * PAXB_BASE_OFFSET)
+
+#define PAXB_CLK_CTRL_OFFSET             0x000
+#define PAXB_EP_PERST_SRC_SEL_MASK       (1 << 2)
+#define PAXB_EP_MODE_PERST_MASK          (1 << 1)
+#define PAXB_RC_PCIE_RST_OUT_MASK        (1 << 0)
+
+#define PAXB_MAX_IMAP_WINDOWS            8
+#define PAXB_IMAP_REG_WIDTH              8
+#define PAXB_IMAP0_REG_WIDTH             4
+#define PAXB_AXUSER_REG_WIDTH            4
+
+#define PAXB_CFG_IND_ADDR_OFFSET         0x120
+#define PAXB_CFG_IND_DATA_OFFSET         0x124
+#define PAXB_CFG_IND_ADDR_MASK           0x1ffc
+#define PAXB_CFG_CFG_TYPE_MASK           0x1
+
+#define PAXB_EP_CFG_ADDR_OFFSET          0x1f8
+#define PAXB_EP_CFG_DATA_OFFSET          0x1fc
+#define PAXB_EP_CFG_ADDR_MASK            0xffc
+#define PAXB_EP_CFG_TYPE_MASK            0x1
+
+#define PAXB_0_DEFAULT_IMAP              0xed0
+#define DEFAULT_ADDR_INVALID             BIT(0)
+#define PAXB_0_DEFAULT_IMAP_AXUSER       0xed8
+#define PAXB_0_DEFAULT_IMAP_AXCACHE      0xedc
+#define IMAP_AXCACHE                     0xff
+#define OARR_VALID                       BIT(0)
+#define IMAP_VALID                       BIT(0)
+
+#define PAXB_IMAP0_BASE_OFFSET           0xc00
+#define PAXB_IARR0_BASE_OFFSET           0xd00
+#define PAXB_IMAP0_OFFSET(idx)           (PAXB_IMAP0_BASE_OFFSET + \
+					  (idx) * PAXB_IMAP0_REG_WIDTH)
+#define PAXB_IMAP0_WINDOW_SIZE           0x1000
+
+#define PAXB_IMAP2_OFFSET                0xcc0
+#define PAXB_IMAP0_REGS_TYPE_OFFSET      0xcd0
+#define PAXB_IARR2_LOWER_OFFSET          0xd10
+
+#define PAXB_IMAP3_BASE_OFFSET           0xe08
+#define PAXB_IMAP3_OFFSET(idx)           (PAXB_IMAP3_BASE_OFFSET + \
+					  (idx) * PAXB_IMAP_REG_WIDTH)
+
+#define PAXB_IMAP3_0_AXUSER_B_OFFSET     0xe48
+#define PAXB_IMAP3_0_AXUSER_OFFSET(idx)  (PAXB_IMAP3_0_AXUSER_B_OFFSET + \
+					  (idx) * PAXB_AXUSER_REG_WIDTH)
+
+#define PAXB_IMAP4_BASE_OFFSET           0xe70
+#define PAXB_IMAP4_OFFSET(idx)           (PAXB_IMAP4_BASE_OFFSET + \
+					  (idx) * PAXB_IMAP_REG_WIDTH)
+
+#define PAXB_IMAP4_0_AXUSER_B_OFFSET     0xeb0
+#define PAXB_IMAP4_0_AXUSER_OFFSET(idx)  (PAXB_IMAP4_0_AXUSER_B_OFFSET + \
+					  (idx) * PAXB_AXUSER_REG_WIDTH)
+
+#define PAXB_CFG_LINK_STATUS_OFFSET      0xf0c
+#define PAXB_CFG_PHYLINKUP_MASK          (1 << 3)
+#define PAXB_CFG_DL_ACTIVE_MASK          (1 << 2)
+
+#define PAXB_IMAP0_0_AXUSER_OFFSET       0xf60
+#define PAXB_IMAP2_AXUSER_OFFSET         0xfe0
+
+/* cacheable write-back, allocate on both reads and writes */
+#define IMAP_ARCACHE                     0x0f0
+#define IMAP_AWCACHE                     0xf00
+/* normal access, nonsecure access, and data access */
+/* AWQOS:0xe and ARQOS:0xa */
+/* AWPROT:0x2 and ARPROT:0x1 */
+#define IMAP_AXUSER                      0x002e002a
+
+/*
+ * List of NIC security and PIPEMUX related registers
+ */
+#define SR_PCIE_NIC_SECURITY_BASE      0x58100000
+#define NS3Z_PCIE_NIC_SECURITY_BASE    0x48100000
+
+#define GITS_TRANSLATER                0x63c30000
+
+#define VENDOR_ID                 0x14e4
+#define CFG_RC_DEV_ID             0x434
+#define CFG_RC_DEV_SUBID          0x438
+#define PCI_BRIDGE_CTRL_REG_OFFSET     0x43c
+#define PCI_CLASS_BRIDGE_MASK          0xffff00
+#define PCI_CLASS_BRIDGE_SHIFT         8
+#define PCI_CLASS_BRIDGE_PCI           0x0604
+
+/*
+ * List of PAXB RC configuration space registers
+ */
+
+/* first capability list entry */
+#define PCI_CAPABILITY_LIST_OFFSET    0x34
+#define PCI_CAPABILITY_SPEED_OFFSET   0xc
+#define PCI_EP_CAPABILITY_OFFSET      0x10
+
+#define CFG_RC_LINK_STATUS_CTRL_2     0x0dc
+#define CFG_RC_LINK_SPEED_SHIFT       0
+#define CFG_RC_LINK_SPEED_MASK        (0xf << CFG_RC_LINK_SPEED_SHIFT)
+
+#define CFG_RC_DEVICE_CAP             0x4d4
+#define CFG_RC_DEVICE_CAP_MPS_SHIFT   0
+#define CFG_RC_DEVICE_CAP_MPS_MASK    (0x7 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+/* MPS 256 bytes */
+#define CFG_RC_DEVICE_CAP_MPS_256B    (0x1 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+/* MPS 512 bytes */
+#define CFG_RC_DEVICE_CAP_MPS_512B    (0x2 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+
+#define CFG_RC_TL_FCIMM_NP_LIMIT       0xa10
+#define CFG_RC_TL_FCIMM_NP_VAL         0x01500000
+#define CFG_RC_TL_FCIMM_P_LIMIT        0xa14
+#define CFG_RC_TL_FCIMM_P_VAL          0x03408080
+
+#define CFG_RC_LINK_CAP               0x4dc
+#define CFG_RC_LINK_CAP_SPEED_SHIFT   0
+#define CFG_RC_LINK_CAP_SPEED_MASK    (0xf << CFG_RC_LINK_CAP_SPEED_SHIFT)
+#define CFG_RC_LINK_CAP_WIDTH_SHIFT   4
+#define CFG_RC_LINK_CAP_WIDTH_MASK    (0x1f << CFG_RC_LINK_CAP_WIDTH_SHIFT)
+
+#define CFG_LINK_CAP_RC               0x4f0
+#define CFG_RC_DL_ACTIVE_SHIFT        0
+#define CFG_RC_DL_ACTIVE_MASK         (0x1 << CFG_RC_DL_ACTIVE_SHIFT)
+#define CFG_RC_SLOT_CLK_SHIFT         1
+#define CFG_RC_SLOT_CLK_MASK          (0x1 << CFG_RC_SLOT_CLK_SHIFT)
+
+#define CFG_ROOT_CAP_RC               0x4f8
+#define CFG_ROOT_CAP_LTR_SHIFT        1
+#define CFG_ROOT_CAP_LTR_MASK         (0x1 << CFG_ROOT_CAP_LTR_SHIFT)
+
+#define CFG_RC_CLKREQ_ENABLED         0x4fc
+#define CFG_RC_CLKREQ_ENABLED_SHIFT   0
+#define CFG_RC_CLKREQ_ENABLED_MASK    (0x1 << CFG_RC_CLKREQ_ENABLED_SHIFT)
+
+#define CFG_RC_COEFF_ADDR             0x638
+
+#define CFG_RC_TL_CTRL_0              0x800
+#define RC_MEM_DW_CHK_MASK            0x03fe
+
+#define CFG_RC_PDL_CTRL_4             0x1010
+#define NPH_FC_INIT_SHIFT             24
+#define NPH_FC_INIT_MASK              (U(0xff) << NPH_FC_INIT_SHIFT)
+#define PD_FC_INIT_SHIFT              12
+#define PD_FC_INIT_MASK               (0xffff << PD_FC_INIT_SHIFT)
+
+#define CFG_RC_PDL_CTRL_5             0x1014
+#define PH_INIT_SHIFT                 0
+#define PH_INIT_MASK                  (0xff << PH_INIT_SHIFT)
+
+#define DL_STATUS_OFFSET              0x1048
+#define PHYLINKUP                     BIT(13)
+
+#define PH_INIT                       0x10
+#define PD_FC_INIT                    0x100
+#define NPH_FC_INIT                   0x8
+
+#define SRP_PH_INIT                   0x7F
+#define SRP_PD_FC_INIT                0x200
+#define SRP_NPH_FC_INIT               0x7F
+
+#define CFG_ADDR_BUS_NUM_SHIFT        20
+#define CFG_ADDR_DEV_NUM_SHIFT        15
+#define CFG_ADDR_FUNC_NUM_SHIFT       12
+#define CFG_ADDR_REG_NUM_SHIFT        2
+#define CFG_ADDR_REG_NUM_MASK         0x00000ffc
+#define CFG_ADDR_CFG_TYPE_MASK        0x00000003
+
+#define DL_LINK_UP_TIMEOUT_MS         1000
+
+#define CFG_RETRY_STATUS              0xffff0001
+#define CRS_TIMEOUT_MS                5000
+
+/* create EP config data to write */
+#define DEF_BUS_NO                    1 /* default bus 1 */
+#define DEF_SLOT_NO                   0 /* default slot 0 */
+#define DEF_FN_NO                     0 /* default fn 0 */
+
+#define EP_CONFIG_VAL(bus_no, slot, fn, where) \
+	(((bus_no) << CFG_ADDR_BUS_NUM_SHIFT) | \
+	((slot) << CFG_ADDR_DEV_NUM_SHIFT) | \
+	((fn) << CFG_ADDR_FUNC_NUM_SHIFT) | \
+	((where) & CFG_ADDR_REG_NUM_MASK) | \
+	(1 & CFG_ADDR_CFG_TYPE_MASK))
+
+/* PAXB security offset */
+#define PAXB_SECURITY_IDM_OFFSET 0x1c
+#define PAXB_SECURITY_APB_OFFSET 0x24
+#define PAXB_SECURITY_ECAM_OFFSET 0x3c
+
+#define paxb_get_config(type) paxb_get_##type##_config()
+
+static unsigned int paxb_sec_reg_offset[] = {
+	0x0c, /* PAXB0 AXI */
+	0x10, /* PAXB1 AXI */
+	0x14, /* PAXB2 AXI */
+	0x18, /* PAXB3 AXI */
+	0x20, /* PAXB4 AXI */
+	0x28, /* PAXB5 AXI */
+	0x2c, /* PAXB6 AXI */
+	0x30, /* PAXB7 AXI */
+	0x24, /* PAXB APB */
+};
+
+const paxb_cfg *paxb;
+
+/*
+ * Given a PIPEMUX strap and PCIe core index, this function returns 1 if a
+ * PCIe core needs to be enabled
+ */
+int pcie_core_needs_enable(unsigned int core_idx)
+{
+	if (paxb->core_needs_enable)
+		return paxb->core_needs_enable(core_idx);
+
+	return 0;
+}
+
+static void pcie_set_default_tx_coeff(uint32_t core_idx, uint32_t link_width)
+{
+	unsigned int lanes = 0;
+	uint32_t data, addr;
+
+	addr = CFG_RC_COEFF_ADDR;
+	for (lanes = 0; lanes < link_width; lanes = lanes + 2) {
+		data = paxb_rc_cfg_read(core_idx, addr);
+		data &= 0xf0f0f0f0;
+		data |= (7 & 0xf);
+		data |= (7 & 0xf) << 8;
+		data |= (7 & 0xf) << 16;
+		data |= (7 & 0xf) << 24;
+
+		paxb_rc_cfg_write(core_idx, addr, data);
+		addr += 4;
+	}
+}
+
+static int paxb_rc_link_init(void)
+{
+	uint32_t val, link_speed;
+	unsigned int link_width;
+	uint32_t core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		link_width = paxb->get_link_width(core_idx);
+		if (!link_width) {
+			ERROR("Unsupported PIPEMUX\n");
+			return -EOPNOTSUPP;
+		}
+
+		link_speed = paxb->get_link_speed();
+		/* program RC's link cap reg to advertise proper link width */
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP);
+		val &= ~CFG_RC_LINK_CAP_WIDTH_MASK;
+		val |= (link_width << CFG_RC_LINK_CAP_WIDTH_SHIFT);
+		paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val);
+
+		/* program RC's link cap reg to advertise proper link speed */
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP);
+		val &= ~CFG_RC_LINK_CAP_SPEED_MASK;
+		val |= link_speed << CFG_RC_LINK_CAP_SPEED_SHIFT;
+		paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val);
+
+		/* also need to program RC's link status control register */
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_STATUS_CTRL_2);
+		val &= ~(CFG_RC_LINK_SPEED_MASK);
+		val |= link_speed << CFG_RC_LINK_SPEED_SHIFT;
+		paxb_rc_cfg_write(core_idx, CFG_RC_LINK_STATUS_CTRL_2, val);
+
+#ifdef WAR_PLX_PRESET_PARITY_FAIL
+		/* WAR to avoid crash with PLX switch in GEN3*/
+		/* While PRESET, PLX switch is not fixing parity so disabled */
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_REG_PHY_CTL_10);
+		val &= ~(PHY_CTL_10_GEN3_MATCH_PARITY);
+		paxb_rc_cfg_write(core_idx, CFG_RC_REG_PHY_CTL_10, val);
+#endif
+		pcie_set_default_tx_coeff(core_idx, link_width);
+	}
+	return 0;
+}
+
+#ifdef PAXB_LINKUP
+static void paxb_perst_ctrl(unsigned int core_idx, bool assert)
+{
+	uint32_t clk_ctrl = PAXB_OFFSET(core_idx) + PAXB_CLK_CTRL_OFFSET;
+
+	if (assert) {
+		mmio_clrbits_32(clk_ctrl, PAXB_EP_PERST_SRC_SEL_MASK |
+				PAXB_EP_MODE_PERST_MASK |
+				PAXB_RC_PCIE_RST_OUT_MASK);
+		udelay(250);
+	} else {
+		mmio_setbits_32(clk_ctrl, PAXB_RC_PCIE_RST_OUT_MASK);
+		mdelay(100);
+	}
+}
+
+static void paxb_start_link_up(void)
+{
+	unsigned int core_idx;
+	uint32_t val, timeout;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		/* toggle PERST */
+		paxb_perst_ctrl(core_idx, true);
+		paxb_perst_ctrl(core_idx, false);
+
+		timeout = DL_LINK_UP_TIMEOUT_MS;
+		/* wait for Link up */
+		do {
+			val = mmio_read_32(PAXB_OFFSET(core_idx) +
+					   PAXB_CFG_LINK_STATUS_OFFSET);
+			if (val & PAXB_CFG_DL_ACTIVE_MASK)
+				break;
+
+			mdelay(1);
+		} while (--timeout);
+
+		if (!timeout)
+			ERROR("PAXB core %u link is down\n", core_idx);
+	}
+}
+#endif
+
+static void pcie_core_soft_reset(unsigned int core_idx)
+{
+	uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET;
+	uintptr_t ctrl = (uintptr_t)(PCIE_CORE_SOFT_RST_CFG_BASE + offset);
+
+	/* Put PCIe core in soft reset */
+	mmio_clrbits_32(ctrl, PCIE_CORE_SOFT_RST);
+
+	/* Wait for 1 us before pulling PCIe core out of soft reset */
+	udelay(PCIE_CORE_SOFT_RST_DELAY_US);
+
+	mmio_setbits_32(ctrl, PCIE_CORE_SOFT_RST);
+}
+
+static int pcie_core_pwron_switch(uintptr_t ctrl, uintptr_t status,
+				  uint32_t mask)
+{
+	uint32_t val;
+	unsigned int timeout = PCIE_CORE_PWR_TIMEOUT_MS;
+
+	/* enable switch */
+	mmio_setbits_32(ctrl, mask);
+
+	/* now wait for it to stabilize */
+	do {
+		val = mmio_read_32(status);
+		if ((val & mask) == mask)
+			return 0;
+		mdelay(1);
+	} while (--timeout);
+
+	return -EIO;
+}
+
+static int pcie_core_pwr_seq(uintptr_t ctrl, uintptr_t status)
+{
+	int ret;
+
+	/*
+	 * Enable the switch with the following sequence:
+	 * 1. Array weak switch output switch
+	 * 2. Array strong switch
+	 * 3. Weak switch output acknowledge
+	 * 4. Strong switch output acknowledge
+	 */
+	ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWERON);
+	if (ret)
+		return ret;
+
+	ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWEROK);
+	if (ret)
+		return ret;
+
+	ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWERON);
+	if (ret)
+		return ret;
+
+	ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWEROK);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * This function enables PCIe core and PAXB memory buffer power, and then
+ * remove the PCIe core from isolation
+ */
+static int pcie_core_pwr_init(unsigned int core_idx)
+{
+	int ret;
+	uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET;
+	uintptr_t ctrl, status;
+
+	/* enable mem power to PCIe core */
+	ctrl = (uintptr_t)(PCIE_CORE_MEM_PWR_BASE + offset);
+	status = (uintptr_t)(PCIE_CORE_MEM_PWR_STATUS_BASE + offset);
+	ret = pcie_core_pwr_seq(ctrl, status);
+	if (ret) {
+		ERROR("PCIe core mem power failed\n");
+		return ret;
+	}
+
+	/* now enable mem power to PAXB wrapper */
+	ctrl = (uintptr_t)(PCIE_PAXB_MEM_PWR_BASE + offset);
+	status = (uintptr_t)(PCIE_PAXB_MEM_PWR_STATUS_BASE + offset);
+	ret = pcie_core_pwr_seq(ctrl, status);
+	if (ret) {
+		ERROR("PAXB mem power failed\n");
+		return ret;
+	}
+
+	/* now remove power isolation */
+	ctrl = (uintptr_t)(PCIE_CORE_ISO_CFG_BASE + offset);
+	mmio_clrbits_32(ctrl, PCIE_CORE_ISO | PCIE_CORE_MEM_ISO);
+
+	return 0;
+}
+
+static void pcie_ss_reset(void)
+{
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
+			1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R);
+}
+
+/*
+ * This function reads the PIPEMUX strap, figures out all the PCIe cores that
+ * need to be enabled and enable the mem power for those cores
+ */
+static int pcie_cores_init(void)
+{
+	int ret;
+	uint32_t core_idx;
+
+	if (paxb->pipemux_init) {
+		ret = paxb->pipemux_init();
+		if (ret)
+			return ret;
+	}
+
+	/* bring PCIe subsystem out of reset */
+	pcie_ss_reset();
+
+	/* power up all PCIe cores that will be used as RC */
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		ret = pcie_core_pwr_init(core_idx);
+		if (ret) {
+			ERROR("PCIe core %u power up failed\n", core_idx);
+			return ret;
+		}
+
+		pcie_core_soft_reset(core_idx);
+
+		VERBOSE("PCIe core %u is powered up\n", core_idx);
+	}
+
+	return ret;
+}
+
+void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where,
+			      uint32_t val)
+{
+	mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET,
+		      (where & PAXB_CFG_IND_ADDR_MASK) |
+		      PAXB_CFG_CFG_TYPE_MASK);
+	mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET, val);
+}
+
+unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where)
+{
+	unsigned int val;
+
+	mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET,
+		      (where & PAXB_CFG_IND_ADDR_MASK) |
+		      PAXB_CFG_CFG_TYPE_MASK);
+	val = mmio_read_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET);
+
+	return val;
+}
+
+static void paxb_cfg_mps(void)
+{
+	uint32_t val, core_idx, mps;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_DEVICE_CAP);
+		val &= ~CFG_RC_DEVICE_CAP_MPS_MASK;
+		mps = CFG_RC_DEVICE_CAP_MPS_256B;
+		if (core_idx == 0 || core_idx == 1 ||
+		    core_idx == 6 || core_idx == 7) {
+			mps = CFG_RC_DEVICE_CAP_MPS_512B;
+		}
+		val |= mps;
+		paxb_rc_cfg_write(core_idx, CFG_RC_DEVICE_CAP, val);
+	}
+}
+
+static void paxb_cfg_dev_id(void)
+{
+	uint32_t val, core_idx;
+	uint32_t device_id;
+
+	device_id = paxb->device_id;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		/* Set Core in RC mode */
+		mmio_setbits_32(PCIE_CORE_USER_CFG +
+				(core_idx * PCIE_CORE_PWR_OFFSET), 1);
+
+		/* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
+		val = paxb_rc_cfg_read(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET);
+		val &= ~PCI_CLASS_BRIDGE_MASK;
+		val |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
+		paxb_rc_cfg_write(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET, val);
+
+		val = (VENDOR_ID << 16) | device_id;
+		paxb_rc_cfg_write(core_idx, CFG_RC_DEV_ID, val);
+
+		val = (device_id << 16) | VENDOR_ID;
+		paxb_rc_cfg_write(core_idx, CFG_RC_DEV_SUBID, val);
+	}
+}
+
+static void paxb_cfg_tgt_trn(void)
+{
+	uint32_t val, core_idx;
+
+	/*
+	 * Disable all mem Rd/Wr size check so it allows target read/write
+	 * transactions to be more than stipulated DW. As a result, PAXB root
+	 * complex will not abort these read/write transcations beyond
+	 * stipulated limit
+	 */
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_TL_CTRL_0);
+		val &= ~(RC_MEM_DW_CHK_MASK);
+		paxb_rc_cfg_write(core_idx, CFG_RC_TL_CTRL_0, val);
+	}
+}
+
+static void paxb_cfg_pdl_ctrl(void)
+{
+	uint32_t val, core_idx;
+	uint32_t nph, ph, pd;
+
+	/* increase the credit counter to 4 for non-posted header */
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		nph = NPH_FC_INIT;
+		ph = PH_INIT;
+		pd = PD_FC_INIT;
+
+		if (core_idx == 0 || core_idx == 1 ||
+		    core_idx == 6 || core_idx == 7) {
+			nph = SRP_NPH_FC_INIT;
+			ph = SRP_PH_INIT;
+			pd = SRP_PD_FC_INIT;
+		}
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_4);
+		val &= ~NPH_FC_INIT_MASK;
+		val &= ~PD_FC_INIT_MASK;
+		val = val | (nph << NPH_FC_INIT_SHIFT);
+		val = val | (pd << PD_FC_INIT_SHIFT);
+		paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_4, val);
+
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_5);
+		val &= ~PH_INIT_MASK;
+		val = val | (ph << PH_INIT_SHIFT);
+		paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_5, val);
+
+		/*
+		 * ASIC to give more optmized value after further investigation.
+		 * till then this is important to have to get similar
+		 * performance on all the slots.
+		 */
+		paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_NP_LIMIT,
+				CFG_RC_TL_FCIMM_NP_VAL);
+
+		paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_P_LIMIT,
+				CFG_RC_TL_FCIMM_P_VAL);
+	}
+}
+
+static void paxb_cfg_clkreq(void)
+{
+	uint32_t val, core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_CLKREQ_ENABLED);
+		val &= ~CFG_RC_CLKREQ_ENABLED_MASK;
+		paxb_rc_cfg_write(core_idx, CFG_RC_CLKREQ_ENABLED, val);
+	}
+}
+
+static void paxb_cfg_dl_active(bool enable)
+{
+	uint32_t val, core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_LINK_CAP_RC);
+		if (enable)
+			val |= CFG_RC_DL_ACTIVE_MASK;
+		else
+			val &= ~CFG_RC_DL_ACTIVE_MASK;
+		paxb_rc_cfg_write(core_idx, CFG_LINK_CAP_RC, val);
+	}
+}
+
+static void paxb_cfg_LTR(int enable)
+{
+	uint32_t val, core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_ROOT_CAP_RC);
+		if (enable)
+			val |= CFG_ROOT_CAP_LTR_MASK;
+		else
+			val &= ~CFG_ROOT_CAP_LTR_MASK;
+		paxb_rc_cfg_write(core_idx, CFG_ROOT_CAP_RC, val);
+	}
+}
+
+static void paxb_ib_regs_bypass(void)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < paxb->num_cores; i++) {
+		if (!pcie_core_needs_enable(i))
+			continue;
+
+		/* Configure Default IMAP window */
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP,
+			      DEFAULT_ADDR_INVALID);
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXUSER,
+			      IMAP_AXUSER);
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXCACHE,
+			      IMAP_AXCACHE);
+
+		/* Configure MSI IMAP window */
+		mmio_setbits_32(PAXB_OFFSET(i) +
+				PAXB_IMAP0_REGS_TYPE_OFFSET,
+				0x1);
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_IARR0_BASE_OFFSET,
+			      GITS_TRANSLATER | OARR_VALID);
+		for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) {
+			mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j),
+				      (GITS_TRANSLATER +
+				       (j * PAXB_IMAP0_WINDOW_SIZE)) |
+				      IMAP_VALID);
+		}
+	}
+}
+
+static void paxb_ib_regs_init(void)
+{
+	unsigned int core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		/* initialize IARR2 to zero */
+		mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_IARR2_LOWER_OFFSET,
+			      0x0);
+		mmio_setbits_32(PAXB_OFFSET(core_idx) +
+				PAXB_IMAP0_REGS_TYPE_OFFSET,
+				0x1);
+	}
+}
+
+static void paxb_cfg_apb_timeout(void)
+{
+	unsigned int core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		/* allow unlimited timeout */
+		mmio_write_32(PAXB_OFFSET(core_idx) +
+			PAXB_APB_TIMEOUT_COUNT_OFFSET,
+			0xFFFFFFFF);
+	}
+}
+
+static void paxb_smmu_cfg(void)
+{
+	unsigned int core_idx;
+	uint32_t offset;
+	uint32_t val;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		offset = core_idx * PCIE_CORE_PWR_OFFSET;
+		val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset);
+		val &= ~(0xFFF00);
+		val |= (PAXB_SMMU_SID_CFG_FUN_WIDTH |
+			PAXB_SMMU_SID_CFG_DEV_WIDTH |
+			PAXB_SMMU_SID_CFG_BUS_WIDTH);
+		mmio_write_32(PCIE_PAXB_SMMU_SID_CFG + offset, val);
+		val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset);
+		VERBOSE("smmu cfg reg 0x%x\n", val);
+	}
+}
+
+static void paxb_cfg_coherency(void)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < paxb->num_cores; i++) {
+		if (!pcie_core_needs_enable(i))
+			continue;
+
+#ifdef USE_DDR
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_OFFSET,
+			      IMAP_ARCACHE | IMAP_AWCACHE);
+#endif
+
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_0_AXUSER_OFFSET,
+			      IMAP_AXUSER);
+
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_AXUSER_OFFSET,
+			      IMAP_AXUSER);
+
+		for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) {
+#ifdef USE_DDR
+			mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP3_OFFSET(j),
+				      IMAP_ARCACHE | IMAP_AWCACHE);
+			mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP4_OFFSET(j),
+				      IMAP_ARCACHE | IMAP_AWCACHE);
+#endif
+			/* zero out IMAP0 mapping windows for MSI/MSI-X */
+			mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j),
+				      0x0);
+
+			mmio_write_32(PAXB_OFFSET(i) +
+				      PAXB_IMAP3_0_AXUSER_OFFSET(j),
+				      IMAP_AXUSER);
+			mmio_write_32(PAXB_OFFSET(i) +
+				      PAXB_IMAP4_0_AXUSER_OFFSET(j),
+				      IMAP_AXUSER);
+		}
+	}
+}
+
+/*
+ * This function configures all PAXB related blocks to allow non-secure access
+ */
+void paxb_ns_init(enum paxb_type type)
+{
+	unsigned int reg;
+
+	switch (type) {
+	case PAXB_SR:
+		for (reg = 0; reg < ARRAY_SIZE(paxb_sec_reg_offset); reg++) {
+
+			mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE +
+					paxb_sec_reg_offset[reg], 0x1);
+		}
+	/* Enabled all PAXB's relevant IDM blocks access in non-secure mode */
+	mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE + PAXB_SECURITY_IDM_OFFSET,
+			0xffff);
+		break;
+	case PAXB_NS3Z:
+		mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+				paxb_sec_reg_offset[0], 0x1);
+		mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+				PAXB_SECURITY_IDM_OFFSET, 0xffff);
+		mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+				PAXB_SECURITY_APB_OFFSET, 0x7);
+		mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+				PAXB_SECURITY_ECAM_OFFSET, 0x1);
+		break;
+	}
+}
+
+static int paxb_set_config(void)
+{
+	paxb = paxb_get_config(sr);
+	if (paxb)
+		return 0;
+
+	return -ENODEV;
+}
+
+void paxb_init(void)
+{
+	int ret;
+
+	ret = paxb_set_config();
+	if (ret)
+		return;
+
+	paxb_ns_init(paxb->type);
+
+	ret = pcie_cores_init();
+	if (ret)
+		return;
+
+	if (paxb->phy_init) {
+		ret = paxb->phy_init();
+		if (ret)
+			return;
+	}
+
+	paxb_cfg_dev_id();
+	paxb_cfg_tgt_trn();
+	paxb_cfg_pdl_ctrl();
+	if (paxb->type == PAXB_SR) {
+		paxb_ib_regs_init();
+		paxb_cfg_coherency();
+	} else
+		paxb_ib_regs_bypass();
+
+	paxb_cfg_apb_timeout();
+	paxb_smmu_cfg();
+	paxb_cfg_clkreq();
+	paxb_rc_link_init();
+
+	/* Stingray Doesn't support LTR */
+	paxb_cfg_LTR(false);
+	paxb_cfg_dl_active(true);
+
+	paxb_cfg_mps();
+
+#ifdef PAXB_LINKUP
+	paxb_start_link_up();
+#endif
+	INFO("PAXB init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/paxc.c b/plat/brcm/board/stingray/src/paxc.c
new file mode 100644
index 0000000..44af4b0
--- /dev/null
+++ b/plat/brcm/board/stingray/src/paxc.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <iommu.h>
+#include <platform_def.h>
+#include <sr_utils.h>
+
+#define PAXC_BASE                  0x60400000
+#define PAXC_AXI_CFG_PF            0x10
+#define PAXC_AXI_CFG_PF_OFFSET(pf) (PAXC_AXI_CFG_PF + (pf) * 4)
+#define PAXC_ARPROT_PF_CFG         0x40
+#define PAXC_AWPROT_PF_CFG         0x44
+
+#define PAXC_ARQOS_PF_CFG          0x48
+#define PAXC_ARQOS_VAL             0xaaaaaaaa
+
+#define PAXC_AWQOS_PF_CFG          0x4c
+#define PAXC_AWQOS_VAL             0xeeeeeeee
+
+#define PAXC_CFG_IND_ADDR_OFFSET   0x1f0
+#define PAXC_CFG_IND_ADDR_MASK     0xffc
+#define PAXC_CFG_IND_DATA_OFFSET   0x1f4
+
+/* offsets for PAXC root complex configuration space registers */
+
+#define PAXC_CFG_ID_OFFSET           0x434
+#define PAXC_RC_VENDOR_ID            0x14e4
+#define PAXC_RC_VENDOR_ID_SHIFT      16
+
+#define PAXC_RC_DEVICE_ID            0xd750
+
+#define PAXC_CFG_LINK_CAP_OFFSET     0x4dc
+#define PAXC_RC_LINK_CAP_SPD_SHIFT   0
+#define PAXC_RC_LINK_CAP_SPD_MASK    (0xf << PAXC_RC_LINK_CAP_SPD_SHIFT)
+#define PAXC_RC_LINK_CAP_SPD         3
+#define PAXC_RC_LINK_CAP_WIDTH_SHIFT 4
+#define PAXC_RC_LINK_CAP_WIDTH_MASK  (0x1f << PAXC_RC_LINK_CAP_WIDTH_SHIFT)
+#define PAXC_RC_LINK_CAP_WIDTH       16
+
+/* offsets for MHB registers */
+
+#define MHB_BASE                   0x60401000
+#define MHB_MEM_PWR_STATUS_PAXC    (MHB_BASE + 0x1c0)
+#define MHB_PWR_ARR_POWERON        0x8
+#define MHB_PWR_ARR_POWEROK        0x4
+#define MHB_PWR_POWERON            0x2
+#define MHB_PWR_POWEROK            0x1
+#define MHB_PWR_STATUS_MASK        (MHB_PWR_ARR_POWERON | \
+				    MHB_PWR_ARR_POWEROK | \
+				    MHB_PWR_POWERON | \
+				    MHB_PWR_POWEROK)
+
+/* max number of PFs from Nitro that PAXC sees */
+#define MAX_NR_NITRO_PF            8
+
+#ifdef EMULATION_SETUP
+static void paxc_reg_dump(void)
+{
+}
+#else
+/* total number of PAXC registers */
+#define NR_PAXC_REGS               53
+static void paxc_reg_dump(void)
+{
+	uint32_t idx, offset = 0;
+
+	VERBOSE("PAXC register dump start\n");
+	for (idx = 0; idx < NR_PAXC_REGS; idx++, offset += 4)
+		VERBOSE("offset: 0x%x val: 0x%x\n", offset,
+			mmio_read_32(PAXC_BASE + offset));
+	VERBOSE("PAXC register dump end\n");
+}
+#endif /* EMULATION_SETUP */
+
+#ifdef EMULATION_SETUP
+static void mhb_reg_dump(void)
+{
+}
+#else
+#define NR_MHB_REGS                227
+static void mhb_reg_dump(void)
+{
+	uint32_t idx, offset = 0;
+
+	VERBOSE("MHB register dump start\n");
+	for (idx = 0; idx < NR_MHB_REGS; idx++, offset += 4)
+		VERBOSE("offset: 0x%x val: 0x%x\n", offset,
+			mmio_read_32(MHB_BASE + offset));
+	VERBOSE("MHB register dump end\n");
+}
+#endif /* EMULATION_SETUP */
+
+static void paxc_rc_cfg_write(uint32_t where, uint32_t val)
+{
+	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
+		      where & PAXC_CFG_IND_ADDR_MASK);
+	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET, val);
+}
+
+static uint32_t paxc_rc_cfg_read(uint32_t where)
+{
+	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
+		      where & PAXC_CFG_IND_ADDR_MASK);
+	return mmio_read_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET);
+}
+
+/*
+ * Function to program PAXC root complex link capability register
+ */
+static void paxc_cfg_link_cap(void)
+{
+	uint32_t val;
+
+	val = paxc_rc_cfg_read(PAXC_CFG_LINK_CAP_OFFSET);
+	val &= ~(PAXC_RC_LINK_CAP_SPD_MASK | PAXC_RC_LINK_CAP_WIDTH_MASK);
+	val |= (PAXC_RC_LINK_CAP_SPD << PAXC_RC_LINK_CAP_SPD_SHIFT) |
+		(PAXC_RC_LINK_CAP_WIDTH << PAXC_RC_LINK_CAP_WIDTH_SHIFT);
+	paxc_rc_cfg_write(PAXC_CFG_LINK_CAP_OFFSET, val);
+}
+
+/*
+ * Function to program PAXC root complex vendor ID and device ID
+ */
+static void paxc_cfg_id(void)
+{
+	uint32_t val;
+
+	val = (PAXC_RC_VENDOR_ID << PAXC_RC_VENDOR_ID_SHIFT) |
+		PAXC_RC_DEVICE_ID;
+	paxc_rc_cfg_write(PAXC_CFG_ID_OFFSET, val);
+}
+
+void paxc_init(void)
+{
+	unsigned int pf_index;
+	unsigned int val;
+
+	val = mmio_read_32(MHB_MEM_PWR_STATUS_PAXC);
+	if ((val & MHB_PWR_STATUS_MASK) != MHB_PWR_STATUS_MASK) {
+		INFO("PAXC not powered\n");
+		return;
+	}
+
+	paxc_cfg_id();
+	paxc_cfg_link_cap();
+
+	paxc_reg_dump();
+	mhb_reg_dump();
+
+#ifdef USE_DDR
+	/*
+	 * Set AWCACHE and ARCACHE to 0xff (Cacheable write-back,
+	 * allocate on both reads and writes) per
+	 * recommendation from the ASIC team
+	 */
+	val = 0xff;
+#else
+	/* disable IO cache if non-DDR memory is used, e.g., external SRAM */
+	val = 0x0;
+#endif
+	for (pf_index = 0; pf_index < MAX_NR_NITRO_PF; pf_index++)
+		mmio_write_32(PAXC_BASE + PAXC_AXI_CFG_PF_OFFSET(pf_index),
+			      val);
+
+	/*
+	 * Set ARPROT and AWPROT to enable non-secure access from
+	 * PAXC to all PFs, PF0 to PF7
+	 */
+	mmio_write_32(PAXC_BASE + PAXC_ARPROT_PF_CFG, 0x22222222);
+	mmio_write_32(PAXC_BASE + PAXC_AWPROT_PF_CFG, 0x22222222);
+
+	mmio_write_32(PAXC_BASE + PAXC_ARQOS_PF_CFG, PAXC_ARQOS_VAL);
+	mmio_write_32(PAXC_BASE + PAXC_AWQOS_PF_CFG, PAXC_AWQOS_VAL);
+
+	INFO("PAXC init done\n");
+}
+
+/*
+ * These defines do not match the regfile but they are renamed in a way such
+ * that they are much more readible
+ */
+
+#define MHB_NIC_SECURITY_BASE  0x60500000
+#define MHB_NIC_PAXC_AXI_NS    0x0008
+#define MHB_NIC_IDM_NS         0x000c
+#define MHB_NIC_MHB_APB_NS     0x0010
+#define MHB_NIC_NITRO_AXI_NS   0x0014
+#define MHB_NIC_PCIE_AXI_NS    0x0018
+#define MHB_NIC_PAXC_APB_NS    0x001c
+#define MHB_NIC_EP_APB_NS      0x0020
+
+#define MHB_NIC_PAXC_APB_S_IDM_SHIFT     5
+#define MHB_NIC_EP_APB_S_IDM_SHIFT       4
+#define MHB_NIC_MHB_APB_S_IDM_SHIFT      3
+#define MHB_NIC_PAXC_AXI_S_IDM_SHIFT     2
+#define MHB_NIC_PCIE_AXI_S_IDM_SHIFT     1
+#define MHB_NIC_NITRO_AXI_S_IDM_SHIFT    0
+
+#define NIC400_NITRO_TOP_NIC_SECURITY_BASE 0x60d00000
+
+#define NITRO_NIC_SECURITY_3_SHIFT       0x14
+#define NITRO_NIC_SECURITY_4_SHIFT       0x18
+#define NITRO_NIC_SECURITY_5_SHIFT       0x1c
+#define NITRO_NIC_SECURITY_6_SHIFT       0x20
+
+void paxc_mhb_ns_init(void)
+{
+	unsigned int val;
+	uintptr_t mhb_nic_gpv = MHB_NIC_SECURITY_BASE;
+#ifndef NITRO_SECURE_ACCESS
+	uintptr_t nic400_nitro_gpv = NIC400_NITRO_TOP_NIC_SECURITY_BASE;
+#endif /* NITRO_SECURE_ACCESS */
+
+	/* set PAXC AXI to allow non-secure access */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS, val);
+
+	/* set various MHB IDM interfaces to allow non-secure access */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_IDM_NS);
+	val |= (0x1 << MHB_NIC_PAXC_APB_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_EP_APB_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_MHB_APB_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_PAXC_AXI_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_PCIE_AXI_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_NITRO_AXI_S_IDM_SHIFT);
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_IDM_NS, val);
+
+	/* set MHB APB to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS, val);
+
+	/* set Nitro AXI to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS, val);
+
+	/* set PCIe AXI to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS, val);
+
+	/* set PAXC APB to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS, val);
+
+	/* set EP APB to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS, val);
+
+#ifndef NITRO_SECURE_ACCESS
+	/* Set NIC400 to allow non-secure access */
+	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_3_SHIFT, 0x1);
+	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_4_SHIFT, 0x1);
+	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_5_SHIFT, 0x1);
+	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_6_SHIFT, 0x1);
+#endif /* NITRO_SECURE_ACCESS */
+}
diff --git a/plat/brcm/board/stingray/src/pm.c b/plat/brcm/board/stingray/src/pm.c
new file mode 100644
index 0000000..a5ac2e7
--- /dev/null
+++ b/plat/brcm/board/stingray/src/pm.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/ccn.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+
+#ifdef USE_PAXC
+#include <chimp.h>
+#endif
+#include <cmn_plat_util.h>
+#include <ihost_pm.h>
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+static uint64_t plat_sec_entrypoint;
+
+/*******************************************************************************
+ * SR handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int brcm_pwr_domain_on(u_register_t mpidr)
+{
+	int cpuid;
+
+	cpuid = plat_brcm_calc_core_pos(mpidr);
+	INFO("mpidr :%lu, cpuid:%d\n", mpidr, cpuid);
+
+#ifdef USE_SINGLE_CLUSTER
+	if (cpuid > 1)
+		return PSCI_E_INTERN_FAIL;
+#endif
+
+	ihost_power_on_cluster(mpidr);
+
+	ihost_power_on_secondary_core(mpidr, plat_sec_entrypoint);
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * SR handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
+
+	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+					PLAT_LOCAL_STATE_OFF);
+
+	if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
+					PLAT_LOCAL_STATE_OFF) {
+		INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id);
+		ccn_enter_snoop_dvm_domain(1 << cluster_id);
+	}
+
+	/* Enable the gic cpu interface */
+	plat_brcm_gic_pcpu_init();
+
+	/* Program the gic per-cpu distributor or re-distributor interface */
+	plat_brcm_gic_cpuif_enable();
+
+	INFO("Gic Initialization done for this affinity instance\n");
+}
+
+static void __dead2 brcm_system_reset(void)
+{
+	uint32_t reset_type = SOFT_SYS_RESET_L1;
+
+#ifdef USE_PAXC
+	if (bcm_chimp_is_nic_mode())
+		reset_type = SOFT_RESET_L3;
+#endif
+	INFO("System rebooting - L%d...\n", reset_type);
+
+	plat_soft_reset(reset_type);
+
+	/* Prevent the function to return due to the attribute */
+	while (1)
+		;
+}
+
+static int brcm_system_reset2(int is_vendor, int reset_type,
+			      u_register_t cookie)
+{
+	INFO("System rebooting - L%d...\n", reset_type);
+
+	plat_soft_reset(reset_type);
+
+	/*
+	 * plat_soft_reset cannot return (it is a __dead function),
+	 * but brcm_system_reset2 has to return some value, even in
+	 * this case.
+	 */
+	return 0;
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard
+ * platform will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+const plat_psci_ops_t plat_brcm_psci_pm_ops = {
+	.pwr_domain_on		= brcm_pwr_domain_on,
+	.pwr_domain_on_finish	= brcm_pwr_domain_on_finish,
+	.system_reset		= brcm_system_reset,
+	.system_reset2		= brcm_system_reset2
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	*psci_ops = &plat_brcm_psci_pm_ops;
+	plat_sec_entrypoint = sec_entrypoint;
+
+	return 0;
+}
diff --git a/plat/brcm/board/stingray/src/scp_cmd.c b/plat/brcm/board/stingray/src/scp_cmd.c
new file mode 100644
index 0000000..2aa9519
--- /dev/null
+++ b/plat/brcm/board/stingray/src/scp_cmd.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <drivers/delay_timer.h>
+
+#include <platform_def.h>
+#include <scp.h>
+#include <scp_cmd.h>
+
+#include "m0_ipc.h"
+
+/*
+ * Reads a response from CRMU MAILBOX
+ * Assumes that access has been granted and locked.
+ * Note that this is just a temporary implementation until
+ * channels are introduced
+ */
+static void scp_read_response(crmu_response_t *resp)
+{
+	uint32_t code;
+
+	code = mmio_read_32(CRMU_MAIL_BOX0);
+	resp->completed = code & MCU_IPC_CMD_DONE_MASK;
+	resp->cmd = code & SCP_CMD_MASK;
+	resp->ret = (code & MCU_IPC_CMD_REPLY_MASK) >> MCU_IPC_CMD_REPLY_SHIFT;
+}
+
+/*
+ * Send a command to SCP and wait for timeout us.
+ * Return:  0 on success
+ *         -1 if there was no proper reply from SCP
+ *         >0 if there was a response from MCU, but
+ *            command completed with an error.
+ */
+int scp_send_cmd(uint32_t cmd, uint32_t param, uint32_t timeout)
+{
+	int ret = -1;
+
+	mmio_write_32(CRMU_MAIL_BOX0, cmd);
+	mmio_write_32(CRMU_MAIL_BOX1, param);
+	do {
+		crmu_response_t scp_resp;
+
+		udelay(1);
+		scp_read_response(&scp_resp);
+		if (scp_resp.completed &&
+			(scp_resp.cmd == cmd)) {
+			/* This command has completed */
+			ret = scp_resp.ret;
+			break;
+		}
+	} while (--timeout);
+
+	return ret;
+}
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;
+}
diff --git a/plat/brcm/board/stingray/src/sdio.c b/plat/brcm/board/stingray/src/sdio.c
new file mode 100644
index 0000000..aa2b71a
--- /dev/null
+++ b/plat/brcm/board/stingray/src/sdio.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <sdio.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+const SDIO_CFG sr_sdio0_cfg = {
+	.cfg_base = SR_IPROC_SDIO0_CFG_BASE,
+	.sid_base = SR_IPROC_SDIO0_SID_BASE,
+	.io_ctrl_base = SR_IPROC_SDIO0_IOCTRL_BASE,
+	.pad_base = SR_IPROC_SDIO0_PAD_BASE,
+};
+const SDIO_CFG sr_sdio1_cfg = {
+	.cfg_base = SR_IPROC_SDIO1_CFG_BASE,
+	.sid_base = SR_IPROC_SDIO1_SID_BASE,
+	.io_ctrl_base = SR_IPROC_SDIO1_IOCTRL_BASE,
+	.pad_base = SR_IPROC_SDIO1_PAD_BASE,
+};
+
+void brcm_stingray_sdio_init(void)
+{
+	unsigned int val;
+	const SDIO_CFG *sdio0_cfg, *sdio1_cfg;
+
+	sdio0_cfg = &sr_sdio0_cfg;
+	sdio1_cfg = &sr_sdio1_cfg;
+
+	INFO("set sdio0 caps\n");
+	/* SDIO0 CAPS0 */
+	val = SDIO0_CAP0_CFG;
+	INFO("caps0 0x%x\n", val);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP0, val);
+
+	/* SDIO0 CAPS1 */
+	val = SDIO0_CAP1_CFG;
+	INFO("caps1 0x%x\n", val);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP1, val);
+
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0,
+		      SDIO_PRESETVAL0);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1,
+		      SDIO_PRESETVAL1);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2,
+		      SDIO_PRESETVAL2);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3,
+		      SDIO_PRESETVAL3);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4,
+		      SDIO_PRESETVAL4);
+
+	val = SR_SID_VAL(0x3, 0x0, 0x2) << SDIO_SID_SHIFT;
+	mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val);
+	mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val);
+
+	val = mmio_read_32(sdio0_cfg->io_ctrl_base);
+	val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */
+	val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */
+	mmio_write_32(sdio0_cfg->io_ctrl_base, val);
+
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CLK,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA0,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA1,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA2,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA3,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA4,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA5,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA6,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA7,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CMD,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+
+	INFO("set sdio1 caps\n");
+
+	/* SDIO1 CAPS0 */
+	val = SDIO1_CAP0_CFG;
+	INFO("caps0 0x%x\n", val);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP0, val);
+	/* SDIO1 CAPS1 */
+	val = SDIO1_CAP1_CFG;
+	INFO("caps1 0x%x\n", val);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP1, val);
+
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0,
+		      SDIO_PRESETVAL0);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1,
+		      SDIO_PRESETVAL1);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2,
+		      SDIO_PRESETVAL2);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3,
+		      SDIO_PRESETVAL3);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4,
+		      SDIO_PRESETVAL4);
+
+	val = SR_SID_VAL(0x3, 0x0, 0x3) << SDIO_SID_SHIFT;
+	mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val);
+	mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val);
+
+	val = mmio_read_32(sdio1_cfg->io_ctrl_base);
+	val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */
+	val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */
+	mmio_write_32(sdio1_cfg->io_ctrl_base, val);
+
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CLK,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA0,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA1,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA2,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA3,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA4,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA5,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA6,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA7,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CMD,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+
+	INFO("sdio init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/sr_paxb_phy.c b/plat/brcm/board/stingray/src/sr_paxb_phy.c
new file mode 100644
index 0000000..7380e09
--- /dev/null
+++ b/plat/brcm/board/stingray/src/sr_paxb_phy.c
@@ -0,0 +1,806 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <paxb.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+/* total number of PCIe Phys */
+#define NUM_OF_PCIE_SERDES            8
+
+#define CFG_RC_PMI_ADDR               0x1130
+#define PMI_RX_TERM_SEQ               ((0x1 << 27) | (0x1ff << 16) | (0xd090))
+#define PMI_RX_TERM_VAL               0x4c00
+#define PMI_PLL_CTRL_4                0xd0b4
+#define PMI_SERDES_CLK_ENABLE         (1 << 12)
+
+#define WAR_PLX_PRESET_PARITY_FAIL
+
+#define CFG_RC_REG_PHY_CTL_10         0x1838
+#define PHY_CTL_10_GEN3_MATCH_PARITY  (1 << 15)
+
+#define PMI_X8_CORE0_7_PATCH_SEQ      ((0x1 << 27) | (0x1ff << 16) | (0xd2a5))
+#define PMI_X8_CORE0_7_PATCH_VAL      0xd864
+
+#define PMI_ADDR_BCAST(addr)          ((0x1 << 27) | (0x1ff << 16) | (addr))
+#define PMI_ADDR_LANE0(addr)          ((0x1 << 27) | (addr))
+#define PMI_ADDR_LANE1(addr)          ((0x1 << 27) | (0x1 << 16) | (addr))
+
+#define MERLIN16_PCIE_BLK2_PWRMGMT_7	((0x1 << 27) | (0x1ff << 16) | 0x1208)
+#define MERLIN16_PCIE_BLK2_PWRMGMT_8	((0x1 << 27) | (0x1ff << 16) | 0x1209)
+#define MERLIN16_AMS_TX_CTRL_5		((0x1 << 27) | (0x1ff << 16) | 0xd0a5)
+#define MERLIN16_AMS_TX_CTRL_5_VAL	\
+		((1 << 13) | (1 << 12) | (1 << 11) | (1 << 10))
+#define MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL   0x96
+#define MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL   0x12c
+
+#define CFG_RC_PMI_WDATA              0x1134
+#define CFG_RC_WCMD_SHIFT             31
+#define CFG_RC_WCMD_MASK              ((uint32_t)1U << CFG_RC_WCMD_SHIFT)
+#define CFG_RC_RCMD_SHIFT             30
+#define CFG_RC_RCMD_MASK              ((uint32_t)1U << CFG_RC_RCMD_SHIFT)
+#define CFG_RC_RWCMD_MASK             (CFG_RC_RCMD_MASK | CFG_RC_WCMD_MASK)
+#define CFG_RC_PMI_RDATA              0x1138
+#define CFG_RC_RACK_SHIFT             31
+#define CFG_RC_RACK_MASK              ((uint32_t)1U << CFG_RC_RACK_SHIFT)
+
+/* allow up to 5 ms for PMI write to finish */
+#define PMI_TIMEOUT_MS                5
+
+/* in 2x8 RC mode, one needs to patch up Serdes 3 and 7 for link to come up */
+#define SERDES_PATCH_PIPEMUX_INDEX    0x3
+#define SERDES_PATCH_INDEX            0x8
+
+#define DSC_UC_CTRL                   0xd00d
+#define DSC_UC_CTRL_RDY_CMD           (1 << 7)
+#define LANE_DBG_RST_CTRL             0xd164
+#define UC_A_CLK_CTRL0                0xd200
+#define UC_A_RST_CTRL0                0xd201
+#define UC_A_AHB_CTRL0                0xd202
+#define UC_A_AHB_STAT0                0xd203
+#define UC_A_AHB_WADDR_LSW            0xd204
+#define UC_A_AHB_WADDR_MSW            0xd205
+#define UC_A_AHB_WDATA_LSW            0xd206
+#define UC_A_AHB_WDATA_MSW            0xd207
+#define UC_A_AHB_RADDR_LSW            0xd208
+#define UC_A_AHB_RADDR_MSW            0xd209
+#define UC_A_AHB_RDATA_LSW            0xd20a
+#define UC_A_AHB_RDATA_MSW            0xd20b
+#define UC_VERSION_NUM                0xd230
+#define DSC_SM_CTL22                  0xd267
+#define UC_DBG1                       0xd251
+
+#define LOAD_UC_CHECK                 0
+#define UC_RAM_INIT_TIMEOUT           100
+#define UC_RAM_CONTROL                0xd225
+#define UC_INIT_TIMEOUT               100
+#define SIZE_ALIGN(x, a)              (((x) + (a) - 1) & ~((a) - 1))
+#define SZ_4                          4
+#define GET_2_BYTES(p, i)             ((uint16_t)p[i] | (uint16_t)p[i+1] << 8)
+
+/*
+ * List of PCIe LCPLL related registers
+ *
+ * LCPLL channel 0 provides the Serdes pad clock when running in RC mode
+ */
+#define PCIE_LCPLL_BASE             0x40000000
+
+#define PCIE_LCPLL_CTRL0_OFFSET     0x00
+#define PCIE_LCPLL_RESETB_SHIFT     31
+#define PCIE_LCPLL_RESETB_MASK      BIT(PCIE_LCPLL_RESETB_SHIFT)
+#define PCIE_LCPLL_P_RESETB_SHIFT   30
+#define PCIE_LCPLL_P_RESETB_MASK    BIT(PCIE_LCPLL_P_RESETB_SHIFT)
+
+#define PCIE_LCPLL_CTRL3_OFFSET     0x0c
+#define PCIE_LCPLL_EN_CTRL_SHIFT    16
+#define PCIE_LCPLL_CM_ENA           0x1a
+#define PCIE_LCPLL_CM_BUF_ENA       0x18
+#define PCIE_LCPLL_D2C2_ENA         0x2
+#define PCIE_LCPLL_REF_CLK_SHIFT    1
+#define PCIE_LCPLL_REF_CLK_MASK     BIT(PCIE_LCPLL_REF_CLK_SHIFT)
+#define PCIE_LCPLL_CTRL13_OFFSET    0x34
+#define PCIE_LCPLL_D2C2_CTRL_SHIFT  16
+#define PCIE_LCPLL_D2C2_TERM_DISC   0xe0
+
+#define PCIE_LCPLL_STATUS_OFFSET    0x40
+#define PCIE_LCPLL_LOCK_SHIFT       12
+#define PCIE_LCPLL_LOCK_MASK        BIT(PCIE_LCPLL_LOCK_SHIFT)
+
+#define PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG  0x114
+#define PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG 0x11c
+
+/* wait 500 microseconds for PCIe LCPLL to power up */
+#define PCIE_LCPLL_DELAY_US         500
+
+/* allow up to 5 ms for PCIe LCPLL VCO to lock */
+#define PCIE_LCPLL_TIMEOUT_MS       5
+
+#define PCIE_PIPE_MUX_CONFIGURATION_CFG  0x4000010c
+
+#define PCIE_PIPEMUX_SHIFT        19
+#define PCIE_PIPEMUX_MASK         0xf
+
+/* keep track of PIPEMUX index to use */
+static unsigned int pipemux_idx;
+
+/*
+ * PCIe PIPEMUX lookup table
+ *
+ * Each array index represents a PIPEMUX strap setting
+ * The array element represents a bitmap where a set bit means the PCIe core
+ * needs to be enabled as RC
+ */
+static uint8_t pipemux_table[] = {
+	/* PIPEMUX = 0, EP 1x16 */
+	0x00,
+	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+	0x80,
+	/* PIPEMUX = 2, EP 4x4 */
+	0x00,
+	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+	0x81,
+	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+	0xc3,
+	/* PIPEMUX = 5, RC 8x2, all 8 cores */
+	0xff,
+	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+	0xcd,
+	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+	0xfd,
+	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+	0xf0,
+	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+	0xc0,
+	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+	0x42,
+	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+	0x3c,
+	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+	0xfc,
+	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+	0x4c,
+};
+
+/*
+ * Return 1 if pipemux strap is supported
+ */
+static int pipemux_strap_is_valid(uint32_t pipemux)
+{
+	if (pipemux < ARRAY_SIZE(pipemux_table))
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * Read the PCIe PIPEMUX from strap
+ */
+static uint32_t pipemux_strap_read(void)
+{
+	uint32_t pipemux;
+
+	pipemux = mmio_read_32(PCIE_PIPE_MUX_CONFIGURATION_CFG);
+	pipemux &= PCIE_PIPEMUX_MASK;
+	if (pipemux == PCIE_PIPEMUX_MASK) {
+		/* read the PCIe PIPEMUX strap setting */
+		pipemux = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
+		pipemux >>= PCIE_PIPEMUX_SHIFT;
+		pipemux &= PCIE_PIPEMUX_MASK;
+	}
+
+	return pipemux;
+}
+
+/*
+ * Store the PIPEMUX index (set for each boot)
+ */
+static void pipemux_save_index(unsigned int idx)
+{
+	pipemux_idx = idx;
+}
+
+static int paxb_sr_core_needs_enable(unsigned int core_idx)
+{
+	return !!((pipemux_table[pipemux_idx] >> core_idx) & 0x1);
+}
+
+static int pipemux_sr_init(void)
+{
+	uint32_t pipemux;
+
+	/* read the PCIe PIPEMUX strap setting */
+	pipemux = pipemux_strap_read();
+	if (!pipemux_strap_is_valid(pipemux)) {
+		ERROR("Invalid PCIe PIPEMUX strap %u\n", pipemux);
+		return -EIO;
+	}
+
+	/* no PCIe RC is needed */
+	if (!pipemux_table[pipemux]) {
+		WARN("PIPEMUX indicates no PCIe RC required\n");
+		return -ENODEV;
+	}
+
+	/* save the PIPEMUX strap */
+	pipemux_save_index(pipemux);
+
+	return 0;
+}
+
+/*
+ * PCIe RC serdes link width
+ *
+ * The array is first organized in rows as indexed by the PIPEMUX setting.
+ * Within each row, eight lane width entries are specified -- one entry
+ * per PCIe core, from 0 to 7.
+ *
+ * Note: The EP lanes/cores are not mapped in this table!  EP cores are
+ *       controlled and thus configured by Nitro.
+ */
+static uint8_t link_width_table[][NUM_OF_SR_PCIE_CORES] = {
+	/* PIPEMUX = 0, EP 1x16 */
+	{0, 0, 0, 0, 0, 0, 0, 0},
+	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+	{0, 0, 0, 0, 0, 0, 0, 8},
+	/* PIPEMUX = 2, EP 4x4 */
+	{0, 0, 0, 0, 0, 0, 0, 0},
+	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+	{8, 0, 0, 0, 0, 0, 0, 8},
+	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+	{4, 4, 0, 0, 0, 0, 4, 4},
+	/* PIPEMUX = 5, RC 8x2, all 8 cores */
+	{2, 2, 2, 2, 2, 2, 2, 2},
+	/* PIPEMUX = 6, RC 3x4 (cores 0, 6, 7), RC 2x2 (cores 2, 3) */
+	{4, 0, 2, 2, 0, 0, 4, 4},
+	/* PIPEMUX = 7, RC 1x4 (core 0), RC 6x2 (cores 2, 3, 4, 5, 6, 7 */
+	{4, 0, 2, 2, 2, 2, 2, 2},
+	/* PIPEMUX = 8, EP 1x8 + RC 4x2 (cores 4, 5, 6, 7) */
+	{0, 0, 0, 0, 2, 2, 2, 2},
+	/* PIPEMUX = 9, EP 1x8 + RC 2x4 (cores 6, 7) */
+	{0, 0, 0, 0, 0, 0, 4, 4},
+	/* PIPEMUX = 10, EP 2x4 + RC 2x4 (cores 1, 6) */
+	{0, 4, 0, 0, 0, 0, 4, 0},
+	/* PIPEMUX = 11, EP 2x4 + RC 4x2 (cores 2, 3, 4, 5) */
+	{0, 0, 2, 2, 2, 2, 0, 0},
+	/* PIPEMUX = 12, EP 1x4 + RC 6x2 (cores 2, 3, 4, 5, 6, 7) */
+	{0, 0, 2, 2, 2, 2, 2, 2},
+	/* PIPEMUX = 13, EP 2x4 + RC 1x4 (core 6) + RC 2x2 (cores 2, 3) */
+	{0, 0, 2, 2, 0, 0, 4, 0}
+};
+
+/*
+ * function for writes to the Serdes registers through the PMI interface
+ */
+static int paxb_pmi_write(unsigned int core_idx, uint32_t pmi, uint32_t val)
+{
+	uint32_t status;
+	unsigned int timeout = PMI_TIMEOUT_MS;
+
+	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
+
+	val &= ~CFG_RC_RWCMD_MASK;
+	val |= CFG_RC_WCMD_MASK;
+	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, val);
+
+	do {
+		status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_WDATA);
+
+		/* wait for write command bit to clear */
+		if ((status & CFG_RC_WCMD_MASK) == 0)
+			return 0;
+	} while (--timeout);
+
+	return -EIO;
+}
+
+/*
+ * function for reads from the Serdes registers through the PMI interface
+ */
+static int paxb_pmi_read(unsigned int core_idx, uint32_t pmi, uint32_t *val)
+{
+	uint32_t status;
+	unsigned int timeout = PMI_TIMEOUT_MS;
+
+	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
+
+	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, CFG_RC_RCMD_MASK);
+
+	do {
+		status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
+
+		/* wait for read ack bit set */
+		if ((status & CFG_RC_RACK_MASK)) {
+			*val = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
+			return 0;
+		}
+	} while (--timeout);
+
+	return -EIO;
+}
+
+
+#ifndef BOARD_PCIE_EXT_CLK
+/*
+ * PCIe Override clock lookup table
+ *
+ * Each array index represents pcie override clock has been done
+ * by CFW or not.
+ */
+static uint8_t pcie_override_clk_table[] = {
+	/* PIPEMUX = 0, EP 1x16 */
+	0x0,
+	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+	0x1,
+	/* PIPEMUX = 2, EP 4x4 */
+	0x0,
+	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+	0x0,
+	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+	0x0,
+	/* PIPEMUX = 5, RC 8x2, all 8 cores */
+	0x0,
+	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+	0x0,
+	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+	0x0,
+	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+	0x0,
+	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+	0x0,
+	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+	0x0,
+	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+	0x0,
+	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+	0x0,
+	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+	0x0,
+};
+
+/*
+ * Bring up LCPLL channel 0 reference clock for PCIe serdes used in RC mode
+ */
+static int pcie_lcpll_init(void)
+{
+	uintptr_t reg;
+	unsigned int timeout = PCIE_LCPLL_TIMEOUT_MS;
+	uint32_t val;
+
+	if (pcie_override_clk_table[pipemux_idx]) {
+		/*
+		 * Check rc_mode_override again to avoid halt
+		 * because of cfw uninitialized lcpll.
+		 */
+		reg = (uintptr_t)(PCIE_LCPLL_BASE +
+				  PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG);
+		val = mmio_read_32(reg);
+		if (val & 0x1)
+			return 0;
+		else
+			return -ENODEV;
+	}
+
+	/* power on PCIe LCPLL and its LDO */
+	reg = (uintptr_t)CRMU_AON_CTRL1;
+	mmio_setbits_32(reg, CRMU_PCIE_LCPLL_PWR_ON_MASK |
+			     CRMU_PCIE_LCPLL_PWRON_LDO_MASK);
+	udelay(PCIE_LCPLL_DELAY_US);
+
+	/* remove isolation */
+	mmio_clrbits_32(reg, CRMU_PCIE_LCPLL_ISO_IN_MASK);
+	udelay(PCIE_LCPLL_DELAY_US);
+
+	/* disconnect termination */
+	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL13_OFFSET);
+	mmio_setbits_32(reg, PCIE_LCPLL_D2C2_TERM_DISC <<
+			PCIE_LCPLL_D2C2_CTRL_SHIFT);
+
+	/* enable CML buf1/2 and D2C2 */
+	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET);
+	mmio_setbits_32(reg, PCIE_LCPLL_CM_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
+
+	/* select diff clock mux out as ref clock */
+	mmio_clrbits_32(reg, PCIE_LCPLL_REF_CLK_MASK);
+
+	/* delay for 500 microseconds per ASIC spec for PCIe LCPLL */
+	udelay(PCIE_LCPLL_DELAY_US);
+
+	/* now bring PCIe LCPLL out of reset */
+	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL0_OFFSET);
+	mmio_setbits_32(reg, PCIE_LCPLL_RESETB_MASK);
+
+	/* wait for PLL to lock */
+	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_STATUS_OFFSET);
+	do {
+		val = mmio_read_32(reg);
+		if ((val & PCIE_LCPLL_LOCK_MASK) == PCIE_LCPLL_LOCK_MASK) {
+			/* now bring the post divider out of reset */
+			reg = (uintptr_t)(PCIE_LCPLL_BASE +
+					  PCIE_LCPLL_CTRL0_OFFSET);
+			mmio_setbits_32(reg, PCIE_LCPLL_P_RESETB_MASK);
+			VERBOSE("PCIe LCPLL locked\n");
+			return 0;
+		}
+		mdelay(1);
+	} while (--timeout);
+
+	ERROR("PCIe LCPLL failed to lock\n");
+	return -EIO;
+}
+#else
+/*
+ * Bring up EXT CLK reference clock for PCIe serdes used in RC mode
+ * XTAL_BYPASS		(3 << 0)
+ * INTR_LC_REF		(5 << 0)
+ * PD_CML_LC_REF_OUT	(1 << 4)
+ * PD_CML_REF_CH_OUT	(1 << 8)
+ * CLK_MASTER_SEL	(1 << 11)
+ * CLK_MASTER_CTRL_A	(1 << 12)
+ * CLK_MASTER_CTRL_B	(2 << 14)
+ */
+static const uint16_t pcie_ext_clk[][NUM_OF_PCIE_SERDES] = {
+	/* PIPEMUX = 0, EP 1x16 */
+	{0},
+	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+	{0},
+	/* PIPEMUX = 2, EP 4x4 */
+	{0},
+	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+	{0x8803, 0x9115, 0x9115, 0x1115, 0x8803, 0x9115, 0x9115, 0x1115},
+	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+	{0x8803, 0x1115, 0x8915, 0x1115, 0x8803, 0x1115, 0x8915, 0x1115,},
+	/* PIPEMUX = 5, RC 8x2, all 8 cores */
+	{0x0803, 0x0915, 0x0915, 0x0915, 0x0803, 0x0915, 0x0915, 0x0915,},
+	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+	{0},
+	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+	{0},
+	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+	{0},
+	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+	{0},
+	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+	{0},
+	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+	{0},
+	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+	{0},
+	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+	{0},
+};
+
+static void pcie_ext_clk_init(void)
+{
+	unsigned int serdes;
+	uint32_t val;
+
+	for (serdes = 0; serdes < NUM_OF_PCIE_SERDES; serdes++) {
+		val = pcie_ext_clk[pipemux_idx][serdes];
+		if (!val)
+			return;
+		mmio_write_32(PCIE_CORE_RESERVED_CFG +
+			      serdes * PCIE_CORE_PWR_OFFSET, val);
+	}
+	/* disable CML buf1/2 and enable D2C2 */
+	mmio_clrsetbits_32((PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET),
+			PCIE_LCPLL_CM_BUF_ENA << PCIE_LCPLL_EN_CTRL_SHIFT,
+			PCIE_LCPLL_D2C2_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
+	mmio_write_32(PCIE_LCPLL_BASE + PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG, 1);
+	INFO("Overriding Clocking - using REF clock from PAD...\n");
+}
+#endif
+
+static int load_uc(unsigned int core_idx)
+{
+	return 0;
+}
+
+static int paxb_serdes_gate_clock(unsigned int core_idx, int gate_clk)
+{
+	unsigned int link_width, serdes, nr_serdes;
+	uintptr_t pmi_base;
+	unsigned int rdata;
+	uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
+
+	link_width = paxb->get_link_width(core_idx);
+	if (!link_width) {
+		ERROR("Unsupported PIPEMUX\n");
+		return -EOPNOTSUPP;
+	}
+
+	nr_serdes = link_width / 2;
+	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
+
+	for (serdes = 0; serdes < nr_serdes; serdes++) {
+		mmio_write_32(pmi_base, serdes);
+		paxb_pmi_read(core_idx, PMI_ADDR_LANE0(PMI_PLL_CTRL_4), &rdata);
+		if (!gate_clk)
+			rdata |= PMI_SERDES_CLK_ENABLE;
+		else
+			rdata &= ~PMI_SERDES_CLK_ENABLE;
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(PMI_PLL_CTRL_4), rdata);
+	}
+	return 0;
+}
+
+static int paxb_gen3_serdes_init(unsigned int core_idx, uint32_t nSerdes)
+{
+	uint32_t rdata;
+	int serdes;
+	uintptr_t pmi_base;
+	unsigned int timeout;
+	unsigned int reg_d230, reg_d267;
+
+
+	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE +
+			(core_idx * PCIE_CORE_PWR_OFFSET));
+
+	for (serdes = 0; serdes < nSerdes; serdes++) {
+		/* select the PMI interface */
+		mmio_write_32(pmi_base, serdes);
+
+		/* Clock enable */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_CLK_CTRL0),
+				0x3);
+
+		/* Release reset of master */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+				0x1);
+
+		/* clearing PRAM memory */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
+				0x100);
+
+		timeout = UC_RAM_INIT_TIMEOUT;
+		do {
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE0(UC_A_AHB_STAT0),
+					&rdata);
+		} while ((rdata & 0x01) == 0 && timeout--);
+
+		if (!timeout)
+			return -EIO;
+
+		timeout = UC_RAM_INIT_TIMEOUT;
+		do {
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE1(UC_A_AHB_STAT0),
+					&rdata);
+		} while ((rdata & 0x01) == 0 && timeout--);
+
+		if (!timeout)
+			return -EIO;
+
+		/* clearing PRAM memory */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
+				0);
+
+		/* to identify 2 lane serdes */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_DBG1), 0x1);
+
+		/* De-Assert Pram & master resets */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+				0x9);
+
+		if (load_uc(core_idx))
+			return -EIO;
+
+		/* UC UC ready for command */
+		paxb_pmi_read(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
+				&rdata);
+		rdata |= DSC_UC_CTRL_RDY_CMD;
+		paxb_pmi_write(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
+				rdata);
+
+		paxb_pmi_read(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
+				&rdata);
+		rdata |= DSC_UC_CTRL_RDY_CMD;
+		paxb_pmi_write(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
+				rdata);
+
+		/* Lane reset */
+		paxb_pmi_write(core_idx,
+				PMI_ADDR_BCAST(LANE_DBG_RST_CTRL), 0x3);
+
+		/* De-Assert Core and Master resets */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+				0x3);
+
+		timeout = UC_INIT_TIMEOUT;
+		while (timeout--) {
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE0(UC_VERSION_NUM),
+					&reg_d230);
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE0(DSC_SM_CTL22),
+					&reg_d267);
+
+			if (((reg_d230 & 0xffff) != 0) &
+					((reg_d267 & 0xc000) == 0xc000)) {
+				break;
+			}
+			mdelay(1);
+		}
+
+		if (!timeout)
+			return -EIO;
+
+		timeout = UC_INIT_TIMEOUT;
+		while (timeout--) {
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE1(UC_VERSION_NUM),
+					&reg_d230);
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE1(DSC_SM_CTL22),
+					&reg_d267);
+
+			if (((reg_d230 & 0xffff) != 0) &
+					((reg_d267 & 0xc000) == 0xc000)) {
+				break;
+			}
+			mdelay(1);
+		}
+
+		if (!timeout)
+			return -EIO;
+	}
+	return 0;
+}
+
+static int pcie_serdes_requires_patch(unsigned int serdes_idx)
+{
+	if (pipemux_idx != SERDES_PATCH_PIPEMUX_INDEX)
+		return 0;
+
+	return !!((SERDES_PATCH_INDEX >> serdes_idx) & 0x1);
+}
+
+static void pcie_tx_coeff_p7(unsigned int core_idx)
+{
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11b), 0x00aa);
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11c), 0x1155);
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11d), 0x2449);
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11e), 0x000f);
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd307), 0x0001);
+}
+
+
+static unsigned int paxb_sr_get_rc_link_width(unsigned int core_idx)
+{
+	return link_width_table[pipemux_idx][core_idx];
+}
+
+static uint32_t paxb_sr_get_rc_link_speed(void)
+{
+	return GEN3_LINK_SPEED;
+}
+
+
+static int paxb_serdes_init(unsigned int core_idx, unsigned int nr_serdes)
+{
+	uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
+	unsigned int serdes;
+	uintptr_t pmi_base;
+	int ret;
+
+	/*
+	 * Each serdes has a x2 link width
+	 *
+	 * Use PAXB to patch the serdes for proper RX termination through the
+	 * PMI interface
+	 */
+	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
+	for (serdes = 0; serdes < nr_serdes; serdes++) {
+		/* select the PMI interface */
+		mmio_write_32(pmi_base, serdes);
+
+		/* patch Serdes for RX termination */
+		ret = paxb_pmi_write(core_idx, PMI_RX_TERM_SEQ,
+				     PMI_RX_TERM_VAL);
+		if (ret)
+			goto err_pmi;
+
+		ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_7,
+				     MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL);
+		if (ret)
+			goto err_pmi;
+
+		ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_8,
+				     MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL);
+		if (ret)
+			goto err_pmi;
+
+		ret = paxb_pmi_write(core_idx, MERLIN16_AMS_TX_CTRL_5,
+				     MERLIN16_AMS_TX_CTRL_5_VAL);
+		if (ret)
+			goto err_pmi;
+
+		pcie_tx_coeff_p7(core_idx);
+
+		if (pcie_serdes_requires_patch(serdes)) {
+			if (((core_idx == 0) || (core_idx == 7))) {
+				ret = paxb_pmi_write(core_idx,
+						PMI_X8_CORE0_7_PATCH_SEQ,
+						PMI_X8_CORE0_7_PATCH_VAL);
+				if (ret)
+					goto err_pmi;
+			}
+		}
+	}
+
+	return 0;
+
+err_pmi:
+	ERROR("PCIe PMI write failed\n");
+	return ret;
+}
+
+static int paxb_sr_phy_init(void)
+{
+	int ret;
+	unsigned int core_idx;
+
+#ifndef BOARD_PCIE_EXT_CLK
+	ret = pcie_lcpll_init();
+	if (ret)
+		return ret;
+#else
+	pcie_ext_clk_init();
+#endif
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+		unsigned int link_width;
+
+		paxb_serdes_gate_clock(core_idx, 0);
+
+		link_width = paxb->get_link_width(core_idx);
+		if (!link_width) {
+			ERROR("Unsupported PIPEMUX\n");
+			return -EOPNOTSUPP;
+		}
+
+		ret = paxb_serdes_init(core_idx, link_width / 2);
+		if (ret) {
+			ERROR("PCIe serdes initialization failed for core %u\n",
+			      core_idx);
+			return ret;
+		}
+
+
+		ret = paxb_gen3_serdes_init(core_idx, link_width / 2);
+		if (ret) {
+			ERROR("PCIe GEN3 serdes initialization failed\n");
+			return ret;
+		}
+
+	}
+	return 0;
+}
+
+const paxb_cfg sr_paxb_cfg = {
+	.type = PAXB_SR,
+	.device_id = SR_B0_DEVICE_ID,
+	.pipemux_init = pipemux_sr_init,
+	.phy_init = paxb_sr_phy_init,
+	.core_needs_enable = paxb_sr_core_needs_enable,
+	.num_cores = NUM_OF_SR_PCIE_CORES,
+	.get_link_width = paxb_sr_get_rc_link_width,
+	.get_link_speed = paxb_sr_get_rc_link_speed,
+};
+
+const paxb_cfg *paxb_get_sr_config(void)
+{
+	return &sr_paxb_cfg;
+}
diff --git a/plat/brcm/board/stingray/src/topology.c b/plat/brcm/board/stingray/src/topology.c
new file mode 100644
index 0000000..24718e5
--- /dev/null
+++ b/plat/brcm/board/stingray/src/topology.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stdint.h>
+
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+/*
+ * On Stingray, the system power level is the highest power level.
+ * The first entry in the power domain descriptor specifies the
+ * number of system power domains i.e. 1.
+ */
+#define SR_PWR_DOMAINS_AT_MAX_PWR_LVL	 1
+
+/*
+ * The Stingray power domain tree descriptor. The cluster power domains
+ * are arranged so that when the PSCI generic code creates the power
+ * domain tree, the indices of the CPU power domain nodes it allocates
+ * match the linear indices returned by plat_core_pos_by_mpidr()
+ * i.e. CLUSTER0 CPUs are allocated indices from 0 to 1 and the higher
+ * indices for other Cluster CPUs.
+ */
+const unsigned char sr_power_domain_tree_desc[] = {
+	/* No of root nodes */
+	SR_PWR_DOMAINS_AT_MAX_PWR_LVL,
+	/* No of children for the root node */
+	BRCM_CLUSTER_COUNT,
+	/* No of children for the first cluster node */
+	PLATFORM_CLUSTER0_CORE_COUNT,
+	/* No of children for the second cluster node */
+	PLATFORM_CLUSTER1_CORE_COUNT,
+	/* No of children for the third cluster node */
+	PLATFORM_CLUSTER2_CORE_COUNT,
+	/* No of children for the fourth cluster node */
+	PLATFORM_CLUSTER3_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the Stingray topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return sr_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	return plat_brcm_calc_core_pos(mpidr);
+}
diff --git a/plat/brcm/board/stingray/src/tz_sec.c b/plat/brcm/board/stingray/src/tz_sec.c
new file mode 100644
index 0000000..07b12a7
--- /dev/null
+++ b/plat/brcm/board/stingray/src/tz_sec.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/tzc400.h>
+#include <lib/mmio.h>
+
+#include <cmn_sec.h>
+#include <platform_def.h>
+
+/*
+ * Trust Zone controllers
+ */
+#define TZC400_FS_SRAM_ROOT	0x66d84000
+
+/*
+ * TZPC Master configure registers
+ */
+
+/* TZPC_TZPCDECPROT0set */
+#define TZPC0_MASTER_NS_BASE		0x68b40804
+#define TZPC0_SATA3_BIT			5
+#define TZPC0_SATA2_BIT			4
+#define TZPC0_SATA1_BIT			3
+#define TZPC0_SATA0_BIT			2
+#define TZPC0_USB3H1_BIT		1
+#define TZPC0_USB3H0_BIT		0
+#define TZPC0_MASTER_SEC_DEFAULT	0
+
+/* TZPC_TZPCDECPROT1set */
+#define TZPC1_MASTER_NS_BASE		0x68b40810
+#define TZPC1_SDIO1_BIT			6
+#define TZPC1_SDIO0_BIT			5
+#define TZPC1_AUDIO0_BIT		4
+#define TZPC1_USB2D_BIT			3
+#define TZPC1_USB2H1_BIT		2
+#define TZPC1_USB2H0_BIT		1
+#define TZPC1_AMAC0_BIT			0
+#define TZPC1_MASTER_SEC_DEFAULT	0
+
+
+struct tz_sec_desc {
+	uintptr_t addr;
+	uint32_t val;
+};
+
+static const struct tz_sec_desc tz_master_defaults[] = {
+{ TZPC0_MASTER_NS_BASE, TZPC0_MASTER_SEC_DEFAULT },
+{ TZPC1_MASTER_NS_BASE, TZPC1_MASTER_SEC_DEFAULT }
+};
+
+/*
+ * Initialize the TrustZone Controller for SRAM partitioning.
+ */
+static void bcm_tzc_setup(void)
+{
+	VERBOSE("Configuring SRAM TrustZone Controller\n");
+
+	/* Init the TZASC controller */
+	tzc400_init(TZC400_FS_SRAM_ROOT);
+
+	/*
+	 * Close the entire SRAM space
+	 * Region 0 covers the entire SRAM space
+	 * None of the NS device can access it.
+	 */
+	tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
+
+	/* Do raise an exception if a NS device tries to access secure memory */
+	tzc400_set_action(TZC_ACTION_ERR);
+}
+
+/*
+ * Configure TZ Master as NS_MASTER or SECURE_MASTER
+ * To set a Master to non-secure, use *_SET registers
+ * To set a Master to secure, use *_CLR registers (set + 0x4 address)
+ */
+static void tz_master_set(uint32_t base, uint32_t value, uint32_t ns)
+{
+	if (ns == SECURE_MASTER) {
+		mmio_write_32(base + 4, value);
+	} else {
+		mmio_write_32(base, value);
+	}
+}
+
+/*
+ * Initialize the secure environment for sdio.
+ */
+void plat_tz_sdio_ns_master_set(uint32_t ns)
+{
+	tz_master_set(TZPC1_MASTER_NS_BASE,
+			1 << TZPC1_SDIO0_BIT,
+			ns);
+}
+
+/*
+ * Initialize the secure environment for usb.
+ */
+void plat_tz_usb_ns_master_set(uint32_t ns)
+{
+	tz_master_set(TZPC1_MASTER_NS_BASE,
+			1 << TZPC1_USB2H0_BIT,
+			ns);
+}
+
+/*
+ * Set masters to default configuration.
+ *
+ * DMA security settings are programmed into the PL-330 controller and
+ * are not set by iProc TZPC registers.
+ * DMA always comes up as secure master (*NS bit is 0).
+ *
+ * Because the default reset values of TZPC are 0 (== Secure),
+ * ARM Verilog code makes all masters, including PCIe, come up as
+ * secure.
+ * However, SOTP has a bit called SOTP_ALLMASTER_NS that overrides
+ * TZPC and makes all masters non-secure for AB devices.
+ *
+ * Hence we first set all the TZPC bits to program all masters,
+ * including PCIe, as non-secure, then set the CLEAR_ALLMASTER_NS bit
+ * so that the SOTP_ALLMASTER_NS cannot override TZPC.
+ * now security settings for each masters come from TZPC
+ * (which makes all masters other than DMA as non-secure).
+ *
+ * During the boot, all masters other than DMA Ctrlr + list
+ * are non-secure in an AB Prod/AB Dev/AB Pending device.
+ *
+ */
+void plat_tz_master_default_cfg(void)
+{
+	int i;
+
+	/* Configure default secure and non-secure TZ Masters */
+	for (i = 0; i < ARRAY_SIZE(tz_master_defaults); i++) {
+		tz_master_set(tz_master_defaults[i].addr,
+			      tz_master_defaults[i].val,
+			      SECURE_MASTER);
+		tz_master_set(tz_master_defaults[i].addr,
+			      ~tz_master_defaults[i].val,
+			      NS_MASTER);
+	}
+
+	/* Clear all master NS */
+	mmio_setbits_32(SOTP_CHIP_CTRL,
+			1 << SOTP_CLEAR_SYSCTRL_ALL_MASTER_NS);
+
+	/* Initialize TZ controller and Set SRAM to secure */
+	bcm_tzc_setup();
+}
diff --git a/plat/brcm/common/brcm_bl2_mem_params_desc.c b/plat/brcm/common/brcm_bl2_mem_params_desc.c
new file mode 100644
index 0000000..f711354
--- /dev/null
+++ b/plat/brcm/common/brcm_bl2_mem_params_desc.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+	/* Fill SCP_BL2 related information if it exists */
+	{
+	    .image_id = SCP_BL2_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = SCP_BL2_BASE,
+	    .image_info.image_max_size = PLAT_MAX_SCP_BL2_SIZE,
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+#endif /* SCP_BL2_BASE */
+
+	/* Fill BL31 related information */
+	{
+	    .image_id = BL31_IMAGE_ID,
+
+	    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),
+#if DEBUG
+	    .ep_info.args.arg3 = BRCM_BL31_PLAT_PARAM_VAL,
+#endif
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+	    .image_info.image_base = BL31_BASE,
+	    .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+#ifdef BL32_BASE
+	    .next_handoff_image_id = BL32_IMAGE_ID,
+#else
+	    .next_handoff_image_id = BL33_IMAGE_ID,
+#endif
+	},
+
+#ifdef BL32_BASE
+	/* Fill BL32 related information */
+	{
+	    .image_id = BL32_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+	    .ep_info.pc = BL32_BASE,
+
+	    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_LIMIT - BL32_BASE,
+
+	    .next_handoff_image_id = BL33_IMAGE_ID,
+	},
+#endif /* BL32_BASE */
+
+	/* Fill BL33 related information */
+	{
+	    .image_id = BL33_IMAGE_ID,
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+#ifdef PRELOADED_BL33_BASE
+	    .ep_info.pc = PRELOADED_BL33_BASE,
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#else
+	    .ep_info.pc = PLAT_BRCM_NS_IMAGE_OFFSET,
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = PLAT_BRCM_NS_IMAGE_OFFSET,
+	    .image_info.image_max_size = BRCM_DRAM1_SIZE,
+#endif /* PRELOADED_BL33_BASE */
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+	}
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/brcm/common/brcm_bl2_setup.c b/plat/brcm/common/brcm_bl2_setup.c
new file mode 100644
index 0000000..9a7153b
--- /dev/null
+++ b/plat/brcm/common/brcm_bl2_setup.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <lib/mmio.h>
+
+#include <bcm_console.h>
+#include <platform_def.h>
+#include <plat/brcm/common/plat_brcm.h>
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/* Weak definitions may be overridden in specific BRCM platform */
+#pragma weak plat_bcm_bl2_platform_setup
+#pragma weak plat_bcm_bl2_plat_arch_setup
+#pragma weak plat_bcm_security_setup
+#pragma weak plat_bcm_bl2_plat_handle_scp_bl2
+#pragma weak plat_bcm_bl2_early_platform_setup
+
+void plat_bcm_bl2_early_platform_setup(void)
+{
+}
+
+void plat_bcm_bl2_platform_setup(void)
+{
+}
+
+void plat_bcm_bl2_plat_arch_setup(void)
+{
+}
+
+void plat_bcm_security_setup(void)
+{
+}
+
+void bcm_bl2_early_platform_setup(uintptr_t tb_fw_config,
+				  meminfo_t *mem_layout)
+{
+	/* Initialize the console to provide early debug support */
+	bcm_console_boot_init();
+
+	/* Setup the BL2 memory layout */
+	bl2_tzram_layout = *mem_layout;
+
+	/* Initialise the IO layer and register platform IO devices */
+	plat_brcm_io_setup();
+
+	/* Log HW reset event */
+	INFO("RESET: 0x%x\n",
+		mmio_read_32(CRMU_RESET_EVENT_LOG));
+}
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+			       u_register_t arg2, u_register_t arg3)
+{
+	/* SoC specific setup */
+	plat_bcm_bl2_early_platform_setup();
+
+	/* Initialize delay timer driver using SP804 dual timer 0 */
+	sp804_timer_init(SP804_TIMER0_BASE,
+			 SP804_TIMER0_CLKMULT, SP804_TIMER0_CLKDIV);
+
+	/* BRCM platforms generic setup */
+	bcm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
+}
+
+/*
+ * Perform Broadcom platform setup.
+ */
+void bcm_bl2_platform_setup(void)
+{
+	/* Initialize the secure environment */
+	plat_bcm_security_setup();
+}
+
+void bl2_platform_setup(void)
+{
+	bcm_bl2_platform_setup();
+	plat_bcm_bl2_platform_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bcm_bl2_plat_arch_setup(void)
+{
+#ifndef MMU_DISABLED
+	if (!(read_sctlr_el1() & SCTLR_M_BIT)) {
+		const mmap_region_t bl_regions[] = {
+			MAP_REGION_FLAT(bl2_tzram_layout.total_base,
+					bl2_tzram_layout.total_size,
+					MT_MEMORY | MT_RW | MT_SECURE),
+			MAP_REGION_FLAT(BL_CODE_BASE,
+					BL_CODE_END - BL_CODE_BASE,
+					MT_CODE | MT_SECURE),
+			MAP_REGION_FLAT(BL_RO_DATA_BASE,
+					BL_RO_DATA_END - BL_RO_DATA_BASE,
+					MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM
+			MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+					BL_COHERENT_RAM_END -
+					BL_COHERENT_RAM_BASE,
+					MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+			{0}
+		};
+
+		setup_page_tables(bl_regions, plat_brcm_get_mmap());
+		enable_mmu_el1(0);
+	}
+#endif
+}
+
+void bl2_plat_arch_setup(void)
+{
+#ifdef ENA_MMU_BEFORE_DDR_INIT
+	/*
+	 * Once MMU is enabled before DDR, MEMORY TESTS
+	 * get affected as read/write transaction might occures from
+	 * caches. So For running memory test, one should not set this
+	 * flag.
+	 */
+	bcm_bl2_plat_arch_setup();
+	plat_bcm_bl2_plat_arch_setup();
+#else
+	plat_bcm_bl2_plat_arch_setup();
+	bcm_bl2_plat_arch_setup();
+#endif
+}
+
+int bcm_bl2_handle_post_image_load(unsigned int image_id)
+{
+	int err = 0;
+
+	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+	assert(bl_mem_params);
+
+	switch (image_id) {
+	case BL32_IMAGE_ID:
+		bl_mem_params->ep_info.spsr = brcm_get_spsr_for_bl32_entry();
+		break;
+
+	case BL33_IMAGE_ID:
+		/* BL33 expects to receive the primary CPU MPID (through r0) */
+		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+		bl_mem_params->ep_info.spsr = brcm_get_spsr_for_bl33_entry();
+		break;
+
+#ifdef SCP_BL2_BASE
+	case SCP_BL2_IMAGE_ID:
+		/* The subsequent handling of SCP_BL2 is platform specific */
+		err = bcm_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+		if (err)
+			WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+		break;
+#endif
+	default:
+		/* Do nothing in default case */
+		break;
+	}
+
+	return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bcm_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	return bcm_bl2_handle_post_image_load(image_id);
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	return bcm_bl2_plat_handle_post_image_load(image_id);
+}
+
+#ifdef SCP_BL2_BASE
+int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+	return 0;
+}
+
+int bcm_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+	return plat_bcm_bl2_plat_handle_scp_bl2(scp_bl2_image_info);
+}
+#endif
diff --git a/plat/brcm/common/brcm_bl31_setup.c b/plat/brcm/common/brcm_bl31_setup.c
new file mode 100644
index 0000000..d3fa83d
--- /dev/null
+++ b/plat/brcm/common/brcm_bl31_setup.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <bcm_console.h>
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+#ifdef BL33_SHARED_DDR_BASE
+struct bl33_info *bl33_info = (struct bl33_info *)BL33_SHARED_DDR_BASE;
+#endif
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* Weak definitions may be overridden in specific BRCM platform */
+#pragma weak plat_bcm_bl31_early_platform_setup
+#pragma weak plat_brcm_pwrc_setup
+#pragma weak plat_brcm_security_setup
+
+void plat_brcm_security_setup(void)
+{
+
+}
+
+void plat_brcm_pwrc_setup(void)
+{
+
+}
+
+void plat_bcm_bl31_early_platform_setup(void *from_bl2,
+				   bl_params_t *plat_params_from_bl2)
+{
+
+}
+
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	assert(sec_state_is_valid(type));
+	next_image_info = (type == NON_SECURE)
+			? &bl33_image_ep_info : &bl32_image_ep_info;
+	/*
+	 * None of the images on the ARM development platforms can have 0x0
+	 * as the entrypoint
+	 */
+	if (next_image_info->pc)
+		return next_image_info;
+	else
+		return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup common to ARM standard platforms.
+ * Here is an opportunity to copy parameters passed by the calling EL (S-EL1
+ * in BL2 & 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.
+ ******************************************************************************/
+void __init brcm_bl31_early_platform_setup(void *from_bl2,
+					  uintptr_t soc_fw_config,
+					  uintptr_t hw_config,
+					  void *plat_params_from_bl2)
+{
+	/* Initialize the console to provide early debug support */
+	bcm_console_boot_init();
+
+	/* Initialize delay timer driver using SP804 dual timer 0 */
+	sp804_timer_init(SP804_TIMER0_BASE,
+			 SP804_TIMER0_CLKMULT, SP804_TIMER0_CLKDIV);
+
+#if RESET_TO_BL31
+	/* There are no parameters from BL2 if BL31 is a reset vector */
+	assert(from_bl2 == NULL);
+	assert(plat_params_from_bl2 == NULL);
+
+# ifdef BL32_BASE
+	/* Populate entry point information for BL32 */
+	SET_PARAM_HEAD(&bl32_image_ep_info,
+		       PARAM_EP,
+		       VERSION_1,
+		       0);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = brcm_get_spsr_for_bl32_entry();
+# endif /* BL32_BASE */
+
+	/* Populate entry point information for BL33 */
+	SET_PARAM_HEAD(&bl33_image_ep_info,
+		       PARAM_EP,
+		       VERSION_1,
+		       0);
+	/*
+	 * Tell BL31 where the non-trusted software image
+	 * is located and the entry state information
+	 */
+	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+
+	bl33_image_ep_info.spsr = brcm_get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+# if ARM_LINUX_KERNEL_AS_BL33
+	/*
+	 * According to the file ``Documentation/arm64/booting.txt`` of the
+	 * Linux kernel tree, Linux expects the physical address of the device
+	 * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+	 * must be 0.
+	 */
+	bl33_image_ep_info.args.arg0 = (u_register_t)PRELOADED_DTB_BASE;
+	bl33_image_ep_info.args.arg1 = 0U;
+	bl33_image_ep_info.args.arg2 = 0U;
+	bl33_image_ep_info.args.arg3 = 0U;
+# endif
+
+#else /* RESET_TO_BL31 */
+
+	/*
+	 * In debug builds, we pass a special value in 'plat_params_from_bl2'
+	 * to verify platform parameters from BL2 to BL31.
+	 * In release builds, it's not used.
+	 */
+	assert(((unsigned long long)plat_params_from_bl2) ==
+		BRCM_BL31_PLAT_PARAM_VAL);
+
+	/*
+	 * Check params passed from BL2 should not be NULL
+	 */
+	bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+	assert(params_from_bl2 != NULL);
+	assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+	assert(params_from_bl2->h.version >= VERSION_2);
+
+	bl_params_node_t *bl_params = params_from_bl2->head;
+
+	/*
+	 * Copy BL33 and BL32 (if present), entry point information.
+	 * They are stored in Secure RAM, in BL2's address space.
+	 */
+	while (bl_params != NULL) {
+		if (bl_params->image_id == BL32_IMAGE_ID &&
+		    bl_params->image_info->h.attr != IMAGE_ATTRIB_SKIP_LOADING)
+			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;
+	}
+
+	if (bl33_image_ep_info.pc == 0U)
+		panic();
+#endif /* RESET_TO_BL31 */
+
+#ifdef BL33_SHARED_DDR_BASE
+	/* Pass information to BL33 thorugh x0 */
+	bl33_image_ep_info.args.arg0 = (u_register_t)BL33_SHARED_DDR_BASE;
+	bl33_image_ep_info.args.arg1 = 0ULL;
+	bl33_image_ep_info.args.arg2 = 0ULL;
+	bl33_image_ep_info.args.arg3 = 0ULL;
+#endif
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+		u_register_t arg2, u_register_t arg3)
+{
+#ifdef BL31_LOG_LEVEL
+	SET_LOG_LEVEL(BL31_LOG_LEVEL);
+#endif
+
+	brcm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+	plat_bcm_bl31_early_platform_setup((void *)arg0, (void *)arg3);
+
+#ifdef DRIVER_CC_ENABLE
+	/*
+	 * Initialize Interconnect for this cluster during cold boot.
+	 * No need for locks as no other CPU is active.
+	 */
+	plat_brcm_interconnect_init();
+
+	/*
+	 * Enable Interconnect coherency for the primary CPU's cluster.
+	 * Earlier bootloader stages might already do this (e.g. Trusted
+	 * Firmware's BL1 does it) but we can't assume so. There is no harm in
+	 * executing this code twice anyway.
+	 * Platform specific PSCI code will enable coherency for other
+	 * clusters.
+	 */
+	plat_brcm_interconnect_enter_coherency();
+#endif
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform setup common to ARM standard platforms
+ ******************************************************************************/
+void brcm_bl31_platform_setup(void)
+{
+	/* Initialize the GIC driver, cpu and distributor interfaces */
+	plat_brcm_gic_driver_init();
+	plat_brcm_gic_init();
+
+	/* Initialize power controller before setting up topology */
+	plat_brcm_pwrc_setup();
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM
+ * standard platforms
+ * Perform BL31 platform setup
+ ******************************************************************************/
+void brcm_bl31_plat_runtime_setup(void)
+{
+	console_switch_state(CONSOLE_FLAG_RUNTIME);
+
+	/* Initialize the runtime console */
+	bcm_console_runtime_init();
+}
+
+void bl31_platform_setup(void)
+{
+	brcm_bl31_platform_setup();
+
+	/* Initialize the secure environment */
+	plat_brcm_security_setup();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+	brcm_bl31_plat_runtime_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl31_arch_setup()) does not do anything platform
+ * specific.
+ ******************************************************************************/
+void __init brcm_bl31_plat_arch_setup(void)
+{
+#ifndef MMU_DISABLED
+	const mmap_region_t bl_regions[] = {
+		MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+				MT_MEMORY | MT_RW | MT_SECURE),
+		MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+				MT_CODE | MT_SECURE),
+		MAP_REGION_FLAT(BL_RO_DATA_BASE,
+				BL_RO_DATA_END - BL_RO_DATA_BASE,
+				MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM
+		MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+				BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+				MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+		{0}
+	};
+
+	setup_page_tables(bl_regions, plat_brcm_get_mmap());
+
+	enable_mmu_el3(0);
+#endif
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+	brcm_bl31_plat_arch_setup();
+}
diff --git a/plat/brcm/common/brcm_ccn.c b/plat/brcm/common/brcm_ccn.c
new file mode 100644
index 0000000..9396aaa
--- /dev/null
+++ b/plat/brcm/common/brcm_ccn.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <drivers/arm/ccn.h>
+
+#include <platform_def.h>
+
+static const unsigned char master_to_rn_id_map[] = {
+	PLAT_BRCM_CLUSTER_TO_CCN_ID_MAP
+};
+
+static const ccn_desc_t bcm_ccn_desc = {
+	.periphbase = PLAT_BRCM_CCN_BASE,
+	.num_masters = ARRAY_SIZE(master_to_rn_id_map),
+	.master_to_rn_id_map = master_to_rn_id_map
+};
+
+void plat_brcm_interconnect_init(void)
+{
+	ccn_init(&bcm_ccn_desc);
+}
+
+void plat_brcm_interconnect_enter_coherency(void)
+{
+	ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+void plat_brcm_interconnect_exit_coherency(void)
+{
+	ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/brcm/common/brcm_common.c b/plat/brcm/common/brcm_common.c
new file mode 100644
index 0000000..f23719d
--- /dev/null
+++ b/plat/brcm/common/brcm_common.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+/* Weak definitions may be overridden in specific BRCM platform */
+#pragma weak plat_get_ns_image_entrypoint
+#pragma weak plat_brcm_get_mmap
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	return PLAT_BRCM_NS_IMAGE_OFFSET;
+#endif
+}
+
+uint32_t brcm_get_spsr_for_bl32_entry(void)
+{
+	/*
+	 * The Secure Payload Dispatcher service is responsible for
+	 * setting the SPSR prior to entry into the BL32 image.
+	 */
+	return 0;
+}
+
+uint32_t brcm_get_spsr_for_bl33_entry(void)
+{
+	unsigned int mode;
+	uint32_t spsr;
+
+	/* Figure out what mode we enter the non-secure world in */
+	mode = el_implemented(2) ? MODE_EL2 : MODE_EL1;
+
+	/*
+	 * TODO: Consider the possibility of specifying the SPSR in
+	 * the FIP ToC and allowing the platform to have a say as
+	 * well.
+	 */
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+
+const mmap_region_t *plat_brcm_get_mmap(void)
+{
+	return plat_brcm_mmap;
+}
diff --git a/plat/brcm/common/brcm_gicv3.c b/plat/brcm/common/brcm_gicv3.c
new file mode 100644
index 0000000..c4137c0
--- /dev/null
+++ b/plat/brcm/common/brcm_gicv3.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/gicv3.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t brcm_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t brcm_interrupt_props[] = {
+	/* G1S interrupts */
+	PLAT_BRCM_G1S_IRQ_PROPS(INTR_GROUP1S),
+	/* G0 interrupts */
+	PLAT_BRCM_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ *   - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ *   - No CPUs implemented in the system use affinity level 3.
+ */
+static unsigned int brcm_gicv3_mpidr_hash(u_register_t mpidr)
+{
+	mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+	return plat_core_pos_by_mpidr(mpidr);
+}
+
+static const gicv3_driver_data_t brcm_gic_data = {
+	.gicd_base = PLAT_BRCM_GICD_BASE,
+	.gicr_base = PLAT_BRCM_GICR_BASE,
+	.interrupt_props = brcm_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(brcm_interrupt_props),
+	.rdistif_num = PLATFORM_CORE_COUNT,
+	.rdistif_base_addrs = brcm_rdistif_base_addrs,
+	.mpidr_to_core_pos = brcm_gicv3_mpidr_hash
+};
+
+void plat_brcm_gic_driver_init(void)
+{
+	/* TODO Check if this is required to be initialized here
+	 * after getting initialized in EL3, should we re-init this here
+	 * in S-EL1
+	 */
+	gicv3_driver_init(&brcm_gic_data);
+}
+
+void plat_brcm_gic_init(void)
+{
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_brcm_gic_cpuif_enable(void)
+{
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_brcm_gic_cpuif_disable(void)
+{
+	gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void plat_brcm_gic_pcpu_init(void)
+{
+	gicv3_rdistif_init(plat_my_core_pos());
+}
+
+void plat_brcm_gic_redistif_on(void)
+{
+	gicv3_rdistif_on(plat_my_core_pos());
+}
+
+void plat_brcm_gic_redistif_off(void)
+{
+	gicv3_rdistif_off(plat_my_core_pos());
+}
diff --git a/plat/brcm/common/brcm_image_load.c b/plat/brcm/common/brcm_image_load.c
new file mode 100644
index 0000000..ba02bda
--- /dev/null
+++ b/plat/brcm/common/brcm_image_load.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#pragma weak plat_flush_next_bl_params
+#pragma weak plat_get_bl_image_load_info
+#pragma weak plat_get_next_bl_params
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+	flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+struct bl_load_info *plat_get_bl_image_load_info(void)
+{
+	return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+	bl_params_t *next_bl_params = get_next_bl_params_from_mem_params_desc();
+
+	populate_next_bl_params_config(next_bl_params);
+	return next_bl_params;
+}
diff --git a/plat/brcm/common/brcm_io_storage.c b/plat/brcm/common/brcm_io_storage.c
new file mode 100644
index 0000000..66ec292
--- /dev/null
+++ b/plat/brcm/common/brcm_io_storage.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <cmn_plat_def.h>
+#include <cmn_plat_util.h>
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+	.offset = PLAT_BRCM_FIP_BASE,
+	.length = PLAT_BRCM_FIP_MAX_SIZE
+};
+
+static const io_block_spec_t qspi_fip_block_spec = {
+	.offset = PLAT_BRCM_FIP_QSPI_BASE,
+	.length = PLAT_BRCM_FIP_MAX_SIZE
+};
+
+static const io_block_spec_t nand_fip_block_spec = {
+	.offset = PLAT_BRCM_FIP_NAND_BASE,
+	.length = PLAT_BRCM_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t scp_bl2_uuid_spec = {
+	.uuid = UUID_SCP_FIRMWARE_SCP_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+static const io_uuid_spec_t tb_fw_config_uuid_spec = {
+	.uuid = UUID_TB_FW_CONFIG,
+};
+
+static const io_uuid_spec_t hw_config_uuid_spec = {
+	.uuid = UUID_HW_CONFIG,
+};
+
+static const io_uuid_spec_t soc_fw_config_uuid_spec = {
+	.uuid = UUID_SOC_FW_CONFIG,
+};
+
+static const io_uuid_spec_t tos_fw_config_uuid_spec = {
+	.uuid = UUID_TOS_FW_CONFIG,
+};
+
+static const io_uuid_spec_t nt_fw_config_uuid_spec = {
+	.uuid = UUID_NT_FW_CONFIG,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = {
+	.uuid = UUID_SCP_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+	.uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_cert_uuid_spec = {
+	.uuid = UUID_SCP_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+	.uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+static int open_qspi(const uintptr_t spec);
+static int open_nand(const uintptr_t spec);
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+/* By default, BRCM platforms load images from the FIP */
+static const struct plat_io_policy policies[] = {
+	[FIP_IMAGE_ID] = {
+		&memmap_dev_handle,
+		(uintptr_t)&fip_block_spec,
+		open_memmap
+	},
+	[BL2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl2_uuid_spec,
+		open_fip
+	},
+	[SCP_BL2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&scp_bl2_uuid_spec,
+		open_fip
+	},
+	[BL31_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl31_uuid_spec,
+		open_fip
+	},
+	[BL32_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		open_fip
+	},
+	[BL33_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl33_uuid_spec,
+		open_fip
+	},
+	[TB_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tb_fw_config_uuid_spec,
+		open_fip
+	},
+	[HW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&hw_config_uuid_spec,
+		open_fip
+	},
+	[SOC_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&soc_fw_config_uuid_spec,
+		open_fip
+	},
+	[TOS_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tos_fw_config_uuid_spec,
+		open_fip
+	},
+	[NT_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&nt_fw_config_uuid_spec,
+		open_fip
+	},
+#if TRUSTED_BOARD_BOOT
+	[TRUSTED_BOOT_FW_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tb_fw_cert_uuid_spec,
+		open_fip
+	},
+	[TRUSTED_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&trusted_key_cert_uuid_spec,
+		open_fip
+	},
+	[SCP_FW_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&scp_fw_key_cert_uuid_spec,
+		open_fip
+	},
+	[SOC_FW_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&soc_fw_key_cert_uuid_spec,
+		open_fip
+	},
+	[TRUSTED_OS_FW_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tos_fw_key_cert_uuid_spec,
+		open_fip
+	},
+	[NON_TRUSTED_FW_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&nt_fw_key_cert_uuid_spec,
+		open_fip
+	},
+	[SCP_FW_CONTENT_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&scp_fw_cert_uuid_spec,
+		open_fip
+	},
+	[SOC_FW_CONTENT_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&soc_fw_cert_uuid_spec,
+		open_fip
+	},
+	[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tos_fw_cert_uuid_spec,
+		open_fip
+	},
+	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&nt_fw_cert_uuid_spec,
+		open_fip
+	},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+/* By default, BRCM platforms load images from the FIP */
+static const struct plat_io_policy boot_source_policies[] = {
+	[BOOT_SOURCE_QSPI] = {
+		&memmap_dev_handle,
+		(uintptr_t)&qspi_fip_block_spec,
+		open_qspi
+	},
+	[BOOT_SOURCE_NAND] = {
+		&memmap_dev_handle,
+		(uintptr_t)&nand_fip_block_spec,
+		open_nand
+	},
+};
+
+/* Weak definitions may be overridden in specific brcm platform */
+#pragma weak plat_brcm_io_setup
+#pragma weak plat_brcm_process_flags
+
+static int open_fip(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	/* See if a Firmware Image Package is available */
+	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+	if (result == 0) {
+		result = io_open(fip_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using FIP\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+
+static int open_memmap(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+	if (result == 0) {
+		result = io_open(memmap_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using Memmap\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+static int open_qspi(const uintptr_t spec)
+{
+	return open_memmap(spec);
+}
+
+static int open_nand(const uintptr_t spec)
+{
+	return open_memmap(spec);
+}
+
+
+void brcm_io_setup(void)
+{
+	int io_result;
+	uint32_t boot_source;
+
+	io_result = register_io_dev_fip(&fip_dev_con);
+	assert(io_result == 0);
+
+	io_result = register_io_dev_memmap(&memmap_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to devices and cache the handles */
+	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+				&fip_dev_handle);
+	assert(io_result == 0);
+
+	boot_source = boot_source_get();
+	switch (boot_source) {
+	case BOOT_SOURCE_QSPI:
+	case BOOT_SOURCE_NAND:
+	default:
+		io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+					&memmap_dev_handle);
+		break;
+	}
+	assert(io_result == 0);
+
+	/* Ignore improbable errors in release builds */
+	(void)io_result;
+}
+
+void plat_brcm_io_setup(void)
+{
+	brcm_io_setup();
+}
+
+void plat_brcm_process_flags(uint16_t plat_toc_flags __unused)
+{
+	WARN("%s not implemented\n", __func__);
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int result;
+	const struct plat_io_policy *policy;
+	uint32_t boot_source;
+	uint16_t lcl_plat_toc_flg;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	boot_source = boot_source_get();
+	if (image_id == FIP_IMAGE_ID)
+		policy = &boot_source_policies[boot_source];
+	else
+		policy = &policies[image_id];
+
+	result = policy->check(policy->image_spec);
+	if (result == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+
+		if (image_id == TRUSTED_BOOT_FW_CERT_ID) {
+			/*
+			 * Process the header flags to perform
+			 * such custom actions as speeding up PLL.
+			 * CERT seems to be the first image accessed
+			 * by BL1 so this is where we process the flags.
+			 */
+			fip_dev_get_plat_toc_flag((io_dev_info_t *)fip_dev_handle,
+						  &lcl_plat_toc_flg);
+			plat_brcm_process_flags(lcl_plat_toc_flg);
+		}
+	}
+
+	return result;
+}
diff --git a/plat/brcm/common/brcm_mhu.c b/plat/brcm/common/brcm_mhu.c
new file mode 100644
index 0000000..56f44e0
--- /dev/null
+++ b/plat/brcm/common/brcm_mhu.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+
+#include <brcm_mhu.h>
+#include <platform_def.h>
+
+#include "m0_ipc.h"
+
+#define PLAT_MHU_INTR_REG	AP_TO_SCP_MAILBOX1
+
+/* SCP MHU secure channel registers */
+#define SCP_INTR_S_STAT		CRMU_IHOST_SW_PERSISTENT_REG11
+#define SCP_INTR_S_SET		CRMU_IHOST_SW_PERSISTENT_REG11
+#define SCP_INTR_S_CLEAR	CRMU_IHOST_SW_PERSISTENT_REG11
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT		CRMU_IHOST_SW_PERSISTENT_REG10
+#define CPU_INTR_S_SET		CRMU_IHOST_SW_PERSISTENT_REG10
+#define CPU_INTR_S_CLEAR	CRMU_IHOST_SW_PERSISTENT_REG10
+
+static DEFINE_BAKERY_LOCK(bcm_lock);
+
+/*
+ * Slot 31 is reserved because the MHU hardware uses this register bit to
+ * indicate a non-secure access attempt. The total number of available slots is
+ * therefore 31 [30:0].
+ */
+#define MHU_MAX_SLOT_ID		30
+
+void mhu_secure_message_start(unsigned int slot_id)
+{
+	int iter = 1000000;
+
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+
+	bakery_lock_get(&bcm_lock);
+	/* Make sure any previous command has finished */
+	do {
+		if (!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) &
+		   (1 << slot_id)))
+			break;
+
+		 udelay(1);
+
+	} while (--iter);
+
+	assert(iter != 0);
+}
+
+void mhu_secure_message_send(unsigned int slot_id)
+{
+	uint32_t response, iter = 1000000;
+
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+	assert(!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) &
+							(1 << slot_id)));
+
+	/* Send command to SCP */
+	mmio_setbits_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
+	mmio_write_32(CRMU_MAIL_BOX0, MCU_IPC_MCU_CMD_SCPI);
+	mmio_write_32(PLAT_BRCM_MHU_BASE + PLAT_MHU_INTR_REG, 0x1);
+
+	/* Wait until IPC transport acknowledges reception of SCP command */
+	do {
+		response = mmio_read_32(CRMU_MAIL_BOX0);
+		if ((response & ~MCU_IPC_CMD_REPLY_MASK) ==
+		   (MCU_IPC_CMD_DONE_MASK | MCU_IPC_MCU_CMD_SCPI))
+			break;
+
+		udelay(1);
+
+	} while (--iter);
+
+	assert(iter != 0);
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+	/* Wait for response from SCP */
+	uint32_t response, iter = 1000000;
+
+	do {
+		response = mmio_read_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT);
+		if (!response)
+			break;
+
+		udelay(1);
+	} while (--iter);
+	assert(iter != 0);
+
+	return response;
+}
+
+void mhu_secure_message_end(unsigned int slot_id)
+{
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+
+	/*
+	 * Clear any response we got by writing one in the relevant slot bit to
+	 * the CLEAR register
+	 */
+	mmio_clrbits_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
+	bakery_lock_release(&bcm_lock);
+}
+
+void mhu_secure_init(void)
+{
+	bakery_lock_init(&bcm_lock);
+
+	/*
+	 * The STAT register resets to zero. Ensure it is in the expected state,
+	 * as a stale or garbage value would make us think it's a message we've
+	 * already sent.
+	 */
+	mmio_write_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT, 0);
+	mmio_write_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT, 0);
+}
+
+void plat_brcm_pwrc_setup(void)
+{
+	mhu_secure_init();
+}
diff --git a/plat/brcm/common/brcm_mhu.h b/plat/brcm/common/brcm_mhu.h
new file mode 100644
index 0000000..6c89a34
--- /dev/null
+++ b/plat/brcm/common/brcm_mhu.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BRCM_MHU_H
+#define BRCM_MHU_H
+
+#include <stdint.h>
+
+void mhu_secure_message_start(unsigned int slot_id);
+void mhu_secure_message_send(unsigned int slot_id);
+uint32_t mhu_secure_message_wait(void);
+void mhu_secure_message_end(unsigned int slot_id);
+
+void mhu_secure_init(void);
+
+#endif	/* BRCM_MHU_H */
diff --git a/plat/brcm/common/brcm_scpi.c b/plat/brcm/common/brcm_scpi.c
new file mode 100644
index 0000000..0a703cb
--- /dev/null
+++ b/plat/brcm/common/brcm_scpi.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <brcm_mhu.h>
+#include <brcm_scpi.h>
+#include <platform_def.h>
+
+#define SCPI_SHARED_MEM_SCP_TO_AP	(PLAT_SCP_COM_SHARED_MEM_BASE)
+#define SCPI_SHARED_MEM_AP_TO_SCP	(PLAT_SCP_COM_SHARED_MEM_BASE \
+								 + 0x100)
+
+/* Header and payload addresses for commands from AP to SCP */
+#define SCPI_CMD_HEADER_AP_TO_SCP		\
+	((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
+#define SCPI_CMD_PAYLOAD_AP_TO_SCP		\
+	((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
+
+/* Header and payload addresses for responses from SCP to AP */
+#define SCPI_RES_HEADER_SCP_TO_AP \
+	((scpi_cmd_t *) SCPI_SHARED_MEM_SCP_TO_AP)
+#define SCPI_RES_PAYLOAD_SCP_TO_AP \
+	((void *) (SCPI_SHARED_MEM_SCP_TO_AP + sizeof(scpi_cmd_t)))
+
+/* ID of the MHU slot used for the SCPI protocol */
+#define SCPI_MHU_SLOT_ID		0
+
+static void scpi_secure_message_start(void)
+{
+	mhu_secure_message_start(SCPI_MHU_SLOT_ID);
+}
+
+static void scpi_secure_message_send(size_t payload_size)
+{
+	/*
+	 * Ensure that any write to the SCPI payload area is seen by SCP before
+	 * we write to the MHU register. If these 2 writes were reordered by
+	 * the CPU then SCP would read stale payload data
+	 */
+	dmbst();
+
+	mhu_secure_message_send(SCPI_MHU_SLOT_ID);
+}
+
+static void scpi_secure_message_receive(scpi_cmd_t *cmd)
+{
+	uint32_t mhu_status;
+
+	assert(cmd != NULL);
+
+	mhu_status = mhu_secure_message_wait();
+
+	/* Expect an SCPI message, reject any other protocol */
+	if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
+		ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
+		      mhu_status);
+		panic();
+	}
+
+	/*
+	 * Ensure that any read to the SCPI payload area is done after reading
+	 * the MHU register. If these 2 reads were reordered then the CPU would
+	 * read invalid payload data
+	 */
+	dmbld();
+
+	memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
+}
+
+static void scpi_secure_message_end(void)
+{
+	mhu_secure_message_end(SCPI_MHU_SLOT_ID);
+}
+
+int scpi_wait_ready(void)
+{
+	scpi_cmd_t scpi_cmd;
+
+	VERBOSE("Waiting for SCP_READY command...\n");
+
+	/* Get a message from the SCP */
+	scpi_secure_message_start();
+	scpi_secure_message_receive(&scpi_cmd);
+	scpi_secure_message_end();
+
+	/* We are expecting 'SCP Ready', produce correct error if it's not */
+	scpi_status_t status = SCP_OK;
+
+	if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
+		ERROR("Unexpected SCP command: expected #%u, received #%u\n",
+		      SCPI_CMD_SCP_READY, scpi_cmd.id);
+		status = SCP_E_SUPPORT;
+	} else if (scpi_cmd.size != 0) {
+		ERROR("SCP_READY cmd has incorrect size: expected 0, got %u\n",
+		      scpi_cmd.size);
+		status = SCP_E_SIZE;
+	}
+
+	VERBOSE("Sending response for SCP_READY command\n");
+
+	/*
+	 * Send our response back to SCP.
+	 * We are using the same SCPI header, just update the status field.
+	 */
+	scpi_cmd.status = status;
+	scpi_secure_message_start();
+	memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd));
+	scpi_secure_message_send(0);
+	scpi_secure_message_end();
+
+	return status == SCP_OK ? 0 : -1;
+}
+
+void scpi_set_brcm_power_state(unsigned int mpidr,
+		scpi_power_state_t cpu_state, scpi_power_state_t cluster_state,
+		scpi_power_state_t brcm_state)
+{
+	scpi_cmd_t *cmd;
+	uint32_t state = 0;
+	uint32_t *payload_addr;
+
+#if ARM_PLAT_MT
+	/*
+	 * The current SCPI driver only caters for single-threaded platforms.
+	 * Hence we ignore the thread ID (which is always 0) for such platforms.
+	 */
+	state |= (mpidr >> MPIDR_AFF1_SHIFT) & 0x0f;	/* CPU ID */
+	state |= ((mpidr >> MPIDR_AFF2_SHIFT) & 0x0f) << 4;	/* Cluster ID */
+#else
+	state |= mpidr & 0x0f;	/* CPU ID */
+	state |= (mpidr & 0xf00) >> 4;	/* Cluster ID */
+#endif /* ARM_PLAT_MT */
+
+	state |= cpu_state << 8;
+	state |= cluster_state << 12;
+	state |= brcm_state << 16;
+
+	scpi_secure_message_start();
+
+	/* Populate the command header */
+	cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+	cmd->id = SCPI_CMD_SET_POWER_STATE;
+	cmd->set = SCPI_SET_NORMAL;
+	cmd->sender = 0;
+	cmd->size = sizeof(state);
+	/* Populate the command payload */
+	payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
+	*payload_addr = state;
+	scpi_secure_message_send(sizeof(state));
+
+	/*
+	 * SCP does not reply to this command in order to avoid MHU interrupts
+	 * from the sender, which could interfere with its power state request.
+	 */
+	scpi_secure_message_end();
+}
+
+/*
+ * Query and obtain power state from SCP.
+ *
+ * In response to the query, SCP returns power states of all CPUs in all
+ * clusters of the system. The returned response is then filtered based on the
+ * supplied MPIDR. Power states of requested cluster and CPUs within are updated
+ * via. supplied non-NULL pointer arguments.
+ *
+ * Returns 0 on success, or -1 on errors.
+ */
+int scpi_get_brcm_power_state(unsigned int mpidr, unsigned int *cpu_state_p,
+		unsigned int *cluster_state_p)
+{
+	scpi_cmd_t *cmd;
+	scpi_cmd_t response;
+	int power_state, cpu, cluster, rc = -1;
+
+	/*
+	 * Extract CPU and cluster membership of the given MPIDR. SCPI caters
+	 * for only up to 0xf clusters, and 8 CPUs per cluster
+	 */
+	cpu = mpidr & MPIDR_AFFLVL_MASK;
+	cluster = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	if (cpu >= 8 || cluster >= 0xf)
+		return -1;
+
+	scpi_secure_message_start();
+
+	/* Populate request headers */
+	zeromem(SCPI_CMD_HEADER_AP_TO_SCP, sizeof(*cmd));
+	cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+	cmd->id = SCPI_CMD_GET_POWER_STATE;
+
+	/*
+	 * Send message and wait for SCP's response
+	 */
+	scpi_secure_message_send(0);
+	scpi_secure_message_receive(&response);
+
+	if (response.status != SCP_OK)
+		goto exit;
+
+	/* Validate SCP response */
+	if (!CHECK_RESPONSE(response, cluster))
+		goto exit;
+
+	/* Extract power states for required cluster */
+	power_state = *(((uint16_t *) SCPI_RES_PAYLOAD_SCP_TO_AP) + cluster);
+	if (CLUSTER_ID(power_state) != cluster)
+		goto exit;
+
+	/* Update power state via. pointers */
+	if (cluster_state_p)
+		*cluster_state_p = CLUSTER_POWER_STATE(power_state);
+	if (cpu_state_p)
+		*cpu_state_p = CPU_POWER_STATE(power_state);
+	rc = 0;
+
+exit:
+	scpi_secure_message_end();
+	return rc;
+}
+
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
+{
+	scpi_cmd_t *cmd;
+	uint8_t *payload_addr;
+
+	scpi_secure_message_start();
+
+	/* Populate the command header */
+	cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+	cmd->id = SCPI_CMD_SYS_POWER_STATE;
+	cmd->set = 0;
+	cmd->sender = 0;
+	cmd->size = sizeof(*payload_addr);
+	/* Populate the command payload */
+	payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
+	*payload_addr = system_state & 0xff;
+	scpi_secure_message_send(sizeof(*payload_addr));
+
+	scpi_secure_message_end();
+
+	return SCP_OK;
+}
diff --git a/plat/brcm/common/brcm_scpi.h b/plat/brcm/common/brcm_scpi.h
new file mode 100644
index 0000000..f3b658f
--- /dev/null
+++ b/plat/brcm/common/brcm_scpi.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BRCM_SCPI_H
+#define BRCM_SCPI_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * An SCPI command consists of a header and a payload.
+ * The following structure describes the header. It is 64-bit long.
+ */
+typedef struct {
+	/* Command ID */
+	uint32_t id		: 7;
+	/* Set ID. Identifies whether this is a standard or extended command. */
+	uint32_t set		: 1;
+	/* Sender ID to match a reply. The value is sender specific. */
+	uint32_t sender		: 8;
+	/* Size of the payload in bytes (0 - 511) */
+	uint32_t size		: 9;
+	uint32_t reserved	: 7;
+	/*
+	 * Status indicating the success of a command.
+	 * See the enum below.
+	 */
+	uint32_t status;
+} scpi_cmd_t;
+
+typedef enum {
+	SCPI_SET_NORMAL = 0,	/* Normal SCPI commands */
+	SCPI_SET_EXTENDED	/* Extended SCPI commands */
+} scpi_set_t;
+
+enum {
+	SCP_OK = 0,	/* Success */
+	SCP_E_PARAM,	/* Invalid parameter(s) */
+	SCP_E_ALIGN,	/* Invalid alignment */
+	SCP_E_SIZE,	/* Invalid size */
+	SCP_E_HANDLER,	/* Invalid handler or callback */
+	SCP_E_ACCESS,	/* Invalid access or permission denied */
+	SCP_E_RANGE,	/* Value out of range */
+	SCP_E_TIMEOUT,	/* Time out has ocurred */
+	SCP_E_NOMEM,	/* Invalid memory area or pointer */
+	SCP_E_PWRSTATE,	/* Invalid power state */
+	SCP_E_SUPPORT,	/* Feature not supported or disabled */
+	SCPI_E_DEVICE,	/* Device error */
+	SCPI_E_BUSY,	/* Device is busy */
+};
+
+typedef uint32_t scpi_status_t;
+typedef enum {
+	SCPI_CMD_SCP_READY = 0x01,
+	SCPI_CMD_SET_POWER_STATE = 0x03,
+	SCPI_CMD_GET_POWER_STATE = 0x04,
+	SCPI_CMD_SYS_POWER_STATE = 0x05
+} scpi_command_t;
+
+/*
+ * Macros to parse SCP response to GET_POWER_STATE command
+ *
+ *   [3:0] : cluster ID
+ *   [7:4] : cluster state: 0 = on; 3 = off; rest are reserved
+ *   [15:8]: on/off state for individual CPUs in the cluster
+ *
+ * Payload is in little-endian
+ */
+#define CLUSTER_ID(_resp)		((_resp) & 0xf)
+#define CLUSTER_POWER_STATE(_resp)	(((_resp) >> 4) & 0xf)
+
+/* Result is a bit mask of CPU on/off states in the cluster */
+#define CPU_POWER_STATE(_resp)		(((_resp) >> 8) & 0xff)
+
+/*
+ * For GET_POWER_STATE, SCP returns the power states of every cluster. The
+ * size of response depends on the number of clusters in the system. The
+ * SCP-to-AP payload contains 2 bytes per cluster. Make sure the response is
+ * large enough to contain power states of a given cluster
+ */
+#define CHECK_RESPONSE(_resp, _clus)  (_resp.size >= (((_clus) + 1) * 2))
+
+typedef enum {
+	scpi_power_on = 0,
+	scpi_power_retention = 1,
+	scpi_power_off = 3,
+} scpi_power_state_t;
+
+typedef enum {
+	scpi_system_shutdown = 0,
+	scpi_system_reboot = 1,
+	scpi_system_reset = 2
+} scpi_system_state_t;
+
+extern int scpi_wait_ready(void);
+extern void scpi_set_brcm_power_state(unsigned int mpidr,
+				      scpi_power_state_t cpu_state,
+				      scpi_power_state_t cluster_state,
+				      scpi_power_state_t css_state);
+int scpi_get_brcm_power_state(unsigned int mpidr, unsigned int *cpu_state_p,
+			      unsigned int *cluster_state_p);
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
+
+#endif	/* BRCM_SCPI_H */
diff --git a/plat/socionext/uniphier/include/platform_def.h b/plat/socionext/uniphier/include/platform_def.h
index 7c6341d..b23386d 100644
--- a/plat/socionext/uniphier/include/platform_def.h
+++ b/plat/socionext/uniphier/include/platform_def.h
@@ -62,7 +62,6 @@
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
 
-#define PLAT_XLAT_TABLES_DYNAMIC	1
 #define MAX_XLAT_TABLES			9
 #define MAX_MMAP_REGIONS		13
 
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index 8819545..2c0ed92 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -21,6 +21,9 @@
 BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES
 endif
 
+# The dynamic xlat table is only used in BL2
+BL2_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+
 # Cortex-A53 revision r0p4-51rel0
 # needed for LD20, unneeded for LD11, PXs3 (no ACE)
 ERRATA_A53_855873		:= 1