]>
Commit | Line | Data |
---|---|---|
b3fe817e SL |
1 | From 413bdc69fdc13745967d82cfe3bb59a03949b522 Mon Sep 17 00:00:00 2001 |
2 | From: Adrian Hunter <adrian.hunter@intel.com> | |
3 | Date: Thu, 15 Nov 2018 15:53:43 +0200 | |
4 | Subject: mmc: sdhci: Handle auto-command errors | |
5 | ||
6 | [ Upstream commit af849c86109d79222e549826068bbf4e7f9a2472 ] | |
7 | ||
8 | If the host controller supports auto-commands then enable the auto-command | |
9 | error interrupt and handle it. In the case of auto-CMD23, the error is | |
10 | treated the same as manual CMD23 error. In the case of auto-CMD12, | |
11 | commands-during-transfer are not permitted, so the error handling is | |
12 | treated the same as a data error. | |
13 | ||
14 | Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> | |
15 | Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> | |
16 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
17 | --- | |
18 | drivers/mmc/host/sdhci.c | 35 +++++++++++++++++++++++++++++++++++ | |
19 | drivers/mmc/host/sdhci.h | 7 ++++++- | |
20 | 2 files changed, 41 insertions(+), 1 deletion(-) | |
21 | ||
22 | diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c | |
23 | index 0eb05a42a857..c749d3dc1d36 100644 | |
24 | --- a/drivers/mmc/host/sdhci.c | |
25 | +++ b/drivers/mmc/host/sdhci.c | |
26 | @@ -841,6 +841,11 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) | |
27 | else | |
28 | host->ier = (host->ier & ~dma_irqs) | pio_irqs; | |
29 | ||
30 | + if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12)) | |
31 | + host->ier |= SDHCI_INT_AUTO_CMD_ERR; | |
32 | + else | |
33 | + host->ier &= ~SDHCI_INT_AUTO_CMD_ERR; | |
34 | + | |
35 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | |
36 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | |
37 | } | |
38 | @@ -2642,6 +2647,21 @@ static void sdhci_timeout_data_timer(struct timer_list *t) | |
39 | ||
40 | static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) | |
41 | { | |
42 | + /* Handle auto-CMD12 error */ | |
43 | + if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd) { | |
44 | + struct mmc_request *mrq = host->data_cmd->mrq; | |
45 | + u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); | |
46 | + int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? | |
47 | + SDHCI_INT_DATA_TIMEOUT : | |
48 | + SDHCI_INT_DATA_CRC; | |
49 | + | |
50 | + /* Treat auto-CMD12 error the same as data error */ | |
51 | + if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { | |
52 | + *intmask_p |= data_err_bit; | |
53 | + return; | |
54 | + } | |
55 | + } | |
56 | + | |
57 | if (!host->cmd) { | |
58 | /* | |
59 | * SDHCI recovers from errors by resetting the cmd and data | |
60 | @@ -2676,6 +2696,21 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) | |
61 | return; | |
62 | } | |
63 | ||
64 | + /* Handle auto-CMD23 error */ | |
65 | + if (intmask & SDHCI_INT_AUTO_CMD_ERR) { | |
66 | + struct mmc_request *mrq = host->cmd->mrq; | |
67 | + u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); | |
68 | + int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? | |
69 | + -ETIMEDOUT : | |
70 | + -EILSEQ; | |
71 | + | |
72 | + if (mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { | |
73 | + mrq->sbc->error = err; | |
74 | + sdhci_finish_mrq(host, mrq); | |
75 | + return; | |
76 | + } | |
77 | + } | |
78 | + | |
79 | if (intmask & SDHCI_INT_RESPONSE) | |
80 | sdhci_finish_command(host); | |
81 | } | |
82 | diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h | |
83 | index 33a7728c71fa..0f8c4f3ccafc 100644 | |
84 | --- a/drivers/mmc/host/sdhci.h | |
85 | +++ b/drivers/mmc/host/sdhci.h | |
86 | @@ -151,7 +151,8 @@ | |
87 | #define SDHCI_INT_ERROR_MASK 0xFFFF8000 | |
88 | ||
89 | #define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ | |
90 | - SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) | |
91 | + SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | \ | |
92 | + SDHCI_INT_AUTO_CMD_ERR) | |
93 | #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ | |
94 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ | |
95 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ | |
96 | @@ -167,6 +168,10 @@ | |
97 | #define SDHCI_CQE_INT_MASK (SDHCI_CQE_INT_ERR_MASK | SDHCI_INT_CQE) | |
98 | ||
99 | #define SDHCI_AUTO_CMD_STATUS 0x3C | |
100 | +#define SDHCI_AUTO_CMD_TIMEOUT 0x00000002 | |
101 | +#define SDHCI_AUTO_CMD_CRC 0x00000004 | |
102 | +#define SDHCI_AUTO_CMD_END_BIT 0x00000008 | |
103 | +#define SDHCI_AUTO_CMD_INDEX 0x00000010 | |
104 | ||
105 | #define SDHCI_HOST_CONTROL2 0x3E | |
106 | #define SDHCI_CTRL_UHS_MASK 0x0007 | |
107 | -- | |
108 | 2.19.1 | |
109 |