| @@ -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 |
48 | int sdhcdebug = 1; | | 48 | int 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) |
50 | void sdhc_dump_regs(struct sdhc_host *); | | 50 | void 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 | |
60 | struct sdhc_host { | | 60 | struct 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)); |