summaryrefslogtreecommitdiff
path: root/sys/arch/arm/xscale/pxa2x0_mmc.c
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 /sys/arch/arm/xscale/pxa2x0_mmc.c
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
Diffstat (limited to 'sys/arch/arm/xscale/pxa2x0_mmc.c')
-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);
+ }
}
}