mmc: sdhci: Rework SDHCI_QUIRK_BROKEN_R1B

As noted in commit 3a6383207b ("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>
This commit is contained in:
Sean Anderson 2023-10-27 16:57:03 -04:00 committed by Jaehoon Chung
parent c27c8102e1
commit 21c84bb111
2 changed files with 13 additions and 7 deletions

View 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);

View 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)