From 2c96a293bbd6b34698c6710ea8607049956247c4 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 11 Aug 2011 15:25:41 +0000 Subject: mmc: atmel-mci: change namespace Homogenize namespace to atmci. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 301 ++++++++++++++++++++++--------------------- 1 file changed, 151 insertions(+), 150 deletions(-) (limited to 'drivers/mmc/host/atmel-mci.c') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fa8cae1d7005..c2a0949f3257 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -39,7 +39,7 @@ #include "atmel-mci-regs.h" -#define ATMCI_DATA_ERROR_FLAGS (MCI_DCRCE | MCI_DTOE | MCI_OVRE | MCI_UNRE) +#define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE) #define ATMCI_DMA_THRESHOLD 16 enum { @@ -166,7 +166,7 @@ struct atmel_mci { struct clk *mck; struct platform_device *pdev; - struct atmel_mci_slot *slot[ATMEL_MCI_MAX_NR_SLOTS]; + struct atmel_mci_slot *slot[ATMCI_MAX_NR_SLOTS]; }; /** @@ -223,7 +223,7 @@ struct atmel_mci_slot { * Enable or disable features/registers based on * whether the processor supports them */ -static bool mci_has_rwproof(void) +static bool atmci_has_rwproof(void) { if (cpu_is_at91sam9261() || cpu_is_at91rm9200()) return false; @@ -352,7 +352,7 @@ static int atmci_regs_show(struct seq_file *s, void *v) struct atmel_mci *host = s->private; u32 *buf; - buf = kmalloc(MCI_REGS_SIZE, GFP_KERNEL); + buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -363,47 +363,47 @@ static int atmci_regs_show(struct seq_file *s, void *v) */ spin_lock_bh(&host->lock); clk_enable(host->mck); - memcpy_fromio(buf, host->regs, MCI_REGS_SIZE); + memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE); clk_disable(host->mck); spin_unlock_bh(&host->lock); seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", - buf[MCI_MR / 4], - buf[MCI_MR / 4] & MCI_MR_RDPROOF ? " RDPROOF" : "", - buf[MCI_MR / 4] & MCI_MR_WRPROOF ? " WRPROOF" : "", - buf[MCI_MR / 4] & 0xff); - seq_printf(s, "DTOR:\t0x%08x\n", buf[MCI_DTOR / 4]); - seq_printf(s, "SDCR:\t0x%08x\n", buf[MCI_SDCR / 4]); - seq_printf(s, "ARGR:\t0x%08x\n", buf[MCI_ARGR / 4]); + buf[ATMCI_MR / 4], + buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "", + buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "", + buf[ATMCI_MR / 4] & 0xff); + seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]); + seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]); + seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]); seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n", - buf[MCI_BLKR / 4], - buf[MCI_BLKR / 4] & 0xffff, - (buf[MCI_BLKR / 4] >> 16) & 0xffff); + buf[ATMCI_BLKR / 4], + buf[ATMCI_BLKR / 4] & 0xffff, + (buf[ATMCI_BLKR / 4] >> 16) & 0xffff); if (atmci_is_mci2()) - seq_printf(s, "CSTOR:\t0x%08x\n", buf[MCI_CSTOR / 4]); + seq_printf(s, "CSTOR:\t0x%08x\n", buf[ATMCI_CSTOR / 4]); /* Don't read RSPR and RDR; it will consume the data there */ - atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); - atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); + atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]); + atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]); if (atmci_is_mci2()) { u32 val; - val = buf[MCI_DMA / 4]; + val = buf[ATMCI_DMA / 4]; seq_printf(s, "DMA:\t0x%08x OFFSET=%u CHKSIZE=%u%s\n", val, val & 3, ((val >> 4) & 3) ? 1 << (((val >> 4) & 3) + 1) : 1, - val & MCI_DMAEN ? " DMAEN" : ""); + val & ATMCI_DMAEN ? " DMAEN" : ""); - val = buf[MCI_CFG / 4]; + val = buf[ATMCI_CFG / 4]; seq_printf(s, "CFG:\t0x%08x%s%s%s%s\n", val, - val & MCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "", - val & MCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "", - val & MCI_CFG_HSMODE ? " HSMODE" : "", - val & MCI_CFG_LSYNC ? " LSYNC" : ""); + val & ATMCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "", + val & ATMCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "", + val & ATMCI_CFG_HSMODE ? " HSMODE" : "", + val & ATMCI_CFG_LSYNC ? " LSYNC" : ""); } kfree(buf); @@ -466,7 +466,7 @@ err: dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); } -static inline unsigned int ns_to_clocks(struct atmel_mci *host, +static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, unsigned int ns) { return (ns * (host->bus_hz / 1000000) + 999) / 1000; @@ -482,7 +482,8 @@ static void atmci_set_timeout(struct atmel_mci *host, unsigned dtocyc; unsigned dtomul; - timeout = ns_to_clocks(host, data->timeout_ns) + data->timeout_clks; + timeout = atmci_ns_to_clocks(host, data->timeout_ns) + + data->timeout_clks; for (dtomul = 0; dtomul < 8; dtomul++) { unsigned shift = dtomul_to_shift[dtomul]; @@ -498,7 +499,7 @@ static void atmci_set_timeout(struct atmel_mci *host, dev_vdbg(&slot->mmc->class_dev, "setting timeout to %u cycles\n", dtocyc << dtomul_to_shift[dtomul]); - mci_writel(host, DTOR, (MCI_DTOMUL(dtomul) | MCI_DTOCYC(dtocyc))); + atmci_writel(host, DTOR, (ATMCI_DTOMUL(dtomul) | ATMCI_DTOCYC(dtocyc))); } /* @@ -512,13 +513,13 @@ static u32 atmci_prepare_command(struct mmc_host *mmc, cmd->error = -EINPROGRESS; - cmdr = MCI_CMDR_CMDNB(cmd->opcode); + cmdr = ATMCI_CMDR_CMDNB(cmd->opcode); if (cmd->flags & MMC_RSP_PRESENT) { if (cmd->flags & MMC_RSP_136) - cmdr |= MCI_CMDR_RSPTYP_136BIT; + cmdr |= ATMCI_CMDR_RSPTYP_136BIT; else - cmdr |= MCI_CMDR_RSPTYP_48BIT; + cmdr |= ATMCI_CMDR_RSPTYP_48BIT; } /* @@ -526,28 +527,28 @@ static u32 atmci_prepare_command(struct mmc_host *mmc, * it's too difficult to determine whether this is an ACMD or * not. Better make it 64. */ - cmdr |= MCI_CMDR_MAXLAT_64CYC; + cmdr |= ATMCI_CMDR_MAXLAT_64CYC; if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN) - cmdr |= MCI_CMDR_OPDCMD; + cmdr |= ATMCI_CMDR_OPDCMD; data = cmd->data; if (data) { - cmdr |= MCI_CMDR_START_XFER; + cmdr |= ATMCI_CMDR_START_XFER; if (cmd->opcode == SD_IO_RW_EXTENDED) { - cmdr |= MCI_CMDR_SDIO_BLOCK; + cmdr |= ATMCI_CMDR_SDIO_BLOCK; } else { if (data->flags & MMC_DATA_STREAM) - cmdr |= MCI_CMDR_STREAM; + cmdr |= ATMCI_CMDR_STREAM; else if (data->blocks > 1) - cmdr |= MCI_CMDR_MULTI_BLOCK; + cmdr |= ATMCI_CMDR_MULTI_BLOCK; else - cmdr |= MCI_CMDR_BLOCK; + cmdr |= ATMCI_CMDR_BLOCK; } if (data->flags & MMC_DATA_READ) - cmdr |= MCI_CMDR_TRDIR_READ; + cmdr |= ATMCI_CMDR_TRDIR_READ; } return cmdr; @@ -563,14 +564,14 @@ static void atmci_start_command(struct atmel_mci *host, "start command: ARGR=0x%08x CMDR=0x%08x\n", cmd->arg, cmd_flags); - mci_writel(host, ARGR, cmd->arg); - mci_writel(host, CMDR, cmd_flags); + atmci_writel(host, ARGR, cmd->arg); + atmci_writel(host, CMDR, cmd_flags); } -static void send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) +static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) { atmci_start_command(host, data->stop, host->stop_cmdr); - mci_writel(host, IER, MCI_CMDRDY); + atmci_writel(host, IER, ATMCI_CMDRDY); } #ifdef CONFIG_MMC_ATMELMCI_DMA @@ -595,7 +596,7 @@ static void atmci_stop_dma(struct atmel_mci *host) } else { /* Data transfer was stopped by the interrupt handler */ atmci_set_pending(host, EVENT_XFER_COMPLETE); - mci_writel(host, IER, MCI_NOTBUSY); + atmci_writel(host, IER, ATMCI_NOTBUSY); } } @@ -609,7 +610,7 @@ static void atmci_dma_complete(void *arg) if (atmci_is_mci2()) /* Disable DMA hardware handshaking on MCI */ - mci_writel(host, DMA, mci_readl(host, DMA) & ~MCI_DMAEN); + atmci_writel(host, DMA, atmci_readl(host, DMA) & ~ATMCI_DMAEN); atmci_dma_cleanup(host); @@ -641,7 +642,7 @@ static void atmci_dma_complete(void *arg) * completion callback" rule of the dma engine * framework. */ - mci_writel(host, IER, MCI_NOTBUSY); + atmci_writel(host, IER, ATMCI_NOTBUSY); } } @@ -660,7 +661,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) * non-word-aligned buffers or lengths. Also, we don't bother * with all the DMA setup overhead for short transfers. */ - if (data->blocks * data->blksz < ATMCI_DMA_THRESHOLD) + if (data->blocks * data->blksz < ATATMCI_DMA_THRESHOLD) return -EINVAL; if (data->blksz & 3) return -EINVAL; @@ -679,7 +680,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) return -ENODEV; if (atmci_is_mci2()) - mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN); + atmci_writel(host, DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN); if (data->flags & MMC_DATA_READ) direction = DMA_FROM_DEVICE; @@ -729,7 +730,7 @@ static void atmci_stop_dma(struct atmel_mci *host) { /* Data transfer was stopped by the interrupt handler */ atmci_set_pending(host, EVENT_XFER_COMPLETE); - mci_writel(host, IER, MCI_NOTBUSY); + atmci_writel(host, IER, ATMCI_NOTBUSY); } #endif /* CONFIG_MMC_ATMELMCI_DMA */ @@ -766,9 +767,9 @@ static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data) host->sg = data->sg; host->pio_offset = 0; if (data->flags & MMC_DATA_READ) - iflags |= MCI_RXRDY; + iflags |= ATMCI_RXRDY; else - iflags |= MCI_TXRDY; + iflags |= ATMCI_TXRDY; } return iflags; @@ -792,24 +793,24 @@ static void atmci_start_request(struct atmel_mci *host, host->data_status = 0; if (host->need_reset) { - mci_writel(host, CR, MCI_CR_SWRST); - mci_writel(host, CR, MCI_CR_MCIEN); - mci_writel(host, MR, host->mode_reg); + atmci_writel(host, CR, ATMCI_CR_SWRST); + atmci_writel(host, CR, ATMCI_CR_MCIEN); + atmci_writel(host, MR, host->mode_reg); if (atmci_is_mci2()) - mci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, CFG, host->cfg_reg); host->need_reset = false; } - mci_writel(host, SDCR, slot->sdc_reg); + atmci_writel(host, SDCR, slot->sdc_reg); - iflags = mci_readl(host, IMR); - if (iflags & ~(MCI_SDIOIRQA | MCI_SDIOIRQB)) + iflags = atmci_readl(host, IMR); + if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", iflags); if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) { /* Send init sequence (74 clock cycles) */ - mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT); - while (!(mci_readl(host, SR) & MCI_CMDRDY)) + atmci_writel(host, CMDR, ATMCI_CMDR_SPCMD_INIT); + while (!(atmci_readl(host, SR) & ATMCI_CMDRDY)) cpu_relax(); } iflags = 0; @@ -818,15 +819,15 @@ static void atmci_start_request(struct atmel_mci *host, atmci_set_timeout(host, slot, data); /* Must set block count/size before sending command */ - mci_writel(host, BLKR, MCI_BCNT(data->blocks) - | MCI_BLKLEN(data->blksz)); + atmci_writel(host, BLKR, ATMCI_BCNT(data->blocks) + | ATMCI_BLKLEN(data->blksz)); dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n", - MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz)); + ATMCI_BCNT(data->blocks) | ATMCI_BLKLEN(data->blksz)); iflags |= atmci_prepare_data(host, data); } - iflags |= MCI_CMDRDY; + iflags |= ATMCI_CMDRDY; cmd = mrq->cmd; cmdflags = atmci_prepare_command(slot->mmc, cmd); atmci_start_command(host, cmd, cmdflags); @@ -836,13 +837,13 @@ static void atmci_start_request(struct atmel_mci *host, if (mrq->stop) { host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); - host->stop_cmdr |= MCI_CMDR_STOP_XFER; + host->stop_cmdr |= ATMCI_CMDR_STOP_XFER; if (!(data->flags & MMC_DATA_WRITE)) - host->stop_cmdr |= MCI_CMDR_TRDIR_READ; + host->stop_cmdr |= ATMCI_CMDR_TRDIR_READ; if (data->flags & MMC_DATA_STREAM) - host->stop_cmdr |= MCI_CMDR_STREAM; + host->stop_cmdr |= ATMCI_CMDR_STREAM; else - host->stop_cmdr |= MCI_CMDR_MULTI_BLOCK; + host->stop_cmdr |= ATMCI_CMDR_MULTI_BLOCK; } /* @@ -851,7 +852,7 @@ static void atmci_start_request(struct atmel_mci *host, * conditions (e.g. command and data complete, but stop not * prepared yet.) */ - mci_writel(host, IER, iflags); + atmci_writel(host, IER, iflags); } static void atmci_queue_request(struct atmel_mci *host, @@ -909,13 +910,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) struct atmel_mci *host = slot->host; unsigned int i; - slot->sdc_reg &= ~MCI_SDCBUS_MASK; + slot->sdc_reg &= ~ATMCI_SDCBUS_MASK; switch (ios->bus_width) { case MMC_BUS_WIDTH_1: - slot->sdc_reg |= MCI_SDCBUS_1BIT; + slot->sdc_reg |= ATMCI_SDCBUS_1BIT; break; case MMC_BUS_WIDTH_4: - slot->sdc_reg |= MCI_SDCBUS_4BIT; + slot->sdc_reg |= ATMCI_SDCBUS_4BIT; break; } @@ -926,10 +927,10 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_lock_bh(&host->lock); if (!host->mode_reg) { clk_enable(host->mck); - mci_writel(host, CR, MCI_CR_SWRST); - mci_writel(host, CR, MCI_CR_MCIEN); + atmci_writel(host, CR, ATMCI_CR_SWRST); + atmci_writel(host, CR, ATMCI_CR_MCIEN); if (atmci_is_mci2()) - mci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, CFG, host->cfg_reg); } /* @@ -937,7 +938,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * core ios update when finding the minimum. */ slot->clock = ios->clock; - for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { if (host->slot[i] && host->slot[i]->clock && host->slot[i]->clock < clock_min) clock_min = host->slot[i]->clock; @@ -952,28 +953,28 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) clkdiv = 255; } - host->mode_reg = MCI_MR_CLKDIV(clkdiv); + host->mode_reg = ATMCI_MR_CLKDIV(clkdiv); /* * WRPROOF and RDPROOF prevent overruns/underruns by * stopping the clock when the FIFO is full/empty. * This state is not expected to last for long. */ - if (mci_has_rwproof()) - host->mode_reg |= (MCI_MR_WRPROOF | MCI_MR_RDPROOF); + if (atmci_has_rwproof()) + host->mode_reg |= (ATMCI_MR_WRPROOF | ATMCI_MR_RDPROOF); if (atmci_is_mci2()) { /* setup High Speed mode in relation with card capacity */ if (ios->timing == MMC_TIMING_SD_HS) - host->cfg_reg |= MCI_CFG_HSMODE; + host->cfg_reg |= ATMCI_CFG_HSMODE; else - host->cfg_reg &= ~MCI_CFG_HSMODE; + host->cfg_reg &= ~ATMCI_CFG_HSMODE; } if (list_empty(&host->queue)) { - mci_writel(host, MR, host->mode_reg); + atmci_writel(host, MR, host->mode_reg); if (atmci_is_mci2()) - mci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, CFG, host->cfg_reg); } else { host->need_clock_update = true; } @@ -984,16 +985,16 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_lock_bh(&host->lock); slot->clock = 0; - for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { if (host->slot[i] && host->slot[i]->clock) { any_slot_active = true; break; } } if (!any_slot_active) { - mci_writel(host, CR, MCI_CR_MCIDIS); + atmci_writel(host, CR, ATMCI_CR_MCIDIS); if (host->mode_reg) { - mci_readl(host, MR); + atmci_readl(host, MR); clk_disable(host->mck); } host->mode_reg = 0; @@ -1057,9 +1058,9 @@ static void atmci_enable_sdio_irq(struct mmc_host *mmc, int enable) struct atmel_mci *host = slot->host; if (enable) - mci_writel(host, IER, slot->sdio_irq); + atmci_writel(host, IER, slot->sdio_irq); else - mci_writel(host, IDR, slot->sdio_irq); + atmci_writel(host, IDR, slot->sdio_irq); } static const struct mmc_host_ops atmci_ops = { @@ -1086,9 +1087,9 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) * busy transferring data. */ if (host->need_clock_update) { - mci_writel(host, MR, host->mode_reg); + atmci_writel(host, MR, host->mode_reg); if (atmci_is_mci2()) - mci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, CFG, host->cfg_reg); } host->cur_slot->mrq = NULL; @@ -1117,16 +1118,16 @@ static void atmci_command_complete(struct atmel_mci *host, u32 status = host->cmd_status; /* Read the response from the card (up to 16 bytes) */ - cmd->resp[0] = mci_readl(host, RSPR); - cmd->resp[1] = mci_readl(host, RSPR); - cmd->resp[2] = mci_readl(host, RSPR); - cmd->resp[3] = mci_readl(host, RSPR); + cmd->resp[0] = atmci_readl(host, RSPR); + cmd->resp[1] = atmci_readl(host, RSPR); + cmd->resp[2] = atmci_readl(host, RSPR); + cmd->resp[3] = atmci_readl(host, RSPR); - if (status & MCI_RTOE) + if (status & ATMCI_RTOE) cmd->error = -ETIMEDOUT; - else if ((cmd->flags & MMC_RSP_CRC) && (status & MCI_RCRCE)) + else if ((cmd->flags & MMC_RSP_CRC) && (status & ATMCI_RCRCE)) cmd->error = -EILSEQ; - else if (status & (MCI_RINDE | MCI_RDIRE | MCI_RENDE)) + else if (status & (ATMCI_RINDE | ATMCI_RDIRE | ATMCI_RENDE)) cmd->error = -EIO; else cmd->error = 0; @@ -1138,8 +1139,8 @@ static void atmci_command_complete(struct atmel_mci *host, if (cmd->data) { atmci_stop_dma(host); host->data = NULL; - mci_writel(host, IDR, MCI_NOTBUSY - | MCI_TXRDY | MCI_RXRDY + atmci_writel(host, IDR, ATMCI_NOTBUSY + | ATMCI_TXRDY | ATMCI_RXRDY | ATMCI_DATA_ERROR_FLAGS); } } @@ -1191,11 +1192,11 @@ static void atmci_detect_change(unsigned long data) * Reset controller to terminate any ongoing * commands or data transfers. */ - mci_writel(host, CR, MCI_CR_SWRST); - mci_writel(host, CR, MCI_CR_MCIEN); - mci_writel(host, MR, host->mode_reg); + atmci_writel(host, CR, ATMCI_CR_SWRST); + atmci_writel(host, CR, ATMCI_CR_MCIEN); + atmci_writel(host, MR, host->mode_reg); if (atmci_is_mci2()) - mci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, CFG, host->cfg_reg); host->data = NULL; host->cmd = NULL; @@ -1261,7 +1262,7 @@ static void atmci_tasklet_func(unsigned long priv) dev_vdbg(&host->pdev->dev, "tasklet: state %u pending/completed/mask %lx/%lx/%x\n", state, host->pending_events, host->completed_events, - mci_readl(host, IMR)); + atmci_readl(host, IMR)); do { prev_state = state; @@ -1291,7 +1292,7 @@ static void atmci_tasklet_func(unsigned long priv) EVENT_DATA_ERROR)) { atmci_stop_dma(host); if (data->stop) - send_stop_cmd(host, data); + atmci_send_stop_cmd(host, data); state = STATE_DATA_ERROR; break; } @@ -1313,11 +1314,11 @@ static void atmci_tasklet_func(unsigned long priv) atmci_set_completed(host, EVENT_DATA_COMPLETE); status = host->data_status; if (unlikely(status & ATMCI_DATA_ERROR_FLAGS)) { - if (status & MCI_DTOE) { + if (status & ATMCI_DTOE) { dev_dbg(&host->pdev->dev, "data timeout error\n"); data->error = -ETIMEDOUT; - } else if (status & MCI_DCRCE) { + } else if (status & ATMCI_DCRCE) { dev_dbg(&host->pdev->dev, "data CRC error\n"); data->error = -EILSEQ; @@ -1330,7 +1331,7 @@ static void atmci_tasklet_func(unsigned long priv) } else { data->bytes_xfered = data->blocks * data->blksz; data->error = 0; - mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS); + atmci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS); } if (!data->stop) { @@ -1340,7 +1341,7 @@ static void atmci_tasklet_func(unsigned long priv) prev_state = state = STATE_SENDING_STOP; if (!data->error) - send_stop_cmd(host, data); + atmci_send_stop_cmd(host, data); /* fall through */ case STATE_SENDING_STOP: @@ -1380,7 +1381,7 @@ static void atmci_read_data_pio(struct atmel_mci *host) unsigned int nbytes = 0; do { - value = mci_readl(host, RDR); + value = atmci_readl(host, RDR); if (likely(offset + 4 <= sg->length)) { put_unaligned(value, (u32 *)(buf + offset)); @@ -1412,9 +1413,9 @@ static void atmci_read_data_pio(struct atmel_mci *host) nbytes += offset; } - status = mci_readl(host, SR); + status = atmci_readl(host, SR); if (status & ATMCI_DATA_ERROR_FLAGS) { - mci_writel(host, IDR, (MCI_NOTBUSY | MCI_RXRDY + atmci_writel(host, IDR, (ATMCI_NOTBUSY | ATMCI_RXRDY | ATMCI_DATA_ERROR_FLAGS)); host->data_status = status; data->bytes_xfered += nbytes; @@ -1423,7 +1424,7 @@ static void atmci_read_data_pio(struct atmel_mci *host) tasklet_schedule(&host->tasklet); return; } - } while (status & MCI_RXRDY); + } while (status & ATMCI_RXRDY); host->pio_offset = offset; data->bytes_xfered += nbytes; @@ -1431,8 +1432,8 @@ static void atmci_read_data_pio(struct atmel_mci *host) return; done: - mci_writel(host, IDR, MCI_RXRDY); - mci_writel(host, IER, MCI_NOTBUSY); + atmci_writel(host, IDR, ATMCI_RXRDY); + atmci_writel(host, IER, ATMCI_NOTBUSY); data->bytes_xfered += nbytes; smp_wmb(); atmci_set_pending(host, EVENT_XFER_COMPLETE); @@ -1451,7 +1452,7 @@ static void atmci_write_data_pio(struct atmel_mci *host) do { if (likely(offset + 4 <= sg->length)) { value = get_unaligned((u32 *)(buf + offset)); - mci_writel(host, TDR, value); + atmci_writel(host, TDR, value); offset += 4; nbytes += 4; @@ -1472,20 +1473,20 @@ static void atmci_write_data_pio(struct atmel_mci *host) host->sg = sg = sg_next(sg); if (!sg) { - mci_writel(host, TDR, value); + atmci_writel(host, TDR, value); goto done; } offset = 4 - remaining; buf = sg_virt(sg); memcpy((u8 *)&value + remaining, buf, offset); - mci_writel(host, TDR, value); + atmci_writel(host, TDR, value); nbytes += offset; } - status = mci_readl(host, SR); + status = atmci_readl(host, SR); if (status & ATMCI_DATA_ERROR_FLAGS) { - mci_writel(host, IDR, (MCI_NOTBUSY | MCI_TXRDY + atmci_writel(host, IDR, (ATMCI_NOTBUSY | ATMCI_TXRDY | ATMCI_DATA_ERROR_FLAGS)); host->data_status = status; data->bytes_xfered += nbytes; @@ -1494,7 +1495,7 @@ static void atmci_write_data_pio(struct atmel_mci *host) tasklet_schedule(&host->tasklet); return; } - } while (status & MCI_TXRDY); + } while (status & ATMCI_TXRDY); host->pio_offset = offset; data->bytes_xfered += nbytes; @@ -1502,8 +1503,8 @@ static void atmci_write_data_pio(struct atmel_mci *host) return; done: - mci_writel(host, IDR, MCI_TXRDY); - mci_writel(host, IER, MCI_NOTBUSY); + atmci_writel(host, IDR, ATMCI_TXRDY); + atmci_writel(host, IER, ATMCI_NOTBUSY); data->bytes_xfered += nbytes; smp_wmb(); atmci_set_pending(host, EVENT_XFER_COMPLETE); @@ -1511,7 +1512,7 @@ done: static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status) { - mci_writel(host, IDR, MCI_CMDRDY); + atmci_writel(host, IDR, ATMCI_CMDRDY); host->cmd_status = status; smp_wmb(); @@ -1523,7 +1524,7 @@ static void atmci_sdio_interrupt(struct atmel_mci *host, u32 status) { int i; - for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { struct atmel_mci_slot *slot = host->slot[i]; if (slot && (status & slot->sdio_irq)) { mmc_signal_sdio_irq(slot->mmc); @@ -1539,40 +1540,40 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) unsigned int pass_count = 0; do { - status = mci_readl(host, SR); - mask = mci_readl(host, IMR); + status = atmci_readl(host, SR); + mask = atmci_readl(host, IMR); pending = status & mask; if (!pending) break; if (pending & ATMCI_DATA_ERROR_FLAGS) { - mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS - | MCI_RXRDY | MCI_TXRDY); - pending &= mci_readl(host, IMR); + atmci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS + | ATMCI_RXRDY | ATMCI_TXRDY); + pending &= atmci_readl(host, IMR); host->data_status = status; smp_wmb(); atmci_set_pending(host, EVENT_DATA_ERROR); tasklet_schedule(&host->tasklet); } - if (pending & MCI_NOTBUSY) { - mci_writel(host, IDR, - ATMCI_DATA_ERROR_FLAGS | MCI_NOTBUSY); + if (pending & ATMCI_NOTBUSY) { + atmci_writel(host, IDR, + ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY); if (!host->data_status) host->data_status = status; smp_wmb(); atmci_set_pending(host, EVENT_DATA_COMPLETE); tasklet_schedule(&host->tasklet); } - if (pending & MCI_RXRDY) + if (pending & ATMCI_RXRDY) atmci_read_data_pio(host); - if (pending & MCI_TXRDY) + if (pending & ATMCI_TXRDY) atmci_write_data_pio(host); - if (pending & MCI_CMDRDY) + if (pending & ATMCI_CMDRDY) atmci_cmd_interrupt(host, status); - if (pending & (MCI_SDIOIRQA | MCI_SDIOIRQB)) + if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) atmci_sdio_interrupt(host, status); } while (pass_count++ < 5); @@ -1705,7 +1706,7 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, } #ifdef CONFIG_MMC_ATMELMCI_DMA -static bool filter(struct dma_chan *chan, void *slave) +static bool atmci_filter(struct dma_chan *chan, void *slave) { struct mci_dma_data *sl = slave; @@ -1730,14 +1731,14 @@ static void atmci_configure_dma(struct atmel_mci *host) dma_cap_mask_t mask; setup_dma_addr(pdata->dma_slave, - host->mapbase + MCI_TDR, - host->mapbase + MCI_RDR); + host->mapbase + ATMCI_TDR, + host->mapbase + ATMCI_RDR); /* Try to grab a DMA channel */ dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); host->dma.chan = - dma_request_channel(mask, filter, pdata->dma_slave); + dma_request_channel(mask, atmci_filter, pdata->dma_slave); } if (!host->dma.chan) dev_notice(&host->pdev->dev, "DMA not available, using PIO\n"); @@ -1789,7 +1790,7 @@ static int __init atmci_probe(struct platform_device *pdev) goto err_ioremap; clk_enable(host->mck); - mci_writel(host, CR, MCI_CR_SWRST); + atmci_writel(host, CR, ATMCI_CR_SWRST); host->bus_hz = clk_get_rate(host->mck); clk_disable(host->mck); @@ -1810,13 +1811,13 @@ static int __init atmci_probe(struct platform_device *pdev) ret = -ENODEV; if (pdata->slot[0].bus_width) { ret = atmci_init_slot(host, &pdata->slot[0], - 0, MCI_SDCSEL_SLOT_A, MCI_SDIOIRQA); + 0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA); if (!ret) nr_slots++; } if (pdata->slot[1].bus_width) { ret = atmci_init_slot(host, &pdata->slot[1], - 1, MCI_SDCSEL_SLOT_B, MCI_SDIOIRQB); + 1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB); if (!ret) nr_slots++; } @@ -1854,15 +1855,15 @@ static int __exit atmci_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { if (host->slot[i]) atmci_cleanup_slot(host->slot[i], i); } clk_enable(host->mck); - mci_writel(host, IDR, ~0UL); - mci_writel(host, CR, MCI_CR_MCIDIS); - mci_readl(host, SR); + atmci_writel(host, IDR, ~0UL); + atmci_writel(host, CR, ATMCI_CR_MCIDIS); + atmci_readl(host, SR); clk_disable(host->mck); #ifdef CONFIG_MMC_ATMELMCI_DMA @@ -1885,7 +1886,7 @@ static int atmci_suspend(struct device *dev) struct atmel_mci *host = dev_get_drvdata(dev); int i; - for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { struct atmel_mci_slot *slot = host->slot[i]; int ret; @@ -1916,7 +1917,7 @@ static int atmci_resume(struct device *dev) int i; int ret = 0; - for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { struct atmel_mci_slot *slot = host->slot[i]; int err; -- cgit v1.2.3 From 03fc9a7f0c48a05ca548cd277835d7da97ed6936 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 11 Aug 2011 15:25:42 +0000 Subject: mmc: atmel-mci: change atmci_readl and atmci_writel macros Change atmci_readl and atmci_writel macros: remove string concatenation. We can use these macros with registers which are not prefixed by ATMCI_. This is the case if we want to write PDC registers which are common to several devices so they are not prefixed with ATMCI_. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci-regs.h | 4 +- drivers/mmc/host/atmel-mci.c | 126 +++++++++++++++++++------------------- 2 files changed, 65 insertions(+), 65 deletions(-) (limited to 'drivers/mmc/host/atmel-mci.c') diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index 29331ab67dc3..8574e910d1f8 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h @@ -121,8 +121,8 @@ /* Register access macros */ #define atmci_readl(port,reg) \ - __raw_readl((port)->regs + ATMCI_##reg) + __raw_readl((port)->regs + reg) #define atmci_writel(port,reg,value) \ - __raw_writel((value), (port)->regs + ATMCI_##reg) + __raw_writel((value), (port)->regs + reg) #endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */ diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index c2a0949f3257..87eeccc6d9a4 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -499,7 +499,7 @@ static void atmci_set_timeout(struct atmel_mci *host, dev_vdbg(&slot->mmc->class_dev, "setting timeout to %u cycles\n", dtocyc << dtomul_to_shift[dtomul]); - atmci_writel(host, DTOR, (ATMCI_DTOMUL(dtomul) | ATMCI_DTOCYC(dtocyc))); + atmci_writel(host, ATMCI_DTOR, (ATMCI_DTOMUL(dtomul) | ATMCI_DTOCYC(dtocyc))); } /* @@ -564,14 +564,14 @@ static void atmci_start_command(struct atmel_mci *host, "start command: ARGR=0x%08x CMDR=0x%08x\n", cmd->arg, cmd_flags); - atmci_writel(host, ARGR, cmd->arg); - atmci_writel(host, CMDR, cmd_flags); + atmci_writel(host, ATMCI_ARGR, cmd->arg); + atmci_writel(host, ATMCI_CMDR, cmd_flags); } static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) { atmci_start_command(host, data->stop, host->stop_cmdr); - atmci_writel(host, IER, ATMCI_CMDRDY); + atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY); } #ifdef CONFIG_MMC_ATMELMCI_DMA @@ -596,7 +596,7 @@ static void atmci_stop_dma(struct atmel_mci *host) } else { /* Data transfer was stopped by the interrupt handler */ atmci_set_pending(host, EVENT_XFER_COMPLETE); - atmci_writel(host, IER, ATMCI_NOTBUSY); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); } } @@ -610,7 +610,7 @@ static void atmci_dma_complete(void *arg) if (atmci_is_mci2()) /* Disable DMA hardware handshaking on MCI */ - atmci_writel(host, DMA, atmci_readl(host, DMA) & ~ATMCI_DMAEN); + atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); atmci_dma_cleanup(host); @@ -642,7 +642,7 @@ static void atmci_dma_complete(void *arg) * completion callback" rule of the dma engine * framework. */ - atmci_writel(host, IER, ATMCI_NOTBUSY); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); } } @@ -680,7 +680,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) return -ENODEV; if (atmci_is_mci2()) - atmci_writel(host, DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN); + atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN); if (data->flags & MMC_DATA_READ) direction = DMA_FROM_DEVICE; @@ -730,7 +730,7 @@ static void atmci_stop_dma(struct atmel_mci *host) { /* Data transfer was stopped by the interrupt handler */ atmci_set_pending(host, EVENT_XFER_COMPLETE); - atmci_writel(host, IER, ATMCI_NOTBUSY); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); } #endif /* CONFIG_MMC_ATMELMCI_DMA */ @@ -793,24 +793,24 @@ static void atmci_start_request(struct atmel_mci *host, host->data_status = 0; if (host->need_reset) { - atmci_writel(host, CR, ATMCI_CR_SWRST); - atmci_writel(host, CR, ATMCI_CR_MCIEN); - atmci_writel(host, MR, host->mode_reg); + atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); + atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); + atmci_writel(host, ATMCI_MR, host->mode_reg); if (atmci_is_mci2()) - atmci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, ATMCI_CFG, host->cfg_reg); host->need_reset = false; } - atmci_writel(host, SDCR, slot->sdc_reg); + atmci_writel(host, ATMCI_SDCR, slot->sdc_reg); - iflags = atmci_readl(host, IMR); + iflags = atmci_readl(host, ATMCI_IMR); if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", iflags); if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) { /* Send init sequence (74 clock cycles) */ - atmci_writel(host, CMDR, ATMCI_CMDR_SPCMD_INIT); - while (!(atmci_readl(host, SR) & ATMCI_CMDRDY)) + atmci_writel(host, ATMCI_CMDR, ATMCI_CMDR_SPCMD_INIT); + while (!(atmci_readl(host, ATMCI_SR) & ATMCI_CMDRDY)) cpu_relax(); } iflags = 0; @@ -819,7 +819,7 @@ static void atmci_start_request(struct atmel_mci *host, atmci_set_timeout(host, slot, data); /* Must set block count/size before sending command */ - atmci_writel(host, BLKR, ATMCI_BCNT(data->blocks) + atmci_writel(host, ATMCI_BLKR, ATMCI_BCNT(data->blocks) | ATMCI_BLKLEN(data->blksz)); dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n", ATMCI_BCNT(data->blocks) | ATMCI_BLKLEN(data->blksz)); @@ -852,7 +852,7 @@ static void atmci_start_request(struct atmel_mci *host, * conditions (e.g. command and data complete, but stop not * prepared yet.) */ - atmci_writel(host, IER, iflags); + atmci_writel(host, ATMCI_IER, iflags); } static void atmci_queue_request(struct atmel_mci *host, @@ -927,10 +927,10 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_lock_bh(&host->lock); if (!host->mode_reg) { clk_enable(host->mck); - atmci_writel(host, CR, ATMCI_CR_SWRST); - atmci_writel(host, CR, ATMCI_CR_MCIEN); + atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); + atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); if (atmci_is_mci2()) - atmci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, ATMCI_CFG, host->cfg_reg); } /* @@ -972,9 +972,9 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } if (list_empty(&host->queue)) { - atmci_writel(host, MR, host->mode_reg); + atmci_writel(host, ATMCI_MR, host->mode_reg); if (atmci_is_mci2()) - atmci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, ATMCI_CFG, host->cfg_reg); } else { host->need_clock_update = true; } @@ -992,9 +992,9 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } if (!any_slot_active) { - atmci_writel(host, CR, ATMCI_CR_MCIDIS); + atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS); if (host->mode_reg) { - atmci_readl(host, MR); + atmci_readl(host, ATMCI_MR); clk_disable(host->mck); } host->mode_reg = 0; @@ -1058,9 +1058,9 @@ static void atmci_enable_sdio_irq(struct mmc_host *mmc, int enable) struct atmel_mci *host = slot->host; if (enable) - atmci_writel(host, IER, slot->sdio_irq); + atmci_writel(host, ATMCI_IER, slot->sdio_irq); else - atmci_writel(host, IDR, slot->sdio_irq); + atmci_writel(host, ATMCI_IDR, slot->sdio_irq); } static const struct mmc_host_ops atmci_ops = { @@ -1087,9 +1087,9 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) * busy transferring data. */ if (host->need_clock_update) { - atmci_writel(host, MR, host->mode_reg); + atmci_writel(host, ATMCI_MR, host->mode_reg); if (atmci_is_mci2()) - atmci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, ATMCI_CFG, host->cfg_reg); } host->cur_slot->mrq = NULL; @@ -1118,10 +1118,10 @@ static void atmci_command_complete(struct atmel_mci *host, u32 status = host->cmd_status; /* Read the response from the card (up to 16 bytes) */ - cmd->resp[0] = atmci_readl(host, RSPR); - cmd->resp[1] = atmci_readl(host, RSPR); - cmd->resp[2] = atmci_readl(host, RSPR); - cmd->resp[3] = atmci_readl(host, RSPR); + cmd->resp[0] = atmci_readl(host, ATMCI_RSPR); + cmd->resp[1] = atmci_readl(host, ATMCI_RSPR); + cmd->resp[2] = atmci_readl(host, ATMCI_RSPR); + cmd->resp[3] = atmci_readl(host, ATMCI_RSPR); if (status & ATMCI_RTOE) cmd->error = -ETIMEDOUT; @@ -1139,7 +1139,7 @@ static void atmci_command_complete(struct atmel_mci *host, if (cmd->data) { atmci_stop_dma(host); host->data = NULL; - atmci_writel(host, IDR, ATMCI_NOTBUSY + atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY | ATMCI_TXRDY | ATMCI_RXRDY | ATMCI_DATA_ERROR_FLAGS); } @@ -1192,11 +1192,11 @@ static void atmci_detect_change(unsigned long data) * Reset controller to terminate any ongoing * commands or data transfers. */ - atmci_writel(host, CR, ATMCI_CR_SWRST); - atmci_writel(host, CR, ATMCI_CR_MCIEN); - atmci_writel(host, MR, host->mode_reg); + atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); + atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); + atmci_writel(host, ATMCI_MR, host->mode_reg); if (atmci_is_mci2()) - atmci_writel(host, CFG, host->cfg_reg); + atmci_writel(host, ATMCI_CFG, host->cfg_reg); host->data = NULL; host->cmd = NULL; @@ -1262,7 +1262,7 @@ static void atmci_tasklet_func(unsigned long priv) dev_vdbg(&host->pdev->dev, "tasklet: state %u pending/completed/mask %lx/%lx/%x\n", state, host->pending_events, host->completed_events, - atmci_readl(host, IMR)); + atmci_readl(host, ATMCI_IMR)); do { prev_state = state; @@ -1331,7 +1331,7 @@ static void atmci_tasklet_func(unsigned long priv) } else { data->bytes_xfered = data->blocks * data->blksz; data->error = 0; - atmci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS); + atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS); } if (!data->stop) { @@ -1381,7 +1381,7 @@ static void atmci_read_data_pio(struct atmel_mci *host) unsigned int nbytes = 0; do { - value = atmci_readl(host, RDR); + value = atmci_readl(host, ATMCI_RDR); if (likely(offset + 4 <= sg->length)) { put_unaligned(value, (u32 *)(buf + offset)); @@ -1413,9 +1413,9 @@ static void atmci_read_data_pio(struct atmel_mci *host) nbytes += offset; } - status = atmci_readl(host, SR); + status = atmci_readl(host, ATMCI_SR); if (status & ATMCI_DATA_ERROR_FLAGS) { - atmci_writel(host, IDR, (ATMCI_NOTBUSY | ATMCI_RXRDY + atmci_writel(host, ATMCI_IDR, (ATMCI_NOTBUSY | ATMCI_RXRDY | ATMCI_DATA_ERROR_FLAGS)); host->data_status = status; data->bytes_xfered += nbytes; @@ -1432,8 +1432,8 @@ static void atmci_read_data_pio(struct atmel_mci *host) return; done: - atmci_writel(host, IDR, ATMCI_RXRDY); - atmci_writel(host, IER, ATMCI_NOTBUSY); + atmci_writel(host, ATMCI_IDR, ATMCI_RXRDY); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); data->bytes_xfered += nbytes; smp_wmb(); atmci_set_pending(host, EVENT_XFER_COMPLETE); @@ -1452,7 +1452,7 @@ static void atmci_write_data_pio(struct atmel_mci *host) do { if (likely(offset + 4 <= sg->length)) { value = get_unaligned((u32 *)(buf + offset)); - atmci_writel(host, TDR, value); + atmci_writel(host, ATMCI_TDR, value); offset += 4; nbytes += 4; @@ -1473,20 +1473,20 @@ static void atmci_write_data_pio(struct atmel_mci *host) host->sg = sg = sg_next(sg); if (!sg) { - atmci_writel(host, TDR, value); + atmci_writel(host, ATMCI_TDR, value); goto done; } offset = 4 - remaining; buf = sg_virt(sg); memcpy((u8 *)&value + remaining, buf, offset); - atmci_writel(host, TDR, value); + atmci_writel(host, ATMCI_TDR, value); nbytes += offset; } - status = atmci_readl(host, SR); + status = atmci_readl(host, ATMCI_SR); if (status & ATMCI_DATA_ERROR_FLAGS) { - atmci_writel(host, IDR, (ATMCI_NOTBUSY | ATMCI_TXRDY + atmci_writel(host, ATMCI_IDR, (ATMCI_NOTBUSY | ATMCI_TXRDY | ATMCI_DATA_ERROR_FLAGS)); host->data_status = status; data->bytes_xfered += nbytes; @@ -1503,8 +1503,8 @@ static void atmci_write_data_pio(struct atmel_mci *host) return; done: - atmci_writel(host, IDR, ATMCI_TXRDY); - atmci_writel(host, IER, ATMCI_NOTBUSY); + atmci_writel(host, ATMCI_IDR, ATMCI_TXRDY); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); data->bytes_xfered += nbytes; smp_wmb(); atmci_set_pending(host, EVENT_XFER_COMPLETE); @@ -1512,7 +1512,7 @@ done: static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status) { - atmci_writel(host, IDR, ATMCI_CMDRDY); + atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY); host->cmd_status = status; smp_wmb(); @@ -1540,16 +1540,16 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) unsigned int pass_count = 0; do { - status = atmci_readl(host, SR); - mask = atmci_readl(host, IMR); + status = atmci_readl(host, ATMCI_SR); + mask = atmci_readl(host, ATMCI_IMR); pending = status & mask; if (!pending) break; if (pending & ATMCI_DATA_ERROR_FLAGS) { - atmci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS + atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS | ATMCI_RXRDY | ATMCI_TXRDY); - pending &= atmci_readl(host, IMR); + pending &= atmci_readl(host, ATMCI_IMR); host->data_status = status; smp_wmb(); @@ -1557,7 +1557,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) tasklet_schedule(&host->tasklet); } if (pending & ATMCI_NOTBUSY) { - atmci_writel(host, IDR, + atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY); if (!host->data_status) host->data_status = status; @@ -1790,7 +1790,7 @@ static int __init atmci_probe(struct platform_device *pdev) goto err_ioremap; clk_enable(host->mck); - atmci_writel(host, CR, ATMCI_CR_SWRST); + atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); host->bus_hz = clk_get_rate(host->mck); clk_disable(host->mck); @@ -1861,9 +1861,9 @@ static int __exit atmci_remove(struct platform_device *pdev) } clk_enable(host->mck); - atmci_writel(host, IDR, ~0UL); - atmci_writel(host, CR, ATMCI_CR_MCIDIS); - atmci_readl(host, SR); + atmci_writel(host, ATMCI_IDR, ~0UL); + atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS); + atmci_readl(host, ATMCI_SR); clk_disable(host->mck); #ifdef CONFIG_MMC_ATMELMCI_DMA -- cgit v1.2.3 From 796211b7953bd1036670359f31cd97f309322107 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 11 Aug 2011 15:25:44 +0000 Subject: mmc: atmel-mci: add pdc support and runtime capabilities detection Add pdc support for atmel-mci. It makes at91-mci driver useless because it was only used for the old atmel MCI core which has pdc but no dma support. To allow removing at91-mci, the capabilities of the MCI core are detected at runtime -- then the driver will use pio, pdc or dma transfers. Warning: at91rm9200 is not supported, to support it we need to use swab32 on data but I have no board to test it. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci-regs.h | 14 + drivers/mmc/host/atmel-mci.c | 527 +++++++++++++++++++++++++++++--------- 2 files changed, 423 insertions(+), 118 deletions(-) (limited to 'drivers/mmc/host/atmel-mci.c') diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index 7310b207a442..000b3ad0f5ca 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h @@ -88,8 +88,14 @@ # define ATMCI_BLKE ( 1 << 3) /* Data Block Ended */ # define ATMCI_DTIP ( 1 << 4) /* Data Transfer In Progress */ # define ATMCI_NOTBUSY ( 1 << 5) /* Data Not Busy */ +# define ATMCI_ENDRX ( 1 << 6) /* End of RX Buffer */ +# define ATMCI_ENDTX ( 1 << 7) /* End of TX Buffer */ # define ATMCI_SDIOIRQA ( 1 << 8) /* SDIO IRQ in slot A */ # define ATMCI_SDIOIRQB ( 1 << 9) /* SDIO IRQ in slot B */ +# define ATMCI_SDIOWAIT ( 1 << 12) /* SDIO Read Wait Operation Status */ +# define ATMCI_CSRCV ( 1 << 13) /* CE-ATA Completion Signal Received */ +# define ATMCI_RXBUFF ( 1 << 14) /* RX Buffer Full */ +# define ATMCI_TXBUFE ( 1 << 15) /* TX Buffer Empty */ # define ATMCI_RINDE ( 1 << 16) /* Response Index Error */ # define ATMCI_RDIRE ( 1 << 17) /* Response Direction Error */ # define ATMCI_RCRCE ( 1 << 18) /* Response CRC Error */ @@ -97,6 +103,13 @@ # define ATMCI_RTOE ( 1 << 20) /* Response Time-Out Error */ # define ATMCI_DCRCE ( 1 << 21) /* Data CRC Error */ # define ATMCI_DTOE ( 1 << 22) /* Data Time-Out Error */ +# define ATMCI_CSTOE ( 1 << 23) /* Completion Signal Time-out Error */ +# define ATMCI_BLKOVRE ( 1 << 24) /* DMA Block Overrun Error */ +# define ATMCI_DMADONE ( 1 << 25) /* DMA Transfer Done */ +# define ATMCI_FIFOEMPTY ( 1 << 26) /* FIFO Empty Flag */ +# define ATMCI_XFRDONE ( 1 << 27) /* Transfer Done Flag */ +# define ATMCI_ACKRCV ( 1 << 28) /* Boot Operation Acknowledge Received */ +# define ATMCI_ACKRCVE ( 1 << 29) /* Boot Operation Acknowledge Error */ # define ATMCI_OVRE ( 1 << 30) /* RX Overrun Error */ # define ATMCI_UNRE ( 1 << 31) /* TX Underrun Error */ #define ATMCI_DMA 0x0050 /* DMA Configuration[2] */ @@ -114,6 +127,7 @@ #define ATMCI_WPSR 0x00e8 /* Write Protection Status[2] */ # define ATMCI_GET_WP_VS(x) ((x) & 0x0f) # define ATMCI_GET_WP_VSRC(x) (((x) >> 8) & 0xffff) +#define ATMCI_VERSION 0x00FC /* Version */ #define ATMCI_FIFO_APERTURE 0x0200 /* FIFO Aperture[2] */ /* This is not including the FIFO Aperture on MCI2 */ diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 87eeccc6d9a4..57596782061b 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -58,18 +59,35 @@ enum atmel_mci_state { STATE_DATA_ERROR, }; +enum atmci_xfer_dir { + XFER_RECEIVE = 0, + XFER_TRANSMIT, +}; + +enum atmci_pdc_buf { + PDC_FIRST_BUF = 0, + PDC_SECOND_BUF, +}; + +struct atmel_mci_caps { + bool has_dma; + bool has_pdc; + bool has_cfg_reg; + bool has_cstor_reg; + bool has_highspeed; + bool has_rwproof; +}; + struct atmel_mci_dma { -#ifdef CONFIG_MMC_ATMELMCI_DMA struct dma_chan *chan; struct dma_async_tx_descriptor *data_desc; -#endif }; /** * struct atmel_mci - MMC controller state shared between all slots * @lock: Spinlock protecting the queue and associated data. * @regs: Pointer to MMIO registers. - * @sg: Scatterlist entry currently being processed by PIO code, if any. + * @sg: Scatterlist entry currently being processed by PIO or PDC code. * @pio_offset: Offset into the current scatterlist entry. * @cur_slot: The slot which is currently using the controller. * @mrq: The request currently being processed on @cur_slot, @@ -77,6 +95,7 @@ struct atmel_mci_dma { * @cmd: The command currently being sent to the card, or NULL. * @data: The data currently being transferred, or NULL if no data * transfer is in progress. + * @data_size: just data->blocks * data->blksz. * @dma: DMA client state. * @data_chan: DMA channel being used for the current data transfer. * @cmd_status: Snapshot of SR taken upon completion of the current @@ -103,6 +122,13 @@ struct atmel_mci_dma { * @mck: The peripheral bus clock hooked up to the MMC controller. * @pdev: Platform device associated with the MMC controller. * @slot: Slots sharing this MMC controller. + * @caps: MCI capabilities depending on MCI version. + * @prepare_data: function to setup MCI before data transfer which + * depends on MCI capabilities. + * @submit_data: function to start data transfer which depends on MCI + * capabilities. + * @stop_transfer: function to stop data transfer which depends on MCI + * capabilities. * * Locking * ======= @@ -143,6 +169,7 @@ struct atmel_mci { struct mmc_request *mrq; struct mmc_command *cmd; struct mmc_data *data; + unsigned int data_size; struct atmel_mci_dma dma; struct dma_chan *data_chan; @@ -167,6 +194,12 @@ struct atmel_mci { struct platform_device *pdev; struct atmel_mci_slot *slot[ATMCI_MAX_NR_SLOTS]; + + struct atmel_mci_caps caps; + + u32 (*prepare_data)(struct atmel_mci *host, struct mmc_data *data); + void (*submit_data)(struct atmel_mci *host, struct mmc_data *data); + void (*stop_transfer)(struct atmel_mci *host); }; /** @@ -219,31 +252,6 @@ struct atmel_mci_slot { #define atmci_set_pending(host, event) \ set_bit(event, &host->pending_events) -/* - * Enable or disable features/registers based on - * whether the processor supports them - */ -static bool atmci_has_rwproof(void) -{ - if (cpu_is_at91sam9261() || cpu_is_at91rm9200()) - return false; - else - return true; -} - -/* - * The new MCI2 module isn't 100% compatible with the old MCI module, - * and it has a few nice features which we want to use... - */ -static inline bool atmci_is_mci2(void) -{ - if (cpu_is_at91sam9g45()) - return true; - - return false; -} - - /* * The debugfs stuff below is mostly optimized away when * CONFIG_DEBUG_FS is not set. @@ -379,7 +387,7 @@ static int atmci_regs_show(struct seq_file *s, void *v) buf[ATMCI_BLKR / 4], buf[ATMCI_BLKR / 4] & 0xffff, (buf[ATMCI_BLKR / 4] >> 16) & 0xffff); - if (atmci_is_mci2()) + if (host->caps.has_cstor_reg) seq_printf(s, "CSTOR:\t0x%08x\n", buf[ATMCI_CSTOR / 4]); /* Don't read RSPR and RDR; it will consume the data there */ @@ -387,7 +395,7 @@ static int atmci_regs_show(struct seq_file *s, void *v) atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]); atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]); - if (atmci_is_mci2()) { + if (host->caps.has_dma) { u32 val; val = buf[ATMCI_DMA / 4]; @@ -396,6 +404,9 @@ static int atmci_regs_show(struct seq_file *s, void *v) ((val >> 4) & 3) ? 1 << (((val >> 4) & 3) + 1) : 1, val & ATMCI_DMAEN ? " DMAEN" : ""); + } + if (host->caps.has_cfg_reg) { + u32 val; val = buf[ATMCI_CFG / 4]; seq_printf(s, "CFG:\t0x%08x%s%s%s%s\n", @@ -574,33 +585,109 @@ static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY); } -#ifdef CONFIG_MMC_ATMELMCI_DMA -static void atmci_dma_cleanup(struct atmel_mci *host) +/* + * Configure given PDC buffer taking care of alignement issues. + * Update host->data_size and host->sg. + */ +static void atmci_pdc_set_single_buf(struct atmel_mci *host, + enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb) { - struct mmc_data *data = host->data; + u32 pointer_reg, counter_reg; + + if (dir == XFER_RECEIVE) { + pointer_reg = ATMEL_PDC_RPR; + counter_reg = ATMEL_PDC_RCR; + } else { + pointer_reg = ATMEL_PDC_TPR; + counter_reg = ATMEL_PDC_TCR; + } + + if (buf_nb == PDC_SECOND_BUF) { + pointer_reg += 0x10; + counter_reg += 0x10; + } + + atmci_writel(host, pointer_reg, sg_dma_address(host->sg)); + if (host->data_size <= PAGE_SIZE) { + if (host->data_size & 0x3) { + /* If size is different from modulo 4, transfer bytes */ + atmci_writel(host, counter_reg, host->data_size); + atmci_writel(host, ATMCI_MR, host->mode_reg | ATMCI_MR_PDCFBYTE); + } else { + /* Else transfer 32-bits words */ + atmci_writel(host, counter_reg, host->data_size / 4); + } + host->data_size = 0; + } else { + /* We assume the size of a page is 32-bits aligned */ + atmci_writel(host, counter_reg, PAGE_SIZE / 4); + host->data_size -= PAGE_SIZE; + if (host->data_size) + host->sg = sg_next(host->sg); + } +} + +/* + * Configure PDC buffer according to the data size ie configuring one or two + * buffers. Don't use this function if you want to configure only the second + * buffer. In this case, use atmci_pdc_set_single_buf. + */ +static void atmci_pdc_set_both_buf(struct atmel_mci *host, int dir) +{ + atmci_pdc_set_single_buf(host, dir, PDC_FIRST_BUF); + if (host->data_size) + atmci_pdc_set_single_buf(host, dir, PDC_SECOND_BUF); +} + +/* + * Unmap sg lists, called when transfer is finished. + */ +static void atmci_pdc_cleanup(struct atmel_mci *host) +{ + struct mmc_data *data = host->data; if (data) - dma_unmap_sg(host->dma.chan->device->dev, - data->sg, data->sg_len, - ((data->flags & MMC_DATA_WRITE) - ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); + dma_unmap_sg(&host->pdev->dev, + data->sg, data->sg_len, + ((data->flags & MMC_DATA_WRITE) + ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); } -static void atmci_stop_dma(struct atmel_mci *host) +/* + * Disable PDC transfers. Update pending flags to EVENT_XFER_COMPLETE after + * having received ATMCI_TXBUFE or ATMCI_RXBUFF interrupt. Enable ATMCI_NOTBUSY + * interrupt needed for both transfer directions. + */ +static void atmci_pdc_complete(struct atmel_mci *host) { - struct dma_chan *chan = host->data_chan; + atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); + atmci_pdc_cleanup(host); - if (chan) { - dmaengine_terminate_all(chan); - atmci_dma_cleanup(host); - } else { - /* Data transfer was stopped by the interrupt handler */ + /* + * If the card was removed, data will be NULL. No point trying + * to send the stop command or waiting for NBUSY in this case. + */ + if (host->data) { atmci_set_pending(host, EVENT_XFER_COMPLETE); + tasklet_schedule(&host->tasklet); atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); } } -/* This function is called by the DMA driver from tasklet context. */ +static void atmci_dma_cleanup(struct atmel_mci *host) +{ + struct mmc_data *data = host->data; + + if (data) + dma_unmap_sg(host->dma.chan->device->dev, + data->sg, data->sg_len, + ((data->flags & MMC_DATA_WRITE) + ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); +} + +/* + * This function is called by the DMA driver from tasklet context. + */ static void atmci_dma_complete(void *arg) { struct atmel_mci *host = arg; @@ -608,7 +695,7 @@ static void atmci_dma_complete(void *arg) dev_vdbg(&host->pdev->dev, "DMA complete\n"); - if (atmci_is_mci2()) + if (host->caps.has_dma) /* Disable DMA hardware handshaking on MCI */ atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); @@ -646,7 +733,90 @@ static void atmci_dma_complete(void *arg) } } -static int +/* + * Returns a mask of interrupt flags to be enabled after the whole + * request has been prepared. + */ +static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data) +{ + u32 iflags; + + data->error = -EINPROGRESS; + + host->sg = data->sg; + host->data = data; + host->data_chan = NULL; + + iflags = ATMCI_DATA_ERROR_FLAGS; + + /* + * Errata: MMC data write operation with less than 12 + * bytes is impossible. + * + * Errata: MCI Transmit Data Register (TDR) FIFO + * corruption when length is not multiple of 4. + */ + if (data->blocks * data->blksz < 12 + || (data->blocks * data->blksz) & 3) + host->need_reset = true; + + host->pio_offset = 0; + if (data->flags & MMC_DATA_READ) + iflags |= ATMCI_RXRDY; + else + iflags |= ATMCI_TXRDY; + + return iflags; +} + +/* + * Set interrupt flags and set block length into the MCI mode register even + * if this value is also accessible in the MCI block register. It seems to be + * necessary before the High Speed MCI version. It also map sg and configure + * PDC registers. + */ +static u32 +atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data) +{ + u32 iflags, tmp; + unsigned int sg_len; + enum dma_data_direction dir; + + data->error = -EINPROGRESS; + + host->data = data; + host->sg = data->sg; + iflags = ATMCI_DATA_ERROR_FLAGS; + + /* Enable pdc mode */ + atmci_writel(host, ATMCI_MR, host->mode_reg | ATMCI_MR_PDCMODE); + + if (data->flags & MMC_DATA_READ) { + dir = DMA_FROM_DEVICE; + iflags |= ATMCI_ENDRX | ATMCI_RXBUFF; + } else { + dir = DMA_TO_DEVICE; + iflags |= ATMCI_ENDTX | ATMCI_TXBUFE; + } + + /* Set BLKLEN */ + tmp = atmci_readl(host, ATMCI_MR); + tmp &= 0x0000ffff; + tmp |= ATMCI_BLKLEN(data->blksz); + atmci_writel(host, ATMCI_MR, tmp); + + /* Configure PDC */ + host->data_size = data->blocks * data->blksz; + sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir); + BUG_ON(sg_len < host->data_size / PAGE_SIZE); + if (host->data_size) + atmci_pdc_set_both_buf(host, + ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT)); + + return iflags; +} + +static u32 atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) { struct dma_chan *chan; @@ -655,20 +825,29 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) unsigned int i; enum dma_data_direction direction; unsigned int sglen; + u32 iflags; + + data->error = -EINPROGRESS; + + WARN_ON(host->data); + host->sg = NULL; + host->data = data; + + iflags = ATMCI_DATA_ERROR_FLAGS; /* * We don't do DMA on "complex" transfers, i.e. with * non-word-aligned buffers or lengths. Also, we don't bother * with all the DMA setup overhead for short transfers. */ - if (data->blocks * data->blksz < ATATMCI_DMA_THRESHOLD) - return -EINVAL; + if (data->blocks * data->blksz < ATMCI_DMA_THRESHOLD) + return atmci_prepare_data(host, data); if (data->blksz & 3) - return -EINVAL; + return atmci_prepare_data(host, data); for_each_sg(data->sg, sg, data->sg_len, i) { if (sg->offset & 3 || sg->length & 3) - return -EINVAL; + return atmci_prepare_data(host, data); } /* If we don't have a channel, we can't do DMA */ @@ -679,7 +858,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) if (!chan) return -ENODEV; - if (atmci_is_mci2()) + if (host->caps.has_dma) atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN); if (data->flags & MMC_DATA_READ) @@ -688,7 +867,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) direction = DMA_TO_DEVICE; sglen = dma_map_sg(chan->device->dev, data->sg, - data->sg_len, direction); + data->sg_len, direction); desc = chan->device->device_prep_slave_sg(chan, data->sg, sglen, direction, @@ -700,13 +879,32 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) desc->callback = atmci_dma_complete; desc->callback_param = host; - return 0; + return iflags; unmap_exit: dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, direction); return -ENOMEM; } -static void atmci_submit_data(struct atmel_mci *host) +static void +atmci_submit_data(struct atmel_mci *host, struct mmc_data *data) +{ + return; +} + +/* + * Start PDC according to transfer direction. + */ +static void +atmci_submit_data_pdc(struct atmel_mci *host, struct mmc_data *data) +{ + if (data->flags & MMC_DATA_READ) + atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN); + else + atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN); +} + +static void +atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) { struct dma_chan *chan = host->data_chan; struct dma_async_tx_descriptor *desc = host->dma.data_desc; @@ -717,64 +915,39 @@ static void atmci_submit_data(struct atmel_mci *host) } } -#else /* CONFIG_MMC_ATMELMCI_DMA */ - -static int atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) +static void atmci_stop_transfer(struct atmel_mci *host) { - return -ENOSYS; -} - -static void atmci_submit_data(struct atmel_mci *host) {} - -static void atmci_stop_dma(struct atmel_mci *host) -{ - /* Data transfer was stopped by the interrupt handler */ atmci_set_pending(host, EVENT_XFER_COMPLETE); atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); } -#endif /* CONFIG_MMC_ATMELMCI_DMA */ - /* - * Returns a mask of interrupt flags to be enabled after the whole - * request has been prepared. + * Stop data transfer because error(s) occured. */ -static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data) +static void atmci_stop_transfer_pdc(struct atmel_mci *host) { - u32 iflags; - - data->error = -EINPROGRESS; - - WARN_ON(host->data); - host->sg = NULL; - host->data = data; - - iflags = ATMCI_DATA_ERROR_FLAGS; - if (atmci_prepare_data_dma(host, data)) { - host->data_chan = NULL; + atmci_set_pending(host, EVENT_XFER_COMPLETE); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); +} - /* - * Errata: MMC data write operation with less than 12 - * bytes is impossible. - * - * Errata: MCI Transmit Data Register (TDR) FIFO - * corruption when length is not multiple of 4. - */ - if (data->blocks * data->blksz < 12 - || (data->blocks * data->blksz) & 3) - host->need_reset = true; +static void atmci_stop_transfer_dma(struct atmel_mci *host) +{ + struct dma_chan *chan = host->data_chan; - host->sg = data->sg; - host->pio_offset = 0; - if (data->flags & MMC_DATA_READ) - iflags |= ATMCI_RXRDY; - else - iflags |= ATMCI_TXRDY; + if (chan) { + dmaengine_terminate_all(chan); + atmci_dma_cleanup(host); + } else { + /* Data transfer was stopped by the interrupt handler */ + atmci_set_pending(host, EVENT_XFER_COMPLETE); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); } - - return iflags; } +/* + * Start a request: prepare data if needed, prepare the command and activate + * interrupts. + */ static void atmci_start_request(struct atmel_mci *host, struct atmel_mci_slot *slot) { @@ -796,7 +969,7 @@ static void atmci_start_request(struct atmel_mci *host, atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); atmci_writel(host, ATMCI_MR, host->mode_reg); - if (atmci_is_mci2()) + if (host->caps.has_cfg_reg) atmci_writel(host, ATMCI_CFG, host->cfg_reg); host->need_reset = false; } @@ -824,7 +997,7 @@ static void atmci_start_request(struct atmel_mci *host, dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n", ATMCI_BCNT(data->blocks) | ATMCI_BLKLEN(data->blksz)); - iflags |= atmci_prepare_data(host, data); + iflags |= host->prepare_data(host, data); } iflags |= ATMCI_CMDRDY; @@ -833,7 +1006,7 @@ static void atmci_start_request(struct atmel_mci *host, atmci_start_command(host, cmd, cmdflags); if (data) - atmci_submit_data(host); + host->submit_data(host, data); if (mrq->stop) { host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); @@ -929,7 +1102,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) clk_enable(host->mck); atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); - if (atmci_is_mci2()) + if (host->caps.has_cfg_reg) atmci_writel(host, ATMCI_CFG, host->cfg_reg); } @@ -960,10 +1133,10 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * stopping the clock when the FIFO is full/empty. * This state is not expected to last for long. */ - if (atmci_has_rwproof()) + if (host->caps.has_rwproof) host->mode_reg |= (ATMCI_MR_WRPROOF | ATMCI_MR_RDPROOF); - if (atmci_is_mci2()) { + if (host->caps.has_cfg_reg) { /* setup High Speed mode in relation with card capacity */ if (ios->timing == MMC_TIMING_SD_HS) host->cfg_reg |= ATMCI_CFG_HSMODE; @@ -973,7 +1146,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (list_empty(&host->queue)) { atmci_writel(host, ATMCI_MR, host->mode_reg); - if (atmci_is_mci2()) + if (host->caps.has_cfg_reg) atmci_writel(host, ATMCI_CFG, host->cfg_reg); } else { host->need_clock_update = true; @@ -1088,7 +1261,7 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) */ if (host->need_clock_update) { atmci_writel(host, ATMCI_MR, host->mode_reg); - if (atmci_is_mci2()) + if (host->caps.has_cfg_reg) atmci_writel(host, ATMCI_CFG, host->cfg_reg); } @@ -1137,7 +1310,7 @@ static void atmci_command_complete(struct atmel_mci *host, "command error: status=0x%08x\n", status); if (cmd->data) { - atmci_stop_dma(host); + host->stop_transfer(host); host->data = NULL; atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY | ATMCI_TXRDY | ATMCI_RXRDY @@ -1195,7 +1368,7 @@ static void atmci_detect_change(unsigned long data) atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); atmci_writel(host, ATMCI_MR, host->mode_reg); - if (atmci_is_mci2()) + if (host->caps.has_cfg_reg) atmci_writel(host, ATMCI_CFG, host->cfg_reg); host->data = NULL; @@ -1211,7 +1384,7 @@ static void atmci_detect_change(unsigned long data) /* fall through */ case STATE_SENDING_DATA: mrq->data->error = -ENOMEDIUM; - atmci_stop_dma(host); + host->stop_transfer(host); break; case STATE_DATA_BUSY: case STATE_DATA_ERROR: @@ -1290,7 +1463,7 @@ static void atmci_tasklet_func(unsigned long priv) case STATE_SENDING_DATA: if (atmci_test_and_clear_pending(host, EVENT_DATA_ERROR)) { - atmci_stop_dma(host); + host->stop_transfer(host); if (data->stop) atmci_send_stop_cmd(host, data); state = STATE_DATA_ERROR; @@ -1556,6 +1729,56 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) atmci_set_pending(host, EVENT_DATA_ERROR); tasklet_schedule(&host->tasklet); } + + if (pending & ATMCI_ENDTX) { + atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); + if (host->data_size) { + atmci_pdc_set_single_buf(host, + XFER_TRANSMIT, PDC_SECOND_BUF); + atmci_writel(host, ATMCI_IER, ATMCI_ENDTX); + } + } + + if (pending & ATMCI_TXBUFE) { + atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE); + /* + * We can receive this interruption before having configured + * the second pdc buffer, so we need to reconfigure first and + * second buffers again + */ + if (host->data_size) { + atmci_pdc_set_both_buf(host, XFER_TRANSMIT); + atmci_writel(host, ATMCI_IER, ATMCI_TXBUFE); + } else { + atmci_pdc_complete(host); + } + } + + if (pending & ATMCI_ENDRX) { + atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); + + if (host->data_size) { + atmci_pdc_set_single_buf(host, + XFER_RECEIVE, PDC_SECOND_BUF); + atmci_writel(host, ATMCI_IER, ATMCI_ENDRX); + } + } + + if (pending & ATMCI_RXBUFF) { + atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF); + /* + * We can receive this interruption before having configured + * the second pdc buffer, so we need to reconfigure first and + * second buffers again + */ + if (host->data_size) { + atmci_pdc_set_both_buf(host, XFER_RECEIVE); + atmci_writel(host, ATMCI_IER, ATMCI_RXBUFF); + } else { + atmci_pdc_complete(host); + } + } + if (pending & ATMCI_NOTBUSY) { atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY); @@ -1622,7 +1845,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; if (sdio_irq) mmc->caps |= MMC_CAP_SDIO_IRQ; - if (atmci_is_mci2()) + if (host->caps.has_highspeed) mmc->caps |= MMC_CAP_SD_HIGHSPEED; if (slot_data->bus_width >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; @@ -1705,7 +1928,6 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, mmc_free_host(slot->mmc); } -#ifdef CONFIG_MMC_ATMELMCI_DMA static bool atmci_filter(struct dma_chan *chan, void *slave) { struct mci_dma_data *sl = slave; @@ -1747,9 +1969,60 @@ static void atmci_configure_dma(struct atmel_mci *host) "Using %s for DMA transfers\n", dma_chan_name(host->dma.chan)); } + +static inline unsigned int atmci_get_version(struct atmel_mci *host) +{ + return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; +} + +/* + * HSMCI (High Speed MCI) module is not fully compatible with MCI module. + * HSMCI provides DMA support and a new config register but no more supports + * PDC. + */ +static void __init atmci_get_cap(struct atmel_mci *host) +{ + unsigned int version; + + version = atmci_get_version(host); + dev_info(&host->pdev->dev, + "version: 0x%x\n", version); + + host->caps.has_dma = 0; + host->caps.has_pdc = 0; + host->caps.has_cfg_reg = 0; + host->caps.has_cstor_reg = 0; + host->caps.has_highspeed = 0; + host->caps.has_rwproof = 0; + + /* keep only major version number */ + switch (version & 0xf00) { + case 0x100: + case 0x200: + host->caps.has_pdc = 1; + host->caps.has_rwproof = 1; + break; + case 0x300: + case 0x400: + case 0x500: +#ifdef CONFIG_AT_HDMAC + host->caps.has_dma = 1; #else -static void atmci_configure_dma(struct atmel_mci *host) {} + host->caps.has_dma = 0; + dev_info(&host->pdev->dev, + "has dma capability but dma engine is not selected, then use pio\n"); #endif + host->caps.has_cfg_reg = 1; + host->caps.has_cstor_reg = 1; + host->caps.has_highspeed = 1; + host->caps.has_rwproof = 1; + break; + default: + dev_warn(&host->pdev->dev, + "Unmanaged mci version, set minimum capabilities\n"); + break; + } +} static int __init atmci_probe(struct platform_device *pdev) { @@ -1802,7 +2075,27 @@ static int __init atmci_probe(struct platform_device *pdev) if (ret) goto err_request_irq; - atmci_configure_dma(host); + /* Get MCI capabilities and set operations according to it */ + atmci_get_cap(host); + if (host->caps.has_dma) { + dev_info(&pdev->dev, "using DMA\n"); + host->prepare_data = &atmci_prepare_data_dma; + host->submit_data = &atmci_submit_data_dma; + host->stop_transfer = &atmci_stop_transfer_dma; + } else if (host->caps.has_pdc) { + dev_info(&pdev->dev, "using PDC\n"); + host->prepare_data = &atmci_prepare_data_pdc; + host->submit_data = &atmci_submit_data_pdc; + host->stop_transfer = &atmci_stop_transfer_pdc; + } else { + dev_info(&pdev->dev, "no DMA, no PDC\n"); + host->prepare_data = &atmci_prepare_data; + host->submit_data = &atmci_submit_data; + host->stop_transfer = &atmci_stop_transfer; + } + + if (host->caps.has_dma) + atmci_configure_dma(host); platform_set_drvdata(pdev, host); @@ -1834,10 +2127,8 @@ static int __init atmci_probe(struct platform_device *pdev) return 0; err_init_slot: -#ifdef CONFIG_MMC_ATMELMCI_DMA if (host->dma.chan) dma_release_channel(host->dma.chan); -#endif free_irq(irq, host); err_request_irq: iounmap(host->regs); -- cgit v1.2.3 From 11d1488b01b803254842b756ff7662085b37970e Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 11 Aug 2011 15:25:45 +0000 Subject: mmc: atmel-mci: change atmci_start_command to atmci_send_command Rename atmci_start_command() to atmci_send_command() which is more appropriate; atmci_start_command suggests we're sending a start command. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/mmc/host/atmel-mci.c') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 57596782061b..caae967dcafe 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -565,7 +565,7 @@ static u32 atmci_prepare_command(struct mmc_host *mmc, return cmdr; } -static void atmci_start_command(struct atmel_mci *host, +static void atmci_send_command(struct atmel_mci *host, struct mmc_command *cmd, u32 cmd_flags) { WARN_ON(host->cmd); @@ -581,7 +581,7 @@ static void atmci_start_command(struct atmel_mci *host, static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) { - atmci_start_command(host, data->stop, host->stop_cmdr); + atmci_send_command(host, data->stop, host->stop_cmdr); atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY); } @@ -1003,7 +1003,7 @@ static void atmci_start_request(struct atmel_mci *host, iflags |= ATMCI_CMDRDY; cmd = mrq->cmd; cmdflags = atmci_prepare_command(slot->mmc, cmd); - atmci_start_command(host, cmd, cmdflags); + atmci_send_command(host, cmd, cmdflags); if (data) host->submit_data(host, data); -- cgit v1.2.3 From 1ebbe3d31fd96865b4d4874f3c74fef0e386fb79 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 11 Aug 2011 15:25:46 +0000 Subject: mmc: atmel-mci: use ATMEL_PDC_SCND_BUF_OFF instead of a literal value Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 4 ++-- include/linux/atmel_pdc.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/mmc/host/atmel-mci.c') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index caae967dcafe..c0a0659261aa 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -603,8 +603,8 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host, } if (buf_nb == PDC_SECOND_BUF) { - pointer_reg += 0x10; - counter_reg += 0x10; + pointer_reg += ATMEL_PDC_SCND_BUF_OFF; + counter_reg += ATMEL_PDC_SCND_BUF_OFF; } atmci_writel(host, pointer_reg, sg_dma_address(host->sg)); diff --git a/include/linux/atmel_pdc.h b/include/linux/atmel_pdc.h index 5058a31d2ce8..63499ce806ea 100644 --- a/include/linux/atmel_pdc.h +++ b/include/linux/atmel_pdc.h @@ -33,4 +33,6 @@ #define ATMEL_PDC_PTSR 0x124 /* Transfer Status Register */ +#define ATMEL_PDC_SCND_BUF_OFF 0x10 /* Offset between first and second buffer registers */ + #endif -- cgit v1.2.3 From 341fa4c3affe1171005597847a86e4c26dea8bb1 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 11 Aug 2011 15:25:47 +0000 Subject: mmc: atmel-mci: correct sg buffer size evaluation Assuming that a sg buffer size is a page size is false so use sg_dma_len. A 4096 bytes can be required with two 2048-bytes sg buffer. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/mmc/host/atmel-mci.c') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index c0a0659261aa..96004c9fe3a5 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -608,7 +608,7 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host, } atmci_writel(host, pointer_reg, sg_dma_address(host->sg)); - if (host->data_size <= PAGE_SIZE) { + if (host->data_size <= sg_dma_len(host->sg)) { if (host->data_size & 0x3) { /* If size is different from modulo 4, transfer bytes */ atmci_writel(host, counter_reg, host->data_size); @@ -620,8 +620,8 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host, host->data_size = 0; } else { /* We assume the size of a page is 32-bits aligned */ - atmci_writel(host, counter_reg, PAGE_SIZE / 4); - host->data_size -= PAGE_SIZE; + atmci_writel(host, counter_reg, sg_dma_len(host->sg) / 4); + host->data_size -= sg_dma_len(host->sg); if (host->data_size) host->sg = sg_next(host->sg); } @@ -808,7 +808,6 @@ atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data) /* Configure PDC */ host->data_size = data->blocks * data->blksz; sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir); - BUG_ON(sg_len < host->data_size / PAGE_SIZE); if (host->data_size) atmci_pdc_set_both_buf(host, ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT)); -- cgit v1.2.3 From 7e8ba228d9f43a4e4b3ed0e6aa3399e8f30d7bc1 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 11 Aug 2011 15:25:48 +0000 Subject: mmc: atmel-mci: fix a potential issue about pending PDC interrupts This patch fixes a potential issue about PDC interrupts. For example we have a ENDRX pending interrupt and a RXBUFF pending interrupt. We have received the RXBUFF interrupt but the transfer is not finished (so we didn't have time to give a new buffer to the PDC controller). Then we will compute ENDRX interrupt and we will give a new buffer to the PDC controller, just after we will compute the RXBUFF interrupt and give one or two new buffers to the PDC controller but we are not sure that the first buffer given has been filled. So in this situation we may have "lost" one sg buffer. It's the same for transmission. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers/mmc/host/atmel-mci.c') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 96004c9fe3a5..a7ee50271465 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1729,17 +1729,9 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) tasklet_schedule(&host->tasklet); } - if (pending & ATMCI_ENDTX) { - atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); - if (host->data_size) { - atmci_pdc_set_single_buf(host, - XFER_TRANSMIT, PDC_SECOND_BUF); - atmci_writel(host, ATMCI_IER, ATMCI_ENDTX); - } - } - if (pending & ATMCI_TXBUFE) { atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE); + atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); /* * We can receive this interruption before having configured * the second pdc buffer, so we need to reconfigure first and @@ -1747,24 +1739,24 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) */ if (host->data_size) { atmci_pdc_set_both_buf(host, XFER_TRANSMIT); + atmci_writel(host, ATMCI_IER, ATMCI_ENDTX); atmci_writel(host, ATMCI_IER, ATMCI_TXBUFE); } else { atmci_pdc_complete(host); } - } - - if (pending & ATMCI_ENDRX) { - atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); + } else if (pending & ATMCI_ENDTX) { + atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); if (host->data_size) { atmci_pdc_set_single_buf(host, - XFER_RECEIVE, PDC_SECOND_BUF); - atmci_writel(host, ATMCI_IER, ATMCI_ENDRX); + XFER_TRANSMIT, PDC_SECOND_BUF); + atmci_writel(host, ATMCI_IER, ATMCI_ENDTX); } } if (pending & ATMCI_RXBUFF) { atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF); + atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); /* * We can receive this interruption before having configured * the second pdc buffer, so we need to reconfigure first and @@ -1772,12 +1764,22 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) */ if (host->data_size) { atmci_pdc_set_both_buf(host, XFER_RECEIVE); + atmci_writel(host, ATMCI_IER, ATMCI_ENDRX); atmci_writel(host, ATMCI_IER, ATMCI_RXBUFF); } else { atmci_pdc_complete(host); } + } else if (pending & ATMCI_ENDRX) { + atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); + + if (host->data_size) { + atmci_pdc_set_single_buf(host, + XFER_RECEIVE, PDC_SECOND_BUF); + atmci_writel(host, ATMCI_IER, ATMCI_ENDRX); + } } + if (pending & ATMCI_NOTBUSY) { atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY); -- cgit v1.2.3