All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes
@ 2011-11-10 21:56 Anton Staaf
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 1/4] Tegra2: mmc: define register field values in tegra2_mmc.h Anton Staaf
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Anton Staaf @ 2011-11-10 21:56 UTC (permalink / raw)
  To: u-boot

I have removed the bounce buffer implmenetation from this patch set as it
feels like a separate task now.  This patch set is just magic number cleanup
, a bit of refactoring, and bug fixes in the existing Tegra2 MMC driver.

Changes in v2:
- Added initial patch to define Tegra MMC register field values
- Remove patches for bounce buffer implementation

Changes in v3:
- Added back comments about register values
- Shortened #defined macro names

Anton Staaf (4):
  Tegra2: mmc: define register field values in tegra2_mmc.h
  Tegra2: mmc: Support DMA restarts at buffer boundaries
  Tegra2: mmc: Add data transfer completion timeout
  Tegra2: mmc: Factor out mmc_wait_inhibit functionality

 drivers/mmc/tegra2_mmc.c |  130 ++++++++++++++++++++++++++++++----------------
 drivers/mmc/tegra2_mmc.h |   49 +++++++++++++++++
 2 files changed, 134 insertions(+), 45 deletions(-)

Cc: Andy Fleming <afleming@gmail.com>
Cc: Tom Warren <twarren@nvidia.com>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>

