ARM: 7719/1: mmc: mmci: Support for CMD23
authorUlf Hansson <ulf.hansson@linaro.org>
Mon, 13 May 2013 14:40:56 +0000 (15:40 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 22 May 2013 23:07:03 +0000 (00:07 +0100)
Support added for transmission of CMD23 during multi block read or
write. In order to activate this feature, MMC_CAP_CMD23 flag needs
to be enabled in the capabilities field. Note that CMD23 support is
mandatory to support features like reliable write, data tag, context
ID, packed command.

This patch is based upon a patch from Saugata Das.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
drivers/mmc/host/mmci.c

index 5f53cf8..9df8b84 100644 (file)
@@ -848,7 +848,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
                        /* The error clause is handled above, success! */
                        data->bytes_xfered = data->blksz * data->blocks;
 
                        /* The error clause is handled above, success! */
                        data->bytes_xfered = data->blksz * data->blocks;
 
-               if (!data->stop) {
+               if (!data->stop || host->mrq->sbc) {
                        mmci_request_end(host, data->mrq);
                } else {
                        mmci_start_command(host, data->stop, 0);
                        mmci_request_end(host, data->mrq);
                } else {
                        mmci_start_command(host, data->stop, 0);
@@ -861,6 +861,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
             unsigned int status)
 {
        void __iomem *base = host->base;
             unsigned int status)
 {
        void __iomem *base = host->base;
+       bool sbc = (cmd == host->mrq->sbc);
 
        host->cmd = NULL;
 
 
        host->cmd = NULL;
 
@@ -875,7 +876,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
                cmd->resp[3] = readl(base + MMCIRESPONSE3);
        }
 
                cmd->resp[3] = readl(base + MMCIRESPONSE3);
        }
 
-       if (!cmd->data || cmd->error) {
+       if ((!sbc && !cmd->data) || cmd->error) {
                if (host->data) {
                        /* Terminate the DMA transfer */
                        if (dma_inprogress(host)) {
                if (host->data) {
                        /* Terminate the DMA transfer */
                        if (dma_inprogress(host)) {
@@ -884,7 +885,9 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
                        }
                        mmci_stop_data(host);
                }
                        }
                        mmci_stop_data(host);
                }
-               mmci_request_end(host, cmd->mrq);
+               mmci_request_end(host, host->mrq);
+       } else if (sbc) {
+               mmci_start_command(host, host->mrq->cmd, 0);
        } else if (!(cmd->data->flags & MMC_DATA_READ)) {
                mmci_start_data(host, cmd->data);
        }
        } else if (!(cmd->data->flags & MMC_DATA_READ)) {
                mmci_start_data(host, cmd->data);
        }
@@ -1125,7 +1128,10 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        if (mrq->data && mrq->data->flags & MMC_DATA_READ)
                mmci_start_data(host, mrq->data);
 
        if (mrq->data && mrq->data->flags & MMC_DATA_READ)
                mmci_start_data(host, mrq->data);
 
-       mmci_start_command(host, mrq->cmd, 0);
+       if (mrq->sbc)
+               mmci_start_command(host, mrq->sbc, 0);
+       else
+               mmci_start_command(host, mrq->cmd, 0);
 
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
        spin_unlock_irqrestore(&host->lock, flags);
 }