Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/allwinner eliminate most of the polling from aw...
details: https://anonhg.NetBSD.org/src/rev/e385236350df
branches: trunk
changeset: 332146:e385236350df
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Sep 08 23:51:48 2014 +0000
description:
eliminate most of the polling from awin_mmc_exec_command
diffstat:
sys/arch/arm/allwinner/awin_mmc.c | 160 +++++++++++++++++++++++--------------
1 files changed, 101 insertions(+), 59 deletions(-)
diffs (truncated from 334 to 300 lines):
diff -r 22bb20f89479 -r e385236350df sys/arch/arm/allwinner/awin_mmc.c
--- a/sys/arch/arm/allwinner/awin_mmc.c Mon Sep 08 22:12:12 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_mmc.c Mon Sep 08 23:51:48 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_mmc.c,v 1.6 2014/09/08 11:06:03 jmcneill Exp $ */
+/* $NetBSD: awin_mmc.c,v 1.7 2014/09/08 23:51:48 jmcneill Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
#include "locators.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_mmc.c,v 1.6 2014/09/08 11:06:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_mmc.c,v 1.7 2014/09/08 23:51:48 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -50,6 +50,7 @@
static int awin_mmc_match(device_t, cfdata_t, void *);
static void awin_mmc_attach(device_t, device_t, void *);
+static void awin_mmc_attach_i(device_t);
static int awin_mmc_intr(void *);
@@ -91,6 +92,7 @@
void *sc_ih;
kmutex_t sc_intr_lock;
kcondvar_t sc_intr_cv;
+ kcondvar_t sc_idst_cv;
int sc_mmc_number;
int sc_mmc_width;
@@ -108,6 +110,8 @@
int sc_idma_ndesc;
void *sc_idma_desc;
+ uint32_t sc_intr_rint;
+ uint32_t sc_intr_mint;
uint32_t sc_idma_idst;
bool sc_has_gpio_detect;
@@ -219,7 +223,6 @@
struct awin_mmc_softc * const sc = device_private(self);
struct awinio_attach_args * const aio = aux;
const struct awin_locators * const loc = &aio->aio_loc;
- struct sdmmcbus_attach_args saa;
prop_dictionary_t cfg = device_properties(self);
const char *pin_name;
@@ -228,7 +231,8 @@
sc->sc_dmat = aio->aio_dmat;
sc->sc_mmc_number = loc->loc_port;
mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
- cv_init(&sc->sc_intr_cv, "awinmmcio");
+ cv_init(&sc->sc_intr_cv, "awinmmcirq");
+ cv_init(&sc->sc_idst_cv, "awinmmcdma");
bus_space_subregion(sc->sc_bst, aio->aio_core_bsh,
loc->loc_offset, loc->loc_size, &sc->sc_bsh);
@@ -276,6 +280,15 @@
}
aprint_normal_dev(self, "interrupting at irq %d\n", loc->loc_intr);
+ config_interrupts(self, awin_mmc_attach_i);
+}
+
+static void
+awin_mmc_attach_i(device_t self)
+{
+ struct awin_mmc_softc *sc = device_private(self);
+ struct sdmmcbus_attach_args saa;
+
awin_mmc_host_reset(sc);
awin_mmc_bus_width(sc, 1);
@@ -304,24 +317,59 @@
awin_mmc_intr(void *priv)
{
struct awin_mmc_softc *sc = priv;
- uint32_t idst;
+ uint32_t idst, rint, mint;
mutex_enter(&sc->sc_intr_lock);
idst = MMC_READ(sc, AWIN_MMC_IDST);
- if (!idst) {
+ rint = MMC_READ(sc, AWIN_MMC_RINT);
+ mint = MMC_READ(sc, AWIN_MMC_MINT);
+ if (!idst && !rint && !mint) {
mutex_exit(&sc->sc_intr_lock);
return 0;
}
MMC_WRITE(sc, AWIN_MMC_IDST, idst);
+ MMC_WRITE(sc, AWIN_MMC_RINT, rint);
+ MMC_WRITE(sc, AWIN_MMC_MINT, mint);
- sc->sc_idma_idst |= idst;
- cv_broadcast(&sc->sc_intr_cv);
+ if (idst) {
+ sc->sc_idma_idst |= idst;
+ cv_broadcast(&sc->sc_idst_cv);
+ }
+
+ if (rint) {
+ sc->sc_intr_rint |= rint;
+ cv_broadcast(&sc->sc_intr_cv);
+ }
mutex_exit(&sc->sc_intr_lock);
return 1;
}
+static int
+awin_mmc_wait_rint(struct awin_mmc_softc *sc, uint32_t mask, int timeout)
+{
+ int retry = timeout;
+ int error;
+
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
+
+ if (sc->sc_intr_rint & mask)
+ return 0;
+
+ while (retry > 0) {
+ error = cv_timedwait(&sc->sc_intr_cv,
+ &sc->sc_intr_lock, hz);
+ if (error && error != EWOULDBLOCK)
+ return error;
+ if (sc->sc_intr_rint & mask)
+ return 0;
+ --retry;
+ }
+
+ return ETIMEDOUT;
+}
+
static void
awin_mmc_led(struct awin_mmc_softc *sc, int on)
{
@@ -342,6 +390,14 @@
MMC_WRITE(sc, AWIN_MMC_GCTRL,
MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_RESET);
+ MMC_WRITE(sc, AWIN_MMC_IMASK,
+ AWIN_MMC_INT_CMD_DONE | AWIN_MMC_INT_ERROR |
+ AWIN_MMC_INT_DATA_OVER | AWIN_MMC_INT_AUTO_CMD_DONE);
+
+ MMC_WRITE(sc, AWIN_MMC_GCTRL,
+ MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_INTEN);
+
+
return 0;
}
@@ -418,11 +474,12 @@
break;
delay(10);
}
+
if (retry == 0) {
- aprint_error_dev(sc->sc_dev, "timeout updating clk\n");
+ aprint_error_dev(sc->sc_dev, "timeout updating clock\n");
return ETIMEDOUT;
}
- MMC_WRITE(sc, AWIN_MMC_RINT, MMC_READ(sc, AWIN_MMC_RINT));
+
return 0;
}
@@ -578,8 +635,6 @@
{
struct awin_mmc_softc *sc = sch;
uint32_t cmdval = AWIN_MMC_CMD_START;
- uint32_t status;
- int retry;
#ifdef AWIN_MMC_DEBUG
aprint_normal_dev(sc->sc_dev,
@@ -588,6 +643,8 @@
cmd->c_blklen);
#endif
+ mutex_enter(&sc->sc_intr_lock);
+
if (cmd->c_opcode == 0)
cmdval |= AWIN_MMC_CMD_SEND_INIT_SEQ;
if (cmd->c_flags & SCF_RSP_PRESENT)
@@ -617,21 +674,23 @@
MMC_WRITE(sc, AWIN_MMC_BYTECNT, nblks * cmd->c_blklen);
}
+ sc->sc_intr_rint = 0;
+
MMC_WRITE(sc, AWIN_MMC_ARG, cmd->c_arg);
#ifdef AWIN_MMC_DEBUG
aprint_normal_dev(sc->sc_dev, "cmdval = %08x\n", cmdval);
#endif
+
if (cmd->c_datalen == 0) {
MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode);
} else {
- mutex_enter(&sc->sc_intr_lock);
cmd->c_resid = cmd->c_datalen;
cmd->c_error = awin_mmc_dma_prepare(sc, cmd);
awin_mmc_led(sc, 0);
MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode);
if (cmd->c_error == 0) {
- cmd->c_error = cv_timedwait(&sc->sc_intr_cv,
+ cmd->c_error = cv_timedwait(&sc->sc_idst_cv,
&sc->sc_intr_lock, hz*10);
}
if (sc->sc_idma_idst & AWIN_MMC_IDST_ERROR) {
@@ -640,66 +699,49 @@
cmd->c_error = ETIMEDOUT;
}
awin_mmc_led(sc, 1);
- mutex_exit(&sc->sc_intr_lock);
if (cmd->c_error) {
+#ifdef AWIN_MMC_DEBUG
aprint_error_dev(sc->sc_dev,
"xfer failed, error %d\n", cmd->c_error);
+#endif
goto done;
}
}
- retry = 0xfffff;
- while (--retry > 0) {
- status = MMC_READ(sc, AWIN_MMC_RINT);
- if (status & AWIN_MMC_INT_ERROR) {
- retry = 0;
- break;
- }
- if (status & AWIN_MMC_INT_CMD_DONE)
- break;
- delay(10);
- }
- if (retry == 0) {
+ cmd->c_error = awin_mmc_wait_rint(sc,
+ AWIN_MMC_INT_ERROR|AWIN_MMC_INT_CMD_DONE, hz * 10);
+ if (cmd->c_error == 0 && (sc->sc_intr_rint & AWIN_MMC_INT_ERROR))
+ cmd->c_error = EIO;
+ if (cmd->c_error) {
#ifdef AWIN_MMC_DEBUG
aprint_error_dev(sc->sc_dev,
- "RINT (1) timeout, status = %08x\n", status);
+ "cmd failed, error %d\n", cmd->c_error);
#endif
- cmd->c_error = ETIMEDOUT;
goto done;
}
-#ifdef AWIN_MMC_DEBUG
- aprint_normal_dev(sc->sc_dev, "status = %08x\n", status);
-#endif
-
+
if (cmd->c_datalen > 0) {
- retry = 0xffff;
- while (--retry > 0) {
- uint32_t done;
- status = MMC_READ(sc, AWIN_MMC_RINT);
- if (status & AWIN_MMC_INT_ERROR) {
- retry = 0;
- break;
- }
- if (cmd->c_blklen < cmd->c_datalen)
- done = status & AWIN_MMC_INT_AUTO_CMD_DONE;
- else
- done = status & AWIN_MMC_INT_DATA_OVER;
- if (done)
- break;
- delay(10);
+ cmd->c_error = awin_mmc_wait_rint(sc,
+ AWIN_MMC_INT_ERROR|
+ AWIN_MMC_INT_AUTO_CMD_DONE|
+ AWIN_MMC_INT_DATA_OVER,
+ hz*10);
+ if (cmd->c_error == 0 &&
+ (sc->sc_intr_rint & AWIN_MMC_INT_ERROR)) {
+ cmd->c_error = ETIMEDOUT;
}
- if (retry == 0) {
+ if (cmd->c_error) {
#ifdef AWIN_MMC_DEBUG
aprint_error_dev(sc->sc_dev,
- "RINT (2) timeout, status = %08x\n", status);
+ "data timeout, rint = %08x\n",
+ sc->sc_intr_rint);
#endif
cmd->c_error = ETIMEDOUT;
goto done;
}
- }
-
- if (cmd->c_flags & SCF_RSP_BSY) {
- retry = 0xfffff;
+ } else if (cmd->c_flags & SCF_RSP_BSY) {
Home |
Main Index |
Thread Index |
Old Index