-- 
1.7.3.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 1/4] Tegra2: mmc: define register field values in tegra2_mmc.h
  2011-11-10 21:56 [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Anton Staaf
@ 2011-11-10 21:56 ` Anton Staaf
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 2/4] Tegra2: mmc: Support DMA restarts at buffer boundaries Anton Staaf
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Anton Staaf @ 2011-11-10 21:56 UTC (permalink / raw)
  To: u-boot

This moves the magic numbers sprinkled about the MMC driver
to a single location in the header file and gives them
meaningful names.

Signed-off-by: Anton Staaf <robotboy@chromium.org>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Tom Warren <twarren@nvidia.com>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>
---

Changes in v3:
- Added back the comments about register field values
- Shortened a number of the #defined macro names

 drivers/mmc/tegra2_mmc.c |   63 ++++++++++++++++++++++++++-------------------
 drivers/mmc/tegra2_mmc.h |   49 +++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 27 deletions(-)

diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c
index 78b1190..2bea07d 100644
--- a/drivers/mmc/tegra2_mmc.c
+++ b/drivers/mmc/tegra2_mmc.c
@@ -81,7 +81,8 @@ static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data)
 	 * 11 = Selects 64-bit Address ADMA2
 	 */
 	ctrl = readb(&host->reg->hostctl);
-	ctrl &= ~(3 << 3);			/* SDMA */
+	ctrl &= ~TEGRA_MMC_HOSTCTL_DMASEL_MASK;
+	ctrl |= TEGRA_MMC_HOSTCTL_DMASEL_SDMA;
 	writeb(ctrl, &host->reg->hostctl);
 
 	/* We do not handle DMA boundaries, so set it to max (512 KiB) */
@@ -103,11 +104,14 @@ static void mmc_set_transfer_mode(struct mmc_host *host, struct mmc_data *data)
 	 * ENBLKCNT[1]	: Block Count Enable
 	 * ENDMA[0]	: DMA Enable
 	 */
-	mode = (1 << 1) | (1 << 0);
+	mode = (TEGRA_MMC_TRNMOD_DMA_ENABLE |
+		TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE);
+
 	if (data->blocks > 1)
-		mode |= (1 << 5);
+		mode |= TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT;
+
 	if (data->flags & MMC_DATA_READ)
-		mode |= (1 << 4);
+		mode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ;
 
 	writew(mode, &host->reg->trnmod);
 }
@@ -130,16 +134,16 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	 * CMDINHDAT[1]	: Command Inhibit (DAT)
 	 * CMDINHCMD[0]	: Command Inhibit (CMD)
 	 */
-	mask = (1 << 0);
+	mask = TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD;
 	if ((data != NULL) || (cmd->resp_type & MMC_RSP_BUSY))
-		mask |= (1 << 1);
+		mask |= TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT;
 
 	/*
 	 * We shouldn't wait for data inhibit for stop commands, even
 	 * though they might use busy signaling
 	 */
 	if (data)
-		mask &= ~(1 << 1);
+		mask &= ~TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT;
 
 	while (readl(&host->reg->prnsts) & mask) {
 		if (timeout == 0) {
@@ -175,20 +179,20 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	 *	11 = Length 48 Check busy after response
 	 */
 	if (!(cmd->resp_type & MMC_RSP_PRESENT))
-		flags = 0;
+		flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE;
 	else if (cmd->resp_type & MMC_RSP_136)
-		flags = (1 << 0);
+		flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136;
 	else if (cmd->resp_type & MMC_RSP_BUSY)
-		flags = (3 << 0);
+		flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY;
 	else
-		flags = (2 << 0);
+		flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48;
 
 	if (cmd->resp_type & MMC_RSP_CRC)
-		flags |= (1 << 3);
+		flags |= TEGRA_MMC_TRNMOD_CMD_CRC_CHECK;
 	if (cmd->resp_type & MMC_RSP_OPCODE)
-		flags |= (1 << 4);
+		flags |= TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK;
 	if (data)
-		flags |= (1 << 5);
+		flags |= TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER;
 
 	debug("cmd: %d\n", cmd->cmdidx);
 
@@ -197,7 +201,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	for (i = 0; i < retry; i++) {
 		mask = readl(&host->reg->norintsts);
 		/* Command Complete */
-		if (mask & (1 << 0)) {
+		if (mask & TEGRA_MMC_NORINTSTS_CMD_COMPLETE) {
 			if (!data)
 				writel(mask, &host->reg->norintsts);
 			break;
@@ -209,11 +213,11 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 		return TIMEOUT;
 	}
 
-	if (mask & (1 << 16)) {
+	if (mask & TEGRA_MMC_NORINTSTS_CMD_TIMEOUT) {
 		/* Timeout Error */
 		debug("timeout: %08x cmd %d\n", mask, cmd->cmdidx);
 		return TIMEOUT;
-	} else if (mask & (1 << 15)) {
+	} else if (mask & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT) {
 		/* Error Interrupt */
 		debug("error: %08x cmd %d\n", mask, cmd->cmdidx);
 		return -1;
@@ -259,17 +263,17 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 		while (1) {
 			mask = readl(&host->reg->norintsts);
 
-			if (mask & (1 << 15)) {
+			if (mask & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT) {
 				/* Error Interrupt */
 				writel(mask, &host->reg->norintsts);
 				printf("%s: error during transfer: 0x%08x\n",
 						__func__, mask);
 				return -1;
-			} else if (mask & (1 << 3)) {
+			} else if (mask & TEGRA_MMC_NORINTSTS_DMA_INTERRUPT) {
 				/* DMA Interrupt */
 				debug("DMA end\n");
 				break;
-			} else if (mask & (1 << 1)) {
+			} else if (mask & TEGRA_MMC_NORINTSTS_XFER_COMPLETE) {
 				/* Transfer Complete */
 				debug("r/w is done\n");
 				break;
@@ -310,12 +314,14 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
 	 * ENINTCLK[0]		: Internal Clock Enable
 	 */
 	div >>= 1;
-	clk = (div << 8) | (1 << 0);
+	clk = ((div << TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_SHIFT) |
+	       TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE);
 	writew(clk, &host->reg->clkcon);
 
 	/* Wait max 10 ms */
 	timeout = 10;
-	while (!(readw(&host->reg->clkcon) & (1 << 1))) {
+	while (!(readw(&host->reg->clkcon) &
+		 TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE)) {
 		if (timeout == 0) {
 			printf("%s: timeout error\n", __func__);
 			return;
@@ -324,7 +330,7 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
 		udelay(1000);
 	}
 
-	clk |= (1 << 2);
+	clk |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
 	writew(clk, &host->reg->clkcon);
 
 	debug("mmc_change_clock: clkcon = %08X\n", clk);
@@ -375,7 +381,7 @@ static void mmc_reset(struct mmc_host *host)
 	 * 1 = reset
 	 * 0 = work
 	 */
-	writeb((1 << 0), &host->reg->swrst);
+	writeb(TEGRA_MMC_SWRST_SW_RESET_FOR_ALL, &host->reg->swrst);
 
 	host->clock = 0;
 
@@ -383,7 +389,7 @@ static void mmc_reset(struct mmc_host *host)
 	timeout = 100;
 
 	/* hw clears the bit when it's done */
-	while (readb(&host->reg->swrst) & (1 << 0)) {
+	while (readb(&host->reg->swrst) & TEGRA_MMC_SWRST_SW_RESET_FOR_ALL) {
 		if (timeout == 0) {
 			printf("%s: timeout error\n", __func__);
 			return;
@@ -418,7 +424,10 @@ static int mmc_core_init(struct mmc *mmc)
 	*/
 	mask = readl(&host->reg->norintstsen);
 	mask &= ~(0xffff);
-	mask |= (1 << 5) | (1 << 4) | (1 << 1) | (1 << 0);
+	mask |= (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE |
+		 TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE |
+		 TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY |
+		 TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY);
 	writel(mask, &host->reg->norintstsen);
 
 	/*
@@ -427,7 +436,7 @@ static int mmc_core_init(struct mmc *mmc)
 	 */
 	mask = readl(&host->reg->norintsigen);
 	mask &= ~(0xffff);
-	mask |= (1 << 1);
+	mask |= TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE;
 	writel(mask, &host->reg->norintsigen);
 
 	return 0;
diff --git a/drivers/mmc/tegra2_mmc.h b/drivers/mmc/tegra2_mmc.h
index 28698e0..671583c 100644
--- a/drivers/mmc/tegra2_mmc.h
+++ b/drivers/mmc/tegra2_mmc.h
@@ -68,6 +68,55 @@ struct tegra2_mmc {
 	unsigned char	res6[0x100];	/* RESERVED, offset 100h-1FFh */
 };
 
+#define TEGRA_MMC_HOSTCTL_DMASEL_MASK				(3 << 3)
+#define TEGRA_MMC_HOSTCTL_DMASEL_SDMA				(0 << 3)
+#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_32BIT			(2 << 3)
+#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_64BIT			(3 << 3)
+
+#define TEGRA_MMC_TRNMOD_DMA_ENABLE				(1 << 0)
+#define TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE			(1 << 1)
+#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_WRITE		(0 << 4)
+#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ			(1 << 4)
+#define TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT			(1 << 5)
+
+#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_MASK			(3 << 0)
+#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE		(0 << 0)
+#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136		(1 << 0)
+#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48		(2 << 0)
+#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY	(3 << 0)
+
+#define TEGRA_MMC_TRNMOD_CMD_CRC_CHECK				(1 << 3)
+#define TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK			(1 << 4)
+#define TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER	(1 << 5)
+
+#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD			(1 << 0)
+#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT			(1 << 1)
+
+#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE			(1 << 0)
+#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE			(1 << 1)
+#define TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE			(1 << 2)
+
+#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_SHIFT			8
+#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_MASK			(0xff << 8)
+
+#define TEGRA_MMC_SWRST_SW_RESET_FOR_ALL			(1 << 0)
+#define TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE			(1 << 1)
+#define TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE			(1 << 2)
+
+#define TEGRA_MMC_NORINTSTS_CMD_COMPLETE			(1 << 0)
+#define TEGRA_MMC_NORINTSTS_XFER_COMPLETE			(1 << 1)
+#define TEGRA_MMC_NORINTSTS_DMA_INTERRUPT			(1 << 3)
+#define TEGRA_MMC_NORINTSTS_ERR_INTERRUPT			(1 << 15)
+#define TEGRA_MMC_NORINTSTS_CMD_TIMEOUT				(1 << 16)
+
+#define TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE			(1 << 0)
+#define TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE			(1 << 1)
+#define TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT			(1 << 3)
+#define TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY		(1 << 4)
+#define TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY			(1 << 5)
+
+#define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE			(1 << 1)
+
 struct mmc_host {
 	struct tegra2_mmc *reg;
 	unsigned int version;	/* SDHCI spec. version */
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 2/4] Tegra2: mmc: Support DMA restarts at buffer boundaries
  2011-11-10 21:56 [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Anton Staaf
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 1/4] Tegra2: mmc: define register field values in tegra2_mmc.h Anton Staaf
@ 2011-11-10 21:56 ` Anton Staaf
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 3/4] Tegra2: mmc: Add data transfer completion timeout Anton Staaf
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Anton Staaf @ 2011-11-10 21:56 UTC (permalink / raw)
  To: u-boot

