msm_shared: mmc: Add BAM and DML support.

Change-Id: I81fb4105a313cb6d555587418e806c5f22dcb37b
diff --git a/platform/copper/include/platform/iomap.h b/platform/copper/include/platform/iomap.h
index f29cccd..d099e3d 100644
--- a/platform/copper/include/platform/iomap.h
+++ b/platform/copper/include/platform/iomap.h
@@ -30,6 +30,7 @@
 #define _PLATFORM_MSMCOPPER_IOMAP_H_
 
 #define SDRAM_START_ADDR            0x00000000
+#define SDRAM_SEC_BANK_START_ADDR   0x10000000
 
 #define MSM_SHARED_BASE             0x0FA00000
 
@@ -41,15 +42,22 @@
 #define APCS_APC_KPSS_PLL_BASE      (KPSS_BASE + 0x0000A000)
 #define APCS_KPSS_CFG_BASE          (KPSS_BASE + 0x00010000)
 #define APCS_KPSS_WDT_BASE          (KPSS_BASE + 0x00017000)
-#define KPSS_APCS_QTMR_AC_BASE      (KPSS_BASE + 0x20000)
-#define KPSS_APCS_F0_QTMR_V1_BASE   (KPSS_BASE + 0x21000)
-#define QTMR_BASE                   KPSS_APCS_F0_QTMR_V1_BASE
 
 #define PERIPH_SS_BASE              0xF9800000
+
+#define MSM_SDC1_BAM_BASE           (PERIPH_SS_BASE + 0x00004000)
 #define MSM_SDC1_BASE               (PERIPH_SS_BASE + 0x00024000)
+#define MSM_SDC1_DML_BASE           (PERIPH_SS_BASE + 0x00024800)
+#define MSM_SDC3_BAM_BASE           (PERIPH_SS_BASE + 0x00044000)
 #define MSM_SDC3_BASE               (PERIPH_SS_BASE + 0x00064000)
+#define MSM_SDC3_DML_BASE           (PERIPH_SS_BASE + 0x00064800)
+#define MSM_SDC2_BAM_BASE           (PERIPH_SS_BASE + 0x00084000)
 #define MSM_SDC2_BASE               (PERIPH_SS_BASE + 0x000A4000)
+#define MSM_SDC2_DML_BASE           (PERIPH_SS_BASE + 0x000A4800)
+#define MSM_SDC4_BAM_BASE           (PERIPH_SS_BASE + 0x000C4000)
 #define MSM_SDC4_BASE               (PERIPH_SS_BASE + 0x000E4000)
+#define MSM_SDC4_DML_BASE           (PERIPH_SS_BASE + 0x000E4800)
+
 #define BLSP1_UART0_BASE            (PERIPH_SS_BASE + 0x0011D000)
 #define BLSP1_UART1_BASE            (PERIPH_SS_BASE + 0x0011E000)
 #define BLSP1_UART2_BASE            (PERIPH_SS_BASE + 0x0011F000)
@@ -70,7 +78,6 @@
 
 #define MPM2_MPM_CTRL_BASE          0xFC4A1000
 
-
 /* Clock control registers */
 
 /* GPLL */
