diff options
author | Sebastian Rasmussen <sebastian.rasmussen@stericsson.com> | 2011-04-11 11:28:22 +0200 |
---|---|---|
committer | Sebastian RASMUSSEN <sebastian.rasmussen@stericsson.com> | 2011-04-11 11:35:43 +0200 |
commit | 02f80f7843f665d552ab6fbe4445ba782e77ae36 (patch) | |
tree | 42d6ba967d91c9c9b3cf4f04b5f27fa64b396eb5 /drivers/mmc | |
parent | 7d92304ec4e34ea7e0af90f8a9a4f33526f8ce0d (diff) |
Revert "mmci: reorganize send request to split in"
This reverts commit 0c6eefa863a9415fbb3b96c5c533926d2708118e.
Change-Id: I1ce9c68006adfec95fae889fa3bfefda2111f2f5
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/20573
Reviewed-by: Sebastian RASMUSSEN <sebastian.rasmussen@stericsson.com>
Tested-by: Sebastian RASMUSSEN <sebastian.rasmussen@stericsson.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/mmci.c | 481 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.h | 65 |
2 files changed, 237 insertions, 309 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index b0c53445c84..023ecb29f5e 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -58,6 +58,8 @@ static unsigned int dataread_delay_clks = 7500000; * @txsize_threshold: Sets DMA burst size to minimal if transfer size is * less or equal to this threshold. This shall be specified in * number of bytes. Set 0 for no burst compensation + * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware + * and will not work at all. * @sdio: variant supports SDIO * @st_clkdiv: true if using a ST-specific clock divider algorithm * @pwrreg_powerup: power up value for MMCIPOWER register @@ -74,6 +76,7 @@ struct variant_data { unsigned int fifosize; unsigned int fifohalfsize; unsigned int txsize_threshold; + bool broken_blockend; bool sdio; bool st_clkdiv; unsigned int pwrreg_powerup; @@ -106,6 +109,7 @@ static struct variant_data variant_ux500 = { .clkreg_enable = 1 << 14, /* HWFCEN */ .dmareg_enable = 1 << 12, /* DMAREQCTRL */ .datalength_bits = 24, + .broken_blockend = true, .sdio = true, .st_clkdiv = true, .pwrreg_powerup = MCI_PWR_ON, @@ -335,6 +339,46 @@ static void mmci_stop_data(struct mmci_host *host) host->data = NULL; } +static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) +{ + unsigned int flags = SG_MITER_ATOMIC; + + if (data->flags & MMC_DATA_READ) + flags |= SG_MITER_TO_SG; + else + flags |= SG_MITER_FROM_SG; + + sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); +} + +static void +mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) +{ + void __iomem *base = host->base; + + dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n", + cmd->opcode, cmd->arg, cmd->flags); + + if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) { + writel(0, base + MMCICOMMAND); + udelay(1); + } + + c |= cmd->opcode | MCI_CPSM_ENABLE; + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) + c |= MCI_CPSM_LONGRSP; + c |= MCI_CPSM_RESPONSE; + } + if (/*interrupt*/0) + c |= MCI_CPSM_INTERRUPT; + + host->cmd = cmd; + + writel(cmd->arg, base + MMCIARGUMENT); + writel(c, base + MMCICOMMAND); +} + static void mmci_complete_data_xfer(struct mmci_host *host) { @@ -358,15 +402,6 @@ mmci_complete_data_xfer(struct mmci_host *host) } } -static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) -{ - unsigned int flags = SG_MITER_ATOMIC; - - flags |= data->flags & MMC_DATA_READ ? - SG_MITER_TO_SG : SG_MITER_FROM_SG; - sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); -} - /* * All the DMA operation mode stuff goes inside this ifdef. * This assumes that you have a generic DMA device interface, @@ -611,6 +646,148 @@ static inline int mmci_dma_start_data(struct mmci_host *host, } #endif +static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) +{ + struct variant_data *variant = host->variant; + unsigned int datactrl, timeout, irqmask0, irqmask1; + unsigned int clkcycle_ns; + void __iomem *base; + int blksz_bits; + u32 clk; + + dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n", + data->blksz, data->blocks, data->flags); + + host->data = data; + host->size = data->blksz * data->blocks; + host->data_xfered = 0; + host->last_blockend = false; + host->dataend = false; + host->cache_len = 0; + host->cache = 0; + + clkcycle_ns = 1000000000 / host->cclk; + timeout = data->timeout_ns / clkcycle_ns; + timeout += data->timeout_clks; + + if (data->flags & MMC_DATA_READ) { + /* + * Since the read command is sent after we have setup + * the data transfer we must increase the data timeout. + * Unfortunately this is not enough since some cards + * does not seem to stick to what is stated in their + * CSD for TAAC and NSAC. + */ + timeout += dataread_delay_clks; + } + + base = host->base; + writel(timeout, base + MMCIDATATIMER); + writel(host->size, base + MMCIDATALENGTH); + + blksz_bits = ffs(data->blksz) - 1; + +#ifdef CONFIG_ARCH_U8500 + /* Temporary solution for db8500v2. */ + if (cpu_is_u8500v20_or_later()) + datactrl = MCI_DPSM_ENABLE | (data->blksz << 16); + else +#endif + datactrl = MCI_DPSM_ENABLE | blksz_bits << 4; + + if (data->flags & MMC_DATA_READ) + datactrl |= MCI_DPSM_DIRECTION; + + if (host->mmc->card && mmc_card_ddr_mode(host->mmc->card)) { + datactrl |= MCI_ST_DPSM_DDRMODE; + + /* Needed for DDR */ + clk = readl(base + MMCICLOCK); + clk |= MCI_NEG_EDGE; + + writel(clk, (base + MMCICLOCK)); + } + + if (variant->sdio && + host->mmc->card && + mmc_card_sdio(host->mmc->card)) { + /* + * The ST Micro variants has a special bit + * to enable SDIO mode. This bit is set the first time + * a SDIO data transfer is done and must remain set + * after the data transfer is completed. The reason is + * because of otherwise no SDIO interrupts can be + * received. + */ + datactrl |= MCI_ST_DPSM_SDIOEN; + + /* + * The ST Micro variant for SDIO transfer sizes + * less than or equal to 8 bytes needs to have clock + * H/W flow control disabled. Since flow control is + * not really needed for anything that fits in the + * FIFO, we can disable it for any write smaller + * than the FIFO size. + */ + if ((host->size <= variant->fifosize) && + (data->flags & MMC_DATA_WRITE)) + writel(readl(host->base + MMCICLOCK) & + ~variant->clkreg_enable, + host->base + MMCICLOCK); + else + writel(readl(host->base + MMCICLOCK) | + variant->clkreg_enable, + host->base + MMCICLOCK); + } + + if (host->dma_enable) { + int ret; + + /* + * Attempt to use DMA operation mode, if this + * should fail, fall back to PIO mode + */ + ret = mmci_dma_start_data(host, datactrl); + if (!ret) + return; + } + + /* IRQ mode, map the SG list for CPU reading/writing */ + mmci_init_sg(host, data); + + if (data->flags & MMC_DATA_READ) { + irqmask1 = MCI_RXFIFOHALFFULLMASK; + + /* + * If we have less than a FIFOSIZE of bytes to + * transfer, trigger a PIO interrupt as soon as any + * data is available. + */ + if (host->size < variant->fifosize) + irqmask1 |= MCI_RXDATAAVLBLMASK; + } else { + /* + * We don't actually need to include "FIFO empty" here + * since its implicit in "FIFO half empty". + */ + irqmask1 = MCI_TXFIFOHALFEMPTYMASK; + } + + /* Setup IRQ */ + irqmask0 = readl(base + MMCIMASK0); + if (variant->broken_blockend) { + host->last_blockend = true; + irqmask0 &= ~MCI_DATABLOCKENDMASK; + } else { + irqmask0 |= MCI_DATABLOCKENDMASK; + } + writel(irqmask0, base + MMCIMASK0); + mmci_set_mask1(host, irqmask1); + + /* Start the data transfer */ + writel(datactrl, base + MMCIDATACTRL); +} + static void mmci_data_irq(struct mmci_host *host, struct mmc_data *data, unsigned int status) @@ -876,14 +1053,6 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, return ptr - buffer; } -static void mmci_start_data(struct mmci_host *host) -{ - writel(host->mmci_clockctrl, host->base + MMCICLOCK); - writel(host->mmci_datatimer, host->base + MMCIDATATIMER); - writel(host->mmci_datalenght, host->base + MMCIDATALENGTH); - writel(host->mmci_datactrl, host->base + MMCIDATACTRL); -} - /* * PIO data transfer IRQ handler. */ @@ -1021,225 +1190,16 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) return IRQ_RETVAL(ret); } -static int mmci_setup_data(struct mmci_host *host, struct mmc_data *data) -{ - unsigned int clkcycle_ns; - int blksz_bits; - - dev_dbg(mmc_dev(host->mmc), "[%s] blksz:%d nb_blk:%d sg_len:%d " - "ptr_sg:%p flags %08x\n", __func__, data->blksz, - data->blocks, data->sg_len, data->sg, data->flags); - - host->size = data->blksz * data->blocks; - host->pio_active = XFER_NONE; - - clkcycle_ns = 1000000000 / host->cclk; - host->mmci_datatimer = data->timeout_ns / clkcycle_ns; - host->mmci_datatimer += data->timeout_clks; - - blksz_bits = ffs(data->blksz) - 1; - - /*FIXME shift must be define */ -#ifdef CONFIG_ARCH_U8500 - /* Temporary solution for db8500v2. */ - if (cpu_is_u8500v20_or_later()) - host->mmci_datactrl = data->blksz << 16; - else -#endif - host->mmci_datactrl = blksz_bits << 4; - - if (data->flags & MMC_DATA_READ) { - host->mmci_datactrl |= MCI_DPSM_DIRECTION; - host->mmci_datatimer += dataread_delay_clks; - } - - host->mmci_datactrl |= MCI_DPSM_ENABLE; - - /* Needed for DDR */ - if (host->mmc->card && mmc_card_ddr_mode(host->mmc->card)) { - host->mmci_datactrl |= MCI_ST_DPSM_DDRMODE; - host->mmci_clockctrl |= MCI_NEG_EDGE; - } - - host->mmci_datalenght = data->blksz * data->blocks; - - /* irq mask */ - host->mmci_mask0 = MCI_DATACRCFAILMASK | MCI_DATATIMEOUTMASK | - MCI_TXUNDERRUNMASK | MCI_RXOVERRUNMASK | MCI_STARTBITERRMASK; - - return 0; -} - -static inline void mmci_prepare_sdio(struct mmci_host *host, - struct mmc_data *data) -{ - struct variant_data *variant = host->variant; - - /* The ST Micro variants: - * -has a special bit to enable SDIO. - * -for SDIO transfer sizes less then 8 bytes - * should have clock H/W flow control disabled. - */ - host->mmci_clockctrl |= variant->clkreg_enable; - if (variant->sdio && host->mmc->card) { - if (mmc_card_sdio(host->mmc->card)) { - host->mmci_datactrl |= MCI_ST_DPSM_SDIOEN; - if ((host->size <= variant->fifosize) && - (data->flags & MMC_DATA_WRITE)) - host->mmci_clockctrl &= ~variant->clkreg_enable; - else - host->mmci_clockctrl |= variant->clkreg_enable; - } - } -} - -static inline void mmci_prepare_pio(struct mmci_host *host, - struct mmc_data *data) -{ - struct variant_data *variant = host->variant; - u32 irqmask1 = 0; - int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0; - host->cache_len = 0; - host->cache = 0; - - host->pio_active = rw ? XFER_WRITE : XFER_READ; - - /* IRQ mode, map the SG list for CPU reading/writing */ - mmci_init_sg(host, data); - - /* FIXME - * if write case, perhaps we can preload the fifo - */ - if (data->flags & MMC_DATA_READ) { - irqmask1 |= MCI_RXFIFOHALFFULLMASK; - /* - * If we have less than a FIFOSIZE of bytes to - * transfer, trigger a PIO interrupt as soon as any - * data is available. - */ - if (host->size < variant->fifosize) - irqmask1 |= MCI_RXDATAAVLBLMASK; - } else { - /* - * We don't actually need to include "FIFO empty" here - * since its implicit in "FIFO half empty". - */ - irqmask1 |= MCI_TXFIFOHALFEMPTYMASK; - } - - host->mmci_mask0 &= ~MCI_DATAENDMASK; - mmci_set_mask1(host, irqmask1); -} - -static void mmci_prepare_data(struct mmci_host *host, - struct mmc_data *data) -{ - int res = 0; - - mmci_prepare_sdio(host, data); - - /* - * Attempt to use DMA operation mode, if this - * should fail, fall back to PIO mode - */ - if (host->dma_enable) { - res = mmci_prepare_dma(host, data); - if (!res) { - host->dma_complete = COMPLETION_DMA_START; - return; - } else { - host->dma_complete = COMPLETION_DMA_NONE; - dev_dbg(mmc_dev(host->mmc), - "prepare dma error %d.\n", res); - host->mmci_datactrl &= ~MCI_DPSM_DMAENABLE; - host->mmci_datactrl &= ~host->variant->dmareg_enable; - } - } - - mmci_prepare_pio(host, data); -} - -static void mmci_prepare_command(struct mmci_host *host, - struct mmc_command *cmd) -{ - host->mmci_mask0 |= MCI_CMDTIMEOUTMASK | MCI_CMDCRCFAILMASK; - - if (cmd->data) - host->complete_what = COMPLETION_XFERFINISH_RSPFIN; - else if (cmd->flags & MMC_RSP_PRESENT) - host->complete_what = COMPLETION_RSPFIN; - else - host->complete_what = COMPLETION_CMDSENT; - - host->mmci_argument = cmd->arg; - host->mmci_command = cmd->opcode | MCI_CPSM_ENABLE; - - if (cmd->flags & MMC_RSP_PRESENT) { - host->mmci_command |= MCI_CPSM_RESPONSE; - host->mmci_mask0 |= MCI_CMDRESPENDMASK; - if (cmd->flags & MMC_RSP_136) - host->mmci_command |= MCI_CPSM_LONGRSP; - } else - host->mmci_mask0 |= MCI_CMDSENTMASK; -} - -static void mmci_send_command(struct mmci_host *host) -{ - writel(host->mmci_argument, host->base + MMCIARGUMENT); - writel(host->mmci_command, host->base + MMCICOMMAND); -} - -static void mmci_send_request(struct mmc_host *mmc) -{ - struct mmci_host *host = mmc_priv(mmc); - struct mmc_request *mrq = host->mrq; - struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd; - int res; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - - /* Clear mmci status and mask registers */ - writel(0x7ff, host->base + MMCICLEAR); - clear_imasks(host); - - if (cmd->data) { - res = mmci_setup_data(host, cmd->data); - if (res) { - dev_err(mmc_dev(mmc), "data setup error %d.\n", res); - goto err_data; - } - - mmci_prepare_data(host, cmd->data); - - if (cmd->data->flags & MMC_DATA_READ) - mmci_start_data(host); - } - - mmci_prepare_command(host, cmd); - enable_imasks(host); - mmci_send_command(host); - - spin_unlock_irqrestore(&host->lock, flags); - - return; - -err_data: - cmd->error = res; - cmd->data->error = res; - mmc_request_done(mmc, mrq); - return; -} - static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct mmci_host *host = mmc_priv(mmc); - host->cmd_is_stop = 0; + struct variant_data *variant = host->variant; + unsigned long flags; WARN_ON(host->mrq != NULL); if (mrq->data && - (!host->variant->non_power_of_2_blksize || + (!variant->non_power_of_2_blksize || #ifdef CONFIG_ARCH_U8500 !cpu_is_u8500v20_or_later() || #endif @@ -1252,9 +1212,16 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) return; } + spin_lock_irqsave(&host->lock, flags); + host->mrq = mrq; - host->stat.nb_core_req++; - mmci_send_request(mmc); + + if (mrq->data && mrq->data->flags & MMC_DATA_READ) + mmci_start_data(host, mrq->data); + + mmci_start_command(host, mrq->cmd, 0); + + spin_unlock_irqrestore(&host->lock, flags); } static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) @@ -1354,7 +1321,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (host->pwr != pwr) { host->pwr = pwr; - host->mmci_power = pwr; writel(pwr, host->base + MMCIPOWER); } @@ -1431,9 +1397,10 @@ static int mmci_enable(struct mmc_host *mmc) writel(MCI_ST_DPSM_SDIOEN, host->base + MMCIDATACTRL); } - /* Restore registers for POWER and CLOCK. */ - writel(host->mmci_power, host->base + MMCIPOWER); - writel(host->mmci_clockctrl, host->base + MMCICLOCK); + /* Restore registers for POWER, CLOCK and IRQMASK0 */ + writel(host->irqmask0_reg, host->base + MMCIMASK0); + writel(host->pwr_reg, host->base + MMCIPOWER); + writel(host->clk_reg, host->base + MMCICLOCK); spin_unlock_irqrestore(&host->lock, flags); @@ -1454,13 +1421,18 @@ static int mmci_disable(struct mmc_host *mmc, int lazy) spin_lock_irqsave(&host->lock, flags); + /* Save registers for POWER, CLOCK and IRQMASK0 */ + host->irqmask0_reg = readl(host->base + MMCIMASK0); + host->pwr_reg = readl(host->base + MMCIPOWER); + host->clk_reg = readl(host->base + MMCICLOCK); + /* - * Make sure we do not get any interrupts when disable is done - * of the clock and the regulator. Especially important for SDIO + * Make sure we do not get any interrupts when we disabled the + * clock and the regulator. Especially important for SDIO * interrupts, since they may occur even without any active * request handling ongoing. */ - disable_imasks(host); + writel(0, host->base + MMCIMASK0); spin_unlock_irqrestore(&host->lock, flags); @@ -1546,6 +1518,10 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) host->gpio_cd = -ENOSYS; host->gpio_cd_irq = -1; + host->irqmask0_reg = 0; + host->pwr_reg = 0; + host->clk_reg = 0; + host->hw_designer = amba_manf(dev); host->hw_revision = amba_rev(dev); dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer); @@ -1708,11 +1684,9 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) && host->gpio_cd_irq < 0) mmc->caps |= MMC_CAP_NEEDS_POLL; - ret = mmci_setup_dma(host); - if (ret) - mmci_disable_dma(host); + mmci_setup_dma(host); - ret = request_irq(dev->irq[0], mmci_irq, 0, + ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); if (ret) goto unmap; @@ -1720,19 +1694,20 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) if (dev->irq[1] == NO_IRQ) host->singleirq = true; else { - ret = request_irq(dev->irq[1], mmci_pio_irq, 0, + ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host); if (ret) goto irq0_free; } + /* Prepare IRQMASK0 */ + host->irqmask0_reg = MCI_IRQENABLE; + if (host->variant->broken_blockend) + host->irqmask0_reg &= ~MCI_DATABLOCKEND; + amba_set_drvdata(dev, mmc); - ret = mmc_add_host(mmc); - if (ret) { - dev_err(mmc_dev(host->mmc), "failed to add mmc host.\n"); - goto irq0_free; - } + mmc_add_host(mmc); dev_info(&dev->dev, "%s: MMCI/PL180 manf %x rev %x cfg %02x at 0x%016llx\n", @@ -1743,9 +1718,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) /* Ugly hack for u8500_sdio_detect_card, to be removed soon. */ sdio_host_ptr = host; - tasklet_init(&host->mmci_tasklet, - mmci_tasklet, (unsigned long) host); - mmci_debugfs_create(host); return 0; @@ -1791,7 +1763,8 @@ static int __devexit mmci_remove(struct amba_device *dev) mmci_debugfs_remove(host); mmc_remove_host(mmc); - disable_imasks(host); + writel(0, host->base + MMCIMASK0); + writel(0, host->base + MMCIMASK1); writel(0, host->base + MMCICOMMAND); writel(0, host->base + MMCIDATACTRL); @@ -1858,8 +1831,8 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state) mmc_host_enable(mmc); mmc_power_save_host(mmc); mmc_host_disable(mmc); - host->mmci_power = 0; - host->mmci_clockctrl = 0; + host->pwr_reg = 0; + host->clk_reg = 0; } } else { diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 6216aa34e55..87d35cc1fea 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -78,7 +78,6 @@ #define MCI_CMDRESPEND (1 << 6) #define MCI_CMDSENT (1 << 7) #define MCI_DATAEND (1 << 8) -#define MCI_STARTBITERR (1 << 9) #define MCI_DATABLOCKEND (1 << 10) #define MCI_CMDACTIVE (1 << 11) #define MCI_TXACTIVE (1 << 12) @@ -104,7 +103,6 @@ #define MCI_CMDRESPENDCLR (1 << 6) #define MCI_CMDSENTCLR (1 << 7) #define MCI_DATAENDCLR (1 << 8) -#define MCI_STARTBITERRCLR (1 << 9) #define MCI_DATABLOCKENDCLR (1 << 10) #define MCI_SDIOITC (1 << 22) #define MCI_CEATAENDC (1 << 23) @@ -119,7 +117,6 @@ #define MCI_CMDRESPENDMASK (1 << 6) #define MCI_CMDSENTMASK (1 << 7) #define MCI_DATAENDMASK (1 << 8) -#define MCI_STARTBITERRMASK (1 << 9) #define MCI_DATABLOCKENDMASK (1 << 10) #define MCI_CMDACTIVEMASK (1 << 11) #define MCI_TXACTIVEMASK (1 << 12) @@ -162,38 +159,12 @@ struct variant_data; struct dma_chan; struct dma_async_tx_descriptor; -enum mmci_dma_complete{ - COMPLETION_DMA_NONE, - COMPLETION_DMA_START, - COMPLETION_DMA_XFERFINISH, -}; - -enum mmci_waitfor { - COMPLETION_NONE, - COMPLETION_FINALIZE, - COMPLETION_REQ, - COMPLETION_CMDSENT, - COMPLETION_RSPFIN, - COMPLETION_XFERFINISH, - COMPLETION_XFERFINISH_RSPFIN, -}; - -struct mmci_stat{ - unsigned long nb_core_req; - unsigned long nb_cmdcrcfail; - unsigned long nb_rxoverrun; - unsigned long nb_txunderrun; - unsigned long nb_datacrcfail; - unsigned long nb_datatimeout; - unsigned long nb_startbiterr; - unsigned long nb_dma_err; -}; - struct mmci_host { phys_addr_t phybase; void __iomem *base; struct mmc_request *mrq; struct mmc_command *cmd; + struct mmc_data *data; struct mmc_host *mmc; struct clk *clk; int gpio_cd; @@ -217,6 +188,14 @@ struct mmci_host { struct timer_list timer; unsigned int oldstat; + bool last_blockend; + bool dataend; + + /* register cache */ + unsigned int irqmask0_reg; + unsigned int pwr_reg; + unsigned int clk_reg; + /* pio stuff */ struct sg_mapping_iter sg_miter; unsigned int size; @@ -235,32 +214,8 @@ struct mmci_host { struct dma_async_tx_descriptor *dma_desc; #endif - struct tasklet_struct mmci_tasklet; - enum mmci_waitfor complete_what; - enum mmci_dma_complete dma_complete; - - int cmd_is_stop; - -#define XFER_NONE 0 -#define XFER_READ 1 -#define XFER_WRITE 2 - u32 pio_active; - - /* mmci registers*/ - u32 mmci_command; - u32 mmci_argument; - - u32 mmci_mask0; - u32 mmci_mask1; - - u32 mmci_datatimer; - u32 mmci_datalenght; - u32 mmci_datactrl; - u32 mmci_clockctrl; - u32 mmci_power; - - struct mmci_stat stat; #ifdef CONFIG_DEBUG_FS struct dentry *debug_regs; #endif }; + |