Currently if a DMA buffer straddles a buffer alignment boundary
(512KiB) then the DMA engine will pause and generate a DMA
interrupt.  Since the DMA interrupt is not enabled it will hang
the MMC driver.

This patch adds support for restarting the DMA transfer.  The
SYSTEM_ADDRESS register contains the next address that would have
been read/written when a boundary is hit.  So we can read that
and write it back.  The write triggers the resumption of the
transfer.

Signed-off-by: Anton Staaf <robotboy@chromium.org>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Tom Warren <twarren@nvidia.com>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>
---
 drivers/mmc/tegra2_mmc.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c
index 2bea07d..159cef1 100644
--- a/drivers/mmc/tegra2_mmc.c
+++ b/drivers/mmc/tegra2_mmc.c
@@ -270,9 +270,16 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 						__func__, mask);
 				return -1;
 			} else if (mask & TEGRA_MMC_NORINTSTS_DMA_INTERRUPT) {
-				/* DMA Interrupt */
+				/*
+				 * DMA Interrupt, restart the transfer where
+				 * it was interrupted.
+				 */
+				unsigned int address = readl(&host->reg->sysad);
+
 				debug("DMA end\n");
-				break;
+				writel(TEGRA_MMC_NORINTSTS_DMA_INTERRUPT,
+				       &host->reg->norintsts);
+				writel(address, &host->reg->sysad);
 			} else if (mask & TEGRA_MMC_NORINTSTS_XFER_COMPLETE) {
 				/* Transfer Complete */
 				debug("r/w is done\n");
@@ -419,6 +426,7 @@ static int mmc_core_init(struct mmc *mmc)
 	 * NORMAL Interrupt Status Enable Register init
 	 * [5] ENSTABUFRDRDY : Buffer Read Ready Status Enable
 	 * [4] ENSTABUFWTRDY : Buffer write Ready Status Enable
+	 * [3] ENSTADMAINT   : DMA boundary interrupt
 	 * [1] ENSTASTANSCMPLT : Transfre Complete Status Enable
 	 * [0] ENSTACMDCMPLT : Command Complete Status Enable
 	*/
@@ -426,6 +434,7 @@ static int mmc_core_init(struct mmc *mmc)
 	mask &= ~(0xffff);
 	mask |= (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE |
 		 TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE |
+		 TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT |
 		 TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY |
 		 TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY);
 	writel(mask, &host->reg->norintstsen);
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 3/4] Tegra2: mmc: Add data transfer completion timeout
  2011-11-10 21:56 [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Anton Staaf
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 1/4] Tegra2: mmc: define register field values in tegra2_mmc.h Anton Staaf
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 2/4] Tegra2: mmc: Support DMA restarts at buffer boundaries Anton Staaf
@ 2011-11-10 21:56 ` Anton Staaf
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 4/4] Tegra2: mmc: Factor out mmc_wait_inhibit functionality Anton Staaf
  2011-11-14 22:26 ` [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Andy Fleming
  4 siblings, 0 replies; 6+ messages in thread
From: Anton Staaf @ 2011-11-10 21:56 UTC (permalink / raw)
  To: u-boot

Currently when no expected completion condition occures in the
mmc_send_cmd while loop that is waiting for a data transfer to
complete the MMC driver just hangs.

This patch adds an arbitrary 2 second timeout.  If nothing we
recognize occures within 2 seconds some diagnostic information
is printed and we fail out.

Signed-off-by: Anton Staaf <robotboy@chromium.org>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Tom Warren <twarren@nvidia.com>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>
---
 drivers/mmc/tegra2_mmc.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c
index 159cef1..bbd0ccd 100644
--- a/drivers/mmc/tegra2_mmc.c
+++ b/drivers/mmc/tegra2_mmc.c
@@ -260,6 +260,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	}
 
 	if (data) {
+		unsigned long	start = get_timer(0);
+
 		while (1) {
 			mask = readl(&host->reg->norintsts);
 
@@ -284,6 +286,18 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 				/* Transfer Complete */
 				debug("r/w is done\n");
 				break;
+			} else if (get_timer(start) > 2000UL) {
+				writel(mask, &host->reg->norintsts);
+				printf("%s: MMC Timeout\n"
+				       "    Interrupt status        0x%08x\n"
+				       "    Interrupt status enable 0x%08x\n"
+				       "    Interrupt signal enable 0x%08x\n"
+				       "    Present status          0x%08x\n",
+				       __func__, mask,
+				       readl(&host->reg->norintstsen),
+				       readl(&host->reg->norintsigen),
+				       readl(&host->reg->prnsts));
+				return -1;
 			}
 		}
 		writel(mask, &host->reg->norintsts);
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 4/4] Tegra2: mmc: Factor out mmc_wait_inhibit functionality
  2011-11-10 21:56 [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Anton Staaf
                   ` (2 preceding siblings ...)
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 3/4] Tegra2: mmc: Add data transfer completion timeout Anton Staaf
@ 2011-11-10 21:56 ` Anton Staaf
  2011-11-14 22:26 ` [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Andy Fleming
  4 siblings, 0 replies; 6+ messages in thread
From: Anton Staaf @ 2011-11-10 21:56 UTC (permalink / raw)
  To: u-boot

This is a well encapsulated section of mmc_send_cmd, by moving
it to it's own function it increases the readability of mmc_send_cmd.

Signed-off-by: Anton Staaf <robotboy@chromium.org>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Tom Warren <twarren@nvidia.com>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>
---
 drivers/mmc/tegra2_mmc.c |   46 +++++++++++++++++++++++++++-------------------
 1 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c
index bbd0ccd..ccf48bb 100644
--- a/drivers/mmc/tegra2_mmc.c
+++ b/drivers/mmc/tegra2_mmc.c
@@ -116,34 +116,24 @@ static void mmc_set_transfer_mode(struct mmc_host *host, struct mmc_data *data)
 	writew(mode, &host->reg->trnmod);
 }
 
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
-			struct mmc_data *data)
+static int mmc_wait_inhibit(struct mmc_host *host,
+			    struct mmc_cmd *cmd,
+			    struct mmc_data *data,
+			    unsigned int timeout)
 {
-	struct mmc_host *host = (struct mmc_host *)mmc->priv;
-	int flags, i;
-	unsigned int timeout;
-	unsigned int mask;
-	unsigned int retry = 0x100000;
-	debug(" mmc_send_cmd called\n");
-
-	/* Wait max 10 ms */
-	timeout = 10;
-
 	/*
 	 * PRNSTS
-	 * CMDINHDAT[1]	: Command Inhibit (DAT)
-	 * CMDINHCMD[0]	: Command Inhibit (CMD)
+	 * CMDINHDAT[1] : Command Inhibit (DAT)
+	 * CMDINHCMD[0] : Command Inhibit (CMD)
 	 */
-	mask = TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD;
-	if ((data != NULL) || (cmd->resp_type & MMC_RSP_BUSY))
-		mask |= TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT;
+	unsigned int mask = TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD;
 
 	/*
 	 * We shouldn't wait for data inhibit for stop commands, even
 	 * though they might use busy signaling
 	 */
-	if (data)
-		mask &= ~TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT;
+	if ((data == NULL) && (cmd->resp_type & MMC_RSP_BUSY))
+		mask |= TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT;
 
 	while (readl(&host->reg->prnsts) & mask) {
 		if (timeout == 0) {
@@ -154,6 +144,24 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 		udelay(1000);
 	}
 
+	return 0;
+}
+
+static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+			struct mmc_data *data)
+{
+	struct mmc_host *host = (struct mmc_host *)mmc->priv;
+	int flags, i;
+	int result;
+	unsigned int mask;
+	unsigned int retry = 0x100000;
+	debug(" mmc_send_cmd called\n");
+
+	result = mmc_wait_inhibit(host, cmd, data, 10 /* ms */);
+
+	if (result < 0)
+		return result;
+
 	if (data)
 		mmc_prepare_data(host, data);
 
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes
  2011-11-10 21:56 [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Anton Staaf
                   ` (3 preceding siblings ...)
  2011-11-10 21:56 ` [U-Boot] [PATCH v3 4/4] Tegra2: mmc: Factor out mmc_wait_inhibit functionality Anton Staaf
@ 2011-11-14 22:26 ` Andy Fleming
  4 siblings, 0 replies; 6+ messages in thread
From: Andy Fleming @ 2011-11-14 22:26 UTC (permalink / raw)
  To: u-boot

On Thu, Nov 10, 2011 at 3:56 PM, Anton Staaf <robotboy@chromium.org> wrote:
> I have removed the bounce buffer implmenetation from this patch set as it
> feels like a separate task now. ?This patch set is just magic number cleanup
> , a bit of refactoring, and bug fixes in the existing Tegra2 MMC driver.
>
> Changes in v2:
> - Added initial patch to define Tegra MMC register field values
> - Remove patches for bounce buffer implementation
>
> Changes in v3:
> - Added back comments about register values
> - Shortened #defined macro names
>
> Anton Staaf (4):
> ?Tegra2: mmc: define register field values in tegra2_mmc.h
> ?Tegra2: mmc: Support DMA restarts at buffer boundaries
> ?Tegra2: mmc: Add data transfer completion timeout
> ?Tegra2: mmc: Factor out mmc_wait_inhibit functionality

All applied, thanks!

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-11-14 22:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-10 21:56 [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Anton Staaf
2011-11-10 21:56 ` [U-Boot] [PATCH v3 1/4] Tegra2: mmc: define register field values in tegra2_mmc.h Anton Staaf
2011-11-10 21:56 ` [U-Boot] [PATCH v3 2/4] Tegra2: mmc: Support DMA restarts at buffer boundaries Anton Staaf
2011-11-10 21:56 ` [U-Boot] [PATCH v3 3/4] Tegra2: mmc: Add data transfer completion timeout Anton Staaf
2011-11-10 21:56 ` [U-Boot] [PATCH v3 4/4] Tegra2: mmc: Factor out mmc_wait_inhibit functionality Anton Staaf
2011-11-14 22:26 ` [U-Boot] [PATCH v3 0/4] Tegra2: mmc DMA related fixes Andy Fleming

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.