Module Name:    src
Committed By:   jmcneill
Date:           Wed Jan 22 23:19:12 UTC 2020

Modified Files:
        src/sys/dev/fdt: dwcmmc_fdt.c
        src/sys/dev/ic: dwc_mmc.c dwc_mmc_reg.h dwc_mmc_var.h

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/fdt/dwcmmc_fdt.c
cvs rdiff -u -r1.20 -r1.21 src/sys/dev/ic/dwc_mmc.c
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/ic/dwc_mmc_reg.h
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/ic/dwc_mmc_var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/fdt/dwcmmc_fdt.c
diff -u src/sys/dev/fdt/dwcmmc_fdt.c:1.10 src/sys/dev/fdt/dwcmmc_fdt.c:1.11
--- src/sys/dev/fdt/dwcmmc_fdt.c:1.10	Wed Jan  1 12:18:18 2020
+++ src/sys/dev/fdt/dwcmmc_fdt.c	Wed Jan 22 23:19:11 2020
@@ -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 <[email protected]>
@@ -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 @@ static int	dwcmmc_fdt_signal_voltage(str
 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 @@ dwcmmc_fdt_attach(device_t parent, devic
 		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;

Index: src/sys/dev/ic/dwc_mmc.c
diff -u src/sys/dev/ic/dwc_mmc.c:1.20 src/sys/dev/ic/dwc_mmc.c:1.21
--- src/sys/dev/ic/dwc_mmc.c:1.20	Wed Jan  1 12:18:18 2020
+++ src/sys/dev/ic/dwc_mmc.c	Wed Jan 22 23:19:12 2020
@@ -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 <[email protected]>
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 
 #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 @@ dwc_mmc_dma_prepare(struct dwc_mmc_softc
 	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 @@ dwc_mmc_exec_command(sdmmc_chipset_handl
 	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 @@ dwc_mmc_exec_command(sdmmc_chipset_handl
 	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 @@ dwc_mmc_exec_command(sdmmc_chipset_handl
 		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 @@ done:
 #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 @@ dwc_mmc_card_enable_intr(sdmmc_chipset_h
 	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 @@ dwc_mmc_init(struct dwc_mmc_softc *sc)
 		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 @@ dwc_mmc_intr(void *priv)
 #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);
 	}
 

Index: src/sys/dev/ic/dwc_mmc_reg.h
diff -u src/sys/dev/ic/dwc_mmc_reg.h:1.8 src/sys/dev/ic/dwc_mmc_reg.h:1.9
--- src/sys/dev/ic/dwc_mmc_reg.h:1.8	Wed Jan 22 21:59:10 2020
+++ src/sys/dev/ic/dwc_mmc_reg.h	Wed Jan 22 23:19:12 2020
@@ -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 <[email protected]>
@@ -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)

Index: src/sys/dev/ic/dwc_mmc_var.h
diff -u src/sys/dev/ic/dwc_mmc_var.h:1.11 src/sys/dev/ic/dwc_mmc_var.h:1.12
--- src/sys/dev/ic/dwc_mmc_var.h:1.11	Wed Jan  1 12:18:18 2020
+++ src/sys/dev/ic/dwc_mmc_var.h	Wed Jan 22 23:19:12 2020
@@ -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 <[email protected]>
@@ -69,6 +69,7 @@ struct dwc_mmc_softc {
 	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;

Reply via email to