[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