diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2009-09-03 20:17:26 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2009-09-03 20:17:26 +0000 |
commit | 86a6a5101480795bffb83ea7a080a1c0116cad53 (patch) | |
tree | 60c7e274a6fedba66f6dc75f0c73ec14132c3bd6 | |
parent | 6dca254c3bd2f12561c7f5c8c11996132cc6ac26 (diff) |
Rearrange the interrupt handler so that it handlers "error status bits"
first instead of trying to push data transfers forward. Also, ensure that
DONE interrupts are only un-masked when we are on the last sub-block, and
that otherwise we process based on RD_REQ and WR_REQ interrupts coming in.
Done with drahn and marex (starting from bizzare workarounds by marex
which we could not explain)
This appears to make Zaurus SD reads & writes completely reliable, even at
very low cpu speeds.
ok drahn marex
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_mmc.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/sys/arch/arm/xscale/pxa2x0_mmc.c b/sys/arch/arm/xscale/pxa2x0_mmc.c index 6798fd9d2ec..f614158150d 100644 --- a/sys/arch/arm/xscale/pxa2x0_mmc.c +++ b/sys/arch/arm/xscale/pxa2x0_mmc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_mmc.c,v 1.7 2009/09/03 18:39:08 marex Exp $ */ +/* $OpenBSD: pxa2x0_mmc.c,v 1.8 2009/09/03 20:17:25 deraadt Exp $ */ /* * Copyright (c) 2007 Uwe Stuehler <uwe@openbsd.org> @@ -395,7 +395,7 @@ pxammc_exec_command(sdmmc_chipset_handle_t sch, CSR_WRITE_4(sc, MMC_NUMBLK, numblk); /* Enable data interrupts. */ - CSR_CLR_4(sc, MMC_I_MASK, MMC_I_DATA_TRAN_DONE | + CSR_CLR_4(sc, MMC_I_MASK, MMC_I_RXFIFO_RD_REQ | MMC_I_TXFIFO_WR_REQ | MMC_I_DAT_ERR); @@ -524,11 +524,6 @@ pxammc_intr(void *arg) goto end; } - if (ISSET(status, MMC_I_TXFIFO_WR_REQ | MMC_I_RXFIFO_RD_REQ)) { - pxammc_intr_data(sc); - CLR(status, MMC_I_TXFIFO_WR_REQ | MMC_I_RXFIFO_RD_REQ); - } - if (ISSET(status, MMC_I_DAT_ERR)) { sc->sc_cmd->c_error = EIO; pxammc_intr_done(sc); @@ -548,6 +543,11 @@ pxammc_intr(void *arg) CLR(status, MMC_I_DATA_TRAN_DONE); } + if (ISSET(status, MMC_I_TXFIFO_WR_REQ | MMC_I_RXFIFO_RD_REQ)) { + pxammc_intr_data(sc); + CLR(status, MMC_I_TXFIFO_WR_REQ | MMC_I_RXFIFO_RD_REQ); + } + end: /* Avoid further unhandled interrupts. */ if (status != 0) { @@ -651,10 +651,12 @@ pxammc_intr_data(struct pxammc_softc *sc) if (cmd->c_resid > 0) CSR_CLR_4(sc, MMC_I_MASK, MMC_I_RXFIFO_RD_REQ); - else + else { CSR_SET_4(sc, MMC_I_MASK, MMC_I_RXFIFO_RD_REQ); + CSR_CLR_4(sc, MMC_I_MASK, MMC_I_DATA_TRAN_DONE); + } } else { - int short_xfer = n < 32; + int short_xfer = (n != 0 && n != 32); while (n-- > 0) CSR_WRITE_1(sc, MMC_TXFIFO, *cmd->c_buf++); @@ -663,8 +665,10 @@ pxammc_intr_data(struct pxammc_softc *sc) if (cmd->c_resid > 0) CSR_CLR_4(sc, MMC_I_MASK, MMC_I_TXFIFO_WR_REQ); - else + else { CSR_SET_4(sc, MMC_I_MASK, MMC_I_TXFIFO_WR_REQ); + CSR_CLR_4(sc, MMC_I_MASK, MMC_I_DATA_TRAN_DONE); + } } } |