diff --git a/platform/msm_shared/include/mmc_dml.h b/platform/msm_shared/include/mmc_dml.h
new file mode 100644
index 0000000..3941bf6
--- /dev/null
+++ b/platform/msm_shared/include/mmc_dml.h
@@ -0,0 +1,59 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MMC_DML_H__
+#define __MMC_DML_H__
+
+#include <platform/iomap.h>
+
+#define SDCC_DML_CONFIG(base)                       (0x00 + base)
+#define SDCC_CONSUMER_CRCI_SEL_SHIFT                2
+#define SDCC_PRODUCER_CRCI_SEL_SHIFT                0
+#define SDCC_PRODUCER_TRANS_END_EN_SHIFT            4
+#define SDCC_BYPASS_SHIFT                           16
+#define SDCC_DIRECT_MODE_SHIFT                      17
+#define SDCC_INFINITE_CONS_TRANS_SHIFT              18
+
+#define SDCC_DML_STATUS(base)                       (0x04 + base)
+#define SDCC_DML_PRODUCER_IDLE_SHIFT                0
+#define SDCC_DML_CONSUMER_IDLE_SHIFT                16
+
+#define SDCC_DML_SW_RESET(base)                     (0x08 + base)
+#define SDCC_DML_PRODUCER_START(base)               (0x0C + base)
+#define SDCC_DML_CONSUMER_START(base)               (0x10 + base)
+#define SDCC_DML_PRODUCER_PIPE_LOGICAL_SIZE(base)   (0x14 + base)
+#define SDCC_DML_CONSUMER_PIPE_LOGICAL_SIZE(base)   (0x18 + base)
+
+#define SDCC_DML_PIPE_ID(base)                      (0x1C + base)
+#define SDCC_CONSUMER_PIPE_ID_SHIFT                 16
+#define SDCC_PRODUCER_PIPE_ID_SHIFT                 0
+
+#define SDCC_DML_PRODUCER_BAM_BLOCK_SIZE(base)      (0x24 + base)
+#define SDCC_DML_PRODUCER_BAM_TRANS_SIZE(base)      (0x28 + base)
+
+#endif
diff --git a/platform/msm_shared/mmc.c b/platform/msm_shared/mmc.c
index e04c64f..803a1e2 100644
--- a/platform/msm_shared/mmc.c
+++ b/platform/msm_shared/mmc.c
@@ -39,6 +39,11 @@
 #include "adm.h"
 #endif
 
+#if MMC_BOOT_BAM
+#include "bam.h"
+#include "mmc_dml.h"
+#endif
+
 #ifndef NULL
 #define NULL        0
 #endif
@@ -46,7 +51,7 @@
 #define MMC_BOOT_DATA_READ     0
 #define MMC_BOOT_DATA_WRITE    1
 
-static unsigned int mmc_boot_fifo_data_transfer(unsigned int *data_ptr,
+static unsigned int mmc_boot_data_transfer(unsigned int *data_ptr,
 						unsigned int data_len,
 						unsigned char direction);
 
@@ -56,6 +61,32 @@
 static unsigned int mmc_boot_fifo_write(unsigned int *data_ptr,
 					unsigned int data_len);
 
+static unsigned int mmc_boot_status_error(unsigned mmc_status);
+
+#if MMC_BOOT_BAM
+
+void mmc_boot_dml_init();
+
+static void mmc_boot_dml_producer_trans_init(unsigned trans_end,
+										     unsigned size);
+
+static void mmc_boot_dml_consumer_trans_init();
+
+static uint32_t mmc_boot_dml_chk_producer_idle();
+
+static void mmc_boot_dml_wait_producer_idle();
+static void mmc_boot_dml_wait_consumer_idle();
+static void mmc_boot_dml_reset();
+static int mmc_bam_init(uint32_t bam_base);
+static int mmc_bam_transfer_data();
+static unsigned int
+mmc_boot_bam_setup_desc(unsigned int *data_ptr,
+			    unsigned int data_len, unsigned char direction);
+
+
+#endif
+
+
 #define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
 
 /* data access time unit in ns */
@@ -78,6 +109,30 @@
 static unsigned char ext_csd_buf[512];
 static unsigned char wp_status_buf[8];
 
+#if MMC_BOOT_BAM
+
+static uint32_t mmc_sdc_bam_base[] =
+	{ MSM_SDC1_BAM_BASE, MSM_SDC2_BAM_BASE, MSM_SDC3_BAM_BASE, MSM_SDC4_BAM_BASE };
+
+static uint32_t mmc_sdc_dml_base[] =
+	{ MSM_SDC1_DML_BASE, MSM_SDC2_DML_BASE, MSM_SDC3_DML_BASE, MSM_SDC4_DML_BASE };
+
+uint32_t dml_base;
+static struct bam_instance bam;
+
+#define MMC_BOOT_BAM_FIFO_SIZE           100
+
+#define MMC_BOOT_BAM_READ_PIPE_INDEX     0
+#define MMC_BOOT_BAM_WRITE_PIPE_INDEX    1
+
+#define MMC_BOOT_BAM_READ_PIPE           0
+#define MMC_BOOT_BAM_WRITE_PIPE          1
+
+/* Align at BAM_DESC_SIZE boundary */
+static struct bam_desc desc_fifo[MMC_BOOT_BAM_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
+
+#endif
+
 int mmc_clock_enable_disable(unsigned id, unsigned enable);
 int mmc_clock_get_rate(unsigned id);
 int mmc_clock_set_rate(unsigned id, unsigned rate);
@@ -1071,12 +1126,17 @@
 	    MMC_BOOT_MCI_DATA_ENABLE | MMC_BOOT_MCI_DATA_DIR | (512 <<
 								MMC_BOOT_MCI_BLKSIZE_POS);
 
-#if MMC_BOOT_ADM
+#if MMC_BOOT_ADM || MMC_BOOT_BAM
 	mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
 #endif
 
 	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);
 
+#if MMC_BOOT_BAM
+	/*  Setup SDCC BAM descriptors for Read operation. */
+	mmc_ret = mmc_boot_bam_setup_desc(mmc_ptr, 512, MMC_BOOT_DATA_READ);
+#endif
+
 	memset((struct mmc_boot_command *)&cmd, 0,
 	       sizeof(struct mmc_boot_command));
 	/* CMD8 */
@@ -1092,7 +1152,10 @@
 	}
 
 	/* Read the transfer data from SDCC FIFO. */
