From 3cc75aa740bb27e4ff270759226182a35ad70611 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Thu, 23 Jul 2015 23:52:54 +0000 Subject: [PATCH] Add a SDHC_FLAG_NO_TIMEOUT quirk to handle spurious timeouts on Tegra K1 during data transfers. While here, increase the soft timeout for DMA transfers from 1s to 3s. --- sys/dev/sdmmc/sdhc.c | 19 +++++++++++++++---- sys/dev/sdmmc/sdhcvar.h | 3 ++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/sys/dev/sdmmc/sdhc.c b/sys/dev/sdmmc/sdhc.c index 868ce0e4b78b..bd61948aa002 100644 --- a/sys/dev/sdmmc/sdhc.c +++ b/sys/dev/sdmmc/sdhc.c @@ -1,4 +1,4 @@ -/* $NetBSD: sdhc.c,v 1.60 2015/07/22 09:54:42 skrll Exp $ */ +/* $NetBSD: sdhc.c,v 1.61 2015/07/23 23:52:54 jmcneill Exp $ */ /* $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $ */ /* @@ -23,7 +23,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.60 2015/07/22 09:54:42 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.61 2015/07/23 23:52:54 jmcneill Exp $"); #ifdef _KERNEL_OPT #include "opt_sdmmc.h" @@ -55,7 +55,7 @@ void sdhc_dump_regs(struct sdhc_host *); #define SDHC_COMMAND_TIMEOUT hz #define SDHC_BUFFER_TIMEOUT hz #define SDHC_TRANSFER_TIMEOUT hz -#define SDHC_DMA_TIMEOUT hz +#define SDHC_DMA_TIMEOUT (hz*3) struct sdhc_host { struct sdhc_softc *sc; /* host controller device */ @@ -1119,6 +1119,17 @@ sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) mutex_exit(&hp->intr_mtx); } + if (ISSET(hp->sc->sc_flags, SDHC_FLAG_NO_TIMEOUT)) { + const uint16_t eintr = SDHC_CMD_TIMEOUT_ERROR; + if (cmd->c_data != NULL) { + HCLR2(hp, SDHC_EINTR_SIGNAL_EN, eintr); + HCLR2(hp, SDHC_EINTR_STATUS_EN, eintr); + } else { + HSET2(hp, SDHC_EINTR_SIGNAL_EN, eintr); + HSET2(hp, SDHC_EINTR_STATUS_EN, eintr); + } + } + /* * Start the MMC command, or mark `cmd' as failed and return. */ @@ -1332,7 +1343,7 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd) if (hp->sc->sc_vendor_transfer_data_dma != NULL) { error = hp->sc->sc_vendor_transfer_data_dma(sc, cmd); if (error == 0 && !sdhc_wait_intr(hp, - SDHC_TRANSFER_COMPLETE, SDHC_TRANSFER_TIMEOUT)) { + SDHC_TRANSFER_COMPLETE, SDHC_DMA_TIMEOUT)) { error = ETIMEDOUT; } } else { diff --git a/sys/dev/sdmmc/sdhcvar.h b/sys/dev/sdmmc/sdhcvar.h index 32a0e984e406..e0c84123259d 100644 --- a/sys/dev/sdmmc/sdhcvar.h +++ b/sys/dev/sdmmc/sdhcvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: sdhcvar.h,v 1.18 2015/05/03 11:46:25 jmcneill Exp $ */ +/* $NetBSD: sdhcvar.h,v 1.19 2015/07/23 23:52:54 jmcneill Exp $ */ /* $OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $ */ /* @@ -54,6 +54,7 @@ struct sdhc_softc { #define SDHC_FLAG_EXTDMA_DMAEN 0x00008000 /* ext. dma need SDHC_DMA_ENABLE */ #define SDHC_FLAG_NO_CLKBASE 0x00020000 /* ignore clkbase register */ #define SDHC_FLAG_SINGLE_POWER_WRITE 0x00040000 +#define SDHC_FLAG_NO_TIMEOUT 0x00080000 /* ignore timeout interrupts */ uint32_t sc_clkbase; int sc_clkmsk; /* Mask for SDCLK */