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