summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-12-20 01:13:13 +0000
committerian <ian@FreeBSD.org>2014-12-20 01:13:13 +0000
commit7814dfac2fc976412cebca6c48d0b949f495c1c1 (patch)
treeff1a6817bca2c031c02e20ad2184b75062530784 /sys/arm
parentf2e6cf3c8743406f318dbc756d18cd6bf9fb3509 (diff)
downloadFreeBSD-src-7814dfac2fc976412cebca6c48d0b949f495c1c1.zip
FreeBSD-src-7814dfac2fc976412cebca6c48d0b949f495c1c1.tar.gz
Add a new sdhci quirk, SDHCI_QUIRK_WAITFOR_RESET_ASSERTED, to work around
TI OMAP controllers which will return the reset-in-progress bit as zero if you read the status register too fast after setting the reset bit. The zero is apparently from a stale snapshot of the internal state presented in the interface register, and leads to a false indication that the reset is complete when it either hasn't started yet or is in-progress. The workaround is to first loop until the bit is seen as asserted, then do the normal loop waiting to see it de-asserted. Submitted by: Michal Meloun <meloun@miracle.cz>
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/ti/ti_sdhci.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/sys/arm/ti/ti_sdhci.c b/sys/arm/ti/ti_sdhci.c
index 6db13c3..380a40e 100644
--- a/sys/arm/ti/ti_sdhci.c
+++ b/sys/arm/ti/ti_sdhci.c
@@ -413,9 +413,27 @@ ti_sdhci_hw_init(device_t dev)
DELAY(100);
}
- /* Reset both the command and data state machines */
+ /*
+ * Reset the command and data state machines and also other aspects of
+ * the controller such as bus clock and power.
+ *
+ * If we read the software reset register too fast after writing it we
+ * can get back a zero that means the reset hasn't started yet rather
+ * than that the reset is complete. Per TI recommendations, work around
+ * it by reading until we see the reset bit asserted, then read until
+ * it's clear. We also set the SDHCI_QUIRK_WAITFOR_RESET_ASSERTED quirk
+ * so that the main sdhci driver uses this same logic in its resets.
+ */
ti_sdhci_write_1(dev, NULL, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL);
- timeout = 1000;
+ timeout = 10000;
+ while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) &
+ SDHCI_RESET_ALL) != SDHCI_RESET_ALL) {
+ if (--timeout == 0) {
+ break;
+ }
+ DELAY(1);
+ }
+ timeout = 10000;
while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) &
SDHCI_RESET_ALL)) {
if (--timeout == 0) {
@@ -583,6 +601,12 @@ ti_sdhci_attach(device_t dev)
sc->slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE;
/*
+ * Reset bits are broken, have to wait to see the bits asserted
+ * before waiting to see them de-asserted.
+ */
+ sc->slot.quirks |= SDHCI_QUIRK_WAITFOR_RESET_ASSERTED;
+
+ /*
* DMA is not really broken, I just haven't implemented it yet.
*/
sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA;
OpenPOWER on IntegriCloud