aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2016-10-05 05:11:21 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2016-10-10 08:20:34 -0400
commitfc605f1d8060133596bb6083fc4b7b306d1d5931 (patch)
tree3036ddd4e1667fc847ea8bea31cd22b712a79d2d
parent3f2d26643595973e835e8356ea90c7c15cb1b0f1 (diff)
mmc: sdhci: Fix SDHCI_QUIRK2_STOP_WITH_TC
Multi-block data transfers can specify the number of blocks either using a Set Block Count command (CMD23) or by sending a STOP command (CMD12) after the required number of blocks has transferred. CMD23 is preferred, but some cards don't support it. CMD12 with R1b response is used for writes, and R1 response for reads. Some SDHCI host controllers give a Transfer Complete (TC) interrupt for the STOP command (CMD12) whether or not a R1b response has been specified. The quirk SDHCI_QUIRK2_STOP_WITH_TC identifies those host controllers, but the implementation only considers the case where the TC interrupt arrives at the same time as the Command Complete (CC) interrupt. However, occasionally TC arrives before CC. That is harmless, but does generate an error message "Got data interrupt 0x00000002 even though no data operation was in progress". A simpler approach is to force R1b response onto all STOP commands, because SDHCI will handle TC before CC in the general case, so do that. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/sdhci.c14
1 files changed, 6 insertions, 8 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 48055666c655..3711813f5654 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1077,6 +1077,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
1077 /* Initially, a command has no error */ 1077 /* Initially, a command has no error */
1078 cmd->error = 0; 1078 cmd->error = 0;
1079 1079
1080 if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
1081 cmd->opcode == MMC_STOP_TRANSMISSION)
1082 cmd->flags |= MMC_RSP_BUSY;
1083
1080 /* Wait max 10 ms */ 1084 /* Wait max 10 ms */
1081 timeout = 10; 1085 timeout = 10;
1082 1086
@@ -2409,7 +2413,7 @@ static void sdhci_timeout_data_timer(unsigned long data)
2409 * * 2413 * *
2410\*****************************************************************************/ 2414\*****************************************************************************/
2411 2415
2412static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) 2416static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
2413{ 2417{
2414 if (!host->cmd) { 2418 if (!host->cmd) {
2415 /* 2419 /*
@@ -2453,11 +2457,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
2453 return; 2457 return;
2454 } 2458 }
2455 2459
2456 if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
2457 !(host->cmd->flags & MMC_RSP_BUSY) && !host->data &&
2458 host->cmd->opcode == MMC_STOP_TRANSMISSION)
2459 *mask &= ~SDHCI_INT_DATA_END;
2460
2461 if (intmask & SDHCI_INT_RESPONSE) 2460 if (intmask & SDHCI_INT_RESPONSE)
2462 sdhci_finish_command(host); 2461 sdhci_finish_command(host);
2463} 2462}
@@ -2680,8 +2679,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
2680 } 2679 }
2681 2680
2682 if (intmask & SDHCI_INT_CMD_MASK) 2681 if (intmask & SDHCI_INT_CMD_MASK)
2683 sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, 2682 sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
2684 &intmask);
2685 2683
2686 if (intmask & SDHCI_INT_DATA_MASK) 2684 if (intmask & SDHCI_INT_DATA_MASK)
2687 sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 2685 sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);