[msm_shared/mmc]: data mover for mmc/sd data transfers
- disabled until display patch goes in.
Change-Id: Ia43ff6269d2d193fbaaf0610d1938296a62281d7
diff --git a/platform/msm_shared/mmc.c b/platform/msm_shared/mmc.c
index f345ec3..aefccef 100644
--- a/platform/msm_shared/mmc.c
+++ b/platform/msm_shared/mmc.c
@@ -33,10 +33,28 @@
#include "mmc.h"
#include <platform/iomap.h>
+#if MMC_BOOT_ADM
+#include "adm.h"
+#endif
+
#ifndef NULL
#define NULL 0
#endif
+#define MMC_BOOT_DATA_READ 0
+#define MMC_BOOT_DATA_WRITE 1
+
+
+static unsigned int mmc_boot_fifo_data_transfer(unsigned int* data_ptr,
+ unsigned int data_len,
+ unsigned char direction);
+
+static unsigned int mmc_boot_fifo_read(unsigned int* data_ptr,
+ unsigned int data_len);
+
+static unsigned int mmc_boot_fifo_write(unsigned int* data_ptr,
+ unsigned int data_len);
+
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
/* data access time unit in ns */
@@ -1124,10 +1142,7 @@
struct mmc_boot_command cmd;
unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
unsigned int mmc_reg = 0;
- unsigned int mmc_status = 0;
unsigned int* mmc_ptr = (unsigned int *)buf;
- unsigned int mmc_count = 0;
- unsigned int read_error;
memset(buf,0, 512);
@@ -1163,6 +1178,11 @@
/* Set appropriate fields and write the MCI_DATA_CTL register. */
/* Set ENABLE bit to 1 to enable the data transfer. */
mmc_reg = MMC_BOOT_MCI_DATA_ENABLE | MMC_BOOT_MCI_DATA_DIR | (512 << MMC_BOOT_MCI_BLKSIZE_POS);
+
+#if MMC_BOOT_ADM
+ mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
+#endif
+
writel( mmc_reg, MMC_BOOT_MCI_DATA_CTL );
memset( (struct mmc_boot_command *)&cmd, 0,
@@ -1180,56 +1200,10 @@
return mmc_ret;
}
- read_error = MMC_BOOT_MCI_STAT_DATA_CRC_FAIL | \
- MMC_BOOT_MCI_STAT_DATA_TIMEOUT | \
- MMC_BOOT_MCI_STAT_RX_OVRRUN;
+ /* Read the transfer data from SDCC FIFO. */
+ mmc_ret = mmc_boot_fifo_data_transfer(mmc_ptr, 512, MMC_BOOT_DATA_READ);
- /* Read the transfer data from SDCC2 FIFO. If Data Mover is not used
- read the data from the MCI_FIFO register as long as RXDATA_AVLBL
- bit of MCI_STATUS register is set to 1 and bits DATA_CRC_FAIL,
- DATA_TIMEOUT, RX_OVERRUN of MCI_STATUS register are cleared to 0.
- Continue the reads until the whole transfer data is received */
-
- do
- {
- mmc_ret = MMC_BOOT_E_SUCCESS;
- mmc_status = readl( MMC_BOOT_MCI_STATUS );
-
- if( mmc_status & read_error )
- {
- mmc_ret = mmc_boot_status_error(mmc_status);
- break;
- }
-
- if( mmc_status & MMC_BOOT_MCI_STAT_RX_DATA_AVLBL )
- {
- unsigned read_count = 1;
- if ( mmc_status & MMC_BOOT_MCI_STAT_RX_FIFO_HFULL)
- {
- read_count = MMC_BOOT_MCI_HFIFO_COUNT;
- }
-
- for (int i=0; i<read_count; i++)
- {
- /* FIFO contains 16 32-bit data buffer on 16 sequential addresses*/
- *mmc_ptr = readl( MMC_BOOT_MCI_FIFO +
- ( mmc_count % MMC_BOOT_MCI_FIFO_SIZE ) );
- mmc_ptr++;
- /* increase mmc_count by word size */
- mmc_count += sizeof( unsigned int );
- }
- /* quit if we have read enough of data */
- if (mmc_count >= 512)
- break;
- }
- else if( mmc_status & MMC_BOOT_MCI_STAT_DATA_END )
- {
- break;
- }
- }while(1);
-
- return MMC_BOOT_E_SUCCESS;
-
+ return mmc_ret;
}
/*
@@ -1477,12 +1451,9 @@
{
unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
unsigned int mmc_status = 0;
- unsigned int* mmc_ptr = in;
- unsigned int mmc_count = 0;
unsigned int mmc_reg = 0;
unsigned int addr;
unsigned int xfer_type;
- unsigned int write_error;
unsigned int status;
if( ( host == NULL ) || ( card == NULL ) )
@@ -1508,7 +1479,7 @@
MMC_BOOT_XFER_SINGLE_BLOCK;
/* For MMCHC/SDHC data address is specified in unit of 512B */
- addr = ( (card->type != MMC_BOOT_TYPE_MMCHC) && (card->type != MMC_BOOT_TYPE_SDHC) )
+ addr = ( (card->type != MMC_BOOT_TYPE_MMCHC) && (card->type != MMC_BOOT_TYPE_SDHC) )
? (unsigned int) data_addr : (unsigned int) (data_addr / 512);
/* Set the FLOW_ENA bit of MCI_CLK register to 1 */
@@ -1543,63 +1514,20 @@
/* Clear MODE bit to 0 to enable block oriented data transfer. For
MMC cards only, if stream data transfer mode is desired, set
MODE bit to 1. */
+
/* Set DM_ENABLE bit to 1 in order to enable DMA, otherwise set 0 */
+
+#if MMC_BOOT_ADM
+ mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
+#endif
+
/* Write size of block to be used during the data transfer to
BLOCKSIZE field */
mmc_reg |= card->wr_block_len << MMC_BOOT_MCI_BLKSIZE_POS;
writel( mmc_reg, MMC_BOOT_MCI_DATA_CTL );
- write_error = MMC_BOOT_MCI_STAT_DATA_CRC_FAIL | \
- MMC_BOOT_MCI_STAT_DATA_TIMEOUT | \
- MMC_BOOT_MCI_STAT_TX_UNDRUN;
-
- /* Write the transfer data to SDCC3 FIFO */
- /* If Data Mover is used for data transfer, prepare a command list entry
- and enable the Data Mover to work with SDCC2 */
- /* If Data Mover is NOT used for data xfer: */
- do
- {
- mmc_ret = MMC_BOOT_E_SUCCESS;
- mmc_status = readl( MMC_BOOT_MCI_STATUS );
-
- if( mmc_status & write_error )
- {
- mmc_ret = mmc_boot_status_error(mmc_status);
- break;
- }
-
- /* Write the data in MCI_FIFO register as long as TXFIFO_FULL bit of
- MCI_STATUS register is 0. Continue the writes until the whole
- transfer data is written. */
- if (((data_len-mmc_count) >= MMC_BOOT_MCI_FIFO_SIZE/2) &&
- ( mmc_status & MMC_BOOT_MCI_STAT_TX_FIFO_HFULL ))
- {
- for (int i=0; i < MMC_BOOT_MCI_HFIFO_COUNT; i++ )
- {
- /* FIFO contains 16 32-bit data buffer on 16 sequential addresses*/
- writel( *mmc_ptr, MMC_BOOT_MCI_FIFO +
- ( mmc_count % MMC_BOOT_MCI_FIFO_SIZE ) );
- mmc_ptr++;
- /* increase mmc_count by word size */
- mmc_count += sizeof( unsigned int );
- }
-
- }
- else if( !( mmc_status & MMC_BOOT_MCI_STAT_TX_FIFO_FULL ) && (mmc_count != data_len))
- {
- /* FIFO contains 16 32-bit data buffer on 16 sequential addresses*/
- writel( *mmc_ptr, MMC_BOOT_MCI_FIFO +
- ( mmc_count % MMC_BOOT_MCI_FIFO_SIZE ) );
- mmc_ptr++;
- /* increase mmc_count by word size */
- mmc_count += sizeof( unsigned int );
- }
- else if((mmc_status & MMC_BOOT_MCI_STAT_DATA_END))
- {
- break; //success
- }
-
- } while(1);
+ /* write data to FIFO */
+ mmc_ret = mmc_boot_fifo_data_transfer(in, data_len, MMC_BOOT_DATA_WRITE);
if( mmc_ret != MMC_BOOT_E_SUCCESS )
{
@@ -1750,9 +1678,6 @@
unsigned int* out )
{
unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
- unsigned int mmc_status = 0;
- unsigned int* mmc_ptr = out;
- unsigned int mmc_count = 0;
unsigned int mmc_reg = 0;
unsigned int xfer_type;
unsigned int addr = 0;
@@ -1806,7 +1731,6 @@
/* If Data Mover is used for data transfer then prepare Command
List Entry and enable the Data mover to work with SDCC2 */
- /* Note: Data Mover not used */
/* Write data timeout period to MCI_DATA_TIMER register. */
/* Data timeout period should be in card bus clock periods */
@@ -1834,7 +1758,13 @@
/* Clear MODE bit to 0 to enable block oriented data transfer. For
MMC cards only, if stream data transfer mode is desired, set
MODE bit to 1. */
- /* Set DM_ENABLE bit to 1 in order to enable DMA, otherwise set 0 */
+
+ /* If DMA is to be used, Set DM_ENABLE bit to 1 */
+
+#if MMC_BOOT_ADM
+ mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
+#endif
+
/* Write size of block to be used during the data transfer to
BLOCKSIZE field */
mmc_reg |= (card->rd_block_len << MMC_BOOT_MCI_BLKSIZE_POS);
@@ -1850,53 +1780,8 @@
return mmc_ret;
}
- read_error = MMC_BOOT_MCI_STAT_DATA_CRC_FAIL | \
- MMC_BOOT_MCI_STAT_DATA_TIMEOUT | \
- MMC_BOOT_MCI_STAT_RX_OVRRUN;
-
- /* Read the transfer data from SDCC2 FIFO. If Data Mover is not used
- read the data from the MCI_FIFO register as long as RXDATA_AVLBL
- bit of MCI_STATUS register is set to 1 and bits DATA_CRC_FAIL,
- DATA_TIMEOUT, RX_OVERRUN of MCI_STATUS register are cleared to 0.
- Continue the reads until the whole transfer data is received */
-
- do
- {
- mmc_ret = MMC_BOOT_E_SUCCESS;
- mmc_status = readl( MMC_BOOT_MCI_STATUS );
-
- if( mmc_status & read_error )
- {
- mmc_ret = mmc_boot_status_error(mmc_status);
- break;
- }
-
- if( mmc_status & MMC_BOOT_MCI_STAT_RX_DATA_AVLBL )
- {
- unsigned read_count = 1;
- if ( mmc_status & MMC_BOOT_MCI_STAT_RX_FIFO_HFULL)
- {
- read_count = MMC_BOOT_MCI_HFIFO_COUNT;
- }
-
- for (int i=0; i<read_count; i++)
- {
- /* FIFO contains 16 32-bit data buffer on 16 sequential addresses*/
- *mmc_ptr = readl( MMC_BOOT_MCI_FIFO +
- ( mmc_count % MMC_BOOT_MCI_FIFO_SIZE ) );
- mmc_ptr++;
- /* increase mmc_count by word size */
- mmc_count += sizeof( unsigned int );
- }
- /* quit if we have read enough of data */
- if (mmc_count == data_len)
- break;
- }
- else if( mmc_status & MMC_BOOT_MCI_STAT_DATA_END )
- {
- break;
- }
- }while(1);
+ /* Read the transfer data from SDCC FIFO. */
+ mmc_ret = mmc_boot_fifo_data_transfer(out, data_len, MMC_BOOT_DATA_READ);
if( mmc_ret != MMC_BOOT_E_SUCCESS )
{
@@ -2702,12 +2587,7 @@
{
struct mmc_boot_command cmd;
unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
- unsigned int mmc_status = 0;
- unsigned int* mmc_ptr = out;
- unsigned int mmc_count = 0;
unsigned int mmc_reg = 0;
- unsigned int xfer_type;
- unsigned int read_error;
/* Set the FLOW_ENA bit of MCI_CLK register to 1 */
mmc_reg = readl( MMC_BOOT_MCI_CLK );
@@ -2723,6 +2603,11 @@
/* Set appropriate fields and write the MCI_DATA_CTL register. */
/* Set ENABLE bit to 1 to enable the data transfer. */
mmc_reg = MMC_BOOT_MCI_DATA_ENABLE | MMC_BOOT_MCI_DATA_DIR | (data_len << MMC_BOOT_MCI_BLKSIZE_POS);
+
+#if MMC_BOOT_ADM
+ mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
+#endif
+
writel( mmc_reg, MMC_BOOT_MCI_DATA_CTL );
memset( (struct mmc_boot_command *)&cmd, 0,
@@ -2740,47 +2625,8 @@
return mmc_ret;
}
- read_error = MMC_BOOT_MCI_STAT_DATA_CRC_FAIL | \
- MMC_BOOT_MCI_STAT_DATA_TIMEOUT | \
- MMC_BOOT_MCI_STAT_RX_OVRRUN;
-
- do
- {
- mmc_ret = MMC_BOOT_E_SUCCESS;
- mmc_status = readl( MMC_BOOT_MCI_STATUS );
-
- if( mmc_status & read_error )
- {
- mmc_ret = mmc_boot_status_error(mmc_status);
- break;
- }
-
- if( mmc_status & MMC_BOOT_MCI_STAT_RX_DATA_AVLBL )
- {
- unsigned read_count = 1;
- if ( mmc_status & MMC_BOOT_MCI_STAT_RX_FIFO_HFULL)
- {
- read_count = MMC_BOOT_MCI_HFIFO_COUNT;
- }
-
- for (int i=0; i<read_count; i++)
- {
- /* FIFO contains 16 32-bit data buffer on 16 sequential addresses*/
- *mmc_ptr = readl( MMC_BOOT_MCI_FIFO +
- ( mmc_count % MMC_BOOT_MCI_FIFO_SIZE ) );
- mmc_ptr++;
- /* increase mmc_count by word size */
- mmc_count += sizeof( unsigned int );
- }
- /* quit if we have read enough of data */
- if (mmc_count == data_len)
- break;
- }
- else if( mmc_status & MMC_BOOT_MCI_STAT_DATA_END )
- {
- break;
- }
- }while(1);
+ /* Read the transfer data from SDCC FIFO. */
+ mmc_ret = mmc_boot_fifo_data_transfer(out, data_len, MMC_BOOT_DATA_READ);
if( mmc_ret != MMC_BOOT_E_SUCCESS )
{
@@ -3017,4 +2863,171 @@
unsigned mmc_get_psn(void)
{
return mmc_card.cid.psn;
+}
+
+/*
+ * Read/write data from/to SDC FIFO.
+ */
+static unsigned int mmc_boot_fifo_data_transfer(unsigned int* data_ptr,
+ unsigned int data_len,
+ unsigned char direction)
+{
+ unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+
+#if MMC_BOOT_ADM
+ adm_result_t ret;
+ adm_dir_t adm_dir;
+
+ if(direction == MMC_BOOT_DATA_READ)
+ {
+ adm_dir = ADM_MMC_READ;
+ }
+ else
+ {
+ adm_dir = ADM_MMC_WRITE;
+ }
+
+ ret = adm_transfer_mmc_data(mmc_slot,
+ (unsigned char*) data_ptr,
+ data_len,
+ adm_dir);
+
+ if(ret != ADM_RESULT_SUCCESS)
+ {
+ dprintf(CRITICAL, "MMC ADM transfer error: %d\n", ret);
+ mmc_ret = MMC_BOOT_E_FAILURE;
+ }
+#else
+
+ if(direction == MMC_BOOT_DATA_READ)
+ {
+ mmc_ret = mmc_boot_fifo_read(data_ptr, data_len);
+ }
+ else
+ {
+ mmc_ret = mmc_boot_fifo_write(data_ptr, data_len);
+ }
+#endif
+ return mmc_ret;
+}
+
+/*
+ * Read data to SDC FIFO.
+ */
+static unsigned int mmc_boot_fifo_read(unsigned int* mmc_ptr,
+ unsigned int data_len)
+{
+ unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+ unsigned int mmc_status = 0;
+ unsigned int mmc_count = 0;
+ unsigned int read_error = MMC_BOOT_MCI_STAT_DATA_CRC_FAIL | \
+ MMC_BOOT_MCI_STAT_DATA_TIMEOUT | \
+ MMC_BOOT_MCI_STAT_RX_OVRRUN;
+
+
+ /* Read the data from the MCI_FIFO register as long as RXDATA_AVLBL
+ bit of MCI_STATUS register is set to 1 and bits DATA_CRC_FAIL,
+ DATA_TIMEOUT, RX_OVERRUN of MCI_STATUS register are cleared to 0.
+ Continue the reads until the whole transfer data is received */
+
+ do
+ {
+ mmc_ret = MMC_BOOT_E_SUCCESS;
+ mmc_status = readl( MMC_BOOT_MCI_STATUS );
+
+ if( mmc_status & read_error )
+ {
+ mmc_ret = mmc_boot_status_error(mmc_status);
+ break;
+ }
+
+ if( mmc_status & MMC_BOOT_MCI_STAT_RX_DATA_AVLBL )
+ {
+ unsigned read_count = 1;
+ if ( mmc_status & MMC_BOOT_MCI_STAT_RX_FIFO_HFULL)
+ {
+ read_count = MMC_BOOT_MCI_HFIFO_COUNT;
+ }
+
+ for (unsigned int i=0; i<read_count; i++)
+ {
+ /* FIFO contains 16 32-bit data buffer on 16 sequential addresses*/
+ *mmc_ptr = readl( MMC_BOOT_MCI_FIFO +
+ ( mmc_count % MMC_BOOT_MCI_FIFO_SIZE ) );
+ mmc_ptr++;
+ /* increase mmc_count by word size */
+ mmc_count += sizeof( unsigned int );
+ }
+ /* quit if we have read enough of data */
+ if (mmc_count == data_len)
+ break;
+ }
+ else if( mmc_status & MMC_BOOT_MCI_STAT_DATA_END )
+ {
+ break;
+ }
+ }while(1);
+
+ return mmc_ret;
+}
+
+/*
+ * Write data to SDC FIFO.
+ */
+static unsigned int mmc_boot_fifo_write(unsigned int* mmc_ptr,
+ unsigned int data_len)
+{
+ unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+ unsigned int mmc_status = 0;
+ unsigned int mmc_count = 0;
+ unsigned int write_error = MMC_BOOT_MCI_STAT_DATA_CRC_FAIL | \
+ MMC_BOOT_MCI_STAT_DATA_TIMEOUT | \
+ MMC_BOOT_MCI_STAT_TX_UNDRUN;
+
+
+ /* Write the transfer data to SDCC3 FIFO */
+ do
+ {
+ mmc_ret = MMC_BOOT_E_SUCCESS;
+ mmc_status = readl( MMC_BOOT_MCI_STATUS );
+
+ if( mmc_status & write_error )
+ {
+ mmc_ret = mmc_boot_status_error(mmc_status);
+ break;
+ }
+
+ /* Write the data in MCI_FIFO register as long as TXFIFO_FULL bit of
+ MCI_STATUS register is 0. Continue the writes until the whole
+ transfer data is written. */
+ if (((data_len-mmc_count) >= MMC_BOOT_MCI_FIFO_SIZE/2) &&
+ ( mmc_status & MMC_BOOT_MCI_STAT_TX_FIFO_HFULL ))
+ {
+ for (int i=0; i < MMC_BOOT_MCI_HFIFO_COUNT; i++ )
+ {
+ /* FIFO contains 16 32-bit data buffer on 16 sequential addresses*/
+ writel( *mmc_ptr, MMC_BOOT_MCI_FIFO +
+ ( mmc_count % MMC_BOOT_MCI_FIFO_SIZE ) );
+ mmc_ptr++;
+ /* increase mmc_count by word size */
+ mmc_count += sizeof( unsigned int );
+ }
+
+ }
+ else if( !( mmc_status & MMC_BOOT_MCI_STAT_TX_FIFO_FULL ) && (mmc_count != data_len))
+ {
+ /* FIFO contains 16 32-bit data buffer on 16 sequential addresses*/
+ writel( *mmc_ptr, MMC_BOOT_MCI_FIFO +
+ ( mmc_count % MMC_BOOT_MCI_FIFO_SIZE ) );
+ mmc_ptr++;
+ /* increase mmc_count by word size */
+ mmc_count += sizeof( unsigned int );
+ }
+ else if((mmc_status & MMC_BOOT_MCI_STAT_DATA_END))
+ {
+ break; //success
+ }
+
+ } while(1);
+ return mmc_ret;
}