Patchwork [U-Boot,v1] mmc: bfin: Ensure MMR writing is done before next command.

login
register
mail settings
Submitter Sonic Zhang
Date April 27, 2013, 11:04 a.m.
Message ID <1367060650-16269-1-git-send-email-sonic.adi@gmail.com>
Download mbox | patch
Permalink /patch/240104/
State Rejected
Delegated to: Sonic Zhang
Headers show

Comments

Sonic Zhang - April 27, 2013, 11:04 a.m.
From: Sonic Zhang <sonic.zhang@analog.com>

- Ensure MMR writing is done before next command.
- Invalidate the buffer before starting to read.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---
 drivers/mmc/bfin_sdh.c |   30 +++++++++++++++++++++++-------
 1 files changed, 23 insertions(+), 7 deletions(-)
Sonic Zhang - April 27, 2013, 11:21 a.m.
Hi Mike

On Sat, Apr 27, 2013 at 7:14 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> On Saturday 27 April 2013 07:04:10 Sonic Zhang wrote:
>> From: Sonic Zhang <sonic.zhang@analog.com>
>>
>> - Ensure MMR writing is done before next command.
>> - Invalidate the buffer before starting to read.
>
> this patch was written by Cliff, not yourself.  the description really doesn't
> match reality, and no one has yet to explain what this is doing.  i'm fairly
> certain Cliff, when presented with the bug (iirc, it was "mmc doesn't work at
> low SCLK") just threw in a crap ton of SSYNCs to slow the driver down and
> shuffled some code until it worked.  no real analysis as to what was actually
> necessary.
>
> hence, i never pushed this upstream.  i still don't think this belongs in
> mainline.

Good catch. I can't find the log of this patch in local tree, because
you moved the bfin_sdh.c someday.
Yes, this patch looks like a workaround. So, ignore it.

Regards,

Sonic

Patch

diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c
index 0f98b96..028cb58 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -136,6 +136,9 @@  static int sdh_setup_data(struct mmc *mmc, struct mmc_data *data)
 	/* Don't support write yet. */
 	if (data->flags & MMC_DATA_WRITE)
 		return UNUSABLE_ERR;
+	blackfin_dcache_flush_invalidate_range(data->dest,
+			data->dest + data_size);
+	SSYNC();
 #ifndef RSI_BLKSZ
 	data_ctl |= ((ffs(data_size) - 1) << 4);
 #else
@@ -143,21 +146,22 @@  static int sdh_setup_data(struct mmc *mmc, struct mmc_data *data)
 #endif
 	data_ctl |= DTX_DIR;
 	bfin_write_SDH_DATA_CTL(data_ctl);
+	SSYNC();
 	dma_cfg = WDSIZE_32 | PSIZE_32 | RESTART | WNR | DMAEN;
 
 	bfin_write_SDH_DATA_TIMER(-1);
-
-	blackfin_dcache_flush_invalidate_range(data->dest,
-			data->dest + data_size);
+	SSYNC();
 	/* configure DMA */
 	bfin_write_DMA_START_ADDR(data->dest);
 	bfin_write_DMA_X_COUNT(data_size / 4);
 	bfin_write_DMA_X_MODIFY(4);
 	bfin_write_DMA_CONFIG(dma_cfg);
+	SSYNC();
 	bfin_write_SDH_DATA_LGTH(data_size);
+	SSYNC();
 	/* kick off transfer */
 	bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E);
-
+	SSYNC();
 	return 0;
 }
 
@@ -167,6 +171,7 @@  static int bfin_sdh_request(struct mmc *mmc, struct mmc_cmd *cmd,
 {
 	u32 status;
 	int ret = 0;
+	u16 reg = 0;
 
 	if (data) {
 		ret = sdh_setup_data(mmc, data);
@@ -191,14 +196,18 @@  static int bfin_sdh_request(struct mmc *mmc, struct mmc_cmd *cmd,
 		} while (!(status & (DAT_BLK_END | DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN)));
 
 		if (status & DAT_TIME_OUT) {
-			bfin_write_SDH_STATUS_CLR(DAT_TIMEOUT_STAT);
+			reg |= DAT_TIMEOUT_STAT;
 			ret |= TIMEOUT;
 		} else if (status & (DAT_CRC_FAIL | RX_OVERRUN)) {
-			bfin_write_SDH_STATUS_CLR(DAT_CRC_FAIL_STAT | RX_OVERRUN_STAT);
+			reg |= DAT_CRC_FAIL_STAT | RX_OVERRUN_STAT;
 			ret |= COMM_ERR;
 		} else
-			bfin_write_SDH_STATUS_CLR(DAT_BLK_END_STAT | DAT_END_STAT);
+			reg |= DAT_BLK_END_STAT | DAT_END_STAT;
 
+		bfin_write_SDH_STATUS_CLR(reg);
+		bfin_write_DMA_CONFIG(0);
+		bfin_write_SDH_DATA_CTL(0);
+		SSYNC();
 		if (ret) {
 			printf("tranfering data failed\n");
 			return ret;
@@ -218,6 +227,7 @@  static void sdh_set_clk(unsigned long clk)
 		/* setting SD_CLK */
 		sys_clk = get_sclk();
 		bfin_write_SDH_CLK_CTL(clk_ctl & ~CLK_E);
+		SSYNC();
 		if (sys_clk % (2 * clk) == 0)
 			clk_div = sys_clk / (2 * clk) - 1;
 		else
@@ -230,6 +240,7 @@  static void sdh_set_clk(unsigned long clk)
 		bfin_write_SDH_CLK_CTL(clk_ctl);
 	} else
 		bfin_write_SDH_CLK_CTL(clk_ctl & ~CLK_E);
+	SSYNC();
 }
 
 static void bfin_sdh_set_ios(struct mmc *mmc)
@@ -247,6 +258,7 @@  static void bfin_sdh_set_ios(struct mmc *mmc)
 		clk_ctl |= WIDE_BUS_4;
 	}
 	bfin_write_SDH_CLK_CTL(clk_ctl);
+	SSYNC();
 	sdh_set_clk(mmc->clock);
 }
 
@@ -262,14 +274,18 @@  static int bfin_sdh_init(struct mmc *mmc)
 #if defined(__ADSPBF54x__)
 	bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
 #endif
+	SSYNC();
 	bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
+	SSYNC();
 	/* Disable card detect pin */
 	bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | 0x60);
+	SSYNC();
 #ifndef RSI_BLKSZ
 	bfin_write_SDH_PWR_CTL(PWR_ON | ROD_CTL);
 #else
 	bfin_write_SDH_CFG(bfin_read_SDH_CFG() | PWR_ON);
 #endif
+	SSYNC();
 	return 0;
 }