Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

src: Simplify interrupt handling by only enabling interrupts for...



details:   https://anonhg.NetBSD.org/src/rev/d6e53b4425fb
branches:  trunk
changeset: 318210:d6e53b4425fb
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Apr 15 18:24:52 2018 +0000
description:
Simplify interrupt handling by only enabling interrupts for events that
we actually need. After we've consumed the event, mask the interrupt.

diffstat:

 sys/arch/arm/sunxi/sunxi_mmc.c |  85 ++++++++++++++++++++++++-----------------
 1 files changed, 50 insertions(+), 35 deletions(-)

diffs (219 lines):

diff -r e280911ca1ca -r d6e53b4425fb sys/arch/arm/sunxi/sunxi_mmc.c
--- a/sys/arch/arm/sunxi/sunxi_mmc.c    Sun Apr 15 17:26:39 2018 +0000
+++ b/sys/arch/arm/sunxi/sunxi_mmc.c    Sun Apr 15 18:24:52 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_mmc.c,v 1.21 2018/03/19 08:57:57 ryo Exp $ */
+/* $NetBSD: sunxi_mmc.c,v 1.22 2018/04/15 18:24:52 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "opt_sunximmc.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_mmc.c,v 1.21 2018/03/19 08:57:57 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_mmc.c,v 1.22 2018/04/15 18:24:52 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -555,7 +555,7 @@
 sunxi_mmc_intr(void *priv)
 {
        struct sunxi_mmc_softc *sc = priv;
-       uint32_t idst, rint;
+       uint32_t idst, rint, imask;
 
        mutex_enter(&sc->sc_intr_lock);
        idst = MMC_READ(sc, SUNXI_MMC_IDST);
@@ -565,17 +565,20 @@
                return 0;
        }
        MMC_WRITE(sc, SUNXI_MMC_IDST, idst);
-       MMC_WRITE(sc, SUNXI_MMC_RINT, rint);
+       MMC_WRITE(sc, SUNXI_MMC_RINT, rint & ~SUNXI_MMC_INT_SDIO_INT);
 
        DPRINTF(sc->sc_dev, "mmc intr idst=%08X rint=%08X\n",
            idst, rint);
 
        if (idst != 0) {
+               MMC_WRITE(sc, SUNXI_MMC_IDIE, 0);
                sc->sc_idma_idst |= idst;
                cv_broadcast(&sc->sc_idst_cv);
        }
 
        if ((rint & ~SUNXI_MMC_INT_SDIO_INT) != 0) {
+               imask = MMC_READ(sc, SUNXI_MMC_IMASK);
+               MMC_WRITE(sc, SUNXI_MMC_IMASK, imask & ~SUNXI_MMC_INT_SDIO_INT);
                sc->sc_intr_rint |= (rint & ~SUNXI_MMC_INT_SDIO_INT);
                cv_broadcast(&sc->sc_intr_cv);
        }
@@ -629,12 +632,14 @@
 sunxi_mmc_host_reset(sdmmc_chipset_handle_t sch)
 {
        struct sunxi_mmc_softc *sc = sch;
+       uint32_t gctrl;
        int retry = 1000;
 
        DPRINTF(sc->sc_dev, "host reset\n");
 
-       MMC_WRITE(sc, SUNXI_MMC_GCTRL,
-           MMC_READ(sc, SUNXI_MMC_GCTRL) | SUNXI_MMC_GCTRL_RESET);
+       gctrl = MMC_READ(sc, SUNXI_MMC_GCTRL);
+       gctrl |= SUNXI_MMC_GCTRL_RESET;
+       MMC_WRITE(sc, SUNXI_MMC_GCTRL, gctrl);
        while (--retry > 0) {
                if (!(MMC_READ(sc, SUNXI_MMC_GCTRL) & SUNXI_MMC_GCTRL_RESET))
                        break;
@@ -643,12 +648,15 @@
 
        MMC_WRITE(sc, SUNXI_MMC_TIMEOUT, 0xffffffff);
 
-       MMC_WRITE(sc, SUNXI_MMC_IMASK,
-           SUNXI_MMC_INT_CMD_DONE | SUNXI_MMC_INT_ERROR |
-           SUNXI_MMC_INT_DATA_OVER | SUNXI_MMC_INT_AUTO_CMD_DONE);
+       MMC_WRITE(sc, SUNXI_MMC_IMASK, 0);
+
+       MMC_WRITE(sc, SUNXI_MMC_RINT, 0xffffffff);
 
-       MMC_WRITE(sc, SUNXI_MMC_GCTRL,
-           MMC_READ(sc, SUNXI_MMC_GCTRL) | SUNXI_MMC_GCTRL_INTEN);
+       gctrl = MMC_READ(sc, SUNXI_MMC_GCTRL);
+       gctrl |= SUNXI_MMC_GCTRL_INTEN;
+       gctrl &= ~SUNXI_MMC_GCTRL_WAIT_MEM_ACCESS_DONE;
+       gctrl &= ~SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
+       MMC_WRITE(sc, SUNXI_MMC_GCTRL, gctrl);
 
        return 0;
 }
@@ -965,24 +973,23 @@
 
        sc->sc_idma_idst = 0;
 
+       MMC_WRITE(sc, SUNXI_MMC_DLBA, desc_paddr);
+       MMC_WRITE(sc, SUNXI_MMC_FTRGLEVEL, sc->sc_config->dma_ftrglevel);
+
        val = MMC_READ(sc, SUNXI_MMC_GCTRL);
        val |= SUNXI_MMC_GCTRL_DMAEN;
-       val |= SUNXI_MMC_GCTRL_INTEN;
        MMC_WRITE(sc, SUNXI_MMC_GCTRL, val);
        val |= SUNXI_MMC_GCTRL_DMARESET;
        MMC_WRITE(sc, SUNXI_MMC_GCTRL, val);
+
        MMC_WRITE(sc, SUNXI_MMC_DMAC, SUNXI_MMC_DMAC_SOFTRESET);
+       if (ISSET(cmd->c_flags, SCF_CMD_READ))
+               val = SUNXI_MMC_IDST_RECEIVE_INT;
+       else
+               val = 0;
+       MMC_WRITE(sc, SUNXI_MMC_IDIE, val);
        MMC_WRITE(sc, SUNXI_MMC_DMAC,
            SUNXI_MMC_DMAC_IDMA_ON|SUNXI_MMC_DMAC_FIX_BURST);
-       val = MMC_READ(sc, SUNXI_MMC_IDIE);
-       val &= ~(SUNXI_MMC_IDST_RECEIVE_INT|SUNXI_MMC_IDST_TRANSMIT_INT);
-       if (ISSET(cmd->c_flags, SCF_CMD_READ))
-               val |= SUNXI_MMC_IDST_RECEIVE_INT;
-       else
-               val |= SUNXI_MMC_IDST_TRANSMIT_INT;
-       MMC_WRITE(sc, SUNXI_MMC_IDIE, val);
-       MMC_WRITE(sc, SUNXI_MMC_DLBA, desc_paddr);
-       MMC_WRITE(sc, SUNXI_MMC_FTRGLEVEL, sc->sc_config->dma_ftrglevel);
 
        return 0;
 }
@@ -990,6 +997,8 @@
 static void
 sunxi_mmc_dma_complete(struct sunxi_mmc_softc *sc, struct sdmmc_command *cmd)
 {
+       MMC_WRITE(sc, SUNXI_MMC_DMAC, 0);
+
        bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
            sc->sc_idma_size, BUS_DMASYNC_POSTWRITE);
 
@@ -1011,6 +1020,7 @@
 {
        struct sunxi_mmc_softc *sc = sch;
        uint32_t cmdval = SUNXI_MMC_CMD_START;
+       uint32_t imask, oimask;
        const bool poll = (cmd->c_flags & SCF_POLL) != 0;
        int retry;
 
@@ -1030,6 +1040,9 @@
        if (cmd->c_flags & SCF_RSP_CRC)
                cmdval |= SUNXI_MMC_CMD_CHECK_RSP_CRC;
 
+       imask = oimask = MMC_READ(sc, SUNXI_MMC_IMASK);
+       imask |= SUNXI_MMC_INT_ERROR;
+
        if (cmd->c_datalen > 0) {
                unsigned int nblks;
 
@@ -1044,12 +1057,20 @@
 
                if (nblks > 1) {
                        cmdval |= SUNXI_MMC_CMD_SEND_AUTO_STOP;
+                       imask |= SUNXI_MMC_INT_AUTO_CMD_DONE;
+               } else {
+                       imask |= SUNXI_MMC_INT_DATA_OVER;
                }
 
                MMC_WRITE(sc, SUNXI_MMC_BLKSZ, cmd->c_blklen);
                MMC_WRITE(sc, SUNXI_MMC_BYTECNT, nblks * cmd->c_blklen);
+       } else {
+               imask |= SUNXI_MMC_INT_CMD_DONE;
        }
 
+       MMC_WRITE(sc, SUNXI_MMC_IMASK, imask);
+       MMC_WRITE(sc, SUNXI_MMC_RINT, 0xffff);
+
        sc->sc_intr_rint = 0;
 
        MMC_WRITE(sc, SUNXI_MMC_A12A,
@@ -1065,9 +1086,9 @@
                cmd->c_resid = cmd->c_datalen;
                cmd->c_error = sunxi_mmc_dma_prepare(sc, cmd);
                MMC_WRITE(sc, SUNXI_MMC_CMD, cmdval | cmd->c_opcode);
-               if (cmd->c_error == 0) {
-                       const uint32_t idst_mask =
-                           SUNXI_MMC_IDST_ERROR | SUNXI_MMC_IDST_COMPLETE;
+               if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_CMD_READ)) {
+                       const uint32_t idst_mask = SUNXI_MMC_IDST_RECEIVE_INT;
+
                        retry = 10;
                        while ((sc->sc_idma_idst & idst_mask) == 0) {
                                if (retry-- == 0) {
@@ -1078,17 +1099,6 @@
                                    &sc->sc_intr_lock, hz);
                        }
                }
-               sunxi_mmc_dma_complete(sc, cmd);
-               if (sc->sc_idma_idst & SUNXI_MMC_IDST_ERROR) {
-                       cmd->c_error = EIO;
-               } else if (!(sc->sc_idma_idst & SUNXI_MMC_IDST_COMPLETE)) {
-                       cmd->c_error = ETIMEDOUT;
-               }
-               if (cmd->c_error) {
-                       DPRINTF(sc->sc_dev,
-                           "xfer failed, error %d\n", cmd->c_error);
-                       goto done;
-               }
        }
 
        cmd->c_error = sunxi_mmc_wait_rint(sc,
@@ -1107,6 +1117,8 @@
        }
                
        if (cmd->c_datalen > 0) {
+               sunxi_mmc_dma_complete(sc, cmd);
+
                cmd->c_error = sunxi_mmc_wait_rint(sc,
                    SUNXI_MMC_INT_ERROR|
                    SUNXI_MMC_INT_AUTO_CMD_DONE|
@@ -1147,6 +1159,9 @@
 
 done:
        cmd->c_flags |= SCF_ITSDONE;
+       MMC_WRITE(sc, SUNXI_MMC_IMASK, oimask);
+       MMC_WRITE(sc, SUNXI_MMC_RINT, 0xffff);
+       MMC_WRITE(sc, SUNXI_MMC_IDST, 0x337);
        mutex_exit(&sc->sc_intr_lock);
 
        if (cmd->c_error) {



Home | Main Index | Thread Index | Old Index