Merge branch 'u-boot-ti/master' into 'u-boot-arm/master'
[platform/kernel/u-boot.git] / drivers / mmc / sunxi_mmc.c
index eb7b115..d4e574f 100644 (file)
 #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);