#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;
/* Reset controller */
writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
+ udelay(1000);
return 0;
}
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--)
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)
{
unsigned int timeout_msecs;
int error = 0;
unsigned int status = 0;
- unsigned int usedma = 0;
unsigned int bytecnt = 0;
if (mmchost->fatal_err)
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;
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 ?
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);