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/06b62f8c79d1
branches: trunk
changeset: 1006672:06b62f8c79d1
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 e9ce987afd74 -r 06b62f8c79d1 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 e9ce987afd74 -r 06b62f8c79d1 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 e9ce987afd74 -r 06b62f8c79d1 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 e9ce987afd74 -r 06b62f8c79d1 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