summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2009-09-03 20:17:26 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2009-09-03 20:17:26 +0000
commit86a6a5101480795bffb83ea7a080a1c0116cad53 (patch)
tree60c7e274a6fedba66f6dc75f0c73ec14132c3bd6
parent6dca254c3bd2f12561c7f5c8c11996132cc6ac26 (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.c24
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);
+ }
}
}