|
@@ -16,28 +16,6 @@
|
|
|
#include <asm/arch/cpu.h>
|
|
|
#include <asm/arch/mmc.h>
|
|
|
|
|
|
-struct sunxi_mmc_des {
|
|
|
- u32 reserved1_1:1;
|
|
|
- u32 dic:1; /* disable interrupt on completion */
|
|
|
- u32 last_des:1; /* 1-this data buffer is the last buffer */
|
|
|
- u32 first_des:1; /* 1-data buffer is the first buffer,
|
|
|
- 0-data buffer contained in the next
|
|
|
- descriptor is 1st buffer */
|
|
|
- u32 des_chain:1; /* 1-the 2nd address in the descriptor is the
|
|
|
- next descriptor address */
|
|
|
- u32 end_of_ring:1; /* 1-last descriptor flag when using dual
|
|
|
- data buffer in descriptor */
|
|
|
- u32 reserved1_2:24;
|
|
|
- u32 card_err_sum:1; /* transfer error flag */
|
|
|
- u32 own:1; /* des owner:1-idma owns it, 0-host owns it */
|
|
|
-#define SDXC_DES_NUM_SHIFT 16
|
|
|
-#define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT)
|
|
|
- u32 data_buf1_sz:16;
|
|
|
- u32 data_buf2_sz:16;
|
|
|
- u32 buf_addr_ptr1;
|
|
|
- u32 buf_addr_ptr2;
|
|
|
-};
|
|
|
-
|
|
|
struct sunxi_mmc_host {
|
|
|
unsigned mmc_no;
|
|
|
uint32_t *mclkreg;
|
|
@@ -189,6 +167,7 @@ static int mmc_core_init(struct mmc *mmc)
|
|
|
|
|
|
/* Reset controller */
|
|
|
writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
|
|
|
+ udelay(1000);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -204,6 +183,9 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
|
|
|
unsigned timeout_msecs = 2000;
|
|
|
unsigned *buff = (unsigned int *)(reading ? data->dest : data->src);
|
|
|
|
|
|
+ /* Always read / write data through the CPU */
|
|
|
+ setbits_le32(&mmchost->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB);
|
|
|
+
|
|
|
for (i = 0; i < (byte_cnt >> 2); i++) {
|
|
|
while (readl(&mmchost->reg->status) & status_bit) {
|
|
|
if (!timeout_msecs--)
|
|
@@ -220,85 +202,6 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int mmc_trans_data_by_dma(struct mmc *mmc, struct mmc_data *data)
|
|
|
-{
|
|
|
- struct sunxi_mmc_host *mmchost = mmc->priv;
|
|
|
- unsigned byte_cnt = data->blocksize * data->blocks;
|
|
|
- unsigned char *buff;
|
|
|
- unsigned des_idx = 0;
|
|
|
- unsigned buff_frag_num =
|
|
|
- (byte_cnt + SDXC_DES_BUFFER_MAX_LEN - 1) >> SDXC_DES_NUM_SHIFT;
|
|
|
- unsigned remain;
|
|
|
- unsigned i, rval;
|
|
|
- ALLOC_CACHE_ALIGN_BUFFER(struct sunxi_mmc_des, pdes, buff_frag_num);
|
|
|
-
|
|
|
- buff = data->flags & MMC_DATA_READ ?
|
|
|
- (unsigned char *)data->dest : (unsigned char *)data->src;
|
|
|
- remain = byte_cnt & (SDXC_DES_BUFFER_MAX_LEN - 1);
|
|
|
-
|
|
|
- flush_cache((unsigned long)buff, (unsigned long)byte_cnt);
|
|
|
- for (i = 0; i < buff_frag_num; i++, des_idx++) {
|
|
|
- memset((void *)&pdes[des_idx], 0, sizeof(struct sunxi_mmc_des));
|
|
|
- pdes[des_idx].des_chain = 1;
|
|
|
- pdes[des_idx].own = 1;
|
|
|
- pdes[des_idx].dic = 1;
|
|
|
- if (buff_frag_num > 1 && i != buff_frag_num - 1)
|
|
|
- pdes[des_idx].data_buf1_sz = 0; /* 0 == max_len */
|
|
|
- else
|
|
|
- pdes[des_idx].data_buf1_sz = remain;
|
|
|
-
|
|
|
- pdes[des_idx].buf_addr_ptr1 =
|
|
|
- (u32) buff + i * SDXC_DES_BUFFER_MAX_LEN;
|
|
|
- if (i == 0)
|
|
|
- pdes[des_idx].first_des = 1;
|
|
|
-
|
|
|
- if (i == buff_frag_num - 1) {
|
|
|
- pdes[des_idx].dic = 0;
|
|
|
- pdes[des_idx].last_des = 1;
|
|
|
- pdes[des_idx].end_of_ring = 1;
|
|
|
- pdes[des_idx].buf_addr_ptr2 = 0;
|
|
|
- } else {
|
|
|
- pdes[des_idx].buf_addr_ptr2 = (u32)&pdes[des_idx + 1];
|
|
|
- }
|
|
|
- }
|
|
|
- flush_cache((unsigned long)pdes,
|
|
|
- sizeof(struct sunxi_mmc_des) * (des_idx + 1));
|
|
|
-
|
|
|
- rval = readl(&mmchost->reg->gctrl);
|
|
|
- /* Enable DMA */
|
|
|
- writel(rval | SUNXI_MMC_GCTRL_DMA_RESET | SUNXI_MMC_GCTRL_DMA_ENABLE,
|
|
|
- &mmchost->reg->gctrl);
|
|
|
- /* Reset iDMA */
|
|
|
- writel(SUNXI_MMC_IDMAC_RESET, &mmchost->reg->dmac);
|
|
|
- /* Enable iDMA */
|
|
|
- writel(SUNXI_MMC_IDMAC_FIXBURST | SUNXI_MMC_IDMAC_ENABLE,
|
|
|
- &mmchost->reg->dmac);
|
|
|
- rval = readl(&mmchost->reg->idie) &
|
|
|
- ~(SUNXI_MMC_IDIE_TXIRQ|SUNXI_MMC_IDIE_RXIRQ);
|
|
|
- if (data->flags & MMC_DATA_WRITE)
|
|
|
- rval |= SUNXI_MMC_IDIE_TXIRQ;
|
|
|
- else
|
|
|
- rval |= SUNXI_MMC_IDIE_RXIRQ;
|
|
|
- writel(rval, &mmchost->reg->idie);
|
|
|
- writel((u32) pdes, &mmchost->reg->dlba);
|
|
|
- writel((0x2 << 28) | (0x7 << 16) | (0x01 << 3),
|
|
|
- &mmchost->reg->ftrglevel);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static void mmc_enable_dma_accesses(struct mmc *mmc, int dma)
|
|
|
-{
|
|
|
- struct sunxi_mmc_host *mmchost = mmc->priv;
|
|
|
-
|
|
|
- unsigned int gctrl = readl(&mmchost->reg->gctrl);
|
|
|
- if (dma)
|
|
|
- gctrl &= ~SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
|
|
|
- else
|
|
|
- gctrl |= SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
|
|
|
- writel(gctrl, &mmchost->reg->gctrl);
|
|
|
-}
|
|
|
-
|
|
|
static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs,
|
|
|
unsigned int done_bit, const char *what)
|
|
|
{
|
|
@@ -327,7 +230,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
|
|
unsigned int timeout_msecs;
|
|
|
int error = 0;
|
|
|
unsigned int status = 0;
|
|
|
- unsigned int usedma = 0;
|
|
|
unsigned int bytecnt = 0;
|
|
|
|
|
|
if (mmchost->fatal_err)
|
|
@@ -378,20 +280,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
|
|
|
|
|
bytecnt = data->blocksize * data->blocks;
|
|
|
debug("trans data %d bytes\n", bytecnt);
|
|
|
-#if defined(CONFIG_MMC_SUNXI_USE_DMA) && !defined(CONFIG_SPL_BUILD)
|
|
|
- if (bytecnt > 64) {
|
|
|
-#else
|
|
|
- if (0) {
|
|
|
-#endif
|
|
|
- usedma = 1;
|
|
|
- mmc_enable_dma_accesses(mmc, 1);
|
|
|
- ret = mmc_trans_data_by_dma(mmc, data);
|
|
|
- writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
|
|
|
- } else {
|
|
|
- mmc_enable_dma_accesses(mmc, 0);
|
|
|
- writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
|
|
|
- ret = mmc_trans_data_by_cpu(mmc, data);
|
|
|
- }
|
|
|
+ writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
|
|
|
+ ret = mmc_trans_data_by_cpu(mmc, data);
|
|
|
if (ret) {
|
|
|
error = readl(&mmchost->reg->rint) & \
|
|
|
SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT;
|
|
@@ -405,7 +295,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
|
|
goto out;
|
|
|
|
|
|
if (data) {
|
|
|
- timeout_msecs = usedma ? 120 * bytecnt : 120;
|
|
|
+ timeout_msecs = 120;
|
|
|
debug("cacl timeout %x msec\n", timeout_msecs);
|
|
|
error = mmc_rint_wait(mmc, timeout_msecs,
|
|
|
data->blocks > 1 ?
|
|
@@ -442,23 +332,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
|
|
debug("mmc resp 0x%08x\n", cmd->response[0]);
|
|
|
}
|
|
|
out:
|
|
|
- if (data && usedma) {
|
|
|
- /* IDMASTAREG
|
|
|
- * IDST[0] : idma tx int
|
|
|
- * IDST[1] : idma rx int
|
|
|
- * IDST[2] : idma fatal bus error
|
|
|
- * IDST[4] : idma descriptor invalid
|
|
|
- * IDST[5] : idma error summary
|
|
|
- * IDST[8] : idma normal interrupt sumary
|
|
|
- * IDST[9] : idma abnormal interrupt sumary
|
|
|
- */
|
|
|
- status = readl(&mmchost->reg->idst);
|
|
|
- writel(status, &mmchost->reg->idst);
|
|
|
- writel(0, &mmchost->reg->idie);
|
|
|
- writel(0, &mmchost->reg->dmac);
|
|
|
- writel(readl(&mmchost->reg->gctrl) & ~SUNXI_MMC_GCTRL_DMA_ENABLE,
|
|
|
- &mmchost->reg->gctrl);
|
|
|
- }
|
|
|
if (error < 0) {
|
|
|
writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
|
|
|
mmc_update_clk(mmc);
|