Source-Changes-HG archive

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

[src/trunk]: src/sys/dev dwc_mmc fixes:



details:   https://anonhg.NetBSD.org/src/rev/840215e20f4b
branches:  trunk
changeset: 848271:840215e20f4b
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Wed Jan 22 23:19:11 2020 +0000

description:
dwc_mmc fixes:
 - Rockchip uses a different SDIO int bit, so take this into consideration
 - Avoid unnecessary resets and always wait for resets to complete
 - kpause instead of delay while holding spinlock
 - Do not attempt autostop for SD_IO_RW_EXTENDED commands
 - Allow for sub-blklen byte counts for single block transfers

diffstat:

 sys/dev/fdt/dwcmmc_fdt.c |   7 ++++-
 sys/dev/ic/dwc_mmc.c     |  54 +++++++++++++++++++++++++++++------------------
 sys/dev/ic/dwc_mmc_reg.h |   8 +++++-
 sys/dev/ic/dwc_mmc_var.h |   3 +-
 4 files changed, 46 insertions(+), 26 deletions(-)

diffs (237 lines):

diff -r b54f9ed15901 -r 840215e20f4b sys/dev/fdt/dwcmmc_fdt.c
--- a/sys/dev/fdt/dwcmmc_fdt.c  Wed Jan 22 22:39:27 2020 +0000
+++ b/sys/dev/fdt/dwcmmc_fdt.c  Wed Jan 22 23:19:11 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwcmmc_fdt.c,v 1.10 2020/01/01 12:18:18 jmcneill Exp $ */
+/* $NetBSD: dwcmmc_fdt.c,v 1.11 2020/01/22 23:19:11 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015-2018 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwcmmc_fdt.c,v 1.10 2020/01/01 12:18:18 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwcmmc_fdt.c,v 1.11 2020/01/22 23:19:11 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -56,12 +56,14 @@
 struct dwcmmc_fdt_config {
        u_int           ciu_div;
        u_int           flags;
+       uint32_t        intr_cardmask;
 };
 
 static const struct dwcmmc_fdt_config dwcmmc_rk3288_config = {
        .ciu_div = 2,
        .flags = DWC_MMC_F_USE_HOLD_REG |
                 DWC_MMC_F_DMA,
+       .intr_cardmask = __BIT(24),
 };
 
 static const struct of_compat_data compat_data[] = {
@@ -156,6 +158,7 @@
                sc->sc_bus_width = 4;
 
        sc->sc_fifo_depth = fifo_depth;
+       sc->sc_intr_cardmask = esc->sc_conf->intr_cardmask;
        sc->sc_ciu_div = esc->sc_conf->ciu_div;
        sc->sc_flags = esc->sc_conf->flags;
        sc->sc_pre_power_on = dwcmmc_fdt_pre_power_on;
diff -r b54f9ed15901 -r 840215e20f4b sys/dev/ic/dwc_mmc.c
--- a/sys/dev/ic/dwc_mmc.c      Wed Jan 22 22:39:27 2020 +0000
+++ b/sys/dev/ic/dwc_mmc.c      Wed Jan 22 23:19:11 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc.c,v 1.20 2020/01/01 12:18:18 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc.c,v 1.21 2020/01/22 23:19:12 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.20 2020/01/01 12:18:18 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.21 2020/01/22 23:19:12 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -35,6 +35,7 @@
 #include <sys/intr.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/proc.h>
 
 #include <dev/sdmmc/sdmmcvar.h>
 #include <dev/sdmmc/sdmmcchip.h>
@@ -532,7 +533,6 @@
        val |= DWC_MMC_GCTRL_DMARESET;
        MMC_WRITE(sc, DWC_MMC_GCTRL, val);
 
-       MMC_WRITE(sc, DWC_MMC_DMAC, DWC_MMC_DMAC_SOFTRESET);
        if (cmd->c_flags & SCF_CMD_READ)
                val = DWC_MMC_IDST_RECEIVE_INT;
        else
@@ -597,7 +597,7 @@
        if (ISSET(sc->sc_flags, DWC_MMC_F_USE_HOLD_REG))
                cmdval |= DWC_MMC_CMD_USE_HOLD_REG;
 
-       if (cmd->c_opcode == 0)
+       if (cmd->c_opcode == MMC_GO_IDLE_STATE)
                cmdval |= DWC_MMC_CMD_SEND_INIT_SEQ;
        if (cmd->c_flags & SCF_RSP_PRESENT)
                cmdval |= DWC_MMC_CMD_RSP_EXP;
@@ -611,6 +611,14 @@
        if (cmd->c_datalen > 0) {
                unsigned int nblks;
 
+               MMC_WRITE(sc, DWC_MMC_GCTRL,
+                   MMC_READ(sc, DWC_MMC_GCTRL) | DWC_MMC_GCTRL_FIFORESET);
+               for (retry = 0; retry < 100; retry++) {
+                       if (!(MMC_READ(sc, DWC_MMC_DMAC) & DWC_MMC_DMAC_SOFTRESET))
+                               break;
+                       kpause("dwcmmcfifo", false, uimax(mstohz(1), 1), &sc->sc_intr_lock);
+               }
+
                cmdval |= DWC_MMC_CMD_DATA_EXP | DWC_MMC_CMD_WAIT_PRE_OVER;
                if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
                        cmdval |= DWC_MMC_CMD_WRITE;
@@ -620,15 +628,22 @@
                if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
                        ++nblks;
 
-               if (nblks > 1) {
+               if (nblks > 1 && cmd->c_opcode != SD_IO_RW_EXTENDED) {
                        cmdval |= DWC_MMC_CMD_SEND_AUTO_STOP;
                        imask |= DWC_MMC_INT_AUTO_CMD_DONE;
                } else {
                        imask |= DWC_MMC_INT_DATA_OVER;
                }
 
+               MMC_WRITE(sc, DWC_MMC_TIMEOUT, 0xffffffff);
                MMC_WRITE(sc, DWC_MMC_BLKSZ, cmd->c_blklen);
-               MMC_WRITE(sc, DWC_MMC_BYTECNT, nblks * cmd->c_blklen);
+               MMC_WRITE(sc, DWC_MMC_BYTECNT,
+                   nblks > 1 ? nblks * cmd->c_blklen : cmd->c_datalen);
+               if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
+                       MMC_WRITE(sc, DWC_MMC_CARDTHRCTL,
+                           __SHIFTIN(cmd->c_blklen, DWC_MMC_CARDTHRCTL_RDTHR) |
+                           DWC_MMC_CARDTHRCTL_RDTHREN);
+               }
        }
 
        MMC_WRITE(sc, DWC_MMC_IMASK, imask | sc->sc_intr_card);
@@ -712,19 +727,13 @@
 #ifdef DWC_MMC_DEBUG
                aprint_error_dev(sc->sc_dev, "i/o error %d\n", cmd->c_error);
 #endif
-               MMC_WRITE(sc, DWC_MMC_GCTRL,
-                   MMC_READ(sc, DWC_MMC_GCTRL) |
-                     DWC_MMC_GCTRL_DMARESET | DWC_MMC_GCTRL_FIFORESET);
-               for (retry = 0; retry < 1000; retry++) {
-                       if (!(MMC_READ(sc, DWC_MMC_GCTRL) & DWC_MMC_GCTRL_RESET))
+               MMC_WRITE(sc, DWC_MMC_DMAC, DWC_MMC_DMAC_SOFTRESET);
+               for (retry = 0; retry < 100; retry++) {
+                       if (!(MMC_READ(sc, DWC_MMC_DMAC) & DWC_MMC_DMAC_SOFTRESET))
                                break;
-                       delay(10);
+                       kpause("dwcmmcrst", false, uimax(mstohz(1), 1), NULL);
                }
-               dwc_mmc_update_clock(sc);
        }
-
-       MMC_WRITE(sc, DWC_MMC_GCTRL,
-           MMC_READ(sc, DWC_MMC_GCTRL) | DWC_MMC_GCTRL_FIFORESET);
 }
 
 static void
@@ -736,10 +745,10 @@
        mutex_enter(&sc->sc_intr_lock);
        imask = MMC_READ(sc, DWC_MMC_IMASK);
        if (enable)
-               imask |= DWC_MMC_INT_SDIO_INT;
+               imask |= sc->sc_intr_cardmask;
        else
-               imask &= ~DWC_MMC_INT_SDIO_INT;
-       sc->sc_intr_card = imask & DWC_MMC_INT_SDIO_INT;
+               imask &= ~sc->sc_intr_cardmask;
+       sc->sc_intr_card = imask & sc->sc_intr_cardmask;
        MMC_WRITE(sc, DWC_MMC_IMASK, imask);
        mutex_exit(&sc->sc_intr_lock);
 }
@@ -776,6 +785,9 @@
                sc->sc_fifo_depth = __SHIFTOUT(val, DWC_MMC_FIFOTH_RX_WMARK) + 1;
        }
 
+       if (sc->sc_intr_cardmask == 0)
+               sc->sc_intr_cardmask = DWC_MMC_INT_SDIO_INT(0);
+
        mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
        cv_init(&sc->sc_intr_cv, "dwcmmcirq");
 
@@ -815,9 +827,9 @@
 #endif
 
        /* Handle SDIO card interrupt */
