drivers: Add emmc driver for Broadcom platforms

Add emmc driver for Broadcom platforms

Change-Id: I126a6dfccd41062cb0b856f2c2fb1f724730b95e
Signed-off-by: Sheetal Tigadoli <sheetal.tigadoli@broadcom.com>
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/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/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
index a0112c5..2a7ebdf 100644
--- a/plat/brcm/board/common/board_common.mk
+++ b/plat/brcm/board/common/board_common.mk
@@ -28,6 +28,10 @@
 $(eval $(call add_define,SYSCNT_FREQ))
 endif
 
+ifeq (${DRIVER_EMMC_ENABLE},)
+DRIVER_EMMC_ENABLE :=1
+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
@@ -89,6 +93,14 @@
 $(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
@@ -97,7 +109,8 @@
 USE_TBBR_DEFS			:=	1
 
 PLAT_INCLUDES		+=	-Iplat/brcm/board/common \
-				-Iinclude/drivers/brcm
+				-Iinclude/drivers/brcm \
+				-Iinclude/drivers/brcm/emmc
 
 PLAT_BL_COMMON_SOURCES	+=	plat/brcm/common/brcm_common.c \
 				plat/brcm/board/common/cmn_sec.c \
@@ -116,6 +129,22 @@
 				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
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/platform.mk b/plat/brcm/board/stingray/platform.mk
index cc7ae53..8d2119d 100644
--- a/plat/brcm/board/stingray/platform.mk
+++ b/plat/brcm/board/stingray/platform.mk
@@ -24,6 +24,13 @@
 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
 
@@ -178,6 +185,7 @@
 				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)
diff --git a/plat/brcm/board/stingray/src/bl2_setup.c b/plat/brcm/board/stingray/src/bl2_setup.c
index 0b0a3ff..9a79744 100644
--- a/plat/brcm/board/stingray/src/bl2_setup.c
+++ b/plat/brcm/board/stingray/src/bl2_setup.c
@@ -15,6 +15,7 @@
 #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>