[U-Boot] [PATCH 5/5] fix for MMC write issue
Srikanth Reddy Vintha
srikanth.reddy at lntinfotech.com
Mon Aug 13 10:13:29 CEST 2012
From: Shrinivas Sahukar <shrinivas.sahukar at lntinfotech.com>
Signed-off-by: Shrinivas Sahukar <shrinivas.sahukar at lntinfotech.com>
---
drivers/mmc/qc_mmc.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/qc_mmc.c b/drivers/mmc/qc_mmc.c
index 930c410..9949cda 100644
--- a/drivers/mmc/qc_mmc.c
+++ b/drivers/mmc/qc_mmc.c
@@ -180,6 +180,65 @@ static unsigned int mmc_boot_fifo_read(unsigned int *mmc_ptr,
return mmc_ret;
}
+/*
+ * Write data to SDC FIFO.
+ */
+static unsigned int mmc_boot_fifo_write(unsigned int *mmc_ptr,
+ unsigned int data_len, struct mmc *mmc)
+{
+ 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;
+ unsigned int i;
+ struct mmc_priv *priv = (struct mmc_priv *)mmc->priv;
+ unsigned long reg_status, reg_fifo;
+
+ reg_status = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_STATUS);
+ reg_fifo = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_FIFO);
+
+ /* Write the transfer data to SDCC3 FIFO */
+ do {
+ mmc_ret = MMC_BOOT_E_SUCCESS;
+ mmc_status = readl(reg_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)) {
+ unsigned write_count = 1;
+ write_count = MMC_BOOT_MCI_HFIFO_COUNT;
+ for (i = 0; i < write_count; i++) {
+ /* FIFO contains 16 32-bit data buffer
+ on 16 sequential addresses */
+ writel(*mmc_ptr, reg_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, reg_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;
+ }
+ } while (1);
+ return mmc_ret;
+}
+
static unsigned int mmc_boot_fifo_data_transfer(unsigned int *data_ptr,
unsigned int data_len,
unsigned char direction,
@@ -189,6 +248,8 @@ static unsigned int mmc_boot_fifo_data_transfer(unsigned int *data_ptr,
if (direction == MMC_BOOT_DATA_READ)
mmc_ret = mmc_boot_fifo_read(data_ptr, data_len, mmc);
+ else
+ mmc_ret = mmc_boot_fifo_write(data_ptr, data_len, mmc);
return mmc_ret;
}
@@ -350,7 +411,7 @@ static unsigned int mmc_boot_send_command(struct mmc_cmd *cmd,
break;
}
- } while (1);
+ } while (1);
return mmc_return;
}
@@ -413,6 +474,7 @@ int mmc_boot_send_command_map(struct mmc *mmc,
struct mmc_data *data)
{
unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+ unsigned char direction = 0;
/* todo: do we need to fill in command type ?? */
@@ -434,6 +496,10 @@ int mmc_boot_send_command_map(struct mmc *mmc,
mmc->read_bl_len = MMC_BOOT_RD_BLOCK_LEN;
data->blocksize = MMC_BOOT_RD_BLOCK_LEN;
}
+ direction = MMC_BOOT_DATA_READ;
+ } else if ((cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK) ||
+ (cmd->cmdidx == MMC_CMD_WRITE_SINGLE_BLOCK)) {
+ direction = MMC_BOOT_DATA_WRITE;
} else if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) {
/* explicitly disable the prg enabled flag */
cmd->flags &= ~MMC_BOOT_PROGRAM_ENABLED;
@@ -441,7 +507,6 @@ int mmc_boot_send_command_map(struct mmc *mmc,
cmd->flags |= MMC_BOOT_XFER_MODE_BLOCK;
}
-
/* For Data cmd's */
if (data != NULL)
mmc_boot_init_data(mmc, cmd, data);
@@ -460,7 +525,7 @@ int mmc_boot_send_command_map(struct mmc *mmc,
return mmc_ret;
mmc_boot_fifo_data_transfer((unsigned int *) data->dest,
data->blocks * data->blocksize,
- MMC_BOOT_DATA_READ,
+ direction,
mmc);
}
--
1.7.1
More information about the U-Boot
mailing list