-	mmc_ret = mmc_boot_fifo_data_transfer(mmc_ptr, 512, MMC_BOOT_DATA_READ);
+	mmc_ret = mmc_boot_data_transfer(mmc_ptr, 512, MMC_BOOT_DATA_READ);
+
+	/* Reset DPSM */
+	writel(0, MMC_BOOT_MCI_DATA_CTL);
 
 	return mmc_ret;
 }
@@ -1361,6 +1424,10 @@
 	/* Write the total size of the transfer data to MCI_DATA_LENGTH register */
 	writel(data_len, MMC_BOOT_MCI_DATA_LENGTH);
 
+#if MMC_BOOT_BAM
+		mmc_boot_bam_setup_desc(in, data_len, MMC_BOOT_DATA_WRITE);
+#endif
+
 	/* Send command to the card/device in order to start the write data xfer.
 	   The possible commands are CMD24/25/53/60/61 */
 	mmc_ret = mmc_boot_send_write_command(card, xfer_type, addr);
@@ -1382,7 +1449,7 @@
 
 	/* Set DM_ENABLE bit to 1 in order to enable DMA, otherwise set 0 */
 
-#if MMC_BOOT_ADM
+#if MMC_BOOT_ADM || MMC_BOOT_BAM
 	mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
 #endif
 
@@ -1393,7 +1460,7 @@
 
 	/* write data to FIFO */
 	mmc_ret =
-	    mmc_boot_fifo_data_transfer(in, data_len, MMC_BOOT_DATA_WRITE);
+	    mmc_boot_data_transfer(in, data_len, MMC_BOOT_DATA_WRITE);
 
 	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
 		dprintf(CRITICAL, "Error No.%d: Failure on data transfer from the \
@@ -1438,6 +1505,14 @@
 	}
 	while (1);
 
+#if MMC_BOOT_BAM
+	/* Wait for DML trasaction to end */
+	mmc_boot_dml_wait_consumer_idle();
+#endif
+
+	/* Reset DPSM */
+	writel(0, MMC_BOOT_MCI_DATA_CTL);
+
 	return MMC_BOOT_E_SUCCESS;
 }
 