-       if ((mint & DWC_MMC_INT_SDIO_INT) != 0) {
+       if ((mint & sc->sc_intr_cardmask) != 0) {
                imask = MMC_READ(sc, DWC_MMC_IMASK);
-               MMC_WRITE(sc, DWC_MMC_IMASK, imask & ~DWC_MMC_INT_SDIO_INT);
+               MMC_WRITE(sc, DWC_MMC_IMASK, imask & ~sc->sc_intr_cardmask);
                sdmmc_card_intr(sc->sc_sdmmc_dev);
        }
 
diff -r b54f9ed15901 -r 840215e20f4b sys/dev/ic/dwc_mmc_reg.h
--- a/sys/dev/ic/dwc_mmc_reg.h  Wed Jan 22 22:39:27 2020 +0000
+++ b/sys/dev/ic/dwc_mmc_reg.h  Wed Jan 22 23:19:11 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc_reg.h,v 1.8 2020/01/22 21:59:10 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc_reg.h,v 1.9 2020/01/22 23:19:12 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -67,6 +67,7 @@
 #define DWC_MMC_IDIE                   0x0090
 #define DWC_MMC_DSCADDR                        0x0094
 #define DWC_MMC_BUFADDR                        0x0098
+#define DWC_MMC_CARDTHRCTL             0x0100
 
 #define DWC_MMC_GCTRL_USE_INTERNAL_DMAC        __BIT(25)
 #define DWC_MMC_GCTRL_SEND_AUTO_STOP_CCSD __BIT(10)
@@ -107,7 +108,7 @@
 
 #define DWC_MMC_INT_CARD_REMOVE                __BIT(31)
 #define DWC_MMC_INT_CARD_INSERT                __BIT(30)
-#define DWC_MMC_INT_SDIO_INT           __BIT(24)
+#define DWC_MMC_INT_SDIO_INT(n)                __BIT(16 + (n))
 #define DWC_MMC_INT_END_BIT_ERR                __BIT(15)
 #define DWC_MMC_INT_AUTO_CMD_DONE      __BIT(14)
 #define DWC_MMC_INT_START_BIT_ERR      __BIT(13)
@@ -167,6 +168,9 @@
 #define DWC_MMC_IDST_COMPLETE \
        (DWC_MMC_IDST_RECEIVE_INT | DWC_MMC_IDST_TRANSMIT_INT)
 
+#define DWC_MMC_CARDTHRCTL_RDTHR       __BITS(27,16)
+#define DWC_MMC_CARDTHRCTL_RDTHREN     __BIT(0)
+
 struct dwc_mmc_idma_desc {
        uint32_t                dma_config;
 #define DWC_MMC_IDMA_CONFIG_DIC                __BIT(1)
diff -r b54f9ed15901 -r 840215e20f4b sys/dev/ic/dwc_mmc_var.h
--- a/sys/dev/ic/dwc_mmc_var.h  Wed Jan 22 22:39:27 2020 +0000
+++ b/sys/dev/ic/dwc_mmc_var.h  Wed Jan 22 23:19:11 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc_var.h,v 1.11 2020/01/01 12:18:18 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc_var.h,v 1.12 2020/01/22 23:19:12 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -69,6 +69,7 @@
        size_t sc_dmabounce_buflen;
 
        uint32_t sc_intr_card;
+       uint32_t sc_intr_cardmask;
        struct sdmmc_command *sc_curcmd;
        bool sc_wait_dma;
        bool sc_wait_cmd;



Home | Main Index | Thread Index | Old Index