diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2006-07-30 16:40:28 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2006-07-30 16:40:28 +0000 |
commit | 1b7c2a6be07ff60c68c501ef9e2729b519a3d85c (patch) | |
tree | 534e667993619de5767faadc51e14c4642f2971c /sys | |
parent | 169e70e80afebd781d28e396e81ef57692eded9e (diff) |
o Change sdhc_soft_reset() to pass the bits we want to reset and wait
until all bits are cleared.
o Change sdhc_host_reset() to use the above function and use RESET_ALL.
This avoid timeouts on TI controllers when initializing the controller but
does not fix the command timeouts.
uwe@ ok.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/sdmmc/sdhc.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/sys/dev/sdmmc/sdhc.c b/sys/dev/sdmmc/sdhc.c index e6fc16bd2e7..b7754b614f6 100644 --- a/sys/dev/sdmmc/sdhc.c +++ b/sys/dev/sdmmc/sdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdhc.c,v 1.10 2006/07/19 23:56:03 fgsch Exp $ */ +/* $OpenBSD: sdhc.c,v 1.11 2006/07/30 16:40:27 fgsch Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -87,7 +87,7 @@ int sdhc_bus_clock(sdmmc_chipset_handle_t, int); void sdhc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *); int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *); int sdhc_wait_state(struct sdhc_host *, u_int32_t, u_int32_t); -void sdhc_soft_reset(struct sdhc_host *); +int sdhc_soft_reset(struct sdhc_host *, int); int sdhc_wait_intr(struct sdhc_host *, int, int); void sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *); void sdhc_read_data(struct sdhc_host *, u_char *, int); @@ -302,17 +302,13 @@ sdhc_shutdown(void *arg) /* * Reset the host controller. Called during initialization, when * cards are removed, upon resume, and during error recovery. - * - * Unfortunately, at least one vendor does not follow the simplified - * SDHC specification: TI's PCI7621 does not clear reset bits, so we - * have no way to tell whether the reset was successful or timed out. */ int sdhc_host_reset(sdmmc_chipset_handle_t sch) { struct sdhc_host *hp = sch; u_int16_t imask; - int timo; + int error; int s; s = splsdmmc(); @@ -324,18 +320,8 @@ sdhc_host_reset(sdmmc_chipset_handle_t sch) * Reset the entire host controller and wait up to 100ms for * the controller to clear the reset bit. */ - HWRITE1(hp, SDHC_SOFTWARE_RESET, SDHC_RESET_MASK); - for (timo = 10; timo > 0; timo--) { - if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), SDHC_RESET_MASK)) - break; - sdmmc_delay(10000); - } - if (timo == 0) { - DPRINTF(("%s: timeout reg=%#x\n", HDEVNAME(hp), - HREAD1(hp, SDHC_SOFTWARE_RESET))); - HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); - /* return ETIMEDOUT; but see above. */ - } + if ((error = sdhc_soft_reset(hp, SDHC_RESET_ALL)) != 0) + return (error); /* Set data timeout counter value to max for now. */ HWRITE1(hp, SDHC_TIMEOUT_CTL, SDHC_TIMEOUT_MAX); @@ -787,12 +773,27 @@ sdhc_write_data(struct sdhc_host *hp, u_char *datap, int datalen) } /* Prepare for another command. */ -void -sdhc_soft_reset(struct sdhc_host *hp) +int +sdhc_soft_reset(struct sdhc_host *hp, int mask) { - DPRINTF(("%s: software reset\n", HDEVNAME(hp))); - HWRITE1(hp, SDHC_SOFTWARE_RESET, SDHC_RESET_DAT|SDHC_RESET_CMD); - sdmmc_delay(10000); + int timo; + + DPRINTF(("%s: software reset reg=%#x\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); + } + if (timo == 0) { + DPRINTF(("%s: timeout reg=%#x\n", HDEVNAME(hp), + HREAD1(hp, SDHC_SOFTWARE_RESET))); + HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); + return (ETIMEDOUT); + } + + return (0); } int @@ -821,7 +822,7 @@ sdhc_wait_intr(struct sdhc_host *hp, int mask, int timo) /* Command timeout has higher priority than command complete. */ if (ISSET(status, SDHC_ERROR_INTERRUPT)) { hp->intr_error_status = 0; - sdhc_soft_reset(hp); + (void)sdhc_soft_reset(hp, SDHC_RESET_DAT|SDHC_RESET_CMD); status = 0; } |