[U-Boot] [PATCH v1] mmc: bfin: Ensure MMR writing is done before next command.
Sonic Zhang
sonic.adi at gmail.com
Sat Apr 27 13:04:10 CEST 2013
From: Sonic Zhang <sonic.zhang at analog.com>
- Ensure MMR writing is done before next command.
- Invalidate the buffer before starting to read.
Signed-off-by: Sonic Zhang <sonic.zhang at analog.com>
---
drivers/mmc/bfin_sdh.c | 30 +++++++++++++++++++++++-------
1 files changed, 23 insertions(+), 7 deletions(-)
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;
}
--
1.7.0.4
More information about the U-Boot
mailing list