mmc: sdhci: Support cap_cmd_during_tfr requests
authorAdrian Hunter <adrian.hunter@intel.com>
Tue, 16 Aug 2016 10:44:13 +0000 (13:44 +0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 26 Sep 2016 19:31:29 +0000 (21:31 +0200)
Now SDHCI supports commands during transfer, enable support for the core
API.

There are 3 small changes needed:

First, auto-CMD12 cannot be used with a cap_cmd_during_tfr request because
the host controller cannot expect the command line to be available.

Secondly, a cap_cmd_during_tfr request must not send a stop command, again
because the host controller cannot expect the command line to be available.

Thirdly, when a cap_cmd_during_tfr command completes, use
mmc_command_complete() to notify the upper layers that the command line is
now available for further commands.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci.c

index 0851a4bba41387534bca1906fed41f7baff59da7..48055666c6557a98286dd6d07118c82a218f5c76 100644 (file)
@@ -888,7 +888,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
 static inline bool sdhci_auto_cmd12(struct sdhci_host *host,
                                    struct mmc_request *mrq)
 {
-       return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12);
+       return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) &&
+              !mrq->cap_cmd_during_tfr;
 }
 
 static void sdhci_set_transfer_mode(struct sdhci_host *host,
@@ -1031,9 +1032,18 @@ static void sdhci_finish_data(struct sdhci_host *host)
                        sdhci_do_reset(host, SDHCI_RESET_DATA);
                }
 
-               /* Avoid triggering warning in sdhci_send_command() */
-               host->cmd = NULL;
-               sdhci_send_command(host, data->stop);
+               /*
+                * 'cap_cmd_during_tfr' request must not use the command line
+                * after mmc_command_done() has been called. It is upper layer's
+                * responsibility to send the stop command if required.
+                */
+               if (data->mrq->cap_cmd_during_tfr) {
+                       sdhci_finish_mrq(host, data->mrq);
+               } else {
+                       /* Avoid triggering warning in sdhci_send_command() */
+                       host->cmd = NULL;
+                       sdhci_send_command(host, data->stop);
+               }
        } else {
                sdhci_finish_mrq(host, data->mrq);
        }
@@ -1165,6 +1175,9 @@ static void sdhci_finish_command(struct sdhci_host *host)
                }
        }
 
+       if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd)
+               mmc_command_done(host->mmc, cmd->mrq);
+
        /*
         * The host can send and interrupt when the busy state has
         * ended, allowing us to wait without wasting CPU cycles.