@@ -1619,7 +1694,7 @@
 
 	/* If DMA is to be used, Set DM_ENABLE bit to 1 */
 
-#if MMC_BOOT_ADM
+#if MMC_BOOT_ADM || MMC_BOOT_BAM
 	mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
 #endif
 
@@ -1628,6 +1703,10 @@
 	mmc_reg |= (card->rd_block_len << MMC_BOOT_MCI_BLKSIZE_POS);
 	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);
 
+#if MMC_BOOT_BAM
+	/* Setup SDCC FIFO descriptors for Read operation. */
+	mmc_ret = mmc_boot_bam_setup_desc(out, data_len, MMC_BOOT_DATA_READ);
+#endif
 	/* Send command to the card/device in order to start the read data
 	   transfer. Possible commands: CMD17/18/53/60/61. */
 	mmc_ret = mmc_boot_send_read_command(card, xfer_type, addr);
@@ -1639,8 +1718,7 @@
 	}
 
 	/* Read the transfer data from SDCC FIFO. */
-	mmc_ret =
-	    mmc_boot_fifo_data_transfer(out, data_len, MMC_BOOT_DATA_READ);
+	mmc_ret = mmc_boot_data_transfer(out, data_len, MMC_BOOT_DATA_READ);
 
 	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
 		dprintf(CRITICAL, "Error No.%d: Failure on data transfer from the \
@@ -1661,6 +1739,9 @@
 		}
 	}
 
+	/* Reset DPSM */
+	writel(0, MMC_BOOT_MCI_DATA_CTL);
+
 	return MMC_BOOT_E_SUCCESS;
 }
 
@@ -2143,6 +2224,12 @@
 		return MMC_BOOT_E_FAILURE;
 	}
 
+#if MMC_BOOT_BAM
+
+	mmc_ret = mmc_bam_init(mmc_sdc_bam_base[slot - 1]);
+	dml_base = mmc_sdc_dml_base[slot - 1];
+#endif
+
 	/* Initialize and identify cards connected to host */
 	mmc_ret = mmc_boot_init_and_identify_cards(&mmc_host, &mmc_card);
 	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
@@ -2235,7 +2322,7 @@
 	    MMC_BOOT_MCI_DATA_ENABLE | MMC_BOOT_MCI_DATA_DIR | (data_len <<
 								MMC_BOOT_MCI_BLKSIZE_POS);
 
-#if MMC_BOOT_ADM
+#if MMC_BOOT_ADM || MMC_BOOT_BAM
 	mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
 #endif
 
@@ -2257,7 +2344,7 @@
 
 	/* Read the transfer data from SDCC FIFO. */
 	mmc_ret =
