Thu Jul 23 23:52:54 2015 UTC ()
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.


(jmcneill)
diff -r1.60 -r1.61 src/sys/dev/sdmmc/sdhc.c
diff -r1.18 -r1.19 src/sys/dev/sdmmc/sdhcvar.h

cvs diff -r1.60 -r1.61 src/sys/dev/sdmmc/sdhc.c (expand / switch to unified diff)

--- src/sys/dev/sdmmc/sdhc.c 2015/07/22 09:54:42 1.60
+++ src/sys/dev/sdmmc/sdhc.c 2015/07/23 23:52:54 1.61
@@ -1,39 +1,39 @@ @@ -1,39 +1,39 @@
1/* $NetBSD: sdhc.c,v 1.60 2015/07/22 09:54:42 skrll Exp $ */ 1/* $NetBSD: sdhc.c,v 1.61 2015/07/23 23:52:54 jmcneill Exp $ */
2/* $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $ */ 2/* $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> 5 * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */ 18 */
19 19
20/* 20/*
21 * SD Host Controller driver based on the SD Host Controller Standard 21 * SD Host Controller driver based on the SD Host Controller Standard
22 * Simplified Specification Version 1.00 (www.sdcard.com). 22 * Simplified Specification Version 1.00 (www.sdcard.com).
23 */ 23 */
24 24
25#include <sys/cdefs.h> 25#include <sys/cdefs.h>
26__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.60 2015/07/22 09:54:42 skrll Exp $"); 26__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.61 2015/07/23 23:52:54 jmcneill Exp $");
27 27
28#ifdef _KERNEL_OPT 28#ifdef _KERNEL_OPT
29#include "opt_sdmmc.h" 29#include "opt_sdmmc.h"
30#endif 30#endif
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/device.h> 33#include <sys/device.h>
34#include <sys/kernel.h> 34#include <sys/kernel.h>
35#include <sys/kthread.h> 35#include <sys/kthread.h>
36#include <sys/malloc.h> 36#include <sys/malloc.h>
37#include <sys/systm.h> 37#include <sys/systm.h>
38#include <sys/mutex.h> 38#include <sys/mutex.h>
39#include <sys/condvar.h> 39#include <sys/condvar.h>
@@ -45,27 +45,27 @@ __KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.6 @@ -45,27 +45,27 @@ __KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.6
45#include <dev/sdmmc/sdmmcvar.h> 45#include <dev/sdmmc/sdmmcvar.h>
46 46
47#ifdef SDHC_DEBUG 47#ifdef SDHC_DEBUG
48int sdhcdebug = 1; 48int sdhcdebug = 1;
49#define DPRINTF(n,s) do { if ((n) <= sdhcdebug) printf s; } while (0) 49#define DPRINTF(n,s) do { if ((n) <= sdhcdebug) printf s; } while (0)
50void sdhc_dump_regs(struct sdhc_host *); 50void sdhc_dump_regs(struct sdhc_host *);
51#else 51#else
52#define DPRINTF(n,s) do {} while (0) 52#define DPRINTF(n,s) do {} while (0)
53#endif 53#endif
54 54
55#define SDHC_COMMAND_TIMEOUT hz 55#define SDHC_COMMAND_TIMEOUT hz
56#define SDHC_BUFFER_TIMEOUT hz 56#define SDHC_BUFFER_TIMEOUT hz
57#define SDHC_TRANSFER_TIMEOUT hz 57#define SDHC_TRANSFER_TIMEOUT hz
58#define SDHC_DMA_TIMEOUT hz 58#define SDHC_DMA_TIMEOUT (hz*3)
59 59
60struct sdhc_host { 60struct sdhc_host {
61 struct sdhc_softc *sc; /* host controller device */ 61 struct sdhc_softc *sc; /* host controller device */
62 62
63 bus_space_tag_t iot; /* host register set tag */ 63 bus_space_tag_t iot; /* host register set tag */
64 bus_space_handle_t ioh; /* host register set handle */ 64 bus_space_handle_t ioh; /* host register set handle */
65 bus_size_t ios; /* host register space size */ 65 bus_size_t ios; /* host register space size */
66 bus_dma_tag_t dmat; /* host DMA tag */ 66 bus_dma_tag_t dmat; /* host DMA tag */
67 67
68 device_t sdmmc; /* generic SD/MMC device */ 68 device_t sdmmc; /* generic SD/MMC device */
69 69
70 struct kmutex host_mtx; 70 struct kmutex host_mtx;
71 71
@@ -1109,26 +1109,37 @@ sdhc_exec_command(sdmmc_chipset_handle_t @@ -1109,26 +1109,37 @@ sdhc_exec_command(sdmmc_chipset_handle_t
1109 if (cmd->c_data && ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) { 1109 if (cmd->c_data && ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
1110 const uint16_t ready = SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY; 1110 const uint16_t ready = SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY;
1111 mutex_enter(&hp->intr_mtx); 1111 mutex_enter(&hp->intr_mtx);
1112 if (ISSET(hp->flags, SHF_USE_DMA)) { 1112 if (ISSET(hp->flags, SHF_USE_DMA)) {
1113 HCLR2(hp, SDHC_NINTR_SIGNAL_EN, ready); 1113 HCLR2(hp, SDHC_NINTR_SIGNAL_EN, ready);
1114 HCLR2(hp, SDHC_NINTR_STATUS_EN, ready); 1114 HCLR2(hp, SDHC_NINTR_STATUS_EN, ready);
1115 } else { 1115 } else {
1116 HSET2(hp, SDHC_NINTR_SIGNAL_EN, ready); 1116 HSET2(hp, SDHC_NINTR_SIGNAL_EN, ready);
1117 HSET2(hp, SDHC_NINTR_STATUS_EN, ready); 1117 HSET2(hp, SDHC_NINTR_STATUS_EN, ready);
1118 } 1118 }
1119 mutex_exit(&hp->intr_mtx); 1119 mutex_exit(&hp->intr_mtx);
1120 } 1120 }
1121 1121
 1122 if (ISSET(hp->sc->sc_flags, SDHC_FLAG_NO_TIMEOUT)) {
 1123 const uint16_t eintr = SDHC_CMD_TIMEOUT_ERROR;
 1124 if (cmd->c_data != NULL) {
 1125 HCLR2(hp, SDHC_EINTR_SIGNAL_EN, eintr);
 1126 HCLR2(hp, SDHC_EINTR_STATUS_EN, eintr);
 1127 } else {
 1128 HSET2(hp, SDHC_EINTR_SIGNAL_EN, eintr);
 1129 HSET2(hp, SDHC_EINTR_STATUS_EN, eintr);
 1130 }
 1131 }
 1132
1122 /* 1133 /*
1123 * Start the MMC command, or mark `cmd' as failed and return. 1134 * Start the MMC command, or mark `cmd' as failed and return.
1124 */ 1135 */
1125 error = sdhc_start_command(hp, cmd); 1136 error = sdhc_start_command(hp, cmd);
1126 if (error) { 1137 if (error) {
1127 cmd->c_error = error; 1138 cmd->c_error = error;
1128 goto out; 1139 goto out;
1129 } 1140 }
1130 1141
1131 /* 1142 /*
1132 * Wait until the command phase is done, or until the command 1143 * Wait until the command phase is done, or until the command
1133 * is marked done for any other reason. 1144 * is marked done for any other reason.
1134 */ 1145 */
@@ -1322,27 +1333,27 @@ sdhc_transfer_data(struct sdhc_host *hp, @@ -1322,27 +1333,27 @@ sdhc_transfer_data(struct sdhc_host *hp,
1322 /* XXX I forgot why I wanted to know when this happens :-( */ 1333 /* XXX I forgot why I wanted to know when this happens :-( */
1323 if ((cmd->c_opcode == 52 || cmd->c_opcode == 53) && 1334 if ((cmd->c_opcode == 52 || cmd->c_opcode == 53) &&
1324 ISSET(MMC_R1(cmd->c_resp), 0xcb00)) { 1335 ISSET(MMC_R1(cmd->c_resp), 0xcb00)) {
1325 aprint_error_dev(hp->sc->sc_dev, 1336 aprint_error_dev(hp->sc->sc_dev,
1326 "CMD52/53 error response flags %#x\n", 1337 "CMD52/53 error response flags %#x\n",
1327 MMC_R1(cmd->c_resp) & 0xff00); 1338 MMC_R1(cmd->c_resp) & 0xff00);
1328 } 1339 }
1329#endif 1340#endif
1330 1341
1331 if (cmd->c_dmamap != NULL) { 1342 if (cmd->c_dmamap != NULL) {
1332 if (hp->sc->sc_vendor_transfer_data_dma != NULL) { 1343 if (hp->sc->sc_vendor_transfer_data_dma != NULL) {
1333 error = hp->sc->sc_vendor_transfer_data_dma(sc, cmd); 1344 error = hp->sc->sc_vendor_transfer_data_dma(sc, cmd);
1334 if (error == 0 && !sdhc_wait_intr(hp, 1345 if (error == 0 && !sdhc_wait_intr(hp,
1335 SDHC_TRANSFER_COMPLETE, SDHC_TRANSFER_TIMEOUT)) { 1346 SDHC_TRANSFER_COMPLETE, SDHC_DMA_TIMEOUT)) {
1336 error = ETIMEDOUT; 1347 error = ETIMEDOUT;
1337 } 1348 }
1338 } else { 1349 } else {
1339 error = sdhc_transfer_data_dma(hp, cmd); 1350 error = sdhc_transfer_data_dma(hp, cmd);
1340 } 1351 }
1341 } else 1352 } else
1342 error = sdhc_transfer_data_pio(hp, cmd); 1353 error = sdhc_transfer_data_pio(hp, cmd);
1343 if (error) 1354 if (error)
1344 cmd->c_error = error; 1355 cmd->c_error = error;
1345 SET(cmd->c_flags, SCF_ITSDONE); 1356 SET(cmd->c_flags, SCF_ITSDONE);
1346 1357
1347 DPRINTF(1,("%s: data transfer done (error=%d)\n", 1358 DPRINTF(1,("%s: data transfer done (error=%d)\n",
1348 HDEVNAME(hp), cmd->c_error)); 1359 HDEVNAME(hp), cmd->c_error));

cvs diff -r1.18 -r1.19 src/sys/dev/sdmmc/sdhcvar.h (expand / switch to unified diff)

--- src/sys/dev/sdmmc/sdhcvar.h 2015/05/03 11:46:25 1.18
+++ src/sys/dev/sdmmc/sdhcvar.h 2015/07/23 23:52:54 1.19
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sdhcvar.h,v 1.18 2015/05/03 11:46:25 jmcneill Exp $ */ 1/* $NetBSD: sdhcvar.h,v 1.19 2015/07/23 23:52:54 jmcneill Exp $ */
2/* $OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $ */ 2/* $OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> 5 * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
@@ -44,26 +44,27 @@ struct sdhc_softc { @@ -44,26 +44,27 @@ struct sdhc_softc {
44#define SDHC_FLAG_ENHANCED 0x00000020 /* Freescale ESDHC */ 44#define SDHC_FLAG_ENHANCED 0x00000020 /* Freescale ESDHC */
45#define SDHC_FLAG_8BIT_MODE 0x00000040 /* MMC 8bit mode is supported */ 45#define SDHC_FLAG_8BIT_MODE 0x00000040 /* MMC 8bit mode is supported */
46#define SDHC_FLAG_HAVE_CGM 0x00000080 /* Netlogic XLP */ 46#define SDHC_FLAG_HAVE_CGM 0x00000080 /* Netlogic XLP */
47#define SDHC_FLAG_NO_LED_ON 0x00000100 /* LED_ON unsupported in HOST_CTL */ 47#define SDHC_FLAG_NO_LED_ON 0x00000100 /* LED_ON unsupported in HOST_CTL */
48#define SDHC_FLAG_HOSTCAPS 0x00000200 /* No device provided capabilities */ 48#define SDHC_FLAG_HOSTCAPS 0x00000200 /* No device provided capabilities */
49#define SDHC_FLAG_RSP136_CRC 0x00000400 /* Resp 136 with CRC and end-bit */ 49#define SDHC_FLAG_RSP136_CRC 0x00000400 /* Resp 136 with CRC and end-bit */
50#define SDHC_FLAG_SINGLE_ONLY 0x00000800 /* Single transfer only */ 50#define SDHC_FLAG_SINGLE_ONLY 0x00000800 /* Single transfer only */
51#define SDHC_FLAG_WAIT_RESET 0x00001000 /* Wait for soft resets to start */ 51#define SDHC_FLAG_WAIT_RESET 0x00001000 /* Wait for soft resets to start */
52#define SDHC_FLAG_NO_HS_BIT 0x00002000 /* Don't set SDHC_HIGH_SPEED bit */ 52#define SDHC_FLAG_NO_HS_BIT 0x00002000 /* Don't set SDHC_HIGH_SPEED bit */
53#define SDHC_FLAG_EXTERNAL_DMA 0x00004000 53#define SDHC_FLAG_EXTERNAL_DMA 0x00004000
54#define SDHC_FLAG_EXTDMA_DMAEN 0x00008000 /* ext. dma need SDHC_DMA_ENABLE */ 54#define SDHC_FLAG_EXTDMA_DMAEN 0x00008000 /* ext. dma need SDHC_DMA_ENABLE */
55#define SDHC_FLAG_NO_CLKBASE 0x00020000 /* ignore clkbase register */ 55#define SDHC_FLAG_NO_CLKBASE 0x00020000 /* ignore clkbase register */
56#define SDHC_FLAG_SINGLE_POWER_WRITE 0x00040000 56#define SDHC_FLAG_SINGLE_POWER_WRITE 0x00040000
 57#define SDHC_FLAG_NO_TIMEOUT 0x00080000 /* ignore timeout interrupts */
57 58
58 uint32_t sc_clkbase; 59 uint32_t sc_clkbase;
59 int sc_clkmsk; /* Mask for SDCLK */ 60 int sc_clkmsk; /* Mask for SDCLK */
60 uint32_t sc_caps;/* attachment provided capabilities */ 61 uint32_t sc_caps;/* attachment provided capabilities */
61 62
62 int (*sc_vendor_rod)(struct sdhc_softc *, int); 63 int (*sc_vendor_rod)(struct sdhc_softc *, int);
63 int (*sc_vendor_write_protect)(struct sdhc_softc *); 64 int (*sc_vendor_write_protect)(struct sdhc_softc *);
64 int (*sc_vendor_card_detect)(struct sdhc_softc *); 65 int (*sc_vendor_card_detect)(struct sdhc_softc *);
65 int (*sc_vendor_bus_clock)(struct sdhc_softc *, int); 66 int (*sc_vendor_bus_clock)(struct sdhc_softc *, int);
66 int (*sc_vendor_transfer_data_dma)(struct sdhc_softc *, struct sdmmc_command *); 67 int (*sc_vendor_transfer_data_dma)(struct sdhc_softc *, struct sdmmc_command *);
67}; 68};
68 69
69/* Host controller functions called by the attachment driver. */ 70/* Host controller functions called by the attachment driver. */