aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <loos@FreeBSD.org>2017-05-09 19:01:57 +0000
committerLuiz Otavio O Souza <loos@FreeBSD.org>2017-05-09 19:01:57 +0000
commit915780d7642db2677a54d56cc3cfbbfe3f849b6a (patch)
tree82d277e8bc9831dea933de7e159a4291bac39c5b
parentda880f61cabe70119930bf3eb12a04ac7db51c3b (diff)
downloadsrc-915780d7642db2677a54d56cc3cfbbfe3f849b6a.tar.gz
src-915780d7642db2677a54d56cc3cfbbfe3f849b6a.zip
Add a new SDHCI quirk, SDHCI_QUIRK_BROKEN_AUTO_STOP, to workaround
controllers that do not support or have broken ACMD12 implementations. Reviewed by: jmcneill Obtained from: NetBSD MFC after: 2 weeks Sponsored by: Rubicon Communications, LLC (Netgate) Differential Revision: https://reviews.freebsd.org/D10602
Notes
Notes: svn path=/head/; revision=318095
-rw-r--r--sys/dev/sdhci/sdhci.c14
-rw-r--r--sys/dev/sdhci/sdhci.h2
2 files changed, 10 insertions, 6 deletions
diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c
index 26602ec57b4c..68ff1db715b1 100644
--- a/sys/dev/sdhci/sdhci.c
+++ b/sys/dev/sdhci/sdhci.c
@@ -1060,7 +1060,7 @@ sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data)
mode |= SDHCI_TRNS_MULTI;
if (data->flags & MMC_DATA_READ)
mode |= SDHCI_TRNS_READ;
- if (slot->req->stop)
+ if (slot->req->stop && !(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP))
mode |= SDHCI_TRNS_ACMD12;
if (slot->flags & SDHCI_USE_DMA)
mode |= SDHCI_TRNS_DMA;
@@ -1305,7 +1305,8 @@ sdhci_finish_data(struct sdhci_slot *slot)
slot->intmask |= SDHCI_INT_RESPONSE);
}
/* Unload rest of data from DMA buffer. */
- if (!slot->data_done && (slot->flags & SDHCI_USE_DMA)) {
+ if (!slot->data_done && (slot->flags & SDHCI_USE_DMA) &&
+ slot->curcmd->data != NULL) {
if (data->flags & MMC_DATA_READ) {
left = data->len - slot->offset;
bus_dmamap_sync(slot->dmatag, slot->dmamap,
@@ -1343,17 +1344,18 @@ sdhci_start(struct sdhci_slot *slot)
sdhci_start_command(slot, req->cmd);
return;
}
-/* We don't need this until using Auto-CMD12 feature
- if (!(slot->flags & STOP_STARTED) && req->stop) {
+ if ((slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP) &&
+ !(slot->flags & STOP_STARTED) && req->stop) {
slot->flags |= STOP_STARTED;
sdhci_start_command(slot, req->stop);
return;
}
-*/
if (sdhci_debug > 1)
slot_printf(slot, "result: %d\n", req->cmd->error);
if (!req->cmd->error &&
- (slot->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) {
+ ((slot->curcmd == req->stop &&
+ (slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP)) ||
+ (slot->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
sdhci_reset(slot, SDHCI_RESET_CMD);
sdhci_reset(slot, SDHCI_RESET_DATA);
}
diff --git a/sys/dev/sdhci/sdhci.h b/sys/dev/sdhci/sdhci.h
index 0b299150b990..814f81ed5407 100644
--- a/sys/dev/sdhci/sdhci.h
+++ b/sys/dev/sdhci/sdhci.h
@@ -87,6 +87,8 @@
#define SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 (1 << 26)
/* Controller support for SDHCI_CTRL2_PRESET_VALUE is broken. */
#define SDHCI_QUIRK_PRESET_VALUE_BROKEN (1 << 27)
+/* Controller does not support or the support for ACMD12 is broken. */
+#define SDHCI_QUIRK_BROKEN_AUTO_STOP (1 << 28)
/*
* Controller registers