]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
mmc: sdhci: Rework SDHCI_QUIRK_BROKEN_R1B
authorSean Anderson <sean.anderson@seco.com>
Fri, 27 Oct 2023 20:57:03 +0000 (16:57 -0400)
committerJaehoon Chung <jh80.chung@samsung.com>
Wed, 1 Nov 2023 01:01:10 +0000 (10:01 +0900)
As noted in commit 3a6383207be ("mmc: sdhci: add the quirk for broken
r1b response"), some MMC controllers don't always set the transfer
complete bit with R1b responses.

According to the SD Host Controller Simplified Specification v4.20,

> In the case of a command pairing with response-with-busy[, Transfer
> Complete] is set when busy is de-asserted. Refer to DAT Line Active
> and Command Inhibit (DAT) in the Present State register.

By polling the DAT Line Active bit in the present state register, we can
detect when we are no longer busy, without waiting for a long timeout.
This results in much faster reads/writes on buggy controllers.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Tested-by: Henrik Grimler <henrik@grimler.se>
drivers/mmc/sdhci.c
include/sdhci.h

index fc9c6c379964d7dbfebb2d5ef6ccc280dfdb5643..0178ed8a11e1235b45a5b3ec49a7fee2a32c75c7 100644 (file)
@@ -306,14 +306,19 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
                if (stat & SDHCI_INT_ERROR)
                        break;
 
-               if (get_timer(start) >= SDHCI_READ_STATUS_TIMEOUT) {
-                       if (host->quirks & SDHCI_QUIRK_BROKEN_R1B) {
+               if (host->quirks & SDHCI_QUIRK_BROKEN_R1B &&
+                   cmd->resp_type & MMC_RSP_BUSY && !data) {
+                       unsigned int state =
+                               sdhci_readl(host, SDHCI_PRESENT_STATE);
+
+                       if (!(state & SDHCI_DAT_ACTIVE))
                                return 0;
-                       } else {
-                               printf("%s: Timeout for status update!\n",
-                                      __func__);
-                               return -ETIMEDOUT;
-                       }
+               }
+
+               if (get_timer(start) >= SDHCI_READ_STATUS_TIMEOUT) {
+                       printf("%s: Timeout for status update: %08x %08x\n",
+                              __func__, stat, mask);
+                       return -ETIMEDOUT;
                }
        } while ((stat & mask) != mask);
 
index 70fefca2a9729f007c19019725f4fae99648dc45..a1b74e3bd79905e165a2c55421a516c9a7ebce34 100644 (file)
@@ -57,6 +57,7 @@
 #define SDHCI_PRESENT_STATE    0x24
 #define  SDHCI_CMD_INHIBIT     BIT(0)
 #define  SDHCI_DATA_INHIBIT    BIT(1)
+#define  SDHCI_DAT_ACTIVE      BIT(2)
 #define  SDHCI_DOING_WRITE     BIT(8)
 #define  SDHCI_DOING_READ      BIT(9)
 #define  SDHCI_SPACE_AVAILABLE BIT(10)