From: Micky Ching <micky_ch...@realsil.com.cn>

when card is work in SD4.0 mode, we should send tlp instead of cmd.
add this function to handle tlp request.

Signed-off-by: Micky Ching <micky_ch...@realsil.com.cn>
Signed-off-by: Wei Wang <wei_w...@realsil.com.cn>
---
 drivers/mmc/core/core.c | 111 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 104 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c296bc0..ebb6fea 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -45,6 +45,7 @@
 #include "mmc_ops.h"
 #include "sd_ops.h"
 #include "sdio_ops.h"
+#include "sd.h"
 
 /* If the device is not responding */
 #define MMC_CORE_TIMEOUT_MS    (10 * 60 * 1000) /* 10 minute timeout */
@@ -131,7 +132,42 @@ static inline void mmc_should_fail_request(struct mmc_host 
*host,
 void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
 {
        struct mmc_command *cmd = mrq->cmd;
-       int err = cmd->error;
+       struct mmc_tlp *tlp = mrq->tlp;
+       int err;
+
+       if (tlp && cmd)
+               pr_debug("%s: cmd and native tlp conflict, done native tlp\n",
+                       mmc_hostname(host));
+
+       if (tlp) {
+               err = tlp->error;
+               if (err && tlp->retries && !mmc_card_removed(host->card)) {
+                       /*
+                        * Request starter must handle retries - see
+                        * mmc_wait_for_req_done().
+                        */
+                       if (mrq->done)
+                               mrq->done(mrq);
+               } else {
+                       led_trigger_event(host->led, LED_OFF);
+
+                       pr_debug("%s: native TLP req done(%d) %04x %04x %08x 
%08x %08x %08x\n",
+                               mmc_hostname(host), err,
+                               tlp->tlp_back->header, tlp->tlp_back->argument,
+                               tlp->tlp_back->payload[0],
+                               tlp->tlp_back->payload[1],
+                               tlp->tlp_back->payload[2],
+                               tlp->tlp_back->payload[3]);
+
+                       if (mrq->done)
+                               mrq->done(mrq);
+
+                       mmc_host_clk_release(host);
+               }
+               return;
+       }
+
+       err = cmd->error;
 
        if (err && cmd->retries && mmc_host_is_spi(host)) {
                if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)
@@ -201,9 +237,18 @@ static int mmc_start_request(struct mmc_host *host, struct 
mmc_request *mrq)
                         mrq->sbc->arg, mrq->sbc->flags);
        }
 
-       pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
-                mmc_hostname(host), mrq->cmd->opcode,
-                mrq->cmd->arg, mrq->cmd->flags);
+       if (mrq->tlp && mrq->cmd)
+               pr_debug("%s: cmd and native tlp conflict, start native tlp\n",
+                       mmc_hostname(host));
+
+       if (mrq->tlp)
+               pr_debug("%s: starting native TLP header %04x argument %04x\n",
+                        mmc_hostname(host), mrq->tlp->tlp_send->header,
+                        mrq->tlp->tlp_send->argument);
+       else if (mrq->cmd)
+               pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
+                        mmc_hostname(host), mrq->cmd->opcode,
+                        mrq->cmd->arg, mrq->cmd->flags);
 
        if (mrq->data) {
                pr_debug("%s:     blksz %d blocks %d flags %08x "
@@ -221,6 +266,8 @@ static int mmc_start_request(struct mmc_host *host, struct 
mmc_request *mrq)
        }
 
        WARN_ON(!host->claimed);
+       if (!mrq->cmd)
+               goto start;
 
        mrq->cmd->error = 0;
        mrq->cmd->mrq = mrq;
@@ -250,6 +297,25 @@ static int mmc_start_request(struct mmc_host *host, struct 
mmc_request *mrq)
                        mrq->stop->mrq = mrq;
                }
        }
+
+       if (mmc_card_uhsii(host->card)) {
+               mrq->cmd->use_tlp = true;
+               if (mrq->data)
+                       mmc_sd_tran_pack_dcmd(host->card, mrq->cmd);
+               else
+                       mmc_sd_tran_pack_ccmd(host->card, mrq->cmd);
+
+               if (mrq->sbc) {
+                       mrq->sbc->use_tlp = true;
+                       mmc_sd_tran_pack_ccmd(host->card, mrq->sbc);
+               }
+               if (mrq->stop) {
+                       mrq->stop->use_tlp = true;
+                       mmc_sd_tran_pack_ccmd(host->card, mrq->stop);
+               }
+       }
+
+start:
        mmc_host_clk_hold(host);
        led_trigger_event(host->led, LED_FULL);
        host->ops->request(host, mrq);
@@ -356,7 +422,7 @@ static int __mmc_start_data_req(struct mmc_host *host, 
struct mmc_request *mrq)
 
        err = mmc_start_request(host, mrq);
        if (err) {
-               mrq->cmd->error = err;
+               mmc_set_mrq_error_code(mrq, err);
                mmc_wait_data_done(mrq);
        }
 
@@ -372,7 +438,7 @@ static int __mmc_start_req(struct mmc_host *host, struct 
mmc_request *mrq)
 
        err = mmc_start_request(host, mrq);
        if (err) {
-               mrq->cmd->error = err;
+               mmc_set_mrq_error_code(mrq, err);
                complete(&mrq->completion);
        }
 
@@ -436,7 +502,7 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,
        return err;
 }
 
-static void mmc_wait_for_req_done(struct mmc_host *host,
+static void mmc_wait_for_cmd_req_done(struct mmc_host *host,
                                  struct mmc_request *mrq)
 {
        struct mmc_command *cmd;
@@ -475,6 +541,37 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
        }
 }
 
+static void mmc_wait_for_tlp_req_done(struct mmc_host *host,
+                                 struct mmc_request *mrq)
+{
+       struct mmc_tlp *tlp;
+
+       while (1) {
+               wait_for_completion(&mrq->completion);
+
+               tlp = mrq->tlp;
+
+               if (!tlp->error || !tlp->retries ||
+                       mmc_card_removed(host->card))
+                       break;
+
+               pr_debug("%s: native TLP req failed: %d, retrying...\n",
+                       mmc_hostname(host), tlp->error);
+               tlp->retries--;
+               tlp->error = 0;
+               host->ops->request(host, mrq);
+       }
+}
+
+static void mmc_wait_for_req_done(struct mmc_host *host,
+       struct mmc_request *mrq)
+{
+       if (mrq->cmd)
+               mmc_wait_for_cmd_req_done(host, mrq);
+       else
+               mmc_wait_for_tlp_req_done(host, mrq);
+}
+
 /**
  *     mmc_pre_req - Prepare for a new request
  *     @host: MMC host to prepare command
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to