--- sdhc.c.~1.32.~ 2012-11-19 02:42:09.000000000 +0000 +++ sdhc.c 2012-12-11 23:27:59.000000000 +0000 @@ -1512,18 +1512,47 @@ DPRINTF(1,("%s: software reset reg=%08x\n", HDEVNAME(hp), mask)); - HWRITE1(hp, SDHC_SOFTWARE_RESET, mask); - for (timo = 10; timo > 0; timo--) { - if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask)) - break; - sdmmc_delay(10000); - HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); - } - if (timo == 0) { - DPRINTF(1,("%s: timeout reg=%08x\n", HDEVNAME(hp), - HREAD1(hp, SDHC_SOFTWARE_RESET))); - HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); - return ETIMEDOUT; + /* + * The DAT and CMD resets require a little dance to wait for + * the reset to begin. + */ + if (mask & (SDHC_RESET_DAT | SDHC_RESET_CMD)) { + /* Request the reset. */ + HWRITE1(hp, SDHC_SOFTWARE_RESET, mask); + + /* Wait until the reset has begun. */ + /* XXX This seems fragile...what if we miss it? */ + for (timo = 1000; timo > 0; timo--) + if (HREAD1(hp, SDHC_SOFTWARE_RESET) & mask) + break; + if (timo == 0) + return ETIMEDOUT; + + /* Wait until the reset has finished. */ + for (timo = 10; timo > 0; timo--) { + if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask)) + break; + sdmmc_delay(10000); + } + if (timo == 0) + return ETIMEDOUT; + } else { + /* Request the reset. */ + HWRITE1(hp, SDHC_SOFTWARE_RESET, mask); + + /* Wait until the reset has finished. */ + for (timo = 10; timo > 0; timo--) { + if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask)) + break; + sdmmc_delay(10000); + HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); + } + if (timo == 0) { + DPRINTF(1,("%s: timeout reg=%08x\n", HDEVNAME(hp), + HREAD1(hp, SDHC_SOFTWARE_RESET))); + HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); + return ETIMEDOUT; + } } if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) { @@ -1554,7 +1583,7 @@ DPRINTF(2,("%s: intr status %#x error %#x\n", HDEVNAME(hp), status, hp->intr_error_status)); - + /* Command timeout has higher priority than command complete. */ if (ISSET(status, SDHC_ERROR_INTERRUPT) || hp->intr_error_status) { hp->intr_error_status = 0; @@ -1612,7 +1641,7 @@ HWRITE2(hp, SDHC_EINTR_STATUS, error); } } - + DPRINTF(2,("%s: interrupt status=%x error=%x\n", HDEVNAME(hp), status, error));