mmc: meson-gx: add CMD23 mode
authorHeiner Kallweit <hkallweit1@gmail.com>
Sat, 25 Mar 2017 10:28:13 +0000 (11:28 +0100)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 24 Apr 2017 19:41:51 +0000 (21:41 +0200)
CMD23 mode (use "set block count" command before transferring multiple
data blocks) typically is more performant as host / card know upfront
how many data blocks to expect. Therefore add support for this mode to
the driver.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/meson-gx-mmc.c

index 810b68d5067b18e08ad50986a7b2acef72e083b1..f5dd5cc7104077e5fbbaeb4d745ddb25327c559b 100644 (file)
@@ -175,6 +175,17 @@ static unsigned int meson_mmc_get_timeout_msecs(struct mmc_data *data)
        return min(timeout, 32768U); /* max. 2^15 ms */
 }
 
+static struct mmc_command *meson_mmc_get_next_command(struct mmc_command *cmd)
+{
+       if (cmd->opcode == MMC_SET_BLOCK_COUNT && !cmd->error)
+               return cmd->mrq->cmd;
+       else if (mmc_op_multi(cmd->opcode) &&
+                (!cmd->mrq->sbc || cmd->error || cmd->data->error))
+               return cmd->mrq->stop;
+       else
+               return NULL;
+}
+
 static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
 {
        struct mmc_host *mmc = host->mmc;
@@ -620,7 +631,7 @@ out:
 static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
 {
        struct meson_host *host = dev_id;
-       struct mmc_command *cmd = host->cmd;
+       struct mmc_command *next_cmd, *cmd = host->cmd;
        struct mmc_data *data;
        unsigned int xfer_bytes;
 
@@ -635,10 +646,11 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
                                    host->bounce_buf, xfer_bytes);
        }
 
-       if (!data || !data->stop || cmd->mrq->sbc)
-               meson_mmc_request_done(host->mmc, cmd->mrq);
+       next_cmd = meson_mmc_get_next_command(cmd);
+       if (next_cmd)
+               meson_mmc_start_cmd(host->mmc, next_cmd);
        else
-               meson_mmc_start_cmd(host->mmc, data->stop);
+               meson_mmc_request_done(host->mmc, cmd->mrq);
 
        return IRQ_HANDLED;
 }
@@ -750,6 +762,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        if (ret)
                goto err_div_clk;
 
+       mmc->caps |= MMC_CAP_CMD23;
        mmc->max_blk_count = CMD_CFG_LENGTH_MASK;
        mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size;