-	    mmc_boot_fifo_data_transfer(out, data_len, MMC_BOOT_DATA_READ);
+	    mmc_boot_data_transfer(out, data_len, MMC_BOOT_DATA_READ);
 
 	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
 		dprintf(CRITICAL, "Error No.%d: Failure on data transfer from the \
@@ -2468,7 +2555,7 @@
  * Read/write data from/to SDC FIFO.
  */
 static unsigned int
-mmc_boot_fifo_data_transfer(unsigned int *data_ptr,
+mmc_boot_data_transfer(unsigned int *data_ptr,
 			    unsigned int data_len, unsigned char direction)
 {
 	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
@@ -2491,6 +2578,9 @@
 		dprintf(CRITICAL, "MMC ADM transfer error: %d\n", ret);
 		mmc_ret = MMC_BOOT_E_FAILURE;
 	}
+
+#elif MMC_BOOT_BAM
+	mmc_ret = mmc_bam_transfer_data(data_ptr, data_len, direction);
 #else
 
 	if (direction == MMC_BOOT_DATA_READ) {
@@ -2499,6 +2589,7 @@
 		mmc_ret = mmc_boot_fifo_write(data_ptr, data_len);
 	}
 #endif
+
 	return mmc_ret;
 }
 
@@ -2830,3 +2921,273 @@
 {
 	return &mmc_card;
 }
+
+#if MMC_BOOT_BAM
+
+void mmc_boot_dml_init()
+{
+	uint32_t val = 0;
+
+	/* Initialize s/w reset for DML core */
+	mmc_boot_dml_reset();
+
+	/* Program DML config:
+	 * 1. Disable producer and consumer CRCI.
+	 * 2. Set Bypass mode for the DML for Direct access.
+	 */
+	val = 0;
+	val |= 1 >> SDCC_BYPASS_SHIFT;
+	writel(val, SDCC_DML_CONFIG(dml_base));
+
+	/* Program consumer logic size:
+	 * This is for handshaking between the BAM and the DML blocks.
+	 */
+	writel(4096, SDCC_DML_CONSUMER_PIPE_LOGICAL_SIZE(dml_base));
+
+	/* Program producer logic size
+	 * This is for handshaking between the BAM and the DML blocks.
+	 */
+	writel(4096, SDCC_DML_PRODUCER_PIPE_LOGICAL_SIZE(dml_base));
+
+
+	/* Write the pipe id numbers. */
+	val = 0;
+	val |= bam.pipe[MMC_BOOT_BAM_READ_PIPE_INDEX].pipe_num << SDCC_PRODUCER_PIPE_ID_SHIFT;
+	val |= bam.pipe[MMC_BOOT_BAM_WRITE_PIPE_INDEX].pipe_num << SDCC_CONSUMER_PIPE_ID_SHIFT;
+
+	writel(val, SDCC_DML_PIPE_ID(dml_base));
+
+}
+
+/* Function to set up SDCC dml for System producer transaction. */
+static void mmc_boot_dml_consumer_trans_init()
+{
+	uint32_t val = 0;
+
+	val = 0 << SDCC_PRODUCER_CRCI_SEL_SHIFT;
+	val |= 1 << SDCC_CONSUMER_CRCI_SEL_SHIFT;
+	writel(val, SDCC_DML_CONFIG(dml_base));
+
+
+	/* Start the consumer transaction */
+	writel(1, SDCC_DML_CONSUMER_START(dml_base));
+
+}
+
+/* Function to set up SDCC dml for System consumer transaction.
+ * trans_end: 1: Assert DML trasaction signal
+ *                 at the end of transaction.
+ *                 0: Do not assert DML transaction signal.
+ * size: Transaction size
+ */
+static void mmc_boot_dml_producer_trans_init(unsigned trans_end,
+                                             unsigned size)
+{
+	uint32_t val = 0;
+
+	val = 1 << SDCC_PRODUCER_CRCI_SEL_SHIFT;
+	val |= 0 << SDCC_CONSUMER_CRCI_SEL_SHIFT;
+	val |=  trans_end << SDCC_PRODUCER_TRANS_END_EN_SHIFT;
+	writel(val, SDCC_DML_CONFIG(dml_base));
+
+	/* Set block size */
+    writel(BLOCK_SIZE, SDCC_DML_PRODUCER_BAM_BLOCK_SIZE(dml_base));
+
+	/* Write transaction size */
+	writel(size, SDCC_DML_PRODUCER_BAM_TRANS_SIZE(dml_base));
+
+	/* Start the producer transaction */
+	writel(1, SDCC_DML_PRODUCER_START(dml_base));
+}
+
+/* Function to check producer idle status of the DML.
+ * return value: 1: Producer is idle
+ *                    0: Producer is busy
+ */
+static uint32_t mmc_boot_dml_chk_producer_idle()
+{
+	uint32_t val = 0;
+
+	val = readl(SDCC_DML_STATUS(dml_base));
+
+	/* Read only the producer idle status */
+	val &= (1 << SDCC_DML_PRODUCER_IDLE_SHIFT);
+
+	return val;
+}
+
+/* Function to clear transaction complete flag */
+static void mmc_boot_dml_clr_trans_complete()
+{
+	uint32_t val;
+
+	val = readl(SDCC_DML_CONFIG(dml_base));
+
+	val &=  ~(1 << SDCC_PRODUCER_TRANS_END_EN_SHIFT);
+	writel(val, SDCC_DML_CONFIG(dml_base));
+}
+
+/* Blocking function to wait until DML is idle. */
+static void mmc_boot_dml_wait_producer_idle()
+{
+	while(!(readl(SDCC_DML_STATUS(dml_base)) & 1));
+}
+
+/* Blocking function to wait until DML is idle. */
+static void mmc_boot_dml_wait_consumer_idle()
+{
+	while(!(readl(SDCC_DML_STATUS(dml_base)) & (1 << SDCC_DML_CONSUMER_IDLE_SHIFT)));
+}
+
+/* Initialize S/W reset */
+static void mmc_boot_dml_reset()
+{
+	/* Initialize s/w reset for DML core */
+	writel(1, SDCC_DML_SW_RESET(dml_base));
+
+}
+
+static int mmc_bam_init(uint32_t bam_base)
+{
+
+	uint32_t mmc_ret = MMC_BOOT_E_SUCCESS;
+
+	bam.base = bam_base;
+	/* Read pipe parameter initializations. */
+	bam.pipe[MMC_BOOT_BAM_READ_PIPE_INDEX].pipe_num = MMC_BOOT_BAM_READ_PIPE;
+	/* System consumer */
+	bam.pipe[MMC_BOOT_BAM_READ_PIPE_INDEX].trans_type = BAM2SYS;
+	/* Set the descriptor FIFO start ptr */
+	bam.pipe[MMC_BOOT_BAM_READ_PIPE_INDEX].fifo.head = desc_fifo;
+	/* Set the descriptor FIFO lengths */
+	bam.pipe[MMC_BOOT_BAM_READ_PIPE_INDEX].fifo.size = MMC_BOOT_BAM_FIFO_SIZE;
+
+	/* Write pipe parameter initializations.*/
+	bam.pipe[MMC_BOOT_BAM_WRITE_PIPE_INDEX].pipe_num = MMC_BOOT_BAM_WRITE_PIPE;
+	/* System producer */
+	bam.pipe[MMC_BOOT_BAM_WRITE_PIPE_INDEX].trans_type = SYS2BAM;
+	/* Write fifo uses the same fifo as read */
+	bam.pipe[MMC_BOOT_BAM_WRITE_PIPE_INDEX].fifo.head = desc_fifo;
+	/* Set the descriptor FIFO lengths */
+	bam.pipe[MMC_BOOT_BAM_WRITE_PIPE_INDEX].fifo.size = MMC_BOOT_BAM_FIFO_SIZE;
+
+	/* Programs the minimum threshold for BAM transfer*/
+	bam.threshold = BLOCK_SIZE;
+
+	/* Initialize MMC BAM */
+	bam_init(&bam);
+
+	/* Initialize BAM MMC read pipe */
+	bam_sys_pipe_init(&bam, MMC_BOOT_BAM_READ_PIPE_INDEX);
+
+	mmc_ret = bam_pipe_fifo_init(&bam, bam.pipe[MMC_BOOT_BAM_READ_PIPE_INDEX].pipe_num);
+
+	if (mmc_ret)
+	{
+		dprintf(CRITICAL, "MMC: BAM Read pipe fifo init error\n");
+		goto mmc_bam_init_error;
+	}
+
+	/* Initialize BAM MMC write pipe */
+	bam_sys_pipe_init(&bam, MMC_BOOT_BAM_WRITE_PIPE_INDEX);
+
+	mmc_ret = bam_pipe_fifo_init(&bam, bam.pipe[MMC_BOOT_BAM_WRITE_PIPE_INDEX].pipe_num);
+
+	if (mmc_ret)
+	{
+		dprintf(CRITICAL, "MMC: BAM Write pipe fifo init error\n");
+		goto mmc_bam_init_error;
+	}
+
+	mmc_boot_dml_init();
+
+	mmc_bam_init_error:
+
+	return mmc_ret;
+}
+
+static int mmc_bam_transfer_data(unsigned int *data_ptr,
+                                 unsigned int data_len,
+			                     unsigned int dir)
+{
+	uint32_t mmc_ret;
+	uint32_t offset;
+
+	mmc_ret = MMC_BOOT_E_SUCCESS;
+
+	if(dir == MMC_BOOT_DATA_READ)
+	{
+		/* Check BAM IRQ status reg to verify the desc has been processed */
+		mmc_ret = bam_wait_for_interrupt(&bam,
+					MMC_BOOT_BAM_READ_PIPE_INDEX, P_PRCSD_DESC_EN_MASK);
+
+		if (mmc_ret != BAM_RESULT_SUCCESS)
+		{
+			dprintf(CRITICAL, "BAM transfer error \n");
+			mmc_ret = MMC_BOOT_E_FAILURE;
+			goto mmc_bam_transfer_err;
+		}
+
+		mmc_boot_dml_wait_producer_idle();
+
+		/* Update BAM pipe fifo offsets */
+		offset = bam_read_offset_update(&bam, MMC_BOOT_BAM_READ_PIPE_INDEX);
+
+		/* Reset DPSM */
+		writel(0, MMC_BOOT_MCI_DATA_CTL);
+
+		dprintf(SPEW, "Offset value is %d \n", offset);
+	}
+	else
+	{
+		/* Check BAM IRQ status reg to verify the desc has been processed */
+		mmc_ret = bam_wait_for_interrupt(&bam,
+					MMC_BOOT_BAM_WRITE_PIPE_INDEX, P_TRNSFR_END_EN_MASK);
+
+		if (mmc_ret != BAM_RESULT_SUCCESS)
+		{
+			dprintf(CRITICAL, "BAM transfer error \n");
+			mmc_ret = MMC_BOOT_E_FAILURE;
+			goto mmc_bam_transfer_err;
+		}
+
+		/* Update BAM pipe fifo offsets */
+		offset = bam_read_offset_update(&bam, MMC_BOOT_BAM_WRITE_PIPE_INDEX);
+
+		dprintf(SPEW, "Offset value is %d \n", offset);
+	}
+
+mmc_bam_transfer_err:
+
+	return mmc_ret;
+}
+
+static unsigned int
+mmc_boot_bam_setup_desc(unsigned int *data_ptr,
+                        unsigned int data_len,
+                        unsigned char direction)
+{
+	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+
+	if (direction == MMC_BOOT_DATA_READ)
+	{
+		mmc_boot_dml_producer_trans_init(1, data_len);
+		mmc_ret = bam_add_desc(&bam, MMC_BOOT_BAM_READ_PIPE_INDEX,
+					(unsigned char *)data_ptr, data_len);
+	}
+	else
+	{
+		mmc_boot_dml_consumer_trans_init();
+		mmc_ret = bam_add_desc(&bam, MMC_BOOT_BAM_WRITE_PIPE_INDEX,
+					(unsigned char *)data_ptr, data_len);
+	}
+
+	/* Update return value enums */
+	if (mmc_ret != BAM_RESULT_SUCCESS)
+	{
+		dprintf(CRITICAL, "MMC BAM transfer error: %d\n", mmc_ret);
+		mmc_ret = MMC_BOOT_E_FAILURE;
+	}
+}
+
+#endif
diff --git a/project/copper.mk b/project/copper.mk
index e6e7b40..7b97869 100644
--- a/project/copper.mk
+++ b/project/copper.mk
@@ -12,3 +12,4 @@
 DEFINES += WITH_DEBUG_UART=1
 #DEFINES += WITH_DEBUG_FBCON=1
 DEFINES += DEVICE_TREE=1
+DEFINES += MMC_BOOT_BAM=1