aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebastian.rasmussen@stericsson.com>2011-04-11 11:28:22 +0200
committerSebastian RASMUSSEN <sebastian.rasmussen@stericsson.com>2011-04-11 11:35:43 +0200
commit02f80f7843f665d552ab6fbe4445ba782e77ae36 (patch)
tree42d6ba967d91c9c9b3cf4f04b5f27fa64b396eb5 /drivers/mmc
parent7d92304ec4e34ea7e0af90f8a9a4f33526f8ce0d (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.c481
-rw-r--r--drivers/mmc/host/mmci.h65
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
};
+